Check-in [6cd1c31096]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:add tkzinc to [undroidwish] builds
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6cd1c31096bb793654b8d8a07625bcc3413238d4
User & Date: chw 2017-10-03 18:16:50
Context
2017-10-04
06:43
add two missing defines to sdltk check-in: 9fe193774a user: chw tags: trunk
2017-10-03
18:31
merge with trunk check-in: f1d3d998cb user: chw tags: wtf-8-experiment
18:16
add tkzinc to [undroidwish] builds check-in: 6cd1c31096 user: chw tags: trunk
18:02
make FBO for SDL GL context with both depth and stencil buffers if possible check-in: b3100836b5 user: chw tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added jni/tkzinc/BUGS.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Text stippling is not available under openGL.

Line ends and line joins are not fully implemented under openGL.
The default behavior if to draw round ends and joins.

Line dashes are not really usable in openGL. Some cases work ok,
like aligned rectangles and other not, like curves and arcs.

Tiling/stippling begin on the item or item bounding box edge
rather than on the border edge so that the tile/stipple is
partially masked by the border.

Item tiling is not available for Windows GDI.

Maps are not rendered filled in openGL. The code of maps still
lags behind.

Added jni/tkzinc/Copyright.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Copyright (c) 2005, Centre d'études de la Navigation Aérienne, Patrick Lecoanet
All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

Added jni/tkzinc/LGPL.txt.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
		  GNU LESSER GENERAL PUBLIC LICENSE
		       Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

		  GNU LESSER GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.
  
  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.

  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.

  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.

  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

			    NO WARRANTY

  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

		     END OF TERMS AND CONDITIONS

Added jni/tkzinc/Makefile.in.





































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
#  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
#
# See the file "Copyright" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# $Revision$
#
#
# This Makefile.in is derived from the Sample TEA template which is:
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002 ActiveState SRL.
#

PACKAGE_NAME      = @PACKAGE_NAME@
PACKAGE_VERSION   = @PACKAGE_VERSION@

PKG_SOURCES	      = @PKG_SOURCES@
PKG_OBJECTS	      = @PKG_OBJECTS@

PKG_STUB_SOURCES	= @PKG_STUB_SOURCES@
PKG_STUB_OBJECTS	= @PKG_STUB_OBJECTS@

PKG_TCL_SOURCES   = @PKG_TCL_SOURCES@

PKG_HEADERS       = @PKG_HEADERS@

PKG_LIB_FILE      = @PKG_LIB_FILE@
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@

BINARIES	= $(PKG_LIB_FILE) $(PKG_STUB_LIB_FILE)

SHELL		= @SHELL@

srcdir		= @srcdir@
prefix		= @prefix@
exec_prefix	= @exec_prefix@

libdir		= @libdir@
includedir	= @includedir@

DESTDIR		=

PKG_DIR		= $(PACKAGE_NAME)$(PACKAGE_VERSION)
pkglibdir	= $(libdir)/$(PKG_DIR)

top_builddir	= .

INSTALL		= @INSTALL@
INSTALL_PROGRAM	= @INSTALL_PROGRAM@
INSTALL_DATA	= @INSTALL_DATA@
INSTALL_SCRIPT	= @INSTALL_SCRIPT@

CC		= @CC@
CFLAGS_DEBUG	= @CFLAGS_DEBUG@
CFLAGS_DEFAULT	= @CFLAGS_DEFAULT@
CFLAGS_OPTIMIZE	= @CFLAGS_OPTIMIZE@
CFLAGS_WARNING	= @CFLAGS_WARNING@
CLEANFILES	= @CLEANFILES@
EXEEXT		= @EXEEXT@
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
MAKE_LIB	= @MAKE_LIB@
MAKE_STUB_LIB	= @MAKE_STUB_LIB@
MAKE_SHARED_LIB	= @MAKE_SHARED_LIB@
MAKE_STATIC_LIB	= @MAKE_STATIC_LIB@
OBJEXT		= @OBJEXT@
RANLIB		= @RANLIB@
SHLIB_CFLAGS	= @SHLIB_CFLAGS@
SHLIB_LD	= @SHLIB_LD@
SHLIB_LD_LIBS	= @SHLIB_LD_LIBS@
STLIB_LD	= @STLIB_LD@
TCL_BIN_DIR	= @TCL_BIN_DIR@
TCL_SRC_DIR	= @TCL_SRC_DIR@
TK_BIN_DIR	= @TK_BIN_DIR@
TK_SRC_DIR	= @TK_SRC_DIR@
#
# This is necessary for packages that use private Tcl headers
TCL_TOP_DIR_NATIVE	= @TCL_TOP_DIR_NATIVE@
TK_TOP_DIR_NATIVE	= @TK_TOP_DIR_NATIVE@
# Not used, but retained for reference of what libs Tcl required
TCL_LIBS	= @TCL_LIBS@


#========================================================================
# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
# package without installing.  The other environment variables allow us
# to test against an uninstalled Tcl.  Add special env vars that you
# require for testing here (like TCLX_LIBRARY).
#========================================================================

EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR)
TCLSH_ENV	= TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \
		  LD_LIBRARY_PATH="$(EXTRA_PATH):$(LD_LIBRARY_PATH)" \
		  LIBPATH="$(EXTRA_PATH):${LIBPATH}" \
		  SHLIB_PATH="$(EXTRA_PATH):${SHLIB_PATH}" \
		  PATH="$(EXTRA_PATH):$(PATH)" \
		  TCLLIBPATH="$(top_builddir)"
TCLSH_PROG	= @TCLSH_PROG@
WISH_PROG	= @WISH_PROG@
TCLSH		= $(TCLSH_ENV) $(TCLSH_PROG)
WISH		= $(TCLSH_ENV) $(WISH_PROG)
SHARED_BUILD	= @SHARED_BUILD@

# The local includes must come first, because the TK_XINCLUDES can be
# just a comment
TCL_INCLUDES = @TCL_INCLUDES@
TK_INCLUDES = @TK_INCLUDES@
GL_INCLUDES = @GL_INCLUDES@
INCLUDES	= -I$(srcdir)/generic @TCL_INCLUDES@ @TK_INCLUDES@ @GL_INCLUDES@

TCL_EXTRA_CFLAGS	= $(MEM_DEBUG_FLAGS) @TCL_EXTRA_CFLAGS@

DEFS		= @DEFS@ @PKG_CFLAGS@ $(TCL_EXTRA_CFLAGS)

CONFIG_CLEAN_FILES = Makefile

CPPFLAGS	= @CPPFLAGS@
LIBS		= @PKG_LIBS@ @LIBS@
AR		= @AR@
CFLAGS		= @CFLAGS@
COMPILE		= $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)


#
# No stubs build right now
#all: package libraries
all: package

package: $(PKG_LIB_FILE) pkgIndex.tcl

libraries: $(PKG_STUB_LIB_FILE)


#========================================================================
# The doc target is for building man pages. Currently the zinc doc is
# only available in html and pdf formats. These formats require tools
# (LaTeX, pdfTeX, h4tex) that are not readily available on all
# platforms. To ease automatic construction of the package the target
# doc does not involve the construction of pdf and html.
#========================================================================

doc:

doc-clean:
	(cd doc; \
				rm -f refman.aux refman.idx refman.ind refman.lof refman.lot; \
				rm -f refman.log refman.out refman.toc texput.log refman.tpt; \
				rm -f idxmake.dvi idxmake.log refman.4ct refman.4dx refman.4ix; \
				rm -f refman.4tc refman.dvi refman.idx refman.ilg refman.ind; \
				rm -f refman.log refman.tmp refman.xref refman.lg refman.idv)

pdf: doc-clean doc/refman.tex
	(cd doc; \
	  pdflatex refman.tex; \
		makeindex -o refman.ind refman.idx; \
	  pdflatex refman.tex; \
	  pdflatex refman.tex)

html: doc-clean doc/refman.tex
	(cd doc; \
	  htlatex refman.tex refman; \
	  tex '\def\filename{{refman}{idx}{4dx}{ind}}' '\input' idxmake.4ht; \
		makeindex -o refman.ind refman.4dx; \
		htlatex refman.tex refman)

#
# No stubs and no headers installed right now
#install: install-package install-libraries install-headers install-demos
install: install-package install-demos

install-package:
	@mkdir -p $(DESTDIR)$(pkglibdir)
	$(INSTALL_PROGRAM) $(PKG_LIB_FILE) $(DESTDIR)$(pkglibdir)/$(PKG_LIB_FILE)
	for p in $(srcdir)/library/*.tcl ; do \
		destp=`basename $$p`; \
		echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
		$(INSTALL_DATA) $$p $(DESTDIR)$(pkglibdir)/$$destp; \
	done
	cat pkgIndex.tcl >> $(DESTDIR)$(pkglibdir)/pkgIndex.tcl

install-headers:
	echo "Installing header files in $(DESTDIR)$(includedir)"; \
	mkdir -p $(DESTDIR)$(includedir); \
	for i in "$(PKG_HEADERS)" ; do \
		echo "Install $(srcdir)/$$i" ; \
		destp=`basename $$i`; \
		$(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir)/$$destp ; \
	done

install-libraries:
	@echo "Installing $(PKG_STUB_LIB_FILE) in $(DESTDIR)$(libdir)"
	@mkdir -p $(DESTDIR)$(libdir)
	$(INSTALL_PROGRAM) $(PKG_STUB_LIB_FILE) $(DESTDIR)$(libdir)

install-demos:
	@mkdir -p $(DESTDIR)$(pkglibdir)/demos
	@echo "Installing demo files in $(DESTDIR)$(pkglibdir)/demos"
	@for p in $(srcdir)/demos/*; do \
		p=`basename $$p`; \
		echo " Install $$p $(DESTDIR)$(pkglibdir)/demos/$$p"; \
		$(INSTALL_DATA) $(srcdir)/demos/$$p $(DESTDIR)$(pkglibdir)/demos/$$p; \
	done
	@mkdir -p $(DESTDIR)$(pkglibdir)/demos/images
	@mkdir -p $(DESTDIR)$(pkglibdir)/demos/data
	@for p in $(srcdir)/demos/images/*; do \
		p=`basename $$p`; \
		echo " Install $$p $(DESTDIR)$(pkglibdir)/demos/images/$$p"; \
		$(INSTALL_DATA) $(srcdir)/demos/images/$$p $(DESTDIR)$(pkglibdir)/demos/images/$$p; \
	done
	@for p in $(srcdir)/demos/data/*; do \
		p=`basename $$p`; \
		echo " Install $$p $(DESTDIR)$(pkglibdir)/demos/data/$$p"; \
		$(INSTALL_DATA) $(srcdir)/demos/data/$$p $(DESTDIR)$(pkglibdir)/demos/data/$$p; \
	done

test: package libraries
	$(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) ; \

shell: package libraries
	@$(TCLSH) $(SCRIPT)

gdb:
	$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)

depend:

$(PKG_LIB_FILE): $(PKG_OBJECTS)
	-rm -f $(PKG_LIB_FILE)
	${MAKE_LIB}
	$(RANLIB) $(PKG_LIB_FILE)

$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
	-rm -f $(PKG_STUB_LIB_FILE)
	${MAKE_STUB_LIB}
	$(RANLIB) $(PKG_STUB_LIB_FILE)
  
#========================================================================
# We need to enumerate the list of .c to .o lines here.
#
# In the following lines, $(srcdir) refers to the toplevel directory
# containing your extension.  If your sources are in a subdirectory,
# you will have to modify the paths to reflect this:
#
# sample.$(OBJEXT): $(srcdir)/generic/sample.c
# 	$(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
#
# Setting the VPATH variable to a list of paths will cause the makefile
# to look into these paths when resolving .c to .obj dependencies.
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================

VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx

.SUFFIXES: .c .$(OBJEXT)

.c.$(OBJEXT):
	$(COMPILE) -c `@CYGPATH@ $<` -o $@

#========================================================================
# Create the pkgIndex.tcl file.
# It is usually easiest to let Tcl do this for you with pkg_mkIndex, but
# you may find that you need to customize the package.  If so, either
# modify the -hand version, or create a pkgIndex.tcl.in file and have
# the configure script output the pkgIndex.tcl by editing configure.in.
#========================================================================

pkgIndex.tcl:
	(echo 'package ifneeded $(PACKAGE_NAME) $(PACKAGE_VERSION) \
	    [list load [file join $$dir $(PKG_LIB_FILE)]]'\
	) > pkgIndex.tcl

#========================================================================
# Don't modify the file to clean here.  Instead, set the "CLEANFILES"
# variable in configure.in
#========================================================================

clean: doc-clean 
	-test -z "$(BINARIES)" || rm -f $(BINARIES)
	-rm -f *.$(OBJEXT) core *.core
	-test -z "$(CLEANFILES)" || rm -Rf $(CLEANFILES)

distclean: clean
	-rm -f *.tab.c *~
	-rm -f $(CONFIG_CLEAN_FILES)
	-rm -f config.cache config.log config.status

#========================================================================
# Install binary object libraries.  On Windows this includes both .dll and
# .lib files.  Because the .lib files are not explicitly listed anywhere,
# we need to deduce their existence from the .dll file of the same name.
# Library files go into the lib directory.
# In addition, this will generate the pkgIndex.tcl
# file in the install location (assuming it can find a usable tclsh shell)
#
# You should not have to modify this target.
#========================================================================

Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status
	cd $(top_builddir) \
	  && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status

.PHONY: all package clean depend distclean doc install libraries test

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

Added jni/tkzinc/Perl/Makefile.PL.



















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
use 5.006;
use Tk;
use Config;
use Tk::Config;
use ExtUtils::MakeMaker;
use strict;

my $TkLibDir = $Tk::library;
my $platform = $Tk::platform;

my $VERSION = SEEexport2cpan;


if (!$TkLibDir)
{
    print stderr "==================================================================\n";
    print stderr "Could not find the Perl/Tk (pTk) library.\n";
    print stderr "Please, install first Perl/Tk interface before installing Tk::Zinc\n";
    print stderr "==================================================================\n";
    die;
}


print "Configuring version $VERSION for $platform platform...\n";
print "Using $TkLibDir as Tk library...\n";

my @GENERIC_C = ('Tabular.c', 'Rectangle.c', 'Arc.c', 'Curve.c',
		 'Item.c', 'PostScript.c', 'Attrs.c', 'Draw.c', 'Geo.c', 'List.c',
		 'perfos.c', 'Transfo.c', 'Group.c', 'Icon.c', 'Text.c', 'Image.c', 'Color.c',
		 'Field.c', 'Triangles.c', 'Viewport.c', 'WindowUtils.c', 'Window.c', 'tkZinc.c');

my @ATC_C = ('OverlapMan.c', 'Track.c', 'Reticle.c', 'Map.c', 'MapInfo.c');

my @WIN_C = ('WinPort.c');

my @C;

my $WIN = ($platform =~ /win/i);

push @C, @GENERIC_C ;

my $NeededLibs = ['-L/usr/X11R6/lib -lXext -lX11 -lGLU -lGL -L.'];

if ($WIN) {
    push @C, @WIN_C;
    $NeededLibs = ['-lglu32 -lopengl32']
}
my $ZincObj = "Zinc" . $Config{"_o"};

my $INC = "-I. -I$TkLibDir -I$TkLibDir/pTk -I$TkLibDir/X11";

unless ($WIN) {
  $INC .= " -I/usr/X11R6/include";
}

#For some reason which the author of ExtUtils::MM_Unix forget, Unix machines like to have
#PERL_DL_NONLAZY set for tests. This is FALSE for TkZinc.

if ($] >= 5.008000) {
  *ExtUtils::MM_Unix::test_via_harness = sub {
    my($self, $perl, $tests) = @_;
#    return $self->SUPER::test_via_harness("PERL_DL_NONLAZY=1 $perl", $tests);
    # I should use the SUPER method, but this needs some import tunning...
    return ExtUtils::MM_Any::test_via_harness($self, $perl, $tests);
  };

#Again, the PERL_DL_NONLAZY thing.
  *ExtUtils::MM_Unix::test_via_script = sub {
    my($self, $perl, $script) = @_;
#    return $self->SUPER::test_via_script("PERL_DL_NONLAZY=1 $perl", $script);
    # I should use the SUPER method, but this needs some import tunning...
    return ExtUtils::MM_Any::test_via_script($self, $perl, $script);
  };
}

# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.

my $mm_ver = $ExtUtils::MakeMaker::VERSION;
if ($mm_ver =~ /_/) { # dev version
    $mm_ver = eval $mm_ver;
    die $@ if $@;
}

WriteMakefile(
    'ABSTRACT'      => 'a canvas offering groups, tranformations, transparency, color gradient...',
    'AUTHOR'        => 'Patrick Lecoanet <lecoanet@cena.fr>',
    'NAME'          => 'Tk::Zinc',
    'PREREQ_PM'     => $WIN ? {Tk => 8.004} : {Tk => 8.0},
    'LIBS'          => $NeededLibs, 
    'OPTIMIZE'      => &optimize,
    'DEFINE'        => &get_flags,
    'INC'           => $INC,
    'C'             => [@C],
    'XS_VERSION'    => $Tk::Config::VERSION,
    'XS'            => {'Zinc.xs' => 'Zinc.c'},
    'linkext'       => {LINKTYPE => 'dynamic'},
    'depend'        => {$ZincObj => '$(O_FILES) Zinc.c'},
    'LDFROM'        => "\$(O_FILES) $ZincObj",
    ($mm_ver <= 6.45
        ? ()
        : (META_MERGE => {
            'meta-spec' => { version => 2 },
            resources => {
                repository  => {
                    type => 'hg',
                    web  => 'https://bitbucket.org/plecoanet/tkzinc',
                    url  => 'https://bitbucket.org/plecoanet/tkzinc/src',
                },
            },
          })
    ),
);

sub optimize {
  foreach my $arg (@ARGV) {
    if ($arg =~ /(enable-symbols)/i) {
      return "-g";
    }
  }
  return "-O";
}

sub get_flags {
    my %DEF_FLAGS = ('GL'        => 1,
		     'SHAPE'     => 1,
		     'ATC'        => 1
		     );
    
    foreach my $arg (@ARGV) {
	print "$arg ....\n";
	my ($name, $value) = split(/[=]+/, $arg);
	if ($name =~ /(with-gl)/i) {
	    if ($value =~ /no/i) {
		$DEF_FLAGS{'GL'} = 0;
	    }
	}
	elsif ($name =~ /(with-atc)/i) {
	    if ($value =~ /no/i) {
		$DEF_FLAGS{'ATC'} = 0;
	    }
	}
	elsif ($name =~ /(with-shape)/i) {
	    if ($value =~ /no/i) {
		$DEF_FLAGS{'SHAPE'} = 0;
	    }
	}
    }
    
    my $defines = "-DPTK -DPACKAGE_VERSION=\\\"$VERSION\\\"";

    if ($WIN) {
	#
	# No shape extension on Windows (planned later).
	$DEF_FLAGS{'SHAPE'} = 0;
	#
	# Visual C++ does not define __STDC__ by default
	$defines .= ' -D__STDC__';
    }

    print "Configuring with:\n    ";
    foreach my $flag (keys %DEF_FLAGS) {
	print "$flag=", $DEF_FLAGS{$flag} ? 'ok' : 'no', " ";
	if ($DEF_FLAGS{$flag}) {	    
	    $defines = $defines . " " . "-D$flag";
	    if ($flag eq 'ATC') {
		push @C, @ATC_C
	    }
	}
    }
    if ($Tk::VERSION =~ /^800/) {
      $defines .= " -DPTK_800";
      print "PTK=800";
    } else {
      print "PTK=804";
    }
    print "\n";
    return $defines;
}

#
# For the demo
#
# perl -Mblib demos/zinc-demos

Added jni/tkzinc/Perl/README.



































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
Tk::Zinc - another Canvas which proposes many new functions, some based on openGL

Tk::Zinc for Perl/Tk is available for Linux, Windows and MacOSX. 
the easiest way could be to use he CPAN. However new releases are usually 
first available on www.tkzinc.org
To build it you need:

* On a Linux system, you need Perl (>= 5.6) and perl-tk (800 or 804) as well as
  perl-tk developpement packages.

* On MacOSX you need:
  - fink with tk-pm package and its dependencies (http://fink.sf.net)
    tk-pm is available in unstable. You can add this binary unstable tree to you /sw/etc/apt/sources.list:
    deb http://fink.opendarwin.org/bbraun 10.3/unstable main crypto
    deb http://fink.opendarwin.org/bbraun 10.3/stable main crypto
  - X11 et X11 sdk from Apple (http://www.apple.com/macosx/x11/)

* On WinXP you need:
  - activeperl (5.8.6.811 or higher) from activatestate.com 
  - and
    - if you want to compile TkZinc by yourself:
      Visual C++ or the Free Visual C++ Command Line Tools
    - or the TkZinc msi package available from www.tkzinc.org


Install:

  perl Makefile.PL
  # you can use the following options: --with-gl=yes|no --with-atc=yes|no --with-shape=yes|no
  # current defaults are  --with-gl=yes --with-atc=yes --with-shape=yes

  make
  make test

  # to run demos before installing:
  perl -Iblib/arch -Iblib/lib demos/zinc-demos

  make install



WATCH OUT! On Linux it is quite frequent to have both Mesa and proprietary
           openGL libraries installed. This may lead to big problems at
           runtime if the linker picks the wrong library. It is often the
           the case between the static (libGL.a) Mesa library and the dynamic
           (libGL.so) NVidia library. It is very important to assert that
           the link is done with the library matching the openGL driver
           loaded in the X server.

In the case you need to use another version of perl-tk than the one installed in the 
system, you should use the following command as a template to adapt to follow your 
specific pathes of the alternative perl-tk installation:

  env PERL5LIB=/usr/local/test/804_027/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi perl Makefile.PL
  make
  env PERL5LIB=/usr/local/test/804_027/lib/perl5/5.8.1/i386-linux-thread-multi:/usr/local/test/804_027/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi make test

  # to run demos before installing:
  env PERL5LIB=/usr/local/test/804_027/lib/perl5/5.8.1/i386-linux-thread-multi:/usr/local/test/804_027/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi perl -Iblib/arch -Iblib/lib demos/zinc-demos

  # and finally
  make install

  # and to run your script:
  env PERL5LIB=/usr/local/test/804_027/lib/perl5/5.8.1/i386-linux-thread-multi:/usr/local/test/804_027/lib/perl5/site_perl/5.8.1/i386-linux-thread-multi perl <your_script.pl>




up-to-date documentation is also available at https://bitbucket.org/plecoanet/tkzinc
The source of the reference manual is available in the full source package,
which also includes TkZinc for Tcl/Tk, for Perl/Tk, and for Python.


After installation, we recommend you to launch the zinc-demos script,
a frontend to more than 30 small demos.

For more information on building Tk::Zinc, a README is available in 
the tkzinc-*tgz tar file (on Tkzinc web site) used for building all
flavor of TkZinc (ie tcl, perl and python)

This software is delivered under new  BSD licence.
For the copyright, please, read the Copyright file.

For any question on Tk::Zinc usage, build or installation pb,
please create an inquiry on Bitbucket: https://bitbucket.org/plecoanet/tkzinc/issues


Authors and Contributors:

Tk::Zinc main author is Patrick Lecoanet (CENA)
Sub-Modules, demos and documentation have been developped by
Daniel Etienne (CENA), Christophe Mertz (formerly CENA and now IntuiLab), 
Jean-Luc Vinot (CENA), with contributions from Stéphane Chatty (Intuilab), 
Céline Schlienger (IntuiLab), Alexandre Lemort (IntuiLab)
Stéphane Conversy (CENA) contributed to the MacOSX port.
Many others contributed with their bug reports!

Added jni/tkzinc/Perl/Zinc.pm.





























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# $Id$
# $Name$

package Tk::Zinc;

use Tk;
use Tk::Photo;
use Carp;

use base qw(Tk::Widget); 
Construct Tk::Widget 'Zinc';


use vars qw($VERSION $REVISION);

$REVISION = q$Revision$ ;  # this line is automagically modified by CVS
$VERSION = SEEexport2cpan;


bootstrap Tk::Zinc $Tk::VERSION;

sub Tk_cmd { \&Tk::zinc }

sub CreateOptions
{
 return (shift->SUPER::CreateOptions,'-render')
}

Tk::Methods("add", "addtag", "anchorxy", "bbox", "becomes", "bind", "cget",
	    "chggroup", "clone", "collapsemotions", "configure", "contour", "coords",
      "currentpart", "cursor", "dchars", "dtag", "find", "fit", "focus",
      "gdelete", "gettags", "gname", "group", "hasanchors", "hasfields",
      "hastag", "index", "insert", "itemcget", "itemconfigure", "lower",
      "monitor", "numparts", "postscript", "raise", "remove", "rotate",
      "scale", "select", "skew", "smooth", "tapply", "tcompose", "tdelete",
      "tget", "transform", "translate", "treset", "trestore", "tsave", "tset",
	    "type", "vertexat", "xview", "yview");

## coord0 is a compatibility function usefull for porting old application
## previously running with Tk::Zinc V <= 3.2.6a
## The Zinc methode coords0 can/should replace coords as long as no control points are
## used in curve or rectangle or an arc...
## This can dramaticaly simplify the port of an old application from Zinc V<3.2.6a to
## a newer version of Zinc. HOWEVER YOU STILL MUST CHANGE THE CODE OF THIS OLD APPICATION
##
## Remember: the incompatible change in Zinc is due to the introduction of
## control points in curves (and a future release, in arc or rectangle items...)
sub coords0 {
    if (wantarray) {
	## we are in list context, so we should convert the returned value
	## to match the specification of Zinc Version <= 3.2.6a
	my @res = &Tk::Zinc::coords(@_);
	if ( !ref $res[0] ) {
	    ## The first item of the list is not a reference, so the
	    ## list is guarranted to be a flat list (x, y, x, y, ... x, y)
	    return @res;
	}
	else {
	    ## The list is a list of references like : [x y] or [x y symbol] 
	    ## In the latter case, coord0 should warn that there is a control point!
	    ## coord0 will return a flatten list of (x, y, ... x , y)
	    my @res0;
	    foreach my $ref (@res) {
		my @array = @{$ref};
	        if ($#array > 1) {
		   my $item = $_[1];
		   my $zinc = $_[0];
		   my $type = $zinc->type($item);
		   carp "Using Zinc coord0 compatibility method with item $item (type=$type) which contains a control point: @array";
	        }
		push @res0, $array[0];
		push @res0, $array[1];
	    }
	    return @res0;
        }
    }
    else {
	## contexte scalaire
	## le résultat n'était pas utilisé jusqu'à présent, vu le bug...
	## donc inutile de le convertir!
	return &Tk::Zinc::coords(@_);
    }
}

1;

__END__

=head1 NAME

Tk::Zinc - TkZinc is another Canvas which proposes many new functions, some based on openGL

=for category Tk Widget Classes

=head1 SYNOPSIS

I<$zinc> = I<$parent>-E<gt>B<Zinc>(?I<options>?);

=head1 DESCRIPTION

I<Zinc> widget is very similar to Tk Canvase in that it supports
structured graphics. Like the Canvas, TkZinc implements items used to
display graphical entities. Those items can be manipulated and bindings can be
associated with them to implement interaction behaviors. But unlike the
Canvas, TkZinc can structure the items in a hierarchy (with the use of
group items), has support for affine 2D transforms (i.e. translation, scaling, and
rotation), clipping can be set for sub-trees of the item hierarchy, the item set
is quite more powerful including field specific items for Air Traffic systems and
new rendering techniques such as transparency and gradients.

Since the 3.2.2 version, TkZinc also offers as a runtime option, the support
for openGL rendering, giving access to features such as antialiasing, transparency,
color gradients and even a new, openGL oriented, item type triangles.

TkZinc full documentation is available as part of the Zinc software as a
pdf file, B<refman.pdf> and html pages B<refman/index.html>.

As a complement to the reference manual, small Perl/Tk demos of TkZinc are
also available through a small application named zinc-demos, highly inspired
from the widget application included in Tk. The aim of these demos are both
to demonstrates the power of TkZinc and to help newcomers start using
TkZinc with small examples.

=head1 WHERE CAN I FIND TkZinc?

TkZinc is available as source in tar.gz format at L<https://bitbucket.org/plecoanet/tkzinc>.
There is some old packages at http://freshmeat.net/projects/zincisnotcanvas/, but please use the Bitbucket repo.

TkZinc is also available on CPAN since v3.294 (a kind of 3.2.94)

=head1 AUTHOR

Patrick Lecoanet <lecoanet@cena.fr>

=head1 COPYRIGHT

Zinc has been developed by the CENA (Centres d'Etudes de la Navigation
Aérienne) for its own needs in advanced HMI (Human Machine Interfaces or Interactions).
Because we are confident in the benefit of free software, the CENA delivered this
toolkit under the GNU Library General Public License.

This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

Parts of this software are derived from the Tk toolkit which is copyrighted
under another open source license by The Regents of the University of California
and Sun Microsystems, Inc. The GL
font rendering is derived from Mark Kilgard code described in 'A Simple OpenGL-based
API for Texture Mapped Text' and is copyrighted by Mark Kilgard under an open source license.

=head1 SEE ALSO

L<Tk(1)>, L<zinc-demos(1)>.

=cut

Added jni/tkzinc/Perl/Zinc.xs.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
  Copyright (c) 1995-1997 Nick Ing-Simmons. All rights reserved.
  This program is free software; you can redistribute it and/or
  modify it under the same terms as Perl itself.
*/

#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#include <tkGlue.def>

#include <pTk/tkPort.h>
#include <pTk/tkInt.h>
#ifdef _WIN32
#include <pTk/tkWinInt.h>
#endif
#include <pTk/tkImgPhoto.h>
#include <pTk/tkVMacro.h>
#include <tkGlue.h>
#include <tkGlue.m>

extern int
ZincObjCmd(
	   ClientData client_data,
	   Tcl_Interp* interp,
	   int argc,
	   Tcl_Obj* CONST args[]);

extern int
ZnVideomapObjCmd(
	         ClientData client_data,
	         Tcl_Interp* interp,
	         int argc,
	         Tcl_Obj* CONST args[]);

extern int
ZnMapInfoObjCmd(
	        ClientData client_data,
	        Tcl_Interp* interp,
	        int argc,
	        Tcl_Obj* CONST args[]);

DECLARE_VTABLES;
TkimgphotoVtab *TkimgphotoVptr;

MODULE = Tk::Zinc	PACKAGE = Tk::Zinc

PROTOTYPES: DISABLE

BOOT:
 {
  IMPORT_VTABLES;
  TkimgphotoVptr = (TkimgphotoVtab *) SvIV(perl_get_sv("Tk::TkimgphotoVtab",GV_ADDWARN|GV_ADD));

  Lang_TkCommand("zinc", ZincObjCmd);
  Lang_TkCommand("videomap", ZnVideomapObjCmd);
  Lang_TkCommand("mapinfo", ZnMapInfoObjCmd);
 }

Added jni/tkzinc/Perl/Zinc/Debug.pm.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
#        Tk::Zinc::Debug Perl Module :
#
#        For debugging/analysing a Zinc application.
#
#        Author : Daniel Etienne <etienne@cena.fr>
#
# $Id$
#---------------------------------------------------------------------------
package Tk::Zinc::Debug;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use strict 'vars';
use vars qw(@ISA @EXPORT @EXPORT_OK $WARNING $endoptions);
use Carp;
use English;
require Exporter;
use File::Basename;
use Tk::Dialog;
use Tk::Tree;
use Tk::ItemStyle;
use Tk::Pane;
use Tk::FBox;
use Tk::Balloon;

@ISA = qw(Exporter);
@EXPORT = qw(finditems snapshot tree init);
@EXPORT_OK = qw(finditems snapshot tree init);

my ($itemstyle, $groupstyle, $step);
my (%result_tl, $result_fm, $search_tl, $helptree_tl, %coords_tl, %transfo_tl,
    $helpcoords_tl, $searchtree_tl, $tree_tl, %alloptions_tl, $tree,
    $cursorxy_tl, $cursorxy);
my $showitemflag;
my ($x0, $y0);
my ($help_print, $imagecounter, $saving) = (0, 0, 0);
my %searchEntryValue;
my $searchTreeEntryValue;
my %wwidth;
my %wheight;
my $preload;
my %defaultoptions;
my %instances;
my @instances;
my %cmdoptions;
my $initobjectfunction;
my %userbindings;
my $selectedzinc;
my $control_tl;
my %button;
my %on_command;
my %off_command;
my @znpackinfo;
my $screenwidth;
my $balloonhelp;
#---------------------------------------------------------------------------
#
# Initialisation functions for plugin usage
#
#---------------------------------------------------------------------------

# Hack to overload the Tk::Zinc::InitObject method
#
BEGIN {
    
    # test if Tk::Zinc::Debug is loaded using the -M perl option
    $preload = 1 if (caller(2))[2] == 0;
    return unless $preload;
    # parse Tk::Zinc::Debug options
    require Getopt::Long;
    Getopt::Long::Configure('pass_through');
    Getopt::Long::GetOptions(\%cmdoptions, 'optionsToDisplay=s', 'optionsFormat=s',
			     'snapshotBasename=s', 'expandTagsField=i');
    # save current Tk::Zinc::InitObject function; it will be invoked in
    # overloaded one (see below)
    use Tk;
    use Tk::Zinc;
    $initobjectfunction = Tk::Zinc->can('InitObject');
    
} # end BEGIN


# Hack to capture the instance(s) of zinc. Tk::Zinc::Debug init function
# is invoked here.
#
sub Tk::Zinc::InitObject {
    
    # invoke function possibly overloaded in other modules
    &$initobjectfunction(@_) if $initobjectfunction;
    return unless $preload;
    my $zinc = $_[0];
    &init($zinc);
   
} # end Tk::Zinc::InitObject


#---------------------------------------------------------------------------
#
# Initialisation function
#
#---------------------------------------------------------------------------

sub init {

    my $zinc = shift;
    $screenwidth = $zinc->screenwidth;
    my %options = @_;
    for my $opt (keys(%options)) {
        carp "in Tk::Zinc::Debug initialisation function, unknown option $opt\n"
            unless $opt eq '-optionsToDisplay' or $opt eq '-optionsFormat'
		or $opt eq '-snapshotBasename' or $opt eq '-expandTagsField' ;
    }
    $cmdoptions{optionsToDisplay} = $options{-optionsToDisplay} if
	not defined $cmdoptions{optionsToDisplay} and
	    defined $options{-optionsToDisplay};
    $cmdoptions{optionsFormat} = $options{-optionsFormat} if
	not defined $cmdoptions{optionsFormat} and
	    defined $options{-optionsFormat};
    $cmdoptions{snapshotBasename} = $options{-snapshotBasename} if
	not defined $cmdoptions{snapshotBasename} and
	    defined $options{-snapshotBasename};
    $cmdoptions{expandTagsField} = $options{-expandTagsField} if
	not defined $cmdoptions{expandTagsField} and
	    defined $options{-expandTagsField};
	
    &newinstance($zinc);
    return if Tk::Exists($control_tl);
    print "Tk::Zinc::Debug is ON\n";
    my $bitmaps = &createBitmaps($zinc);
    $control_tl = $zinc->Toplevel;
    $control_tl->title("Tk::Zinc::Debug (V $VERSION)");
    my $fm1 = $control_tl->Frame()->pack(-side => 'left', -padx => 0);
    my $fm2 = $control_tl->Frame()->pack(-side => 'left', -padx => 20);
    my $fm3 = $control_tl->Frame()->pack(-side => 'left', -padx => 0);
    
    for (qw(zn findenclosed findoverlap tree item id snapshot cursorxy)) {
	$button{$_} = $fm1->Checkbutton(-image => $bitmaps->{$_},
					-indicatoron => 0,
					-foreground => 'gray20')->pack(-side => 'left');
    }
    for (qw(zoomminus zoomplus move)) {
	$button{$_} = $fm2->Checkbutton(-image => $bitmaps->{$_},
					-indicatoron => 0,
					-foreground => 'gray20')->pack(-side => 'left');
    }
    for (qw(balloon close)) {
	$button{$_} = $fm3->Checkbutton(-image => $bitmaps->{$_},
					-indicatoron => 0,
					-foreground => 'gray20')->pack(-side => 'left');
    }
    my $bg = $button{zn}->cget(-background);
    for (values(%button)) {
	$_->configure(-selectcolor => $bg);
    }
    $balloonhelp = &balloonhelp();
    $button{balloon}->toggle;
    $control_tl->withdraw();
    $button{zn}->configure(-command => \&focuscommand);
    $button{balloon}->configure(-command => sub {
				    if ($button{balloon}->{Value} == 0) {
					$balloonhelp->configure(-state => 'none');
				    } else {
					$balloonhelp->configure(-state => 'balloon');
				    }
			 });
    #--------------------------------------------------
    # on/off commands for exclusive modes :
    #--------------------------------------------------
    
    # findenclosed mode
    $on_command{findenclosed} = sub {
	&saveDragAndDropBindings($selectedzinc);
	$button{findenclosed}->{Value} = 1;
	$selectedzinc->Tk::bind("<ButtonPress-1>",
				[\&startrectangle, 'simple', 'Enclosed',
				       'sienna']);
	$selectedzinc->Tk::bind("<B1-Motion>", \&resizerectangle);
	$selectedzinc->Tk::bind("<ButtonRelease-1>",
				[\&stoprectangle, 'enclosed',
				 'Items enclosed in rectangle']);
    };
    $off_command{findenclosed} = sub {
	$button{findenclosed}->{Value} = 0;
	&restoreDragAndDropBindings($selectedzinc);
	$selectedzinc->remove("zincdebugrectangle", "zincdebuglabel");
    };
    # findoverlap mode
    $on_command{findoverlap} = sub {
	&saveDragAndDropBindings($selectedzinc);
	$button{findoverlap}->{Value} = 1;
	$selectedzinc->Tk::bind("<ButtonPress-1>", [\&startrectangle, 'mixed',
						    'Overlap', 'sienna']);
	$selectedzinc->Tk::bind("<B1-Motion>", \&resizerectangle);
	$selectedzinc->Tk::bind("<ButtonRelease-1>",
				[\&stoprectangle, 'overlapping',
				 'Items which overlap rectangle']);
    };
    $off_command{findoverlap} = sub {
	$button{findoverlap}->{Value} = 0;
	&restoreDragAndDropBindings($selectedzinc);
	$selectedzinc->remove("zincdebugrectangle", "zincdebuglabel");
    };
    # item mode
    $on_command{item} = sub {
	&saveDragAndDropBindings($selectedzinc);
	$button{item}->{Value} = 1;
	$selectedzinc->Tk::bind("<ButtonPress-1>", [\&findintree]);
    };
    $off_command{item} = sub {
	$button{item}->{Value} = 0;
	&restoreDragAndDropBindings($selectedzinc);
    };
    # cursor device position mode
    $on_command{cursorxy} = sub {
	&saveMotionBinding($selectedzinc);
	$button{cursorxy}->{Value} = 1;
	&cursorxyOpen;
	$selectedzinc->Tk::bind("<Motion>", [\&cursorxy]);
    };
    $off_command{cursorxy} = sub {
	$button{cursorxy}->{Value} = 0;
	&cursorxyClose;
	&restoreMotionBinding($selectedzinc);
    };
    
    # move mode
    $on_command{move} = sub {
	&saveDragAndDropBindings($selectedzinc);
	$button{move}->{Value} = 1;
	my ($x0, $y0);
	$selectedzinc->Tk::bind('<ButtonPress-1>', sub {
	    my $ev = $selectedzinc->XEvent;
	    ($x0, $y0) = ($ev->x, $ev->y);
	});
	$selectedzinc->Tk::bind('<B1-Motion>', sub {
	    my $ev = $selectedzinc->XEvent;
	    my ($x, $y) = ($ev->x, $ev->y);
	    $selectedzinc->translate(1, $x-$x0, $y-$y0) if defined $x0;
	    ($x0, $y0) = ($x, $y);
	});
    };
    $off_command{move} = sub {
	$button{move}->{Value} = 0;
	&restoreDragAndDropBindings($selectedzinc);
    };
    # zn mode
    $on_command{zn} = sub {
	$button{zn}->{Value} = 1;
	for my $zinc (&instances) {
	    $zinc->remove("zincdebugrectangle", "zincdebuglabel");
	    &saveDragAndDropBindings($zinc);
	    my $r;
	    $zinc->Tk::bind("<ButtonPress-1>", sub {
		$zinc->update;
		my ($w, $h) = ($zinc->cget(-width), $zinc->cget(-height));
		$zinc->tsave(1, 'transfoTopgroup', 1);
		$r = $zinc->add('rectangle', 1, [30, 30, $w-30, $h-30],
				-linecolor => 'red',
				-linewidth => 10);
		$zinc->trestore($r, 'transfoTopgroup');
		$zinc->raise($r);
		$selectedzinc = $zinc;
	    });
	    $zinc->Tk::bind("<ButtonRelease-1>", sub {
		$zinc->remove($r);
	    });
	}
    };
    $off_command{zn} = sub {
	$button{zn}->{Value} = 0;
        for my $zinc (&instances) {
	    &restoreDragAndDropBindings($zinc);
	}
    };

    my @but = qw(findenclosed findoverlap item move zn cursorxy);
    for my $name (@but) {
	$button{$name}->configure(-command => sub {
	    if ($button{$name}->{Value} == 1) {
		for my $other (@but) {
		    &{$off_command{$other}} unless $other eq $name;
		}
	    &{$on_command{$name}};
	    } else {
		&{$off_command{$name}};
	    }});
    }

    $button{id}->configure(-command => sub {
	$button{id}->update;
	&searchentry($zinc);
	$button{id}->toggle;
    });
    
    $button{snapshot}->configure(-command => sub {
	$button{snapshot}->update;
	&printWindow($zinc);
	$button{snapshot}->toggle;
    });
    
    $button{zoomminus}->configure(-command => sub {
	$button{zoomminus}->update;
	my $w = $selectedzinc->cget(-width);
	my $h = $selectedzinc->cget(-height);
	$selectedzinc->translate(1, -$w/2, -$h/2);
	$selectedzinc->scale(1, 1/1.1, 1/1.1);
	$selectedzinc->translate(1, $w/2, $h/2);
	$button{zoomminus}->toggle;
	});
    
    $button{zoomplus}->configure(-command => sub {
	$button{zoomplus}->update;
	my $w = $selectedzinc->cget(-width);
	my $h = $selectedzinc->cget(-height);
	$selectedzinc->translate(1, -$w/2, -$h/2);
	$selectedzinc->scale(1, 1.1, 1.1);
	$selectedzinc->translate(1, $w/2, $h/2);
	$button{zoomplus}->toggle;
	});
        
    $button{tree}->configure(-command => sub {
	$button{tree}->update;
	&showtree($selectedzinc);
	$button{tree}->toggle;
	});
    
    $button{close}->configure(-command => sub {
	$button{close}->update;
	&Tk::Zinc::Debug::iconify;
	&restoreDragAndDropBindings($selectedzinc);
	for my $name (@but) {
	    &{$off_command{$name}};
	}
	$button{close}->toggle;
    });
    
} # end init


#---------------------------------------------------------------------------
#
# Deprecated functions
#
#---------------------------------------------------------------------------

sub tree {
    
    carp "in Tk::Zinc::Debug module, tree() function is deprecated.\n";
    &init($_[0]);
    
} # end tree


sub finditems {
    
    carp "in Tk::Zinc::Debug module, finditems() function is deprecated.\n";
    &init($_[0]);
    
} # end finditems



sub snapshot {
    
    carp "in Tk::Zinc::Debug module, snapshot() function is deprecated.\n";
    &init($_[0]);

} # end snapshot


#---------------------------------------------------------------------------
#
# Functions related to cursor position
#
#---------------------------------------------------------------------------
sub cursorxy {

    my $ev = shift->XEvent;
    $cursorxy = $ev->x.", ".$ev->y;
    
} # end cursorxy


sub cursorxyOpen {

    if (Tk::Exists($cursorxy_tl)) {
	$cursorxy_tl->raise;
	return;
    }
    $cursorxy_tl = $control_tl->Toplevel;
    $cursorxy_tl->Label(-text => "Cursor device position")->pack;
    $cursorxy_tl->Label(-textvariable => \$cursorxy)->pack;
    $cursorxy_tl->minsize(150, 40);
    $cursorxy_tl->raise;
    
} # end cursorxyOpen


sub cursorxyClose {

    $cursorxy_tl->destroy if Tk::Exists($cursorxy_tl);

} # end cursorxyClose


#---------------------------------------------------------------------------
#
# Functions related to items tree
#
#---------------------------------------------------------------------------

# build or rebuild the items tree
sub showtree {
    
    my $zinc = shift;
    my $optionstodisplay = $cmdoptions{optionsToDisplay};
    my $optionsFormat = $cmdoptions{optionsFormat};
    # styles definition
    $itemstyle =
	$zinc->ItemStyle('text', -stylename => "item", -foreground => 'black')
	    unless $itemstyle;
    $groupstyle =
	$zinc->ItemStyle('text', -stylename => "group", -foreground => 'black')
	    unless $groupstyle;

    $WARNING = 0;
    my @optionstodisplay = split(/,/, $optionstodisplay);
    $WARNING = 1;
    &hidetree();
    $tree_tl = $control_tl->Toplevel;
    $tree_tl->minsize(280, 200);
    $tree_tl->title("Zinc Items Tree");
    $tree = $tree_tl->Scrolled('Tree',
			       -scrollbars => 'se',
			       -height => 40,
			       -width => 50,
			       -itemtype => 'text',
			       -selectmode => 'single',
			       -separator => '.',
			       -drawbranch => 1,
			       -indent => 30,
			       -command => sub {
				   my $path = shift;
				   my $item = (split(/\./, $path))[-1];
				   &showresult("Attributes of item $item", $zinc, $item);
				   $zinc->after(100, sub {
				       &undohighlightitem(undef, $zinc)});
			       },
			       );
    &wheelmousebindings($tree);
    $tree->bind('<1>', [sub {
	my $path = $tree->nearest($_[1]);
	my $item = (split(/\./, $path))[-1];
	&highlightitem($tree, $zinc, $item, 0);
		       
    }, Ev('y')]);
    
    $tree->bind('<2>', [sub {
	my $path = $tree->nearest($_[1]);
	return if $path eq 1;
	$tree->selectionClear;
	$tree->selectionSet($path);
	$tree->anchorSet($path);
	my $item = (split(/\./, $path))[-1];
	&highlightitem($tree, $zinc, $item, 1);
		       
    }, Ev('y')]);

    $tree->bind('<3>', [sub {
	my $path = $tree->nearest($_[1]);
	return if $path eq 1;
	$tree->selectionClear;
	$tree->selectionSet($path);
	$tree->anchorSet($path);
	my $item = (split(/\./, $path))[-1];
	&highlightitem($tree, $zinc, $item, 2);
		       
    }, Ev('y')]);
    
    $tree->add("1", -text => "Group(1)", -state => 'disabled');
    &scangroup($zinc, $tree, 1, "1", $optionsFormat, @optionstodisplay);
    $tree->autosetmode;
    # control buttons frame
    my $tree_butt_fm = $tree_tl->Frame(-height => 40)->pack(-side => 'bottom',
							    -fill => 'y');
    $tree_butt_fm->Button(-text => 'Help',
			  -command => [\&showHelpAboutTree, $zinc],
			  )->pack(-side => 'left', -pady => 10,
				  -padx => 10, -fill => 'both');
    
    $tree_butt_fm->Button(-text => 'Search',
			  -command => [\&searchInTree, $zinc],
			  )->pack(-side => 'left', -pady => 10,
				  -padx => 10, -fill => 'both');
    $tree_butt_fm->Button(-text => "Build\ncode",
			  -command => [\&buildCode, $zinc, $tree],
			  )->pack(-side => 'left', -pady => 10,
				  -padx => 10, -fill => 'both');
    
    $tree_butt_fm->Button(-text => "Attributes",
			  -command => sub {
			      my $path = $tree->selectionGet;
			      $path = 1 unless $path;
			      my $item = (split(/\./, $path))[-1];
			      &showresult("Attributes of item $item", $zinc, $item);
			  },
			  )->pack(-side => 'left', -pady => 10,
				  -padx => 10, -fill => 'both');
    

    $tree_butt_fm->Button(-text => 'Close',
			  -command => sub {$zinc->remove("zincdebug");
					   $tree_tl->destroy},
			  )->pack(-side => 'left', -pady => 10,
				  -padx => 20, -fill => 'both');
    # pack tree
    $tree->pack(-padx => 10, -pady => 10,
		-ipadx => 10,
		-side => 'top',
		-fill => 'both',
		-expand => 1,
		);
    

} # end showtree


# destroy the items tree
sub hidetree {
    
    $tree_tl->destroy if $tree_tl and Tk::Exists($tree_tl);
    
} # end hidetree


# find a pointed item in the items tree
sub findintree {
    
    my $zinc = shift;
    if (not Tk::Exists($tree_tl)) {
	&showtree($zinc);
    }
    my $ev = $zinc->XEvent;
    ($x0, $y0) = ($ev->x, $ev->y);
    my @atomicgroups = &unsetAtomicity($zinc);
    my $item = $zinc->find('closest', $x0, $y0);
    &restoreAtomicity($zinc, @atomicgroups);
    return unless $item > 1;
    my @ancestors = reverse($zinc->find('ancestors', $item));
    my $path = join('.', @ancestors).".".$item;
    # tree is rebuilded unless path exists
    unless ($tree->info('exists', $path)) {
	$tree_tl->destroy;
	#print "path=$path rebuild tree\n";
	&showtree($zinc);
    }
    $tree->see($path);
    $tree->selectionClear;
    $tree->anchorSet($path);
    $tree->selectionSet($path);
    &surrounditem($zinc, $item);
    $tree->focus;

} # end findintree


sub searchInTree {
    
    my $zinc = shift;
    $searchtree_tl->destroy if $searchtree_tl and Tk::Exists($searchtree_tl);
    $searchtree_tl = $tree_tl->Toplevel;
    $searchtree_tl->transient($tree_tl);
    $searchtree_tl->title("Find string in tree");
    my $fm = $searchtree_tl->Frame->pack(-side => 'top');
    $fm->Label(-text => "Find : ",
	       )->pack(-side => 'left', -padx => 10, -pady => 10);
    my $entry = $fm->Entry(-width => 20)->pack(-side => 'left',
					       -padx => 10, -pady => 10);
    my $status = $searchtree_tl->Label(-foreground => 'sienna',
				   )->pack(-side => 'top');
    my $ep = 1;
    my $searchfunc =  sub {
	my $side = shift;
	my $found = 0;
        #print "ep=$ep side=$side\n";
	$status->configure(-text => "");
	$status->update;
	$searchTreeEntryValue = $entry->get();
	$searchTreeEntryValue = quotemeta($searchTreeEntryValue);
	my $text;
	while ($ep) {
 	    $ep = $tree->info($side, $ep);
	    unless ($ep) {
		$ep = 1;
		$found = 0;
		last;
	    }
	    $text = $tree->entrycget($ep, -text);
	    if ($text =~ /$searchTreeEntryValue/) {
		$tree->see($ep);
		$tree->selectionClear;
		$tree->anchorSet($ep);
		$tree->selectionSet($ep);
		$found = 1;
		last;
	    }
	}
	#print "searchTreeEntryValue=$searchTreeEntryValue found=$found\n";
	$status->configure(-text => "Search string not found") unless $found > 0;
    };

    my $fm2 = $searchtree_tl->Frame->pack(-side => 'top');
    $fm2->Button(-text => 'Prev',
		 -command => sub {&$searchfunc('prev');},
		 )->pack(-side => 'left', -pady => 10);
    $fm2->Button(-text => 'Next',
		 -command => sub {&$searchfunc('next');},
		 )->pack(-side => 'left', -pady => 10);
    $fm2->Button(-text => 'Close',
		 -command => sub {$searchtree_tl->destroy},
		 )->pack(-side => 'right', -pady => 10);
    $entry->focus;
    $entry->delete(0, 'end');
    $entry->insert(0, $searchTreeEntryValue) if $searchTreeEntryValue;
    $entry->bind('<Key-Return>', sub {&$searchfunc('next');});
    
} # end searchInTree


sub extractinfo {
    my $zinc = shift;
    my $item = shift;
    my $format = shift;
    my $option = shift;
    my $titleflag = shift;
    $option =~ s/^\s+//;
    $option =~ s/\s+$//;
    #print "option=[$option]\n";
    my @info;
    $WARNING = 0;
    eval {@info = $zinc->itemcget($item, $option)};
    #print "eval $option = (@info) $@\n";
    return if $@;
    return if @info == 0;
    my $info;
    my $sep = ($format eq 'column') ? "\n  " : ", ";
    if ($titleflag) {
	$info = $sep."[$option] ".$info[0];
    } else {
	$info = $sep.$info[0];
    }
    if (@info > 1) {
	shift(@info);
	for (@info) {
	    if ($format eq 'column') {
		if (length($info." ".$_) > 40) {
		    if ($titleflag) {
			$info .= $sep."[$option] ".$_;
		    } else {
			$info .= $sep.$_;
		    }
		} else {
		    $info .= ", $_";
		}
	    } else {
		$info .= $sep.$_;
	    }
	}
    }
    $WARNING = 1;
    return $info;
    
} # end extractinfo


sub scangroup {
    
    my ($zinc, $tree, $group, $path, $format, @optionstodisplay) = @_;
    my @items = $zinc->find('withtag', "$group.");
    for my $item (@items) {
	my $Type = ucfirst($zinc->type($item));
	my $info = " ";
	if (@optionstodisplay == 1) {
	    $info .= &extractinfo($zinc, $item, $format, $optionstodisplay[0]);
	} elsif (@optionstodisplay > 1) {
	    for my $opt (@optionstodisplay) {
		$info .= &extractinfo($zinc, $item, $format, $opt, 1);
	    }
	}
	if ($Type eq "Group") {
	    $tree->add($path.".".$item,
		       -text => "$Type($item)$info",
		       -style => 'group',
		       );
	    &scangroup($zinc, $tree, $item, $path.".".$item, $format, @optionstodisplay);
	} else {
	    $tree->add($path.".".$item,
		       -text => "$Type($item)$info",
		       -style => 'item',
		       );
	}
    }

} # end scangroup

#---------------------------------------------------------------------------
#
# Functions used to build code
#
#---------------------------------------------------------------------------

# build perl code corresponding to a branch of the items tree
sub buildCode {
    
    my $zinc = shift;
    my $tree = shift;
    my @code;
    push(@code, 'use Tk;');
    push(@code, 'use Tk::Zinc;');
    push(@code, 'my $mw = MainWindow->new();');
    push(@code, 'my $zinc = $mw->Zinc(-render => '.$zinc->cget(-render).
	 ')->pack(-expand => 1, -fill => "both");');
    push(@code, '# hash %items : keys are original items ID, values are built items ID');
    push(@code, 'my %items;');
    push(@code, '');
    my $path = $tree->selectionGet;
    $path = 1 unless $path;
    my $item = (split(/\./, $path))[-1];
    $endoptions = [];
    if ($zinc->type($item) eq 'group') {
	push(@code, &buildGroup($zinc, $item, 1));
	for(@$endoptions) {
	    my ($item, $option, $value) = @$_;
	    push(@code,
		 '$zinc->itemconfigure('.$item.', '.$option.' => '.$value.');');
	}
    } else {
	push(@code, &buildItem($zinc, $item, 1));
    }
    push(@code, &buildEnd);
    
    my $file = $zinc->getSaveFile(-filetypes => [['Perl Files',   '.pl'],
                                               ['All Files',   '*']],
				  -initialfile => 'zincdebug.pl',
				  -title => 'Save code',
				  );
    return unless defined $file;
    $zinc->Busy;
    open (OUT, ">$file");
    for (@code) {
	print OUT $_."\n";
    }
    close(OUT);
    $zinc->Unbusy;
    
} # end buildCode


sub buildEnd {

    my @code;
    push(@code, 'for (keys(%items)) {');
    push(@code, '   $zinc->addtag(\'orig\'.$_, "withtag", $items{$_});');
    push(@code, '}');
    push(@code, 'MainLoop;');
    return @code
	
} # end buildEnd


# build a node of tree (corresponding to a TkZinc group item)
sub buildGroup {
    
    my $zinc = shift;
    my $item = shift;
    my $group = shift;
    my @code;
    # creation
    push(@code, '$items{'.$item.'}=$zinc->add("group", '.$group.', ');
    # options
    push(@code, &buildOptions($zinc, $item));
    push(@code, ');');
    push(@code, '');
    # coords
    push(@code, '$zinc->coords($items{'.$item.'}, ['.
	 join(',', $zinc->coords($item)).']);');
    # transformations
    push(@code, &buildTransformations($zinc, $item));
    
    my @items = $zinc->find('withtag', "$item.");
    for my $it (reverse(@items)) {
	if ($zinc->type($it) eq 'group') {
	    push(@code, &buildGroup($zinc, $it, '$items{'.$item.'}'));
	} else {
	    push(@code, &buildItem($zinc, $it, '$items{'.$item.'}'));
	}
    }
    return @code;

} # end buildGroup


# build a leaf of tree (corresponding to a TkZinc non-group item)
sub buildItem {
    
    my $zinc = shift;
    my $item = shift;
    my $group = shift;
    my $type = $zinc->type($item);
    my @code;
    my $numfields = 0;
    my $numcontours = 0;
    # creation    
    my $initstring = '$items{'.$item.'}=$zinc->add("'.$type.'", '.$group.', ';
    if ($type eq 'tabular' or $type eq 'track' or $type eq 'waypoint') {
	$numfields = $zinc->itemcget($item, -numfields);
	$initstring .= $numfields.' ,';
    } elsif ($type eq 'curve' or $type eq 'triangles' or
	     $type eq 'arc' or $type eq 'rectangle') {
	$initstring .= "[ ";
	my (@coords) = $zinc->coords($item);
	if (ref($coords[0]) eq 'ARRAY') {
	    my @coords2;
	    for my $c (@coords) {
		if (@$c > 2) {
		     push(@coords2, '['.$c->[0].', '.$c->[1].', "'.$c->[2].'"]');
		} else {
		     push(@coords2, '['.$c->[0].', '.$c->[1].']');
		    
		}
	    }
	    $initstring .= join(', ', @coords2);
	} else {
	    $initstring .= join(', ', @coords);
	}
	$initstring .= " ], ";
	$numcontours = $zinc->contour($item);
    } 
    push(@code, $initstring);
    # options
    push(@code, &buildOptions($zinc, $item));
    push(@code, ');');
    push(@code, '');
    # fields
    if ($numfields > 0) {
    	for (my $i=0; $i < $numfields; $i++) {
	    push(@code, &buildField($zinc, $item, $i));
	}
    }
    # contours
    if ($numcontours > 1) {
	for (my $i=1; $i < $numcontours; $i++) {
	    my (@coords) = $zinc->coords($item);
	    my @coords2;
	    for my $c (@coords) {
		if (@$c > 2) {
		    push(@coords2, '['.$c->[0].', '.$c->[1].', "'.$c->[2].'"]');
		} else {
		    push(@coords2, '['.$c->[0].', '.$c->[1].']');
		}
	    }
	    my $coordstr = '[ '.join(', ', @coords2).' ]';
	    push(@code, '$zinc->contour($items{'.$item.'}, "add", 0, ');
	    push(@code, '            '.$coordstr.');');
	}
    }
    # transformations
    push(@code, &buildTransformations($zinc, $item));
    
    return @code;

} # end buildItem


# add an information field to an item of the tree
sub buildField {
    
    my $zinc = shift;
    my $item = shift;
    my $field = shift;
    my @code;
    # type group and initargs
    push(@code, '$zinc->itemconfigure($items{'.$item.'}, '.$field.', ');
    # options
    push(@code, &buildOptions($zinc, $item, $field));
    push(@code, ');');
    push(@code, '');
    return @code;

} # end buildField


sub buildTransformations {

    my $zinc = shift;
    my $item = shift;
    my @tr = $zinc->tget($item);
    my @code;
    return ('$zinc->tset($items{'.$item.'}, '.join(", ", @tr).');');

} # end buildTransformations


sub buildOptions {
    
    my $zinc = shift;
    my $item = shift;
    my $field = shift;
    my @code;
    my @args = defined($field) ? ($item, $field) : ($item);
    my @options = $zinc->itemconfigure(@args);
    for my $elem (@options) {
	my ($option, $type, $readonly, $value) = (@$elem)[0, 1, 2, 4];
	next if $value eq '';
	next if $readonly;
	if ($type eq 'point') {
	    push(@code, "           ".$option." => [".join(',', @$value)."], ");
	    
	} elsif (($type eq 'bitmap' or $type eq 'image') and $value !~ /^AtcSymbol/
	    and $value !~ /^AlphaStipple/) {
	    push(@code, "#           ".$option." => '".$value."', ");
	    
	} elsif ($type eq 'item') {
	    $endoptions->[@$endoptions] =
		['$items{'.$item.'}', $option, '$items{'.$value.'}'];
	    
	} elsif ($option eq '-text') {
	    $value =~ s/\"/\\"/;       # comment for emacs legibility => "
	    push(@code, "           ".$option.' => "'.$value.'", ');

	} elsif (ref($value) eq 'ARRAY') {
	    push(@code, "           ".$option." => [qw(".join(' ', @$value).")], ");

	} else {
	    push(@code, "           ".$option." => '".$value."', ");
	}
    }
    return @code;

} # end buildOptions

#---------------------------------------------------------------------------
#
# Functions related to search in a rectangular area
#
#---------------------------------------------------------------------------

# begin to draw rectangular area for search
sub startrectangle {
    
    my ($zinc, $style, $text, $color) = @_;
    $zinc->remove("zincdebugrectangle", "zincdebuglabel");
    my $ev = $zinc->XEvent;
    ($x0, $y0) = ($ev->x, $ev->y);
    # store and name the inverted transformation of top group
    $zinc->tsave(1, 'zoom+move', 1);
    $zinc->add('rectangle', 1, [$x0, $y0, $x0, $y0],
	       -linecolor => $color,
	       -linewidth => 2,
	       -linestyle => $style,
	       -tags => ["zincdebugrectangle"],
			       );
    $zinc->add('text', 1,
	       -color => $color,
	       -font => '7x13',
	       -position => [$x0+5, $y0-15],
	       -text => $text,
	       -tags => ["zincdebuglabel"],
	       );
    # apply to new rectangle the (inverted) transformation stored below
    $zinc->trestore("zincdebugrectangle", 'zoom+move');
    $zinc->trestore("zincdebuglabel", 'zoom+move');
  
} # end startrectangle


# resize the rectangular area for search
sub resizerectangle {
    
    my $zinc = shift;
    my $ev = $zinc->XEvent;
    my ($x, $y) = ($ev->x, $ev->y);
    return unless ($zinc->find('withtag', "zincdebugrectangle"));

    $zinc->coords("zincdebugrectangle", 1, 1, [$x, $y]);
    if ($x < $x0) {
	if ($y < $y0) {
	    $zinc->coords("zincdebuglabel", [$x+5, $y-15]);
	} else {
	    $zinc->coords("zincdebuglabel", [$x+5, $y0-15]);
	}
    } else {
	if ($y < $y0) {
	    $zinc->coords("zincdebuglabel", [$x0+5, $y-15]);
	} else {
	    $zinc->coords("zincdebuglabel", [$x0+5, $y0-15]);
	}
    }
    $zinc->raise("zincdebugrectangle");
    $zinc->raise("zincdebuglabel");

} # end resizerectangle


# stop drawing rectangular area for search
sub stoprectangle {
    
    my ($zinc, $searchtype, $text) = @_;
    return unless ($zinc->find('withtag', "zincdebugrectangle"));

    my @atomicgroups = &unsetAtomicity($zinc);
    $zinc->update;
    my ($c0, $c1) = $zinc->coords("zincdebugrectangle");
    my @coords = (@$c0, @$c1);
    my @items;
    for my $item ($zinc->find($searchtype, @coords, 1, 1)) {
	push (@items, $item) unless $zinc->hastag($item, "zincdebugrectangle") or
	    $zinc->hastag($item, "zincdebuglabel");
    }
    &restoreAtomicity($zinc, @atomicgroups);
    if (@items) {
	&showresult($text, $zinc, @items);
    } else {
	$zinc->remove("zincdebugrectangle", "zincdebuglabel");
    }

} # end stoprectangle


# in order to avoid find problems with group atomicity, we set all -atomic
# attributes to 0
sub unsetAtomicity {
    
    my $zinc = shift;
    my @groups = $zinc->find('withtype', 'group');
    my @atomicgroups;
    for my $group (@groups) {
	if ($zinc->itemcget($group, -atomic)) {
	    push(@atomicgroups, $group);
	    $zinc->itemconfigure($group, -atomic => 0);
	}
    }
    return @atomicgroups;
    
} # end unsetAtomicity


sub restoreAtomicity {
    
    my $zinc = shift;
    my @atomicgroups = @_;
    for my $group (@atomicgroups) {
	$zinc->itemconfigure($group, -atomic => 1);
    }

} # end restoreAtomicity


#---------------------------------------------------------------------------
#
# Function related to item's id search 
#
#---------------------------------------------------------------------------

sub searchentry {
    
    my $zinc = shift;
    $search_tl->destroy if $search_tl and Tk::Exists($search_tl);
    $search_tl = $control_tl->Toplevel;
    $search_tl->title("Specific search");
    my $fm = $search_tl->Frame->pack(-side => 'top');
    $fm->Label(-text => "Item TagOrId : ",
	       )->pack(-side => 'left', -padx => 10, -pady => 10);
    my $entry = $fm->Entry(-width => 20)->pack(-side => 'left',
					       -padx => 10, -pady => 10);
    my $status = $search_tl->Label(-foreground => 'sienna',
				   )->pack(-side => 'top');
    $search_tl->Button(-text => 'Close',
		       -command => sub {$search_tl->destroy},
		       )->pack(-side => 'top', -pady => 10);
    $entry->focus;
    $entry->delete(0, 'end');
    $entry->insert(0, $searchEntryValue{$zinc}) if $searchEntryValue{$zinc};
    $entry->bind('<Key-Return>', [sub {
	$status->configure(-text => "");
	$status->update;
	$searchEntryValue{$zinc} = $entry->get();
	my @items = $zinc->find('withtag', $searchEntryValue{$zinc});
	if (@items) {
	    my $label;
	    if ($searchEntryValue{$zinc} =~ /^\d/) {
		$label = "Attributes of item $searchEntryValue{$zinc}";
	    } else {
		$label = "Attributes of item(s) with tag $searchEntryValue{$zinc}"
	    }
	    &showresult($label, $zinc, @items);
	} else {
	    $status->configure(-text => "No such tagOrId ($searchEntryValue{$zinc})");
	}
    }]);
    
} # end searchentry


#---------------------------------------------------------------------------
#
# Functions related to transformations parameters
#
#---------------------------------------------------------------------------

sub showtransfoparams {

    my ($label, $zinc, $item) = @_;
    my @m = $zinc->tget($item);
    my ($m00, $m01, $m10, $m11, $m20, $m21) = @m;
    my ($xt, $yt, $xsc, $ysc, $a, $xsk, $ysk) = $zinc->tget($item, 'all');
    # bug zinc 
    $ysk = 0 unless defined $ysk;
    for ($m00, $m01, $m10, $m11, $m20, $m21, $xt, $yt, $xsc, $ysc, $a, $xsk, $ysk) {
	$_ = sprintf("%.2f", $_) if /^-?\d+\.\d/;
    }
    $transfo_tl{$item}->destroy if Tk::Exists($transfo_tl{$item});
    $transfo_tl{$item} = $control_tl->Toplevel();
    $transfo_tl{$item}->transient($result_tl{$label})
	if Tk::Exists($result_tl{$label});
    my $title = "Transformations of item $item";
    $transfo_tl{$item}->title($title);
    my $bgcolor = 'ivory';
    my $fm1 = $transfo_tl{$item}->Frame()->pack(-side => 'top',
						-padx => 20,
						-pady => 10,
						-expand => 1,
						-fill => 'x',
						);
    # set transformation to ident
    my $btn = $fm1->Button(-text => "Show item with transformation\nset to identity",
			   -bg => $bgcolor,
			   )->pack(-side => 'top', -padx => 5, -pady => 10);
    $balloonhelp->attach($btn,-balloonmsg =>
			 "Click and maintain to show the transformation  \n".
			 "animation. Use btn1, btn2 or btn3 to select the\n".
			 "best background color for a good visibility.   ");
    $btn->bind('<1>', [\&showtransfo, $zinc, $item, 0]);
    $btn->bind('<2>', [\&showtransfo, $zinc, $item, 1]);
    $btn->bind('<3>', [\&showtransfo, $zinc, $item, 2]);
    
    my $fm11 = $fm1->Frame()->pack(-side => 'left',
				   -padx => 20,
				   );

    my ($set_cb, $reset_cb, $upd_cb);
    
    # matrix
    my $r = 0;
    my $c = 0;
    $fm11->Label(-text => 'matrix', -relief => 'ridge', -bg => $bgcolor)
	->grid(-row => $r++, -columnspan => 2,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm11->Label(-textvariable => \$m00, -relief => 'ridge')
	->grid(-row => $r, -column => $c,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm11->Label(-textvariable => \$m01, -relief => 'ridge')
	->grid(-row => $r++, -column => $c+1,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm11->Label(-textvariable => \$m10, -relief => 'ridge')
	->grid(-row => $r, -column => $c,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm11->Label(-textvariable => \$m11, -relief => 'ridge')
	->grid(-row => $r++, -column => $c+1,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm11->Label(-textvariable => \$m20, -relief => 'ridge')
	->grid(-row => $r, -column => $c,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm11->Label(-textvariable => \$m21, -relief => 'ridge')
	->grid(-row => $r++, -column => $c+1,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    


    my $fm12 = $fm1->Frame()->pack(-side => 'left',
				   -padx => 20,
				   );
    my ($e_xt, $e_yt, $e_xsc, $e_ysc, $e_a, $e_xsk, $e_ysk);

    $set_cb = sub {
	$zinc->treset($item);
	$zinc->translate($item, $e_xt, $e_yt);
	$zinc->rotate($item, $e_a);
	$zinc->scale($item, $e_xsc, $e_ysc);
	$zinc->skew($item, $e_xsk, $e_ysk);
	($m00, $m01, $m10, $m11, $m20, $m21) = $zinc->tget($item);
	for ($m00, $m01, $m10, $m11, $m20, $m21) {
	    $_ = sprintf("%.2f", $_) if /^-?\d+\.\d/;
	}
    };

    # translate params
    $r = 0;
    $c = 0;    
    $fm12->Label(-text => 'translate', -relief => 'ridge', -bg => $bgcolor)
	->grid(-row => $r, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');

    &entrytransfo($fm12, $item, $zinc, 'xt', $xt, \$e_xt, 4, $set_cb)
    	->grid(-row => $r, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    
    &entrytransfo($fm12, $item, $zinc, 'yt', $yt, \$e_yt, 4, $set_cb)
	->grid(-row => $r++, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    
    # rotate params
    $c = 0;
    $fm12->Label(-text => 'rotate', -relief => 'ridge', -bg => $bgcolor)
	->grid(-row => $r, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');

    &entrytransfo($fm12, $item, $zinc, 'a', $a, \$e_a, 4, $set_cb)
	->grid(-row => $r++, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');

    # scale params
    $c = 0;
    $fm12->Label(-text => 'scale', -relief => 'ridge', -bg => $bgcolor)
	->grid(-row => $r, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');

    &entrytransfo($fm12, $item, $zinc, 'xsc', $xsc, \$e_xsc, 4, $set_cb)
	->grid(-row => $r, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    &entrytransfo($fm12, $item, $zinc, 'ysc', $ysc, \$e_ysc, 4, $set_cb)
	->grid(-row => $r++, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    
    # skew params
    $c = 0;
    $fm12->Label(-text => 'skew', -relief => 'ridge', -bg => $bgcolor)
	->grid(-row => $r, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    
    &entrytransfo($fm12, $item, $zinc, 'xsk', $xsk, \$e_xsk, 4, $set_cb)
	->grid(-row => $r, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    &entrytransfo($fm12, $item, $zinc, 'ysk', $ysk, \$e_ysk, 4, $set_cb)
	->grid(-row => $r++, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');


    my $fm2 = $transfo_tl{$item}->Frame()->pack(-side => 'top',
						-padx => 20,
						-pady => 0,
						);
    $fm2->Button(-text => 'Close',
		-command => sub {
		    $transfo_tl{$item}->destroy;
		    delete $transfo_tl{$item};
		})->pack(-side => 'top', -padx => 40, -pady => 20);
    
    
    
} # end showtransfoparams


#---------------------------------------------------------------------------
#
# Functions related to results tables display
#
#---------------------------------------------------------------------------

# display in a toplevel the result of search ; a new toplevel destroyes the
# previous one
sub showresult {
    
    my ($label, $zinc, @items) = @_;
    # toplevel (re-)creation
    $result_tl{$label}->destroy if Tk::Exists($result_tl{$label});
    $result_tl{$label} = $control_tl->Toplevel();
    my $title = "TK::Zinc Debug";
    $title .= " - $label" if $label;
    $result_tl{$label}->title($title);
    $result_tl{$label}->geometry('+10+20');
    $control_tl->raise;
    my $fm = $result_tl{$label}->Frame()->pack(-side => 'bottom',
				       );
    $fm->Button(-text => 'Close',
		-command => sub {
		    $result_tl{$label}->destroy;
		    delete $result_tl{$label};
		    $zinc->remove("zincdebugrectangle", "zincdebuglabel");
		})->pack(-side => 'left', -padx => 40, -pady => 10);
    
    # scrolled pane creation
    $result_fm = $result_tl{$label}->Scrolled('Pane',
					      -scrollbars => 'osoe',
					      -height => 200,
					      -width => 1024,
					      );
    &wheelmousebindings($result_fm);
    my $fm2 = $result_fm->Frame->pack;
    # attributes display
    &showattributes($zinc, $fm2, $label, \@items);
    $result_fm->update;
    $fm2->update;
    my $width = $fm2->width + 10;
    $width = $screenwidth if $width > $screenwidth;
    $result_fm->configure(-width => $width);
    $result_fm->pack(-padx => 10, -pady => 10,
		     -ipadx => 10,
		     -fill => 'both',
		     -expand => 1,
		     );

} # end showresult

# display table containing additionnal options/values
sub showalloptions {
    
    my ($label, $zinc, $item, $fmp) = @_;
    $alloptions_tl{$item}->destroy if Tk::Exists($alloptions_tl{$item});
    $alloptions_tl{$item} = $control_tl->Toplevel();
    $alloptions_tl{$item}->transient($result_tl{$label})
	if Tk::Exists($result_tl{$label});
    my $tl = $alloptions_tl{$item};
    my $title = "All options of item $item";
    $tl->title($title);
    $tl->geometry('-10+0');
    

    # footer
    #----------------
    $tl->Button(-text => 'Close',
		-command => sub {
		    $alloptions_tl{$item}->destroy;
		    delete $alloptions_tl{$item};
		})->pack(-side => 'bottom');
    # option scrolled frame
    #-----------------------
    my $fm = $tl->Scrolled('Pane',
			   -scrollbars => 'oe',
			   -height => 500,
			   )->pack(-padx => 10, -pady => 10,
				   -ipadx => 10,
				   -expand => 1,
				   -fill => 'both');
    
    my $bgcolor = 'ivory';
    my $i = 1;
    $fm->Label(-text => $title, -background => $bgcolor,
	       -fg => 'sienna', -relief => 'ridge')
	->grid(-row => $i++, -column => 1, -ipady => 5, -ipadx => 5,
	       -columnspan => 2, -sticky => 'nswe') if $label;
    $fm->Label(-text => 'Option', -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => 1, -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => 'Value', -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i++, -column => 2, -ipady => 10, -ipadx => 5, -sticky => 'nswe');

    my @options = $zinc->itemconfigure($item);
    for my $elem (@options) {
	my ($option, $type, $value) = (@$elem)[0,1,4];
	$fm->Label(-text => $option, -relief => 'ridge')
	    ->grid(-row => $i, -column => 1,
		   -ipady => 5, -ipadx => 5, -sticky => 'nswe');
	if ($option eq '-tags') {
	    &entryoption($fm, $item, $zinc, $option,
			 join("\n", @$value), 30, 30, scalar @$value)
		->grid(-row => $i, -column => 2, -ipady => 5,
		       -ipadx => 5, -sticky => 'nswe');
	} else {
	    &entryoption($fm, $item, $zinc, $option, undef, 50, 25)
		->grid(-row => $i, -column => 2, -ipady => 5,
		       -ipadx => 5, -sticky => 'nswe');
	}
	$i++;
    }
    
} # end showalloptions


# display device coords table
sub showdevicecoords {
    
    my ($label, $zinc, $item) = @_;
    &showcoords($label, $zinc, $item, 1);

} # end showdevicecoords


# display coords table
sub showcoords {
    
    my ($label, $zinc, $item, $deviceflag) = @_;
    my $bgcolor = 'ivory';
    my $bgcolor2 = 'gray75';
    $coords_tl{$item}->destroy if Tk::Exists($coords_tl{$item}) and not $deviceflag;
    $coords_tl{$item} = $control_tl->Toplevel();
    $coords_tl{$item}->transient($result_tl{$label}) if Tk::Exists($result_tl{$label});
    my $title = "Zinc Debug";
    if ($deviceflag) {
	$title .= " - Coords of item $item";
    } else {
	$title .= " - Device coords of item $item";
    }
    $coords_tl{$item}->title($title);
    $coords_tl{$item}->geometry('+10+20');
    my $coords_fm0 = $coords_tl{$item}->Frame()->pack(-side => 'bottom');
    $coords_fm0->Button(-text => 'Help',
			-command => [\&showHelpAboutCoords, $zinc]
			)->pack(-side => 'left', -padx => 40, -pady => 10);
    $coords_fm0->Button(-text => 'Close',
			-command => sub {
			    &hidecontour($zinc);
			    $coords_tl{$item}->destroy;
			    delete $coords_tl{$item};
			})->pack(-side => 'left', -padx => 40, -pady => 10);
    # scrolled pane creation
    my $coords_fm = $coords_tl{$item}->Scrolled('Pane',
					 -scrollbars => 'oe',
					 -height => 200,
					 )->pack(-padx => 10, -pady => 10,
						 -ipadx => 10,
						 -expand => 1,
						 -fill => 'both');
    my @contour;
    my $contournum = $zinc->contour($item);
    for (my $i=0; $i < $contournum; $i++) {
	my @coords = $zinc->coords($item, $i);
	if (!ref $coords[0]) {
	    ## The first item of the list is not a reference, so the
	    ## list is guarranted to be a flat list (x, y, ...)
	    ## normaly of only one pair of (x y)
	    @coords = $zinc->transform($item, 'device', [@coords])
		if $deviceflag;
	    for (my $j=0; $j < @coords; $j += 2) {
		push(@{$contour[$i]}, [$coords[$j], $coords[$j+1]]);
	    }
	}
	else {
	    ## the first element is an array reference, as every
	    ## other elements of the list
	    for (my $j=0; $j < @coords; $j ++) {
		my @c = @{$coords[$j]};
		@c = $zinc->transform($item, 'device', [@c])
		    if $deviceflag;
		push(@{$contour[$i]}, [@c]);
	    }
	}
    }
    my $row = 1;
    my $col = 1;
    for (my $i=0; $i < @contour; $i++) {
	$col = 1;
	my $lab = $coords_fm->Label(-text => "Contour $i",
				    -background => $bgcolor,
				    -relief => 'ridge')->grid(-row => $row,
							      -column => $col,
							      -ipadx => 5,
							      -ipady => 5,
							      -sticky => 'nswe');
	$lab->bind('<1>', [\&showcontour, $zinc, 'black', $item, $contour[$i],
			   $deviceflag]);
	$lab->bind('<2>', [\&showcontour, $zinc, 'white', $item, $contour[$i],
			   $deviceflag]);
	$lab->bind('<3>', [\&showcontour, $zinc, 'red', $item, $contour[$i],
			   $deviceflag]);
	$lab->bind('<ButtonRelease-1>', sub { &hidecontour($zinc); });
	$lab->bind('<ButtonRelease-2>', sub { &hidecontour($zinc); });
	$lab->bind('<ButtonRelease-3>', sub { &hidecontour($zinc); });
	my $lab1 = $coords_fm->Label(-text => scalar(@{$contour[$i]})." points",
				     -background => $bgcolor,
				     -relief => 'ridge')->grid(-row => $row+1,
							       -column => $col,
							       -ipadx => 5,
							       -ipady => 5,
							       -sticky => 'nswe');
	$lab1->bind('<1>', [\&showcontourpts, $zinc, 'black', $item, $contour[$i],
			    $deviceflag]);
	$lab1->bind('<2>', [\&showcontourpts, $zinc, 'white', $item, $contour[$i],
			    $deviceflag]);
	$lab1->bind('<3>', [\&showcontourpts, $zinc, 'red', $item, $contour[$i],
			    $deviceflag]);
	$lab1->bind('<ButtonRelease-1>', sub { &hidecontour($zinc); });
	$lab1->bind('<ButtonRelease-2>', sub { &hidecontour($zinc); });
	$lab1->bind('<ButtonRelease-3>', sub { &hidecontour($zinc); });
	$col++;
	my @lab;
	for my $coords (@{$contour[$i]}) {
	    if ($col > 10) {
		$col = 2;
		$row++;
	    }
	    $coords->[0] =~ s/\.(\d\d).*/\.$1/;
	    $coords->[1] =~ s/\.(\d\d).*/\.$1/;
	    my @opt;
	    if (defined $coords->[2]) {
		@opt = (-text => sprintf('%s, %s, %s', @$coords),
			-underline => length(join(',', @$coords)) + 1,
			);
	    } else {
		@opt = (-text => sprintf('%s, %s', @{$coords}[0,1]));
	    }
	    push (@lab, $coords_fm->Label(@opt,
					  -width => 15,
					  -relief => 'ridge')->grid(-row => $row,
								    -ipadx => 5,
								    -ipady => 5,
								    -column => $col++,
								    -sticky => 'nswe'));
	}
	$row++ if (@{$contour[$i]} < 10);
	$row++;
	my $j = 0;
	for (@lab) {
	    $_->bind('<1>', [\&showcontourpt, $zinc, 'black',
			     $item, $j, $deviceflag, \@lab, @{$contour[$i]}]);
	    $_->bind('<2>', [\&showcontourpt, $zinc, 'white',
			     $item, $j, $deviceflag, \@lab, @{$contour[$i]}]);
	    $_->bind('<3>', [\&showcontourpt, $zinc, 'red',
			     $item, $j, $deviceflag, \@lab, @{$contour[$i]}]);
	    $j++;
	}

    }

} # end showcoords



# display in a grid the values of most important attributes 
sub showattributes {
    
    my ($zinc, $fm, $label, $items, $expandTagsFlag) = @_;
    $expandTagsFlag = 1;
    &getsize($zinc);
    my $bgcolor = 'ivory';
    my $i = 1;
    $fm->Label(-text => $label, -background => $bgcolor,
	       -fg => 'sienna', -relief => 'ridge')
	->grid(-row => $i++, -column => 0, -ipady => 0, -ipadx => 5,
	       -columnspan => 7, -sticky => 'nswe') if $label;

    &showbanner($fm, $i++);
    $i++;
    for my $item (@$items) {
	my $c = 0;
	my $type = $zinc->type($item);
	# id
	my $idbtn =
	    $fm->Button(-text => $item,
			-foreground => 'sienna'
			)->grid(-row => $i, -column => $c++, -sticky => 'nswe',
				-ipadx => 5);
	$idbtn->bind('<1>', [\&highlightitem, $zinc, $item, 0]);
	$idbtn->bind('<2>', [\&highlightitem, $zinc, $item, 1]);
	$idbtn->bind('<3>', [\&highlightitem, $zinc, $item, 2]);
	$balloonhelp->attach($idbtn,-balloonmsg =>
			     "Click and maintain to show the item.     \n".
			     "Use btn1, btn2 or btn3 to select the best\n".
			     "background color for a good visibility.  ");
	# type
	if ($type eq 'group') {
	    my $gbtn =
		$fm->Button(-text => $type,
			    -command => sub {
				my @items = $zinc->find('withtag', $item.".");
				&showresult("Content of group $item", $zinc, @items);
			    });
	    $gbtn->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	    $balloonhelp->attach($gbtn,-balloonmsg =>
				 "Click to display the group's content.");
	} else {
	    $fm->Label(-text => $type, -relief => 'ridge')
		->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	}
	# parent group
	my $group = $zinc->group($item);
	my $pgbtn =
	    $fm->Button(-text => $group,
			-command => [\&showresult,
				     "Attributes of group $group (parent of $item)",
				     $zinc, $group]);
	$pgbtn->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	$balloonhelp->attach($pgbtn,-balloonmsg =>
			     "Click to display the parent group's attributes.");
	# priority
	&entryoption($fm, $item, $zinc, -priority)
	    ->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 2);
	# sensitiveness
	&entryoption($fm, $item, $zinc, -sensitive)
	    ->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 2);
	# visibility
	&entryoption($fm, $item, $zinc, -visible)
	    ->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 2);
	# other options
	$fm->Button(-text => 'show',
		    -command => [\&showalloptions, $label, $zinc, $item, $fm])
	    ->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	# transformations
	my $tlabel = 'yes';
	my ($xt, $yt, $xsc, $ysc, $a, $xsk) = $zinc->tget($item, 'all');
	$tlabel = 'no' if ($xt == 0 and $yt == 0 and $xsc == 1 and $ysc == 1 and
			   $a == 0 and $xsk == 0);
	my $tbtn =
	    $fm->Button(-text => $tlabel, 
			-command => [\&showtransfoparams, $label, $zinc, $item],
			);
	$tbtn->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	$balloonhelp->attach($tbtn,-balloonmsg =>
			     "Click to display transformation parameters.\n".
			     "Some of them can be updated.               ");
	
	# coords
	my @coords = $zinc->coords($item);
	my $coords;
	if (!ref $coords[0]) {
	    my $x0 = int($coords[0]);
	    my $y0 = int($coords[1]);
	    $coords = "($x0, $y0)";
	} else {
	    my @points0 = @{$coords[0]};
	    my $n = $#coords;
	    my @pointsN = @{$coords[$n]};
	    my $x0 = int($points0[0]);
	    my $y0 = int($points0[1]);
	    my $xn = int($pointsN[0]);
	    my $yn = int($pointsN[1]);
	    if ($n == 1) { ## a couple of points
		$coords = "($x0, $y0, $xn, $yn)";
	    } else {
		$coords = "P0=($x0, $y0), ..., P".$n."=($xn, $yn)";
	    }
	}
	if (@coords > 2) {
	    my $cbtn = $fm->Button(-text => $coords,
				   -command => [\&showcoords, $label, $zinc, $item]);
	    $cbtn->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 2);
	    $balloonhelp->attach($cbtn,-balloonmsg =>
				 "Click to show all coordinates.");
	} else {
	    $fm->Label(-text => $coords, -relief => 'ridge')
		->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	}
	# device coords
	@coords = $zinc->transform($item, 'device', [@coords]);
	if (!ref $coords[0]) {
	    my $x0 = int($coords[0]);
	    my $y0 = int($coords[1]);
	    $coords = "($x0, $y0)";
	} else {
	    my @points0 = @{$coords[0]};
	    my $n = $#coords;
	    my @pointsN = @{$coords[$n]};
	    my $x0 = int($points0[0]);
	    my $y0 = int($points0[1]);
	    my $xn = int($pointsN[0]);
	    my $yn = int($pointsN[1]);
	    if ($n == 1) { ## a couple of points
		$coords = "($x0, $y0, $xn, $yn)";
	    } else {
		$coords = "P0=($x0, $y0), ..., P".$n."=($xn, $yn)";
	    }
	}
	if (@coords > 2) {
	    my $dcbtn =
		$fm->Button(-text => $coords,
			    -command => [\&showdevicecoords, $label, $zinc, $item]);
	    $dcbtn->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 2);
	    $balloonhelp->attach($dcbtn,-balloonmsg =>
				 "Click to show all device coordinates.");
	} else {
	    $fm->Label(-text => $coords, -relief => 'ridge')
		->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	}
	# bounding box
	my @bbox = $zinc->bbox($item);
	if (@bbox == 4) {
	    my ($b0, $b1, $b2, $b3) = @bbox;
	    $b0 = sprintf("%.2f", $b0) if int($b0) ne $b0;
	    $b1 = sprintf("%.2f", $b1) if int($b1) ne $b1;
	    $b2 = sprintf("%.2f", $b2) if int($b2) ne $b2;
	    $b3 = sprintf("%.2f", $b3) if int($b3) ne $b3;
	    my $btn = $fm->Button(-text => "($b0, $b1), ($b2, $b3)")
		->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	    $btn->bind('<1>', [\&showbbox, $zinc, $item]);
	    $btn->bind('<ButtonRelease-1>', [\&hidebbox, $zinc]) ;
	    $balloonhelp->attach($btn,-balloonmsg =>
				 "Click to show the bounding box.");
	} else {
	    $fm->Label(-text => "--", , -relief => 'ridge')
		->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);
	}
	# tags
  	my @tags = $zinc->gettags($item);
	my $height = 2;
	$height = scalar @tags if $cmdoptions{expandTagsField};
	&entryoption($fm, $item, $zinc, -tags, join("\n", @tags), 30, 30, $height)
	    ->grid(-row => $i, -column => $c++, -sticky => 'nswe', -ipadx => 5);

	$i++;
	&showbanner($fm, $i++) if ($i % 15 == 0);
    }
    
} # end showattributes


sub showbanner {
    
    my $fm = shift;
    my $i = shift;
    my $bgcolor = 'ivory';
    my $c = 0;
    $fm->Label(-text => "Item\nId", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++, -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => "Item\nType", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++, -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => "Parent\ngroup", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++, -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => "P\nr\ni\no", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++, -ipady => 2, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => "S\ne\nn\ns", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++, -ipady => 2, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => "V\ni\ns\ni", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++, -ipady => 2, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => "All\noptions", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++,
	       -ipady => 5, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => "Transfo", -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++,
	       -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => 'Coords', -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++,
	       -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => 'Device coords', -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++,
	       -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => 'Bounding box', -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++,
	       -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => 'Tags', -background => $bgcolor, -relief => 'ridge')
	->grid(-row => $i, -column => $c++,
	       -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label()->grid(-row => 1, -column => $c++, -pady => 10);

} # end showbanner


#---------------------------------------------------------------------------
#
# Functions related to contours display
#
#---------------------------------------------------------------------------

# display contour (as simple curve)
sub showcontour {
    my ($widget, $zinc, $color, $item, $contourcoords, $deviceflag) = @_;
    if ($deviceflag) {
	$zinc->add('curve', 1, $contourcoords,
		   -filled => 0,
		   -linecolor => $color,
		   -tags => ['zincdebugcontour']);

    } else {
	$zinc->add('curve', 1, [$zinc->transform($item, 1, $contourcoords)],
		   -filled => 0,
		   -linecolor => $color,
		   -tags => ['zincdebugcontour']);
    }
    $zinc->raise('zincdebugcontour');
    
} # end showcontour


sub hidecontour {
    
    my ($zinc) = @_;
    $zinc->remove('zincdebugcontour');
    
} # end hidecontour


# display contours points (one rectangle per point)
sub showcontourpts {
    my ($widget, $zinc, $color, $item, $contourcoords, $deviceflag) = @_;
    my $i = 0;
    for my $coords (@$contourcoords) {
	my ($x, $y);
	if ($deviceflag) {
	    ($x, $y) = @$coords;
	} else {
	    ($x, $y) = $zinc->transform($item, 1, $coords);
	}
	if ($i == 0) {
	    $zinc->add('arc', 1, [$x-10, $y-10, $x+10, $y+10],
		       -filled => 0,
		       -linewidth => 1,
		       -linecolor => $color,
		       -tags => ['zincdebugcontour']);
	} elsif ($i == @$contourcoords -1) {
	    $zinc->add('arc', 1, [$x-10, $y-10, $x+10, $y+10],
		       -filled => 0,
		       -linewidth => 1,
		       -linecolor => $color,
		       -tags => ['zincdebugcontour']);
	    $zinc->add('arc', 1, [$x-13, $y-13, $x+13, $y+13],
		       -filled => 0,
		       -linewidth => 1,
		       -linecolor => $color,
		       -tags => ['zincdebugcontour']);
	}
	my $dx = 3;
	if (@$coords > 2) {
	    $zinc->add('rectangle', 1, [$x-$dx, $y-$dx, $x+$dx, $y+$dx],
		       -filled => 0,
		       -linewidth => 1,
		       -linecolor => $color,
		       -tags => ['zincdebugcontour']);
	} else {
	    $zinc->add('rectangle', 1, [$x-$dx, $y-$dx, $x+$dx, $y+$dx],
		       -filled => 1,
		       -linewidth => 1,
		       -fillcolor => $color,
		       -linecolor => $color,
		       -tags => ['zincdebugcontour']);
	}
	$i++;
    }
    $zinc->raise('zincdebugcontour');
    
} # end showcontourpts


# display one point of a contour (as a rectangle)
sub showcontourpt {
    
    my ($widget, $zinc, $color, $item, $index, $deviceflag, $labels, @contour) = @_;
    $widget->focus;
    if ($index < 0 or $index >= @contour) {
	$widget->bell;
	return;
    }
    &hidecontour($zinc);
    my $bgcolor = ($labels->[0]->configure(-background))[3];
    for (@$labels) {
	$_->configure(-background => $bgcolor);
    }
    $labels->[$index]->configure(-background => 'bisque');
    my @coords = @{$contour[$index]};
    my ($x, $y);
    if ($deviceflag) {
	($x, $y) = @coords;
    } else {
	($x, $y) = $zinc->transform($item, 1, [@coords]);
    }
    my $dx = 3;
    if (@coords > 2) {
	$zinc->add('rectangle', 1, [$x-$dx, $y-$dx, $x+$dx, $y+$dx],
		   -filled => 0,
		   -linewidth => 1,
		   -linecolor => $color,
		   -tags => ['zincdebugcontour']);
    } else {
	$zinc->add('rectangle', 1, [$x-$dx, $y-$dx, $x+$dx, $y+$dx],
		   -filled => 1,
		   -linewidth => 1,
		   -fillcolor => $color,
		   -linecolor => $color,
		   -tags => ['zincdebugcontour']);
    }
    $widget->bind('<Key-Down>', [\&showcontourpt, $zinc, $color,
				 $item, $index+1, $deviceflag, $labels, @contour]);
    $widget->bind('<Key-Right>', [\&showcontourpt, $zinc, $color,
				 $item, $index+1, $deviceflag, $labels, @contour]);
    $widget->bind('<Key-Up>', [\&showcontourpt, $zinc, $color,
				$item, $index-1, $deviceflag, $labels, @contour]);
    $widget->bind('<Key-Left>', [\&showcontourpt, $zinc, $color,
				$item, $index-1, $deviceflag, $labels, @contour]);
    $zinc->raise('zincdebugcontour');

} # end showcontourpt


#---------------------------------------------------------------------------
#
# Functions related to items graphical presentation
#
#---------------------------------------------------------------------------

# display the bbox of a group item
sub showbbox {
    
    my ($btn, $zinc, $item) = @_;
    $zinc->tsave(1, 'zoom+move', 1);
    my @bbox  = $zinc->bbox($item);
    if (scalar @bbox == 4) {
	# If item is visible, rectangle is drawm surround it.
	# Else, a warning is displayed.
	unless (&itemisoutside($zinc, @bbox)) {
	    my $i = -2;
	    for ('white', 'blue', 'white') {
		$zinc->add('rectangle', 1,
			   [$bbox[0] + $i, $bbox[1] + $i,
			    $bbox[2] - $i, $bbox[3] - $i],
			   -linecolor => $_,
			   -linewidth => 1,
			   -tags => ['zincdebugbbox']);
		$i += 2;
	    }
	}
    }
    $zinc->trestore('zincdebugbbox', 'zoom+move');
    $zinc->raise('zincdebugbbox');

} # end showbbox


sub hidebbox {
    
    my ($btn, $zinc) = @_;
    $zinc->remove("zincdebugbbox");

} # end hidebbox


# display a message box when an item is not visible because outside window
sub itemisoutside {
    
    my $zinc = shift;
    my @bbox = @_;
    return unless @bbox == 4;
    &getsize($zinc);
    #print "bbox=(@bbox) wheight=$wheight{$zinc} wwidth=$wwidth{$zinc}\n";
    my $outflag;
    $WARNING = 0;
    if ($bbox[2] < 0) {
	if ($bbox[1] >  $wheight{$zinc}) {
	    $outflag = 'left+bottom';
	} elsif ($bbox[3] < 0) {
	    $outflag = 'left+top';
	} else {
	    $outflag = 'left';
	} 
    } elsif ($bbox[0] > $wwidth{$zinc}) {
	if ($bbox[1] >  $wheight{$zinc}) {
	    $outflag = 'right+bottom';
	} elsif ($bbox[3] < 0) {
	    $outflag = 'right+top';
	} else {
	    $outflag = 'right';
	}
    } elsif ($bbox[3] < 0) {
	$outflag = 'top';
    } elsif ($bbox[1] > $wheight{$zinc}) {
	$outflag = 'bottom';
    }
    #print "outflag=$outflag bbox=@bbox\n";
    return 0 unless $outflag;
    # create first group which will be translated. We will apply to this group
    # the reverse transformation of topgroup. 
    my $g = $zinc->add('group', 1, -tags => ['zincdebug']);
    # create child group which won't be affected by ancestor's scale.
    my $g1 = $zinc->add('group', $g, -composescale => 0);
    my $hw = 110;
    my $hh = 80;
    my $r = 5;
    $zinc->add('rectangle', $g1, [-$hw, -$hh, $hw, $hh],
	       -filled => 1,
	       -linecolor => 'sienna',
	       -linewidth => 3,
	       -fillcolor => 'bisque',
	       -priority => 1,
	       );
    $zinc->add('text', $g1,
	       -position => [0, 0],
	       -color => 'sienna',
	       -font => '-b&h-lucida-bold-i-normal-sans-34-240-*-*-p-*-iso8859-1',
	       -anchor => 'center',
	       -priority => 2,
	       -text => "Item is\noutside\nwindow\n");
    my ($x, $y);
    if ($outflag eq 'bottom') {
	$x = $bbox[0] + ($bbox[2]-$bbox[0])/2;
	$x = $hw + 10 if $x < $hw + 10;
	$x = $wwidth{$zinc} - $hw - 10 if $x > $wwidth{$zinc} - $hw - 10;
	$y = $wheight{$zinc} - $hh - 10;
    } elsif ($outflag eq 'top') {
	$x = $bbox[0] + ($bbox[2]-$bbox[0])/2;
	$x = $hw + 10 if $x < $hw + 10;
	$x = $wwidth{$zinc} - $hw - 10if $x > $wwidth{$zinc} - $hw - 10;
	$y = $hh + 10;
    } elsif ($outflag eq 'left') {
	$x = $hw + 10;
	$y = $bbox[1] + ($bbox[3]-$bbox[1])/2;
	$y = $hh + 10 if $y < $hh + 10;
	$y = $wheight{$zinc} - $hh - 10 if $y > $wheight{$zinc} - $hh - 10;
    } elsif ($outflag eq 'right') {
	$x = $wwidth{$zinc} - $hw - 10;
	$y = $bbox[1] + ($bbox[3]-$bbox[1])/2;
	$y = $hh + 10 if $y < $hh + 10;
	$y = $wheight{$zinc} - $hh - 10 if $y > $wheight{$zinc} - $hh - 10;
    } elsif ($outflag eq 'left+top') {
	$x = $hw + 10;
	$y = $hh + 10;
    } elsif ($outflag eq 'left+bottom') {
	$x = $hw + 10;
	$y = $wheight{$zinc} - $hh - 10;
    } elsif ($outflag eq 'right+top') {
	$x = $wwidth{$zinc} - $hw - 10;
	$y = $hh + 10;
    } elsif ($outflag eq 'right+bottom') {
	$x = $wwidth{$zinc} - $hw - 10;
	$y = $wheight{$zinc} - $hh - 10;
    }
    # apply the reverse transformation of topgroup to group $g
    $zinc->tsave(1, 'transfo', 1);
    $zinc->trestore($g, 'transfo');
    # then translate group $g1
    $zinc->coords($g1, [$x, $y]);
    $zinc->raise('zincdebug');
    
} # end itemisoutside



# highlight an item (by cloning it and hiding other found items)
# why cloning? because we can't simply make visible an item which
# belongs to an invisible group.
sub highlightitem {
    
    my ($btn, $zinc, $item, $level) = @_;
    return if $showitemflag or $item == 1;
    $showitemflag = 1;
    &surrounditem($zinc, $item, $level);
    
    $btn->bind('<ButtonRelease>', [\&undohighlightitem, $zinc]) if $btn;

} # end highlightitem


sub undohighlightitem {
    
    my ($btn, $zinc) = @_;
    #print "undohighlightitem\n";
    $btn->bind('ReleaseButton', '') if $btn;
    $zinc->remove('zincdebug');
    $showitemflag = 0;

} # end undohighlightitem


sub surrounditem {
    
    my ($zinc, $item, $level) = @_;
    $zinc->remove("zincdebug");
    # cloning
    my $clone = $zinc->clone($item, -visible => 1, -tags => ['zincdebug']);
    $zinc->tsave(1, 'zoom+move', 1);
    $zinc->chggroup($clone, 1, 1);
    my @bbox = $zinc->bbox($clone);
    # create a rectangle around 
    if (scalar @bbox == 4) {
	# If item is visible, rectangle is drawm surround it.
	# Else, a warning is displayed.
	unless (&itemisoutside($zinc, @bbox)) {
	    if (defined($level) and $level > 0) {
		my $r = $zinc->add('rectangle', 1,
				   [$bbox[0] - 10, $bbox[1] - 10,
				    $bbox[2] + 10, $bbox[3] + 10],
				   -linewidth => 0,
				   -filled => 1,
				   -tags => ['zincdebug', 'zincdebugdecorator'],
				   -fillcolor => "gray20");
		$zinc->itemconfigure($r, -fillcolor => "gray80") if $level == 1;
	    } 
	    my $i = 0;
	    for ('white', 'red', 'white') {
		$zinc->add('rectangle', 1,
			   [$bbox[0] - 5 - 2*$i, $bbox[1] - 5 - 2*$i,
			    $bbox[2] + 5 + 2*$i, $bbox[3] + 5 + 2*$i],
			   -linecolor => $_,
			   -linewidth => 1,
			   -tags => ['zincdebug', 'zincdebugdecorator']);
		$i++;
	    }
	}
    }
    # raise
    $zinc->trestore('zincdebugdecorator', 'zoom+move');
    $zinc->raise('zincdebug');
    $zinc->raise($clone);

} # end surrounditem


# functions related to transformation animations
sub showtransfo {
    
    my ($btn, $zinc, $item, $level) = @_;
    my $anim = &highlighttransfo($zinc, $item, $level);
    $btn->bind('<ButtonRelease>', [\&undohighlighttransfo, $zinc, $anim]) if $btn;

} # end showtransfo


sub highlighttransfo {
    
    my ($zinc, $item, $level) = @_;
    $zinc->remove("zincdebug");
    my $g = $zinc->add('group', 1);
    my $g0 = $zinc->add('group', $g, -alpha => 0);
    my $g1 = $zinc->add('group', $g);
    # clone item and reset its transformation
    my $clone0 = $zinc->clone($item, -visible => 1, -tags =>['zincdebug']);
    $zinc->treset($clone0);
    # clone item and preserve its transformation
    my $clone1 = $zinc->clone($item, -visible => 1, -tags => ['zincdebug']);
    # move clones is dedicated group
    $zinc->chggroup($clone0, $g0, 1);
    $zinc->chggroup($clone1, $g1, 1);
    # create a rectangle around 
    my @bbox0  = $zinc->bbox($g);
    if (scalar @bbox0 == 4) {
	$zinc->tsave(1, 'transfo', 1);
	my @bbox = $zinc->transform(1, $g, [@bbox0]);
	# If item is visible, rectangle is drawm surround it.
	# Else, a warning is displayed.
	unless (&itemisoutside($zinc, @bbox0)) {
	    my $r = $zinc->add('rectangle', $g,
			       [$bbox[0] - 10, $bbox[1] - 10,
				$bbox[2] + 10, $bbox[3] + 10],
			       -filled => 1,
			       -linewidth => 0,
			       -tags => ['zincdebug'],
			       -fillcolor => "gray90");
	    $zinc->itemconfigure($r, -fillcolor => "gray50") if $level == 1;
	    $zinc->itemconfigure($r, -fillcolor => "gray20") if $level == 2;
	    $zinc->trestore($r, 'transfo');
	}
    }
    # raise
    $zinc->raise($g);
    $zinc->raise($g0);
    $zinc->raise($g1);
    # animation
    my $anim;
    if ($zinc->cget(-render) == 0) {
	$anim = $zinc->after(150, [sub {
	    $zinc->itemconfigure($g1, -visible => 0);
	    $zinc->itemconfigure($g0, -visible => 1);
	    $zinc->update;
	}]);
    } else {
	my $maxsteps = 5;
	$step = $maxsteps;
	$anim = $zinc->repeat(100, [sub {
	    return if $step < 0;
	    $zinc->itemconfigure($g1, -alpha => ($step)*100/$maxsteps);
	    $zinc->itemconfigure($g0, -alpha => ($maxsteps-$step)*100/$maxsteps);
	    $zinc->update;
	    $step--;
	}]);


    }
    return $anim;

} # end highlighttransfo


sub undohighlighttransfo {
    
    my ($btn, $zinc, $anim) = @_;
    $btn->bind('ReleaseButton', '') if $btn;
    $zinc->remove('zincdebug');
    $zinc->afterCancel($anim);

} # end undohighlighttransfo


#---------------------------------------------------------------------------
#
# Snapshot functions
#
#---------------------------------------------------------------------------

# print a zinc window in png format
sub printWindow {
    
    exit if $saving;
    $saving = 1;
    my ($zinc) = @_;
    my $basename = $cmdoptions{snapshotBasename};
    my $id = $zinc->id;
    my $filename = $basename . $imagecounter . ".png";
    $imagecounter++;
    my $original_cursor = ($zinc->configure(-cursor))[3];
    $zinc->configure(-cursor => 'watch');
    $zinc->update;
    my $res = system("import", -window, $id, $filename);
    $zinc->configure(-cursor => $original_cursor);
    
    $saving = 0;
    if ($res) {
	&showErrorWhilePrinting($zinc, $res)
	}
    else {
	my $dir = `pwd`; chomp ($dir);
	print "Tk::Zinc::Debug: Zinc window snapshot saved in $dir". "/$filename\n";
    }

} # end printWindow


# display complete help screen
sub showErrorWhilePrinting {
    
    my ($zinc, $res) = @_;
    my $dir = `pwd`; chomp ($dir);
    $help_print->destroy if $help_print and Tk::Exists($help_print);
    $help_print = $zinc->Dialog(-title => 'Zinc Print info',
				-text =>
				"To acquire a TkZinc window snapshot, you must " .
				"have access to the import command, which is ".
				"part of imageMagic package\n\n".
				"You must also have the rights to write ".
				"in the current dir : $dir",
				-bitmap => 'warning',
				);
    $help_print->after(300, sub {$help_print->grabRelease});
    $help_print->Show();

} # end showErrorWhilePrinting

#---------------------------------------------------------------------------
#
# Help functions
#
#---------------------------------------------------------------------------

# display help about tree
sub showHelpAboutTree {
    
    my $zinc = shift;
    $helptree_tl->destroy if $helptree_tl and Tk::Exists($helptree_tl);
    $helptree_tl = $tree_tl->Toplevel;
    $helptree_tl->title("Help about Tree");

    my $text = $helptree_tl->Scrolled('Text',
					-font => scalar $zinc->cget(-font),
					-wrap => 'word',
					-foreground => 'gray10',
					-scrollbars => 'osoe',
					);
    &wheelmousebindings($text);
    $text->tagConfigure('keyword', -foreground => 'darkblue');
    $text->insert('end', "\nNAVIGATION IN TREE\n\n");
    $text->insert('end', "<Up>", "keyword");
    $text->insert('end', " arrow key moves the anchor point to the item right on ".
		  "top of the current anchor item. ");
    $text->insert('end', "<Down>", "keyword");
    $text->insert('end', " arrow key moves the anchor point to the item right below ".
		  "the current anchor item. ");
    $text->insert('end', "<Left>", "keyword");
    $text->insert('end', " arrow key moves the anchor to the parent item of the ".
		  "current anchor item. ");
    $text->insert('end', "<Right>", "keyword");
    $text->insert('end', " moves the anchor to the first child of the current anchor ".
		  "item. If the current anchor item does not have any children, moves ".
		  "the anchor to the item right below the current anchor item.\n\n");
    $text->insert('end', "\nHIGHLIGHTING ITEMS\n\n");
    $text->insert('end', "To display item's features, ");
    $text->insert('end', "double-click", "keyword");
    $text->insert('end', " on it, press ");
    $text->insert('end', "<Return>", "keyword");
    $text->insert('end', " key or click on the ");
    $text->insert('end', "Attributes", "keyword");
    $text->insert('end', " button.\n\n");
    $text->insert('end', "To highlight item in the application, simply ");
    $text->insert('end', "click", "keyword");
    $text->insert('end', " on it.");
    &infoAboutHighlighting($text);
    $text->insert('end', "\n\n\nBUILDING CODE\n\n");
    $text->insert('end', "To build perl code, select a branch or a leaf ".
		  "and click on the ");
    $text->insert('end', "Build code", "keyword");
    $text->insert('end', " button. Then select an output file with the ".
		  "file selector.\n\n");
     $text->configure(-state => 'disabled');
    
    $helptree_tl->Button(-command => sub {$helptree_tl->destroy},
			 -text => 'Close')->pack(-side => 'bottom',
						 -pady => 10);
    $text->pack->pack(-side => 'top', -pady => 10, -padx => 10);

} # end showHelpAboutTree


sub showHelpAboutCoords {
    
    my $zinc = shift;
    $helpcoords_tl->destroy if $helpcoords_tl and Tk::Exists($helpcoords_tl);
    $helpcoords_tl = $zinc->Toplevel;
    $helpcoords_tl->title("Help about coordinates");

    my $text = $helpcoords_tl->Scrolled('Text',
				      -font => scalar $zinc->cget(-font),
				      -wrap => 'word',
				      -height => 30,
				      -foreground => 'gray10',
				      -scrollbars => 'oe',
				      );
    &wheelmousebindings($text);
    $text->tagConfigure('keyword', -foreground => 'darkblue');
    $text->tagConfigure('title', -foreground => 'ivory',
			-background => 'gray60',
			-spacing1 => 3,
			-spacing3 => 3);

    
    $text->insert('end', " To display a contour\n", 'title');
    $text->insert('end', "Press button labeled ");
    $text->insert('end', 'Contour i', 'keyword');
    $text->insert('end', " (*). Release it to hide contour.");
    $text->insert('end', "\n\n");
    $text->insert('end', " To display all the points of a contour\n", 'title');
    $text->insert('end', "Press button labeled ");
    $text->insert('end', 'n points', 'keyword');
    $text->insert('end', " (*). Release it to hide points. First plot is ".
		  "particularized by a circle, last one by a double circle. ".
		  "Non-filled plots represent control points of a Bezier curve.");
    $text->insert('end', "\n\n");
    $text->insert('end', " To navigate in the contour\n", 'title');
    $text->insert('end', "Select first a point by clicking in the coordinates table ");
    $text->insert('end', "(*). Th corresponding plot is displayed. Then use the ");
    $text->insert('end', "Up/Down", 'keyword');
    $text->insert('end', " (or ");
    $text->insert('end', "Left/Right", 'keyword');
    $text->insert('end', ") arrows keys to navigate in the contour");
    $text->insert('end', "\n\n");
    $text->insert('end', "\n\n");
    $text->insert('end', "(*) The color of displayed elements depends on the mouse ".
		  "button you press.");
    $text->insert('end', "\n\n");
    $text->configure(-state => 'disabled');
    
    $helpcoords_tl->Button(-command => sub {$helpcoords_tl->destroy},
			 -text => 'Close')->pack(-side => 'bottom',
						 -pady => 10);
    $text->pack->pack(-side => 'top', -pady => 10, -padx => 10);

} # end showHelpAboutCoords



sub infoAboutHighlighting {
    
    my $text = shift;
    $text->insert('end', "By default, using ");
    $text->insert('end', "left mouse button", "keyword");
    $text->insert('end', ", highlighting is done by raising selected item and drawing ".
		  "a rectangle arround. ");
    $text->insert('end', "In order to improve visibility, ");
    $text->insert('end', "item will be light backgrounded if you use ");
    $text->insert('end', "center mouse button", "keyword");
    $text->insert('end', " and dark backgrounded if you use ");
    $text->insert('end', "right mouse button", "keyword");
    $text->insert('end', ". ");
    
} # end infoAboutHighlighting


sub entryballoonhelp {

    my $e = shift;
    my $msg = shift;
    $msg .= "Editable field. To restore the inital value\n".
	    "after edition, enter <Control-z> sequence. ";
    $balloonhelp->attach($e, -balloonposition => 'mouse',
			 -balloonmsg => $msg);
    
} # end entryballoonhelp


sub balloonhelp {
    
    my $b = $control_tl->Balloon(-balloonposition => 'widget',
				 -font => '6x13');
    $b->attach($button{zn},-balloonmsg =>
	       "Widget instance selector. Use it when \n".
	       "your application takes more than one  \n".
	       "TkZinc instance. When this mode is on,\n".
	       "select the TkZinc instance you want   \n".
	       "inspect just by clicking on it.       ");
    $b->attach($button{findenclosed}, -balloonmsg =>
	       "Inspect all items *enclosed* in a  \n".
	       "rectangular area. When this mode is\n".
	       "selected, draw rectangle using left\n".
	       "mouse button.                      ");
    $b->attach($button{findoverlap}, -balloonmsg =>
	       "Inspect all items which *overlap* \n".
	       "a rectangular area. When this mode\n".
	       "is selected, draw rectangle using \n".
	       "left mouse button.                ");
    $b->attach($button{tree}, -balloonmsg =>
	       #"Display the items hierarchy. Can\n".
	       #"build perl code corresponding to\n".
	       #"a specific branch.              ");
	       "Display the items hierarchy. Provide\n".
	       "some related functions, like building\n".
	       "perl code corresponding to a branch.");
    $b->attach($button{item}, -balloonmsg =>
	       "Locate an item in the items tree.  \n".
	       "When this mode is on, select in   \n".
	       "your application the item you want\n".
	       "to inspect just by clicking on it.");
    $b->attach($button{id}, -balloonmsg =>
	       "Open an entry field in which you will  \n".
	       "enter an item's id you want to inspect.");
    $b->attach($button{snapshot}, -balloonmsg =>
	       "Snapshot the application window.");
    $b->attach($button{cursorxy}, -balloonmsg =>
	       "Display the device coordinates\n".
	       "of the X cursor.              ");
    $b->attach($button{zoomminus}, -balloonmsg =>
	       "Shrink the top group.");
    $b->attach($button{zoomplus}, -balloonmsg =>
	       "Expand the top group.");
    $b->attach($button{move}, -balloonmsg =>
	       "Translate the top group. When this\n".
	       "mode is selected, move the top    \n".
	       "group using left mouse button.    ");
    $b->attach($button{balloon},-balloonmsg =>
	       "Balloon help toggle.");
    $b->attach($button{close},-balloonmsg =>
	       "Close this buttons bar.");
    return $b;

} # end balloonhelp



#---------------------------------------------------------------------------
#
# Bitmaps creation for the buttons of the control bar 
#
#---------------------------------------------------------------------------

sub createBitmaps {

    my $zinc = shift;
    my $bitmaps;
    
    $bitmaps->{close} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define close_width 29
#define close_height 29
static unsigned char close_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00,
   0x00, 0x07, 0x1c, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00, 0x1c, 0x07, 0x00,
   0x00, 0xb8, 0x03, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0xe0, 0x00, 0x00,
   0x00, 0xf0, 0x01, 0x00, 0x00, 0xb8, 0x03, 0x00, 0x00, 0x1c, 0x07, 0x00,
   0x00, 0x0e, 0x0e, 0x00, 0x00, 0x07, 0x1c, 0x00, 0x00, 0x02, 0x08, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EOF
    $bitmaps->{zn} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define focus_width 29
#define focus_height 29
static unsigned char focus_bits[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x60, 0x38, 0x00, 0x00,
  0x20, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x8e, 0x33, 0x00,
  0x00, 0x06, 0x7b, 0x00, 0x00, 0x07, 0x67, 0x00, 0x80, 0x03, 0x63, 0x00,
  0xc0, 0x01, 0x63, 0x00, 0xc0, 0x00, 0x63, 0x00, 0xe0, 0x20, 0x63, 0x00,
  0x70, 0x30, 0x63, 0x00, 0xf0, 0xbf, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
EOF
    $bitmaps->{findenclosed} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define findenclosed_width 29
#define findenclosed_height 29
static unsigned char findenclosed_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
   0xfc, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0x03, 0x3c, 0x00, 0x00, 0x03,
   0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03,
   0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03,
   0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03,
   0x18, 0x80, 0x00, 0x03, 0x18, 0x00, 0x01, 0x03, 0x18, 0x00, 0x22, 0x03,
   0x18, 0x00, 0x24, 0x03, 0x18, 0x00, 0x28, 0x03, 0x18, 0x00, 0x20, 0x03,
   0x18, 0x00, 0x3e, 0x03, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03,
   0xf8, 0xff, 0xff, 0x03, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EOF
    $bitmaps->{findoverlap} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define findoverlap_width 29
#define findoverlap_height 29
static unsigned char findoverlap_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
   0xfc, 0xb6, 0x6d, 0x03, 0xfc, 0xb6, 0x6d, 0x03, 0x3c, 0x00, 0x00, 0x00,
   0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
   0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
   0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
   0x18, 0x80, 0x00, 0x03, 0x18, 0x00, 0x01, 0x03, 0x00, 0x00, 0x22, 0x00,
   0x18, 0x00, 0x24, 0x03, 0x18, 0x00, 0x28, 0x03, 0x00, 0x00, 0x20, 0x00,
   0x18, 0x00, 0x3e, 0x03, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
   0xd8, 0xb6, 0x6d, 0x03, 0xd8, 0xb6, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EOF
    $bitmaps->{tree} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define tree_width 29
#define tree_height 29
static unsigned char tree_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0xf0, 0x07, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x10, 0x04, 0x00,
   0xc0, 0x1f, 0x04, 0x00, 0x40, 0x10, 0x04, 0x00, 0x40, 0x10, 0x04, 0x00,
   0x40, 0xf0, 0x07, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x0f,
   0x40, 0x00, 0x20, 0x08, 0x7c, 0x00, 0x20, 0x08, 0x40, 0x00, 0x3f, 0x08,
   0x40, 0x00, 0x21, 0x08, 0x40, 0x00, 0x21, 0x08, 0x40, 0x00, 0xe1, 0x0f,
   0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0xc0, 0xff, 0x01, 0x00,
   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
   0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EOF
    $bitmaps->{item} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define item_width 29
#define item_height 29
static unsigned char item_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x08, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
   0xe0, 0x03, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00,
   0xc0, 0x7f, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00,
   0x00, 0xff, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
   0x00, 0xdc, 0x01, 0x00, 0x00, 0x8c, 0x03, 0x00, 0x00, 0x08, 0x07, 0x00,
   0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00,
   0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x40, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EOF
    $bitmaps->{id} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define id_width 29
#define id_height 29
static unsigned char id_bits[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00, 0x06, 0x0c, 0x00,
  0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x87, 0x0f, 0x00,
  0x00, 0xc6, 0x0c, 0x00, 0x00, 0x66, 0x0c, 0x00, 0x00, 0x66, 0x0c, 0x00,
  0x00, 0x66, 0x0c, 0x00, 0x00, 0x66, 0x0c, 0x00, 0x00, 0x66, 0x0c, 0x00,
  0x00, 0xc6, 0x0c, 0x00, 0x00, 0x8f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
EOF
    $bitmaps->{snapshot} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define snapshot_width 29
#define snapshot_height 29
static unsigned char snapshot_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x1f, 0x00,
   0x80, 0x03, 0x11, 0x00, 0xe0, 0xff, 0xf1, 0x00, 0xf0, 0xff, 0xff, 0x01,
   0xf0, 0xff, 0xff, 0x01, 0xf0, 0xff, 0xff, 0x01, 0xf0, 0x0f, 0xfe, 0x01,
   0xf0, 0xe7, 0xfc, 0x01, 0xf0, 0x13, 0xf9, 0x01, 0xf0, 0x09, 0xf2, 0x01,
   0xf0, 0x05, 0xf4, 0x01, 0xf0, 0x05, 0xf4, 0x01, 0xf0, 0x05, 0xf4, 0x01,
   0xf0, 0x09, 0xf2, 0x01, 0xf0, 0x13, 0xf9, 0x01, 0xf0, 0xe7, 0xfc, 0x01,
   0xf0, 0x0f, 0xfe, 0x01, 0xf0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EOF
    $bitmaps->{zoomminus} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define zoomminus_width 29
#define zoomminus_height 29
static unsigned char zoomminus_bits[] = {
   0x00, 0x0e, 0x00, 0x00, 0xc0, 0x71, 0x00, 0x00, 0x30, 0x80, 0x01, 0x00,
   0x08, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00,
   0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x00,
   0xe1, 0xff, 0x10, 0x00, 0xe1, 0xff, 0x10, 0x00, 0xe1, 0xff, 0x10, 0x00,
   0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x00,
   0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x02, 0x00,
   0x30, 0x80, 0x05, 0x00, 0xc0, 0x71, 0x28, 0x00, 0x00, 0x0e, 0x70, 0x00,
   0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0xe0, 0x03,
   0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x1f,
   0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04};
EOF

    $bitmaps->{zoomplus} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define zoomplus_width 29
#define zoomplus_height 29
static unsigned char zoomplus_bits[] = {
   0x00, 0x0e, 0x00, 0x00, 0xc0, 0x71, 0x00, 0x00, 0x30, 0x80, 0x01, 0x00,
   0x08, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x0e, 0x04, 0x00,
   0x02, 0x0e, 0x08, 0x00, 0x02, 0x0e, 0x08, 0x00, 0x02, 0x0e, 0x08, 0x00,
   0xe1, 0xff, 0x10, 0x00, 0xe1, 0xff, 0x10, 0x00, 0xe1, 0xff, 0x10, 0x00,
   0x02, 0x0e, 0x08, 0x00, 0x02, 0x0e, 0x08, 0x00, 0x02, 0x0e, 0x08, 0x00,
   0x04, 0x0e, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x02, 0x00,
   0x30, 0x80, 0x05, 0x00, 0xc0, 0x71, 0x28, 0x00, 0x00, 0x0e, 0x70, 0x00,
   0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0xe0, 0x03,
   0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x1f,
   0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04};
EOF

    $bitmaps->{move} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define hand_width 29
#define hand_height 29
static unsigned char hand_bits[] = {
   0x00, 0xe0, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x80, 0x13, 0x0f, 0x00,
   0x40, 0x12, 0x11, 0x00, 0x40, 0x14, 0x11, 0x00, 0x40, 0x14, 0xd1, 0x01,
   0x80, 0x14, 0x31, 0x02, 0x80, 0x14, 0x31, 0x02, 0x80, 0x18, 0x31, 0x02,
   0x80, 0x18, 0x31, 0x02, 0x00, 0x11, 0x31, 0x02, 0x00, 0x11, 0x11, 0x01,
   0x1c, 0x11, 0x11, 0x01, 0x22, 0x01, 0x11, 0x01, 0x42, 0x01, 0x10, 0x01,
   0x84, 0x01, 0x00, 0x01, 0x88, 0x01, 0x00, 0x01, 0x08, 0x01, 0x00, 0x02,
   0x08, 0x02, 0x00, 0x02, 0x10, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x02,
   0x20, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01,
   0x80, 0x00, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x06, 0x40, 0x00,
   0x00, 0x08, 0x40, 0x00, 0x00, 0x08, 0x40, 0x00};
EOF

    $bitmaps->{balloon} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define balloon_width 29
#define balloon_height 29
static unsigned char balloon_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x00,
   0x10, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02,
   0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02,
   0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02,
   0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x02,
   0x10, 0x00, 0x00, 0x01, 0xe0, 0xe0, 0xff, 0x00, 0x00, 0x11, 0x00, 0x00,
   0x00, 0x09, 0x00, 0x00, 0x80, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00,
   0x40, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EOF

    $bitmaps->{cursorxy} = $zinc->toplevel->Bitmap(-data => <<EOF);
#define balloon_width 29
#define balloon_height 29
static unsigned char balloon_bits[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
  0x00, 0x06, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
  0x00, 0x1c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x30, 0x06, 0x8c, 0x01, 0x70, 0x07, 0x8c, 0x01, 0x60, 0x03, 0x8c, 0x01,
  0xc0, 0x01, 0xd8, 0x00, 0xc0, 0x01, 0xd8, 0x00, 0x60, 0xe3, 0xd8, 0x00,
  0x70, 0x66, 0x70, 0x00, 0x30, 0x66, 0x70, 0x00, 0x00, 0x30, 0x60, 0x00,
  0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
EOF

    return $bitmaps;
   
} # end  createBitmaps


#---------------------------------------------------------------------------
#
# Miscellaneous
#
#---------------------------------------------------------------------------

sub getsize {
    
    my $zinc = shift;
    $wwidth{$zinc} = $zinc->cget(-width);
    $wheight{$zinc} = $zinc->cget(-height);
        
} # end getsize


sub entryoption {
    
    my ($fm, $item, $zinc, $option, $def, $widthmax, $widthmin, $height) = @_;
    my $arrayflag;
    unless (defined $def) {
	my @def = $zinc->itemcget($item, $option);
	if (@def > 1) {
	    $arrayflag = 1;
	    $def = join(', ', @def);
	} else {
	    $def = $def[0];
	}
    }
    $def = "" unless defined $def;
    my $i0;
    my $e;
    if ($def =~ /\n/) {
	$height = 1 unless defined($height);
	$e = $fm->Text(-height => $height, -width => 1, -wrap => 'none');
	$i0 = '0.0';
    } else {
	$e = $fm->Entry();
	$i0 = 0;
    }
    &entryballoonhelp($e);
    my $width = length($def);
    $width = $widthmax if defined($widthmax) and $width > $widthmax;
    $width = $widthmin if defined($widthmin) and $width < $widthmin;
    $e->configure(-width => $width);
    if ($defaultoptions{$item}->{$option} and
	$def ne $defaultoptions{$item}->{$option}) {
	$e->configure(-foreground => 'blue');
    }
    
    $e->insert($i0, $def);
    $e->bind('<Control-z>', sub {
	return unless defined $defaultoptions{$item}->{$option};
	my $bg = $e->cget(-background);
	$zinc->itemconfigure($item, $option => $defaultoptions{$item}->{$option});
	$e->delete($i0, 'end');
	$e->insert($i0, $defaultoptions{$item}->{$option});
	$e->configure(-background => 'ivory');
	$e->after(80, sub {$e->configure(-background => $bg, -foreground => 'black')});
    });
    $e->bind('<Key-Return>',
	     sub {my $val = $e->get;
		  my $bg = $e->cget(-background);
		  $e->configure(-background => 'ivory');
		  if ($def ne $val) {
		      $defaultoptions{$item}->{$option} = $def
			  unless $defaultoptions{$item}->{$option};
		  }
		  my $fg = ($val ne $defaultoptions{$item}->{$option}) ?
		      'blue' : 'black';
		  $e->after(80, sub {
		      $e->configure(-background => $bg, -foreground => $fg);
		  });
		  if ($arrayflag) {
		      $zinc->itemconfigure($item, $option => [split(/,/, $val)]);
		  } else {
		      $zinc->itemconfigure($item, $option => $val);
		  }
	      });

    return $e;

} # end entryoption


sub entrytransfo {
    
    my ($fm, $item, $zinc, $attr, $def, $var, $width, $set_cb) = @_;
    my $i0;
    my $e;
    $e = $fm->Entry(-textvariable => $var);
    &entryballoonhelp($e);
    $i0 = 0;
    $width = length($def) unless $width;
    $e->configure(-width => $width);   
    $e->insert($i0, $def);
    $e->bind('<Control-z>', sub {
	my $bg = $e->cget(-background);
	$e->delete($i0, 'end');
	$e->insert($i0, $def);
	$e->configure(-background => 'ivory');
	$e->after(80, sub {$e->configure(-background => $bg, -foreground => 'black')});
	&$set_cb;
    });
    $e->bind('<Key-Return>',
	     sub {my $val = $e->get;
		  my $bg = $e->cget(-background);
		  $e->configure(-background => 'ivory');
		  my $fg = ($val ne $def) ? 'blue' : 'black';
		  $e->after(80, sub {
		      $e->configure(-background => $bg, -foreground => $fg);
		  });
		  &$set_cb;
	      });

    return $e;

} # end entrytransfo


sub instances {
    
    return @instances;
    
} # end instances


sub saveMotionBinding {

    my ($zinc) = @_;
    for my $seq ('Motion') {
	$userbindings{$zinc}->{$seq} = $zinc->Tk::bind('<'.$seq.'>')
	    unless defined $userbindings{$zinc}->{$seq};
	$userbindings{$zinc}->{$seq} = "" unless defined $userbindings{$zinc}->{$seq};
	$zinc->Tk::bind('<'.$seq.'>', "");
    }
    
} # end saveMotionBinding


sub restoreMotionBinding {

    my ($zinc) = @_;
    for my $seq ('Motion') {
	next unless defined $userbindings{$zinc}->{$seq};
	$zinc->Tk::bind('<'.$seq.'>', $userbindings{$zinc}->{$seq});
	delete $userbindings{$zinc}->{$seq};
    }
    
} # end restoreMotionBinding


sub saveDragAndDropBindings {

    my ($zinc) = @_;
    for my $seq ('ButtonPress-1', 'B1-Motion', 'ButtonRelease-1') {
	$userbindings{$zinc}->{$seq} = $zinc->Tk::bind('<'.$seq.'>')
	    unless defined $userbindings{$zinc}->{$seq};
	$userbindings{$zinc}->{$seq} = "" unless defined $userbindings{$zinc}->{$seq};
	#print "saveDragAndDropBindings seq=$seq cb=$userbindings{$zinc}->{$seq}\n";
	$zinc->Tk::bind('<'.$seq.'>', "");
    }
    
} # end saveDragAndDropBindings


sub restoreDragAndDropBindings {

    my ($zinc) = @_;
    for my $seq ('ButtonPress-1', 'B1-Motion', 'ButtonRelease-1') {
	next unless defined $userbindings{$zinc}->{$seq};
	$zinc->Tk::bind('<'.$seq.'>', $userbindings{$zinc}->{$seq});
	#print "restoreDragAndDropBindings seq=$seq cb=$userbindings{$zinc}->{$seq}\n";
	delete $userbindings{$zinc}->{$seq};
    }
    
} # end restoreDragAndDropBindings


sub newinstance {
    
    my $zinc = shift;
    return if $instances{$zinc};
    $zinc->toplevel->Tk::bind('<Key-Escape>', \&Tk::Zinc::Debug::deiconify);
    $instances{$zinc} = 1;    
    push(@instances, $zinc);
    $zinc->Tk::focus;
    $selectedzinc = $zinc;
    
} # end newinstance


sub deiconify {

    $button{zn}->destroy() if @instances == 1 and Tk::Exists($button{zn});
    $control_tl->deiconify();
    for (values %result_tl) {
	$_->deiconify if Tk::Exists($_);
    }
    for (values %coords_tl) {
	$_->deiconify if Tk::Exists($_);
    }
    for (values %alloptions_tl) {
	$_->deiconify if Tk::Exists($_);
    }
    $tree_tl->deiconify if Tk::Exists($tree_tl);
    $search_tl->deiconify if Tk::Exists($search_tl);
    $searchtree_tl->deiconify if Tk::Exists($searchtree_tl);
    $cursorxy_tl->deiconify if Tk::Exists($cursorxy_tl);
    $control_tl->raise();

} # end deiconify


sub iconify {

    for (values %result_tl) {
	$_->withdraw if Tk::Exists($_);
    }
    for (values %coords_tl) {
	$_->withdraw if Tk::Exists($_);
    }
    for (values %alloptions_tl) {
	$_->withdraw if Tk::Exists($_);
    }
    $tree_tl->withdraw if Tk::Exists($tree_tl);
    $search_tl->withdraw if Tk::Exists($search_tl);
    $searchtree_tl->withdraw if Tk::Exists($searchtree_tl);
    $cursorxy_tl->withdraw if Tk::Exists($cursorxy_tl);
    $control_tl->withdraw();

} # end iconify

# wheelmousebindings doesn't work for Tk::Pane widgets...
sub wheelmousebindings {
    my $w = shift;
    my $count = shift;
    $count = 3 unless $count > 0;

    $w->bind('<Control-ButtonPress-4>', sub {$w->yview('scroll', -1, 'page')});
    $w->bind('<Shift-ButtonPress-4>', sub {$w->yview('scroll', -1, 'unit')});
    $w->bind('<ButtonPress-4>', sub {$w->yview('scroll', -$count, 'unit')});
    
    $w->bind('<Control-ButtonPress-5>', sub {$w->yview('scroll', 1, 'page')});
    $w->bind('<Shift-ButtonPress-5>', sub {$w->yview('scroll', 1, 'unit')});
    $w->bind('<ButtonPress-5>', sub {$w->yview('scroll', $count, 'unit')});

} # end wheelmousebindings

1;

__END__

    
=head1 NAME

Tk::Zinc::Debug - a perl module for analysing a Zinc application. 


=head1 SYNOPSIS

 perl -MTk::Zinc::Debug zincscript [zincscript-opts] [Debug-initopts]
    
     or
    
 use Tk::Zinc::Debug;
 my $zinc = MainWindow->new()->Zinc()->pack;
 Tk::Zinc::Debug::init($zinc, [options]);


=head1 DESCRIPTION

Tk::Zinc::Debug provides an interface to help developers to inspect Zinc applications.

Press the B<Escape> key in the toplevel of your application to display the Tk::Zinc::Debug buttons bar.


Features :

=over
    
=item B<o> scan a rectangular area

Scan all items which are enclosed in a rectangular area you have first drawn by drag & drop, or all items which overlap it. Result is a Tk table which presents details (options, coordinates, ...) about found items; you can also highlight a particular item, even if it's not visible, by clicking on its corresponding button in the table. You can also display particular item's features by entering this id in dedicated entry field

=item B<o> display items hierarchy

You can find a particular item's position in the tree and you can highlight items and see their features as described above. You can also generate the perl code corresponding to a selected branch (but images can't be reproduced).

=item B<o> snapshot the application window

In order to illustrate a graphical bug for example.
    
=item B<o> display coordinates of the X cursor.
    
=item B<o> zoom/translate the top group
    
=back


=head2 Loading Tk::Zinc::Debug as a plugin
    
If you load Tk::Zinc::Debug using the -M perl option, B<nothing needs to be added to your code>. In this case, the B<init()> function is automatically invoked with its default attributes for each instance of Zinc widget. You can overload these by passing the same options to the command. 

=head1 FUNCTION


=over

=item B<init>($zinc, ?option => value, ...?)

This function creates required Tk bindings to permit items search. You can specify the following options :

=over

=item E<32>E<32>E<32>B<-optionsToDisplay> => opt1[,..,optN]

Used to display some option's values associated to items of the tree. Expected argument is a string of commas separated options.

=item E<32>E<32>E<32>B<-optionsFormat> => row | column

Defines the display format of option's values. Default is 'row'.
    
=item E<32>E<32>E<32>B<-snapshotBasename> => string

Defines the basename used for the file containing the snaphshot. The filename will be <current­dir>/basename<n>.png  Defaulted to 'zincsnapshot'.

=item E<32>E<32>E<32>B<-expandTagsField> => 0 | 1

Specifies if the tags field in the attributes window will be expanded to show all the items tags (it should take up a lot of space). In the default case (value is set to 0), only the head of the list is displayed.


=back


=back
    

=head1 AUTHOR

Daniel Etienne <etienne@cena.fr>

    
=head1 HISTORY

Oct 5 2004 : transformations are correctly managed in built code. Transfo parameters can be displayed and set. new mode to display coordinateds of X cursor.

Oct 14 2003 : add a control bar, and zoom/translate new functionalities. finditems(), tree(), snapshot() functions become deprecated, initialisation is done using the new init() function.

Oct 07 2003 : contours of curves can be displayed and explored.

Sep 15 2003 : due to CPAN-isation, the ZincDebug module has been renamed Tk::Zinc::Debug

May 20 2003 : perl code can be generated from the items tree, with some limitations concerning transformations and images.

Mar 11 2003 : ZincDebug can manage several instances of Zinc widget. Options of ZincDebug functions can be set on the command line. 

Jan 20 2003 : item's attributes can be edited.

Jan 14 2003 : ZincDebug can be loaded at runtime using the -M perl option without any change in the application's code.

Nov 6 2002 : some additional informations (like tags or other attributes values) can be displayed in the items tree. Add feedback when selected item is not visible because outside window.

Sep 2 2002 : add the tree() function

May 27 2002 : add the snapshot() function contributed by Ch. Mertz.
    
Jan 28 2002 : Zincdebug provides the finditems() function and can manage only one instance of Zinc widget. 

Added jni/tkzinc/Perl/Zinc/Graphics.pm.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
#-----------------------------------------------------------------------------------
#
#      Graphics.pm
#      some graphic design functions
#
#-----------------------------------------------------------------------------------
#  Functions to create complexe graphic component :
#  ------------------------------------------------
#      buildZincItem          (realize a zinc item from description hash table
#                              management of enhanced graphics functions)
#
#      repeatZincItem         (duplication of given zinc item)
#
#  Function to compute complexe geometrical forms :
#  (text header of functions explain options for each form,
#  function return curve coords using control points of cubic curve)
#  -----------------------------------------------------------------
#      roundedRectangleCoords (return curve coords of rounded rectangle)
#      hippodromeCoords       (return curve coords of circus form)
#      ellipseCoords          (return curve coords of ellipse form)
#      polygonCoords          (return curve coords of regular polygon)
#      roundedCurveCoords     (return curve coords of rounded curve)
#      polylineCoords         (return curve coords of polyline)
#      shiftPathCoords        (return curve coords of shifting path)
#      tabBoxCoords           (return curve coords of tabBox's pages)
#      pathLineCoords         (return triangles coords of pathline)
#
#  Function to compute 2D 1/2 relief and shadow :
#  function build zinc items (triangles and curve) to simulate this
#  -----------------------------------------------------------------
#      graphicItemRelief      (return triangle items simulate relief of given item)
#      polylineReliefParams   (return triangle coords and lighting triangles color list)
#      graphicItemShadow      (return triangles and curve items simulate shadow of given item))
#      polylineShadowParams   (return triangle and curve coords and shadow triangles color list))
#
#  Geometrical basic Functions :
#  -----------------------------
#      perpendicularPoint
#      lineAngle
#      lineNormal
#      vertexAngle
#      arc_pts
#      rad_point
#      bezierCompute
#      bezierSegment
#      bezierPoint
#
#  Pictorial Functions  :
#  ----------------------
#      setGradients
#      getPattern
#      getTexture
#      getImage
#      init_pixmaps
#      zincItemPredominantColor
#      ZnColorToRGB
#      hexaRGBcolor
#      createGraduate
#      pathGraduate
#      MedianColor
#      LightingColor
#      RGBtoLCH
#      LCHtoRGB
#      RGBtoHLS
#      HLStoRGB
#
#-----------------------------------------------------------------------------------
#      Authors: Jean-Luc Vinot <vinot@cena.fr>
#
# $Id$ 
#-----------------------------------------------------------------------------------
package Tk::Zinc::Graphics;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(&buildZincItem &repeatZincItem &buidTabBoxItem

	     &roundedRectangleCoords &hippodromeCoords &polygonCoords &ellipseCoords
	     &roundedCurveCoords &polylineCoords &tabBoxCoords &pathLineCoords &shiftPathCoords

	     &perpendicularPoint &lineAngle &vertexAngle &rad_point &arc_pts &lineNormal
	     &curve2polylineCoords &curveItem2polylineCoords &bezierSegment &bezierCompute

	     &graphicItemRelief &graphicItemShadow

	     &setGradients &getPattern &getTexture &getImage &init_pixmaps

	     &hexaRGBcolor &createGraduate &lightingColor &zincItemPredominantColor
	     &MedianColor &RGBtoLCH &LCHtoRGB &RGBtoHLS &HLStoRGB
	     );

use strict;
use Carp;
use Tk;
use Tk::PNG;
use Tk::JPEG;
use Math::Trig;

# constante facteur point directeur (conique -> quadratique)
my $const_ptd_factor = .5523;

# constante white point (conversion couleur espace CIE XYZ)
my ($Xw, $Yw, $Zw) = (95.047, 100.0, 108.883);

# limite globale d'approximation courbe bezier
my $bezierClosenessThreshold = .2;

# initialisation et partage de ressources couleurs et images
my @Gradients;
my %textures;
my %images;
my %bitmaps;



#-----------------------------------------------------------------------------------
# Graphics::buildZincItem
# Création d'un objet Zinc de représentation
#-----------------------------------------------------------------------------------
# types d'items valides :
# les items natifs zinc : group, rectangle, arc, curve, text, icon
# les items ci-après permettent de spécifier des curves 'particulières' :
# -roundedrectangle : rectangle à coin arrondi
#       -hippodrome : hippodrome
#          -ellipse : ellipse un centre 2 rayons
#         -polygone : polygone régulier à n cotés (convexe ou en étoile)
#     -roundedcurve : curve multicontours à coins arrondis (rayon unique)
#         -polyline : curve multicontours à coins arrondis (le rayon pouvant être défini 
#                     spécifiquement pour chaque sommet)
#         -pathline : création d'une ligne 'épaisse' avec l'item Zinc triangles
#                     décalage par rapport à un chemin donné (largeur et sens de décalage)
#                     dégradé de couleurs de la ligne (linéaire, transversal ou double)
#-----------------------------------------------------------------------------------
# paramètres :
# widget : <widget> identifiant du widget Zinc
# parentgroup : <tagOrId> identifiant du group parent
#
# options :
#   -itemtype : type de l'item à construire (type zinc ou metatype)
#     -coords : <coords|coordsList> coordonnées de l'item
# -metacoords : <hastable> calcul de coordonnées par type d'item différent de -itemtype
#   -contours : <contourList> paramètres multi-contours
#     -params : <hastable> arguments spécifiques de l'item à passer au widget
#    -addtags : [list of specific tags] to add to params -tags
#    -texture : <imagefile> ajout d'une texture à l'item
#    -pattern : <imagefile> ajout d'un pattern à l'item
#     -relief : <hastable> création d'un relief à l'item invoque la fonction &graphicItemRelief()
#     -shadow : <hastable> création d'une ombre portée à l'item invoque la fonction &graphicItemShadow()
#      -scale : <scale_factor|[xscale_factor,yscale_factor]> application d'une transformation zinc->scale à l'item
#  -translate : <[dx,dy]> application d'un transformation zinc->translate à l'item.
#     -rotate : <angle> application d'une transformation zinc->rotate (en degré) à l'item
#       -name : <str> nom de l'item
# spécifiques item group :
#       -clip : <coordList|hashtable> paramètres de clipping d'un item group (coords ou item)
#      -items : <hashtable> appel récursif de la fonction permettant d'inclure des items au groupe
#-----------------------------------------------------------------------------------
#
#-----------------------------------------------------------------------------------
sub buildZincItem {
  my ($widget, $parentgroup, %options) = @_;
  $parentgroup = 1 if !$parentgroup;

  my $itemtype = $options{'-itemtype'};
  my $coords = $options{'-coords'};
  my $params = $options{'-params'};

  return unless ($widget and $itemtype and ($coords or $options{'-metacoords'}));

  my $name = ($options{'-name'}) ? $options{'-name'} : 'none';

  my $item;
  my $metatype;
  my (@items, @reliefs, @shadows);
  my @tags;


  #--------------------
  # GEOMETRIE DES ITEMS

  # gestion des types d'items particuliers et à raccords circulaires
  if ($itemtype eq 'roundedrectangle'
      or $itemtype eq 'hippodrome'
      or $itemtype eq 'polygone'
      or $itemtype eq 'ellipse'
      or $itemtype eq 'roundedcurve'
      or $itemtype eq 'polyline'
      or $itemtype eq 'curveline') {

    # par défaut la curve sera fermée -closed = 1
    $params->{'-closed'} = 1 if (!defined $params->{'-closed'});
    $metatype = $itemtype;
    $itemtype = 'curve';

    # possibilité de définir les coordonnées initiales par metatype
    if ($options{'-metacoords'}) {
      $options{'-coords'} = &metaCoords(%{$options{'-metacoords'}});

    }

  # création d'une pathline à partir d'item zinc triangles
  } elsif ($itemtype eq 'pathline') {

    $itemtype = 'triangles';
    if ($options{'-metacoords'}) {
      $coords = &metaCoords(%{$options{'-metacoords'}});

    }

    if ($options{'-graduate'}) {
      my $numcolors = scalar(@{$coords});
      $params->{'-colors'} = &pathGraduate($widget, $numcolors, $options{'-graduate'});
    }

    $coords = &pathLineCoords($coords, %options);


  # création d'une boite à onglet
  } elsif ($itemtype eq 'tabbox') {
    return &buildTabBoxItem($widget, $parentgroup, %options);

  }

  # calcul des coordonnées finales de la curve
  $coords = &metaCoords(-type => $metatype, %options) if ($metatype);


  # gestion du multi-contours (accessible pour tous les types d'items géometriques)
  if ($options{'-contours'} and $metatype) {
    my @contours = @{$options{'-contours'}};
    my $numcontours = scalar(@contours);
    for (my $i = 0; $i < $numcontours; $i++) {
      # radius et corners peuvent être défini spécifiquement pour chaque contour
      my ($type, $way, $addcoords, $radius, $corners, $corners_radius) = @{$contours[$i]};
      $radius = $options{'-radius'} if (!defined $radius);

      my $newcoords = &metaCoords(-type => $metatype,
				  -coords => $addcoords,
				  -radius => $radius,
				  -corners => $corners,
				  -corners_radius => $corners_radius
				 );

      $options{'-contours'}->[$i] = [$type, $way, $newcoords];
    }
  }


  #----------------------
  # REALISATION DES ITEMS

  # ITEM GROUP
  # gestion des coordonnées et du clipping
  if ($itemtype eq 'group') {
    $item = $widget->add($itemtype,
			 $parentgroup,
			 %{$params});

    $widget->coords($item, $coords) if $coords;

    # clipping du groupe par item ou par géometrie
    if ($options{'-clip'}) {
      my $clipbuilder = $options{'-clip'};
      my $clip;

      # création d'un item de clipping
      if ($clipbuilder->{'-itemtype'}) {
	$clip = &buildZincItem($widget, $item, %{$clipbuilder});

      } elsif (ref($clipbuilder) eq 'ARRAY' or $widget->type($clipbuilder)) {
	$clip = $clipbuilder;
      }

      $widget->itemconfigure($item, -clip => $clip) if ($clip);
    }

    # créations si besoin des items contenus dans le groupe
    if ($options{'-items'} and ref($options{'-items'}) eq 'HASH') {
      while (my ($itemname, $itemstyle) = each(%{$options{'-items'}})) {
	$itemstyle->{'-name'} = $itemname if (!$itemstyle->{'-name'});
	&buildZincItem($widget, $item, %{$itemstyle});
      }
    }


  # ITEM TEXT ou ICON
  } elsif ($itemtype eq 'text' or $itemtype eq 'icon') {
    my $imagefile;
    if ($itemtype eq 'icon') {
      $imagefile = $params->{'-image'};
      my $image = &getImage($widget, $imagefile);
      $params->{'-image'} = ($image) ? $image : "";
    }

    $item = $widget->add($itemtype,
		       $parentgroup,
		       -position => $coords,
		       %{$params},
		      );

    $params->{'-image'} = $imagefile if $imagefile;


  # ITEMS GEOMETRIQUES -> CURVE
  } else {

    $item = $widget->add($itemtype,
			 $parentgroup,
			 $coords,
			 %{$params},
			);

    if ($itemtype eq 'curve' and $options{'-contours'}) {
      foreach my $contour (@{$options{'-contours'}}) {
	$widget->contour($item, @{$contour});
      }
    }
	
    # gestion du mode norender
    if ($options{'-texture'}) {
      my $texture = &getTexture($widget, $options{'-texture'});
      $widget->itemconfigure($item, -tile => $texture) if $texture;
    }

    if ($options{'-pattern'}) {
      my $bitmap = &getBitmap($options{'-pattern'});
      $widget->itemconfigure($item, -fillpattern => $bitmap) if $bitmap;
    }

  }


  # gestion des tags spécifiques
  if ($options{'-addtags'}) {
    my @tags = @{$options{'-addtags'}};

    my $params_tags = $params->{'-tags'};
    push (@tags, @{$params_tags}) if $params_tags;

    $widget->itemconfigure($item, -tags => \@tags);

  }


  #-------------------------------
  # TRANSFORMATIONS ZINC DE L'ITEM

  # transformation scale de l'item si nécessaire
  if ($options{'-scale'}) {
    my $scale = $options{'-scale'};
    $scale = [$scale, $scale] if (ref($scale) ne 'ARRAY');
    $widget->scale($item, @{$scale}) ;
  }

  # transformation rotate de l'item si nécessaire
  $widget->rotate($item, deg2rad($options{'-rotate'})) if ($options{'-rotate'});

  # transformation translate de l'item si nécessaire
  $widget->translate($item, @{$options{'-translate'}}) if ($options{'-translate'});


  # répétition de l'item
  if ($options{'-repeat'}) {
    push (@items, $item,
	  &repeatZincItem($widget, $item, %{$options{'-repeat'}}));
  }


  #-----------------------
  # RELIEF ET OMBRE PORTEE

  # gestion du relief
  if ($options{'-relief'}) {
    my $target = (@items) ? \@items : $item;
    push (@reliefs, &graphicItemRelief($widget, $target, %{$options{'-relief'}}));
  }

  # gestion de l'ombre portée
  if ($options{'-shadow'}) {
    my $target = (@items) ? \@items : $item;
    push (@shadows, &graphicItemShadow($widget, $target, %{$options{'-shadow'}}));
  }

  push(@items, @reliefs) if @reliefs;
  push(@items, @shadows) if @shadows;

  return (@items) ? @items : $item;

}


#-----------------------------------------------------------------------------------
# Graphics::repeatZincItem
# Duplication (clonage) d'un objet Zinc de représentation
#-----------------------------------------------------------------------------------
# paramètres :
# widget : <widget> identifiant du widget zinc
#   item : <tagOrId> identifiant de l'item source
# options :
#     -num : <n> nombre d'item total (par defaut 2)
#     -dxy : <[dx, dy]> translation entre 2 duplications (par defaut [0,0])
#   -angle : <angle> rotation entre 2 duplications
# -copytag : <sting> ajout d'un tag indexé pour chaque copie
#  -params : <hashtable> {clef => [value list]}> valeur de paramètre de chaque copie
#-----------------------------------------------------------------------------------
sub repeatZincItem {
  my ($widget, $item, %options) = @_;
  my @clones;

  # duplication d'une liste d'items -> appel récursif
  if (ref($item) eq 'ARRAY') {
    foreach my $part (@{$item}) {
      push (@clones, &repeatZincItem($widget, $part, %options));
    }

    return wantarray ? @clones : \@clones;
  }

  my $num = ($options{'-num'}) ? $options{'-num'} : 2;
  my ($dx, $dy) = (defined $options{'-dxy'}) ? @{$options{'-dxy'}} : (0, 0);
  my $angle = $options{'-angle'};
  my $params = $options{'-params'};
  my $copytag = $options{'-copytag'};
  my @tags;

  if ($copytag) {
    @tags = $widget->itemcget($item, -tags);
    unshift (@tags, $copytag."0");
    $widget->itemconfigure($item, -tags => \@tags);
  }

  for (my $i = 1; $i < $num; $i++) {
    my $clone;

    if ($copytag) {
      $tags[0] = $copytag.$i;
      $clone = $widget->clone($item, -tags => \@tags);

    } else {
      $clone = $widget->clone($item);
    }

    push(@clones, $clone);
    $widget->translate($clone, $dx*$i, $dy*$i);
    $widget->rotate($clone, deg2rad($angle*$i)) if $angle;

    if ($params) {
      while (my ($attrib, $value) = each(%{$params})) {
	$widget->itemconfigure($clone, $attrib => $value->[$i]);
      }
    }
  }

  return wantarray ? @clones : \@clones;

}


#-----------------------------------------------------------------------------------
# FONCTIONS GEOMETRIQUES
#-----------------------------------------------------------------------------------

#-----------------------------------------------------------------------------------
# Graphics::metaCoords
# retourne une liste de coordonnées en utilisant la fonction du type d'item spécifié
#-----------------------------------------------------------------------------------
# paramètres : (passés par %options)
#   -type : <string> type de primitive utilisée
# -coords : <coordsList> coordonnées nécessitée par la fonction [type]Coords
#
# les autres options spécialisées au type seront passés à la fonction [type]coords
#-----------------------------------------------------------------------------------
sub metaCoords {
  my (%options) = @_;
  my $pts;

  my $type = delete $options{'-type'};
  my $coords = delete $options{'-coords'};

  if ($type eq 'roundedrectangle') {
    $pts = &roundedRectangleCoords($coords, %options);

  } elsif ($type eq 'hippodrome') {
    $pts = &hippodromeCoords($coords, %options);

  } elsif ($type eq 'ellipse') {
    $pts = &ellipseCoords($coords, %options);

  } elsif ($type eq 'roundedcurve') {
    $pts = &roundedCurveCoords($coords, %options);

  } elsif ($type eq 'polygone') {
    $pts = &polygonCoords($coords, %options);

  } elsif ($type eq 'polyline') {
    $pts = &polylineCoords($coords, %options);

  } elsif ($type eq 'curveline') {
    $pts = &curveLineCoords($coords, %options);
  }

  return $pts;
}


#-----------------------------------------------------------------------------------
# Graphics::ZincItem2CurveCoords
# retourne une liste des coordonnées 'Curve' d'un l'item Zinc
# rectangle, arc ou curve
#-----------------------------------------------------------------------------------
# paramètres :
# widget : <widget> identifiant du widget zinc
#   item : <tagOrId> identifiant de l'item source
# options :
#     -linear : <boolean> réduction à des segments non curviligne (par défaut 0)
# -realcoords : <boolean> coordonnées à transformer dans le groupe père (par défaut 0)
#     -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
#-----------------------------------------------------------------------------------
sub ZincItem2CurveCoords {
  my ($widget, $item, %options) = @_;

  my $itemtype = $widget->type($item);
  return unless ($itemtype);

  my $linear = $options{-linear};
  my $realcoords = $options{-realcoords};
  my $adjust = (defined $options{-adjust}) ? $options{-adjust} : 1;

  my @itemcoords = $widget->coords($item);

  my $coords;
  my @multi;

  if ($itemtype eq 'rectangle') {
    $coords = &roundedRectangleCoords(\@itemcoords, -radius => 0);

  } elsif ($itemtype eq 'arc') {
    $coords = &ellipseCoords(\@itemcoords);
    $coords = &curve2polylineCoords($coords, $adjust) if $linear;

  } elsif ($itemtype eq 'curve') {
      my $numcontours = $widget->contour($item);

      if ($numcontours < 2) {
      $coords = \@itemcoords;
      $coords = &curve2polylineCoords($coords, $adjust) if $linear;


    } else {
      if ($linear) {
	@multi = &curveItem2polylineCoords($widget, $item);

      } else {
	for (my $contour = 0; $contour < $numcontours; $contour++) {
	  my @points = $widget->coords($item, $contour);
	  push (@multi, \@points);
	}
      }

      $coords = \@multi;
    }
  }

  if ($realcoords) {
    my $parentgroup = $widget->group($item);
    if (@multi) {
      my @newcoords;
      foreach my $points (@multi) {
	my @transcoords = $widget->transform($item, $parentgroup, $points);
	push(@newcoords, \@transcoords);
      }

      $coords = \@newcoords;

    } else {
      my @transcoords = $widget->transform($item, $parentgroup, $coords);
      $coords = \@transcoords;
    }

  }

  if (@multi) {
    return (wantarray) ? @{$coords} : $coords;
  } else {
    return (wantarray) ? ($coords) : $coords;
  }
}

#-----------------------------------------------------------------------------------
# Graphics::roundedRectangleCoords
# calcul des coords du rectangle à coins arrondis
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> coordonnées bbox (haut-gauche et bas-droite) du rectangle
# options :
#  -radius : <dimension> rayon de raccord d'angle
# -corners : <booleanList> liste des raccords de sommets [0 (aucun raccord)|1] par défaut [1,1,1,1]
#-----------------------------------------------------------------------------------
sub roundedRectangleCoords {
  my ($coords, %options) = @_;
  my ($x0, $y0, $xn, $yn) = ($coords->[0]->[0], $coords->[0]->[1],
			     $coords->[1]->[0], $coords->[1]->[1]);

  my $radius = $options{'-radius'};
  my $corners = $options{'-corners'} ? $options{'-corners'} : [1, 1, 1, 1];

  # attention aux formes 'négatives'
  if ($xn < $x0) {
    my $xs = $x0;
    ($x0, $xn) = ($xn, $xs);
  }
   if ($yn < $y0) {
    my $ys = $y0;
    ($y0, $yn) = ($yn, $ys);
  }

  my $height = &_min($xn -$x0, $yn - $y0);

  if (!defined $radius) {
    $radius = int($height/10);
    $radius = 3 if $radius < 3;
  }

  if (!$radius or $radius < 2) {
    return [[$x0, $y0],[$x0, $yn],[$xn, $yn],[$xn, $y0]];

  }


  # correction de radius si necessaire
  my $max_rad = $height;
  $max_rad /= 2 if (!defined $corners);
  $radius = $max_rad if $radius > $max_rad;

  # points remarquables
  my $ptd_delta = $radius * $const_ptd_factor;
  my ($x2, $x3) = ($x0 + $radius, $xn - $radius);
  my ($x1, $x4) = ($x2 - $ptd_delta, $x3 + $ptd_delta);
  my ($y2, $y3) = ($y0 + $radius, $yn - $radius);
  my ($y1, $y4) = ($y2 - $ptd_delta, $y3 + $ptd_delta);

  # liste des 4 points sommet du rectangle : angles sans raccord circulaire
  my @angle_pts = ([$x0, $y0],[$x0, $yn],[$xn, $yn],[$xn, $y0]);

  # liste des 4 segments quadratique : raccord d'angle = radius
  my @roundeds = ([[$x2, $y0],[$x1, $y0, 'c'],[$x0, $y1, 'c'],[$x0, $y2],],
		  [[$x0, $y3],[$x0, $y4, 'c'],[$x1, $yn, 'c'],[$x2, $yn],],
		  [[$x3, $yn],[$x4, $yn, 'c'],[$xn, $y4, 'c'],[$xn, $y3],],
		  [[$xn, $y2],[$xn, $y1, 'c'],[$x4, $y0, 'c'],[$x3, $y0],]);

  my @pts = ();
  my $previous;
  for (my $i = 0; $i < 4; $i++) {
    if ($corners->[$i]) {
      if ($previous) {
	# on teste si non duplication de point
	my ($nx, $ny) = @{$roundeds[$i]->[0]};
	if ($previous->[0] == $nx and $previous->[1] == $ny) {
	  pop(@pts);
	}
      }
      push(@pts, @{$roundeds[$i]});
      $previous = $roundeds[$i]->[3];

    } else {
      push(@pts, $angle_pts[$i]);
    }
  }

  return \@pts;
}

#-----------------------------------------------------------------------------------
# Graphics::ellipseCoords
# calcul des coords d'une ellipse
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> coordonnées bbox du rectangle exinscrit
# options :
# -corners : <booleanList> liste des raccords de sommets [0 (aucun raccord)|1] par défaut [1,1,1,1]
#-----------------------------------------------------------------------------------
sub ellipseCoords {
  my ($coords, %options) = @_;
  my ($x0, $y0, $xn, $yn) = ($coords->[0]->[0], $coords->[0]->[1],
			     $coords->[1]->[0], $coords->[1]->[1]);

  my $corners = $options{'-corners'} ? $options{'-corners'} : [1, 1, 1, 1];

  # attention aux formes 'négatives'
  if ($xn < $x0) {
    my $xs = $x0;
    ($x0, $xn) = ($xn, $xs);
  }
   if ($yn < $y0) {
    my $ys = $y0;
    ($y0, $yn) = ($yn, $ys);
  }

  # points remarquables
  my $dx = ($xn - $x0)/2 * $const_ptd_factor;
  my $dy = ($yn - $y0)/2 * $const_ptd_factor;
  my ($x2, $y2) = (($x0+$xn)/2, ($y0+$yn)/2);
  my ($x1, $x3) = ($x2 - $dx, $x2 + $dx);
  my ($y1, $y3) = ($y2 - $dy, $y2 + $dy);

  # liste des 4 points sommet de l'ellipse : angles sans raccord circulaire
  my @angle_pts = ([$x0, $y0],[$x0, $yn],[$xn, $yn],[$xn, $y0]);

  # liste des 4 segments quadratique : raccord d'angle = arc d'ellipse
  my @roundeds = ([[$x2, $y0],[$x1, $y0, 'c'],[$x0, $y1, 'c'],[$x0, $y2],],
		  [[$x0, $y2],[$x0, $y3, 'c'],[$x1, $yn, 'c'],[$x2, $yn],],
		  [[$x2, $yn],[$x3, $yn, 'c'],[$xn, $y3, 'c'],[$xn, $y2],],
		  [[$xn, $y2],[$xn, $y1, 'c'],[$x3, $y0, 'c'],[$x2, $y0],]);

  my @pts = ();
  my $previous;
  for (my $i = 0; $i < 4; $i++) {
    if ($corners->[$i]) {
      if ($previous) {
	# on teste si non duplication de point
	my ($nx, $ny) = @{$roundeds[$i]->[0]};
	if ($previous->[0] == $nx and $previous->[1] == $ny) {
	  pop(@pts);
	}
      }
      push(@pts, @{$roundeds[$i]});
      $previous = $roundeds[$i]->[3];

    } else {
      push(@pts, $angle_pts[$i]);
    }
  }

  return \@pts;

}


#-----------------------------------------------------------------------------------
# Graphics::hippodromeCoords
# calcul des coords d'un hippodrome
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> coordonnées bbox du rectangle exinscrit
# options :
# -orientation : orientation forcée de l'hippodrome [horizontal|vertical]
#     -corners : liste des raccords de sommets [0|1] par défaut [1,1,1,1]
#       -trunc : troncatures [left|right|top|bottom|both]
#-----------------------------------------------------------------------------------
sub hippodromeCoords {
  my ($coords, %options) = @_;
  my ($x0, $y0, $xn, $yn) = ($coords->[0]->[0], $coords->[0]->[1],
			     $coords->[1]->[0], $coords->[1]->[1]);

  my $orientation = ($options{'-orientation'}) ? $options{'-orientation'} : 'none';

  # orientation forcée de l'hippodrome (sinon hippodrome sur le plus petit coté)
  my $height = ($orientation eq 'horizontal') ? abs($yn - $y0)
    : ($orientation eq 'vertical') ? abs($xn - $x0) : &_min(abs($xn - $x0), abs($yn - $y0));
  my $radius = $height/2;
  my $corners = [1, 1, 1, 1];

  if  ($options{'-corners'}) {
    $corners = $options{'-corners'};

  } elsif ($options{'-trunc'}) {
    my $trunc = $options{'-trunc'};
    if ($trunc eq 'both') {
      return [[$x0, $y0],[$x0, $yn],[$xn, $yn],[$xn, $y0]];

    } else {
      $corners = ($trunc eq 'left') ? [0, 0, 1, 1] :
	($trunc eq 'right') ? [1, 1, 0, 0] :
	  ($trunc eq 'top') ? [0, 1, 1, 0] : 
	    ($trunc eq 'bottom') ? [1, 0, 0, 1] : [1, 1, 1, 1];

    }
  }

  # l'hippodrome est un cas particulier de roundedRectangle
  # on retourne en passant la 'configuration' à la fonction générique roundedRectangleCoords
  return &roundedRectangleCoords($coords, -radius => $radius, -corners => $corners);
}


#-----------------------------------------------------------------------------------
# Graphics::polygonCoords
# calcul des coords d'un polygone régulier
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coords> point centre du polygone
# options :
#      -numsides : <integer> nombre de cotés
#        -radius : <dimension> rayon de définition du polygone (distance centre-sommets)
#  -inner_radius : <dimension> rayon interne (polygone type étoile)
#       -corners : <booleanList> liste des raccords de sommets [0|1] par défaut [1,1,1,1]
# -corner_radius : <dimension> rayon de raccord des cotés
#    -startangle : <angle> angle de départ en degré du polygone
#-----------------------------------------------------------------------------------
sub polygonCoords {
  my ($coords, %options) = @_;

  my $numsides = $options{'-numsides'};
  my $radius = $options{'-radius'};
  if ($numsides < 3 or !$radius) {
    print "Vous devez au moins spécifier un nombre de cotés >= 3 et un rayon...\n";
    return undef;
  }

  $coords = [0, 0] if (!defined $coords);
  my $startangle = ($options{'-startangle'}) ? $options{'-startangle'} : 0;
  my $anglestep = 360/$numsides;
  my $inner_radius = $options{'-inner_radius'};
  my @pts;

  # points du polygone
  for (my $i = 0; $i < $numsides; $i++) {
    my ($xp, $yp) = &rad_point($coords, $radius, $startangle + ($anglestep*$i));
    push(@pts, ([$xp, $yp]));

    # polygones 'étoiles'
    if ($inner_radius) {
      ($xp, $yp) = &rad_point($coords, $inner_radius, $startangle + ($anglestep*($i+ 0.5)));
      push(@pts, ([$xp, $yp]));
    }
  }


  @pts = reverse @pts;

  if ($options{'-corner_radius'}) {
    return &roundedCurveCoords(\@pts, -radius => $options{'-corner_radius'}, -corners => $options{'-corners'});
  } else {
    return \@pts;
  }
}



#-----------------------------------------------------------------------------------
# Graphics::roundedAngle
# THIS FUNCTION IS NO MORE USED, NEITHER EXPORTED
# curve d'angle avec raccord circulaire
#-----------------------------------------------------------------------------------
# paramètres :
# widget : identifiant du widget Zinc
# parentgroup : <tagOrId> identifiant de l'item group parent
# coords : <coordsList> les 3 points de l'angle
# radius : <dimension> rayon de raccord
#-----------------------------------------------------------------------------------
sub roundedAngle {
  my ($widget, $parentgroup, $coords, $radius) = @_;
  my ($pt0, $pt1, $pt2) = @{$coords};

  my ($corner_pts, $center_pts) = &roundedAngleCoords($coords, $radius);
  my ($cx0, $cy0) = @{$center_pts};

  # valeur d'angle et angle formé par la bisectrice
  my ($angle)  = &vertexAngle($pt0, $pt1, $pt2);

  $parentgroup = 1 if (!defined $parentgroup);

  $widget->add('curve', $parentgroup,
	     [$pt0,@{$corner_pts},$pt2],
	     -closed => 0, 
	     -linewidth => 1,
	     -priority => 20,
	    );

}

#-----------------------------------------------------------------------------------
# Graphics::roundedAngleCoords
# calcul des coords d'un raccord d'angle circulaire
#-----------------------------------------------------------------------------------
# le raccord circulaire de 2 droites sécantes est traditionnellement réalisé par un
# arc (conique) du cercle inscrit de rayon radius tangent à ces 2 droites
#
# Quadratique :
# une approche de cette courbe peut être réalisée simplement par le calcul de 4 points
# spécifiques qui définiront - quelle que soit la valeur de l'angle formé par les 2
# droites - le segment de raccord :
# - les 2 points de tangence au cercle inscrit seront les points de début et de fin
# du segment de raccord
# - les 2 points de controle seront situés chacun sur le vecteur reliant le point de
# tangence au sommet de l'angle (point secant des 2 droites)
# leur position sur ce vecteur peut être simplifiée comme suit :
# - à un facteur de 0.5523 de la distance au sommet pour un angle >= 90° et <= 270°
# - à une 'réduction' de ce point vers le point de tangence pour les angles limites
# de 90° vers 0° et de 270° vers 360°
# ce facteur sera légérement modulé pour recouvrir plus précisement l'arc correspondant
#-----------------------------------------------------------------------------------
# coords : <coordsList> les 3 points de l'angle
# radius : <dimension> rayon de raccord
#-----------------------------------------------------------------------------------
sub roundedAngleCoords {
  my ($coords, $radius) = @_;
  my ($pt0, $pt1, $pt2) = @{$coords};

  # valeur d'angle et angle formé par la bisectrice
  my ($angle, $bisecangle)  = &vertexAngle($pt0, $pt1, $pt2);

  # distance au centre du cercle inscrit : rayon/sinus demi-angle
  my $sin = sin(deg2rad($angle/2));
  my $delta = ($sin) ? abs($radius / $sin) : $radius;

  # point centre du cercle inscrit de rayon $radius
  my $refangle = ($angle < 180) ? $bisecangle+90 : $bisecangle-90;
  my ($cx0, $cy0) = rad_point($pt1, $delta, $refangle);

  # points de tangeance : pts perpendiculaires du centre aux 2 droites
  my ($px1, $py1) = &perpendicularPoint([$cx0, $cy0], [$pt0, $pt1]);
  my ($px2, $py2) = &perpendicularPoint([$cx0, $cy0], [$pt1, $pt2]);

  # point de controle de la quadratique
  # facteur de positionnement sur le vecteur pt.tangence, sommet
  my $ptd_factor =  $const_ptd_factor;
  if ($angle < 90 or $angle > 270) {
    my $diffangle = ($angle < 90) ? $angle : 360 - $angle;
    $ptd_factor -= (((90 - $diffangle)/90) * ($ptd_factor/4)) if $diffangle > 15 ;
    $ptd_factor = ($diffangle/90) * ($ptd_factor + ((1 - $ptd_factor) * (90 - $diffangle)/90));
  } else {
    my $diffangle = abs(180 - $angle);
    $ptd_factor += (((90 - $diffangle)/90) * ($ptd_factor/3)) if $diffangle > 15;
  }

  # delta xy aux pts de tangence
  my ($d1x, $d1y) = (($pt1->[0] - $px1) * $ptd_factor, ($pt1->[1] - $py1) *  $ptd_factor);
  my ($d2x, $d2y) = (($pt1->[0] - $px2) * $ptd_factor, ($pt1->[1] - $py2) *  $ptd_factor);

  # les 4 points de l'arc 'quadratique'
  my $corner_pts = [[$px1, $py1],[$px1+$d1x, $py1+$d1y, 'c'],
		    [$px2+$d2x, $py2+$d2y, 'c'],[$px2, $py2]];


  # retourne le segment de quadratique et le centre du cercle inscrit
  return ($corner_pts, [$cx0, $cy0]);

}


#-----------------------------------------------------------------------------------
# Graphics::roundedCurveCoords
# retourne les coordonnées d'une curve à coins arrondis
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> liste de coordonnées des points de la curve
# options :
#  -radius : <dimension> rayon de raccord d'angle
# -corners : <booleanList> liste des raccords de sommets [0|1] par défaut [1,1,1,1]
#-----------------------------------------------------------------------------------
sub roundedCurveCoords {
  my ($coords, %options) = @_;
  my $numfaces = scalar(@{$coords});
  my @curve_pts;

  my $radius = (defined $options{'-radius'}) ? $options{'-radius'} : 0;
  my $corners = $options{'-corners'};

  for (my $index = 0; $index < $numfaces; $index++) {
    if ($corners and !$corners->[$index]) {
      push(@curve_pts, $coords->[$index]);

    } else {
      my $prev = ($index) ? $index - 1 : $numfaces - 1;
      my $next = ($index > $numfaces - 2) ? 0 : $index + 1;
      my $anglecoords = [$coords->[$prev], $coords->[$index], $coords->[$next]];

      my ($quad_pts) = &roundedAngleCoords($anglecoords, $radius);
      push(@curve_pts, @{$quad_pts});
    }
  }

  return \@curve_pts;

}


#-----------------------------------------------------------------------------------
# Graphics::polylineCoords
# retourne les coordonnées d'une polyline
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> liste de coordonnées des sommets de la polyline
# options :
#  -radius : <dimension> rayon global de raccord d'angle
# -corners : <booleanList> liste des raccords de sommets [0|1] par défaut [1,1,1,1],
# -corners_radius : <dimensionList> liste des rayons de raccords de sommets
#-----------------------------------------------------------------------------------
sub polylineCoords {
  my ($coords, %options) = @_;
  my $numfaces = scalar(@{$coords});
  my @curve_pts;

  my $radius = ($options{'-radius'}) ? $options{'-radius'} : 0;
  my $corners_radius = $options{'-corners_radius'};
  my $corners = ($corners_radius) ? $corners_radius : $options{'-corners'};

  for (my $index = 0; $index < $numfaces; $index++) {
    if ($corners and !$corners->[$index]) {
      push(@curve_pts, $coords->[$index]);

    } else {
      my $prev = ($index) ? $index - 1 : $numfaces - 1;
      my $next = ($index > $numfaces - 2) ? 0 : $index + 1;
      my $anglecoords = [$coords->[$prev], $coords->[$index], $coords->[$next]];

      my $rad = ($corners_radius) ? $corners_radius->[$index] : $radius;
      my ($quad_pts) = &roundedAngleCoords($anglecoords, $rad);
      push(@curve_pts, @{$quad_pts});
    }
  }

  return \@curve_pts;

}

#-----------------------------------------------------------------------------------
# Graphics::pathLineCoords
# retourne les coordonnées d'une pathLine
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> liste de coordonnées des points du path
# options :
#    -closed : <boolean> ligne fermée
#  -shifting : <out|center|in> sens de décalage du path (par défaut center)
# -linewidth : <dimension> epaisseur de la ligne
#-----------------------------------------------------------------------------------
sub pathLineCoords {
  my ($coords, %options) = @_;
  my $numfaces = scalar(@{$coords});
  my @pts;

  my $closed = $options{'-closed'};
  my $linewidth = ($options{'-linewidth'}) ? $options{'-linewidth'} : 2;
  my $shifting = ($options{'-shifting'}) ? $options{'-shifting'} : 'center';

  return undef if (!$numfaces or $linewidth < 2);

  my $previous = ($closed) ? $coords->[$numfaces - 1] : undef;
  my $next = $coords->[1];
  $linewidth /= 2 if ($shifting eq 'center');

  for (my $i = 0; $i < $numfaces; $i++) {
    my $pt = $coords->[$i];

    if (!$previous) {
      # extrémité de curve sans raccord -> angle plat
      $previous = [$pt->[0] + ($pt->[0] - $next->[0]), $pt->[1] + ($pt->[1] - $next->[1])];
    }

    my ($angle, $bisecangle) = &vertexAngle($previous, $pt, $next);

    # distance au centre du cercle inscrit : rayon/sinus demi-angle
    my $sin = sin(deg2rad($angle/2));
    my $delta = ($sin) ? abs($linewidth / $sin) : $linewidth;

    if ($shifting eq 'out' or $shifting eq 'in') {
      my $adding = ($shifting eq 'out') ? -90 : 90;
      push (@pts,  &rad_point($pt, $delta, $bisecangle + $adding));
      push (@pts,  @{$pt});

    } else {
      push (@pts,  &rad_point($pt, $delta, $bisecangle-90));
      push (@pts,  &rad_point($pt, $delta, $bisecangle+90));

    }

    if ($i == $numfaces - 2) {
      $next = ($closed) ? $coords->[0] :
	[$coords->[$i+1]->[0] + ($coords->[$i+1]->[0] - $pt->[0]), $coords->[$i+1]->[1] + ($coords->[$i+1]->[1] - $pt->[1])];
    } else {
      $next = $coords->[$i+2];
    }

    $previous = $coords->[$i];
  }

  if ($closed) {
    push (@pts, ($pts[0], $pts[1], $pts[2], $pts[3]));
  }

  return \@pts;
}

#-----------------------------------------------------------------------------------
# Graphics::curveLineCoords
# retourne les coordonnées d'une curveLine
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> liste de coordonnées des points de la ligne
# options :
#    -closed : <boolean> ligne fermée
#  -shifting : <out|center|in> sens de décalage du contour (par défaut center)
# -linewidth : <dimension> epaisseur de la ligne
#-----------------------------------------------------------------------------------
sub curveLineCoords {
  my ($coords, %options) = @_;
  my $numfaces = scalar(@{$coords});
  my @gopts;
  my @backpts;
  my @pts;

  my $closed = $options{'-closed'};
  my $linewidth = (defined $options{'-linewidth'}) ? $options{'-linewidth'} : 2;
  my $shifting = ($options{'-shifting'}) ? $options{'-shifting'} : 'center';

  return undef if (!$numfaces or $linewidth < 2);

  my $previous = ($closed) ? $coords->[$numfaces - 1] : undef;
  my $next = $coords->[1];
  $linewidth /= 2 if ($shifting eq 'center');

  for (my $i = 0; $i < $numfaces; $i++) {
    my $pt = $coords->[$i];

    if (!$previous) {
      # extrémité de curve sans raccord -> angle plat
      $previous = [$pt->[0] + ($pt->[0] - $next->[0]), $pt->[1] + ($pt->[1] - $next->[1])];
    }

    my ($angle, $bisecangle) = &vertexAngle($previous, $pt, $next);

    # distance au centre du cercle inscrit : rayon/sinus demi-angle
    my $sin = sin(deg2rad($angle/2));
    my $delta = ($sin) ? abs($linewidth / $sin) : $linewidth;

    if ($shifting eq 'out' or $shifting eq 'in') {
      my $adding = ($shifting eq 'out') ? -90 : 90;
      push (@pts,  &rad_point($pt, $delta, $bisecangle + $adding));
      push (@pts,  @{$pt});

    } else {
      @pts = &rad_point($pt, $delta, $bisecangle+90);
      push (@gopts, \@pts);
      @pts = &rad_point($pt, $delta, $bisecangle-90);
      unshift (@backpts, \@pts);
    }

    if ($i == $numfaces - 2) {
      $next = ($closed) ? $coords->[0] :
	[$coords->[$i+1]->[0] + ($coords->[$i+1]->[0] - $pt->[0]), $coords->[$i+1]->[1] + ($coords->[$i+1]->[1] - $pt->[1])];
    } else {
      $next = $coords->[$i+2];
    }

    $previous = $coords->[$i];
  }

  push(@gopts, @backpts);

  if ($closed) {
    push (@gopts, ($gopts[0], $gopts[1]));
  }

  return \@gopts;
}


#-----------------------------------------------------------------------------------
# Graphics::shiftPathCoords
# retourne les coordonnées d'un décalage de path
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordsList> liste de coordonnées des points du path
# options :
#   -closed : <boolean> ligne fermée
# -shifting : <'out'|'in'> sens de décalage du path (par défaut out)
#    -width : <dimension> largeur de décalage (par défaut 1)
#-----------------------------------------------------------------------------------
sub shiftPathCoords {
  my ($coords, %options) = @_;
  my $numfaces = scalar(@{$coords});

  my $closed = $options{'-closed'};
  my $width = (defined $options{'-width'}) ? $options{'-width'} : 1;
  my $shifting = ($options{'-shifting'}) ? $options{'-shifting'} : 'out';

  return $coords if (!$numfaces or !$width);

  my @pts;

  my $previous = ($closed) ? $coords->[$numfaces - 1] : undef;
  my $next = $coords->[1];

  for (my $i = 0; $i < $numfaces; $i++) {
    my $pt = $coords->[$i];

    if (!$previous) {
      # extrémité de curve sans raccord -> angle plat
      $previous = [$pt->[0] + ($pt->[0] - $next->[0]), $pt->[1] + ($pt->[1] - $next->[1])];
    }

    my ($angle, $bisecangle) = &vertexAngle($previous, $pt, $next);

    # distance au centre du cercle inscrit : rayon/sinus demi-angle
    my $sin = sin(deg2rad($angle/2));
    my $delta = ($sin) ? abs($width / $sin) : $width;

    my $adding = ($shifting eq 'out') ? -90 : 90;
    my ($x, $y) = &rad_point($pt, $delta, $bisecangle + $adding);
    push (@pts,  [$x, $y]);


    if ($i > $numfaces - 3) {
      my $j = $numfaces - 1;
      $next = ($closed) ? $coords->[0] :
	[$pt->[0] + ($pt->[0] - $previous->[0]), $pt->[1] + ($pt->[1] - $previous->[1])];

    } else {
      $next = $coords->[$i+2];
    }

    $previous = $coords->[$i];
  }

  return \@pts;
}

#-----------------------------------------------------------------------------------
# Graphics::perpendicularPoint
# retourne les coordonnées du point perpendiculaire abaissé d'un point sur une ligne
#-----------------------------------------------------------------------------------
# paramètres :
# point : <coords> coordonnées du point de référence
#  line : <coordsList> coordonnées des 2 points de la ligne de référence
#-----------------------------------------------------------------------------------
sub perpendicularPoint {
  my ($point, $line) = @_;
  my ($p1, $p2) = @{$line};

  # cas partiuculier de lignes ortho.
  my $min_dist = .01;
  if (abs($p2->[1] - $p1->[1]) < $min_dist) {
    # la ligne de référence est horizontale
    return ($point->[0], $p1->[1]);

  } elsif (abs($p2->[0] - $p1->[0]) < $min_dist) {
    # la ligne de référence est verticale
    return ($p1->[0], $point->[1]);
  }

  my $a1 = ($p2->[1] - $p1->[1]) / ($p2->[0] - $p1->[0]);
  my $b1 = $p1->[1] - ($a1 * $p1->[0]);

  my $a2 = -1.0 / $a1;
  my $b2 = $point->[1] - ($a2 * $point->[0]);

  my $x = ($b2 - $b1) / ($a1 - $a2);
  my $y = ($a1 * $x) + $b1;

  return ($x, $y);

}


#-----------------------------------------------------------------------------------
# Graphics::lineAngle
# retourne l'angle d'un point par rapport à un centre de référence
#-----------------------------------------------------------------------------------
# paramètres :
# startpoint : <coords> coordonnées du point de départ du segment
#   endpoint : <coords> coordonnées du point d'extremité du segment
#-----------------------------------------------------------------------------------
sub lineAngle {
  my ($startpoint, $endpoint) = @_;
  my $angle = atan2($endpoint->[1] - $startpoint->[1], $endpoint->[0] - $startpoint->[0]);

  $angle += pi/2;
  $angle *= 180/pi;
  $angle += 360  if ($angle < 0);

  return $angle;

}


#-----------------------------------------------------------------------------------
# Graphics::lineNormal
# retourne la valeur d'angle perpendiculaire à une ligne
#-----------------------------------------------------------------------------------
# paramètres :
# startpoint : <coords> coordonnées du point de départ du segment
#   endpoint : <coords> coordonnées du point d'extremité du segment
#-----------------------------------------------------------------------------------
sub lineNormal {
  my ($startpoint, $endpoint) = @_;
  my $angle = &lineAngle($startpoint, $endpoint) + 90;

  $angle -= 360  if ($angle > 360);
  return $angle;

}



#-----------------------------------------------------------------------------------
# Graphics::vertexAngle
# retourne la valeur de l'angle formée par 3 points
# ainsi que l'angle de la bisectrice
#-----------------------------------------------------------------------------------
# paramètres :
# pt0 : <coords> coordonnées du premier point de définition de l'angle
# pt1 : <coords> coordonnées du deuxième point de définition de l'angle
# pt2 : <coords> coordonnées du troisième point de définition de l'angle
#-----------------------------------------------------------------------------------
sub vertexAngle {
  my ($pt0, $pt1, $pt2) = @_;
  my $angle1 = &lineAngle($pt0, $pt1);
  my $angle2 = &lineAngle($pt2, $pt1);

  $angle2 += 360 if $angle2 < $angle1;
  my $alpha = $angle2 - $angle1;
  my $bisectrice = $angle1 + ($alpha/2);

  return ($alpha, $bisectrice);
}


#-----------------------------------------------------------------------------------
# Graphics::arc_pts
# calcul des points constitutif d'un arc
#-----------------------------------------------------------------------------------
# paramètres :
#  center : <coordonnées> centre de l'arc,
#  radius : <dimension> rayon de l'arc,
# options :
#  -angle : <angle> angle de départ en degré de l'arc (par défaut 0)
# -extent : <angle> delta angulaire en degré de l'arc (par défaut 360),
#   -step : <dimension> pas de progresion en degré (par défaut 10)
#-----------------------------------------------------------------------------------
sub arc_pts {
    my ($center, $radius, %options) = @_;
    return unless ($radius);

    $center = [0, 0] if (!defined $center);
    my $angle = (defined $options{'-angle'}) ? $options{'-angle'} : 0;
    my $extent = (defined $options{'-extent'}) ? $options{'-extent'} : 360;
    my $step = (defined $options{'-step'}) ? $options{'-step'} : 10;
    my @pts = ();

    if ($extent > 0) {
	for (my $alpha = $angle; $alpha <= ($angle + $extent); $alpha += $step) {
	    my ($xn, $yn) = &rad_point($center, $radius,$alpha);
	    push (@pts, ([$xn, $yn]));
	}
    } else {
	for (my $alpha = $angle; $alpha >= ($angle + $extent); $alpha += $step) {
	    push (@pts, &rad_point($center, $radius, $alpha));
	}
    }

    return @pts;
}


#-----------------------------------------------------------------------------------
# Graphics::rad_point
# retourne le point circulaire défini par centre-rayon-angle
#-----------------------------------------------------------------------------------
# paramètres :
# center : <coordonnée> coordonnée [x,y] du centre de l'arc,
# radius : <dimension> rayon de l'arc,
#  angle : <angle> angle du point de circonférence avec le centre du cercle
#-----------------------------------------------------------------------------------
sub rad_point {
    my ($center, $radius, $angle) = @_;
    my $alpha = deg2rad($angle);

    my $xpt = $center->[0] + ($radius * cos($alpha));
    my $ypt = $center->[1] + ($radius * sin($alpha));

    return ($xpt, $ypt);
}


#-----------------------------------------------------------------------------------
# Graphics::curveItem2polylineCoords
# Conversion des coordonnées ZnItem curve (multicontours) en coordonnées polyline(s)
#-----------------------------------------------------------------------------------
# paramètres :
# widget : <widget> identifiant du widget zinc
#   item : <tagOrId> identifiant de l'item source
# options :
# -tunits : <integer> nombre pas de division des segments bezier (par défaut 20)
# -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
#-----------------------------------------------------------------------------------
sub curveItem2polylineCoords {
  my ($widget, $item, %options) = @_;
  return unless ($widget and $widget->type($item));

  my @coords;
  my $numcontours = $widget->contour($item);
  my $parentgroup = $widget->group($item);

  for (my $contour = 0; $contour < $numcontours; $contour++) {
    my @points = $widget->coords($item, $contour);
    my @contourcoords = &curve2polylineCoords(\@points, %options);

    push(@coords, \@contourcoords);

  }

  return wantarray ? @coords : \@coords;
}

#-----------------------------------------------------------------------------------
# Graphics::curve2polylineCoords
# Conversion curve -> polygone
#-----------------------------------------------------------------------------------
# paramètres :
# points : <coordsList> liste des coordonnées curve à transformer
# options :
# -tunits : <integer> nombre pas de division des segments bezier (par défaut 20)
# -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
#-----------------------------------------------------------------------------------
sub curve2polylineCoords {
  my ($points, %options) = @_;

  my $tunits = ($options{'-tunits'}) ? $options{'-tunits'} : 20;
  my $adjust = (defined $options{'-adjust'}) ? $options{'-adjust'} : 1;

  my @poly;
  my $previous;
  my @bseg;
  my $numseg = 0;
  my $prevtype;

  foreach my $point (@{$points}) {
    my ($x, $y, $c) = @{$point};
    if ($c eq 'c') {
      push(@bseg, $previous) if (!@bseg);
      push(@bseg, $point);

    } else {
      if (@bseg) {
	push(@bseg, $point);

	if ($adjust) {
	  my @pts = &bezierCompute(\@bseg, -skipend => 1);
	  shift @pts;
	  shift @pts;
	  push(@poly, @pts);

	} else {
	  my @pts = &bezierSegment(\@bseg, -tunits => $tunits, -skipend => 1);
	  shift @pts;
	  shift @pts;
	  push(@poly, @pts);

	}

	@bseg = ();
	$numseg++;
	$prevtype = 'bseg';

      } else {
	push(@poly, ([$x, $y]));
	$prevtype = 'line';
      }
    }

    $previous = $point;
  }


  return wantarray ? @poly : \@poly;
}


#-----------------------------------------------------------------------------------
# Graphics::buildTabBoxItem
# construit les items de représentations Zinc d'une boite à onglets
#-----------------------------------------------------------------------------------
# paramètres :
#      widget : <widget> identifiant du widget zinc
# parentgroup : <tagOrId> identifiant de l'item group parent
#
#    options :
#     -coords : <coordsList> coordonnées haut-gauche et bas-droite du rectangle
#               englobant du TabBox
#     -params : <hastable> arguments spécifiques des items curve à passer au widget
#    -texture : <imagefile> ajout d'une texture aux items curve
#  -tabtitles : <hashtable> table de hash de définition des titres onglets
#  -pageitems : <hashtable> table de hash de définition des pages internes
#     -relief : <hashtable> table de hash de définition du relief de forme
#
# (options de construction géometrique passées à tabBoxCoords)
#  -numpages : <integer> nombre de pages (onglets) de la boite
#    -anchor : <'n'|'e'|'s'|'w'> ancrage (positionnement) de la ligne d'onglets
# -alignment : <'left'|'center'|'right'> alignement des onglets sur le coté d'ancrage
#  -tabwidth : <'auto'>|<dimension>|<dimensionList> : largeur des onglets
#              'auto' largeur répartie, les largeurs sont auto-ajustée si besoin.
# -tabheight : <'auto'>|<dimension> : hauteur des onglets
#  -tabshift : <'auto'>|<dimension> offset de 'biseau' entre base et haut de l'onglet (défaut auto)
#    -radius : <dimension> rayon des arrondis d'angle
#   -overlap : <'auto'>|<dimension> offset de recouvrement/séparation entre onglets
#   -corners : <booleanList> liste 'spécifique' des raccords de sommets [0|1]
#-----------------------------------------------------------------------------------
sub buildTabBoxItem {
  my ($widget, $parentgroup, %options) = @_;
  my $coords = $options{'-coords'};
  my $params = $options{'-params'};
  my @tags = @{$params->{'-tags'}};
  my $texture;

  if ($options{'-texture'}) {
    $texture = &getTexture($widget, $options{'-texture'});
  }

  my $titlestyle = $options{'-tabtitles'};
  my $titles = ($titlestyle) ? $titlestyle->{'-text'} : undef ;

  return undef if (!$coords);

  my @tabs;
  my ($shapes, $tcoords, $invert) = &tabBoxCoords($coords, %options);
  my $k = ($invert) ? scalar @{$shapes} : -1;
  foreach my $shape (reverse @{$shapes}) {
    $k += ($invert) ? -1 : +1;
    my $group = $widget->add('group', $parentgroup);
    $params->{'-tags'} = [@tags, $k, 'intercalaire'];
    my $form = $widget->add('curve', $group, $shape, %{$params});
    $widget->itemconfigure($form, -tile => $texture) if $texture;

    if ($options{'-relief'}) {
      &graphicItemRelief($widget, $form, %{$options{'-relief'}});
    }

    if ($options{'-page'}) {
      my $page = &buildZincItem($widget, $group, %{$options{'-page'}});
    }	

    if ($titles) {
      my $tindex = ($invert) ? $k : $#{$shapes} - $k;
      $titlestyle->{'-itemtype'} = 'text';
      $titlestyle->{'-coords'} = $tcoords->[$tindex];
      $titlestyle->{'-params'}->{'-text'} = $titles->[$tindex],;
      $titlestyle->{'-params'}->{'-tags'} = [@tags, $tindex, 'titre'];
      &buildZincItem($widget, $group, %{$titlestyle});

    }


  }

  return @tabs;
}


#-----------------------------------------------------------------------------------
# tabBoxCoords
# Calcul des shapes de boites à onglets
#-----------------------------------------------------------------------------------
# paramètres :
# coords : <coordList> coordonnées haut-gauche bas-droite du rectangle englobant 
#          de la tabbox
# options
#  -numpages : <integer> nombre de pages (onglets) de la boite
#    -anchor : <'n'|'e'|'s'|'w'> ancrage (positionnement) de la ligne d'onglets
# -alignment : <'left'|'center'|'right'> alignement des onglets sur le coté d'ancrage
#  -tabwidth : <'auto'>|<dimension>|<dimensionList> : largeur des onglets
#              'auto' largeur répartie, les largeurs sont auto-ajustée si besoin.
# -tabheight : <'auto'>|<dimension> : hauteur des onglets
#  -tabshift : <'auto'>|<dimension> offset de 'biseau' entre base et haut de l'onglet (défaut auto)
#    -radius : <dimension> rayon des arrondis d'angle
#   -overlap : <'auto'>|<dimension> offset de recouvrement/séparation entre onglets
#   -corners : <booleanList> liste 'spécifique' des raccords de sommets [0|1]
#-----------------------------------------------------------------------------------
sub tabBoxCoords {
  my ($coords, %options) = @_;

  my ($x0, $y0, $xn, $yn) = (@{$coords->[0]}, @{$coords->[1]});
  my (@shapes, @titles_coords);
  my $inverse;

  my @options = keys(%options);
  my $numpages = $options{'-numpages'};

  if (!defined $x0 or !defined $y0 or !defined $xn or !defined $yn or !$numpages) {
    print "Vous devez au minimum spécifier le rectangle englobant et le nombre de pages\n";
    return undef;

  }

  my $anchor = ($options{'-anchor'}) ? $options{'-anchor'} : 'n';
  my $alignment = ($options{'-alignment'}) ? $options{'-alignment'} : 'left';
  my $len = ($options{'-tabwidth'}) ? $options{'-tabwidth'} : 'auto';
  my $thick = ($options{'-tabheight'}) ? $options{'-tabheight'} : 'auto';
  my $biso = ($options{'-tabshift'}) ? $options{'-tabshift'} : 'auto';
  my $radius = ($options{'-radius'}) ? $options{'-radius'} : 0;
  my $overlap = ($options{'-overlap'}) ? $options{'-overlap'} : 0;
  my $corners = $options{'-corners'};
  my $orientation = ($anchor eq 'n' or $anchor eq 's') ? 'horizontal' : 'vertical';
  my $maxwidth = ($orientation eq 'horizontal') ? ($xn - $x0) : ($yn - $y0);
  my $tabswidth = 0;
  my $align = 1;

  if ($len eq 'auto') {
    $tabswidth = $maxwidth;
    $len = ($tabswidth + ($overlap * ($numpages - 1)))/$numpages;

  } else {
    if (ref($len) eq 'ARRAY') {
      foreach my $w (@{$len}) {
	$tabswidth += ($w - $overlap);
      }
      $tabswidth += $overlap;
    } else {
      $tabswidth = ($len * $numpages) - ($overlap * ($numpages - 1));
    }

    if ($tabswidth > $maxwidth) {
      $tabswidth = $maxwidth;
      $len = ($tabswidth + ($overlap * ($numpages - 1)))/$numpages;
    }

    $align = 0 if ($alignment eq 'center' and (($maxwidth - $tabswidth) > $radius));
  }


  if ($thick eq 'auto') {
    $thick = ($orientation eq 'horizontal') ? int(($yn - $y0)/10) : int(($xn - $y0)/10);
    $thick = 10 if ($thick < 10);
    $thick = 40 if ($thick > 40);
  }

  if ($biso eq 'auto') {
    $biso = int($thick/2);
  }

  if (($alignment eq 'right' and $anchor ne 'w') or
      ($anchor eq 'w' and $alignment ne 'right')) {

    if (ref($len) eq 'ARRAY') {
      for (my $p = 0; $p < $numpages; $p++) {
	$len->[$p] *= -1;
      }
    } else {
      $len *= -1;
    }
    $biso *= -1;
    $overlap *= -1;
  }

  my ($biso1, $biso2) = ($alignment eq 'center') ? ($biso/2, $biso/2) : (0, $biso);

  my (@cadre, @tabdxy);
  my ($xref, $yref);
  if ($orientation eq 'vertical') {
    $thick *= -1 if ($anchor eq 'w');
    my ($startx, $endx) = ($anchor eq 'w') ? ($x0, $xn) : ($xn, $x0);
    my ($starty, $endy) = (($anchor eq 'w' and $alignment ne 'right') or 
			   ($anchor eq 'e' and $alignment eq 'right')) ? 
			     ($yn, $y0) : ($y0, $yn);

    $xref = $startx - $thick;
    $yref = $starty;
    if  ($alignment eq 'center') {
      my $ratio = ($anchor eq 'w') ? -2 : 2;
      $yref += (($maxwidth - $tabswidth)/$ratio);
    }

    @cadre = ([$xref, $endy], [$endx, $endy], [$endx, $starty], [$xref, $starty]);

    # flag de retournement de la liste des pts de curve si nécessaire -> sens anti-horaire
    $inverse = ($alignment ne 'right');

  } else {
    $thick *= -1 if ($anchor eq 's');
    my ($startx, $endx) = ($alignment eq 'right') ? ($xn, $x0) : ($x0, $xn);
    my ($starty, $endy) = ($anchor eq 's') ? ($yn, $y0) : ($y0, $yn);


    $yref = $starty + $thick;
    $xref = ($alignment eq 'center') ? $x0 + (($maxwidth - $tabswidth)/2) : $startx;

    @cadre = ([$endx, $yref], [$endx, $endy], [$startx, $endy], [$startx, $yref]);

    # flag de retournement de la liste des pts de curve si nécessaire -> sens anti-horaire
    $inverse = (($anchor eq 'n' and $alignment ne 'right') or ($anchor eq 's' and $alignment eq 'right'));
  }

  for (my $i = 0; $i < $numpages; $i++) {
    my @pts = ();

    # décrochage onglet
    #push (@pts, ([$xref, $yref])) if $i > 0;

    # cadre
    push (@pts, @cadre);

    # points onglets
    push (@pts, ([$xref, $yref])) if ($i > 0 or !$align);

    my $tw = (ref($len) eq 'ARRAY') ? $len->[$i] : $len;
    @tabdxy = ($orientation eq 'vertical') ?
      ([$thick, $biso1],[$thick, $tw - $biso2],[0, $tw]) : ([$biso1, -$thick],[$tw - $biso2, -$thick],[$tw, 0]);
    foreach my $dxy (@tabdxy) {
      push (@pts, ([$xref + $dxy->[0], $yref + $dxy->[1]]));
    }

    if ($radius) {
      if (!defined $options{'-corners'}) {
	$corners = ($i > 0 or !$align) ? [0, 1, 1, 0, 0, 1, 1, 0] : [0, 1, 1, 0, 1, 1, 0, 0, 0];
      }
      my $curvepts = &roundedCurveCoords(\@pts, -radius => $radius, -corners => $corners);
      @{$curvepts} = reverse @{$curvepts} if ($inverse);
      push (@shapes, $curvepts);
    } else {
      @pts = reverse @pts if ($inverse);
      push (@shapes, \@pts);
    }

    if ($orientation eq 'horizontal') {
      push (@titles_coords, [$xref + ($tw - ($biso2 - $biso1))/2, $yref - ($thick/2)]);
      $xref += ($tw - $overlap);

    } else {
      push (@titles_coords, [$xref + ($thick/2), $yref + ($len - (($biso2 - $biso1)/2))/2]);
      $yref += ($len - $overlap);
    }

  }

  return (\@shapes, \@titles_coords, $inverse);

}


#-----------------------------------------------------------------------------------
# Graphics::graphicItemRelief
# construit un relief à l'item Zinc en utilisant des items Triangles
#-----------------------------------------------------------------------------------
# paramètres :
#  widget : <widget> identifiant du widget zinc
#    item : <tagOrId> identifiant de l'item zinc
# options : <hash> table d'options
#     -closed : <boolean> le relief assure la fermeture de forme (défaut 1)
#     -profil : <'rounded'|'flat'> type de profil (defaut 'rounded')
#     -relief : <'raised'|'sunken'> (défaut 'raised')
#       -side : <'inside'|'outside'> relief interne ou externe à la forme (défaut 'inside')
#      -color : <color> couleur du relief (défaut couleur de la forme)
#   -smoothed : <boolean> facettes relief lissées ou non (défaut 1)
# -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
#      -width : <dimension> 'épaisseur' du relief en pixel
#       -fine : <boolean> mode précision courbe de bezier (défaut 0 : auto-ajustée)
#-----------------------------------------------------------------------------------
sub graphicItemRelief {
  my ($widget, $item, %options) = @_;
  my @items;

  # relief d'une liste d'items -> appel récursif
  if (ref($item) eq 'ARRAY') {
    foreach my $part (@{$item}) {
      push(@items, &graphicItemRelief($widget, $part, %options));
    }

  } else {
    my $itemtype = $widget->type($item);

    return unless ($itemtype);

    my $parentgroup = $widget->group($item);
    my $priority = (defined $options{'-priority'}) ? $options{'-priority'} :
      $widget->itemcget($item, -priority)+1;

    # coords transformés (polyline) de l'item
    my $adjust = !$options{'-fine'};
    foreach my $coords (&ZincItem2CurveCoords($widget, $item, -linear => 1,
					      -realcoords => 1,-adjust => $adjust)) {
      my ($pts, $colors) = &polylineReliefParams($widget, $item, $coords, %options);

      push(@items, $widget->add('triangles', $parentgroup, $pts,
				-priority => $priority,
				-colors => $colors));
    }


    # renforcement du contour
    if ($widget->itemcget($item, -linewidth)) {
      push(@items, $widget->clone($item, -filled => 0, -priority => $priority+1));
    }
  }

  return \@items;
}


#-----------------------------------------------------------------------------------
# Graphics::polylineReliefParams
# retourne la liste des points et des couleurs nécessaires à la construction
# de l'item Triangles du relief
#-----------------------------------------------------------------------------------
# paramètres :
#  widget : <widget> identifiant widget Zinc
#    item : <tagOrId> identifiant item Zinc
# options : <hash> table d'options
#     -closed : <boolean> le relief assure la fermeture de forme (défaut 1)
#     -profil : <'rounded'|'flat'> type de profil (defaut 'rounded')
#     -relief : <'raised'|'sunken'> (défaut 'raised')
#       -side : <'inside'|'outside'> relief interne ou externe à la forme (défaut 'inside')
#      -color : <color> couleur du relief (défaut couleur de la forme)
#   -smoothed : <boolean> facettes relief lissées ou non (défaut 1)
# -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
#      -width : <dimension> 'épaisseur' du relief en pixel
#-----------------------------------------------------------------------------------
sub polylineReliefParams {
  my ($widget, $item, $coords, %options) = @_;

  my $closed = (defined $options{'-closed'}) ? $options{'-closed'} : 1;
  my $profil = ($options{'-profil'}) ? $options{'-profil'} : 'rounded';
  my $relief = ($options{'-relief'}) ? $options{'-relief'} : 'raised';
  my $side = ($options{'-side'}) ? $options{'-side'} : 'inside';
  my $basiccolor = ($options{'-color'}) ? $options{'-color'} : &zincItemPredominantColor($widget, $item);
  my $smoothed = (defined $options{'-smooth'}) ? $options{'-smooth'} : 1;
  my $lightangle = (defined $options{'-lightangle'}) ? $options{'-lightangle'}
    : $widget->cget('-lightangle');

  my $width = $options{'-width'};
  if (!$width or $width < 1) {
    my ($x0, $y0, $x1, $y1) = $widget->bbox($item);
    $width = &_min($x1 -$x0, $y1 - $y0)/10;
    $width = 2 if ($width < 2);
  }

  my $numfaces = scalar(@{$coords});
  my $previous = ($closed) ? $coords->[$numfaces - 1] : undef;
  my $next = $coords->[1];

  my @pts;
  my @colors;
  my $alpha = 100;
  if ($basiccolor =~ /;/) {
    ($basiccolor, $alpha) = split /;/, $basiccolor;

  }

  $alpha /= 2 if (!($options{'-color'} =~ /;/) and $profil eq 'flat');

  my $reliefalphas = ($profil eq 'rounded') ? [0,$alpha] : [$alpha, $alpha];

  for (my $i = 0; $i < $numfaces; $i++) {
    my $pt = $coords->[$i];

    if (!$previous) {
      # extrémité de curve sans raccord -> angle plat
      $previous = [$pt->[0] + ($pt->[0] - $next->[0]), $pt->[1] + ($pt->[1] - $next->[1])];
    }

    my ($angle, $bisecangle) = &vertexAngle($previous, $pt, $next);

    # distance au centre du cercle inscrit : rayon/sinus demi-angle
    my $sin = sin(deg2rad($angle/2));
    my $delta = ($sin) ? abs($width / $sin) : $width;
    my $decal = ($side eq 'outside') ? -90 : 90;

    my @shift_pt = &rad_point($pt, $delta, $bisecangle+$decal);
    push (@pts,  @shift_pt);
    push (@pts,  @{$pt});

    if (!$smoothed and $i) {
      push (@pts, @shift_pt);
      push (@pts,  @{$pt});
    }

    my $faceangle = 360 -(&lineNormal($previous, $next)+90);

    my $light = abs($lightangle - $faceangle);
    $light = 360 - $light if ($light > 180);
    $light = 1 if $light < 1;

    my $lumratio = ($relief eq 'sunken') ? (180-$light)/180 : $light/180;

    if (!$smoothed and $i) {
      push(@colors, ($colors[-2],$colors[-1]));
    }

   if ($basiccolor) {
     # création des couleurs dérivées
     my $shade = &LightingColor($basiccolor, $lumratio);
     my $color0 = $shade.";".$reliefalphas->[0];
     my $color1 = $shade.";".$reliefalphas->[1];
     push(@colors, ($color0, $color1));

   } else {
      my $c = (255*$lumratio);
      my $color0 = &hexaRGBcolor($c, $c, $c, $reliefalphas->[0]);
      my $color1 = &hexaRGBcolor($c, $c, $c, $reliefalphas->[1]);
      push(@colors, ($color0, $color1));
    }

    if ($i == $numfaces - 2) {
      $next = ($closed) ? $coords->[0] :
	[$coords->[$i+1]->[0] + ($coords->[$i+1]->[0] - $pt->[0]), $coords->[$i+1]->[1] + ($coords->[$i+1]->[1] - $pt->[1])];
    } else {
      $next = $coords->[$i+2];
    }

    $previous = $coords->[$i];
  }

  if ($closed) {
    push (@pts, ($pts[0], $pts[1], $pts[2], $pts[3]));
    push (@colors, ($colors[0], $colors[1]));

    if (!$smoothed) {
      push (@pts, ($pts[0], $pts[1], $pts[2], $pts[3]));
      push (@colors, ($colors[0], $colors[1]));
    }

  }


  return (\@pts, \@colors);
}


#-----------------------------------------------------------------------------------
# Graphics::graphicItemShadow
# Création d'une ombre portée à l'item
#-----------------------------------------------------------------------------------
# paramètres :
#  widget : <widget> identifiant widget Zinc
#    item : <tagOrId> identifiant item Zinc
# options : <hash> table d'options
#    -opacity : <percent> opacité de l'ombre (défaut 50)
#     -filled : <boolean> remplissage totale de l'ombre (hors bordure) (defaut 1)
# -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
#   -distance : <dimension> distance de projection de l'ombre en pixel
#  -enlarging : <dimension> grossi de l'ombre portée en pixels (defaut 0)
#      -width : <dimension> taille de diffusion/diffraction (défaut 4)
#      -color : <color> couleur de l'ombre portée (défaut black)
#-----------------------------------------------------------------------------------
sub graphicItemShadow {
  my ($widget, $item, %options) = @_;
  my @items;

  # relief d'une liste d'items -> appel récursif
  if (ref($item) eq 'ARRAY') {
    foreach my $part (@{$item}) {
      push(@items, &graphicItemShadow($widget, $part, %options));
    }

    return \@items;

  } else {

    my $itemtype = $widget->type($item);

    return unless ($itemtype);

    # création d'un groupe à l'ombre portée
    my $parentgroup = ($options{'-parentgroup'}) ? $options{'-parentgroup'} :
      $widget->group($item);
    my $priority = (defined $options{'-priority'}) ? $options{'-priority'} :
      ($widget->itemcget($item, -priority))-1;
    $priority = 0 if ($priority < 0);

    my $shadow = $widget->add('group', $parentgroup, -priority => $priority);

    if ($itemtype eq 'text') {
      my $opacity = (defined $options{'-opacity'}) ? $options{'-opacity'} : 50;
      my $color = ($options{'-color'}) ? $options{'-color'} : '#000000';

      my $clone = $widget->clone($item, -color => $color.";".$opacity);
      $widget->chggroup($clone, $shadow);

    } else {

      # création des items (de dessin) de l'ombre
      my $filled = (defined $options{'-filled'}) ? $options{'-filled'} : 1;

      # coords transformés (polyline) de l'item
      foreach my $coords (&ZincItem2CurveCoords($widget, $item, -linear => 1, -realcoords => 1)) {
	my ($t_pts, $i_pts, $colors) = &polylineShadowParams($widget, $item, $coords, %options);

	# option filled : remplissage hors bordure de l'ombre portée (item curve)
	if ($filled) {
	  if (@items) {
	    $widget->contour($items[0], 'add', 0, $i_pts);
	
	  } else {
	    push(@items, $widget->add('curve', $shadow, $i_pts,
				      -linewidth => 0,
				      -filled => 1,
				      -fillcolor => $colors->[0],
				     ));
	  }
	}
	
	# bordure de diffusion de l'ombre (item triangles)
	push(@items, $widget->add('triangles', $shadow, $t_pts,
			      -colors => $colors));
      }
    }

    # positionnement de l'ombre portée
    my $distance = (defined $options{'-distance'}) ? $options{'-distance'} : 10;
    my $lightangle = (defined $options{'-lightangle'}) ? $options{'-lightangle'}
      : $widget->cget('-lightangle');

    my ($dx, $dy) = &rad_point([0, 0], $distance, $lightangle+180);
    $widget->translate($shadow, $dx, -$dy);

    return $shadow;

  }

}


#-----------------------------------------------------------------------------------
# Graphics::polylineShadowParams
# retourne les listes des points et de couleurs nécessaires à la construction des
# items triangles (bordure externe) et curve (remplissage interne) de l'ombre portée
#-----------------------------------------------------------------------------------
# paramètres :
#  widget : <widget> identifiant widget Zinc
#    item : <tagOrId> identifiant item Zinc
# options : <hash> table d'options
#    -opacity : <percent> opacité de l'ombre (défaut 50)
# -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
#   -distance : <dimension> distance de projection de l'ombre en pixel (défaut 10)
#  -enlarging : <dimension> grossi de l'ombre portée en pixels (defaut 2)
#      -width : <dimension> taille de diffusion/diffraction (défaut distance -2)
#      -color : <color> couleur de l'ombre portée (défaut black)
#-----------------------------------------------------------------------------------
sub polylineShadowParams {
  my ($widget, $item, $coords, %options) = @_;

  my $distance = (defined $options{'-distance'}) ? $options{'-distance'} : 10;
  my $width = (defined $options{'-width'}) ? $options{'-width'} : $distance-2;
  my $opacity = (defined $options{'-opacity'}) ? $options{'-opacity'} : 50;
  my $color = ($options{'-color'}) ? $options{'-color'} : '#000000';
  my $enlarging = (defined $options{'-enlarging'}) ? $options{'-enlarging'} : 2;

  if ($enlarging) {
    $coords = &shiftPathCoords($coords, -width => $enlarging, -closed => 1, -shifting => 'out');
  }

  my $numfaces = scalar(@{$coords});
  my $previous = $coords->[$numfaces - 1];
  my $next = $coords->[1];

  my @t_pts;
  my @i_pts;
  my @colors;
  my ($color0, $color1) = ($color.";$opacity", $color.";0");

  for (my $i = 0; $i < $numfaces; $i++) {
    my $pt = $coords->[$i];

    if (!$previous) {
      # extrémité de curve sans raccord -> angle plat
      $previous = [$pt->[0] + ($pt->[0] - $next->[0]), $pt->[1] + ($pt->[1] - $next->[1])];
    }

    my ($angle, $bisecangle) = &vertexAngle($previous, $pt, $next);

    # distance au centre du cercle inscrit : rayon/sinus demi-angle
    my $sin = sin(deg2rad($angle/2));
    my $delta = ($sin) ? abs($width / $sin) : $width;
    my $decal = 90;

    my @shift_pt = &rad_point($pt, $delta, $bisecangle+$decal);
    push (@i_pts,  @shift_pt);
    push (@t_pts,  @shift_pt);
    push (@t_pts,  @{$pt});

    push(@colors, ($color0, $color1));

    if ($i == $numfaces - 2) {
      $next = $coords->[0];
    } else {
      $next = $coords->[$i+2];
    }

    $previous = $coords->[$i];
  }

  # fermeture
  push(@t_pts, ($t_pts[0], $t_pts[1],$t_pts[2],$t_pts[3]));
  push(@i_pts, ($t_pts[0], $t_pts[1]));
  push(@colors, ($color0, $color1,$color0,$color1));

  return (\@t_pts, \@i_pts, \@colors);
}


#-----------------------------------------------------------------------------------
# Graphics::bezierSegment
# Calcul d'une approximation de segment (Quadratique ou Cubique) de bezier
#-----------------------------------------------------------------------------------
# paramètres :
#    points : <[P1, C1, <C1>, P2]> liste des points définissant le segment de bezier
#
# options :
#  -tunits : <integer> nombre pas de division des segments bezier (par défaut 20)
# -skipend : <boolean> : ne pas retourner le dernier point du segment (chainage)
#-----------------------------------------------------------------------------------
sub bezierSegment {
  my ($coords, %options) = @_;
  my $tunits = ($options{'-tunits'}) ? $options{'-tunits'} : 20;
  my $skipendpt = $options{'-skipend'};

  my @pts;

  my $lastpt = ($skipendpt) ? $tunits-1 : $tunits;
  foreach (my $i = 0; $i <= $lastpt; $i++) {
    my $t = ($i) ? ($i/$tunits) : $i;
    push(@pts, &bezierPoint($t, $coords));
  }

  return wantarray ? @pts : \@pts;

}


#-----------------------------------------------------------------------------------
# Graphics::bezierPoint
# calcul d'un point du segment (Quadratique ou Cubique) de bezier
# params :
# t = <n> (représentation du temps : de 0 à 1)
# coords = (P1, C1, <C1>, P2) liste des points définissant le segment de bezier
# P1 et P2 : extémités du segment et pts situés sur la courbe
# C1 <C2> : point(s) de contrôle du segment
#-----------------------------------------------------------------------------------
# courbe bezier niveau 2 sur (P1, P2, P3)
# P(t) = (1-t)²P1 + 2t(1-t)P2 + t²P3
#
# courbe bezier niveau 3 sur (P1, P2, P3, P4)
# P(t) = (1-t)³P1 + 3t(1-t)²P2 + 3t²(1-t)P3 + t³P4
#-----------------------------------------------------------------------------------
sub bezierPoint {
  my ($t, $coords) = @_;
  my ($p1, $c1, $c2, $p2) = @{$coords};

  # quadratique
  if (!defined $p2) {
    $p2 = $c2;
    $c2 = undef;
  }

  # extrémités : points sur la courbe
  return wantarray ? @{$p1} : $p1 if (!$t);
  return wantarray ? @{$p2} : $p2 if ($t >= 1.0);


  my $t2 = $t * $t;
  my $t3 = $t2 * $t;
  my @pt;

  # calcul pour x et y
  foreach my $i (0, 1) {

    if (defined $c2) {
      my $r1 = (1 - (3*$t) + (3*$t2) -    $t3)  * $p1->[$i];
      my $r2 = (    (3*$t) - (6*$t2) + (3*$t3)) * $c1->[$i];
      my $r3 = (             (3*$t2) - (3*$t3)) * $c2->[$i];
      my $r4 = (                          $t3)  * $p2->[$i];

      $pt[$i] = ($r1 + $r2 + $r3 + $r4);

    } else {
      my $r1 = (1 - (2*$t) +    $t2)  * $p1->[$i];
      my $r2 = (    (2*$t) - (2*$t2)) * $c1->[$i];
      my $r3 = (                $t2)  * $p2->[$i];

      $pt[$i] = ($r1 + $r2 + $r3);
    }
  }

  #return wantarray ? @pt : \@pt;
  return \@pt;

}


#-----------------------------------------------------------------------------------
# Graphics::bezierCompute
# Retourne une liste de coordonnées décrivant un segment de bezier
#-----------------------------------------------------------------------------------
# paramètres :
#     coords : <coordsList> liste des points définissant le segment de bezier
#
# options :
# -precision : <dimension> seuil limite du calcul d'approche de la courbe
#   -skipend : <boolean> : ne pas retourner le dernier point du segment (chaînage bezier)
#-----------------------------------------------------------------------------------
sub bezierCompute {
  my ($coords, %options) = @_;
  my $precision = ($options{'-precision'}) ? $options{'-precision'} : $bezierClosenessThreshold;
  my $lastit = [];

  &subdivideBezier($coords, $lastit, $precision);

  push(@{$lastit}, $coords->[3]) if (!$options{'-skipend'});

  return wantarray ? @{$lastit} : $lastit;
}

#------------------------------------------------------------------------------------
# Graphics::smallEnought
# intégration code Stéphane Conversy : calcul points bezier (précision auto ajustée)
#------------------------------------------------------------------------------------
# distance is something like num/den with den=sqrt(something)
# what we want is to test that distance is smaller than precision,
# so we have distance < precision ?  eq. to distance^2 < precision^2 ?
# eq. to (num^2/something) < precision^2 ?
# eq. to num^2 < precision^2*something
# be careful with huge values though (hence 'long long')
# with common values: 9add 9mul
#------------------------------------------------------------------------------------
sub smallEnoughBezier {
  my ($bezier, $precision) = @_;
  my ($x, $y) = (0, 1);
  my ($A, $B) = ($bezier->[0], $bezier->[3]);

  my $den = (($A->[$y]-$B->[$y])*($A->[$y]-$B->[$y])) + (($B->[$x]-$A->[$x])*($B->[$x]-$A->[$x]));
  my $p = $precision*$precision;

  # compute distance between P1|P2 and P0|P3
  my $M = $bezier->[1];
  my $num1 = (($M->[$x]-$A->[$x])*($A->[$y]-$B->[$y])) + (($M->[$y]-$A->[$y])*($B->[$x]-$A->[$x]));

  $M = $bezier->[2];
  my $num2 = (($M->[$x]-$A->[$x])*($A->[$y]-$B->[$y])) + (($M->[$y]-$A->[$y])*($B->[$x]-$A->[$x]));

  # take the max
  $num1 = $num2 if ($num2 > $num1);

  return ($p*$den > ($num1*$num1)) ? 1 : 0;

}

#-----------------------------------------------------------------------------------
# Graphics::subdivideBezier
# subdivision d'une courbe de bezier
#-----------------------------------------------------------------------------------
sub subdivideBezier {
  my ($bezier, $it, $precision, $integeropt) = @_;
  my ($b0, $b1, $b2, $b3) = @{$bezier};

  if (&smallEnoughBezier($bezier, $precision)) {
    push(@{$it}, ([$b0->[0],$b0->[1]]));

  } else {
    my ($left, $right);

    foreach my $i (0, 1) {

      if ($integeropt) {
	# int optimized (6+3=9)add + (5+3=8)shift

	$left->[0][$i] = $b0->[$i];
	$left->[1][$i] = ($b0->[$i] + $b1->[$i]) >> 1;
	$left->[2][$i] = ($b0->[$i] + $b2->[$i] + ($b1->[$i] << 1)) >> 2; # keep precision
	my $tmp = ($b1->[$i] + $b2->[$i]);
	$left->[3][$i] = ($b0->[$i] + $b3->[$i] + ($tmp << 1) + $tmp) >> 3;

	$right->[3][$i] = $b3->[$i];
	$right->[2][$i] = ($b3->[$i] + $b2->[$i]) >> 1;
	$right->[1][$i] = ($b3->[$i] + $b1->[$i] + ($b2->[$i] << 1) ) >> 2; # keep precision
	$right->[0][$i] = $left->[3]->[$i];

      } else {
	# float

	$left->[0][$i] = $b0->[$i];
	$left->[1][$i] = ($b0->[$i] + $b1->[$i]) / 2;
	$left->[2][$i] = ($b0->[$i] + (2*$b1->[$i]) + $b2->[$i]) / 4;
	$left->[3][$i] = ($b0->[$i] + (3*$b1->[$i]) + (3*$b2->[$i]) + $b3->[$i]) / 8;

	$right->[3][$i] = $b3->[$i];
	$right->[2][$i] = ($b3->[$i] + $b2->[$i]) / 2;
	$right->[1][$i] = ($b3->[$i] + (2*$b2->[$i]) + $b1->[$i]) / 4;
	$right->[0][$i] = ($b3->[$i] + (3*$b2->[$i]) + (3*$b1->[$i]) + $b0->[$i]) / 8;

      }
    }

    &subdivideBezier($left, $it, $precision, $integeropt);
    &subdivideBezier($right, $it, $precision, $integeropt);

  }
}



#-----------------------------------------------------------------------------------
# RESOURCES GRAPHIQUES PATTERNS, TEXTURES, IMAGES, GRADIENTS, COULEURS...
#-----------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------
# Graphics::getPattern
# retourne la ressource bitmap en l'initialisant si première utilisation
#-----------------------------------------------------------------------------------
# paramètres :
# filename : nom du fichier bitmap pattern
# options
# -storage : <hastable> référence de la table de stockage de patterns
#-----------------------------------------------------------------------------------
sub getPattern {
  my ($filename, %options) = @_;
  my $table = (defined $options{'-storage'} and ref($options{'-storage'}) eq 'HASH') ? 
    $options{'-storage'} : \%bitmaps;

  if (!exists($table->{$filename})) {
    my $bitmap = '@'.Tk::findINC($filename);
    $table->{$filename} = $bitmap if $bitmap;

  }

  return $table->{$filename};
}

#-----------------------------------------------------------------------------------
# Graphics::getTexture
# retourne l'image de texture en l'initialisant si première utilisation
#-----------------------------------------------------------------------------------
# paramètres :
#   widget : <widget> identifiant du widget zinc
# filename : nom du fichier texture
# options
# -storage : <hastable> référence de la table de stockage de textures
#-----------------------------------------------------------------------------------
sub getTexture {
  my ($widget, $filename, %options) = @_;
  my $table = (defined $options{'-storage'} and ref($options{'-storage'}) eq 'HASH') ? 
    $options{'-storage'} : \%textures;

  return &getImage($widget, $filename, -storage => $table);

}

#-----------------------------------------------------------------------------------
# Graphics::getImage
# retourne la ressource image en l'initialisant si première utilisation
#-----------------------------------------------------------------------------------
# paramètres :
#   widget : <widget> identifiant du widget zinc
# filename : nom du fichier image
# options
# -storage : <hastable> référence de la table de stockage d'images
#-----------------------------------------------------------------------------------
sub getImage {
  my ($widget, $filename, %options) = @_;
  my $table = (defined $options{'-storage'} and ref($options{'-storage'}) eq 'HASH') ? 
    $options{'-storage'} : \%images;

  if (!exists($table->{$filename})) {
    my $image;
    if ($filename =~ /.png|.PNG/) {
      $image = $widget->Photo(-format => 'png', -file => Tk::findINC($filename));

    } elsif ($filename =~ /.jpg|.JPG|.jpeg|.JPEG/) {
      $image = $widget->Photo(-format => 'jpeg', -file => Tk::findINC($filename));

    } else {
      $image = $widget->Photo(-file => Tk::findINC($filename));
    }

    $table->{$filename} = $image if $image;

  }

  return $table->{$filename};

}


#-----------------------------------------------------------------------------------
# Graphics::init_pixmaps
# initialise une liste de fichier image
#-----------------------------------------------------------------------------------
# paramètres :
#    widget : <widget> identifiant du widget zinc
# filenames : <filenameList> list des noms des fichier image
# options
#  -storage : <hastable> référence de la table de stockage d'images
#-----------------------------------------------------------------------------------
sub init_pixmaps {
  my ($widget, $filenames, %options) = @_;
  my @imgs = ();

  my @files = (ref($filenames) eq 'ARRAY') ? @{$filenames} : ($filenames);

  foreach (@files) {
    push(@imgs, &getImage($widget, $_, %options));
  }

  return @imgs;
}


#-----------------------------------------------------------------------------------
# Graphics::_min
# retourne la plus petite valeur entre 2 valeurs
#-----------------------------------------------------------------------------------
sub _min {
  my ($n1, $n2) = @_;
  my $mini = ($n1 > $n2) ? $n2 : $n1;
  return $mini;

}

#-----------------------------------------------------------------------------------
# Graphics::_max
# retourne la plus grande valeur entre 2 valeurs
#-----------------------------------------------------------------------------------
sub _max {
  my ($n1, $n2) = @_;
  my $maxi = ($n1 > $n2) ? $n1 : $n2;
  return $maxi;

}

#-----------------------------------------------------------------------------------
# Graphics::_trunc
# fonction interne de troncature des nombres: n = position décimale 
#-----------------------------------------------------------------------------------
sub _trunc {
  my ($val, $n) = @_;
  my $str;
  my $dec;

  ($val) =~ /([0-9]+)\.?([0-9]*)/;
  $str = ($val < 0) ? "-$1" : $1;

  if (($2 ne "") && ($n != 0)) {
    $dec = substr($2, 0, $n);
    if ($dec != 0) {
      $str = $str . "." . $dec;
    }
  }
  return $str;
}

#-----------------------------------------------------------------------------------
# Graphics::setGradients
# création de gradient nommés Zinc
#-----------------------------------------------------------------------------------
# paramètres :
#   widget : <widget> identifiant du widget zinc
#    grads : <hastable> table de hash de définition de couleurs zinc
#-----------------------------------------------------------------------------------
sub setGradients {
  my ($widget, $grads) = @_;

  # initialise les gradients de taches
  unless (@Gradients) {
    while (my ($name, $gradient) = each( %{$grads})) {
      # création des gradients nommés
      $widget->gname($gradient, $name);
      push(@Gradients, $name);
    }
  }
}


#-----------------------------------------------------------------------------------
# Graphics::RGB_dec2hex
# conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
#-----------------------------------------------------------------------------------
# paramètres :
#  rgb : <rgbColorList> liste de couleurs au format RGB
#-----------------------------------------------------------------------------------
sub RGB_dec2hex {
   my (@rgb) = @_;
   return (sprintf("#%04x%04x%04x", @rgb));
}

#-----------------------------------------------------------------------------------
# Graphics::pathGraduate
# création d'un jeu de couleurs dégradées pour item pathLine
#-----------------------------------------------------------------------------------
sub pathGraduate {
  my ($widget, $numcolors, $style) = @_;

  my $type = $style->{'-type'};
  my $triangles_colors;

  if ($type eq 'linear') {
    return &createGraduate($widget, $numcolors, $style->{'-colors'}, 2);

  } elsif ($type eq 'double') {
    my $colors1 = &createGraduate($widget, $numcolors/2+1, $style->{'-colors'}->[0]);
    my $colors2 = &createGraduate($widget, $numcolors/2+1, $style->{'-colors'}->[1]);
    my @colors;
    for (my $i = 0; $i <= $numcolors; $i++) {
      push(@colors, ($colors1->[$i], $colors2->[$i]));
    }

    return \@colors;

  } elsif ($type eq 'transversal') {
    my ($c1, $c2) = @{$style->{'-colors'}};
    my @colors = ($c1, $c2);
    for (my $i = 0; $i < $numcolors; $i++) {
      push(@colors, ($c1, $c2));
    }

    return \@colors;
  }
}

#-----------------------------------------------------------------------------------
# Graphics::createGraduate
# création d'un jeu de couleurs intermédiaires (dégradé) entre n couleurs
#-----------------------------------------------------------------------------------
sub createGraduate {
  my ($widget, $totalsteps, $refcolors, $repeat) = @_;
  my @colors;

  $repeat = 1 if (!$repeat);
  my $numgraduates = scalar @{$refcolors} - 1;

  if ($numgraduates < 1) {
    print "Le dégradé necessite au minimum 2 couleurs de référence...\n";
    return undef;
  }

  my $steps = ($numgraduates > 1) ? $totalsteps/($numgraduates -1) : $totalsteps;

  for (my $c = 0; $c < $numgraduates; $c++) {
    my ($c1, $c2) = ($refcolors->[$c], $refcolors->[$c+1]);

    for (my $i = 0 ; $i < $steps ; $i++) {
      my $color = MedianColor($c1, $c2, $i/($steps-1));
      for (my $k = 0; $k < $repeat; $k++) {
	push (@colors, $color);
      }
    }

    if ($c < $numgraduates - 1) {
      for (my $k = 0; $k < $repeat; $k++) {
	pop @colors;
      }
    }
  }

  return \@colors;
}

#-----------------------------------------------------------------------------------
# Graphics::LightingColor
# modification d'une couleur par sa composante luminosité
#-----------------------------------------------------------------------------------
# paramètres :
#  color : <color> couleur au format zinc
#   newL : <pourcent> (de 0 à 1) nouvelle valeur de luminosité
#-----------------------------------------------------------------------------------
sub LightingColor {
    my ($color, $newL) = @_;
    my ($H, $L, $S);

    if ($color and $newL) {
      my ($RGB) = &hexa2RGB($color);
      ($H, $L, $S) = @{&RGBtoHLS(@{$RGB})};


      $newL = 1 if $newL > 1;		
      my ($nR, $nG, $nB) = @{&HLStoRGB($H, $newL, $S)};
      return &hexaRGBcolor($nR*255, $nG*255, $nB*255);
	
    }

    return undef;
}


#-----------------------------------------------------------------------------------
# Graphics::zincItemPredominantColor
# retourne la couleur dominante d'un item ('barycentre' gradiant fillcolor)
#-----------------------------------------------------------------------------------
# paramètres :
#  widget : <widget> identifiant du widget zinc
#    item : <tagOrId> identifiant de l'item zinc
#-----------------------------------------------------------------------------------
sub zincItemPredominantColor {
  my ($widget, $item) = @_;
  my $type = $widget->type($item);

  if ($type eq 'text' or '$type' eq 'icon') {
    return $widget->itemcget($item, -color);

  } elsif ($type eq 'triangles' or
	   $type eq 'rectangle' or
	   $type eq 'arc' or
	   $type eq 'curve') {

    my @colors;

    if ($type eq 'triangles') {
      @colors =  $widget->itemcget($item, -colors);

    } else {
      my $grad =  $widget->itemcget($item, -fillcolor);
      
      return $grad if (scalar (my @unused = (split / /, $grad)) < 2);
	
      my @colorparts = split /\|/, $grad;
      foreach my $section (@colorparts) {
	if ($section !~ /=/) {
	  my ($color, $director, $position) = split / /, $section;
	  push (@colors, $color);
	}
      }
    }
	

    my ($Rs, $Gs, $Bs, $As, $numcolors) = (0, 0, 0, 0, 0);
    foreach my $color (@colors) {
      my ($r, $g, $b, $a) = ZnColorToRGB($color);
      $Rs += $r;
      $Gs += $g;
      $Bs += $b;
      $As += $a;
      $numcolors++;
    }

    my $newR = int($Rs/$numcolors);
    my $newG = int($Gs/$numcolors);
    my $newB = int($Bs/$numcolors);
    my $newA = int($As/$numcolors);

    my $newcolor = &hexaRGBcolor($newR, $newG, $newB, $newA);

    return $newcolor

  } else {
    return '#777777';
  }
}

#-----------------------------------------------------------------------------------
# Graphics::MedianColor
# calcul d'une couleur intermédiaire défini par un ratio ($rate) entre 2 couleurs
#-----------------------------------------------------------------------------------
# paramètres :
#  color1 : <color> première couleur zinc
#  color2 : <color> seconde couleur zinc
#    rate : <pourcent> (de 0  à 1) position de la couleur intermédiaire
#-----------------------------------------------------------------------------------
sub MedianColor {
  my ($color1, $color2, $rate) = @_;
  $rate = 1 if ($rate > 1);
  $rate = 0 if ($rate < 0);

  my ($r0, $g0, $b0, $a0) = &ZnColorToRGB($color1);
  my ($r1, $g1, $b1, $a1) = &ZnColorToRGB($color2);

  my $r = $r0 + int(($r1 - $r0) * $rate);
  my $g = $g0 + int(($g1 - $g0) * $rate);
  my $b = $b0 + int(($b1 - $b0) * $rate);
  my $a = $a0 + int(($a1 - $a0) * $rate);

  return &hexaRGBcolor($r, $g, $b, $a);
}


#-----------------------------------------------------------------------------------
# Graphics::ZnColorToRGB
# conversion d'une couleur Zinc au format RGBA (255,255,255,100)
#-----------------------------------------------------------------------------------
# paramètres :
#  zncolor : <color> couleur au format hexa zinc (#ffffff ou #ffffffffffff)
#-----------------------------------------------------------------------------------
sub ZnColorToRGB {
  my ($zncolor) = @_;

  my ($color, $alpha) = split /;/, $zncolor;
  my $ndigits = (length($color) > 8) ? 4 : 2;
  my $R = hex(substr($color, 1, $ndigits));
  my $G = hex(substr($color, 1+$ndigits, $ndigits));
  my $B = hex(substr($color, 1+($ndigits*2), $ndigits));

  $alpha = 100 if (!defined $alpha or $alpha eq "");

  return ($R, $G, $B, $alpha);

}

#-----------------------------------------------------------------------------------
# ALGORYTHMES DE CONVERSION ENTRE ESPACES DE COULEURS
#-----------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------
# Graphics::RGBtoLCH
# Algorythme de conversion RGB -> CIE LCH°
#-----------------------------------------------------------------------------------
# paramètres :
#  r : <pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB
#  g : <pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB
#  b : <pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB
#-----------------------------------------------------------------------------------
sub  RGBtoLCH {
  my ($r, $g, $b) = @_;

  # Conversion RGBtoXYZ
  my $gamma = 2.4;
  my $rgblimit = 0.03928;


  $r = ($r > $rgblimit) ? (($r + 0.055)/1.055)**$gamma : $r / 12.92;
  $g = ($g > $rgblimit) ? (($g + 0.055)/1.055)**$gamma : $g / 12.92;
  $b = ($b > $rgblimit) ? (($b + 0.055)/1.055)**$gamma : $b / 12.92;

  $r *= 100;
  $g *= 100;
  $b *= 100;

  my $X = (0.4124 * $r) + (0.3576 * $g) + (0.1805 * $b);
  my $Y = (0.2126 * $r) + (0.7152 * $g) + (0.0722 * $b);
  my $Z = (0.0193 * $r) + (0.1192 * $g) + (0.9505 * $b);


  # Conversion XYZtoLab
  $gamma = 1/3;
  my ($L, $A, $B);

  if ($Y == 0) {
    ($L, $A, $B) = (0, 0, 0);

  } else {

    my ($Xs, $Ys, $Zs) = ($X/$Xw, $Y/$Yw, $Z/$Zw);
	
    $Xs = ($Xs > 0.008856) ? $Xs**$gamma : (7.787 * $Xs) + (16/116);
    $Ys = ($Ys > 0.008856) ? $Ys**$gamma : (7.787 * $Ys) + (16/116);
    $Zs = ($Zs > 0.008856) ? $Zs**$gamma : (7.787 * $Zs) + (16/116);

    $L = (116.0 * $Ys) - 16.0;

    $A = 500 * ($Xs - $Ys);
    $B = 200 * ($Ys - $Zs);

  }

  # conversion LabtoLCH 
  my ($C, $H);


  if ($A == 0) {
    $H = 0;

  } else {

    $H = atan2($B, $A);
	
    if ($H > 0) {
      $H = ($H / pi) * 180;

    } else {
      $H = 360 - ( abs($H) / pi) * 180
    }
  }


  $C = sqrt($A**2 + $B**2);

  return [$L, $C, $H];

}


#-----------------------------------------------------------------------------------
# Graphics::LCHtoRGB
# Algorythme de conversion CIE L*CH -> RGB
#-----------------------------------------------------------------------------------
# paramètres :
#  L : <pourcent> (de 0 à 1) valeur de la composante luminosité de la couleur CIE LCH
#  C : <pourcent> (de 0 à 1) valeur de la composante saturation de la couleur CIE LCH
#  H : <pourcent> (de 0 à 1) valeur de la composante teinte de la couleur CIE LCH
#-----------------------------------------------------------------------------------
sub LCHtoRGB {
  my ($L, $C, $H) = @_;
  my ($a, $b);

  # Conversion LCHtoLab
  $a = cos( deg2rad($H)) * $C;
  $b = sin( deg2rad($H)) * $C;

  # Conversion LabtoXYZ
  my $gamma = 3;
  my ($X, $Y, $Z);

  my $Ys = ($L + 16.0) / 116.0;
  my $Xs = ($a / 500) + $Ys;
  my $Zs = $Ys - ($b / 200);


  $Ys = (($Ys**$gamma) > 0.008856) ? $Ys**$gamma : ($Ys - 16 / 116) / 7.787;
  $Xs = (($Xs**$gamma) > 0.008856) ? $Xs**$gamma : ($Xs - 16 / 116) / 7.787;
  $Zs = (($Zs**$gamma) > 0.008856) ? $Zs**$gamma : ($Zs - 16 / 116) / 7.787;


  $X = $Xw * $Xs;
  $Y = $Yw * $Ys;
  $Z = $Zw * $Zs;

  # Conversion XYZtoRGB
  $gamma = 1/2.4;
  my $rgblimit = 0.00304;
  my ($R, $G, $B);


  $X /= 100;
  $Y /= 100;
  $Z /= 100;

  $R = (3.2410 * $X) + (-1.5374 * $Y) + (-0.4986 * $Z);
  $G = (-0.9692 * $X) + (1.8760 * $Y) + (0.0416 * $Z);
  $B = (0.0556 * $X) + (-0.2040 * $Y) + (1.0570 * $Z);

  $R = ($R > $rgblimit) ? (1.055 * ($R**$gamma)) - 0.055 : (12.92 * $R);
  $G = ($G > $rgblimit) ? (1.055 * ($G**$gamma)) - 0.055 : (12.92 * $G);
  $B = ($B > $rgblimit) ? (1.055 * ($B**$gamma)) - 0.055 : (12.92 * $B);

  $R = ($R < 0) ? 0 : ($R > 1.0) ? 1.0 : &_trunc($R, 5);
  $G = ($G < 0) ? 0 : ($G > 1.0) ? 1.0 : &_trunc($G, 5);
  $B = ($B < 0) ? 0 : ($B > 1.0) ? 1.0 : &_trunc($B, 5);

  return [$R, $G, $B];

}

#-----------------------------------------------------------------------------------
# Graphics::RGBtoHLS
# Algorythme de conversion RGB -> HLS
#-----------------------------------------------------------------------------------
#  r : <pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB
#  g : <pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB
#  b : <pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB
#-----------------------------------------------------------------------------------
sub RGBtoHLS {
  my ($r, $g, $b) = @_;
  my ($H, $L, $S);
  my ($min, $max, $diff);


  $max = &max($r,$g,$b);
  $min = &min($r,$g,$b);

  # calcul de la luminosité
  $L = ($max + $min) / 2;

  # calcul de la saturation
  if ($max == $min) {
    # couleur a-chromatique (gris) $r = $g = $b
    $S = 0;
    $H = undef;

    return [$H, $L, $S];
  }

  # couleurs "Chromatiques" --------------------

  # calcul de la saturation
  if ($L <= 0.5) {
    $S = ($max - $min) / ($max + $min);

  } else {
    $S = ($max - $min) / (2 - $max - $min);

  }

  # calcul de la teinte
  $diff = $max - $min;

  if ($r == $max) {
    # couleur entre jaune et magenta
    $H = ($g - $b) / $diff;

  } elsif ($g == $max) {
    # couleur entre cyan et jaune
    $H = 2 + ($b - $r) / $diff;

  } elsif ($b == $max) {
    # couleur entre magenta et cyan
    $H = 4 + ($r - $g) / $diff;
  }

  # Conversion en degrés
  $H *= 60;

  # pour éviter une valeur négative
  if ($H < 0.0) {
    $H += 360;
  }

  return [$H, $L, $S];

}


#-----------------------------------------------------------------------------------
# Graphics::HLStoRGB
# Algorythme de conversion HLS -> RGB
#-----------------------------------------------------------------------------------
# paramètres :
#  H : <pourcent> (de 0 à 1) valeur de la composante teinte de la couleur HLS
#  L : <pourcent> (de 0 à 1) valeur de la composante luminosité de la couleur HLS
#  S : <pourcent> (de 0 à 1) valeur de la composante saturation de la couleur HLS
#-----------------------------------------------------------------------------------
sub HLStoRGB {
  my ($H, $L, $S) = @_;
  my ($R, $G, $B);
  my ($p1, $p2);


  if ($L <= 0.5) { 
    $p2 = $L + ($L * $S);
	
  } else {
    $p2 = $L + $S - ($L * $S);

  }

  $p1 = 2.0 * $L - $p2;

  if ($S == 0) {
    # couleur a-chromatique (gris)
    # $R = $G = $B = $L
    $R = $L;
    $G = $L;
    $B = $L;

  } else {
    # couleurs "Chromatiques"
    $R = &hlsValue($p1, $p2, $H + 120);
    $G = &hlsValue($p1, $p2, $H);
    $B = &hlsValue($p1, $p2, $H - 120);
	
  }

  return [$R, $G, $B];

}

#-----------------------------------------------------------------------------------
# Graphics::hlsValue (sous fonction interne HLStoRGB)
#-----------------------------------------------------------------------------------
sub hlsValue {
  my ($q1, $q2, $hue) = @_;
  my $value;

  $hue = &r_modp($hue, 360);

  if ($hue < 60) { 
    $value = $q1 + ($q2 - $q1) * $hue / 60;

  } elsif ($hue < 180) { 
    $value = $q2;

  } elsif ($hue < 240) { 
    $value = $q1 + ($q2 - $q1) * (240 - $hue) / 60;

  } else {
    $value = $q1;

  }

  return $value;

}


#-----------------------------------------------------------------------------------
# Graphics::hexaRGBcolor
# conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
#-----------------------------------------------------------------------------------
sub hexaRGBcolor {
   my ($r, $g, $b, $a) = @_;

   if (defined $a) {
     my $hexacolor = sprintf("#%02x%02x%02x", ($r, $g, $b));
     return ($hexacolor.";".$a);
   }

   return (sprintf("#%02x%02x%02x", ($r, $g, $b)));
}



sub hexa2RGB {
  my ($hexastr) = @_;
  my ($r, $g, $b);

  if ($hexastr =~ /(\w\w)(\w\w)(\w\w)/) {
    $r = hex($1);
    $g = hex($2);
    $b = hex($3);

    return [$r/255, $g/255, $b/255] if (defined $r and defined $g and defined $b);

  }

  return undef;
}

#-----------------------------------------------------------------------------------
# Graphics::max
# renvoie la valeur maximum d'une liste de valeurs
#-----------------------------------------------------------------------------------
sub max {
  my (@values) = @_;
  return undef if !scalar(@values);

  my $max = undef;

  foreach my $val (@values) {
    if (!defined $max or $val > $max) {
      $max = $val;
    }
  }

  return $max;
}


#-----------------------------------------------------------------------------------
# Graphics::min
# renvoie la valeur minimum d'une liste de valeurs
#-----------------------------------------------------------------------------------
sub min {
  my (@values) = @_;
  return undef if !scalar(@values);

  my $min = undef;

  foreach my $val (@values) {
    if (!defined $min or $val < $min) {
      $min = $val;
    }
  }

  return $min;
}


#-----------------------------------------------------------------------------------
# Graphics::r_modp
# fonction interne : renvoie le résultat POSITIF du modulo m d'un nombre x
#-----------------------------------------------------------------------------------
sub r_modp {
  my ($x, $m) = @_;

  return undef if $m == 0;

  my $value = $x%$m;

  if ($value < 0.0) {
    $value = $value + abs($m);
  }

  return $value;

}


1;


__END__

Added jni/tkzinc/Perl/Zinc/Graphics.pod.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

=head1 NAME

Graphics : module Perl facilitant la creation d'objets graphiques complexes 
par une description simplifiee.


=head1 SYNOPSIS

use Graphics;

&GraphicsFunction(@params, ?option => value?, ...);

=head1 DESCRIPTION

Z<>

=head2 Fonctions exportées

=head3 1. Création de composants graphiques

=over

=item B<o> buildZincItem(Z<>)

=item B<o> repeatZincItem(Z<>)

=item B<o> buildTabBoxItem(Z<>)

=back

=head3 2. Calculs de formes géométriques complexes

=over

=item B<o> roundedRectangleCoords(Z<>)

=item B<o> hippodromeCoords(Z<>)

=item B<o> ellipseCoords(Z<>)

=item B<o> roundedCurveCoords(Z<>)

=item B<o> polygonCoords(Z<>)

=item B<o> polylineCoords(Z<>)

=item B<o> curveLineCoords>(Z<>)

=item B<o> pathLineCoords(Z<>)

=item B<o> shiftPathCoords(Z<>)

=item B<o> tabBoxCoords(Z<>)

=back

=head3 3. Création de relief et ombre portée

=over

=item B<o> graphicItemRelief(Z<>)

=item B<o> graphicItemShadow(Z<>)

=back

=head3 4. Fonctions géométriques de base

=over

=item B<o> perpendicularPoint(Z<>)

=item B<o> lineAngle(Z<>)

=item B<o> vertexAngle(Z<>)

=item B<o> arc_pts(Z<>)

=item B<o> rad_point(Z<>)

=item B<o> bezierCompute(Z<>)

=item B<o> bezierSegment(Z<>)

=item B<o> bezierPoint(Z<>)

=back

=head3 5. Gestion des ressources images

=over

=item B<o> getPattern(Z<>)

=item B<o> getTexture(Z<>)

=item B<o> getImage(Z<>)

=item B<o> init_pixmaps(Z<>)

=back

=head3 6. Gestion des couleurs

=over

=item B<o> setGradiants(Z<>)

=item B<o> zincItemPredominantColor(Z<>)

=item B<o> ZnColorToRGB(Z<>)

=item B<o> hexaRGBcolor(Z<>)

=item B<o> createGraduate(Z<>)

=item B<o> MedianColor(Z<>)

=item B<o> LightingColor(Z<>)

=item B<o> RGBtoLCH(Z<>)

=item B<o> LCHtoRGB(Z<>)

=item B<o> RGBtoHLS(Z<>)

=item B<o> HLStoRGB(Z<>)

=back

Z<>

=head2 1. Création de composants graphiques


=over

=item B<buildZincItem>(widget, parentgroup, options);

Creation d'items de representations Zinc.
Les objets graphiques generes peuvent etre complexes (geometrie, multi contours, 
operateur de forme, empilage d'items, reliefs, ombre portee, repetition, 
transformations...) mais sont decrits par des 
options geometriques ou de surfacage 2D 1/2 de haut niveau.

=over
    
=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget zinc.

=item B<parentgroup>

<tagOrId> identifiant de l'item group parent.


=back


=item B<Options> :

						      
=over

=item B<-itemtype> => type

Specifie le(s) type(s) d'item(s) souhaite(s). Peut etre celui d'un item
natif zinc (B<group>, B<rectangle>, B<arc>, B<curve>, B<text>, B<icon>),
ou un B<'metatype'> permettant de specifier des curves 'particulieres'. Les sections coniques
de ces metatypes (raccords ou arcs) seront simulees par des segments quadratiques de bezier. Ces metatypes sont :

=over

=item roundedrectangle

decrit par 2 cordonnees (haut-gauche et bas-droite du rectangle) et un rayon de raccord angulaire.
Une liste optionnelle de realisation des raccords [0 = sans raccord|1 = avec raccord] permet de specifier pour chaque angle le type de raccord
(angle ou arc).

=item hippodrome

decrit par 2 cordonnees (haut-gauche et bas-droite du rectangle englobant).
Si l'orientation n'est pas specifiee, le rayon de raccord sera egal a la moitie du plus petit cote .
Une liste optionnelle de realisation des raccords permet de specifier pour chaque angle le type de raccord
(angle ou arc).

=item ellipse

decrit par 2 cordonnees (haut-gauche et bas-droite du rectangle englobant).  
Une liste optionnelle de realisation des raccords permet de specifier pour chaque angle le type de raccord
(angle ou arc).

=item polygone

polygone regulier a n cotes, (triangle equilateral, carre, pentagone, hexagone...)
convexe ou en etoile. Le polygone sera inscrit dans un cercle dont le rayon est passe en parametres 
(un 2eme rayon 'interne' decrira un polygone etoile). Un rayon de raccord et une liste de realisation des raccords permettent 
des variantes interressantes.

=item roundedcurve

curve multicontours a coins arrondis, de rayon raccord unique,
pour specifier une forme quelconque.

=item polyline

curve multicontours a coins arrondis. Le rayon de chaque raccord pouvant etre defini
specifiquement.

=item pathline

creation d'une ligne multisegments 'epaisse',
realisee par 'decalage' par rapport a un path donne (largeur et sens de decalage
 [left|both|right] optionnels). Le contour transforme en surface avec l'item Zinc triangles
permet d'appliquer un degrade de couleurs le long du trace (lineaire, transversal ou double).

=back


=item B<-coords> => \@xy

<coords list> coordonnees geometriques ou de position de l'item.

=item B<-metacoords> => \%metatype_params

<hashtable> calcul des coordonnées de l'item par passage d'un [meta]type d'item
différent de celui décrit par -itemtype. (ex. un pathline défini par un polygone)

<coords list> coordonnees geometriques ou de position de l'item.

=item B<-params> => \%zinc_attr

<hashtable> parametres zinc de l'item.

=item B<-contours> => \@list

<contours list> arguments zinc d'ajout de contours .

=item B<-clip>

<coords list or hashtable> clipping d'un item group.

=item B<-items>

<hashtable> table d'items contenus dans un item group.
provoque un appel récursif de la fonction buildZincItem().

=item B<-texture>

<imagefile> ajout d'une texture a l'item.

=item B<-pattern>

<imagefile> ajout d'un pattern a l'item.

=item B<-relief>

<hash table> creation d'un relief a l'item a l'aide d'item zinc triangles.
Invoque la fonction du module Graphics graphicItemRelief()

=item B<-shadow>

<hash table> creation d'une ombre portee a l'item.
Invoque la fonction du module Graphics graphicItemShadow()

=item B<-repeat>

<hash table> repetition de l'item.
Invoque la fonction du module Graphics repeatZincItem()

=item B<-scale> => scale factor or [xscale, yscale] 

application d'une transformation zinc->scale a l'item

=item B<-translate> => [dx,dy]

 application d'une transformation zinc->translate a l'item

=item B<-rotate> => <angle> (en degré) 

application d'une transformation zinc->rotate a l'item

=item B<-addtags>

<tags list> liste de tags specifiques a ajouter aux parametre item -tags.

=item B<-name>

<string> nom de l'item.

=back
						      
=back

Z<>

=item B<repeatZincItem>(widget, item, options);

Répétition (clonage) d'un objet Zinc de representation.
    
=over

=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget zinc.

=item B<item>

<tagOrId> identifiant de l'item zinc a dupliquer.

=back

=item B<Options> :
						      
=over

=item B<-num> => integer

Nombre de répétitions.

=item B<-dxy> => [dx, dy]

Paramètres de translation a appliquer entre 2 copies.

=item B<-angle> => <angle>

angle de rotation en degré a appliquer entre 2 copies.

=item B<-copytag> => <tag name>

ajout d'un tag indexé pour chaque copie.

=item B<-params> => \%zinc_attr

Paramétrage specialises de chaque copie


=back

=back

Z<>

=item B<buildTabBoxItem>(widget, parentgroup, options);

Construit les items de représentation d'une boîte à onglets multi-pages. 
Le positionnement, la forme et la taille des onglets est définie automatiquement
ou spécifiés par options. L'ajout de titres aux pages est possible. Des tags
de base (intercalaires et titres) permettent de définir des interactions de 
sélection/navigation par bindings. 

=over
    
=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget zinc.

=item B<parentgroup>

<tagOrId> identifiant de l'item group parent.

=back

=item B<Options> :
						      
=over

=item B<-coords> => [[x0,y0],[x1,y1]]

<coords> coordonnées haut-gauche et bas-droite de la BoundingBox du tabBox.  

=item B<-numpages>

<integer> nombre de pages du TabBox.

=item B<-anchor> => 'n'|'e'|'s'|'w' 

ancrage nord, est, sud ou ouest des onglets (par défaut 'n')

=item B<-alignment> => 'left'|'center'|'right' 

alignement gauche, centré ou droit des onglets sur l'ancrage (par défaut left)

=item B<-tabwidth> => 'auto'|<dimension>|<dimensionList> 

longeur des onglets : 'auto' longeur répartie sur le coté, longeur absolue ou liste de longeurs
ces dimensions sont autoajustées si dépassement. (par défaut 'auto').

=item B<-tabheight> => 'auto'|<dimension> 

hauteur des onglets (par défaut 'auto')

=item B<-tabshift> => 'auto'|<dimension> 

offset de biseau entre la base et le haut de l'onglet (par défaut 'auto').

=item B<-overlap> => 'auto'|<dimension> 

offset de décalage entre 2 onglets (par défaut 'auto').

=item B<-radius>

<dimension> rayon des arrondis d'angle des onglets. (par défaut 0)

=item B<-corners> 

<booleanList> liste d'application du raccord aux angles sous forme booleenne 
0 = sans raccord 1 = avec raccord.

=item B<-params> => \%zinc_attr

<hashtable> parametres zinc de l'item.

=item B<-texture>

<imagefile> ajout d'une texture a l'item.

=item B<-relief>

<hash table> creation d'un relief pour les pages du tabBox.
Invoque la fonction du module Graphics graphicItemRelief()

=item B<-tabtitles>

<hashtable> table de hash de définition des titres d'onglets (label, params).

=item B<-pageitems>

<hashtable> table d'items 'complémentaire' à réaliser pour chaque page.
provoque un appel récursif de la fonction buildZincItem().


=back

=back

=back

Z<>

=head2 2. Calculs de formes géométriques complexes

=over

=item B<roundedRectangleCoords>(coords, options);

Retourne les coordonnées (curve) d'un rectangle à coins arrondis

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],[x1,y1]]

<coordList> coordonnées haut-gauche et bas-droite du rectangle.

=back

=item B<Options> :
						      
=over

=item B<-radius>  

<dimension> rayon de raccord circulaire des angles.

=item B<-corners> => \@cornersList

Liste de réalisation des raccords de sommets [0 = pad de raccord (droit)| 1 = raccord circulaire].
(par défaut [1,1,1,1]).

=back

=back

Z<>

=item B<hippodromeCoords>(coords, options);

Retourne les coordonnées (curve) d'un hippodrome

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],[x1,y1]]

<coordList> coordonnées haut-gauche et bas-droite du rectangle exinscrit à l'hippodrome.

=back

=item B<Options> :
						      
=over

=item B<-orientation>  => <horizontal|vertical>

orientation forcée de l'hippodrome (sinon hauteur = plus petit coté).

=item B<-corners> => \@cornersList

Liste de réalisation des raccords de sommets [0 = pad de raccord (droit)| 1 = raccord circulaire].
(par défaut [1,1,1,1]).

=item B<-trunc>  => <left|right|top|bottom|both>

troncatures des cotés circulaires de l'hippodrome.

=back

=back

Z<>

=item B<ellipseCoords>(coords, options);

Retourne les coordonnées (curve) d'une ellipse

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],[x1,y1]]

<coordList> coordonnées haut-gauche et bas-droite du rectangle exinscrit.

=back

=item B<Options> :
						      
=over

=item B<-corners> => \@cornersList

Liste de réalisation des quadrants [0 = angle droit| 1 = raccord d'ellipse].
(par défaut [1,1,1,1]).

=back

=back

Z<>

=item B<roundedCurveCoords>(coords, options);

Retourne les coordonnées d'une curve à coins arrondis.

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],...[xn,yn]]

<coordList> coordonnées de la curve

=back

=item B<Options> :
						      
=over

B<-radius> : <dimension> 
rayon de raccord des angles. par defaut 0

B<-corners> : <booleanList> 
liste d'application du raccord circulaire aux angles sous forme booleenne 
0 = sans raccord 1 = avec raccord. par defaut [1,1,...,1].

=back

=back

Z<>

=item B<polygonCoords>(coords, options);

Retourne les coordonnées d'un polygone régulier à n cotés ou d'une étoile à
n branches. Le polygone sera inscrit dans un cercle de rayon -radius, un 2ème
rayon interne décrira les sommets interne de l'étoile. Raccords circulaires
optionnels des sommets du polygone/étoile

=over

=item B<Parametres> :

=over

=item B<coords> => [x0,y0]

<coords> coordonnées du centre du cercle exinscrit au polygone/étoile

=back

=item B<Options> :
						      
=over

B<-numsides> : <dimension> nombre de cote du polygone ou nombre de branches de l'etoile

B<-radius> : <dimension> rayon du cercle exinscrit au polygone

B<-startangle> : <angle> angle de depart du trace de la figure

B<-inner_radius> : <dimension> rayon du cercle des points 'internes' de l'etoile

B<-corner_radius> : <dimension> rayon des raccords d'angles

B<-corners> : <booleanList> liste d'application du raccord aux angles sous forme booleenne 
0 = sans raccord 1 = avec raccord. par defaut [1,1,1,1].

=back

=back

Z<>

=item B<polylineCoords>(coords, options);

Retourne les coordonnées d'une polyline, ligne 'brisée' multi-segments
avec raccords angulaires optionnels.

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],...[xn,yn]]

<coordList> liste de coordonnées des sommets de la polyline

=back

=item B<Options> :
						      
=over

B<-radius> : <dimension> 
rayon global de raccord des angles. par defaut 0

B<-corners> : <booleanList> 
liste d'application du raccord circulaire aux angles sous forme booleenne 
0 = sans raccord 1 = avec raccord. par defaut [1,1,...,1].

B<-corners_radius> : <dimensionList> 
Liste des rayons de raccord des angles.

=back

=back

Z<>

=item B<curveLineCoords>(coords, options);

ATTENTION FONCTION EN CHANTIER 

Retourne les coordonnées curve (de surface) d'un stroke. la ligne est décrite 
le long d'un chemin et dessinée selon les attributs graphiques classiques 'stroke'
(style d'épaisseur, d'extremité, de jointure, de tiret...)

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],...[xn,yn]]

<coordList> coordonnées de la curve

=back

=item B<Options> :
						      
=over

B<-width> : <dimension> 
épaisseur de la ligne. par defaut 1

B<-linecap> : <'butt'|'round'|'square'> 
Forme des extrémités des tracés ouverts.

B<-linejoin> : <'miter'|'round'|'bevel'> 
Forme des sommets des tracés.

B<-dasharray> : <'none'|motifList> 
Spécification du tireté : none (aucun) ou liste de longueurs tiret,[espace],[tiret]...
permettant de définir le dessin du tireté (par défaut none)

B<-dashoffset> : <dimension> 
distance décalage de départ dans le dessin du tireté (par défaut 0)

=back

=back

Z<>

=item B<pathLineCoords>(coords, %options);

retourne les coordonnées (triangles) d'une ligne multisegments 'epaisse',
realisee par 'décalage' par rapport à un path donné (largeur et sens de décalage
 [out|center|in] optionnels).

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],...[xn,yn]]

<coordList> liste de coordonnées du path

=back

=item B<Options> :
						      
=over

B<-closed> : <boolean> 
fermeture du tracé. par defaut 0

B<-shifting> : <'out'|'center'|'in'> 
sens de décalage de l'épaisseur de contour : 'center' (1/2 décalage de chaque coté du path) 'out' (décalage externe) 'in' (décalage interne) par défaut 'center'.

B<-width> : <dimension> 
Largeur du décalage de ligne (par défaut 2).

=back

=back

Z<>

=item B<shiftPathCoords>(coords, %options);

retourne les coordonnées curve de 'décalage' par rapport à un path donné.

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],...[xn,yn]]

<coordList> liste de coordonnées du path

=back

=item B<Options> :
						      
=over

B<-closed> : <boolean> 
fermeture du tracé. par defaut 0

B<-shifting> : <'out'|'in'> 
sens de décalage du path : 'out' (décalage externe) 'in' (décalage interne) par défaut 'out'.

B<-width> : <dimension> 
Largeur du décalage de ligne (par défaut 1).

=back

=back

Z<>

=item B<tabBoxCoords>(coords, options);

Retourne les coordonnées de construction d'un TabBox (boîte à onglets) : liste de curve décrivant les 'pages' du TabBox et coordonnées de position des titres onglets. 

=over

=item B<Parametres> :

=over

=item B<coords> => [[x0,y0],[x1,y1]]

<coords> coordonnées haut-gauche et bas-droite de la BoundingBox du tabBox.  

=back

=item B<Options> :
						      
=over

B<-numpages> : <integer> nombre de pages du TabBox.

B<-anchor> : <'n'|'e'|'s'|'w'> ancrage nord, est, sud ou ouest des onglets (par défaut 'n')

B<-alignment> : <'left'|'center'|'right'> alignement gauche, centré ou droit des onglets sur l'ancrage (par défaut left)

B<-tabwidth> : 'auto'|<dimension|dimensionList> longeur des onglets : 'auto' longeur répartie sur le coté, longeur absolue ou liste de longeurs
ces dimensions sont autoajustées si dépassement. (par défaut 'auto').

B<-tabheight> : 'auto'|<dimension> hauteur des onglets (par défaut 'auto')

B<-tabshift> : 'auto'<dimension> offset de biseau entre la base et le haut de l'onglet (par défaut 'auto').

B<-overlap> : 'auto'<dimension> offset de décalage entre 2 onglets (par défaut 'auto').

B<-radius> : <dimension> 
rayon des arrondis d'angle des onglets. (par défaut 0)

B<-corners> : <booleanList> liste d'application du raccord aux angles sous forme booleenne 
0 = sans raccord 1 = avec raccord.

=back

=back

=back

Z<>

=head2 3. Création de reliefs et ombre portée

Z<>

=over

=item B<graphicItemRelief>(widget, item, %options);

Construit un relief à l'item géometrique 
(qui peut etre multicontours) en utilisant des items zinc triangles.
Ce relief de type 'embossage' de forme possede un
profil (flat ou rounded) et dérive en luminosite la couleur dominante
de l'item (ou une couleur donnée) suivant l'orientation d'éclairage global zinc
-lighangle (ou un angle de lumière donné).  

=over
    
=item B<Parametres> :

=over

=item B<widget>

identifiant du widget zinc.

=item B<item>

identifiant de l'item zinc à mettre en relief.

=back

=item B<Options> :
						      
=over

B<-closed> : <boolean> fermeture (de forme) du relief (par défaut 1).

B<-profil> : <'flat'|'rounded'> type de profil du relief (par défaut 'rounded').

B<-relief> : <'raised'|'sunken'> sens de l'embossage (par defaut 'raised').

B<-side> : <outside|inside> position externe ou interne du relief (defaut 'inside').

B<-color> : <color> couleur de base du relief (défaut couleur dominante de l'item).

B<-smoothed> : <boolean> lissage des 'facettes' du relief (par defaut 1).

B<-lightangle> : <angle> angle de la lumiere (par defaut attribut -lightangle du widget).

B<-width> : <dimension> largeur du 'contour' relief.

B<-fine> : <boolean> mode precision courbe de bezier (par defaut 0 : auto-ajustee).

=back

=back

Z<>

=item B<graphicItemShadow>(widget, item, %options);

Cree une ombre portee a l'item geometrique 
(qui peut etre multicontours) en utilisant des items zinc triangles et curve.
Cette ombre correspond a une projection de la forme en fonction
d'une distance (par defaut 10) d'une orientation lumineuse (par defaut la valeur
globale -lightangle du widget) et d'un 'grossissement' (par defaut 0).
Une largeur 'width' de perimetre de diffusion/diffraction lumineuse (par defaut 4) 
qui permet de lisser le passage de l'ombre au fond, une couleur (par defaut black) 
et une opacite (par defaut 50) completent la specification.

=over

B<Parametres> : 

=over

B<widget> : <widget> identifiant du widget zinc

B<item> : <tagOrId> identifiant de l'item zinc

=back

B<Options> :

=over

B<-opacity> : <percent> poucentage d'opacite de l'ombre (par defaut 50).

B<-distance> : <dimension> distance de projection de l'ombre (par defaut 10).

B<-enlarging> : <dimension> 'grossissement' cone de projection (defaut 0).

B<-color> : <color> couleur de l'ombre (par defaut black).

B<-lightangle> : <angle> angle de la lumiere (par defaut attribut -lightangle du widget).

B<-width> : <dimension> largeur du perimetre de diffusion/diffraction (par defaut 4).

=back

=back

=back

Z<>

=head2 4. Fonctions géométriques de base

Z<>

=over

=item B<perpendicularPoint>(point, line);

retourne les coordonnées du point perpendiculaire abaissé d'un point sur une ligne.

=over

=item B<Parametres> :

=over

=item B<point> => [x, y]

<coords> coordonnées du point de référence.

=item B<line> => [[x0, y0],[x1, y1]]

<coordsList> liste de coordonnées des deux points de la ligne de référence.

=back

=back

Z<>


=item B<lineAngle>(startpoint, endpoint);

retourne l'angle formée par un vecteur, s'utilise aussi pour connaitre l'angle 'circulaire' 
d'un point par rapport à un centre de référence.

=over

=item B<Parametres> :

=over

=item B<startpoint> => [x, y]

<coords> coordonnées du point de départ du segment (ou centre de référence).

=item B<endpoint> => [x, y]

<coords> coordonnées du point de fin du segment (ou point 'circulaire' de référence).

=back

=back

Z<>

=item B<lineNormal>(startpoint, endpoint);

retourne la valeur d'angle perpendiculaire à un vecteur (utilisée par exemple 
pour mesurer l'incidence de lumière d'une facette). 

=over

=item B<Parametres> :

=over

=item B<startpoint> => [x, y]

<coords> coordonnées du point de départ du segment (ou centre de référence).

=item B<endpoint> => [x, y]

<coords> coordonnées du point de fin du segment (ou point 'circulaire' de référence).

=back

=back

Z<>

=item B<vertexAngle>(point0, point1, point2);

retourne la valeur de l'angle formé par trois points ainsi que la valeur d'angle
de la bisectrice de l'angle (fonction utilisé pour les calculs de décalages de path.

=over

=item B<Parametres> :

=over

=item B<point0> => [x, y]

<coords> coordonnées du premier point de définition de l'angle.

=item B<point1> => [x, y]

<coords> coordonnées du deuxième point de définition de l'angle (sommet).

=item B<point2> => [x, y]

<coords> coordonnées du troisième point de définition de l'angle.


=back

=back

Z<>

=item B<arc_pts>(center, radius, %options);

Calcul des points constitutifs d'un arc

=over 

=item B<Parametres> :

=over

=item B<center> => [x0,y0]

<coords> coordonnées du centre de l'arc.

=item B<radius>  

<dimension> rayon de l'arc.

=back

=item B<Options> :
						      
=over

=item B<-angle>  

<angle> angle de départ (en degré) de l'arc (par défaut 0)

=item B<-extent>  

<angle> delta angulaire (en degré) de l'arc (par défaut 360)

=item B<-step>

<angle> pas de progression angulaire (en degré) de calcul des points (par défaut 10).

=back

=back

Z<>

=item B<rad_point>(center, radius, angle);

Retourne le point circulaire défini par centre-rayon-angle.

=over

=item B<Parametres> :

=over

=item B<center> => [x0,y0]

<coords> coordonnées du centre de l'arc.

=item B<radius>  

<dimension> rayon de l'arc.

=item B<angle>  

<angle> angle (en degré) du point de circonférence avec le centre du cercle.

=back

=back

Z<>

=item B<bezierSegment>(coords, %options);

Calcul d'une approximation de segment (Quadratique ou Cubique) de bezier.

=over 

=item B<Parametres> :

=over

=item B<coords>

<coordsList> Liste de coordonnées des points définissant le segment de bezier.

=back

=item B<Options> :
						      
=over

=item B<-tunits>  

<integer> nombre pas de division des segments bezier (par défaut 20)

=item B<-skipend>  

<boolean> ne pas retourner le dernier point du segment (pour chaînage de segments).

=back

=back

Z<>

=item B<bezierPoint>(t, coords);

Calcul d'un point du segment (Quadratique ou Cubique) de bezier.
t représentation du temps (de 0 à 1). 
coords = (P1, C1, <C1>, P2) liste des points définissant le segment de bezier
P1 et P2 : extémités du segment et pts situés sur la courbe
C1 <C2> : point(s) de contrôle du segment

courbe bezier niveau 2 sur (P1, P2, P3)   P(t) = (1-t)²P1 + 2t(1-t)P2 + t²P3

courbe bezier niveau 3 sur (P1, P2, P3, P4)  P(t) = (1-t)³P1 + 3t(1-t)²P2 + 3t²(1-t)P3 + t³P4

=over 

=item B<Parametres> :

=over

=item B<t>

<pourcent> (de 0 à 1) représentation du temps.

=item B<coords>

<coordsList> Liste de coordonnées des points définissant le segment de bezier.

=back

=back

Z<>


=item B<bezierCompute>(coords, %options);

Calcul d'une approximation auto-ajustée de segment (Quadratique ou Cubique) de bezier.
l'approximation se fait par subdivision successive de la courbe jusqu'à atteindre une
distance avec la courbe théorique <= à la précision passée par option (par défaut 0.2).

=over 

=item B<Parametres> :

=over

=item B<coords>

<coordsList> Liste de coordonnées des points définissant le segment de bezier.

=back

=item B<Options> :
						      
=over

=item B<-precision>  

<dimension> seuil limite du calcul d'approche de la courbe (par défaut .2)

=item B<-skipend>  

<boolean> ne pas retourner le dernier point du segment (pour chaînage de segments).

=back

=back

=back

Z<>

=head2 5. Gestion des ressources images

Z<>

=over

=item B<getPattern>(filename, %options);

retourne et partage la ressource image bitmap en l'initialisant et la stockant si première utilisation.

=over

=item B<Parametres> :

=over

=item B<filename>

<image filename> non du fichier bitmap pattern

=back

=item B<Options> :
						      
=over

=item B<-storage>  

<hashtable> référence de la table de stockage privée des patterns.

=back

=back

Z<>

=item B<getTexture>(widget, filename, %options);

retourne et partage la ressource image texture en l'initialisant et la stockant si première utilisation.

=over

=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget zinc.

=item B<filename>

<imagefile> non du fichier image texture

=back

=item B<Options> :
						      
=over

=item B<-storage>  

<hashtable> référence de la table de stockage privée des textures.

=back

=back

Z<>

=item B<getImage>(widget, filename, %options);

retourne et partage la ressource image en l'initialisant et la stockant si première utilisation.

=over

=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget zinc.

=item B<filename>

<imagefile> non du fichier image

=back

=item B<Options> :
						      
=over

=item B<-storage>  

<hashtable> référence de la table de stockage privée des images.

=back

=back

Z<>

=item B<init_pixmaps>(widget, filenames, %options);

Initialise et stocke un ensemble d'images.

=over

=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget zinc.

=item B<filenames>

<imagefileList> Liste des fichier images à initialiser.

=back

=item B<Options> :
						      
=over

=item B<-storage>  

<hashtable> référence de la table de stockage privée des images.

=back

=back

=back

Z<>

=head2 6. Gestion des couleurs

Z<>

=over

=item B<setGradients>(widget, gradients);

Création de gradiants nommés Zinc

=over

=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget Zinc

=item B<gradients>  

<hashtable> référence de la table de définition des gradiants zinc ('non' => 'zincGradient').

=back

=back

Z<>

=item B<zincItemPredominantColor>(widget, item);

retourne la couleur dominante d'un item ('barycentre' gradiant fillcolor).

=over

=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget Zinc

=item B<item>  

<tagOrId>  identifiant de l'item zinc.

=back

=back

Z<>

=item B<medianColor>(color1, color2, rate);

calcul d'une couleur intermédiaire défini par un ratio ($rate) entre 2 couleurs.

=over

=item B<Parametres> :

=over

=item B<color1>

<color> première couleur

=item B<color2>  

<color> première couleur

=item B<rate>

<pourcent> (de 0 à 1) position de la couleur intermédiaire.

=back

=back

Z<>

=item B<createGraduate>(widget, steps, refcolors, repeat);

création d'un jeu de couleurs intermédiaires (dégradé) entre n couleurs.

=over

=item B<Parametres> :

=over

=item B<widget>

<widget> identifiant du widget Zinc

=item B<steps>  

<integer> nombre totale de couleurs retournées.

=item B<refcolors>  

<colorList> liste de couleurs servant à créer le dégradé.

=item B<repeat>  

<integer> répétition de chaque couleur utilisé par exemple pour triangles path
où la couleur est répétée 2 fois (par défaut 1).

=back

=back

Z<>

=item B<lightingColor>(color, newL);

Modification d'une couleur par sa composante luminosité (exemple relief).

=over

=item B<Parametres> :

=over

=item B<color>

<color> couleur au format zinc.

=item B<newL>

<pourcent> (de 0 à 1) nouvelle valeur de luminosité.

=back

=back

Z<>

=item B<ZnColorToRGB>(zncolor);

conversion d'une couleur Zinc hexa au format RGBA (255,255,255,100).

=over

=item B<Parametres> :

=over

=item B<zncolor>

<color> couleur au format hexa zinc (#ffffff ou #ffffffffffff).

=back

=back

Z<>

=item B<RGBtoLCH>(r, g, b);

conversion d'une couleur de l'espace RGB à l'espace CIE LCH°.

=over

=item B<Parametres> :

=over

=item B<r>

<pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB.

=item B<g>

<pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB.

=item B<b>

<pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB.

=back

=back

Z<>

=item B<LCHtoRGB>(L, C, H);

conversion d'une couleur de l'espace CIE LCH° à l'espace RGB.

=over

=item B<Parametres> :

=over

=item B<L>

<pourcent> (de 0 à 1) valeur de la composante luminosité de la couleur CIE LCH.

=item B<C>

C : <pourcent> (de 0 à 1) valeur de la composante saturation de la couleur CIE LCH

=item B<H>

H : <pourcent> (de 0 à 1) valeur de la composante teinte de la couleur CIE LCH

=back

=back

Z<>

=item B<RGBtoHLS>(r, g, b);

conversion d'une couleur de l'espace RGB à l'espace HLS.

=over

=item B<Parametres> :

=over

=item B<r>

<pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB.

=item B<g>

<pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB.

=item B<b>

<pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB.

=back

=back

Z<>

=item B<HLStoRGB>(H, L, S);

conversion d'une couleur de l'espace HLS à l'espace RGB.

=over

=item B<Parametres> :

=over

=item B<H>

<pourcent> (de 0 à 1) valeur de la composante teinte de la couleur HLS.

=item B<L>

C : <pourcent> (de 0 à 1) valeur de la composante luminosité de la couleur HLS.

=item B<S>

H : <pourcent> (de 0 à 1) valeur de la composante saturation de la couleur HLS.

=back

=back

Z<>

=item B<hexaRGBcolor>(r, g, b, a);

conversion d'une couleur RGBA (255,255,255,100) au format Zinc '#ffffff'.

=over

=item B<Parametres> :

=over

=item B<r>

<colorComposant> (0 à 255) composante rouge de la couleur rgba.

=item B<g>

<colorComposant> (0 à 255) composante verte de la couleur rgba.

=item B<b>

<colorComposant> (0 à 255) composante bleue de la couleur rgba.

=item B<a>

<colorComposant> (0 à 255) composante alpha de la couleur rgba.

=back

=back

Z<>

=back

Z<>


=head1 EXEMPLE

my %gradset = (
   'gdlens' => '=radial -15 -20|#ffb7b7;70|#bd6622;90',
   'gdstar' => '=radial -15 -20|#ffb7b7;50|#bd6622;90');

my %starstyle => (
       # table hash parametres et options
       -itemtype => 'group',
       -coords => [250, 250],
       -params => {-priority => 90,
                   -tags => ['starlens', 'move'],
                   -sensitive => 1,
                   -atomic => 1,
                   },
       -items => {
           'lens' => {-itemtype => 'hippodrome',
                      -coords => [[-200, -200],
                                  [200, 200]],
                      -params => {-closed => 1,
                                  -filled => 1,
                                  -fillcolor => 'gdlens',
                                  -linewidth => 1.5,
                                  -linecolor => '#440000',
                                  -priority => 10,
                                 },
                      -relief => {-width => 14,
                                  -profil => 'rounded',
                                  -lightangle => 135,
                                  },
                      -shadow => {-distance => 20,
                                  -width => 18,
                                  -lightangle => 135,
                                  -opacity => 40,
                                  -enlarging => 6,
                                 },
                      },
          'star' => {-itemtype => 'polygone',
                     -coords => [0, 0],
                     -numsides => 5,
                     -radius => 180,
                     -inner_radius => 70,
                     -corner_radius => 10,
                     -startangle => 270,
                     -corners => [0,1,0,1,0,1,0,1,0,1],
                     -params => {-filled => 1,
                                 -fillcolor => 'gradstar',
                                 -linewidth => 1,
                                 -linecolor => '#330000',
                                 -priority => 20,
                                },
                     -relief => {-width => 10,
                                 -profil => 'rounded',
                                 -side => 'outside',
                                 -relief => 'sunken',
                                },
                     },
             },
       );


&setGradients($widget, \%gradset);

my $star = &buildZincItem($zinc, $topgroup, \%starstyle);

=head1 AUTEURS

Jean-Luc Vinot <vinot@cena.fr>

Added jni/tkzinc/Perl/Zinc/Logo.pm.





























































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
package Tk::Zinc::Logo;

#---------------------------------------------------------------
#
#  Module          : Logo.pm
#  $Id$
#
#  Copyright (C) 2001-2003
#  Centre d'Études de la Navigation Aérienne
#  Authors: Jean-Luc Vinot <vinot@cena.fr>
#
#---------------------------------------------------------------

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use strict;
use Carp;
use Math::Trig;


my @Gradiants;

# paramètres de construction graphique
my %builder = (-gradset => {'logoshape' => '=axial 270 |#ffffff;100 0 28|#66848c;100 96|#7192aa;100 100',
			    'logopoint' => '=radial -20 -20 |#ffffff;100 0|#f70000;100 48|#900000;100 80|#ab0000;100 100',
			    'logoptshad' => '=path 0 0 |#770000;64 0|#770000;70 78|#770000;0 100',
			    },

	       -shape => {-form => {-itemtype => 'curve',
				    -coords => [[0,0],[106,0],[106,58],[122,41],[156,41],[131,69],[153,99],[203,41],
						[155,41],[155,0],[225.71,0],[251.34,0,'c'],[265.17,29.63,'c'],
						[248.71,49.27],[202,105],[246,105],[246,87],[246,59.385,'c'],[268.38,37,'c'],
						[296,37],[323.62,37,'c'],[346,59.385,'c'],[346,87],[346,148],[305,148],
						[305,87],[305,82.58,'c'],[301.42,79,'c'],[297,79],[292.58,79,'c'],
						[289,82.58,'c'],[289,87],[289,150],[251,150],[251,130],[251,125.58,'c'],
						[247.42,122,'c'],[243,122],[243,122],[238.58,122,'c'],[235,125.58,'c'],
						[235,130],[235,150],[168.12,150],[144.7,150,'c'],[132.38,122.57,'c'],
						[147.94,105.06],[148,105],[120,105],[104,81],[104,105],[74,105],[74,41],
						[52,41],[52,105],[20,105],[20,41],[0,41]],

				    -contour => ['add', -1, [[395,78],[395,37],[364.62,37,'c'],[340,61.62,'c'],[340,92],
							    [340,93],[340,123.38,'c'],[364.62,148,'c'],[395,148],[409,148],
							    [409,107],[395,107],[386.72,107,'c'],[380,100.28,'c'],[380,92],
							    [380,93],[380,84.72,'c'],[386.72,78,'c'],[395,78]]],


				    -params => {-closed => 0,
						-filled => 1,
						-visible => 1,
						-fillcolor => 'logoshape',
						-linewidth => 2.5,
						-linecolor => '#000000',
						-priority => 40,
						-fillrule => 'nonzero',
						-tags => ['zinc_shape'],
					       },
				   },

			  -shadow => {-clone => '-form',
				      -translate => [6, 6],
				      -params => {-fillcolor => '#000000;18',
						  -linewidth => 0,
						  -priority => 20,
						 },
				     },
			 },

	       -point => {-coords => [240, 96],
			  -params => {-alpha => 80,
				      -priority => 100,
				     },

			  -form => {-itemtype => 'arc',
				    -coords => [[-20, -20], [20, 20]],
				    -params => {-priority => 50,
						-filled => 1,
						-linewidth => 1,
						-linecolor => '#a10000;100',
						-fillcolor => 'logopoint',
						-closed => 1,
					       },
				   },

			  -shadow => {-clone => '-form',
				      -translate => [5, 5],
				      -params => {-fillcolor => 'logoptshad',
						  -linewidth => 0,
						  -priority => 20,
						 },
				     },
			 },
	      );



sub new {
    my $proto = shift;
    my $type = ref($proto) || $proto;
    my %params = @_;

    my $self = {};
    bless ($self, $type);
    if (exists $params{'-widget'}) {
	$self->{'-widget'} = $params{'-widget'};
    } else {
	croak "in Tk::Zinc::Logo constructor, the -widget attribute must be defined\n";
    }
    $self->{'-parent'} = (exists $params{'-parent'}) ? $params{'-parent'} : 1;
    $self->{'-priority'} = (exists $params{'-priority'}) ? $params{'-priority'} : 500;
    $self->{'-position'} = (exists $params{'-position'}) ? $params{'-position'} : [0, 0];
    $self->{'-scale'} = (exists $params{'-scale'}) ? $params{'-scale'} : [1, 1];

    $self->drawLogo();

    return bless $self, $type;
}



sub drawLogo {
  my ($self) = @_;
  my $zinc = $self->{'-widget'}; 
  my $parent = $self->{'-parent'};
  my $priority = $self->{'-priority'};


  if ($builder{'-gradset'}) {
    while (my ($name, $gradiant) = each( %{$builder{'-gradset'}})) {
      # création des gradiants nommés
      $zinc->gname($gradiant, $name) unless $zinc->gname($name);
      push(@Gradiants, $name);
    }
  }

  # création des groupes logo
  # logogroup : groupe de coordonnées
  my $logogroup =  $self->{'-item'} = $zinc->add('group', $parent, -priority => $priority);
  $zinc->coords($logogroup, $self->{'-position'}) if ($self->{'-position'});

  # group de scaling
  my $group = $self->{'-scaleitem'} = $zinc->add('group', $logogroup);
  $zinc->scale($group,  @{$self->{'-scale'}}) if ($self->{'-scale'});


  # création de l'item shape (Zinc)
  my $formstyle = $builder{'-shape'}->{'-form'};
  $self->ajustLineWidth($formstyle->{'-params'});
  my $shape = $zinc->add('curve', $group,
			$formstyle->{'-coords'},
			%{$formstyle->{'-params'}},
		       );

  $zinc->contour($shape, @{$formstyle->{'-contour'}});

  # ombre portée de la shape
  my $shadstyle = $builder{'-shape'}->{'-shadow'};
  my $shadow = $zinc->clone($shape, %{$shadstyle->{'-params'}});
  $zinc->translate($shadow, @{$shadstyle->{'-translate'}}) if ($shadstyle->{'-translate'});

  # réalisation du point
  my $pointconf = $builder{'-point'};
  my $ptgroup = $zinc->add('group', $group, %{$pointconf->{'-params'}});
  $zinc->coords($ptgroup,  $pointconf->{'-coords'});

  my $pointstyle =  $pointconf->{'-form'};
  my $point = $zinc->add('arc', $ptgroup,
			 $pointstyle->{'-coords'},
			 %{$pointstyle->{'-params'}},
			 );

  my $shadpoint = $zinc->clone($point, %{$shadstyle->{'-params'}});
  $shadstyle = $pointconf->{'-shadow'};
  $zinc->translate($shadpoint, @{$shadstyle->{'-translate'}});

}


sub ajustLineWidth {
  my ($self, $style, $scale) = @_;

  if ($style->{'-linewidth'}) {
    my ($sx, $sy) = @{$self->{'-scale'}};
    my $linewidth = $style->{'-linewidth'};
    if ($linewidth >= 2) {
      my $ratio = ($sx > $sy) ? $sy : $sx;
      $style->{'-linewidth'} = $linewidth * $ratio;
    }
  }
}

1;

__END__

=head1 NAME

Tk::Zinc::Logo - a perl module for drawing the TkZinc logo. 


=head1 SYNOPSIS

 use Tk::Zinc::Logo;
 my $zinc = MainWindow->new()->Zinc()->pack;
 my $logo = $zinc->ZincLogo([options]);



=head1 OPTIONS 

=over

=item B<-parent> => zinc group

Specify the parent group. Default is 1.

=item B<-position> => [x, y]

Specify the relative position of the logo in its parent group. Default is [0, 0].

=item B<-priority> => integer

Specify the priority of the logo in its parent group. Default is 500.

=item B<-scale> => [sx, sy]

Scecify the xscale and yscale factors of the logo. Default is [1, 1].


=back
    

=head1 AUTEUR

Jean-Luc Vinot <vinot@cena.fr>



Added jni/tkzinc/Perl/Zinc/Text.pm.













































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
package Tk::Zinc::Text;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


sub new {
  my $proto = shift;
  my $type = ref($proto) || $proto;
  my ($zinc) = @_;
  my $self = {};

  $zinc->bind('text', '<1>' => sub {startSel($zinc)});
  $zinc->bind('text', '<2>' => sub {pasteSel($zinc)});
  $zinc->bind('text', '<B1-Motion>' => sub {extendSel($zinc)});
  $zinc->bind('text', '<Shift-B1-Motion>' => sub {extendSel($zinc)});
  $zinc->bind('text', '<Shift-1>' => sub {
		my $e = $zinc->XEvent();
		my($x, $y) = ($e->x, $e->y);
		$zinc->select('adjust', 'current', "\@$x,$y"); });
  $zinc->bind('text', '<Left>' => sub {moveCur($zinc, -1);});
  $zinc->bind('text', '<Right>' => sub {moveCur($zinc, 1);});
  $zinc->bind('text', '<Up>' => sub {setCur($zinc, 'up');});
  $zinc->bind('text', '<Down>' => sub {setCur($zinc, 'down');});
  $zinc->bind('text', '<Control-a>' => sub {setCur($zinc, 'bol');});
  $zinc->bind('text', '<Home>' => sub {setCur($zinc, 'bol');});
  $zinc->bind('text', '<Control-e>' => sub {setCur($zinc, 'eol');});
  $zinc->bind('text', '<End>' => sub {setCur($zinc, 'eol');});
  $zinc->bind('text', '<Meta-less>' => sub {setCur($zinc, 0);});
  $zinc->bind('text', '<Meta-greater>' => sub {setCur($zinc, 'end');});
  $zinc->bind('text', '<KeyPress>' => sub {insertKey($zinc);});
  $zinc->bind('text', '<Shift-KeyPress>' => sub {insertKey($zinc);});
  $zinc->bind('text', '<Return>' => sub { insertChar($zinc, chr(10)); });
  $zinc->bind('text', '<BackSpace>' => sub {textDel($zinc, -1)});
  $zinc->bind('text', '<Control-h>' => sub {textDel($zinc, -1)});
  $zinc->bind('text', '<Delete>' => sub {textDel($zinc, 0)});

  bless ($self, $type);
  return $self;
}


sub pasteSel {
  my ($w) = @_;
  my $e = $w->XEvent;
  my($x, $y) = ($e->x(), $e->y());
  my @it = $w->focus();

  if (@it != 0) {
    eval { $w->insert(@it, "\@$x,$y", $w->SelectionGet()); };
  }
}


sub insertChar {
  my ($w, $c) = @_;
  my @it = $w->focus();
  my @selit = $w->select('item');

  if (@it == 0) {
    return;
  }

  if ((scalar(@selit) == scalar(@it)) &&
      ($selit[0] eq $it[0]) && ($selit[1] eq $it[1])) {
    $w->dchars(@it, 'sel.first', 'sel.last');
  }
  $w->insert(@it, 'insert', $c);
}


sub insertKey {
  my ($w) = @_;
  my $c = $w->XEvent->A();

  if ((ord($c) < 32) || (ord($c) == 128)) {
    return;
  }

  insertChar($w, $c);
}


sub setCur {
  my ($w, $where) = @_;
  my @it = $w->focus();

  if (@it != 0) {
    $w->cursor(@it, $where);
  }
}


sub moveCur {
  my ($w, $dir) = @_;
  my @it = $w->focus();
  my $index;

  if (@it != 0) {
    $index = $w->index(@it, 'insert');
    $w->cursor(@it, $index + $dir);
  }
}


sub startSel {
  my($w) = @_;
  my $e = $w->XEvent;
  my($x, $y) = ($e->x(), $e->y());
  my $part = $w->currentpart(1);

  $w->cursor('current', $part, "\@$x,$y");
  $w->focus('current', $part);
  $w->Tk::focus();
  $w->select('from', 'current', $part, "\@$x,$y");
}


sub extendSel {
  my($w) = @_;
  my $e = $w->XEvent;
  my($x, $y) = ($e->x, $e->y);
  my $part = $w->currentpart(1);

  $w->select('to', 'current', $part, "\@$x,$y");
}


sub textDel {
  my($w, $dir) = @_;
  my @it = $w->focus();
  my @selit = $w->select('item');
  my $ind;

  if (@it == 0) {
    return;
  }

  if ((scalar(@selit) == scalar(@it)) &&
      ($selit[0] eq $it[0]) && ($selit[1] eq $it[1])) {
    $w->dchars(@it, 'sel.first', 'sel.last');
  }
  else {
    $ind = $w->index(@it, 'insert') + $dir;
    $w->dchars(@it, $ind, $ind) if ($ind >= 0);
  }
}

1;
__END__

=head1 NAME

Tk::Zinc::Text - Zinc extension for easing text input on text item or on fields

=head1 SYNOPSIS

 use Tk::Zinc::Text;

 $zinc = $mw->Zinc();
 new Tk::Zinc::Text ($zinc);
 ....
 $zinc->addtag('text', 'withtag', $a_text);
 $zinc->addtag('text', 'withtag', $a_track);
 $zinc->addtag('text', 'withtag', $a_waypoint);
 $zinc->addtag('text', 'withtag', $a_tabular);

=head1 DESCRIPTION

This module implements text input with the mouse and keyboard 'a la emacs'.
Text items must have the 'text' tag and must of course be sensitive.
Track, waypoint and tabular items have fields and these fields can
be edited the same way. Only sensitive fields can be edited. the following
interactions are supported:

=over 2

=item B<click 1>

To set the cursor position

=item B<click 2>

To paste the current selection

=item B<drag 1>

To make a selection

=item B<shift drag 1>

To extend the current selection

=item B<shift 1>

To extend the current selection

=item B<left arrow>, B<right arrow>

To move the cursor to the left or to the right

=item B<up arrow>, B<down arrow>

To move the cursor up or down a line

=item B<ctrl+a>, B<home>

To move the cursor at the begining of the line

=item B<ctrl+e>, B<end>

To move the cursor at the end of the line

=item B<meta+<>, B<meta+E<gt>>

To move the cursor at the beginning / end of the text

=item B<BackSpace>, B<ctrl+h>

To delete the char just before the cursor

=item B<Delete>

To delete the char just after the cursor

=item B<Return>

To insert a return char. This does not validate the input!

=back

=head1 BUGS

No known bugs at this time. If you find one, please report them to the authors.

=head1 SEE ALSO

perl(1), Tk(1), Tk::Zinc(3), zinc-demos(1)

=head1 AUTHORS

Patrick Lecoanet <lecoanet@cena.fr>
(and some documentation by Christophe Mertz <mertz@cena.fr>)

=head1 COPYRIGHT

CENA (C) 2002

Tk::Zinc::Text is part of Zinc and has been developed by the CENA (Centres d'Etudes de la Navigation Aérienne)
for its own needs in advanced HMI (Human Machine Interfaces or Interactions). Because we are confident
in the benefit of free software, the CENA delivered this toolkit under the GNU
Library General Public License.

This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MER­CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library
General Public License for more details.

=head1 HISTORY

June 2002 : initial release with Zinc-perl 3.2.6

=cut

Added jni/tkzinc/Perl/Zinc/Trace.pm.







































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1995-1999 Nick Ing-Simmons. All rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself, subject
# to additional disclaimer in Tk/license.terms due to partial
# derivation from Tk8.0 sources.
#
# Copyright (c) 2002 CENA, C.Mertz <mert@cena.fr> to trace all
# Tk::Zinc methods calls as well as the args in a human readable
# form. Updated by D.Etienne.
#
# This package overloads the Tk::Methods function in order to trace
# every Tk::Zinc method call in your application.
#
# This may be very usefull when your application segfaults and
# when you have no idea where this happens in your code.
#
# $Id$
#
# To trap Tk::Zinc errors, use rather the Tk::Zinc::TraceErrors package.
#
# for using this file do some thing like :
# perl -MTk::Zinc::Trace myappli.pl

package Tk::Zinc::Trace;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use vars qw( $ForReplay );

use Tk;
use strict;
use Tk::Zinc::TraceUtils;

my $WidgetMethodfunction;
my %moduleOptions;


BEGIN {
    if (defined $ZincTraceErrors::on && $ZincTraceErrors::on == 1) {
	print STDERR "Tk::Zinc::Trace: incompatible package Tk::Zinc::TraceErrors is already ".
	    "loaded (exit 1)\n";
	exit 1;
    }
    print "## Tk::Zinc::Trace ON\n";
    $ZincTrace::on = 1;
    require Getopt::Long;
    Getopt::Long::Configure('pass_through');
    Getopt::Long::GetOptions(\%moduleOptions, 'code');
    $ForReplay=1 if defined $moduleOptions{code} ;
    select STDOUT; $|=1; ## for flushing the trace output
    # save current Tk::Zinc::InitObject function; it will be invoked in
    # overloaded one (see below)
    use Tk;
    use Tk::Zinc;
    $WidgetMethodfunction = Tk::Zinc->can('WidgetMethod');
    
}

print "## following trace should be very close to a replay-script code\n" if $ForReplay;

my $ZincCounter= "";
my %ZincHash;

#sub Tk::Zinc {
#    print "CREATING Zinc : @_";
#    &$ZincCreationMethodfunction;
#}

sub Tk::Zinc::WidgetMethod {
    my ($zinc, $name, @args) = @_;
    if (defined $Tk::Zinc::Trace::off and $Tk::Zinc::Trace::off > 0) {
	return &$WidgetMethodfunction(@_) if $WidgetMethodfunction;
    }
    my ($package, $filename, $line) = caller(1);
    $package="" unless defined $package;
    $filename="" unless defined $filename;
    $line="" unless defined $line;
    my $widget;
    if (defined $ZincHash{$zinc}) {
	$widget = $ZincHash{$zinc};
    } elsif ($ZincCounter) {
	$ZincHash{$zinc} = '$zinc'.$ZincCounter;
	$widget = '$zinc'.$ZincCounter;
	$ZincCounter++;
    } else {
	$ZincHash{$zinc} = '$zinc';
	$widget = '$zinc';
	$ZincCounter=1; # for the next zinc
    }
    
    if ($ForReplay) {
	print "$widget->$name";
    } else {
	print "TRACE: $filename line $line $name";
    }

    &printList(@args);
    # invoke function possibly overloaded in other modules
    if (wantarray()) {
	my @res = &$WidgetMethodfunction(@_) if $WidgetMethodfunction;
	if ($ForReplay) {
	    print ";\n";
	} else {
	    print "  RETURNS ";
	    &printList (@res);
	    print "\n";
	}
	$zinc->update;
	return @res;
    } else {
	my $res = &$WidgetMethodfunction(@_) if $WidgetMethodfunction;
	if ($ForReplay) {
	    print ";\n";
	} else {
	    print "  RETURNS ";
	    &printItem ($res);
	    print "\n";
	}
	$zinc->update;
	return $res;
    }
}
    
1;


__END__

=head1 NAME

Tk::Zinc::Trace - A module to trace all Tk::Zinc method calls

=head1 SYNOPSIS

use Tk::Zinc::Trace;
$Tk::Zinc::Trace:ForReplay = 1;

or

perl -MTk::Zinc::Trace YourZincBasedScript.pl [--code]

=head1 DESCRIPTION

When loaded, this module overloads a Tk mechanism so that every
Tk::Zinc method call will be traced. Every call will also be followed by a
$zinc->update() so that the method call will be effectively treated.

This module can be very effective for debugging when Tk::Zinc
core dumps and you have no clue which method call can be responsible for. If
you just want to trace Tk::Zinc errors when calling a method you
should rather use the Tk::Zinc::TraceErrors module

The global variable $Tk::Zinc::Trace:off can be used to trace some specific blocks. If set to 1, traces are deactivated, if set to 0, traces are reactivated.
    
If the global variable $Tk::Zinc::Trace:ForReplay is set or if the --code
option is set in the second form, the printout will be very close to re-executable
code, like this:

 ## following trace should be very close to a replay-script code
 $zinc->configure(-relief => 'sunken', -borderwidth => 3,
		  -width => 700, -font => 10x20, -height => 600);
 $zinc->add('rectangle', 1, [10, 10, 100, 50],
	    -fillcolor => 'green', -filled => 1, -linewidth => 10,
	    -relief => 'roundridge', -linecolor => 'darkgreen');
 $zinc->add('text', 1, -font => -adobe-helvetica-bold-r-normal-*-120-*-*-*-*-*-* =>
	    -text => 'A filled rectangle with a "roundridge" relief border of 10 pixels.',
	    -anchor => 'nw', -position => [120, 20]);
 $zinc->add('track', 1, 6,
	    -labelformat => 'x82x60+0+0 x60a0^0^0 x32a0^0>1 a0a0>2>1 x32a0>3>1 a0a0^0>2',
	    -position => [20, 120], -speedvector => [40, -10], -speedvectormark => 1, -speedvectorticks => 1);
 $zinc->coords(4, [20, 120]);

    
If not (the default), the printout will be more informtative, giving
the following information:
    
=over 6

=item * the source filename where the method has been invoked

=item * the line number in the source file

=item * the TkZinc method name

=item * the list of arguments in a human-readable form

=item * the returned value

=back

The trace will look like:

 ## Tk::Zinc::Trace ON
 TRACE: /usr/lib/perl5/Tk/Widget.pm line 196 configure(-relief => 'sunken', -borderwidth => 3, -width => 700, -font => 10x20, -height => 600)  RETURNS undef
 TRACE: Perl/demos/demos/zinc_lib/items.pl line 21 add('rectangle', 1, [10, 10, 100, 50], -fillcolor => 'green', -filled => 1, -linewidth => 10, -relief => 'roundridge', -linecolor => 'darkgreen')  RETURNS 2
 TRACE: Perl/demos/demos/zinc_lib/items.pl line 25 add('text', 1, -font => -adobe-helvetica-bold-r-normal-*-120-*-*-*-*-*-* => -text => 'A filled rectangle with a "roundridge" relief border of 10 pixels.', -anchor => 'nw', -position => [120, 20])  RETURNS 3
 TRACE: Perl/demos/demos/zinc_lib/items.pl line 36 add('track', 1, 6, -labelformat => 'x82x60+0+0 x60a0^0^0 x32a0^0>1 a0a0>2>1 x32a0>3>1 a0a0^0>2', -position => [20, 120], -speedvector => [40, -10], -speedvectormark => 1, -speedvectorticks => 1)  RETURNS 4

=head1 AUTHOR

C.Mertz <mertz@cena.fr> and D.Etienne <etienne@cena.fr>

=head1 CAVEATS and BUGS

This module cannot be used when Tk::Zinc::TraceErrors is already in use.

As every Tk::Zinc method call is followed by an ->update call, this may
dramatically slowdown an application. The trade-off is between application
run-time and developper debug-time.

When using an output "code-like" they are still part of the output which is
not executable code. However, the ouptut could be easily and manually
edited to be executable perl code.

=head1 COPYRIGHT

See Tk::Zinc copyright; BSD

=head1 SEE ALSO

L<Tk::Zinc(3pm)>, L<Tk::Zinc::TraceErrors(3pm)>. L<Tk::Zinc::Debug(3pm)>.

=cut

Added jni/tkzinc/Perl/Zinc/TraceErrors.pm.











































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#
# Copyright (c) 1992-1994 The Regents of the University of California.
# Copyright (c) 1994 Sun Microsystems, Inc.
# Copyright (c) 1995-1999 Nick Ing-Simmons. All rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself, subject
# to additional disclaimer in Tk/license.terms due to partial
# derivation from Tk8.0 sources.
#
# Copyright (c) 2003 CENA, D.Etienne <etienne@cena.fr> to trace all
# Tk::Zinc errors.
#
# This package overloads the Tk::Zinc::WidgetMethods function in order to
# to trap errors by calling every Tk::Zinc method in an eval() block.
#
# This may be very usefull when your application encounters errors such as
# "error .... at /usr/lib/perl5/Tk.pm line 228". With ZincTraceErrors, the
# module name, the line number and the complete error messages are reported
# for each error.
#
# $Id$
#
# When you have no idea where this happens in your code or when your
# application segfaults, use the Tk::Zinc::Trace package which traces every
# Tk::Zinc method call.
#
# for using this file do some thing like :
# perl -MTk::Zinc::TraceErrors myappli.pl

package Tk::Zinc::TraceErrors;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use strict;
use Tk::Zinc::TraceUtils;

my $WidgetMethodfunction;
my $bold = "";
my $_bold = "";

BEGIN {
    my $bold = "";
    my $_bold = "";
    
    if (defined $ZincTrace::on and $ZincTrace::on == 1) {
	print STDERR $bold."Tk::Zinc::TraceErrors: incompatible package Tk::Zinc::Trace is already ".
	    "loaded".$_bold." (exit 1)\n";
	exit 1;
    }
    print $bold."Tk::Zinc::TraceErrors is ON".$_bold."\n";
    $ZincTraceErrors::on = 1;
    select STDOUT; $|=1; ## for flushing the trace output
    # save current Tk::Zinc::InitObject function; it will be invoked in
    # overloaded one (see below)
    use Tk;
    use Tk::Zinc;
    $WidgetMethodfunction = Tk::Zinc->can('WidgetMethod');
    
}

sub Tk::Zinc::WidgetMethod {
    my ($zinc, $name, @args) = @_;
    my ($package, $filename, $line) = caller(1);
    $package="" unless defined $package;
    $filename="" unless defined $filename;
    $line="" unless defined $line;
    # invoke function possibly overloaded in other modules
    my ($res, @res);
    if (wantarray()) {
	eval {@res = &$WidgetMethodfunction(@_) if $WidgetMethodfunction;};
    } else {
	eval {$res = &$WidgetMethodfunction(@_) if $WidgetMethodfunction;};
    }
    if ($@) {
	print $bold."error:".$_bold." $filename line $line $name";
	&printList (@args);
	my $msg = $@;
	$msg =~ s/at .*//g;
	print " ".$bold."returns".$_bold." $msg\n";
    }
    if (wantarray()) {
	return @res;
    } else {
	return $res;
    }
}
    
    

1;


__END__

=head1 NAME

Tk::Zinc::TraceErrors - A module to trace all Tk::Zinc method calls which generate an error

=head1 SYNOPSIS

use Tk::Zinc::TraceErrors;

or

perl -MTk::Zinc::TraceErrors YourZincBasedScript.pl

=head1 DESCRIPTION

When loaded, this module overloads a Tk mechanism so that every
Tk::Zinc method call will be traced if it provokes an error. The execution
will then continue.

This module can be very effective for debugging and application, specially
when Tk gives an unusuable error message such as ".... errors in Tk.pm line 228"
    
=over 6

=item * the source filename where the method has been invoked

=item * the line number in the source file

=item * the TkZinc method name

=item * the list of arguments in a human-readable form

=item * the error message

=back

=head1 AUTHOR

D.Etienne <etienne@cena.fr> and C.Mertz <mertz@cena.fr>

=head1 CAVEAT

This module cannot be used when Tk::Zinc::Trace is already in use.

=head1 COPYRIGHT

See Tk::Zinc copyright; BSD

=head1 SEE ALSO

L<Tk::Zinc(3pm)>, L<Tk::Zinc::Trace(3pm)>. L<Tk::Zinc::Debug(3pm)>.

=cut

Added jni/tkzinc/Perl/Zinc/TraceUtils.pm.







































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package Tk::Zinc::TraceUtils;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Font;
use Tk::Photo;

require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(printItem printArray printList Item Array List);

use strict;

sub printItem {
    print &Item (@_);
}

sub printArray {
    print &Array (@_);
}

sub printList {
    print &List (@_);
}


### to print something
sub Item {
    my ($value) = @_;
    my $ref = ref($value);
#    print "VALUE=$value REF=$ref\n";
    if ($ref eq 'ARRAY') {
	return Array ( @{$value} );
    } elsif ($ref eq 'CODE') {
	return "{CODE}";
    } elsif ($ref eq 'Tk::Photo') {
#	print " **** $value ***** ";
	return "Tk::Photo(\"". scalar $value->cget('-file') . "\")";
    } elsif ($ref eq 'Tk::Font') {
	return "'$value'";
    } elsif ($ref eq '') {  # scalar 
	if (defined $value) {
          if ($value =~ /^-[a-zA-Z]([\w])*$/) { # -option1 or -option-1
            return $value;
          } elsif ($value =~ /^-?\d+(\.\d*(e[+-]?\d+)?)?$/) { # -1. or 1.0 or -1.2e+22  or 1.02e+034
            if ($value =~ /(.*[-+]e)0+(\d+)/) {   # removing the 0 after e+ or e-
              return $1.$2;
            } else {
              return $value;
            }
          } elsif ($value eq ''
                   or $value =~ /\s/
                   or $value =~ /^[a-zA-Z]/
                   or $value =~ /^[\W]/
                  ) {
            return "'$value'";
          } else {
            return $value;
          }
	} else {
	    return "_undef";
	}
    } else { # some  class instance
	return $value;
    }
    
} # end Item


### to print a list of something
sub Array {
    my (@values) = @_;
    if (! scalar @values) {
	return "[]";
    }
    else {  # the list is not empty
	my $res = "[";
	while (@values) {
	    my $value = shift @values;
	    $res .= &Item ($value);
	    $res .= ", " if (@values);
	}
	return $res. "]" ;
    }
    
} # end Array


sub List {
    my $res = "(";
    while (@_) {
	my $v = shift @_;
	$res .= Item ($v);
	if (@_ > 0) {
	    ## still some elements
	    if ($v =~ /^-\d+$/) {
		$res .= ", ";
	    } elsif ($v =~ /^-\w+$/) {
		$res .= " => ";
	    } else {
		$res .= ", ";
	    }
	}
    }
    return $res. ")";
    
} # end List


1;



Added jni/tkzinc/Perl/demos/Makefile.PL.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
use ExtUtils::MakeMaker;
WriteMakefile(
	      'EXE_FILES' => ['zinc-demos'],
	      'PMLIBDIRS' => [ qw( Tk/demos/zinc_pm Tk/demos/zinc_contrib_lib
				   Tk/demos/zinc_data Tk/demos/zinc_lib ) ],
      );
 

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_contrib_lib/README.



>
1
This directory is for deposing zinc demos contribs

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_contrib_lib/TripleRotatingWheel.pl.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
#!/usr/bin/perl
# TripleRotatingWheel gambling game contributed by "zentara"

# Idea derived from the wheelOfFortune.pl demo by D. Etienne etienne@cena.fr
# $Id$ 


use Tk; 
use Tk::Zinc;

my @win =(); # an array to store winning wheel values, can range from
             # () to (1,1,1) 

# We create a classical root widget called MainWindow; then we create Zinc 
# widget child with size, color and relief attributes, and we display it using
# the geometry manager called 'pack'.
my $mw = MainWindow->new;
$mw->geometry("700x600");

$mw->resizable(0,0);

my $zinc = $mw->Zinc(-width => 700, -height => 565,
                    -backcolor => 'black',
		     -borderwidth => 3, -relief => 'sunken');
$zinc->pack;

# Then we create a gray filled rectangle, in which we will display explain text.
$zinc->add('rectangle', 1 , [200, 400, 490, 490],
	   -linewidth => 2,
	   -filled => 1,
	   -fillcolor => 'SkyBlue',
	   );
my $text = $zinc->add('text', 1,
		      -position => [350, 445],
		      -anchor => 'center',
		      );

$zinc->add('rectangle', 1 , [250,275,450,325], #(xpos1,ypos1,xpos2,ypos2)
	   -linewidth => 2,
	   -filled => 1,
	   -fillcolor => 'Orange',
	   );

my $wintext = $zinc->add('text', 1,
		      -position => [350, 300],
		      -anchor => 'center',
		      );

#create winning wheel markers
#create first triangle, then clone and translate
my $tr1 = $zinc->add('triangles', 1,
                     [0,20,20,20,10,50],
                     -fan => 1,
                     -colors => 'Orange',
                     -visible => 1,
                     );
my $tr2 = $zinc->clone($tr1);
my $tr3 = $zinc->clone($tr1);
$zinc->translate($tr1,130,0);
$zinc->translate($tr2,340,0);
$zinc->translate($tr3,550,0);



# Create the Wheel object (see Wheel.pm)
my $wheel1 = Wheel->new($zinc, 350, 500,  100); #start xpos,ypos,mag
my $wheel2 = Wheel->new($zinc, 350, 500, 100);
my $wheel3 = Wheel->new($zinc, 350, 500, 100);

# Display comment
&comment("Strike any key to begin");
&wincomment("READY");

# Create Tk binding
$mw->Tk::bind('<Key>', \&openmode);


MainLoop;

# Callback bound to '<Key>' event when wheel is unmapped
sub openmode {
    # set binding to unmap the wheel
    $mw->Tk::bind('<Key>', \&closemode);
    # set binding to rotate the hand
    $zinc->bind($wheel1, '<1>', sub {spin()}); 
    $zinc->bind($wheel2, '<1>', sub {spin()});    
    $zinc->bind($wheel3, '<1>', sub {spin()});    
    # map the wheel
    $wheel1->show(140, 150);
    $wheel2->show(350, 150);
    $wheel3->show(560, 150);
    
    # and then inform user
    &comment("Click on any wheel to play.\n".
	     "Strike any key to hide the wheels.");
}

sub spin {
    return if $wheel1->ismoving;
    return if $wheel2->ismoving;
    return if $wheel3->ismoving;

  @win=();
  &wincomment("PLAYING");
          $wheel1->rotatewheel(int rand(360));
          $wheel2->rotatewheel(int rand(360));
	  $wheel3->rotatewheel(int rand(360));
#  print "\@win->@win\n";
 }    


# Callback bound to '<Key>' event when wheel is already mapped 
sub closemode {
    return if $wheel1->ismoving;
    return if $wheel2->ismoving;
    return if $wheel3->ismoving;

    # set binding to map the wheel
    $mw->Tk::bind('<Key>', \&openmode);
    # unmap the wheel
    $wheel1->hide(350, 400);
    $wheel2->hide(350, 400);
    $wheel3->hide(350, 400);
    # and then inform user
    &comment("Strike any key to show the wheel");
}

# Just display comment 
sub comment {
    my $string = shift;
    $zinc->itemconfigure($text, -text => $string);
}

# display winning comment 
sub wincomment {
    my $string = shift;
    $zinc->itemconfigure($wintext, -text => $string);
}

sub displaywin {
  if($#win == -1){&wincomment("NO WIN")}
  if($#win == 0){&wincomment("SINGLE")}
  if($#win == 1){&wincomment("DOUBLE")}
  if($#win == 2){&wincomment("TRIPLE")}
 
 #restore disabled mouse click for next spin
  $zinc->bind($wheel1, '<1>',  sub {spin()}); 
  $zinc->bind($wheel2, '<1>', sub {spin()});    
  $zinc->bind($wheel3, '<1>', sub {spin()});    
}

#=============================================================================
#                 Wheel  Class
#=============================================================================
package Wheel;

use strict 'vars';
use Carp;
#====================
# Object constructor
#====================
sub new {
    my ($proto, $widget, $x, $y, $radius) = @_;
  
    # object attributes
    my $self = {
	'widget' => $widget,   # widget reference
	'origin' => [$x, $y],  # origin coordinates
	'radius' => $radius,   # wheel radius
	'topgroup' => undef,   # top Group item
	'itemclip' => undef,   # id of item which clips the wheel
	'angle' => 0,          # delta angle
	'stepsnumber' => 20,   # animations parameters
	'afterdelay' => 30,
	'shrinkrate' => 0.8,   # zoom parameters
	'zoomrate' => 1.1,
	   
	};
    bless $self;    
    
    # First, we create a new Group item for the wheel. Why a Group item ?
    # At least two reasons. Wheel object consists of several Zinc items,  
    # we'll see below; it moves when it is mapped or unmapped, grows when  
    # you hit the jackpot. So, it's more easy to apply such transformations 
    # to a structured items set, using Group capability, rather than apply 
    # to each item separately or using canvas-like Tags mechanism.
    # Second reason refers to clipping. When it is mapped or unmapped, wheel 
    # object is drawn inside a circle with variant radius; clipping is a 
    # specific property of Group item

    # That's why we create a Group item in the top group, and set its
    # coordinates.
    $self->{topgroup} = $widget->add('group', 1, -visible => 0);
    $widget->coords($self->{topgroup}, [$x,$y]);
    
#print "  start widget coords-> $x $y\n";    
        
    # All the following items will be created in this group...
    # Create the invisible Arc item used to clip the wheel, centered on the
    # group origin.
    $self->{itemclip} = $widget->add('arc',  $self->{topgroup},
				     [-$radius, -$radius, $radius, $radius],
				     -visible => 0,
				     );
    $widget->itemconfigure($self->{topgroup}, -clip => $self->{itemclip});

    # Create the wheel with 6 filled Arc items centered on the group origin
    my $i = 0;
    for my $color (qw(magenta blue cyan green yellow red)) {
	$widget->add('arc',  $self->{topgroup},
		     [-$radius, -$radius, $radius, $radius],
		     -visible => 1,
		     -filled => 1,
		     -closed => 1,
		     -extent => 60,
		     -pieslice => 1,
		     -fillcolor => $color,
		     -linewidth => 1,
		     -startangle => 60*$i ,
		     -tags => [$self],
		     );
	$i++;
    }
    
    # Create the Text item representing the jackpot.
    $widget->add('text', $self->{topgroup},
		 -position => [0, -$radius+20],
		 -font =>
		 '-adobe-helvetica-bold-o-normal--34-240-100-100-p-182-iso8859-1',
		 -anchor => 'center',
		 -text => "\$",
		 );
    
    
    # Then we unmap the wheel; in fact, Group item is translated and its
    # clipping circle is shrunk to a point.
    $self->_clipAndTranslate($self->{shrinkrate}**$self->{stepsnumber});
    return $self;
}

#================
# Public methods
#================

# Return 1 if wheel is moving (opening or closing animation)
sub ismoving {
    my $self = shift;
    return 1 if $self->{opening} or $self->{closing} or $self->{turning};
}

# Display wheel with animation effect
sub show {
    my ($self, $x, $y) = @_;
    # simple lock management
    return if $self->{opening} or $self->{closing};
    $self->{opening} = 1;
    # start animation 
    $self->_open($x, $y, 0);
}


# Unmap wheel with animation effect
sub hide {
    my ($self, $x, $y) = @_;
    # simple lock management
    return if $self->{opening} or $self->{closing};
    $self->{closing} = 1;
    # start animation
    $self->_close($x, $y, 0);
}


# Just rotate the hand with animation effect.
sub rotatewheel {
    my $self = shift;
    #print "wheel-> $self->{topgroup}";
    my $angle = shift;
#print "  angle->$angle\n";

    return if $self->{turning};

#prevent "double-clicking", so mouse is disabled
#until current play is over
$zinc->bind($wheel1, '<1>', sub {}); 
$zinc->bind($wheel2, '<1>', sub {});    
$zinc->bind($wheel3, '<1>', sub {});    

    $angle = 0  unless $angle;
    my $oldangle = $self->{angle};
    $self->{angle} = $angle;

    if ((330 < $angle)||($angle < 30)) {
    	$self->{fortune} = 1;
        push (@win, $self->{fortune});
    }
    $self->_rotatewheel(2*3.1416*($angle + 1440 - $oldangle)/360); 
    #the 1440 above gives at least 2 full spins each play  
}

#=================
# Private methods
#=================

# Generate opening animation; see below _clipAndTranslate method for
# Zinc specific use.
sub _open {
    my ($self, $x, $y, $cnt) = @_;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};
    # first step of animation
    if ($cnt == 0) {
	$widget->itemconfigure($group, -visible => 1);
	my @pos = $widget->coords($group);
	$x = ($x - $pos[0])/$self->{stepsnumber};
	$y = ($y - $pos[1])/$self->{stepsnumber};
    # last step
    } elsif ($cnt == $self->{stepsnumber}) {
	$self->{opening} = undef;
	return;
    }
    $cnt++;
    # move and grow the wheel
    $self->_clipAndTranslate(1/$self->{shrinkrate}, $x, $y);
    # process the animation using the 'after' Tk defering method
    $widget->after($self->{afterdelay}, sub {$self->_open($x, $y, $cnt)});
}


# Generate closing animation; see below _clipAndTranslate method for
# Zinc specific use.
sub _close {
    my ($self, $x, $y, $cnt) = @_;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};
    # first step of animation
    if ($cnt == 0) {
	my @pos = $widget->coords($group);
	$x = ($x - $pos[0])/$self->{stepsnumber};
	$y = ($y - $pos[1])/$self->{stepsnumber};
    # last step
    } elsif ($cnt == $self->{stepsnumber}) {
	$widget->itemconfigure($group, -visible => 0);
	$self->{closing} = undef;
	return;
    }
    $cnt++;
    # move and shrink the wheel
    $self->_clipAndTranslate($self->{shrinkrate}, $x, $y);
    # process the animation using the 'after' Tk defering method
    $widget->after($self->{afterdelay}, sub {$self->_close($x, $y, $cnt)});

&main::wincomment("READY");
}

# Generate hand rotation animation.
sub _rotatewheel {
    my ($self, $angle, $cnt) = @_;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};

#grab position of widget
my @pos = $widget->coords($group);
my $x = ($pos[0]);
my $y = ($pos[1]);

    $self->{turning} = 1;
    # first step of animation
    if (not $cnt) {
	$angle /= $self->{stepsnumber};
    
    # last step
    } elsif ($cnt == $self->{stepsnumber}) {
	if ($self->{fortune}) {
	    $self->_fortune;
	} else {
	    $self->{turning} = undef;
	}

        &main::displaywin();
	return;
    }
    $cnt++;
    # use 'rotation' Zinc method.

    $widget->rotate($self->{topgroup}, $angle);
# process the animation using the 'after' Tk defering method

#needed to keep wheel stationary while rotating
$widget->coords($self->{topgroup},[$x,$y]);

    $widget->after($self->{afterdelay}, sub {$self->_rotatewheel($angle, $cnt)});

}

# Generate growing animation to notify jackpot
sub _fortune {
    my ($self, $cnt) = @_;
    $cnt = 0 unless $cnt;
    my $zf;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};
    my @pos = $widget->coords($group);
    # last step of animation
    if ($cnt == 6) {
	$self->{fortune} = undef;
	$self->{turning} = undef;
	return;
    # event steps : wheel grows
    } elsif ($cnt == 0 or $cnt % 2 == 0) {
	$zf = $self->{zoomrate};
    # odd steps : wheel is shrunk
    } else {
	$zf = 1/$self->{zoomrate};
    }
    $cnt++;
    
    # Now, we apply scale transformation to the Group item, using the 'scale'
    # Zinc method. Note that we reset group coords before scaling it, in order
    # that the origin of the transformation corresponds to the center of the
    # wheel. When scale is done, we restore previous coords of group.
    $widget->coords($group, [0, 0]);
    $widget->scale($group, $zf, $zf);
    $widget->coords($group, \@pos);
    
    # process the animation using the 'after' Tk defering method
    $widget->after(100, sub {print "\007";$self->_fortune($cnt)});
    &main::displaywin();
}


# Update group clipping and translation, using 'scale' and 'translate'
# Zinc methods.
sub _clipAndTranslate {
    my ($self, $shrinkfactor, $x, $y) = @_;
    $x = 0 unless $x;
    $y = 0 unless $y;
    $self->{widget}->scale($self->{itemclip}, $shrinkfactor, $shrinkfactor);
    if ($Tk::Zinc::VERSION lt "3.297") {
	$self->{widget}->translate($self->{topgroup}, $x, $y);
    } else {
	my ($xc, $yc) = $self->{widget}->coords($self->{topgroup});
	$self->{widget}->coords($self->{topgroup}, [$xc + $x, $yc + $y]);
    }
}
1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/background_texture.gif.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/hegias_parouest_TE.vid.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/paper-grey.gif.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/paper-grey1.gif.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/paper.gif.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/stripped_texture.gif.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/videomap_orly.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/videomap_paris-w_90_2.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/zinc.gif.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_data/zinc_anti.gif.

cannot compute difference between binary files

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/MagicLens.pl.











































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#!/usr/bin/perl
#-----------------------------------------------------------------------------------
#
#      MagicLens.pl
#
#      This small demo is based on Zinc::Graphics.pm for creating
#      the graphic items.
#      The magnifyer effect is obtained with the help of clipping,
#      and some glass effect is based on color transparency through
#      a triangles item bordering the magnifier
#
#      Authors: Jean-Luc Vinot <vinot@cena.fr>
#
# $Id$
#-----------------------------------------------------------------------------------

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use Tk::Zinc::Graphics;
use Getopt::Long;
use strict 'vars';

# the original fonts are not available everywhere, even if they are free!
my $font_9b = '7x13bold'; # '-cenapii-bleriot mini-bold-r-normal--9-90-75-75-p-*-iso8859-15';
my $font_8 = '7x13';  #'-cenapii-bleriot mini-book-r-normal--8-80-75-75-p-*-iso8859-15';
my ($dx, $dy);

my @basiccolors = (['Jaune','#fff52a','#f1f1f1','#6a6611'],
		   ["Jaune\nOrangé",'#ffc017','#cfcfcf','#6b510a'],
		   ['Orangé','#ff7500','#a5a5a5','#622d00'],
		   ['Rouge','#ff2501','#8b8b8b','#620e00'],
		   ['Magenta','#ec145d','#828282','#600826'],
		   ["Violet\nRouge",'#a41496','#636363','#020940'],
		   ["Violet\nBleu",'#6a25b6','#555555','#2a0f48'],
		   ['Bleu','#324bde','#646464','#101846'],
		   ['Cyan','#0a74f0','#818181','#064a9a'],
		   ["Bleu\nVert",'#009bb4','#969696','#006474'],
		   ['Vert','#0fa706','#979797','#096604'],
		   ["Jaune\nVert",'#9dd625','#c9c9c9','#496311']);

my $circle_coords = [[0,-30],[-16.569,-30,'c'],[-30,-16.569,'c'],[-30,0],[-30,16.569,'c'],[-16.569,30,'c'],[0,30],
		     [16.569,30,'c'],[30,16.569,'c'],[30,0],[30,-16.569,'c'],[16.569,-30,'c'],[0,-30]];


# MagicLens
my %lensitems = ('back' => {-itemtype => 'arc',
			    -coords => [[-100, -100],[100,100]],
			    -params => {-priority => 10,
					-closed => 1,
					-filled => 1,
					-visible => 0,
					-tags => ['lensback'],
				       },
			   },
 		 'light' => {-itemtype => 'pathline',
 			     -metacoords => {-type => 'polygone',
 					     -coords => [0, 0],
 					     -numsides => 36,
 					     -radius => 100,
 					     -startangle => 240,
 					    },
 			     -linewidth => 10,
 			     -shifting => 'in',
 			     -closed => 1,
 			     -graduate => {-type => 'double',
 					   -colors => [['#ffffff;0', '#6666cc;0', '#ffffff;0'],
 						       ['#ffffff;100', '#333399;50', '#ffffff;100']],
 					  },
 			     -params => {-priority => 50,
 					},
 			    },
 		 'bord' => {-itemtype => 'hippodrome',
 			    -coords => [[-100, -100],[100, 100]],
 			    -params => {-priority => 100,
 					-closed => 1,
 					-filled => 0,
 					-linewidth => 2,
 					-linecolor => '#222266;80'
 				       },

 			   },
		);
				

# creation de la fenetre principale
my $mw = MainWindow->new();
$mw->geometry("1000x900+0+0");
$mw->title('Color Magic Lens');


# creation du widget Zinc
my $zinc = $mw->Zinc(-render => 1,
		     -width => 1000,
		     -height => 900,
		     -borderwidth => 0,
		     -lightangle => 140,
		     -borderwidth => 0,
		     );
$zinc->pack(-fill => 'both', -expand => 1);

my $texture = $zinc->Photo(-file => Tk->findINC('demos/zinc_data/paper-grey1.gif'));
$zinc->configure(-tile => $texture);

# création des 2 vues
my $normview = $zinc->add('group', 1, -priority => 100);
my $lensview = $zinc->add('group', 1, -priority => 200);
my $infoview = $zinc->add('group', $lensview);

my $zoom=1.20;
$zinc->scale($infoview, $zoom, $zoom);

my $lenstexture = $zinc->Photo(-file => Tk->findINC('demos/zinc_data/paper-grey.gif'));
$zinc->add('rectangle', $infoview,
	   [[0,0],[1000,900]],
	   -filled => 1,
	   -fillcolor => '#000000',
	   -tile => $lenstexture,
	   -linewidth => 0,
	   );

my $gradbar;

my $x = 60;
for (my $i = 0; $i < 12; $i++) {

  # ajout d'un groupe dans chacune des les 2 vues
  my $cgroup = $zinc->add('group', $normview);
  $zinc->coords($cgroup, [$x, 60]);
  my $lgroup = $zinc->add('group', $infoview);
  $zinc->coords($lgroup, [$x, 60]);

  # références de la couleur : name, Zncolor saturée, ZnColor désaturée, ZnColor d'ombrage
  my ($colorname, $saturcolor, $greycolor, $shadcolor) = @{$basiccolors[$i]};

  # échantillon référence couleur saturée + relief
  my $refgrad = "=radial -12 -20|#ffffff 0|".$saturcolor." 40|".$shadcolor." 100";
  my $refitem = $zinc->add('curve', $cgroup,
			   $circle_coords,
			   -filled => 1,
			   -fillcolor => $refgrad,
			   -linewidth => 2,
			   -priority => 100
			  );

  # clone dans le group infoview
  my $clone = $zinc->clone($refitem);
  $zinc->chggroup($clone, $lgroup);

  # label couleur (infoview)
  $zinc->add('text', $lgroup,
	     -priority => 200,
	     -position => [0, 0],
	     -text => $colorname,
	     -anchor => 'center',
	     -alignment => 'center',
	     -font => $font_9b,
	     -spacing => 2,
	    );

  # dégradé de la couleur vers le gris de même luminosité
  my $bargrad = "=axial 270|".$saturcolor."|".$greycolor;

  # création des échantillons de couleur (curve multi-contours)
  $gradbar = $zinc->add('curve', $cgroup,
			[],
			-closed => 1,
			-filled => 1,
			-fillcolor => $bargrad,
			-linewidth => 2,
			-priority => 20,
			-fillrule => 'nonzero'
		       );

  # définition des couleurs du dégradé (saturation 100% -> 0%)
  my $zncolors = &createGraduate($zinc, 11, [$saturcolor, $greycolor]);
  # on retire les valeurs alphas
  foreach (@{$zncolors}){ ($_) = split /;/, $_;}

  # réalisation des pas de dégradé (saturation -> désaturation)
  my $c;
  for ($c = 0; $c < 11; $c++) {

    # couleur du pas
    my $color = $zncolors->[$c];

    # item zinc de l'exemple couleur
    my $sample = $zinc->clone($refitem, -fillcolor => $color);
    $zinc->translate($sample, 0, 65*($c+1));

    # ajout à la curve multi-contours
    $zinc->contour($gradbar, 'add', 1, $sample);

    # déplacement vers le groupe info
    $zinc->chggroup($sample, $lgroup);

    # label texte (% saturation + ZnColor)
    my $txtcolor = ((10 - $c)*10)."%\n$color";
    $zinc->add('text', $lgroup,
	       -priority => 200,
	       -position => [0, ($c + 1)* 65],
	       -text => $txtcolor,
	       -anchor => 'center',
	       -alignment => 'center',
	       -font => $font_8,
	       -spacing => 2,
	      );
  }


  $x += 80;
}

# création de la MagicLens
my $lensgroup = $zinc->add('group', 1,
			   -priority => 300,
			   -atomic => 1,
			   -tags => ['lens'],
			  );
$zinc->coords($lensgroup, [300, 110]);
&lensMove(0,0);

# items graphiques
while (my ($name, $style) = each(%lensitems)) {
  &buildZincItem($zinc, $lensgroup, %{$style});
}

# clipping lensview
my $lenszone = $zinc->clone('lensback', -tags => ['lenszone']);
$zinc->chggroup($lenszone, $lensview, 1);
$zinc->itemconfigure($lensview, -clip => $lenszone);

# consigne globale
my $consigne = $zinc->add('text', 1,
			  -position => [30, 840],
			  -text => "<Up>, <Down>, <Left> and <Right> keys or <Mouse Drag>\nMove the Magic Color Lens behind the color gradiants\nto see the ZnColor value of Hue/saturation\n",
			  -font => $font_8,
			  -alignment => 'left',
			  -color => '#ffffff',
			  -spacing => 2,
			 );

my $cclone = $zinc->clone($consigne, -font => $font_9b);
$zinc->chggroup($cclone, $infoview);

&setBindings;


MainLoop;
#----------------------------------------------------------------------- fin de MAIN


sub setBindings {
  $zinc->bind('lens', '<1>', sub {&lensStart();});
  $zinc->bind('lens', '<B1-Motion>', sub {&lensMove();});
  $zinc->bind('lens', '<ButtonRelease>', sub {&lensStop();});

  $mw->Tk::focus();

  # Up, Down, Right, Left : Translate
  $mw->Tk::bind('<KeyPress-Up>', sub {lensTranslate('up');});
  $mw->Tk::bind('<KeyPress-Down>', sub {lensTranslate('down');});
  $mw->Tk::bind('<KeyPress-Left>', sub {lensTranslate('left');});
  $mw->Tk::bind('<KeyPress-Right>', sub {lensTranslate('right');});
}




#-----------------------------------------------------------------------------------
# Callback CATCH de sélection (début de déplacement) de la lentille
#-----------------------------------------------------------------------------------
sub lensStart {
  my $ev = $zinc->XEvent;
  ($dx, $dy) = (0 - $ev->x, 0 - $ev->y);

}


#-----------------------------------------------------------------------------------
# Callback MOVE de déplacement de la lentille
#-----------------------------------------------------------------------------------
sub lensMove {
  my ($tx, $ty) = @_;

  if (defined $tx and defined $ty) {
    # interaction clavier
    $zinc->translate('lens', $tx, $ty);
    $zinc->translate('lenszone', $tx, $ty);

  } else {
    my $ev = $zinc->XEvent;
    $zinc->translate('current', $ev->x + $dx, $ev->y +$dy);
    $zinc->translate('lenszone', $ev->x + $dx, $ev->y +$dy);
    ($dx, $dy) = (0 - $ev->x, 0 - $ev->y);
  }

  my ($lx, $ly) = $zinc->coords('lens');
  $zinc->coords($infoview, [$lx * (1-$zoom), $ly * (1-$zoom)]);

}


#-----------------------------------------------------------------------------------
# Callback RELEASE de relaché (fin de déplacement) de la lentille
#-----------------------------------------------------------------------------------
sub lensStop {
  &lensMove;
}

sub lensTranslate {
  my $way = shift;

  my $dx = ($way eq 'left') ? -10 : ($way eq 'right') ? 10 : 0;
  my $dy = ($way eq 'up') ? -10 : ($way eq 'down') ? 10 : 0;

  &lensMove($dx, $dy);

}



1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/Zetris.pl.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
#!/usr/bin/perl
# Zinc port of TkTetris from Slaven Rezic
#------------------------------------------------------------------------------
#
#  Zetris - A Zinc Toy-Appli based on cool TkTetris from Slaven Rezic
#
#  $Id$
#
#  Copyright (C) 2002 Centre d'Etudes de la Navigation Aérienne
#  Author: Marcellin Buisson <buisson@cena.fr>
#
#  Hacked from Original Code to adapt to Tk::Zinc Widget :
#
#------------------------------------------------------------------------------
#
#  Author: Slaven Rezic
#
#  Copyright (C) 1997, 1999, 2000, 2002 Slaven Rezic. All rights reserved.
#  This program is free software; you can redistribute it and/or
#  modify it under the same terms as Perl itself.
#
#  Mail: slaven.rezic@berlin.de
#  WWW:  http://www.rezic.de/eserte/
#
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
#  What are the differences with the original TkTetris ?
#------------------------------------------------------------------------------
#
#  - This TkTetris-like uses a tk widget similar to the canvas
#    and called "Zinc". Zinc bring to Tk widgets openGL features
#    like transparency, color gradients, scaling.
#    So to use Zetris graphic enhancement, you need openGL capability.
#    Zinc comes with other features like grouping and clipping.
#
#  - A color gradient is used for Zetris background,
#
#  - Zetris balls are filled with transparently color gradients,
#    (transparency is visible when balls fall over TkZinc logo)
#
#  - Zetris balls have a little transparent shadow,
#
#  - The TkZinc logo is animated by rotation and scaling effects,
#
#  - Introducing of groups provided by Zinc for grouping items
#    This feature is particularly useful for applying transformations,
#
#  - The TkZinc logo over background isn't an image but only curves
#    and color gradients (made by <vinot@cena.fr>)
#
#  - Please feel free to provide any feedback to <buisson@cena.fr>
#  
#  - CM: Zetris now works even without openGL. It is just ugly!
#
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# ToDos :
#
#  - Complete this basic version in a full playable game like tktetris.
#  - Review conception through Zinc features.
#    (using groups capabilities for drawing blocks for instance)
#  - Adding special effects when completing a line or changing level.
#
#------------------------------------------------------------------------------
use Tk;
use Tk::Zinc;
use strict;
use Tk::Zinc::Logo;

package main;

use Getopt::Long;

use vars qw($VERSION);

$VERSION = sprintf("%d.%00d", q$Revision$ =~ /(\d+)\.(\d+)/);

my $max_size     = 4;
my $nmbr_blks    = 7;
my $width        = 12;
my $height       = 20;
my $geometry;

my $level;
my $just_started = 1;
my $speed;
my $base_speed = 500;

my $last_resize;
my $fontheight   = 0;

my $basefont
  = sub { sprintf "-*-helvetica-medium-r-normal--%s-*", $_[0] };
my $base2font
  = sub { sprintf "-*-courier-medium-r-normal--%s-*", $_[0] };

my $blocks = 0;
my $lines = 0;
my $mylines = 0;

my $pause = undef;
my $pause_w;
my $freefall = 0;
my $points = 0;
my $flat = 0;
my $moveable_drop = 0;

my $old_win_height;
my $draw_shadow = 1;

# Animation constants
my $afterdelay = 1;
my $stepsnumber = 10;
my $zoomrate = 1.1;

my $active_block    = undef;
my $active_block_nr = undef;
my $active_dir      = undef;
my $next_block      = undef;
my $next_block_nr   = undef;
my $next_dir        = undef;
my $posx = undef;
my $posy = undef;

my $n = 0;

my(%color_dark, %color_very_dark);
my %color_bright =
  (2 => 'red',
   3 => 'green',
   4 => 'blue',
   5 => 'cyan',
   6 => 'yellow',
   7 => 'orange',
   8 => 'pink',
  );

# Blocks matrix
my $block =
  [[[qw(0 0 0 0)],
    [qw(0 2 0 0)],
    [qw(0 2 2 0)],
    [qw(0 2 0 0)]],
   [[qw(0 0 0 0)],
    [qw(3 3 0 0)],
    [qw(0 3 0 0)],
    [qw(0 3 0 0)]],
   [[qw(0 0 0 0)],
    [qw(0 4 4 0)],
    [qw(0 4 0 0)],
    [qw(0 4 0 0)]],
   [[qw(0 0 0 0)],
    [qw(0 5 0 0)],
    [qw(0 5 5 0)],
    [qw(0 0 5 0)]],
   [[qw(0 0 0 0)],
    [qw(0 6 0 0)],
    [qw(6 6 0 0)],
    [qw(6 0 0 0)]],
   [[qw(0 7 0 0)],
    [qw(0 7 0 0)],
    [qw(0 7 0 0)],
    [qw(0 7 0 0)]],
   [[qw(0 0 0 0)],
    [qw(0 0 0 0)],
    [qw(8 8 0 0)],
    [qw(8 8 0 0)]],
  ];

my $playfield;
reset_playfield();

my $step_x = 20;
my $step_y = 20;
my $boxsize_x    = $step_x-2;
my $boxsize_y    = $step_y-2;
my $block_border = int($boxsize_x/10);
my $help_top;

my $top = MainWindow->new();
$top->minsize(181, 83);
$top->title('Zetris');

{
  my $width_height_set = 0;
  if ($geometry)
    {
      if ($geometry =~ /^(=?(\d+)x(\d+))?(([+-]\d+)([+-]\d+))?$/)
	{
	  if (defined $2 and defined $3)
	    {
	      my($width, $height) = ($2, $3);
	      $top->GeometryRequest($width, $height);
	      $width_height_set++;
	    }
	  if (defined $5 and defined $6)
	    {
	      my($x, $y) = ($5, $6);
	      $top->geometry("$x$y");
	    }
	}
      else
	{
	  die "Can't parse geometry: $geometry";
	}
    }
    if (!$width_height_set)
      {
	$top->GeometryRequest($top->screenwidth,
			      $top->screenheight);
      }
}

my $base_level = 1;

$level = level();
$speed = speed();

resize_calc();

while(my($k, $v) = each %color_bright)
  {
    $color_dark{$k} = $top->Darken($v, 80);
    $color_very_dark{$k} = $top->Darken($v, 60);
  }


# Zinc Widget (openGl rendering option set to 1)
my $tetris = $top->Zinc(-width  => $step_x*($width-2),
			-height => $step_y*($height-1),
			-backcolor => '#707070',
			-lightangle => 130,
			-render => 1,
		       )->pack;

# Zetris will no more die if there is no openGL render. I did some minor
# modification (transparency, item priority) to make all needed item
# visible, even without alpha-transparency

my $render = $tetris->cget(-render);

my $shadow_group = $tetris->add('group',1, -visible => 1);

my $pause_group = $tetris->add('group',1, -visible => 1);

my $topgroup = 1;

$tetris->pack(-fill => 'both',
	    -expand=> 1);

$tetris->add('rectangle',
	     1, # Zinc group
	     [0, 0,$step_x*($width-2) ,$step_y*($height-1)] ,
	     -filled => 1,
	     -linewidth => 0,
	     -fillcolor  => $render ? "=axial 90 |black;40|gray80;60" : "grey80",
	     -visible => 1);

my $group = $tetris->add('group', 1, );
my $logo = Tk::Zinc::Logo->new(-widget => $tetris,
			       -parent => $group,
			       -position => [$step_x*($width-2)/2-200,
					     $step_y*($height-1)/2],
			       );

$tetris->lower($group) if $render;

my $score_group = $tetris->add('group',1, -visible => 1);
my $new = $tetris->add('text',$score_group,
		       -text => "    $lines Line\n",
		       #-anchor => 'e',
		       -font => $basefont->($fontheight),
		       -position => [$width-2,10],
		      );
$tetris->add('text',$score_group,
		       -text => "Sorry, without openGL,\nZtetris is just ugly.",
		       #-anchor => 'e',
		       -font => $basefont->($fontheight),
		       -position => [$width-2,100],
	     ) if !$render;

$tetris->lower($score_group) if $render;

my $timer = $top->after(speed(), sub {
			  $old_win_height = $top->height;
			  $just_started = 0;
			  action();
			});

make_key_bindings($top);

print "\n***********************************************\n\n   For help on the game toggle pause with 'p'\n\n***********************************************\n\n";

MainLoop;

#------------------------------------------------------------------------
sub reset_playfield
  {
    my $i;
    # $fake_height: mit negativen Indices können die n-letzten Elemente
    # angesprochen werden...
    my $fake_height = $height+$max_size+1;
    for $i (0 .. $fake_height-1)
      {
	$playfield->[$i][0] = 1;
	my $j;
	for $j (1 .. $width-2)
	  {
	    $playfield->[$i][$j] = 0;
	  }
	$playfield->[$i][$width-1] = 1;
      }
    for $i (0 .. $width-1)
      {
	$playfield->[$height-1][$i] = 1;
      }
  }

sub speed
  {
    my $speed = $base_speed - ($base_speed*$level)/20;
    if ($speed <= 5) { $speed = 5 }
    $speed;
  }

sub level
  {
    int($lines / 10) + 1 + $base_level
  }

sub resize_calc
  {
    $last_resize = time();
    my $win_height;
    if ($just_started)
      {
	$win_height = $top->reqheight;
      }
    else
      {
	$win_height = $top->height;
      }
    $step_x = $step_y = int($win_height/($height+3));
    my $gap = ($step_x > 10 ? 2 : 1);
    $boxsize_x    = $step_x-$gap;
    $boxsize_y    = $step_y-$gap;
    $block_border = int($boxsize_x/10);
    if ($block_border < 1) { $block_border = 1 }
    my @font_height = (10, 11, 12, 14, 17, 18, 20, 24, 25, 34);
    my $req_fontheight = $win_height/30;
    $fontheight = 0;
    foreach (@font_height)
      {
	if ($_ > $req_fontheight)
	  {
	    $fontheight = $_;
	    last;
	  }
      }
    if (!$fontheight) { $fontheight = $font_height[$#font_height] }
    # the following line has been commented out since
    # it modify default font for every application
    # launched by zinc-demos! CM 26/3/02
    # $top->optionAdd("*font" => $basefont->($fontheight));
  }

sub make_key_bindings
  {
    my $top = shift;
#    $top->bind('<Escape>' => \&quit_game);
#    $top->bind('<q>'      => \&quit_game);
#    $top->bind('<Control-c>' => \&quit_game);
    $top->bind('<Left>'   => sub { move('left')  });
    $top->bind('<Right>'  => sub { move('right') });
    $top->bind('<Up>'     => sub { move('antiturn')  });
    $top->bind('<Down>'   => sub { move('turn')  });
    $top->bind('<j>'      => sub { move('left')  });
    $top->bind('<l>'      => sub { move('right') });
    $top->bind('<k>'      => sub { move('turn')  });
    foreach (qw/space KP_Enter/) {
      $top->bind("<$_>"  => sub { move('freefall') });
    }
    $top->bind('<p>'      => sub { toggle_pause() });
    $top->bind('<n>'      => \&stop_and_new_game);
    $top->bind('<h>'      => \&help);
    #$top->bind('all', '<F1>'     => \&help); # don't pause
    $top->bind('all', '<F2>'     => \&lost); 
    #XXX Leave und Enter herausnehmen
    $top->bind('<FocusOut>' => sub { inc_pause(1) });
    #    $top->bind('<Leave>'    => sub { inc_pause(1) });
    $top->bind('<FocusIn>'  => sub { dec_pause(1) });
    #$top->bind('<ButtonRelease>'  => sub {  toggle_pause()});
    #$top->bind('<Key-space>'  => sub {  toggle_pause()});
    #    $top->bind('<Enter>'    => sub { dec_pause(1) });
  }


sub inc_pause
  {
    my $quiet = shift;
    $pause++;
    if (!$quiet && !Tk::Exists($pause_w))
      {
	my $width  = $top->width;
	my $height = $top->height;
	$pause_w = $tetris->add('text',$pause_group,
				   -text => "PAUSE MODE :\n Type p to continue\n
\n\n\nHELP : \n\n- 'p' toggle pause\n\n- Arrow keys to move blocks\n\n- 'n' to start a new game\n\n  ",
				   -font => $basefont->($fontheight),
				   -position => [30,50],
				   -anchor => 'nw',

       );
    }
}

sub dec_pause
  {
    if ($pause)
      {
	$pause--;
	if ($pause < 1)
	  {
	    $tetris->remove($pause_w);
	    undef $pause;
	  }
      }
  }

sub toggle_pause
  {
    my $quiet = shift;
    if ($pause)
      {
	$tetris->remove($pause_w);# if Tk::Exists($pause_w);
	undef $pause;
      }
    else
      {
	
	inc_pause($quiet);
      }
  }


sub action
  {
    if (!$pause)
      {
	if (!defined $active_block_nr)
	  {
	    if (!defined $next_block_nr)
	      {
		get_next_block();
	      }
	    $active_block_nr = $next_block_nr;
	    $blocks++;
	    $active_block = [];
	    copyblock($next_block, $active_block);
	    $active_dir      = $next_dir;
	    get_next_block();
	  }
	if (defined $posx)
	  {
	    # erstes Zeichnen
	    if (testblock($active_block, $posx, $posy+1))
	      {
		drawblock($posx, $posy, 0);
		$posy++;
		drawblock($posx, $posy, 1);
	      }
	    else
	      {
		array_update(($level+1) * int(($height-$posy+5)/5),
			     $posx, $posy);
		return;
	      }
	  }
	else
	  {
	    $posx = int($width / 2) - 1;
	    $posy = -$max_size;
	  }
      }
    $timer = $top->after($freefall ? 1 : speed(), \&action);
  }

sub get_next_block
  {
    $next_block_nr = int(rand()*$nmbr_blks);
    $next_dir      = int(rand()*4);
    $next_block    = $block->[$next_block_nr];
    for (0 .. $next_dir)
      {
	turn($next_block_nr, $next_block);
      }
  }

sub turn
  {
    my($number, $block) = @_;
    my($i, $j, $help_block);
    if ($number != 6)
      {
	if ($number < 5)
	  {
	    for $i (1 .. $max_size-1)
	      {
		for $j (0 .. $max_size-2)
		  {
		    $help_block->[$max_size-1-$j][$i-1] = $block->[$i][$j];
		  }
	      }
	    for $i (1 .. $max_size-1)
	      {
		for $j (0 .. $max_size-2)
		  {
		    $block->[$i][$j] = $help_block->[$i][$j];
		  }
	      }
	  }
	else
	  {
	    for $i (0 .. $max_size-1)
	      {
		for $j (0 .. $max_size-1)
		  {
		    $help_block->[$max_size-1-$j][$i] = $block->[$i][$j];
		  }
	      }
	    copyblock($help_block, $block);
	  }
      }
  }

sub copyblock
  {
    my($from, $to) = @_;
    die if ref $from ne 'ARRAY' || ref $to ne 'ARRAY';
    my($i, $j);
    for $i (0 .. $max_size-1)
      {
	for $j (0 .. $max_size-1)
	  {
	    $to->[$i][$j] = $from->[$i][$j];
	  }
      }
  }
sub rectangle
  {
    my($x, $y, $mode, $zinc) = @_;
    $zinc->remove("$x-$y");         # Zinc command for deleting items
    $zinc->remove("ombre$x-$y");
    if ($mode)
      {
	my($xx, $yy);
	($xx, $yy) = (($x-1)*$step_x, $y*$step_y);
	my $color = $color_bright{$mode};
	# Adding new Zinc item : ball shadow
	my $ombre=$zinc->add(
			     'arc',$shadow_group,[$xx+10,$yy+10,$xx+$boxsize_x+10,$yy+$boxsize_y+10],
			     -visible=>1,
			     -filled=>1,
			     -fillcolor => $render ? "=path 50 50 |black;100 0|black;80 20|black;0 100" : "grey90", # color gradiant
			     -linewidth => 0,
			     -linecolor => 'yellow',
			     -priority => $render ? 6 : 10,
			     -tags => ["ombre$x-$y"]);
	
	$zinc->itemconfigure($shadow_group, -priority => 2);
	
	# Adding new Zinc item : ball
	my $cercle=$zinc->add(
			      'arc',$topgroup,[$xx,$yy,$xx+$boxsize_x,$yy+$boxsize_y],
			      -visible=>1,
			      -filled=>1,
			      -fillcolor => $render ? "=radial -20 -20 |white;90|$color;90" : $color,
			      -linewidth => 1,
			      -priority => 5,
			      -linecolor => "$color;80",
			      -tags => ["$x-$y"]);
      }
  }

sub testblock
  {
    my($active_block, $posx, $posy) = @_;
    for(my $i = 0; $i <= $max_size-1; $i++)
      {
	for(my $j = 0; $j <= $max_size-1; $j++)
	  {
	    if ($active_block->[$i][$j])
	      {
		if ($playfield->[$posy+$i][$posx+$j])
		  {
		    return 0;
		  }
	      }
	  }
      }
    1;
  }

sub drawblock
  {
    my($posx, $posy, $mode, $zinc) = @_;
    my $y = $posy;
    $zinc = $tetris if !$zinc;
    for(my $i = 0; $i <= $max_size-1; $i++)
      {
	my $x = $posx;
	for(my $j = 0; $j <= $max_size-1; $j++)
	  {
	    if ($active_block->[$i][$j])
	      {
		if (!$mode)
		  {
		    rectangle($x, $y, 0, $zinc);
		  }
		else
		  {
		    rectangle($x, $y, $active_block->[$i][$j], $zinc);
		  }
	      }
	    $x++;
	  }
	$y++;
      }
  }



sub new_game {
    reset_playfield();
    renew_field();
    reset_block();
    $next_block_nr = undef;
    reset_game_param();
    action();
}

sub stop_and_new_game {
    stop_game();
    new_game(),
  }

## no more used, because it quits zinc-demos
sub quit_game {

    print "Bye!\n";
    exit;
}

sub lost {
  $top->destroy;
  print "You lost :o( !\n";
  exit;
 }

sub reset_game_param {
    $points = $blocks = $lines = 0;
    $level = level();
    $speed = speed();
    $pause = undef;
}

sub stop_game {
    undef_timer();
    undef $active_block;
}

sub delete_line
  {
    my($y) = @_;
    my $yy = $y*$step_y;
    my $x;
    for $x (1 .. $width-2)
      {
	my $xx = ($x-1)*$step_x;
	$tetris->add
	  ('rectangle',1,
	   [$xx, $yy, $xx+$boxsize_x, $yy+$boxsize_y],
	   -filled => 1,
	   -fillcolor => 'orange;50',
	   -tags => ['delline'],
	  );
      }
    $tetris->idletasks;
    short_sleep(0.05);
    $tetris->remove('delline');
    my $deuxpi = 3.1416;
    my $i = 1;
    my $angle = 360;
    # special effect on TkZinc logo
    rotation($deuxpi*$angle/360);
    $mylines++;
    $tetris->itemconfigure($new,-text => "    $mylines Lines\n", -font => $basefont->($fontheight));
  }

sub rotation
  {
    my ($angle, $cnt) = @_;
    # first step of animation
    if ($cnt == $stepsnumber)
      {
	inflation(); # scaling effect
	return;
      }
    $cnt++;
    # use 'rotation' Zinc method.
    my $stepi = 360/$stepsnumber;
    $angle = $stepi*2*3.1416/360;
    $tetris->rotate($group, $angle, 250, 450 );
    # process the animation using the 'after' Tk defering method
    $tetris->after($afterdelay, sub {rotation($angle, $cnt)});
  }

sub inflation
  {
    my ($cnt) = @_;
    my @pos = $tetris->coords($group);
    my $zf;
    # last step of animation
    if ($cnt == 6)
      {
	return;
	# event steps : wheel grows
      }
    elsif ($cnt % 2 == 0)
      {
	$zf = 4*$zoomrate;
	# odd steps : wheel is shrunk
      }
    else
      {
	$zf = 1/(4*$zoomrate);
      }
    $cnt++;
    # Now, we apply scale transformation to the Group item, using the 'scale'
    # Zinc method. Note that we reset group coords before scaling it, in order
    # that the origin of the transformation corresponds to the center of the
    # wheel. When scale is done, we restore previous coords of group.
    $tetris->coords($group, [0, 0]);
    $tetris->scale($group, $zf, $zf);
    $tetris->coords($group, \@pos);
    # process the animation using the 'after' Tk defering method
    $tetris->after(100, sub {inflation($cnt)});
  }

sub game_over {
  stop_game();
  #    insert_highscore();
  #    show_highscore('Game over');
  #    save_highscore();
  #toggle_pause();
  my $width  = $top->width;
  my $height = $top->height;
  my $new = $tetris->add('text',$pause_group,
			 -font => $basefont->($fontheight),
			 -text => "You lost ! :o)\ntype 'n' to try again !",
			 -position => [20,100],
			);
  $top->update('idletasks');
  short_sleep(1);
  $tetris->remove($new);
 }

sub move {
    my($dir) = @_;
    if (!$active_block || !defined $posx || $pause) {
	$top->bell;
	return;
    }
    if ($dir eq 'right' and testblock($active_block, $posx+1, $posy)) {
	drawblock($posx, $posy, 0);
	$posx++;
	drawblock($posx, $posy, 1);
    } elsif ($dir eq 'left' and testblock($active_block, $posx-1, $posy)) {
	drawblock($posx, $posy, 0);
	$posx--;
	drawblock($posx, $posy, 1);
    } elsif ($dir eq 'turn') {
	my $help_block = [];
	copyblock($active_block, $help_block);
	turn($active_block_nr, $help_block);
	if (testblock($help_block, $posx, $posy)) {
	    drawblock($posx, $posy, 0);
	    copyblock($help_block, $active_block);
	    drawblock($posx, $posy, 1);
	}
    } elsif ($dir eq 'antiturn') {
	my $help_block = [];
	copyblock($active_block, $help_block);
	anti_turn($active_block_nr, $help_block);
	if (testblock($help_block, $posx, $posy)) {
	    drawblock($posx, $posy, 0);
	    copyblock($help_block, $active_block);
	    drawblock($posx, $posy, 1);
	}
    } elsif ($dir eq 'freefall') {
	if ($moveable_drop) {
	    $freefall = 1;
	    undef_timer();
	    action();
	} else {
	    my $free_fall = 0;
	    while (testblock($active_block, $posx, $posy+1)) {
		drawblock($posx, $posy, 0);
		$posy++;
		$free_fall++;
		drawblock($posx, $posy, 1);
		$top->idletasks;
	    }
	    array_update(($level+1)*int(($free_fall+$height-$posy+5)/5),
			 $posx, $posy);
	}
    }
  }

sub array_update
  {
    my($plus, $posx, $posy) = @_;
    my($i, $j);
    undef_timer();
    delete_shadow();
    for $i (0 .. $max_size-1)
      {
	for $j (0 .. $max_size-1) {
	    if ($active_block->[$i][$j] and $posy+$i >= 0) {
		$playfield->[$posy+$i][$posx+$j] = $active_block->[$i][$j];
	    } else {
		if ($active_block->[$i][$j]) {
		    game_over();
		    return;
		}
	    }
	}
    }
    $points += $plus;

    if ($posy >= 0) {
	for $i ($posy .. $height-2) {
	    if (to_del_line($i)) {
		delete_line($i);
		$lines++;
		$points += 10*($level+1);
		for $j (reverse(0 .. $i-1)) {
		    my $k;
		    for $k (1 .. $width-2) {
			$playfield->[$j+1][$k] = $playfield->[$j][$k];
		    }
		}
		renew_field($i);
	    }
	}
    }

    my $oldlevel = $level;
    $level = level();
    if ($oldlevel != $level) {
	my $width  = $top->width;
	my $height = $top->height;
	my $newlevel = $tetris->add('text',$pause_group,
				    -text => 'NEW LEVEL',
				    -font => $basefont->($fontheight),
				    -position => [20,20],
				  );
	$top->update('idletasks');
	short_sleep(0.5);
	$tetris->remove($newlevel);
    }
    
    reset_block();
    action();
}

sub anti_turn
  {
    my($number, $block) = @_;
    for (1 .. 3) { turn($number, $block) }
}

sub undef_timer {
    if ($timer) {
	$timer->cancel;
	undef $timer;
    }
}

sub delete_shadow {
    return if !$draw_shadow;
    for(my $x = 1; $x <= $width-1; $x++) {
#	rectangle($x, 0, 0, $shadow);
    }
}

sub to_del_line {
    my($posy) = @_;
    my $i;
    
    for $i (1 .. $width-2) {
	if ($posy >= 0 and !$playfield->[$posy][$i]) {
	    return 0;
	}
    }
    1;
}
sub reset_block {
    undef $active_block_nr;
    undef $posx;
    $freefall = 0;
}

sub short_sleep {
    my $sleep = shift;
    if ($^O =~ /win/i) {
	$top->Busy;
	my $wait = 0;
	$top->after($sleep*1000, sub { $wait = 1 });
	$top->waitVariable(\$wait);
	$top->Unbusy;
    } else {
	eval { select(undef, undef, undef, $sleep) };
    }
}

sub renew_field {
    my($max_y) = @_;
    $max_y = $height-2 if !defined $max_y;
    my($i, $j);
    for $i (0 .. $max_y) {
	for $j (1 .. $width-2) {
	    if ($playfield->[$i][$j]) {
		rectangle($j, $i, $playfield->[$i][$j], $tetris);
	    } else {
		rectangle($j, $i, 0, $tetris);
	    }
	}
    }
}

sub help
  {
    inc_pause();
    if (defined $help_top and Tk::Exists($help_top))
      {
	$help_top->raise;
	return;
      }
    require Tk::ROText;
    my $firebutton = 'Button';
    eval { require Tk::FireButton; Tk::FireButton->VERSION(1.04); };
    $help_top = $top->Toplevel(-title => 'Tetris Help');
    make_key_bindings($help_top);
    my $ti = "Zetris help :\n  - truc 1\n  - truc 2\n  - truc 3\n \n";
    my $create_but = sub {
	my($t, $command, $fire) = @_;
	my $button = ($fire ? $firebutton : 'Button');
	my $but = $tetris->add('text',$pause_group,
			       -text => $ti,
			       -font => $base2font->(12),
			       -position => [20,20],
				);
    };

    my $cb = $help_top->Button(-text => 'Close',
			       -font => $base2font->(12),
			       -command => sub { $help_top->destroy })->pack;
    $help_top->bind('<Escape>' => sub { $cb->invoke });
}

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/all_options.pl.





















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use Tk::Pane;

use strict;

my $mw = MainWindow->new();

# The explanation displayed when running this demo
my $label=$mw->Label(-text =>
"Click on one of the following
buttons to get a list of Item
attributes (or zinc options)
with their types.\n",
	   -justify => 'left')->pack(-padx => 10, -pady => 10);


# Creating the zinc widget
my $zinc = $mw->Zinc(-width => 1, -height => 1,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 0, -relief => 'sunken',
		     )->pack;

# Creating an instance of every item type
my %itemtypes;

# These Items have fields! So the number of fields must be given at creation time
foreach my $type qw(tabular track waypoint) {
    $itemtypes{$type} = $zinc->add($type, 1, 0);
}

# These items needs no specific initial values
foreach my $type qw(group icon map reticle text window) {
    $itemtypes{$type} = $zinc->add($type, 1);
}

# These items needs some coordinates at creation time
# However curves usually needs more than 2 points.
foreach my $type qw(arc curve rectangle) {
    $itemtypes{$type} = $zinc->add($type, 1, [0,0 , 1,1]);
}
# Triangles item needs at least 3 points for the coordinates 
foreach my $type qw(triangles) {
    $itemtypes{$type} = $zinc->add($type, 1, [0,0 , 1,1 , 2,2]);
}


sub showAllOptions {
    my ($type) = @_;

    my $tl = $mw->Toplevel;
    my $title = "All options of an item $type";
    my @options;
    if ($type eq 'zinc') {
	@options = $zinc->configure();
	$title = "All options of zinc widget";
    }
    else {
	@options = $zinc->itemconfigure($itemtypes{$type});
	$title = "All attributes of an item $type";
    }
    $tl->title($title);
    my $frame = $tl->Scrolled('Pane',
			      -scrollbars => 'e',
			      -height => 600,
			      );
    $frame->pack(-padx => 10, -pady => 10,
		 -ipadx => 10,
		 -fill => 'both',
		 -expand => 1,
		 );

    my $fm = $frame->LabFrame(-labelside => 'acrosstop',
			      -label => $title,
			      )->pack(-padx => 10, -pady => 10,
				      -ipadx => 10,
				      -fill => 'both');
    my $bgcolor = 'ivory';
    $fm->Label(-text => 'Option', -background => $bgcolor, -relief => 'ridge')
	->grid(-row => 1, -column => 1, -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => ($type eq 'zinc') ? 'optionClass' : 'Type',
	       -background => $bgcolor, -relief => 'ridge')
	->grid(-row => 1, -column => 2, -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    $fm->Label(-text => ($type eq 'zinc') ? 'defaultValue' : 'ReadOnly',
	       -background => $bgcolor, -relief => 'ridge')
	->grid(-row => 1, -column => 3, -ipady => 10, -ipadx => 5, -sticky => 'nswe');
    my $i = 2;
    my %options; #we used this hastable to sort the options by their names
    
    if ($type eq 'zinc') {
	for my $elem (@options) {
#	    print "$elem @$elem\n";
	    my ($optionName, $optionDatabaseName, $optionClass, $default, $optionValue) = @$elem;
	    $options{$optionName} = [$optionClass, $default, "", $optionValue];
	}
    }
    else {
	for my $elem (@options) {
	    my ($optionName, $optionType, $readOnly, $empty, $optionValue) = @$elem;
	    $options{$optionName} = [$optionType, $readOnly, $empty, $optionValue];
	}
    }
    for my $optionName (sort keys %options) {
	my ($optionType, $readOnly, $empty, $optionValue) = @{$options{$optionName}};
	$fm->Label(-text => $optionName, -relief => 'ridge')
	    ->grid(-row => $i, -column => 1, -ipady => 10, -ipadx => 5, -sticky => 'nswe');
	$fm->Label(-text => $optionType, -relief => 'ridge')
	    ->grid(-row => $i, -column => 2, -ipady => 10, -ipadx => 5, -sticky => 'nswe');

	# $empty is for provision by Zinc
	if ($type ne 'zinc') {
	    if ($readOnly) {$readOnly = "read only"} else { $readOnly = "" }
	}
	$fm->Label(-text => $readOnly, -relief => 'ridge')
	    ->grid(-row => $i, -column => 3, -ipady => 10, -ipadx => 5, -sticky => 'nswe');
	# we do not display $optionValue for these fake items
	$i++;
    }
    $tl->Button(-text => 'Close',
		-command => sub {$tl->destroy})->pack;    

}

my $col = $mw->Frame()->pack();

my $width=0;
foreach my $type (sort keys %itemtypes) {
    if (length ($type) > $width) {
	$width = length ($type);
    }
}

foreach my $type (sort keys %itemtypes) {
    $col->Button(-text => "$type",
		 -width => $width,
		 -command => sub {&showAllOptions ($type);},
		 )->pack(-pady => 4);	   
}
$col->Button(-text => "zinc widget options",
	     -command => sub {&showAllOptions ('zinc');},
	     )->pack(-pady => 4);	   

MainLoop();


1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/atomic-groups.pl.



























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#!/usr/bin/perl
# $Id$
# this simple sample has been developped by C. Mertz mertz@cena.fr

package atomic_groups;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use Tk::Checkbutton;
use Tk::Label;
use strict;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 500, -height => 350,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 0,
		     )->pack;


my $groups_group_atomicity = 0;
my $red_group_atomicity = 0;
my $green_group_atomicity = 0;

my $display_clipping_item_background = 0;
my $clip = 1;

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text =>
	   "- There are 3 groups: a red group containing 2 redish objects,\n".
	   "a green group containing 2 greenish objects,\n".
	   "and groups_group containing both previous groups.\n".
	   "- You can make some groups atomic or not by depressing \n".
	   "the toggle buttons at the bottom of the window\n".
	   "- Try and then click on some items to observe that callbacks\n".
	   " are then different: they modify either the item, or 2 items of\n".
           " a group or all items",
	   -anchor => 'nw',
	   -position => [10, 10]);


############### creating the top group with its bindings ###############################
my $groups_group = $zinc->add('group', 1, -visible => 1,
			      -atomic => $groups_group_atomicity,
			      -tags => [ 'groups_group' ]);

# the following callbacks will be called only if 'groups_group' IS atomic
$zinc->bind($groups_group, '<1>', \&modify_bitmap_bg);
$zinc->bind($groups_group, '<ButtonRelease-1>', \&modify_bitmap_bg);

############### creating the red_group, with its binding and its content ################
# the red_group may be atomic, that is is makes all children as a single object
# and sensitive to red_group callbacks
my $red_group = $zinc->add('group', $groups_group,
			   -visible => 1,
			   -atomic => $red_group_atomicity,
			   -sensitive => 1,
			   -tags => ['red_group'],
			   );
# the following callbacks will be called only if 'groups_group' IS NOT-atomic
# and if 'red_group' IS atomic
$zinc->bind($red_group, '<1>', sub { &modify_item_lines($red_group)} );
$zinc->bind($red_group, '<ButtonRelease-1>', sub { &modify_item_lines($red_group)} );


my $rc = $zinc->add('arc', $red_group,
		    [100, 200, 140, 240],
		    -filled => 1, -fillcolor => "red2",
		    -linewidth => 3, -linecolor => "white",
		    -tags => [ 'red_circle' ],
		    );

my $rr = $zinc->add('rectangle', $red_group,
		    [300, 200, 400,250],
		    -filled => 1, -fillcolor => "red2",
		    -linewidth => 3, -linecolor => "white",
		    -tags => [ 'red_rectangle' ],
		    );
# the following callbacks will be called only if 'groups_group' IS NOT atomic
# and if 'red_group' IS NOT atomic
$zinc->bind($rc, '<1>', \&toggle_color);
$zinc->bind($rc, '<ButtonRelease-1>', \&toggle_color);
$zinc->bind($rr, '<1>', \&toggle_color);
$zinc->bind($rr, '<ButtonRelease-1>', \&toggle_color);

############### creating the green_group, with its binding and its content ################
# the green_group may be atomic, that is is makes all children as a single object
# and sensitive to green_group callbacks
my $green_group = $zinc->add('group', $groups_group,
			     -visible => 1,
			     -atomic => $green_group_atomicity,
			     -sensitive => 1,
			     -tags => ['green_group'],
			    );
# the following callbacks will be called only if 'groups_group' IS NOT atomic
# and if 'green_group' IS atomic
$zinc->bind($green_group, '<1>', sub { &modify_item_lines($green_group) } );
$zinc->bind($green_group, '<ButtonRelease-1>', sub { &modify_item_lines($green_group) } );

my $gc = $zinc->add('arc', $green_group,
		    [100,270, 140,310],
		    -filled => 1, -fillcolor => "green2",
		    -linewidth => 3, -linecolor => "white",
		    -tags => [ 'green_circle' ],
		    );

my $gr = $zinc->add('rectangle', $green_group,
		    [300,270,  400,320],
		    -filled => 1, -fillcolor => "green2",
		    -linewidth => 3, -linecolor => "white",
		    -tags => [ 'green_rectangle' ],
		    );
# the following callbacks will be called only if 'groups_group' IS NOT atomic
# and if 'green_group' IS NOT atomic
$zinc->bind($gc, '<1>', \&toggle_color);
$zinc->bind($gc, '<ButtonRelease-1>', \&toggle_color);
$zinc->bind($gr, '<1>', \&toggle_color);
$zinc->bind($gr, '<ButtonRelease-1>', \&toggle_color);



my $current_bg = '';
###################### groups_group callback ##############
sub modify_bitmap_bg {
    if ($current_bg eq 'AlphaStipple2') {
	$current_bg = '';
    }
    else {
	$current_bg = 'AlphaStipple2';
    }
    foreach my $item ($rc, $rr, $gc, $gr) {
	$zinc->itemconfigure($item, -fillpattern => $current_bg);
    }
}

#################### red/green_group callback ##############
sub modify_item_lines {
    my ($gr) = @_;
    my @children = $zinc->find('withtag', ".$gr*"); # we are using a pathtag (still undocumented feature of 3.2.6) to get items of an atomic group!
    # we could also temporary modify the groups (make it un-atomic) to get its child

    my $current_linewidth = $zinc->itemcget($children[0], -linewidth);
    if ($current_linewidth == 3) {
	$current_linewidth = 0;
    }
    else {
	$current_linewidth = 3;
    }
    foreach my $item (@children) {
	$zinc->itemconfigure($item, -linewidth => $current_linewidth);
    }
	
}


##################### items callback ######################
sub toggle_color {
    my $item = $zinc->find('withtag', 'current');
    my $fillcolor = $zinc->itemcget($item, -fillcolor);
    my ($color,$num) = $fillcolor =~ /([a-z]+)(\d)/ ;
    if ($num == 2) {
	$num = 4;
    }
    else {
	$num = 2;
    }
    $zinc->itemconfigure($item, -fillcolor => "$color$num");
}


###################### toggle buttons at the bottom #######
my $row = $mw->Frame()->pack();
$row->Checkbutton(-text => 'groups_group is atomic',
		  -variable => \$groups_group_atomicity,
		  -command => sub { &atomic_or_not ($groups_group, \$groups_group_atomicity) },
		  )->pack(-anchor => 'w');	   

$row->Checkbutton(-text => 'red group is atomic   ',
		  -foreground => "red4",
		  -variable => \$red_group_atomicity,
		  -command => sub { &atomic_or_not ($red_group, \$red_group_atomicity) },
		  )->pack(-anchor => 'w');  

$row->Checkbutton(-text => 'green group is atomic ',
		  -foreground => "green4",
		  -variable => \$green_group_atomicity,
		  -command => sub { &atomic_or_not ($green_group, \$green_group_atomicity) },
		  )->pack(-anchor => 'w');
$row->Label()->pack(-anchor => 'w');
$row->Label(-text => "Following command \"\$zinc->find('overlapping', 0,200,500,400)\" returns:")->pack(-anchor => 'w');
my $label = $row->Label(-background => 'gray95')->pack(-anchor => 'w');


sub atomic_or_not {
    my ($gr,$ref_atomic) = @_;
    my $atomic = ${$ref_atomic};
    $zinc->itemconfigure( $gr, -atomic => $atomic);
    &update_found_items;
}

##### to update the list of enclosed items
sub update_found_items {
    $zinc->update;  # to be sure eveyrthing has been updated inside zinc!
    my @found = $zinc->find('overlapping', 0,200,500,400);
    my $str = "";
    foreach my $item (@found) {
	my @tags =   $zinc->itemcget($item, -tags);
	$str .= "  " . $tags[0];
    }
    $label->configure (-text => $str);
}

# to init the list of enclosed items
&update_found_items;

Tk::MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/clipping.pl.













































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/perl
# $Id$
# this simple sample has been developped by C. Mertz mertz@cena.fr

use Tk;
use Tk::Zinc;
use strict;
use Tk::Checkbutton;

package clipping;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 600,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

my $display_clipping_item_background = 0;
my $clip = 1;

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "You can drag and drop the objects.\n".
	   "There are two groups of objects, a \"tan group\" and a \"blue group\".\n".
	   "Try to move them and discover the clipping area which is a curve.\n".
	   "with two contours",
	   -anchor => 'nw',
	   -position => [10, 10]);


my $clipped_group = $zinc->add('group', 1, -visible => 1);

my $clipping_item = $zinc->add('curve', $clipped_group,
			       [10,100, 690,100, 690,590, 520,350,
				350,590, 180,350, 10,590],
			       -closed => 1,
			       -priority => 1,
			       -fillcolor => "tan2",
			       -linewidth => 0,
			       -filled => $display_clipping_item_background);
$zinc->contour($clipping_item, "add", +1, [200,200, 500,200, 500,250, 200,250]);

############### creating the tan_group objects ################
# the tan_group is atomic, that is is makes all children as a single object
# and sensitive to tan_group callbacks
my $tan_group = $zinc->add('group', $clipped_group,
			   -visible => 1,
			   -atomic => 1,
			   -sensitive => 1,
			   );

$zinc->add('arc', $tan_group,
	   [200, 220, 280, 300],
	   -filled => 1,  -linewidth => 1,
	   -startangle => 45, -extent => 270,
	   -pieslice => 1, -closed => 1,
	   -fillcolor => "tan",
	   );

$zinc->add('curve', $tan_group,
	   [400,400, 440,450,  400,500, 500,500, 460,450, 500,400],
	   -filled => 1,  -fillcolor => "tan",
	   -linecolor => "tan",
	   );

############### creating the blue_group objects ################
# the blue_group is atomic too, that is is makes all children as a single object
# and sensitive to blue_group callbacks
my $blue_group = $zinc->add('group', $clipped_group,
			    -visible => 1,
			    -atomic => 1,
			    -sensitive => 1,
			    );

$zinc->add('rectangle', $blue_group,
	   [570,180,  470,280],
	   -filled => 1,  -linewidth => 1,
	   -fillcolor => "blue2",
	   );

$zinc->add('curve', $blue_group,
	   [200,400, 200,500, 300,500, 300,400, 300,300],
	   -filled => 1,  -fillcolor => "blue",
	   -linewidth => 0,
	   );


$zinc->itemconfigure($clipped_group, -clip => $clipping_item);


###################### drag and drop callbacks ############
# for both tan_group and blue_group
$zinc->bind($tan_group, '<ButtonPress-1>' => [\&press, $tan_group, \&motion]);
$zinc->bind($tan_group, '<ButtonRelease-1>' => \&release);
$zinc->bind($blue_group, '<ButtonPress-1>' => [\&press, $blue_group, \&motion]);
$zinc->bind($blue_group, '<ButtonRelease-1>' => \&release);

my ($x_orig, $y_orig);
sub press {
    my ($zinc, $group, $action) = @_;
    my $ev = $zinc->XEvent();
    $x_orig = $ev->x;
    $y_orig = $ev->y;
    $zinc->Tk::bind('<Motion>', [$action, $group]);
}

sub motion {
    my ($zinc, $group) = @_;
    my $ev = $zinc->XEvent();
    my $x = $ev->x;
    my $y = $ev->y;

    $zinc->translate($group, $x-$x_orig, $y-$y_orig);
    $x_orig = $x;
    $y_orig = $y;
}

sub release {
    my ($zinc) = @_;
    $zinc->Tk::bind('<Motion>', '');
}
###################### toggle buttons at the bottom #######
my $row = $mw->Frame()->pack();
$row->Checkbutton(-text => 'Show clipping item',
		 -variable => \$display_clipping_item_background,
		 -command => \&display_clipping_area)->pack;	   

$row->Checkbutton(-text => 'Clip',
		 -variable => \$clip,
		 -command => \&clip)->pack;	   

sub display_clipping_area {
    $zinc->itemconfigure($clipping_item, -filled => $display_clipping_item_background);
}

sub clip {
    if ($clip) {
	$zinc->itemconfigure($clipped_group, -clip => $clipping_item);
    }
    else {
	$zinc->itemconfigure($clipped_group, -clip => undef);
    }
}

Tk::MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/color-circular.pl.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 600,
		     -borderwidth => 3, -relief => 'sunken',
		     -render => 1, # for activating the openGL render
		     )->pack;

# This demo no more dies if there is no openGL. It simply displays
# a string on the bootom of the window!


$zinc->add('rectangle', 1, [10, 10, 80, 80], -fillcolor => "=radial 50 50 |red |blue", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Radial variation from non-transparent red to non-transparent blue\nin a squarre. The gradient starts from the lower right corner.\n",
	   -anchor => 'nw',
	   -position => [120, 20]);

$zinc->add('arc', 1, [10, 110, 90, 190], -fillcolor => "=radial 0 25 |red;40|blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Radial variation from 40%transparent red to 40% transparent blue\nin a disc. The gradient starts in the middle between\nthe center on the bottom point",
	   -anchor => 'nw',
	   -position => [120, 120]);

$zinc->add('arc', 1, [10, 210, 90, 290], -fillcolor => "=radial 0 0 |red;40|green;40 50|blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A variation from 40%transparent red to 40% transparent blue.\n".
	   "through a 40%green on the middle of the disc. The gradient is centered.",
	   -anchor => 'nw',
	   -position => [120, 220]);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Two overlaping radialy, transparently colored items on a white background",
	   -anchor => 'nw',
	   -position => [20, 320]);

$zinc->add('rectangle', 1, [10, 340, 690, 590], -fillcolor => "white", -filled => 1);

$zinc->add('rectangle', 1, [20, 365, 220, 565], -fillcolor => "=radial 0 0 |red;40|green;40 50|blue;40", -filled => 1);

$zinc->add('arc', 1, [150, 365, 350, 565], -fillcolor => "=radial 0 0 |yellow;40|black;40 50|cyan;40", -filled => 1);

$zinc->add('arc', 1, [280, 365, 480, 565], -fillcolor => "=radial 0 0 |black;100|black;100 20|white;40", -filled => 1, -linewidth => 0);

$zinc->add('arc', 1, [480, 365, 580, 500], -fillcolor => "=radial -10 16 |black;100|white;40", -filled => 1);

$zinc->add('arc', 1, [580, 410, 680, 580], -fillcolor => "=radial -40 -40 |black;70|white;20", -filled => 1);
$zinc->add('arc', 1, [580, 410, 680, 580], -fillcolor => "=radial 40 40 |black;70|white;20", -filled => 1);


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "WITHOUT openGL, NO GRADIENT. SORRY!",
	   -anchor => 'nw',
	   -position => [20, 550]) unless $zinc->cget(-render);

MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/color-path-and-conic.pl.





























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 600,
		     -borderwidth => 3, -relief => 'sunken',
		     -render => 1, # for activating the openGL render
		     )->pack;

# This demo no more dies if there is no openGL. It simply displays
# a string on the bootom of the window!


$zinc->add('rectangle', 1, [10, 10, 80, 80], -fillcolor => "=path 0 0 |red |blue", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Path variation from non-transparent red to non-transparent blue\nin a squarre. The gradient start at the middle of the bbox.",
	   -anchor => 'nw',
	   -position => [120, 20]);

$zinc->add('arc', 1, [10, 110, 90, 190], -fillcolor => "=conical 135 |black;40|white;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Conical variation from 40%transparent black to 40% transparent white\nin a disc, center in the middle of the bbox",
	   -anchor => 'nw',
	   -position => [120, 120]);


$zinc->add('arc', 1, [10, 210, 90, 290], -fillcolor => "=path -30 +30 |red;40|green;40 50|blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A path variation from 40%transparent red to 40% transparent blue.\n".
	   "through a 40%green on the middle of the disc. The gradient center\nis toward the SW of the bbox.",
	   -anchor => 'nw',
	   -position => [120, 220]);



$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "overlaping path and conical, transparently colored items on a white background",
	   -anchor => 'nw',
	   -position => [20, 320]);

$zinc->add('rectangle', 1, [10, 340, 690, 590], -fillcolor => "white", -filled => 1);

$zinc->add('rectangle', 1, [20, 365, 220, 565], -fillcolor => "=path -40 -40 |red;40|green;40 50|blue;40", -filled => 1);

$zinc->add('arc', 1, [150, 365, 350, 565], -fillcolor => "=conical 20 -30 45 |yellow;40|black;40 50|cyan;40", -filled => 1);

$zinc->add('arc', 1, [320, 365, 480, 565], -fillcolor => "=path 0 0 |black;100|black;100 20|white;40", -filled => 1, -linewidth => 0);

#$zinc->add('arc', 1, [480, 365, 580, 500], -fillcolor => "=radial -10 16 |black;100|white;40", -filled => 1);

$zinc->add('arc', 1, [580, 410, 680, 580], -fillcolor => "=conical -40 -40 135 |black;70|white;20", -filled => 1);
#$zinc->add('arc', 1, [580, 410, 680, 580], -fillcolor => "=radial 40 40 |black;70|white;20", -filled => 1);


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "WITHOUT openGL, NO GRADIENT. SORRY!",
	   -anchor => 'nw',
	   -position => [20, 550]) unless $zinc->cget(-render);

MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/color-x.pl.





























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 600,
		     -borderwidth => 3, -relief => 'sunken',
		     -render => 1, # for activating the openGL render
		     )->pack;

# This demo no more dies if there is no openGL. It simply displays
# a string on the bootom of the window!

$zinc->add('rectangle', 1, [10,10, 690, 50], -fillcolor => "=axial 0 | red | blue", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A variation from non transparent red to non transparent blue.",
	   -anchor => 'nw',
	   -position => [20, 20]);


$zinc->add('rectangle', 1, [10,60, 690, 100], -fillcolor => "=axial -30 0 30 0 | red | blue", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "The same with a reduced span.",
	   -anchor => 'nw',
	   -position => [20, 70]);


$zinc->add('rectangle', 1, [10,110, 690, 150], -fillcolor => "=axial 0 |red;40|blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A variation from 40%transparent red to 40% transparent blue.",
	   -anchor => 'nw',
	   -position => [20, 120]);


$zinc->add('rectangle', 1, [10,160, 690, 200], -fillcolor => "=axial -30 0 30 0 |red;40|blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "The same with a reduced span.",
	   -anchor => 'nw',
	   -position => [20, 170]);


# we are using here the X explicit notation for rgb color
# we could also have used CIE encoding. If interested,
# please read the X man pages
my $gradient = ($^O eq 'linux') ? "=axial 0 | rgb:ffff/0/0;40 | rgb:0/ffff/0;40 50 | rgb:0/0/ffff;40" 
  : "=axial 0 | #ff0000;40 | #00ff00;40 50 | #0000ff;40";

$zinc->add('rectangle', 1, [10, 210, 690, 300], -fillcolor => "=axial 0 | rgb:ffff/0/0;40 | rgb:0/ffff/0;40 50 | rgb:0/0/ffff;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A variation from 40%transparent red to 40% transparent blue.\n".
	   "through a 40%green on the middle",
	   -anchor => 'nw',
	   -position => [20, 220]);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Two overlaping transparently colored rectangles on a white background",
	   -anchor => 'nw',
	   -position => [20, 320]);

$zinc->add('rectangle', 1, [10, 340, 690, 590], -fillcolor => "white", -filled => 1);
$zinc->add('rectangle', 1, [200, 350, 500, 580], -fillcolor => "red;40|green;40 50|blue;40", -filled => 1);

$zinc->add('rectangle', 1, [10, 400, 690, 500], -fillcolor => "=axial 0 |yellow;40|black;40 50|cyan;40", -filled => 1);


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "WITHOUT openGL, NO GRADIENT. SORRY!",
	   -anchor => 'nw',
	   -position => [20, 550]) unless $zinc->cget(-render);



MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/color-y.pl.























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 600,
		     -borderwidth => 3, -relief => 'sunken',
		     -render => 1, # for activating the openGL render
		     )->pack;

# This demo no more dies if there is no openGL. It simply displays
# a string on the bootom of the window!


$zinc->add('rectangle', 1, [10, 10, 340, 100], -fillcolor => "=axial 90 |red |blue", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A variation from non transparent red\n to non transparent blue.",
	   -anchor => 'nw',
	   -position => [20, 20]);


$zinc->add('rectangle', 1, [360, 10, 690, 100], -fillcolor => "=axial 0 30 0 -30 |red |blue", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "The same with a reduced span.",
	   -anchor => 'nw',
	   -position => [370, 20]);



$zinc->add('rectangle', 1, [10,110, 330, 200], -fillcolor => "=axial 90|red;40 |blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A variation from 40%transparent red\nto 40% transparent blue.",
	   -anchor => 'nw',
	   -position => [20, 120]);


$zinc->add('rectangle', 1, [360,110, 690, 200], -fillcolor => "=axial 0 30 0 -30|red;40 |blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "The same with a reduced span.",
	   -anchor => 'nw',
	   -position => [370, 120]);


$zinc->add('rectangle', 1, [10, 210, 690, 300], -fillcolor => "=axial 90 |red;40|green;40 50|blue;40", -filled => 1);

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A variation from 40%transparent red to 40% transparent blue.\n".
	   "through a 40%green on the middle",
	   -anchor => 'nw',
	   -position => [20, 220]);


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Two overlaping transparently colored rectangles on a white background",
	   -anchor => 'nw',
	   -position => [20, 320]);

$zinc->add('rectangle', 1, [10, 340, 690, 590], -fillcolor => "white", -filled => 1);
$zinc->add('rectangle', 1, [200, 350, 500, 580], -fillcolor => "=axial 90 |red;40|green;40 50|blue;40", -filled => 1);

$zinc->add('rectangle', 1, [10, 400, 690, 500], -fillcolor => "=axial 90 |yellow;40|black;40 50|cyan;40", -filled => 1);


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "WITHOUT openGL, NO GRADIENT. SORRY!",
	   -anchor => 'nw',
	   -position => [20, 550]) unless $zinc->cget(-render);



MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/contours.pl.





















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

package contours; # for avoiding symbol collision between different demos

use Tk;
use Tk::Zinc;

use strict;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

my $mw = MainWindow->new();

# The explanation displayed when running this demo
my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2,
		     -setgrid => 'true', -height => 9);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
'All visibles items are made by combining 2 items using contours:
 - the firebrick curve1 has been holed using a addhole with a circle,
 - the lightblue curve2 has been "mickey-moused" by adding two circles,
 - the yellow curve3 is the union with a disjoint circle,
 - the grey curve4 is combined with 7 circles, with \'positive\' -fillrule.
The following operations are possible:
 - "Mouse Button 1" for dragging objects.
 - "Mouse Button 1" for dragging the black handle and
    modifying the grey curve contour.');

# Creating the zinc widget
my $zinc = $mw->Zinc(-width => 600, -height => 500,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;


# Creation of 2 items NOT visible, but used for creating visible
# curves[1-5] with more than one contours.
# The center of these 2 items is 200,100
my $curve0 = $zinc->add('curve', 1, [ [300,0], [400,100, 'c'], [300,200], [200,300,'c'], [100,200], [0,100,'c'], [100,0],  ],
			-closed => 1, -visible => 0, -filled => 1,
			);
my $cercle100 = $zinc->add('arc', 1, [130,30, 280,180],
			  -visible => 0,
			  );

# cloning curve0 as curve1 and moving it
my $curve1 = $zinc->clone($curve0, -visible => 1, -fillcolor => "firebrick1");
# adding a 'difference' contour to the curve1
$zinc->contour($curve1, 'add', +1, $cercle100);


# cloning curve0 as curve2 and moving it
# creating a curve without contour to control contour clockwise/counterclockwise
my $curve2 = $zinc->add('curve', 1, [], -closed => 1, -filled => 1,
			-visible => 1, -fillcolor => "lightblue2", -fillrule => 'positive');
$zinc->contour($curve2, 'add', -1, $curve0); ## why must the flag be -1 and not -1 !?
# adding the left ear of mickey mouse!
$zinc->translate($curve2,100,90);
# adding the right ear of mickey mouse!
$zinc->contour($curve2, 'add', +1, $cercle100);

$zinc->translate($curve2,-200,0);
# adding an 'intersection' contour to the curve2
$zinc->contour($curve2, 'add', +1, $cercle100);

# ... translate to make it more visible
$zinc->translate($curve2, 320,20);


# cloning curve0 as curve3 and moving it
my $curve3 = $zinc->clone($curve0, -visible => 1, -fillcolor => "yellow3");
$zinc->translate($curve3,0,290);
# adding an 'union' contour to the curve3
$zinc->contour($curve3, 'add', +1, $cercle100);
# ... translate to make it more visible
$zinc->translate($curve3, -130,00);

    


# cloning curve0 as curve4 and moving it slightly
my $curve4 = $zinc->clone($curve0, -visible => 1, -fillcolor => "grey50",
			  -tags => ["grouped"],
			  -fillrule => 'positive',
                          # the tag "grouped" is used for both curve4 and
			  # a handle (see just below)
			  # It is used for translating both easily
			  );

my $index = 2; ## index of the vertex associated to the handle
my ($x,$y) = $zinc->coords($curve4,0,$index);
my $handle = $zinc->add('rectangle', 1, [$x-5,$y-5,$x+5,$y+5],
			-fillcolor => 'black', -filled => 1,
			  -tags => ["grouped"],
			);

# adding a 'difference' contour to the curve4
$zinc->contour($curve4, 'add', +1, $cercle100);
$zinc->translate('grouped',110,0);
$zinc->contour($curve4, 'add', +1, $cercle100);
$zinc->translate('grouped',-220,0);
$zinc->contour($curve4, 'add', +1, $cercle100);
$zinc->translate('grouped',110,80);
$zinc->contour($curve4, 'add', -1, $cercle100);
$zinc->translate('grouped',0,-160);
$zinc->contour($curve4, 'add', +1, $cercle100);

$zinc->translate('grouped',200,80);
$zinc->contour($curve4, 'add', +1, $cercle100);
$zinc->translate('grouped',-350,0);
$zinc->contour($curve4, 'add', +1, $cercle100);

$zinc->translate('grouped',350,250);
#$zinc->lower('grouped');

# Deleting no more usefull items: curve0 and cercle100:
$zinc->remove($curve0, $cercle100);

$zinc->raise($curve1);

# adding drag and drop callback to each visible curve!
foreach my $item ($curve1, $curve2, $curve3, $curve4) {
    # Some bindings for dragging the items
    $zinc->bind($item, '<ButtonPress-1>' => [\&press, $item, \&motion]);
    $zinc->bind($item, '<ButtonRelease-1>' => \&release);
}

# adding drag and drop on curve4 which also moves handle
$zinc->bind($curve4, '<ButtonPress-1>' => [\&press, $curve4, \&motionWithHandle]);
$zinc->bind($curve4, '<ButtonRelease-1>' => \&release);

# adding drag and drop on handle which also modify curve4
$zinc->bind($handle, '<ButtonPress-1>' => [\&press, $handle, \&moveHandle]);
$zinc->bind($handle, '<ButtonRelease-1>' => \&release);

# callback for starting a drag
my ($x_orig, $y_orig);
sub press {
    my ($zinc, $item, $action) = @_;
    my $ev = $zinc->XEvent();
    $x_orig = $ev->x;
    $y_orig = $ev->y;
    $zinc->Tk::bind('<Motion>', [$action, $item]);
}

# Callback for moving an item
sub motion {
    my ($zinc, $item) = @_;
    my $ev = $zinc->XEvent();
    my $x = $ev->x;
    my $y = $ev->y;

    $zinc->translate($item, $x-$x_orig, $y-$y_orig);
    $x_orig = $x;
    $y_orig = $y;
}

# Callback for moving an item and its handle
sub motionWithHandle {
    my ($zinc, $item) = @_;
    my $ev = $zinc->XEvent();
    my $x = $ev->x;
    my $y = $ev->y;

    my ($tag) = $zinc->itemcget($item, -tags);
    $zinc->translate($tag, $x-$x_orig, $y-$y_orig);
    $x_orig = $x;
    $y_orig = $y;
}

# Callback for moving the handle and modifying curve4
# this code is far from being generic. Only for demonstrating how we can
# modify a contour with a unique handle!
sub moveHandle {
    my ($zinc, $handle) = @_;
    my $ev = $zinc->XEvent();
    my $x = $ev->x;
    my $y = $ev->y;

    $zinc->translate($handle, $x-$x_orig, $y-$y_orig);

    my ($vertxX,$vertxY) = $zinc->coords($curve4,0,$index);
    $zinc->coords($curve4,0,$index, [$vertxX+($x-$x_orig), $vertxY+($y-$y_orig)]);
    $x_orig = $x;
    $y_orig = $y;
}

# Callback when releasing the mouse button. It removes any motion callback
sub release {
    my ($zinc) = @_;
    $zinc->Tk::bind('<Motion>', '');
}

Tk::MainLoop();


1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/counter.pl.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
#!/usr/bin/perl
# This simple demo has been developped by C. Schlienger <celine@intuilab.com>

package counter; # for avoiding symbol collision between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;
use constant;

my constant $PI=3.1416;

my $boldfont = '-adobe-helvetica-bold-r-normal--20-240-100-100-p-182-iso8859-1';

my $mw = MainWindow->new();

###################################################
# Zinc
###################################################

my $zinc = $mw->Zinc(-width => 700, -height => 400,
		     -font => "10x20", 
		     -borderwidth => 3, 
		     -relief => 'sunken',
		     -render => 1,
		    )->pack;

if ($zinc->cget(-render)) {
    $zinc->add('rectangle', 1,
	       [0,0,700,400],
	       -filled => 1,  -linewidth => 0,
	       -fillcolor => "=axial 90 |red;40|green;40 50|blue;40"
	       );
} else { ## no openGL rendering!
    # creating a curve in the background to demonstrate the clipping
    # of the hole in the counter
    $zinc->add('curve', 1, [30,30, 350,150, 670,30, 400,200, 670,370, 350,250, 30,370, 300,200, 30,30],
	       -filled => 1,
	       -fillcolor => "tan",
	       );
}

# The explanation displayed when running this demo
$zinc->add('text', 1,
	   -position=> [10,10],
	   -text => 'This toy-appli shows a simple counter. It is made thanks
to clipping and contours : this is the only way to do this.
You can drag the counter. Observe that the color of the background
of the counter is the same as the one of the window (use of clips)',
	   -font => "10x20",
	   );

###################################################
# Les positions
###################################################

#--------------------------------
# Carre dans lequel sera inscrit le cercle du compteur
#---------------------------------

my $x0=250;
my $y0=100;
my $x1=$x0+200;
my $y1=$y0+200;

#--------------------------------
# Rectangle dans lequel defileront les chiffres
#---------------------------------

my $x2=$x0+50;
my $y2=$y0+130;
my $x3=$x1-50;
my $y3=$y1-50;


###################################################
# Chiffres clippes
###################################################

my $general_group = $zinc->add('group',1, -visible => 1);

my $clipped_group1 = $zinc->add('group',$general_group, -visible => 1);

#--------------------------------
# Clipping items
#---------------------------------

my $clipping_item1 = $zinc->add('curve', $clipped_group1,
			       [$x2,$y2,$x3,$y2,$x3,$y3,$x2,$y3,$x2,$y2]
			      );

#--------------------------------
# Clipped items
#---------------------------------

my $group1=$zinc->add('group',$clipped_group1);

my $ecart=17;

# Il y a deux listes de chifres pour centaines, dizaines, unites,
# pour assurer l'enchainement des chiffres quand le temps passe
# (cf. : actions automatiques)

#--------------------------------
# Centaines
#---------------------------------

my $cent = $zinc->add('group',$group1, -visible => 1,);
my $xc=$x2+20;
my $yc=$y2;


my $nbc1=$zinc->add('text', $cent,
	   -font => $boldfont,
	   -text => "0
1
2
3
4
5
6
7
8
9",
	   -anchor => 'nw',
	   -position => [$xc, $yc],
);
my $nbc2=$zinc->add('text', $cent,
	   -font => $boldfont,
	   -text => "0
1
2
3
4
5
6
7
8
9",
	   -anchor => 'nw',
	   -position => [$xc, $yc+210],
);
#--------------------------------
# Dixaines
#---------------------------------

my $dix = $zinc->add('group',$group1, -visible => 1);

my $xd=$xc+30;
my $yd=$y2;
my $nbd1=$zinc->add('text', $dix,
	   -font => $boldfont,
	   -text => "0
1
2
3
4
5
6
7
8
9",
	   -anchor => 'nw',
	   -position => [$xd,$yd]);

my $nbd2=$zinc->add('text', $dix,
	   -font => $boldfont,
	   -text => "0
1
2
3
4
5
6
7
8
9",
	   -anchor => 'nw',
	   -position => [$xd,$yd+210]);
#--------------------------------
# Unites
#---------------------------------

my $unit = $zinc->add('group',$group1, -visible => 1);
my $xu=$xd+30;
my $yu=$y2;
my $nbu1=$zinc->add('text', $unit,
		    -font => $boldfont,
		    -text => "0
1
2
3
4
5
6
7
8
9",
		    -anchor => 'nw',
		    -position => [$xu, $yu]);

my $nbu2=$zinc->add('text', $unit,
		    -font => $boldfont,
		    -text => "0
1
2
3
4
5
6
7
8
9",
		    -anchor => 'nw',
		    -position => [$xu, $yu+210]);

#--------------------------------
# Clip
#---------------------------------

$zinc->itemconfigure($clipped_group1, -clip => $clipping_item1);


###################################################
# Cadran clippe
###################################################

my $clipped_group2 = $zinc->add('group',$general_group, -visible => 1);

#--------------------------------
# Clipping items
#---------------------------------

my $clipping_item2 = $zinc->add('curve', $clipped_group2,
			       [0,0,700,0,700,700,0,700,0,0],
				-linewidth=>0,
			      );

$zinc->contour($clipping_item2,"add",0,[$x2,$y2,$x3,$y2,$x3,$y3,$x2,$y3,$x2,$y2]);

#--------------------------------
# Clipped items
#---------------------------------

my $group2=$zinc->add('group',$clipped_group2);

my $cercle=$zinc->add('arc',$group2,[$x0,$y0,$x1,$y1],
			 -visible=>1,
			 -filled=>1,
			 -fillcolor=>"yellow",);

my $fleche=$zinc-> add('curve', $group2, [$x0+40,$y0+40,$x1-100,$y1-25],
		       -firstend => [10, 10, 10],
		       -linewidth => 7,
		       -linecolor=>"red",
	    );

#--------------------------------
# Clip
#---------------------------------

$zinc->itemconfigure($clipped_group2, -clip => $clipping_item2);

# this translation if for having an "interesting" background in the counter hole
# when we do not have openGL and a gradient in the background
$zinc->translate($general_group,0,21); 

###################################################
# Actions automatiques
###################################################

#--------------------------------
# Variables
#---------------------------------
# Pour le timer
my $repeat=10;

# Pour la rotation
my @centre=($x1-100,$y1-25);
my $pas=40;
my $angle=+$PI/$pas;
my $nb_tot=12;
my $nb=0;

# Pour la translation des centaines
my @c_c1=$zinc->itemcget($nbc1,-position);
my @c_c2=$zinc->itemcget($nbc2,-position);
my $nbtour_cent=2;

# Pour la translation des dizaines
my @c_d1=$zinc->itemcget($nbd1,-position);
my @c_d2=$zinc->itemcget($nbd2,-position);
my $nbtour_dix=2;

# Pour la translation des unites
my @c_u1=$zinc->itemcget($nbu1,-position);
my @c_u2=$zinc->itemcget($nbu2,-position);
my $nbtour_unit=2;


#--------------------------------
# Timer
#---------------------------------
my $timer = $zinc->repeat($repeat, [\&refresh]);

$mw->OnDestroy(\&destroyTimersub );

my $timerIsDead = 0;
sub destroyTimersub {
    $timerIsDead = 1;
    $mw->afterCancel($timer);
    # the timer is not really cancelled when using zinc-demos! 
}

#--------------------------------
# Actions
#---------------------------------
sub refresh {
  #--------------------------------
  # Rotation de la fleche
  #---------------------------------
  return if $timerIsDead;   # the timer is still running when using zinc-demos!
  $zinc->rotate($fleche,$angle,$centre[0],$centre[1]);
  $nb+=1;
  if (($nb==$nb_tot)&&($angle==$PI/$pas))
    {
      $nb=0;
      $angle=-$PI/$pas;
    } 
  else{
    if(($nb==$nb_tot)&&($angle==-$PI/$pas)){
      $nb=0;
      $angle=+$PI/$pas;
    }
  }
  #--------------------------------
  # Deplacement du texte
  #---------------------------------

  #--------------------------------
  # Centaines
  #---------------------------------
  $zinc->translate($cent,0,-0.01);

  my @coords_c1=$zinc->transform($cent,$group1,[$c_c1[0],$c_c1[1]]);
  if(int($coords_c1[1])==$yc-210){
    $zinc->itemconfigure($nbc1,-position=>[$xc,$yc+($nbtour_cent*210)]);
    $nbtour_cent+=1;
    @c_c1=$zinc->itemcget($nbc1,-position);
  }

  my @coords_c2=$zinc->transform($cent,$group1,[$c_c2[0],$c_c2[1]]);
  if($coords_c2[1]==$yc-210){
    $zinc->itemconfigure($nbc2,-position=>[$xc,$yc+($nbtour_cent*210)]);
    $nbtour_cent+=1;
    @c_c2=$zinc->itemcget($nbc2,-position);
  }

  #-------------------------------- 
  #Dixaines
  #---------------------------------
  $zinc->translate($dix,0,-0.1);

  my @coords_d1=$zinc->transform($dix,$group1,[$c_d1[0],$c_d1[1]]);
  if(int($coords_d1[1])==$yd-210){
    $zinc->itemconfigure($nbd1,-position=>[$xd,$yd+($nbtour_dix*210)]);
    $nbtour_dix+=1;
    @c_d1=$zinc->itemcget($nbd1,-position);
  }

  my @coords_d2=$zinc->transform($dix,$group1,[$c_d2[0],$c_d2[1]]);
  if($coords_d2[1]==$yd-210){
    $zinc->itemconfigure($nbd2,-position=>[$xd,$yd+($nbtour_dix*210)]);
    $nbtour_dix+=1;
    @c_d2=$zinc->itemcget($nbd2,-position);
  }


  #--------------------------------
  # Unites
  #---------------------------------
  $zinc->translate($unit,0,-1);

  my @coords_u1=$zinc->transform($unit,$group1,[$c_u1[0],$c_u1[1]]);
  if($coords_u1[1]==$yu-210){
    $zinc->itemconfigure($nbu1,-position=>[$xu,$yu+($nbtour_unit*210)]);
    $nbtour_unit+=1;
    @c_u1=$zinc->itemcget($nbu1,-position);
  }

  my @coords_u2=$zinc->transform($unit,$group1,[$c_u2[0],$c_u2[1]]);
  if($coords_u2[1]==$yu-210){
    $zinc->itemconfigure($nbu2,-position=>[$xu,$yu+($nbtour_unit*210)]);
    $nbtour_unit+=1;
    @c_u2=$zinc->itemcget($nbu2,-position);
  }

}

###################################################
# Actions manuelles
###################################################

#---------------------------------------------
# Drag and drop the counter
#---------------------------------------------

my ($prev_x, $prev_y);
$zinc -> bind($cercle,'<ButtonPress-1>'=>[\&move_on] ); 


#"move_on" state#
sub move_on{
    $prev_x=$zinc->XEvent()->x;
    $prev_y=$zinc->XEvent()->y;
    # move the counter
    $zinc -> bind($cercle,'<Motion>'=> [\&move]);
    $zinc -> bind($cercle,'<ButtonRelease-1>'=> [\&move_off]); #"move_off" state
}


#"move_off" state#
sub move_off{
  $zinc -> bind($cercle,'<Motion>'=>""); 
  $zinc -> bind($cercle,'<ButtonRelease-1>'=>"");
}

#move the counter#
sub move{
  my $x=$zinc->XEvent()->x,
  my $y=$zinc->XEvent()->y;
  $zinc->translate($clipped_group1,$x-$prev_x,$y-$prev_y);
  $zinc->translate($clipped_group2,$x-$prev_x,$y-$prev_y);
  ($prev_x,$prev_y) = ($x,$y);
}
 
Tk::MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/curve_bezier.pl.



























































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

####### This file has been initially inspired from svg examples

package curveBezier;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk::Zinc;


my $mw = MainWindow->new();
$mw->title('example of curves with cubic control points');

my $text = $mw->Text (-relief => 'sunken', -borderwidth => 2,
		      -setgrid => 'true',  -height =>3);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
'6 examples of curves containing control points are displayed, 
 with the list of control points written just below.
You can move the handles to modify the bezier curves');


my $zinc = $mw->Zinc(-width => 700, -height => 650,
		     -font => "10x20",
		     -font => "9x15",
		     -borderwidth => 0,
                     -backcolor => "white",
		     -forecolor => "grey80",
		     -render => 1, # this demo also works without openGL
		     # with openGL, antialiasing makes the curves nicer
		      )->pack;

my $group = $zinc->add('group', 1);

$zinc->add('text',$group, -position => [50,20], -anchor => 'w',
	   -text => "Examples of curve items using cubic bezier control points",
	   -color => "grey20");

## Please note: much of the following items below could be computed
$zinc->add('text',$group, -position => [25,270], -anchor => 'w', -tags => ['bezier1'], -color => "grey20");
$zinc->add('curve',$group,[100, 200, 100, 100], -tags => ['line1', 'l1-2'], -linecolor => "#888888", -filled => 0, -linewidth => 2);
$zinc->add('curve',$group,[400, 100, 400, 200], -tags => ['line1', 'l3-4'], -linecolor => "#888888", -filled => 0, -linewidth => 2);
$zinc->add('curve',$group,[[100, 200], [100, 100, 'c'], [400, 100, 'c'], [400, 200]],
	   -tags => ['bezier1'], -closed => 0, -linecolor => "red", -linewidth => 5);
$zinc->add('arc',$group,[90, 190, 110, 210], -tags => ['handle1',"p1"], -filled => 1, -fillcolor => "#BBBBBB");
$zinc->add('arc',$group,[90, 90, 110, 110], -tags => ['handle1',"p2"], -filled => 1, -linewidth => 0, -fillcolor => "grey80", -filled => 1);
$zinc->add('arc',$group,[390, 90, 410, 110], -tags => ['handle1',"p3"], -filled => 1, -linewidth => 0, -fillcolor => "grey80", -filled => 1);
$zinc->add('arc',$group,[390, 190, 410, 210], -tags => ['handle1',"p4"], -filled => 1, -fillcolor => "#BBBBBB");

$zinc->add('text',$group, -position => [570,270], -anchor => 'w', -tags => ['bezier2'], -color => "grey20");
$zinc->add('curve',$group,[600, 200, 675, 100], -tags => ['line2', 'l1-2'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[975, 100, 900, 200], -tags => ['line2', 'l3-4'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[[600, 200], [675, 100, 'c'], [975, 100, 'c'], [900, 200]],
	   -tags => ['bezier2'], -closed => 0, -linecolor => "red", -linewidth => 5);
$zinc->add('arc',$group,[590, 190, 610, 210], -tags => ['handle2',"p1"], -filled => 1, -linecolor => "grey80", -linewidth => 2);
$zinc->add('arc',$group,[665, 90, 685, 110], -tags => ['handle2',"p2"], -filled => 1, -linewidth => 0, -fillcolor => "grey80");
$zinc->add('arc',$group,[965, 90, 985, 110], -tags => ['handle2',"p3"], -filled => 1, -linewidth => 0, -fillcolor => "grey80");
$zinc->add('arc',$group,[890, 190, 910, 210], -tags => ['handle2',"p4"], -filled => 1, -linecolor => "grey80", -linewidth => 2);

$zinc->add('text',$group, -position => [25,570], -anchor => 'w', -tags => ['bezier3'], -color => "grey20");
$zinc->add('curve',$group,[100, 500, 25, 400], -tags => ['line3', 'l1-2'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[475, 400, 400, 500], -tags => ['line3', 'l3-4'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[[100, 500], [25, 400, 'c'], [475, 400, 'c'], [400, 500]],
	   -tags => ['bezier3'], -closed => 0, -linecolor => "red", -linewidth => 5);
$zinc->add('arc',$group,[90, 490, 110, 510], -tags => ['handle3',"p1"], -filled => 1, -linecolor => "grey80", -linewidth => 2);
$zinc->add('arc',$group,[15, 390, 35, 410], -tags => ['handle3',"p2"], -filled => 1, -linewidth => 0, -fillcolor => "grey80", );
$zinc->add('arc',$group,[465, 390, 485, 410], -tags => ['handle3',"p3"], -filled => 1, -linewidth => 0, -fillcolor => "grey80", );
$zinc->add('arc',$group,[390, 490, 410, 510], -tags => ['handle3',"p4"], -filled => 1, -linecolor => "grey80", -linewidth => 2);

$zinc->add('text',$group, -position => [570,570], -anchor => 'w', -tags => ['bezier4'], -color => "grey20");
$zinc->add('curve',$group,[600, 500, 600, 350], -tags => ['line4', 'l1-2'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[900, 650, 900, 500], -tags => ['line4', 'l3-4'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[[600, 500], [600, 350, 'c'], [900, 650, 'c'], [900, 500]], -tags => ['bezier4'], -closed => 0, -linecolor => "red", -linewidth => 5);
$zinc->add('arc',$group,[590, 490, 610, 510], -tags => ['handle4',"p1"], -filled => 1, -linecolor => "grey80", -linewidth => 2);
$zinc->add('arc',$group,[590, 340, 610, 360], -tags => ['handle4',"p2"], -filled => 1, -linewidth => 0, -fillcolor => "grey80");
$zinc->add('arc',$group,[890, 640, 910, 660], -tags => ['handle4',"p3"], -filled => 1, -linewidth => 0, -fillcolor => "grey80");
$zinc->add('arc',$group,[890, 490, 910, 510], -tags => ['handle4',"p4"], -filled => 1, -linecolor => "grey80", -linewidth => 2);

$zinc->add('text',$group, -position => [25,870], -anchor => 'w', -tags => ['bezier5'], -color => "grey20");
$zinc->add('curve',$group,[100, 800, 175, 700], -tags => ['line5', 'l1-2'], -linecolor => "#888888", -filled => 0, -linewidth => 2);
$zinc->add('curve',$group,[325, 700, 400, 800], -tags => ['line5', 'l3-4'], -linecolor => "#888888", -filled => 0, -linewidth => 2);
$zinc->add('curve',$group,[[100, 800], [175, 700, 'c'], [325, 700, 'c'], [400, 800]],
	   -tags => ['bezier5'], -closed => 0, -linecolor => "red", -linewidth => 5);
$zinc->add('arc',$group,[90, 790, 110, 810], -tags => ['handle5',"p1"], -filled => 1, -linecolor => "grey80", -linewidth => 2);
$zinc->add('arc',$group,[165, 690, 185, 710], -tags => ['handle5',"p2"], -filled => 1, -linewidth => 0, -fillcolor => "grey80", -filled => 1);
$zinc->add('arc',$group,[315, 690, 335, 710], -tags => ['handle5',"p3"], -filled => 1, -linewidth => 0, -fillcolor => "grey80", -filled => 1);
$zinc->add('arc',$group,[390, 790, 410, 810], -tags => ['handle5',"p4"], -filled => 1, -linecolor => "grey80", -linewidth => 2);

$zinc->add('text',$group, -position => [570,980], -anchor => 'w', -tags => ['bezier6'], -color => "grey20");
$zinc->add('curve',$group,[600, 800, 625, 700], -tags => ['line6', 'l1-2'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[725, 700, 750, 800], -tags => ['line6', 'l3-4'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[750, 800, 775, 900], -tags => ['line6', 'l4-5'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[875, 900, 900, 800], -tags => ['line6', 'l6-7'], -linecolor => "#888888", -linewidth => 2);
$zinc->add('curve',$group,[[600, 800], [625, 700, 'c'], [725, 700, 'c'], [750, 800], [775, 900, 'c'], [875, 900, 'c'], [900, 800]],
	   -tags => ['bezier6'], -filled => 0, -closed => 0, -linecolor => "red", -linewidth => 5);
$zinc->add('arc',$group,[590, 790, 610, 810], -tags => ['handle6',"p1"], -filled => 1, -linecolor => "grey80", -linewidth => 2);
$zinc->add('arc',$group,[615, 690, 635, 710], -tags => ['handle6',"p2"], -filled => 1, -linewidth => 0, -fillcolor => "grey80");
$zinc->add('arc',$group,[715, 690, 735, 710], -tags => ['handle6',"p3"], -filled => 1, -linewidth => 0, -fillcolor => "grey80");
$zinc->add('arc',$group,[740, 790, 760, 810], -tags => ['handle6',"p4"], -filled => 1, -linecolor => "blue",-fillcolor => "blue", -linewidth => 2);
$zinc->add('arc',$group,[766, 891, 784, 909], -tags => ['handle6',"p5"], -filled => 1, -linecolor => "grey80", -linewidth => 4);
$zinc->add('arc',$group,[865, 890, 885, 910], -tags => ['handle6',"p6"], -filled => 1, -linewidth => 0, -fillcolor => "grey80");
$zinc->add('arc',$group,[890, 790, 910, 810], -tags => ['handle6',"p7"], -filled => 1, -linecolor => "grey80", -linewidth => 2);

$zinc->scale($group, 0.6, 0.6);

## Set the text of the text item with a tag "tag"
## to a human-readable form of the coords of the
## corresponding curve with the same tag "tag"
sub setText {
    my ($tag) = @_;
    my $textItem = $zinc->find("withtype", 'text', $tag);
    my $curveItem = $zinc->find("withtype", 'curve', $tag);
    my @coords = $zinc->coords($curveItem);
    my $count = 0;
    my $text = "[ ";
    while (@coords) {
	$refXYc = pop @coords;
	my $x=sprintf "%i", $refXYc->[0];
	my $y=sprintf "%i", $refXYc->[1];
	my $t=$refXYc->[2];
	$t = (defined $t) ? ", '".$t."'" : "" ;
	$text .= "[$x, $y$t]";
	if (@coords) { $text .= ", "; }
	if ($count and @coords) {
	    $text .= "\n   ";
	    $count =0;
	} else {
	    $count++;
	}
    }
    $text .= " ]";
    $zinc->itemconfigure($textItem, -text => $text);
}

foreach my $bezierCount (1..6) {
    &setText ("bezier".$bezierCount);
    my $curveItem = $zinc->find("withtype", 'curve', "bezier".$bezierCount);
    my @coords = $zinc->coords($curveItem);
#    print "$bezierCount : ", scalar @coords, "\n";
    $zinc->bind("handle$bezierCount", '<ButtonPress-1>', [\&press, \&motion]);
    $zinc->bind("handle$bezierCount", '<ButtonRelease-1>', [\&release]);
}



&Tk::MainLoop;


##### bindings for moving the handles
my ($cur_x, $cur_y,$item, $bezierNum, $ptNum);
sub press {
    my ($zinc, $action) = @_;
    my $ev = $zinc->XEvent();
    $cur_x = $ev->x;
    $cur_y = $ev->y;
    $item = $zinc->find('withtag', 'current');
    $zinc->bind($item, '<Motion>', [$action]);
    foreach ( $zinc->gettags($item) ) {
	## looking for the tag "handlei"
	if ( /^handle(\d+)$/ ) {
	    $bezierNum = $1;
	}
	## looking for the tag "pj"
	if ( /^p(\d+)$/ ) {
	    $ptNum = $1;
	}
    }
#    print "bezierNum=$bezierNum ptNum=$ptNum\n";
}

sub motion {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my ($dx,$dy) = $zinc->transform($group, [$lx-$cur_x, $ly-$cur_y]);
    &moveHandle($item,$dx,$dy);
    my ($pt1,$pt2) = $zinc->coords($item);
#    print "coords=",@{$pt1}, " ",@{$pt2},"\n";
    $cur_x = $lx;
    $cur_y = $ly;
}

sub release {
    my ($zinc) = @_;
    $zinc->bind($item,'<Motion>', '');
    $item = "";
}

sub moveHandle {
    my ($item,$dx,$dy) = @_;
    my ($pt1,$pt2) = $zinc->coords($item);
    ## modifying the handle coords
    $zinc->coords($item, [ $pt1->[0]+$dx, $pt1->[1]+$dy, $pt2->[0]+$dx, $pt2->[1]+$dy]);
    my $prevPtNum = $ptNum-1;
    # there should only be one such item!
    my $lineA = $zinc->find("withtag", "line$bezierNum && l$prevPtNum-$ptNum");
    if (defined $lineA) {
	my ($x,$y) = $zinc->coords($lineA,0,1); # to get the 2nd point coords
	$zinc->coords($lineA, 0,1, [ $x+$dx, $y+$dy ]);
    }

    my $nextPtNum = $ptNum+1;
    # there should only be one such item:
    my ($lineB) = $zinc->find("withtag", "line$bezierNum && l$ptNum-$nextPtNum");
    if (defined $lineB) {
	my ($x,$y) = $zinc->coords($lineB,0,0); # to get the 1st point coords
	$zinc->coords($lineB, 0,0, [ $x+$dx, $y+$dy ] );
    }

    my ($x,$y,$control) = $zinc->coords("bezier$bezierNum", 0,$ptNum-1);
    $zinc->coords("bezier$bezierNum", 0,$ptNum-1, [ [$x+$dx, $y+$dy, $control] ] );
    &setText ("bezier$bezierNum");
	
}
    

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/fillrule.pl.











































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

####### This file has been largely inspired from figure 11-3
####### of "The OpenGL Programming Guide 3rd Edition, The 
####### Official Guide to Learning OpenGL Version 1.2",  ISBN 0201604582

####### it illustrates the use of :
#######   -fillrule attribute of curves
#######   contour, coords and clone method

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk::Zinc;


my $mw = MainWindow->new();
$mw->title('example of multiple contours and fillrule usage');

my $zinc = $mw->Zinc(-width => 510, -height => 630,
		     -font => "10x20",
		     -font => "9x15",
		     -borderwidth => 0,
                     -backcolor => "white",
		      )->pack;

$zinc->add('text', 1, -position => [20,8], -text => "This (still static) example reproduces figure 11-3
of \"The OpenGL Programming Guide 3rd Edition\" V 1.2");

my $group = $zinc->add('group', 1);

my $g1 = $zinc->add('group', $group);
my $curve1 = $zinc->add('curve',$g1, []);
$zinc->contour($curve1, "add", +1, [ 0,0, 0,120, 120,120, 120,0, 0,0]);
$zinc->contour($curve1, "add", +1, [ 20,20, 20,100, 100,100, 100,20, 20,20]);
$zinc->contour($curve1, "add", +1, [ 40,40, 40,80, 80,80, 80,40, 40,40]);
$zinc->translate($g1, 40,40);


my $g2 = $zinc->add('group', $group);
my $curve2 = $zinc->add('curve',$g2, []);
$zinc->contour($curve2, "add", +1, [ 0,0, 0,120, 120,120, 120,0, 0,0]);
$zinc->contour($curve2, "add", -1, [ 20,20, 20,100, 100,100, 100,20, 20,20]);
$zinc->contour($curve2, "add", -1, [ 40,40, 40,80, 80,80, 80,40, 40,40]);
$zinc->translate($g2, 200,40);


my $g3 = $zinc->add('group', $group);
my $curve3 = $zinc->add('curve',$g3, []);
$zinc->contour($curve3, "add", +1, [ 20,0, 20,120, 100,120, 100,0, 20,0]);
$zinc->contour($curve3, "add", +1, [ 40,20, 60,120, 80,20, 40,20]);
$zinc->contour($curve3, "add", +1, [ 0,60, 0,80, 120,80, 120,60, 0,60]);
$zinc->translate($g3, 360,40);

my $g4 = $zinc->add('group', $group);
my $curve4 = $zinc->add('curve',$g4, []);
$zinc->contour($curve4, "add", +1, [ 0,0, 0,140, 140,140,  140,60,  60,60,  60,80, 80,80, 80,40, 40,40,
				     40,100, 100,100, 100,20, 20,20,
				     20,120, 120,120, 120,0, 0,0]);
$zinc->translate($g4, 520,40);

$zinc->scale($group, 0.6, 0.6);
$zinc->translate($group, 80,20);

$zinc->add('text',$group, -position => [-110, 40], -text => "contours\nand\nwinding\nnumbers");
$zinc->add('text',$group, -position => [-110, 170], -text => "winding\nrules");
my $dy = 0;
foreach my $fillrule ('odd', 'nonzero', 'positive', 'negative', 'abs_geq_2') {
    $dy += 160;
    $zinc->add('text',$group, -position => [-110, 100+$dy], -text => $fillrule eq 'odd' ? "odd\n(default)" : $fillrule);
    foreach my $item ($curve1, $curve2, $curve3, $curve4) {
	my $clone = $zinc->clone($item, -fillrule => $fillrule, -filled => 1);
	$zinc->translate($clone, 0,$dy);
    }
}

# creating simple lines with arrows under each curves
foreach my $item ($curve1, $curve2, $curve3, $curve4) {
    my $contour_number = $zinc->contour($item);
#    print "$item => contour_number=$contour_number\n";
    foreach my $n (0..$contour_number-1) {
	my @points = $zinc->coords($item,$n);
#	print "   ",$#points,"points\n";
	foreach my $i (0 .. $#points-1) {
#	    print "    line $i ",$i+1,"\n";
	    $firstpoint = $points[$i];
	    $lastpoint = $points[$i+1];
	    $middlepoint = [$firstpoint->[0]+($lastpoint->[0]-$firstpoint->[0])/1.5,
			    $firstpoint->[1]+($lastpoint->[1]-$firstpoint->[1])/1.5];
	    $zinc->add("curve", $zinc->group($item),
		       [ $firstpoint, $middlepoint],
		       -lastend => [7,10,4]);
	}
    }
}
&Tk::MainLoop;


    

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/groups_in_ATC_strips.pl.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
#!/usr/bin/perl -w
#-----------------------------------------------------------------------------------
#
#      Copyright (C) 2002
#      Centre d'Études de la Navigation Aérienne
#
#      Authors: Jean-Luc Vinot <vinot@cena.fr> for whole graphic design and coding
#               Christophe Mertz <mertz@cena.fr> for adding simple animations
#                                                and integration in zinc-demos
#                 This integration is still not perfect and requires an extension in zinc
#                 We must know if a neamed gradient already exists, when launching
#                 many time the same demo in the same process!
#
# $Id$
#-----------------------------------------------------------------------------------
#      This small application illustrates both the use of groups in combination
#         of -composescale attributes and an implementation of kind of air traffic
#         control electronic strips.
#      However it is only a simplified example given as is, without any immediate usage!
#
#      3 strips formats are accessible through "+" / "-" buttons on the right side
#
#      1.   small-format: with 2 lines of info, and reduced length
#
#      2.   normal-format: with 3 lines of info, full length
#
#      3.  extended-format: with 3 lines of infos, full length
#                           the 3 lines are zoomed
#                           an additionnel 4th lone is displayed
#
#      An additionnal 4th format (micro-format) is available when double-clicking somewhere...
#
#      Strips can be moved around by drag&drop from the callsign
#
#      When changing size, strips are animated. The animation is a very simple one,
#        which should be enhanced.... You can change the animation parameters, by modifyng
#        $delay and $steps.
#
#-----------------------------------------------------------------------------------

package groups_in_ATC_strips; # for avoiding symbol collision between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

$| = 1;


my @stripGradiants;
my %stripFontset;
my %textures;

my $oldfkey;
my ($dx, $dy);

my $delay = 50; # ms between each animation steps
my $steps = 6;  # number of steps for the animation
my %scales;     # this hash just memorizes the current x and y scaling ratio
                # In a real appli, this should be memorized in strip objects

#----------------------
# configuration data
#----------------------
my $fnb10 = 'cenapii-digistrips-b10';
my $fnb10c = 'cenapii-digistrips-b10c';
my $fnb11 = 'cenapii-digistrips-b11';
my $fnb12 = 'cenapii-digistrips-b12';
my $fnb15 = 'cenapii-radar-b15';
my $fnm20 = 'cenapii-radar-m20';
my $fne18 = 'cenapii-radar-m18';

my @ratio2fontset = ([1.2, 'normal'],
		     [10, 'large']);

my $mwidth = 700;
my $mheight = 500;

my %stripstyle = (-gradset => {'idnt' => '=axial 90 |#ffffff 0|#ffeedd 30|#e9d1ca 90|#e9a89a',
			       'back' => '=axial 0 |#c1daff|#8aaaff',
			       ## the following shadow gradient is sub-optimal
			       'shad' => '=path -40 -40 |#000000;50 0|#000000;50 92|#000000;0 100',
			       'btn_outside' => '=axial 0 |#ffeedd|#8a9acc', 
			       'btn_inside' => '=axial 180 |#ffeedd|#8a9acc',
			       'ch1' => '=axial 0 |#8aaaff|#5B76ED',
			   },
		  
		  -fontset => {'normal' => {'callsign' => $fnb15,
					    'type1' => $fnb12,
					    'type2' => $fnb10,
					    'type3' => $fnb10c,
					},
			       
			       'large' => {'callsign' => $fnm20,
					   'type1' => $fne18,
					   'type2' => $fnb15,
					   'type3' => $fnb12,
				       },
			   },
		  
		  -width => 340,
		  -height => 86,
		  -shadowcoords => [8, 8, 374, 94],
		  -shadowcolor => 'shad',

		  -strip => {-linewidth => 3,
			     -linecolor => '#aaccff',
			     -fillcolor => 'back',
			     -relief => 'roundraised',
			 },

		  -buttons => {-coords => [340, 0],
			       -clipcoords => [0, 0, 90, 83],
			       -zone => {-coords => [0, 0, 26, 85],
					 -fillcolor => 'btn_outside',
					 -linewidth => 0,
				     },
			    
			       -btns => {'btnup' => {-coords => [0, 0, 26, 43],
						     -arrow => [14, 2, 24, 40,
								1, 40, 14, 2],
						     -linewidth => 1,
						     -linecolor => '#aabadd',
						     -fillcolor => 'btn_inside',
						     -label => {-coords => [13, 27],
								-text => "+",
								-font => $fnm20,
								-color => '#ffffff',
								-anchor => 'center',
							    },
						 },
					 
					 'btndn' => {-coords => [0, 43, 26, 86],
						     -arrow => [14, 83, 24, 43,
								1, 43, 14, 83],
						     -linewidth => 1,
						     -linecolor => '#aabadd',
						     -fillcolor => 'btn_inside',
						     -label => {-coords => [13, 56],
								-text => "-",
								-font => $fnm20,
								-color => '#ffffff',
								-anchor => 'center',
							    },
						 },
				     },
			   },
		  
		  -clipcoords => [3, 3, 332, 80],
		  -zones => {'ident' => {-coords => [3, 3, 90, 50],
					 -atomic => 1,
					 -priority => 200,
					 -sensitive => 1,
					 -tags => "move",
					 -linewidth => 1,
					 -filled => 1,
					 -relief => 'sunken',
					 -linecolor => '#ffeedd',
					 -fillcolor => 'idnt',
					 -fields => {-callsign => {-coords => [10, 18],
								   -font => 'callsign',
								   -text => 'EWG361',
								   -anchor => 'w',
								   -color => '#000000',
							       },
						     -company => {-coords => [10, 34],
								  -font => 'type2',
								  -text => 'Eurowing',
								  -anchor => 'w',
								  -color => '#444444',
							      },
						 },
				     },
			     'input' => {-coords => [3, 3, 334, 82],
					 -atomic => 1,
					 -priority => 100,
					 -sensitive => 1,
					 -tags => "scale",
					 -linewidth => 0,
					 -filled => 1,
					 -relief => 'flat',
					 -linecolor => 'white',
					 -fillcolor => 'back', #'#afb2cc',
					 -fields => {-type => {-coords => [100, 18],
							       -font => 'type1',
							       -text => 'TYPA',
							       -anchor => 'w',
							       -color => '#444444',
							   },
						     -cfmu => {-coords => [200, 18],
							       -font => 'type1',
							       -text => '08:26',
							       -anchor => 'e',
							       -color => '#444444',
							   },
						     -ptsid => {-coords => [100, 40],
							       -font => 'type2',
							       -text => 'NIPOR',
							       -anchor => 'w',
							       -color => '#444444',
							   },
						     -confsid => {-coords => [158, 40],
							       -font => 'type2',
							       -text => '8G',
							       -anchor => 'center',
							       -color => '#444444',
							   },
						     -park => {-coords => [200, 40],
							       -font => 'type2',
							       -text => 'G23',
							       -anchor => 'e',
							       -color => '#444444',
							   },
						     
						     -dest => {-coords => [10, 66],
							       -font => 'type2',
							       -text => 'DEST',
							       -anchor => 'w',
							       -color => '#555555',
							   },
						     -champ1 => {-type => 'rect',
								 -coords => [45, 56,
									     135, 76],
								 -filled => 1,
								 -fillcolor => 'ch1',
								 -linecolor => 'white',
								 -linewidth => 0,
							   },
						     -bret => {-coords => [200, 66],
							       -font => 'type2',
							       -text => 'Bret.',
							       -anchor => 'e',
							       -color => '#444444',
							   },
						 },
				     },
			     
			     'zreco' => {-coords => [210, 3, 346, 82],
					 -atomic => 1,
					 -priority => 200,
					 -texture => "stripped_texture.gif",
					 -sensitive => 1,
					 -tags => "edit",
					 -linewidth => 2,
					 -filled => 1,
					 -relief => 'sunken',
					 -linecolor => '#deecff',
					 -fillcolor => '#d3e5ff',
				     },

			     
			 },
		  
		  -zinfo => {-coords => [0, 86],
			     -rectcoords => [0, 0, 340, 20],
			     -shadowcoords => [8, 8, 348, 28],
			     -shadowcolor => 'shad',
			     -atomic => 1,
			     -priority => 200,
			     -sensitive => 1,
			     -tags => "edit2",
			     -linewidth => 2,
			     -linecolor => '#aaccff',
			     -fillcolor => 'back',
			     -relief => 'roundraised',
			     -fields => {-ssr => {-coords => [4, 10],
						  -font => 'type3',
						  -text => '7656',
						  -anchor => 'w',
						  -color => '#444444',
					      },
					 -pdep => {-coords => [47, 10],
						  -font => 'type3',
						  -text => 'G23',
						  -anchor => 'center',
						  -color => '#444444',
					      },
					 -qfu => {-coords => [73, 10],
						  -font => 'type3',
						  -text => '09R',
						  -anchor => 'center',
						  -color => '#444444',
					      },
					 -slabel => {-coords => [105, 10],
						  -font => 'type3',
						  -text => 'vit:',
						  -anchor => 'e',
						  -color => '#444444',
					      },
					 -speed => {-coords => [106, 10],
						    -font => 'type3',
						    -text => '260',
						    -anchor => 'w',
						    -color => '#444444',
					      },
					 -pper => {-coords => [142, 10],
						  -font => 'type3',
						  -text => 'EPL',
						  -anchor => 'center',
						  -color => '#444444',
					      },
					 -rfl => {-coords => [166, 10],
						  -font => 'type3',
						  -text => '210',
						  -anchor => 'center',
						  -color => '#444444',
					      },
					 -cautra => {-coords => [183, 10],
						  -font => 'type3',
						  -text => '8350',
						  -anchor => 'w',
						  -color => '#444444',
					      },
					 -nsect => {-coords => [219, 10],
						  -font => 'type3',
						  -text => 'MOD',
						  -anchor => 'w',
						  -color => '#444444',
					      },
					 -day => {-coords => [297, 10],
						  -font => 'type3',
						  -text => '21/05/02',
						  -anchor => 'e',
						  -color => '#444444',
					      },
					 -hour => {-coords => [332, 10],
						  -font => 'type3',
						  -text => '13:50',
						  -anchor => 'e',
						  -color => '#444444',
					      },
			     },
					 
			  },
		  );

# creation de la fenetre principale
my $mw;
$mw = MainWindow->new();

# The explanation displayed when running this demo
my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2,
		     -setgrid => 'true', -height =>7);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
'These fake air Traffic Control electronic strips illustrates
 the use of groups for an advanced graphic design.
The following interactions are possible:
   "drag&drop button1" on the callsign.
   "button 1" triangle buttons on the right side of the strips
    to modify strips size
   "double click 1" on the blueish zone to fully reduce size');

$mw->title('ATC strips using groups');


#------------------------
# creation du widget Zinc
my $zinc = $mw->Zinc(-render => 1,
		     -width => $mwidth,
		     -height => $mheight,
		     -borderwidth => 0,
		     -lightangle => 130,
		     );
		     
$zinc->pack(-fill => 'both', -expand => 1);

my $texture = $zinc->Photo('background_texture.gif',
			   -file => Tk->findINC('demos/zinc_data/background_texture.gif'));
$zinc->configure(-tile => $texture) if $texture;



my ($xn, $yn) = (10, 30);

# test Strips
for (my $index = 0; $index < 4 ; $index++) {
    
    &createStrip($index, $xn, $yn, \%stripstyle);

    $xn += 50;
    $yn += 120;

}


&initBindings('move', 'scale');


	 

Tk::MainLoop;

#----------------------------------------------------------------------- fin de MAIN


# Création du Strip
sub createStrip {
    my ($index, $x, $y, $style) = @_;

    # initialise les gradiants
    unless (@stripGradiants) {
	my %gradiants = %{$style->{'-gradset'}};
	my ($name, $gradiant);
	while (($name, $gradiant) = each(%gradiants)) {
	    # création des gradients nommés
	    $zinc->gname($gradiant, $name) unless $zinc->gname($gradiant);
	    # the previous test is usefull only
	    # when this script is executed many time in the same process
	    # (it is typically the case in zinc-demos)

	    push(@stripGradiants, $name);
	}  
    }
  
    # initialise les jeux de fontes 
    unless (%stripFontset) {
	%stripFontset = %{$style->{'-fontset'}};
    }

    # création du groupe de base : coords
    my $g1 = $zinc->add('group', 1, -priority => 100, -tags => ["base".$index]);
    $zinc->coords($g1, [$x, $y]);

    # group de transfo 1 : scaling (à partir du coin haut droit)
    my $g2 = $zinc->add('group', $g1, -tags => ["scaling".$index]);


    #-------------------------------------------------------------
    # réalisation du strip lui même (papier support + ombre portée
    #-------------------------------------------------------------
    
    # params strip
    my $stripw = $style->{'-width'};
    my $striph = $style->{'-height'};
    
    # ombre portée
    $zinc->add('rectangle', $g2,
	       $style->{'-shadowcoords'},
	       -filled => 1,
	       -linewidth => 0,
	       -fillcolor => $style->{'-shadowcolor'},
	       -priority => 10,
	       -tags => ["shadow".$index],
	       );


    # strip
    my $sstyle = $style->{'-strip'};    
    my $strip = $zinc->add('rectangle', $g2,
			   [0, 0, $stripw, $striph],
			   -filled => 1,
			   -linewidth => $sstyle->{'-linewidth'},
			   -linecolor => $sstyle->{'-linecolor'},
			   -fillcolor => $sstyle->{'-fillcolor'},
			   -relief => $sstyle->{'-relief'},
			   -priority => 20,
			   -tags => ["strip".$index],
			   );

    if ($sstyle->{'-texture'}) {
	if (!exists($textures{'-strip'})) {
	    my $texture = $zinc->Photo($sstyle->{'-texture'}, 
                                       -file => Tk->findINC("demos/zinc_data/".$sstyle->{-texture}));
	    $textures{'-strip'} = $texture;
	}
	    
	$zinc->itemconfigure($strip, -tile => $textures{'-strip'});
    }
    

    #-------------------------------------------------
    # ajout de la zone des boutons (à droite du strip)
    #-------------------------------------------------
    if ($style->{'-buttons'}) {
	my $bstyle = $style->{'-buttons'};

	# le groupe de la zone bouton
	my $btngroup = $zinc->add('group', $g2, -priority => 40);
	$zinc->coords($btngroup, $bstyle->{'-coords'});

	# sa zone de clipping
	my $btnclip = $zinc->add('rectangle', $btngroup,
				 $bstyle->{'-clipcoords'},
				 -filled => 0,
				 -visible => 0,
				 );
	
	# le clipping du groupe bouton
	$zinc->itemconfigure($btngroup, -clip => $btnclip);
	
	# zone bouton
	$zinc->add('rectangle', $btngroup,
		   $bstyle->{'-zone'}->{'-coords'},
		   -filled => 1,
		   -linewidth => $bstyle->{'-zone'}->{'-linewidth'},
		   -fillcolor => $bstyle->{'-zone'}->{'-fillcolor'},
		   -composescale => 0,
		   -tags => ["content".$index],
		   );
	

	my %btns = %{$bstyle->{'-btns'}};
	my ($name, $btnstyle);
	while (($name, $btnstyle) = each(%btns)) {
#	    print "bouton $name $btnstyle\n";

	    my $sgroup = $zinc->add('group', $btngroup,
				    -atomic => 1,
				    -sensitive => 1,
				    -composescale => 0,
				    -tags => [$name.$index, "content".$index],
				    );

	    $zinc->add('rectangle', $sgroup,
		       $btnstyle->{'-coords'},
		       -filled => 1,
		       -visible => 0,
		       -priority => 100,
		       );
	
	    $zinc->add('curve', $sgroup,
		       $btnstyle->{'-arrow'},
		       -closed => 1,
		       -filled => 1,
		       -linewidth => $btnstyle->{'-linewidth'},
		       -linecolor => $btnstyle->{'-linecolor'},
		       -fillcolor => $btnstyle->{'-fillcolor'},
		       -priority => 50,
		       );

	    $zinc->add('text', $sgroup,
		       -position => $btnstyle->{'-label'}->{'-coords'},
		       -text => $btnstyle->{'-label'}->{'-text'},
		       -font => $btnstyle->{'-label'}->{'-font'},
		       -color => $btnstyle->{'-label'}->{'-color'},
		       -anchor => $btnstyle->{'-label'}->{'-anchor'},
		       -priority => 60,
		       );
	}

	# bindings boutons Up et Down du Strip
	$zinc->bind('btnup'.$index, '<1>', \&extendedStrip);
	$zinc->bind('btndn'.$index, '<1>', \&smallStrip);
	
    }

    # construction du contenu du strip
    &buildContent($index, $g2, 100, $style);

    # et de la barre d'extension info (extended format)
    &buildExtent($index, $g2, $style->{'-zinfo'});

}


# Construction des zones internes du Strips
sub buildContent {
    my ($index, $parent, $priority, $style) = @_;
    
    # group content
    my $g3 = $zinc->add('group', $parent, -priority => $priority);

    # zone de clipping
    my $clip = $zinc->add('rectangle', $g3,
			  $style->{'-clipcoords'},
			  -filled => 0,
			  -visible => 0,
			  );
    
    # clipping du groupe content
    $zinc->itemconfigure($g3, -clip => $clip);

    # création d'un group intermédiaire pour bloquer le scaling
    my $g4 = $zinc->add('group', $g3,
			-composescale => 0,
			-tags => ["content".$index],
			);
    
    # création des zones
    my %zones = %{$style->{'-zones'}};
    my ($name, $zonestyle);
    while (($name, $zonestyle) = each(%zones)) {
	# group de zone
	my $gz = $zinc->add('group', $g4);

	if ($zonestyle->{'-atomic'}) {
	    $zinc->itemconfigure($gz, -atomic => 1,
				 -sensitive => $zonestyle->{'-sensitive'},
				 -priority => $zonestyle->{'-priority'},
				 -tags => [$name.$index, $zonestyle->{'-tags'}],
				 );
	}
	
	my $rectzone = $zinc->add('rectangle', $gz,
				  $zonestyle->{'-coords'},
				  -filled => $zonestyle->{'-filled'},
				  -linewidth => $zonestyle->{'-linewidth'},
				  -linecolor => $zonestyle->{'-linecolor'},
				  -fillcolor => $zonestyle->{'-fillcolor'},
				  -relief => $zonestyle->{'-relief'},
				  -priority => 10,
				  -tags => [$name.$index],
				  );

	if ($zonestyle->{'-texture'}) {
	    if (!exists($textures{$name})) {
		my $texture = $zinc->Photo($zonestyle->{'-texture'}, 
                                           -file => Tk->findINC("demos/zinc_data/".$zonestyle->{-texture}));
		$textures{$name} = $texture;
	    }

	    $zinc->itemconfigure($rectzone, -tile => $textures{$name});
	}


	my %fields;
	%fields = %{$zonestyle->{'-fields'}} if (defined $zonestyle->{'-fields'}) ;
	my ($field, $fieldstyle);
	my $fontsty = $stripFontset{'normal'};
	while ( ($field, $fieldstyle) = each(%fields) ) {
	    if ($fieldstyle->{'-type'} and $fieldstyle->{'-type'} eq 'rect') {
		$zinc->add('rectangle', $gz,
			   $fieldstyle->{'-coords'},
			   -filled => $fieldstyle->{'-filled'},
			   -fillcolor => $fieldstyle->{'-fillcolor'},
			   -linewidth => $fieldstyle->{'-linewidth'},
			   -linecolor => $fieldstyle->{'-linecolor'},
			   -priority => 20,
			   );
		} else {
		
		    my $font = $fieldstyle->{'-font'};
#		    print "buildContent field:$field font:$font\n";
		    $zinc->add('text', $gz,
			       -position => $fieldstyle->{'-coords'},
			       -text => $fieldstyle->{'-text'},
			       -font => $fontsty->{$font},
			       -color => $fieldstyle->{'-color'},
			       -anchor => $fieldstyle->{'-anchor'},
			       -priority => 30,
			       -tags => [$font.$index],
			       );
		}
		
	}

    }
}


# Construction de la barre d'extension info du Strip
sub buildExtent {
    my ($index, $parent, $infostyle) = @_;
    
    # group content
    my $extgroup = $zinc->add('group', $parent);
    $zinc->coords($extgroup, $infostyle->{'-coords'});

    $zinc->itemconfigure($extgroup,
			 -atomic => $infostyle->{'-atomic'},
			 -sensitive => $infostyle->{'-sensitive'},
			 -priority => $infostyle->{'-priority'},
			 -visible => 0,
			 -tags => ["zinfo".$index, $infostyle->{'-tags'}],
			 );

    # ombre portée
    $zinc->add('rectangle', $extgroup,
	       $infostyle->{'-shadowcoords'},
	       -filled => 1,
	       -linewidth => 0,
	       -fillcolor => $infostyle->{'-shadowcolor'},
	       -priority => 10,
	       -tags => ["shadow".$index],
	       );
    
    my $rectzone = $zinc->add('rectangle', $extgroup,
  			      $infostyle->{'-rectcoords'},
  			      -filled => 1,
  			      -linewidth => $infostyle->{'-linewidth'},
  			      -linecolor => $infostyle->{'-linecolor'},
  			      -fillcolor => $infostyle->{'-fillcolor'},
  			      -relief => $infostyle->{'-relief'},
  			      -priority => 20,
  			      );

    if ($infostyle->{'-texture'}) {
  	if (!exists($textures{'-zinfo'})) {
  	    my $texture = $zinc->Photo($infostyle->{'-texture'}, 
                                       -file => Tk->findINC("demos/zinc_data/".$infostyle->{-texture}));
  	    $textures{'-zinfo'} = $texture;
  	}
  	$zinc->itemconfigure($rectzone, -tile => $textures{'-zinfo'});
	
    }

    my %fields = %{$infostyle->{'-fields'}};
    my ($field, $fieldstyle);
    my $fontsty = $stripFontset{'normal'};
    while (($field, $fieldstyle) = each(%fields)) {
	if ($fieldstyle->{'-type'} and $fieldstyle->{'-type'} eq 'rect') {
	    $zinc->add('rectangle', $extgroup,
		       $fieldstyle->{'-coords'},
		       -filled => $fieldstyle->{'-filled'},
		       -fillcolor => $fieldstyle->{'-fillcolor'},
		       -linewidth => $fieldstyle->{'-linewidth'},
		       -linecolor => $fieldstyle->{'-linecolor'},
		       -priority => 40,
		       );
	} else {
	    
	    my $font = $fieldstyle->{'-font'};
#	    print "buildContent field:$field font:$font\n";
	    $zinc->add('text', $extgroup,
		       -position => $fieldstyle->{'-coords'},
		       -text => $fieldstyle->{'-text'},
		       -font => $fontsty->{$font},
		       -color => $fieldstyle->{'-color'},
		       -anchor => $fieldstyle->{'-anchor'},
		       -priority => 50,
		       -tags => [$font.$index],
		       );
	}
	
    }
    
}

# initialisation des bindings généraux dy Strip
sub initBindings {
    my ($movetag, $scaletag) = @_;

    $zinc->bind($movetag, '<1>', \&catchStrip);
    $zinc->bind($movetag, '<ButtonRelease>', \&releaseStrip);
    $zinc->bind($movetag, '<B1-Motion>', \&motionStrip);

    $zinc->bind($scaletag, '<Double-Button-1>', \&microStrip);

}
    
# Callback CATCH de début de déplacement du Strip
sub catchStrip {
    my $index = substr(($zinc->itemcget('current', -tags))[0], 5);

    my ($x, $y) = $zinc->coords("base".$index);
    my $ev = $zinc->XEvent;
    ($dx, $dy) = ($x - $ev->x, $y - $ev->y);

    $zinc->itemconfigure("base".$index, -priority => 200);

}

# Callback MOVE de fin de déplacement du Strip
sub motionStrip {
    my $index = substr(($zinc->itemcget('current', -tags))[0], 5);
    my $ev = $zinc->XEvent;
    $zinc->coords("base".$index, [$ev->x + $dx, $ev->y + $dy]);
    
}

# Callback RELEASE de fin de déplacement du Strip
sub releaseStrip {
    my $index = substr(($zinc->itemcget('current', -tags))[0], 5);
    $zinc->itemconfigure("base".$index, -priority => 100);
}

# Zoom Strip : normal format
sub normalStrip {
    my $index = substr(($zinc->itemcget('current', -tags))[0], 5);

    $zinc->itemconfigure("input".$index, -sensitive => 1);

    &displayRecoZone($index, 1);
    &displayExtentZone($index, 0);
    &configButtons($index, \&extendedStrip, \&smallStrip);
    &changeStripFormat($index, 1, 1, 0, 1);
}

# Zoom Strip : small format (lignes 1 et 2)
sub smallStrip {
    my $index = substr(($zinc->itemcget('current', -tags))[0], 5);

    &displayRecoZone($index, 0);
    &configButtons($index, \&normalStrip, 0);
    &changeStripFormat($index, 1, .63, 0, 1);
}

# Zoom Strip : micro format (zone ident)
sub microStrip {
    my $index = substr(($zinc->itemcget('current', -tags))[0], 5);
    
    &configButtons($index, \&normalStrip, 0);
    &changeStripFormat($index, .28, .63, 0, 1);
    
}

# Zoom Strip : extendedFormat
sub extendedStrip {
    my $index = substr(($zinc->itemcget('current', -tags))[0],5);

    $zinc->itemconfigure("input".$index, -sensitive => 0);
    $zinc->itemconfigure("base".$index, -priority => 150);
    &displayRecoZone($index, 0);
    &displayExtentZone($index, 1);
    &configButtons($index, 0, \&normalStrip);
    &changeStripFormat($index, 1.3, 1.3, 1, 1.3);
}


# affiche/masque la zone Reco
sub displayRecoZone {
    my ($index, $state) = @_;
    my $priority = ($state) ? 200 : 0;
    $zinc->itemconfigure("zreco".$index, -priority => $priority);
}


# affiche/masque la zone Extent
sub displayExtentZone {
    my ($index, $state) = @_;

    $zinc->itemconfigure("zinfo".$index,
			 -visible => $state,
			 -sensitive => $state);
}

# Configure affichage et callbacks des boutons du Strip
sub configButtons {
    my ($index, $funcUp, $funcDown) = @_;

    # button Up
    $zinc->itemconfigure("btnup".$index, -visible => $funcUp);
    $zinc->bind('btnup'.$index, '<1>', $funcUp) if $funcUp;

    # button Down
    $zinc->itemconfigure("btndn".$index, -visible => $funcDown);
    $zinc->bind('btndn'.$index, '<1>', $funcDown) if $funcDown;

}

    
# this function has been hacked to provide the user with an animation
# The animation is (too) simple but provide a better feedback than without
sub changeStripFormat {
    my ($index, $xratio, $yratio, $composeflag, $fontratio) = @_;

    # réinitialisation du groupe scaling
    $zinc->treset("scaling".$index);

    # configure le blocage de transformation du format des champs
    $zinc->itemconfigure("content".$index, -composescale => $composeflag);

    # applique le nouveau scaling
    $scales{$index} = [1,1] unless defined $scales{$index};
    my ($oldXratio,$oldYratio) = @{$scales{$index}};
    $scales{$index}=[$xratio, $yratio];
    my $dx = ($xratio - $oldXratio) / $steps;
    my $dy = ($yratio - $oldYratio) / $steps;
    &_resize($index, $delay, $oldXratio+$dx, $oldYratio+$dy, $dx, $dy, $steps);
}

sub _resize {
    my ($index, $delay, $newXratio, $newYratio, $dx, $dy, $steps) = @_;
    $zinc->treset("scaling".$index);
    $zinc->scale("scaling".$index, $newXratio, $newYratio);
    # jeu de fontes
    &setFontes($index, $newYratio);
    $steps--;
    $zinc->after($delay, sub {&_resize ($index, $delay, $newXratio+$dx, $newYratio+$dy, $dx, $dy, $steps)})
	if $steps > 0;
}

sub getFKey {
    my ($ratio) = @_;
    my $newfkey;
   
    foreach my $param (@ratio2fontset) {
	my ($maxratio, $fkey) = @{$param};
	$newfkey = $fkey;
	if ($ratio < $maxratio) {
	    return $newfkey;
	}
    }
	
    return $newfkey;
}


sub setFontes {
    my ($index, $ratio) = @_;
    my $newfkey = &getFKey($ratio);
    
    if (!$oldfkey or $oldfkey ne $newfkey) {
	my $fontsty = $stripFontset{$newfkey};
#	print "setFontes $oldfkey -> $newfkey\n";
	if ($fontsty) {
	    foreach my $type ('callsign', 'type1', 'type2', 'type3') {
		$zinc->itemconfigure($type.$index, -font => $fontsty->{$type});
	    }
	}
	
	$oldfkey = $newfkey;
    }
}

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/groups_priority.pl.











































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

package groups_priority;  # for avoiding symbol sharing between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;

use strict;

my $mw = MainWindow->new();

# The explanation displayed when running this demo
my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2,
		     -height => 12);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
'There are two groups (a red one and a green one) each containing
 4 rectangles. Those rectangles display their current priority.
The following operations are possible:
   "Mouse Button 1" for dragging objects.
   "Mouse Button 2" for dragging a colored group.
   "Key +" on a rectangle to raise it inside its group.
   "Key -" on a rectangle to lower it inside its group.
   "Key l" on a rectangle to lower its colored group.
   "Key r" on a rectangle to raise its colored group.
   "Key t" on a rectangle to change its group (but not its color!).
   "Key [0-9] on a rectangle to set the priority to [0-9]
Raising or lowering an item inside a group modify its priority if necessary');

# Creating the zinc widget
my $zinc = $mw->Zinc(-width => 600, -height => 500,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

#########################################################################"
# Creating the redish group
my $group1 = $zinc->add('group', 1, -visible => 1);

my $counter=0;
# Adding 4 rectangles with text to redish group
foreach my $data ( [200,100, 'red'], [210,210,'red1'],
		   [390,110,'red2'], [395,215,'red3'] ) {
    $counter += 2;
    my ($centerx,$centery,$color) = @{$data};
    # this small group is for merging together :
    #   the rectangle and the text showing its name
    my $g = $zinc->add('group', $group1,
		       -visible => 1,
		       -atomic => 1,
		       -sensitive => 1,
		       -priority => $counter,
		       );
    my $rec = $zinc->add('rectangle', $g, [$centerx-100,$centery-60,
					   $centerx+100, $centery+60],
			  -fillcolor => $color, -filled => 1,
			  );
    my $txt = $zinc->add('text', $g,
			 -position => [$centerx,$centery],
			 -text => "pri=$counter",
			 -anchor => 'center',
			 );
    # Some bindings for dragging the rectangle or the full group
    $zinc->bind($g, '<ButtonPress-1>' => [\&press, $g, \&motion]);
    $zinc->bind($g, '<ButtonRelease-1>' => \&release);
    $zinc->bind($g, '<ButtonPress-2>' => [\&press, $g, \&groupMotion]);
    $zinc->bind($g, '<ButtonRelease-2>' => \&release);
}

#########################################################################"
# Creating the greenish group
my $group2 = $zinc->add('group', 1, -visible => 1);
$counter=0;

# Adding 4 rectangles with text to greenish group
foreach my $data ( [200,300,'green1'], [210,410,'green2'],
		   [390,310,'green3'], [395,415,'green4'] ) {
    $counter++;
    my ($centerx,$centery,$color) = @{$data};
    # this small group is for merging together a rectangle
    # and the text showing its priority
    my $g = $zinc->add('group', $group2,
		       -atomic => 1,
		       -sensitive => 1,
		       -priority => $counter,
		       );
    my $rec = $zinc->add('rectangle', $g, [$centerx-100,$centery-60,
					   $centerx+100, $centery+60],
			  -fillcolor => $color, -filled => 1,
			  );
    my $txt = $zinc->add('text', $g,
			 -position => [$centerx,$centery],
			 -text => "pri=$counter",
			 -anchor => 'center',
			 );
    # Some bindings for dragging the rectangle or the full group
    $zinc->bind($g, '<ButtonPress-1>' => [\&press, $g, \&motion]);
    $zinc->bind($g, '<ButtonRelease-1>' => \&release);
    $zinc->bind($g, '<ButtonPress-2>' => [\&press, $g, \&groupMotion]);
    $zinc->bind($g, '<ButtonRelease-2>' => \&release);
}


#########################################################################"
# adding the key bindings

# the focus on the widget is ABSOLUTELY necessary for key bindings!
$zinc->Tk::focus(); 

$zinc->Tk::bind('<KeyPress-r>' => \&raiseGroup);
$zinc->Tk::bind('<KeyPress-l>' => \&lowerGroup);
$zinc->Tk::bind('<KeyPress-plus>' => \&raise);
$zinc->Tk::bind('<KeyPress-KP_Add>' => \&raise);
$zinc->Tk::bind('<KeyPress-minus>' => \&lower);
$zinc->Tk::bind('<KeyPress-KP_Subtract>' => \&lower);
$zinc->Tk::bind('<KeyPress-t>' => \&toggleItemGroup);

my @KP_MAPPINGS = qw (Insert End Down Next Left Begin Right Home Up Prior);

for my $i (0..9) {
    $zinc->Tk::bind("<KeyPress-$i>" => [\&setPriorrity, $i]);
    my $code = $KP_MAPPINGS[$i];
    $zinc->Tk::bind("<KeyPress-KP_$code>" => [\&setPriorrity, $i]);
}

# The following binding is currently not possible; only text items
# with focus can get a KeyPress or KeyRelease event
#    $zinc->bind($g, '<KeyPress>' => [\&raise, $g]);

#########################################################################"
# Definition of all callbacks

sub updateLabel {
    my ($group) = @_;
    my $priority = $zinc->itemcget($group, -priority);
    # we get the text item from this group:
    my $textitem = $zinc->find('withtype', 'text', ".$group.");
    $zinc->itemconfigure($textitem, -text => "pri=$priority");
}

sub setPriorrity {
    my ($zinc, $priority) = @_;
    my $item = $zinc->find('withtag', 'current');
    return unless $item;
    $zinc->itemconfigure ($item, -priority => $priority);
    &updateLabel($item);
}
    

# Callback to lower a small group of a rectangle and a text
sub lower {
    my ($zinc) = @_;
    # to get the item under the cursor!
    my $item = $zinc->find('withtag', 'current');
    return unless $item;
    $zinc->lower($item);
    &updateLabel($item);
}

# Callback to raise a small group of a rectangle and a text
sub raise {
    my ($zinc) = @_;
    # to get the item under the cursor!
    my $item = $zinc->find('withtag', 'current');
    return unless $item;
    $zinc->raise($item);
    &updateLabel($item);
}

# Callback to raise the group of groups of a rectangle and a text
sub lowerGroup {
    my ($zinc) = @_;
    # to get the item under the cursor!
    my $item = $zinc->find('withtag', 'current');
    return unless $item;
    my $coloredGroup = $zinc->group($item);
    $zinc->lower($coloredGroup);
}

# Callback to raise the group of groups of a rectangle and a text
sub raiseGroup {
    my ($zinc) = @_;
    # to get the item under the cursor!
    my $item = $zinc->find('withtag', 'current');
    return unless $item;
    my $coloredGroup = $zinc->group($item);
    $zinc->raise($coloredGroup);
    &updateLabel($item);
}

# Callback to change the group of groups of a rectangle and a text
sub toggleItemGroup {
    my ($zinc) = @_;
    # to get the item under the cursor!
    my $item = $zinc->find('withtag', 'current');
    return unless $item;
    my $newgroup;
    if ($group1 == $zinc->group($item)) {
	$newgroup = $group2;
    }
    else {
	$newgroup = $group1;
    }
    
    $zinc->chggroup($item,$newgroup,1); ## the lats argument is true for mainting $item' position
    &updateLabel($item);
}

# callback for starting a drag
my ($x_orig, $y_orig);
sub press {
    my ($zinc, $group, $action) = @_;
    my $ev = $zinc->XEvent();
    $x_orig = $ev->x;
    $y_orig = $ev->y;
    $zinc->Tk::bind('<Motion>', [$action, $group]);
}

# Callback for moving a small group of a rectangle and a text
sub motion {
    my ($zinc, $group) = @_;
    my $ev = $zinc->XEvent();
    my $x = $ev->x;
    my $y = $ev->y;

    $zinc->translate($group, $x-$x_orig, $y-$y_orig);
    $x_orig = $x;
    $y_orig = $y;
}

# Callback for moving a group of groups of a rectangle and a text
sub groupMotion {
    my ($zinc, $group) = @_;
    my $ev = $zinc->XEvent();
    my $x = $ev->x;
    my $y = $ev->y;

    my $coloredGroup = $zinc->group($group);
    $zinc->translate($coloredGroup, $x-$x_orig, $y-$y_orig);
    $x_orig = $x;
    $y_orig = $y;
}

# Callback when releasing the mouse button. It removes any motion callback
sub release {
    my ($zinc) = @_;
    $zinc->Tk::bind('<Motion>', '');
}


Tk::MainLoop();


1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/icon_zoom_resize.pl.



























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/perl
# $Id$
# this simple demo has been developped by C. Mertz <mertz@cena.fr>

package icon_zoom__resize; # for avoiding symbol re-use between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;


my $defaultfont = '-adobe-helvetica-bold-r-normal--*-140-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $text = $mw->Scrolled(qw/Text -relief sunken -borderwidth 2 -setgrid true
	      -height 7 -scrollbars ''/);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
	      'This demo needs openGL for rescaling/rotating the icon
   You can transform this earth gif image with your mouse:
     Drag-Button 1 for zooming the earth,
     Drag-Button 2 for rotating the earth,
     Drag-Button 3 for moving the earth,
     Shift-Drag-Button 1 for modifying the earth transparency'
	      );

my $zinc = $mw->Zinc(-width => 350, -height => 250,
		     -render => 1,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

my $earth_group = $zinc->add('group', 1, );

# the following image is included in Perl/Tk distrib
my $image = $zinc->Photo('earth.gif', -file => Tk->findINC('demos/images/earth.gif'));

my $earth = $zinc->add('icon', $earth_group,
		      -image => $image,
		      -composescale => 1,
		      -composerotation => 1,
		      );
$zinc->add('text', $earth_group,
           -position => [30,30],
#	   -connecteditem => $earth,
	   -text => "try to zoom/resize the earth!\nWorks even without openGL!!",
	   -color => "white",
	   -composescale => 1,
	   -composerotation => 1,
	   );

$zinc->Tk::bind('<ButtonPress-1>', [\&press, \&zoom]);
$zinc->Tk::bind('<ButtonRelease-1>', [\&release]);

$zinc->Tk::bind('<ButtonPress-2>', [\&press, \&rotate]);
$zinc->Tk::bind('<ButtonRelease-2>', [\&release]);

$zinc->Tk::bind('<ButtonPress-3>', [\&press, \&motion]);
$zinc->Tk::bind('<ButtonRelease-3>', [\&release]);
    

$zinc->Tk::bind('<Shift-ButtonPress-1>', [\&press, \&modifyAlpha]);
$zinc->Tk::bind('<Shift-ButtonRelease-1>', [\&release]);



#
# Controls for the window transform.
#
my ($cur_x, $cur_y, $cur_angle);
sub press {
    my ($zinc, $action) = @_;
    my $ev = $zinc->XEvent();
    $cur_x = $ev->x;
    $cur_y = $ev->y;
    $cur_angle = atan2($cur_y, $cur_x);
    $zinc->Tk::bind('<Motion>', [$action]);
}

sub modifyAlpha {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $xrate = $lx /  $zinc->cget(-width);

    $xrate = 0 if $xrate < 0;
    $xrate = 1 if $xrate > 1;

    my $alpha = $xrate * 100;
    
    $zinc->itemconfigure($earth_group, -alpha => $alpha);
}


sub motion {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @res;
    
    @res = $zinc->transform($earth_group, [$lx, $ly, $cur_x, $cur_y]);
    $zinc->translate($earth_group, $res[0] - $res[2], $res[1] - $res[3]);
    $cur_x = $lx;
    $cur_y = $ly;
}

sub zoom {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $maxx;
    my $maxy;
    my $sx;
    my $sy;
    
    if ($lx > $cur_x) {
	$maxx = $lx;
    } else {
	$maxx = $cur_x;
    }
    if ($ly > $cur_y) {
	$maxy = $ly
    } else {
	$maxy = $cur_y;
    }
    return if ($maxx == 0 || $maxy == 0);
    $sx = 1.0 + ($lx - $cur_x)/$maxx;
    $sy = 1.0 + ($ly - $cur_y)/$maxy;
    $cur_x = $lx;
    $cur_y = $ly;
    $zinc->scale($earth_group, $sx, $sy);
}

sub rotate {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $langle;
    
    $langle = atan2($ly, $lx);
    $zinc->rotate($earth_group, -($langle - $cur_angle));
    $cur_angle = $langle;
}

sub release {
    my ($zinc) = @_;
    $zinc->Tk::bind('<Motion>', '');
}

Tk::MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/items.pl.























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/perl -w
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Scrolled('Zinc', -width => 700, -height => 600,
			 -font => '10x20', -borderwidth => 3,
			 -relief => 'sunken', -scrollbars => 'se',
			 -scrollregion => [-100, 0, 1000, 1000]);
$zinc->pack(-expand => 'yes', -fill => 'both');

$zinc->add('rectangle', 1, [10,10, 100, 50], -fillcolor => "green", -filled => 1,
	    -linewidth => 10, -relief => "roundridge", -linecolor => "darkgreen");


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A filled rectangle with a \"roundridge\" relief border of 10 pixels.",
	   -anchor => 'nw',
	   -position => [120, 20]);


my $labelformat = "x82x60+0+0 x60a0^0^0 x32a0^0>1 a0a0>2>1 x32a0>3>1 a0a0^0>2";

my $x=20;
my $y=120;
my $track=$zinc->add('track', 1, 6, # 6 is the number of fields in the flightlabel
		     -labelformat => $labelformat,
		     -position => [$x, $y],
		     -speedvector => [40, -10],
		     -speedvectormark =>  1, # currently works only with openGL
		     -speedvectorticks => 1, # currently works only with openGL
		     );
# moving the track, to display past positions
foreach my $i (0..5) {  $zinc->coords("$track",[$x+$i*10,$y-$i*2]); }

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A flight track for a radar display. (A waypoint looks similar,\n".
	   "but has no speedvector neither past positions)",
	   -anchor => 'nw',
	   -position => [200, 80],
	   );

$zinc->itemconfigure($track, 0,
		     -filled => 0,
		     -bordercolor => 'DarkGreen',
		     -border => "contour",
		     );
$zinc->itemconfigure($track, 1,
		     -filled => 1,
		     -backcolor => 'gray60',
		     -text => "AFR001");
$zinc->itemconfigure($track, 2,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "360");
$zinc->itemconfigure($track, 3,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "/");
$zinc->itemconfigure($track, 4,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "410");
$zinc->itemconfigure($track, 5,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "Beacon");





$zinc->add('arc', 1, [150, 140, 450, 240], -fillcolor => "gray20",
	   -filled => 0,  -linewidth => 1,
	   -startangle => 45, -extent => 270);
$zinc->add('arc', 1, [260, 150, 340, 230], -fillcolor => "gray20",
	   -filled => 0,  -linewidth => 1,
	   -startangle => 45, -extent => 270,
	   -pieslice => 1, -closed => 1,
	   -linestyle => 'mixed', -linewidth => 3,
	   );

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "Two arcs, starting at 45° with an extent of 270°.",
	   -anchor => 'nw',
	   -position => [320, 180]);


$zinc->add('curve', 1, [10, 324, 24, 300, 45, 432, 247, 356, 128, 401],
	   -filled => 0, -relief => 'roundgroove',
           # -linewidth => 10, ## BUG with zinc 3.2.3g 
	   );
$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "An open curve.",
	   -anchor => 'nw',
	   -position => [50, 350]);


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A waypoint",
	   -anchor => 'nw',
	   -position => [10, 480],
	   );
my $waypoint = $zinc->add('waypoint', 1, 6, -position => [100,520],
			  -labelformat => $labelformat,
			  -symbol => "AtcSymbol2",
			  -labeldistance => 30);  

foreach my $fieldId (1..5) {
    $zinc->itemconfigure($waypoint, $fieldId,
			 -filled => 0,
			 -bordercolor => 'DarkGreen',
			 -border => "contour",  # does not work with openGL (zinc-perl v3.2.3e)
			 -text => "field$fieldId",
			 );
}


$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "3 tabulars of 2 fields,\nattached together.",
	   -anchor => 'nw',
	   -position => [510, 380],
	   );

my $labelformat2 = "x72x40 x72a0^0^0 x34a0^0>1";

my $tabular1 = $zinc->add('tabular', 1, 6, -position => [570,250],
			  -labelformat => $labelformat2,
			  );
my $tabular2 = $zinc->add('tabular', 1, 6, -connecteditem => $tabular1,
			  -labelformat => $labelformat2,
			  );
my $tabular3 = $zinc->add('tabular', 1, 6, -connecteditem => $tabular2,
			  -labelformat => $labelformat2,
			  );
my $count=1;
foreach my $tab ($tabular1, $tabular2, $tabular3) {
    $zinc->itemconfigure($tab, 1, -filled => 0,
			 -bordercolor => 'DarkGreen',
			 -border => "contour", -text => "tabular",
			 );
    $zinc->itemconfigure($tab, 2, -filled => 0,
			 -bordercolor => 'DarkGreen',
			 -border => "contour", -text => "n°$count",
			 );
    $count++;
}


$zinc->add('reticle', 1, -position => [530,550],
	   -firstradius => 20, -numcircles => 6,
	   -period => 2, -stepsize => 20,
	   -brightlinestyle => 'dashed', -brightlinecolor => 'darkred', 
	   );

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "a reticle of 6 circles.",
	   -anchor => 'nw',
	   -position => [530, 540]);



$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "maps, triangles and groups items\nare not demonstrated here.",
	   -anchor => 'nw',
	   -position => [10, 550]);



MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/labelformat.pl.































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

my $mw = MainWindow->new();


###########################################
# Text zone
###########################################

my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2,
		     -height => 4);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
'This toy-appli demonstrates the use of labelformat for tabular items.
The fieldPos (please, refer to the "labelformat type" description 
in the "Zinc reference manual") of each field as described in
the labelformat is displayed inside the field.');


###########################################
# Zinc
##########################################
my $zinc = $mw->Zinc(-width => 600, -height => 500,
		     -font => "10x20",
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

###########################################
# Tabulars
###########################################

### first labelformat and tabular
my $labelformat1 = "300x300 x100x20+0+0 x100x20+100+0 x100x20+0+20 x100x20+100+20 x100x20+50+55";

my $tabular1 = $zinc->add('tabular',1, 5,
		    -position => [10,10],
		    -labelformat => $labelformat1,
		   );

&setLabelContent ($tabular1,$labelformat1);

$zinc->add('text', 1, -position => [10,100], -text =>
	   "All fields positions
are given in pixels");


### second labelformat and tabular
my $labelformat2 = "300x300 x110x20+100+30 x80x20<0<0 x80x20<0>0 x80x20>0>0 x80x20>0<0";

my $tabular2 = $zinc->add('tabular',1, 5,
                    -position => [270,10],
		    -labelformat => $labelformat2,
		    );
&setLabelContent ($tabular2,$labelformat2);

$zinc->add('text', 1, -position => [260,100], -text =>
	   "All fields positions are given
relatively to field 0.
They are either on the left/right
and up/down the field 0.");


### third labelformat and tabular
my $labelformat3 = "400x300 x200x70+100+70 x80x26^0<0 x80x26^0>0 x80x29\$0\$0 x80x32\$0^0 x90x20\<1^1 x90x20<2\$2 x90x20^4<4 x90x20^3>3";

my $tabular3 = $zinc->add('tabular',1, 9,
                    -position => [150,180],
                    -labelformat => $labelformat3,
                    );
&setLabelContent ($tabular3,$labelformat3);

$zinc->add('text', 1, -position => [40,360], -text =>
	   "Fields 1-4 are positionned relatively to field 0.
Field 5 is positionned relatively to field 1,
Field 6 is positionned relatively to field 2..."
);


### this function displays in each field, the corresponding <fieldPos>
### part of the labelformat
sub setLabelContent {
  my ($item,$labelformat) = @_;

  my @fieldsSpec = split (/ / , $labelformat);
  shift @fieldsSpec;

  my $i=0;
  foreach my $fieldSpec (@fieldsSpec) {
    my ($posSpec) = $fieldSpec =~ /^.\d+.\d+(.*)/ ;
#    print "$fieldSpec\t$i\t$posSpec\n";
    $zinc->itemconfigure ($item,$i,
                          -text => "$i: $posSpec",
  			  -border => "contour",
			  );
    $i++;
  }
}



MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/lines.pl.

































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 600,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

$zinc->add('text', 1,
	   -font => $defaultfont,
	   -text => "A set of lines with different styles of lines and termination\n".
	   "NB: some attributes such as line styles are not necessarily\n".
	   "  available with an openGL rendering system" ,
	   -anchor => 'nw',
	   -position => [20, 20]);

$zinc-> add('curve', 1, [20, 100, 320, 100]); # default options
$zinc-> add('curve', 1, [20, 120, 320, 120],
	    -linewidth => 20,
	    );
$zinc-> add('curve', 1, [20, 160, 320, 160],
	    -linewidth => 20,
	    -capstyle => "butt",
	    );
$zinc-> add('curve', 1, [20, 200, 320, 200],
	    -linewidth => 20,
	    -capstyle => "projecting",
	    );
$zinc-> add('curve', 1, [20, 240, 320, 240],
	    -linewidth => 20,
	    -linepattern => "AlphaStipple7",
	    -linecolor => "red",
	    );

# right column
$zinc-> add('curve', 1, [340, 100, 680, 100],
	    -firstend => [10, 10, 10],
	    -lastend => [10, 25, 45],
	    );
$zinc-> add('curve', 1, [340, 140, 680, 140],
	    -linewidth => 2,
	    -linestyle => 'dashed',
	    );
$zinc-> add('curve', 1, [340, 180, 680, 180],
	    -linewidth => 4,
	    -linestyle => 'mixed',
	    );
$zinc-> add('curve', 1, [340, 220, 680, 220],
	    -linewidth => 2,
	    -linestyle => 'dotted',
	    );

$zinc->add('curve', 1, [20, 300, 140, 360, 320, 300, 180, 260],
	   -closed => 1,
	   -filled => 1,
	   -fillpattern => "Tk",
	   -fillcolor => "grey60",
	   -linecolor => "red",
	   -marker => "AtcSymbol7",
	   -markercolor => "blue",

	   );


$zinc->add('curve', 1, [340, 300, 440, 360, 620, 300, 480, 260],
	   -closed => 1,
	   -linewidth => 10,
	   -joinstyle => "miter", #"round", # "bevel" | "miter"
	   -linecolor => "red",
	   );
$zinc->add('curve', 1, [400, 300, 440, 330, 560, 300, 480, 280],
	   -closed => 1,
	   -linewidth => 10,
	   -joinstyle => "round", # "bevel" | "miter"
	   -tile => Tk::findINC("Xcamel.gif"),
	   -fillcolor => "grey60",
	   -filled => 1,
	   -linecolor => "red",
	   );

#	   -tile => Tk::findINC("Xcamel.gif"),

MainLoop;


Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/mapinfo.pl.





































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/perl
# $Id$
# This simple demo has been developped by C. Schlienger <celine@intuilab.com>

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;


my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();

###########################################
# Text zone
###########################################

my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2,
		     -height => 4);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
	      'This toy-appli shows zoom actions on map item.
The following operations are possible:
   Click "-" to zoom out
   Click "+" to zoom in ' );

###########################################
# Zinc
###########################################
my $zinc_width=600;
my $zinc_height=500;
my $zinc = $mw->Zinc(-width => $zinc_width, -height => $zinc_height,
		     -font => "10x20",
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

###########################################
# Waypoints and sector
###########################################

my $mapinfo=$mw->mapinfo("mapinfo","create"); #creation of mapinfo

#--------------------------------
# Waypoints
#--------------------------------
$mw->mapinfo("mapinfo","add","symbol",200,100,0);
$mw->mapinfo("mapinfo","add","symbol",300,150,0);
$mw->mapinfo("mapinfo","add","symbol",400,50,0);
$mw->mapinfo("mapinfo","add","symbol",350,450,0);
$mw->mapinfo("mapinfo","add","symbol",300,250,0);
$mw->mapinfo("mapinfo","add","symbol",170,240,0);
$mw->mapinfo("mapinfo","add","symbol",550,200,0);

#--------------------------------
# Waypoints names
#--------------------------------
$mw->mapinfo("mapinfo","add","text","normal","simple",170,100,"DO");
$mw->mapinfo("mapinfo","add","text","normal","simple",270,160,"RE");
$mw->mapinfo("mapinfo","add","text","normal","simple",410,50,"MI");
$mw->mapinfo("mapinfo","add","text","normal","simple",345,470,"FA");
$mw->mapinfo("mapinfo","add","text","normal","simple",280,265,"SOL");
$mw->mapinfo("mapinfo","add","text","normal","simple",150,240,"LA");
$mw->mapinfo("mapinfo","add","text","normal","simple",555,200,"SI");

#--------------------------------
# Routes
#--------------------------------

$mw->mapinfo("mapinfo","add","line","simple",1,200,100,300,150);
$mw->mapinfo("mapinfo","add","line","simple",1,300,150,400,50);
$mw->mapinfo("mapinfo","add","line","simple",1,300,150,350,450);
$mw->mapinfo("mapinfo","add","line","simple",1,300,250,170,240);
$mw->mapinfo("mapinfo","add","line","simple",1,300,250,550,200);

#--------------------------------
# Sectors
#---------------------------------
$mw->mapinfo("mapinfo","add","line","simple",1,300,0,400,50);
$mw->mapinfo("mapinfo","add","line","simple",1,400,50,500,100);
$mw->mapinfo("mapinfo","add","line","simple",1,500,100,550,200);
$mw->mapinfo("mapinfo","add","line","simple",1,550,200,550,400);
$mw->mapinfo("mapinfo","add","line","simple",1,550,400,350,450);
$mw->mapinfo("mapinfo","add","line","simple",1,350,450,170,240);
$mw->mapinfo("mapinfo","add","line","simple",1,170,240,200,100);
$mw->mapinfo("mapinfo","add","line","simple",1,200,100,300,0);

#--------------------------------
# Sectors
#---------------------------------
my $gpe = $zinc ->add('group',1);
my $map = $zinc ->add('map',$gpe,#creation of the map object which has 'mapinfo' information
		      -mapinfo=>"mapinfo",
		      -symbols=>['AtcSymbol15']);


###################################################
# control panel
###################################################
my $rc = $mw->Frame()->pack();

#the reference of the scale function is top-left corner of the zinc object
#so we first translate the group to zoom in order to put its center on top-left corner
#change the scale of the group
#translate the group to put it back at the center of the zinc object 

my $minus=$rc->Button(-width => 2, 
		      -height => 2,
		      -text => '-',
		      -command=>sub{
			$zinc->translate($gpe,-$zinc_width/2,-$zinc_height/2);
			$zinc->scale($gpe,0.8,0.8);
			$zinc->translate($gpe, $zinc_width/2,$zinc_height/2);
		      })->pack(-side=>'left');


my $plus=$rc->Button(-width => 2, 
		     -height => 2,
		     -text => '+',
		     -command=>sub{
		       $zinc->translate($gpe, -$zinc_width/2,-$zinc_height/2);
		       $zinc->scale($gpe,1.2,1.2);
		       $zinc->translate($gpe,$zinc_width/2,$zinc_height/2);
		     })->pack(-side => 'right');



MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/path_tags.pl.











































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#!/usr/bin/perl -w
# $Id$
# this pathtatg demo have been developped by C. Mertz mertz@cena.fr
# with the help of Daniel Etienne etienne@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;

#This demo only works with Tk::Zinc > "3.2.5b";

## this demo demonstrates the use of path tags to address one or more items
## belonging to a hierarchy of groups.
## This hierarchy is described just below, gr_xxx designates a group
## (with a tag xxx) and i_yyy designates an non-group item (with a tag yyy).

#  gr_top --- gr_a --- gr_aa --- gr_aaa --- gr_aaaa --- i_aaaaa
#          |       |         |          |-- i_aaab  |-- i_aaaab
#          |       |         -- i_aab
#          |       |-- i_ab
#          |       |
#          |       ---gr_ac --- i_aca
#          |                |
#          |-- i_b          --- i_acb
#          |
#          --- gr_c --- gr_ca --- i_caa
#                   |         |
#                   |         --- i_cab
#                   |-- i_cb
#                   |
#                   ---gr_cc --- i_cca
#                            |
#                            --- i_ccb
#the same objects are cloned and put in an other hierarchy where
#gr_top is replaced by gr_other_top

my $defaultForecolor = "grey80";
my $selectedColor = "yellow";
my $mw = MainWindow->new();

###########################################
# Text zone
###########################################

my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2,
		     -height => 5, -font => "10x20");
$text->pack(-expand => 'yes', -fill => 'both');

$text->insert('0.0',
'This represents a group hierarchy:
  - groups are represented by a rectangle and an underlined title.
  - non-group items are represented by a text.
Select a pathTag or a tag with one of the radio-button
or experiment your own tags in the input field');

###########################################
# Zinc creation
###########################################

my $zinc = $mw->Zinc(-width => 850, -height => 360, -font => "10x20",
		     -borderwidth => 0, -backcolor => "black",
		     -forecolor => $defaultForecolor,
		     )->pack;

###########################################
# Creation of a bunch of radiobutton and a text input
###########################################

my $tagsfm = $mw->Frame()->pack();
my $pathtag;

my @pl = qw/-side left -expand 1 -padx .5c -pady .2c/;
my $left = $tagsfm->Frame->pack(@pl);
my $middle = $tagsfm->Frame->pack(@pl);
my $right = $tagsfm->Frame->pack(@pl);
my $rtop = $right->Frame->pack(-side => 'top');
my $rbottom = $right->Frame->pack(-side => 'top');
my $rbot_left = $rbottom->Frame->pack(-side => 'left');
my $rbot_right = $rbottom->Frame->pack(-side => 'left');

my $resultfm = $mw->Frame()->pack();
$resultfm->Label(-font => "10x20",
	     -relief => 'flat',
	     -text => 'explanation:',
	     )->pack(-side => 'left');
my $explan_txt = $resultfm->Label(-font => "10x20",
				  -relief => 'flat',
				  -width => 70,
				  -height => 3.5,
				  -text => '...',
				  -justify => 'left',
				  -wraplength => '16c',
				  )->pack(-side => 'left');


@pl = qw/-side top -pady 2 -anchor w/;
my @tags_explan;
@tags_explan = ("top" => "a simple tag for the top group",
		".top" => "all items in the root group with the tag 'top'",
		".top." => "direct children of a group in the root group with the tag 'top'",
		".top*" => "descendance of ONE group in the root group with the tag 'top'",
		".top*cca" => "items with a tag 'cca' in ONE direct group of root group with tag 'top'",
		".5." => "direct content of THE group with id 5");
while (@tags_explan) {
    my $tag = shift @tags_explan;
    my $explan = shift @tags_explan;
    $left->Radiobutton(-text     => $tag,
		       -font => "10x20",
		       -command => sub { &displayPathtag ($explan)},
		       -variable => \$pathtag,
		       -relief   => 'flat',
		       -value    => $tag,
		       )->pack(@pl);
}
@tags_explan = (".top*aa" => "items with a tag 'aa' in a direct group of root group with tag 'top'",
		".top*aa." => "direct children of ONE group with a tag 'aa', descending from a direct group of root group with tag 'top'",
		".top*aa*" => "descendance of ONE group with a tag 'aa', descending from a direct group of root group with tag 'top'",
		".top.a" => "items with a tag 'a' in a direct group of root group with tag 'top'",
		".top.a." => "direct children of ONE group with a tag 'a' in a direct group of root group with tag 'top'",
		".5*" => "descendance of THE group with id 5",
		);
while (@tags_explan) {
    my $tag = shift @tags_explan;
    my $explan = shift @tags_explan;
    $middle->Radiobutton(-text     => $tag,
			 -font => "10x20",
			 -command => sub { &displayPathtag ($explan)},
			 -variable => \$pathtag,
			 -relief   => 'flat',
			 -value    => $tag,
			 )->pack(@pl);
}


$rtop->Label(-font => "10x20",
	     -relief => 'flat',
	     -text => 'your own tag :',
	     )->pack(-side => 'left');
$rtop->Entry(-font => "10x20", -width => 15)
    ->pack(-side => 'left')->bind('<Key-Return>', sub {$pathtag = $_[0]->get();
						       &displayPathtag("sorry, I am not smart enough to explain your pathTag ;-)")});


@tags_explan =  (".top*aa*aaa" => "all items with a tag 'aaa' descending from ONE group with a tag 'aa' descending from ONE group with a tag 'top' child of the root group",
		 ".top*aa*aaa." => "children of ONE group with a tag 'aaa' descending from ONE group with a tag 'aa' descending from ONE group with a tag 'top' child of the root group",
		 ".top*aa*aaa*" => "descendance of ONE group with a tag 'aaa' descending from ONE group with a tag 'aa' descending from ONE group with a tag 'top' child of the root group",
		 ".other_top*aa*" => "descendance of ONE group with a tag 'aa' descending from ONE group with a tag 'other_top' child of the root group",
		 ".5*ca*" => "descendance of ONE group with a tag 'ca' descending from THE group with id 5",
		 );
while (@tags_explan) {
    my $tag = shift @tags_explan;
    my $explan = shift @tags_explan;
    $rbot_left->Radiobutton(-text     => $tag,
			    -font => "10x20",
			    -command => sub { &displayPathtag ($explan)},
			    -variable => \$pathtag,
			    -relief   => 'flat',
			    -value    => $tag,
			    )->pack(@pl);
}

@tags_explan = ("*aa*aaaa" => "all items with a tag 'aaaa' descending from a group with a tag 'aa'",
		"*aaa" => "all items with a tag 'aaa'",
		"aa || ca" => "items with tag 'aa' or tag 'ca'",
		"none" => "no items, as none has the tag 'none'",
		"all" => "all items",
		);
while (@tags_explan) {
    my $tag = shift @tags_explan;
    my $explan = shift @tags_explan;
    $rbot_right->Radiobutton(-text     => $tag,
			     -font => "10x20",
			     -command => sub { &displayPathtag ($explan)},
			     -command => \&displayPathtag,
			     -variable => \$pathtag,
			     -relief   => 'flat',
			     -value    => $tag,
			     )->pack(@pl);
}

# creating the item hierarchy
$zinc ->add('group', 1, -tags => ['top']);
&createSubHierarchy ('top');

# creating a parallel hierarchy
$zinc ->add('group', 1, -tags => ['other_top']);
&createSubHierarchy ('other_top');

### Here we create the genuine hierarchy of groups and items
### Later we will create graphical objects to display groups
sub createSubHierarchy {
    my ($gr) = @_;
    $zinc->add('group', $gr, -tags => ['a']);
    $zinc->add('text',  $gr, -tags => ['b', 'text'], -text => 'b',
	       -position => [270,150]);
    $zinc->add('group', $gr, -tags => ['c']);
    
    $zinc->add('group', 'a', -tags => ['aa']);
    $zinc->add('text',  'a', -tags => ['ab', 'text'], -text => 'ab'
	       , -position => [60,220]);
    $zinc->add('group', 'a', -tags => ['ac']);
    
    $zinc->add('group', 'aa', -tags => ['aaa']);
    $zinc->add('text',  'aa', -tags => ['aab', 'text'], -text => 'aab', 
	       -position => [90,190]);
    $zinc->add('group', 'aaa', -tags => ['aaaa']);
    $zinc->add('text',  'aaaa', -tags => ['aaaaa', 'text'], -text => 'aaaaa', 
	       -position => [150,110]);
    $zinc->add('text',  'aaaa', -tags => ['aaaab', 'text'], -text => 'aaaab',
	       -position => [150,130]);
    $zinc->add('text',  'aaa', -tags => ['aaab', 'text'], -text => 'aaab',
	       -position => [120,160]);
    
    $zinc->add('text', 'ac', -tags => ['aca'], -text => 'aca',
	       -position => [90,260]);
    $zinc->add('text',  'ac', -tags => ['acb', 'text'], -text => 'acb',
	       -position => [90,290]);
    
    $zinc->add('group', 'c', -tags => ['ca']);
    $zinc->add('text',  'c', -tags => ['cb', 'text'], -text => 'cb',
	       -position => [330,160]);
    $zinc->add('group', 'c', -tags => ['cc']);
    
    $zinc->add('text',  'ca', -tags => ['caa', 'text'], -text => 'caa',
	       -position => [360,110]);
    $zinc->add('text',  'ca', -tags => ['cab', 'text'], -text => 'cab',
	       -position => [360,130]);

    $zinc->add('text',  'cc', -tags => ['cca', 'text'], -text => 'cca',
	       -position => [360,200]);
    $zinc->add('text',  'cc', -tags => ['ccb', 'text'], -text => 'ccb',
	       -position => [360,220]);
}

## modifying the priority so that all rectangles and text will be visible
map { $_, $zinc->itemconfigure($_,-priority => 20)} ($zinc->find('withtype', 'text', ".top*"));
map { $_, $zinc->itemconfigure($_,-priority => 20)} ($zinc->find('withtype', 'text', ".other_top*"));
map { $_, $zinc->itemconfigure($_,-priority => 20)} ($zinc->find('withtype', 'group', ".top*"));
map { $_, $zinc->itemconfigure($_,-priority => 20)} ($zinc->find('withtype', 'group', ".other_top*"));

# converts a list of items ids in a list of sorted tags (the first tag of each item)
sub items2tags {
    my @items = @_;
    my @selected_tags;
    foreach my $item (@items) {
	my @tags = $zinc->itemcget ($item, -tags);
	next if $tags[0] =~ /frame|title/  ;    # to remove group titles frame
	push @selected_tags, $tags[0];
    }
    return sort @selected_tags;
}

### drawing :
####   a rectangle item for showing the bounding box of each group, 
###    a text item for the group name (i.e. its first tag)

## backgrounds used to fill rectangles representing groups
my @backgrounds = qw(grey25 grey35 grey43 grey50 grey55);

sub drawHierarchy {
    my ($group,$level) = @_;
    my @tags = $zinc->gettags($group);
#    print "level=$level (", $tags[0],")\n";
    foreach my $g ($zinc->find('withtype', 'group', ".$group.")) {
	&drawHierarchy ($g,$level+1);
    }
    my ($x,$y,$x2,$y2) = $zinc->bbox($group);
    $zinc->add('text',$group, -position => [$x-5,$y-4],
	       -text => $tags[0], -anchor => "w", -alignment => "left",
	       -underlined => 1,
	       -priority => 20,
	       -tags => ["title_".$tags[0], 'group_title'],
	       );
    ($x,$y,$x2,$y2) = $zinc->bbox($group);
    if (defined $x) {
	my $background  = $backgrounds[$level];
	$zinc->add('rectangle', $group, [$x+0,$y+5,$x2+5,$y2+2],
		   -filled => 1,
		   -fillcolor => $background,
		   -priority => $level,
		   -tags => ["frame_".$tags[0], 'group_frame'],
		   );
    } else {
	print "undefined bbox for $group : @tags\n";
    }
}

### this sub extracts out of groups both text and frame representing
### each group. This is necessary to avoid unexpected selection of
### rectangles and titles inside groups
sub extractTextAndFrames {
    foreach my $group_title ($zinc->find('withtag', 'group_title || group_frame')) {
	my @ancestors = $zinc->find('ancestor',$group_title);
#	print "$group_title, @ancestors\n";
	my $grandFather = $ancestors[1];
	$zinc->chggroup($group_title,$grandFather,1);
    }
}

## this sub modifies the color/line color of texts and rectangles
## representing selected items. 
sub displayPathtag {
#    print "var=@_ $pathtag\n";
    my $explanation = shift;
    my @selected = $zinc->find('withtag', $pathtag);
    my @tags = &items2tags(@selected);
#    print "selected: @tags\n";
    $explan_txt->configure(-text => $explanation ? "$explanation\n" : "");
	
    ## unselecting all items 
    foreach my $item ($zinc->find('withtype', 'text')) {
	$zinc->itemconfigure($item, -color => $defaultForecolor);
    }
    foreach my $item ($zinc->find('withtype', 'rectangle')) {
	$zinc->itemconfigure($item, -linecolor => $defaultForecolor);
    }

    ## highlighting selected items
    foreach my $item (@selected) {
	my $type = $zinc->type($item);
#	print $item, " ", $zinc->type($item), " ", join (",",$zinc->gettags($item)), "\n";
	if ($type eq 'text') {
	    $zinc->itemconfigure($item, -color => $selectedColor);
	} elsif ($type eq 'rectangle') {
	    $zinc->itemconfigure($item, -linecolor => $selectedColor);
	} elsif ($type eq 'group') {
	    my $tag = ($zinc->gettags($item))[0];
	    ## as there is 2 // hierachy, we must refine the tag used
	    ## to restrict to the proper hierarchy
	    ## NB: this is due to differences between the group hierarchy
	    ##     and the graphical object hierarchy used for this demo
	    if ($zinc->find('ancestors',$item,'top')) {
		$zinc->itemconfigure(".top*frame_$tag", -linecolor => $selectedColor);
		$zinc->itemconfigure(".top*title_$tag", -color => $selectedColor);
	    } elsif ($zinc->find('ancestors',$item,'other_top')) {
		$zinc->itemconfigure(".other_top*frame_$tag", -linecolor => $selectedColor);
		$zinc->itemconfigure(".other_top*title_$tag", -color => $selectedColor);
	    } else {
		$zinc->itemconfigure("frame_$tag", -linecolor => $selectedColor);
		$zinc->itemconfigure("title_$tag", -color => $selectedColor);
	    }
	}
    }
}

&drawHierarchy('top',0);
&drawHierarchy('other_top',0);
$zinc->translate('other_top', 400,0);
&extractTextAndFrames;



MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/rotation.pl.

























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/perl
# $Id$
# This simple demo has been developped by C. Schlienger <celine@intuilab.com>

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


use Tk;
use Tk::Zinc;
use strict;
use constant;

my constant $PI=3.1416;

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();


###########################################
# Text zone
###########################################

my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2, -height => 4);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
	      'This toy-appli shows rotations on waypoint items.
The following operations are possible:
   Click "<-" for negative rotation
   Click "->" for positive rotation' );


###########################################
# Zinc
###########################################
my $zinc_width=600;
my $zinc_height=500;
my $zinc = $mw->Zinc(-width => $zinc_width, -height => $zinc_height,
		     -font => "10x20",
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

###########################################
# Waypoints
###########################################

my $wp_group = $zinc->add('group', 1, -visible => 1);

my $p1=[200, 200];
my $wp1 = $zinc->add('waypoint',$wp_group, 1,
		    -position => $p1,
		    -connectioncolor => 'green',
		    -symbolcolor => 'blue',
		    -labelformat => 'x20x18+0+0',
		    -leaderwidth=>'0',
		    -labeldx=>'-20'
		   );
$zinc->itemconfigure($wp1, 0,
		     -text => "DO",
		    );

my $p2=[300, 300];
my $wp2 = $zinc->add('waypoint',$wp_group, 1,
		     -position => $p2,
		     -connecteditem => $wp1,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'-20',
		     #-labeldy=>'30'
		    );

$zinc->itemconfigure($wp2, 0,
		     -text => "RE",
		    );

my $p3=[400, 150];
my $wp3 = $zinc->add('waypoint', $wp_group, 2,
		     -position => $p3,
		     -connecteditem => $wp2,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'20',
		     -labeldy=>'+10'
		    );
$zinc->itemconfigure($wp3, 0,
		     -text => "MI",
		    );

###################################################
# control panel
###################################################
my $rc = $mw->Frame()->pack();

my $left=$rc->Button(-width => 2, 
		     -height => 2,
		     -text => '<-',
		     -command=>sub{
		       #--------------------------------
		       # Negative rotation
		       #--------------------------------
		       my @centre=$zinc->coords("$wp2"); #the center of the rotation is $wp2
		       $zinc->rotate("$wp_group",-$PI/6,$centre[0],$centre[1]); 
		     })->pack(-side => 'left');

my $right=$rc->Button(-width => 2, 
		      -height => 2,
		      -text => '->',
		      -command=>sub{
			#--------------------------------
			# Positive rotation
			#--------------------------------
			my @centre=$zinc->coords("$wp2");#the center of the rotation is $wp2
			$zinc->rotate("$wp_group",+$PI/6,$centre[0],$centre[1]); 
		      })->pack(-side=>'right');




MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/simple_interaction_track.pl.



























































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#!/usr/bin/perl
# $Id$
# This simple demo has been developped by C. Schlienger <celine@intuilab.com>

package simple_interaction_track; # for avoiding symbol collision between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


use Tk;
use Tk::Zinc;
use strict;

my $mw = MainWindow->new();



###########################################
# Zinc
###########################################
my $zinc_width=600;
my $zinc_height=500;
my $zinc = $mw->Zinc(-width => $zinc_width, -height => $zinc_height,
		     -font => "10x20",
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

# The explanation displayed when running this demo
$zinc->add('text', 1,
	   -position=> [10,10],
	   -text => 'This toy-appli shows some interactions on different parts
of a flight track item. The following operations are possible:
 - Drag Button 1 on the track to move it.
      Please Note the position history (past positions)
 - Enter/Leave flight label fields
 - Enter/Leave the speedvector, symbol (i.e. current position),
     label, or leader',
	   -font => "9x15",
	   );

###########################################
# Track
###########################################

#the label format (6 formats for 6 fields)#
my $labelformat = "x80x60+0+0 x60a0^0^0 x30a0^0>1 a0a0>2>1 x30a0>3>1 a0a0^0>2";

#the track#
my $x=250;
my $y=200;
my $track=$zinc->add('track', 1, 6, # 6 is the number of field in the flightlabel
		     -labelformat => $labelformat,
		     -position => [$x, $y],#position of the marker
		     -speedvector => [30, -15],#ccords of the speed vector
		     -markersize => 10,
		     );
# moving the track, to display past positions
foreach my $i (0..5) {  $zinc->coords($track,[$x+$i*10,$y-$i*5]); }

#fields of the label#
$zinc->itemconfigure($track, 0,#configuration of field 0 of the label
		     -filled => 0,
		     -bordercolor => 'DarkGreen',
		     -border => "contour",
		    );
$zinc->itemconfigure($track, 1,
		     -filled => 1,
		     -backcolor => 'gray60',
		     -text => "AFR6128");
$zinc->itemconfigure($track, 2,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "390");
$zinc->itemconfigure($track, 3,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "/");
$zinc->itemconfigure($track, 4,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "350");
$zinc->itemconfigure($track, 5,
		     -filled => 0,
		     -backcolor => 'gray65',
		     -text => "TUR");



###########################################
# Events on the track
###########################################
#---------------------------------------------
# Enter/Leave a field of the label of the track
#---------------------------------------------

foreach my $field (0..5) {
  #Entering the field $field higlights it#
  $zinc->bind("$track:$field", 
	      '<Enter>',
	      sub {
		if ($field==0){ 
		  higlight_label_on();
#		  print "CP=", $zinc->currentpart, "\n";
		}
		else{
		  highlight_fields_on($field);
#		  print "CP=", $zinc->currentpart, "\n";
		}
		
	      });
  #Leaving the field cancels the highlight of $field#
  $zinc->bind("$track:$field", 
	      '<Leave>',
	      sub {
		if($field==0){
		  higlight_label_off();
		}
		else{
		  if ($field==1){
		    highlight_field1_off();
		  }
		  else{
		    highlight_other_fields_off($field);
		  }
		}
	      });
}

#fonction#
sub higlight_label_on{
   $zinc->itemconfigure('current', 0,
			-filled => 0,
			-bordercolor => 'red',
			-border => "contour",
		    );
  
}
sub higlight_label_off{
   $zinc->itemconfigure('current', 0,
			-filled => 0,
			-bordercolor => 'DarkGreen',
			-border => "contour",
		    );
  
  
}

sub highlight_fields_on{
  my $field=$_[0];
  $zinc->itemconfigure('current', $field,
		       -border => 'contour',
		       -filled => 1,
		       -color => 'white'
		      );
  
}
sub highlight_field1_off{
    $zinc->itemconfigure('current', 1,
			 -border => '',
			 -filled => 1,
			 -color => 'black',
			 -backcolor => 'gray60'
			);
  
}

sub highlight_other_fields_off{
  my $field=$_[0];
  $zinc->itemconfigure('current', $field,
		       -border => '',
		       -filled => 0,
		       -color => 'black',
		       -backcolor => 'gray65'
		      );
}
#---------------------------------------------
# Enter/Leave other parts of the track
#---------------------------------------------
$zinc->bind("$track:position", 
	      '<Enter>',
	      sub {  $zinc->itemconfigure($track,
					  -symbolcolor=>"red",
					  );
#		  print "CP=", $zinc->currentpart, "\n";
		 });
$zinc->bind("$track:position", 
	      '<Leave>',
	      sub {  $zinc->itemconfigure($track,
					  -symbolcolor=>"black",
					  );
		 });

$zinc->bind("$track:speedvector", 
	      '<Enter>',
	      sub {  $zinc->itemconfigure($track,
					  -speedvectorcolor=>"red",
					  );
		 });
$zinc->bind("$track:speedvector", '<Leave>',
    sub {  $zinc->itemconfigure($track,
				-speedvectorcolor=>"black",
				);
       });

$zinc->bind("$track:leader", '<Enter>',
    sub {  $zinc->itemconfigure($track,
				-leadercolor=>"red",
				);
       });

$zinc->bind("$track:leader", '<Leave>',
    sub {  $zinc->itemconfigure($track,
				-leadercolor=>"black",
				);
       });

#---------------------------------------------
# Drag and drop the track
#---------------------------------------------
#Binding to ButtonPress event -> "move_on" state#
$zinc -> bind($track,'<ButtonPress-1>'=>[ sub { &select_color_on(); #change the color
						&move_on($_[1],$_[2]); #"move_on" state
					    }, Tk::Ev('x'),Tk::Ev('y') ]); 

#Binding to ButtonRelease event -> "move_off" state#
$zinc -> bind($track,'<ButtonRelease-1>'=>sub{&select_color_off(); #change the color
					      &move_off();}); #"move_off" state

#"move_on" state#
sub move_on{
    my ($xi,$yi)=@_;
    #Binding to Motion event -> move the track#
    $zinc -> bind($track,'<Motion>'=>
		  [sub{move($xi,$yi,$_[1],$_[2]); #move the track
		       $xi=$_[1];
		       $yi=$_[2];
		   },Tk::Ev('x'),Tk::Ev('y')]); 
}

#"move_off" state#
sub move_off{
    #Motion event not allowed on track
    $zinc -> bind($track,'<Motion>'=>""); 
}

#move the track#
sub move{
    my ($xi,$yi,$x,$y)=@_;
    select_color_on();
    my @coords=$zinc->coords($track);
    $zinc->coords($track,[$coords[0]+$x-$xi,$coords[1]+$y-$yi]);
}


sub select_color_on{
    $zinc->itemconfigure($track,
			 -speedvectorcolor=>"white",
			 -markercolor=>"white",
			 -leadercolor=>"white" );
}

sub select_color_off{
  $zinc->itemconfigure($track,
		       -speedvectorcolor=>"black",
		       -markercolor=>"black",
		       -leadercolor=>"black" );
}
 Tk::MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/simpleradar.pl.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
#!/usr/bin/perl -w
# $Id$
# This simple radar has been initially developped by P. Lecoanet <lecoanet@cena.fr>
# It has been adapted by C. Mertz <mertz@cena.fr> for demo purpose.

package simpleradar; # for avoiding symbol collision between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


use Tk;
use Tk::Zinc;

use strict;

# to find the SimpleRadarControls module
require Tk->findINC('demos/zinc_pm/SimpleRadarControls.pm');

my $mw = MainWindow->new();

my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2,
		     -height => 11);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
	      'This a very simple radar display, where you can see flight tracks,
   a so-called ministrip (green) and and extend flight label (tan background).
   The following operations are possible:
     Shift-Button 1 for using a squarre lasso (result in the terminal).
     Click Button 2 for identifiying the closest item (result in the terminal).
     Button 3 for dragging most items, but not the ministrip (not in the same group).
     Shift-Button 3 for zooming independently on X and Y axis.
     Ctrl-Button 3 for rotationg graphic objects.
     Enter/Leave in flight label fields, speed vector, position and leader,
       and in the ministrip fields.
     Click Button 1 on flight track to display a route.');



###################################################
# creation zinc
###################################################
my $top = 1;
my $scale = 1.0;
my $center_x = 0.0;
my $center_y = 0.0;
my $zinc_width = 800;
my $zinc_height = 500;
my $delay = 2000;
my $rate = 0.3;
my %tracks = ();

my $pause = 0; # if true the flight are no more moving
my $zinc = $mw->Zinc(-render => 1,
                     -enablerotation => 1,
                     -backcolor => 'gray65',
		     -relief => 'sunken',
		     -font => "10x20");
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => $zinc_width, -height => $zinc_height);
#$radar = $top;
my $radar = $zinc->add('group', $top, -tags => ['controls', 'radar']);
$zinc->configure(-overlapmanager => $radar);

my $rotation = 0;
$zinc->Tk::bind('<Alt-1>', sub { $rotation += 10; $zinc->configure(-screenrotation => $rotation); });
$zinc->Tk::bind('<Alt-3>', sub { $rotation -= 10; $zinc->configure(-screenrotation => $rotation); });

###################################################
# creation panneau controle
###################################################
my $rc = $mw->Frame()->pack();
$rc->Button(-text => 'Up',
	    -command => sub { $center_y -= 30.0;
			      update_transform($zinc); })->grid(-row => 0,
								-column => 2,
								-sticky, 'ew');
$rc->Button(-text => 'Down',
	    -command => sub { $center_y += 30.0;
			      update_transform($zinc); })->grid(-row => 2,
								-column => 2,
								-sticky, 'ew');
$rc->Button(-text => 'Left',
	    -command => sub { $center_x += 30.0;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 1);
$rc->Button(-text => 'Right',
	    -command => sub { $center_x -= 30.0;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 3);
$rc->Button(-text => 'Expand',
	    -command => sub { $scale *= 1.1;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 4);
$rc->Button(-text => 'Shrink',
	    -command => sub { $scale *= 0.9;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 0);
$rc->Button(-text => 'Reset',
	    -command => sub { $scale = 1.0;
			      $center_x = $center_y = 0.0;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 2,
								-sticky, 'ew');

$rc->Button(-text => 'Pause',
	    -command => sub { $pause = ! $pause;
			  })->grid(-row => 0,
				   -column => 6);

###################################################
# Code de reconfiguration lors d'un
# redimensionnement.
###################################################
$zinc->Tk::bind('<Configure>', [\&resize]);

sub resize {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $width = $ev->w;
    my $height = $ev->h;
    my $bw = $zinc->cget(-borderwidth);
    $zinc_width = $width - 2*$bw;
    $zinc_height = $height - 2*$bw;
    update_transform($zinc);
}

sub update_transform {
    my ($zinc) = @_;
    $zinc->treset($top);
    $zinc->translate($top, -$center_x, -$center_y);
    $zinc->scale($top, $scale, $scale);
    $zinc->scale($top, 1, -1);
    my $virtualSize = sqrt($zinc_width*$zinc_width + $zinc_height*$zinc_height);
    my $hVirtualSize = $virtualSize/2;
    $zinc->translate($top, $hVirtualSize, $hVirtualSize);
    #$zinc->translate($top, $zinc_width/2, $zinc_height/2);
}


###################################################
# Creation de pistes.
###################################################
my $one_of_track_item;
sub create_tracks {
    my $i = 20;
    my $j;
    my $track;
    my $x;
    my $y;
    my $w = $zinc_width / $scale;
    my $h = $zinc_height / $scale;
    my $d;
    my $item;
    
    for ( ; $i > 0; $i--) {
	$track = {};
	$track->{'item'} = $item = $zinc->add('track', $radar, 6);
	$one_of_track_item = $item;
	$tracks{$item} = $track;
	$track->{'x'} = rand($w) - $w/2 + $center_x;
	$track->{'y'} = rand($h) - $h/2 + $center_y;
	$d = (rand() > 0.5) ? 1 : -1;
	$track->{'vx'} =  (8.0 + rand(10.0)) * $d;
	$d = (rand() > 0.5) ? 1 : -1;
	$track->{'vy'} =  (8.0 + rand(10.0)) * $d;
	$zinc->itemconfigure($item,
			     -position => [$track->{'x'}, $track->{'y'}],
			     -speedvector => [$track->{'vx'}, $track->{'vy'}],
			     -speedvectorsensitive => 1,
			     -labeldistance => 30,
			     -markersize => 20,
			     -historycolor => 'gray30',
			     -filledhistory => 0,
			     -circlehistory => 1,
			     -labelformat => "x80x60+0+0 x63a0^0^0 x33a0^0>1 a0a0>2>1 x33a0>3>1 a0a0^0>2");
	$zinc->itemconfigure($item, 0,
			     -filled => 0,
			     -backcolor => 'gray60',
#			     -border => "contour",
			     -sensitive => 1
			     );
	$zinc->itemconfigure($item, 1,
			     -filled => 1,
			     -backcolor => 'gray55',
			     -text => sprintf ("AFR%03i",$i));
	$zinc->itemconfigure($item, 2,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "360");
	$zinc->itemconfigure($item, 3,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "/");
	$zinc->itemconfigure($item, 4,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "410");
	$zinc->itemconfigure($item, 5,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "Balise");
	my $b_on = sub { $zinc->itemconfigure('current', $zinc->currentpart(),
					      -border => 'contour')};
	my $b_off = sub { $zinc->itemconfigure('current', $zinc->currentpart(),
					       -border => 'noborder')};
	my $tog_b = sub { my $current = $zinc->find('withtag', 'current');
			  my $curpart = $zinc->currentpart();
			  if ($curpart =~ '[0-9]+') {
			      my $on_off = $zinc->itemcget($current, $curpart, -sensitive);
			      $zinc->itemconfigure($current, $curpart,
						   -sensitive => !$on_off);
			  }
		      };
	for ($j = 0; $j < 6; $j++) {
	    $zinc->bind($item.":$j", '<Enter>', $b_on);
            $zinc->bind($item.":$j", '<Leave>', $b_off);
            $zinc->bind($item, '<1>', $tog_b);
            $zinc->bind($item, '<Shift-1>', sub {});
        }
	$zinc->bind($item, '<Enter>',
		    sub {$zinc->itemconfigure('current',
					      -historycolor => 'red3',
					      -symbolcolor => 'red3',
					      -markercolor => 'red3',
					      -leaderwidth => 2,
					      -leadercolor => 'red3',
					      -speedvectorwidth => 2,
					      -speedvectorcolor => 'red3')});
        $zinc->bind($item, '<Leave>',
                    sub {$zinc->itemconfigure('current',
					      -historycolor => 'black',
					      -symbolcolor => 'black',
					      -markercolor => 'black',
					      -leaderwidth => 1,
					      -leadercolor => 'black',
					      -speedvectorwidth => 1,
					      -speedvectorcolor => 'black')});
        $zinc->bind($item.':position', '<1>', [\&create_route]);
        $zinc->bind($item.':position', '<Shift-1>', sub { });
        $track->{'route'} = 0;
    }
}

create_tracks();

###################################################
# creation way point
###################################################
sub create_route {
    my ($zinc) = @_;
    my $wp;
    my $connected;
    my $x;
    my $y;
    my $i = 4;
    my $track = $tracks{$zinc->find('withtag', 'current')};
    
    if ($track->{'route'} == 0) {
	$x = $track->{'x'} + 8.0 * $track->{'vx'};
	$y = $track->{'y'} + 8.0 * $track->{'vy'};
	$connected = $track->{'item'};
	for ( ; $i > 0; $i--) {
	    $wp = $zinc->add('waypoint', 'radar', 2,
			     -position => [$x, $y],
			     -connecteditem => $connected,
			     -connectioncolor => 'green',
			     -symbolcolor => 'green',
			     -labelformat => 'x20x18+0+0');
	    $zinc->lower($wp, $connected);
	    $zinc->bind($wp.':0', '<Enter>',
			sub {$zinc->itemconfigure('current', 0, -border => 'contour')});
	    $zinc->bind($wp.':position', '<Enter>',
			sub {$zinc->itemconfigure('current', -symbolcolor => 'red')});
	    $zinc->bind($wp.':leader', '<Enter>',
			sub {$zinc->itemconfigure('current', -leadercolor => 'red')});
	    $zinc->bind($wp.':connection', '<Enter>',
			sub {$zinc->itemconfigure('current', -connectioncolor => 'red')});
	    $zinc->bind($wp.':0', '<Leave>',
			sub {$zinc->itemconfigure('current', 0, -border => '')});
	    $zinc->bind($wp.':position', '<Leave>',
			sub {$zinc->itemconfigure('current', -symbolcolor => 'green')});
	    $zinc->bind($wp.':leader', '<Leave>',
			sub {$zinc->itemconfigure('current', -leadercolor => 'black')});
	    $zinc->bind($wp.':connection', '<Leave>',
			sub {$zinc->itemconfigure('current', -connectioncolor => 'green')});
	    $zinc->itemconfigure($wp, 0,
				 -text => "$i",
				 -filled => 1,
                                 -backcolor => 'gray55');
	    $zinc->bind($wp.':position', '<1>', [\&del_way_point]);
	    $x += (2.0 + rand(8.0)) * $track->{'vx'};
	    $y += (2.0 + rand(8.0)) * $track->{'vy'};
	    $connected = $wp;
	}
	$track->{'route'} = $wp;
    }
    else {
	$wp = $track->{'route'};
	while ($wp != $track->{'item'}) {
	    $track->{'route'} = $zinc->itemcget($wp, -connecteditem);
	    $zinc->bind($wp.':position', '<1>', '');
	    $zinc->bind($wp.':position', '<Enter>', '');
	    $zinc->bind($wp.':position', '<Leave>', '');
	    $zinc->bind($wp.':leader', '<Enter>', '');
            $zinc->bind($wp.':leader', '<Leave>', '');
            $zinc->bind($wp.':connection', '<Enter>', '');
            $zinc->bind($wp.':connection', '<Leave>', '');
            $zinc->bind($wp.':0', '<Enter>', '');
            $zinc->bind($wp.':0', '<Leave>', '');
            $zinc->remove($wp);
	    $wp = $track->{'route'};
	}
	$track->{'route'} = 0;
    }
}

###################################################
# suppression waypoint intermediaire
###################################################
sub find_track {
    my ($zinc, $wp) = @_;
    my $connected = $wp;
    
    while ($zinc->type($connected) ne 'track') {
	$connected = $zinc->itemcget($connected, -connecteditem);
    }
    return $connected;
}

sub del_way_point {
    my ($zinc) = @_;
    my $wp = $zinc->find('withtag', 'current');
    my $track = $tracks{find_track($zinc, $wp)};
    my $next = $zinc->itemcget($wp, -connecteditem);
    my $prev;
    my $prevnext;

    $prev = $track->{'route'};
    if ($prev != $wp) {
	$prevnext = $zinc->itemcget($prev, -connecteditem);
	while ($prevnext != $wp) {
	    $prev = $prevnext;
	    $prevnext = $zinc->itemcget($prev, -connecteditem);
	}
    }
    $zinc->itemconfigure($prev, -connecteditem => $next);
    $zinc->bind($wp.':position', '<1>', '');
    $zinc->remove($wp);
    if ($wp == $track->{'route'}) {
	if ($next == $track->{'item'}) {
	    $track->{'route'} = 0;
	}
	else {
	    $track->{'route'} = $next;
	}
    }
}


###################################################
# creation macro
###################################################
my $macro = $zinc->add("tabular", $radar, 10,
    -labelformat => "x73x20+0+0 x20x20+0+0 x53x20+20+0"
    );
$zinc->itemconfigure($macro, 0, -backcolor => "tan1", -filled => 1,
		     -fillpattern => "AlphaStipple7",
		     -bordercolor => "red3");
$zinc->itemconfigure($macro, 1 , -text => "a");
$zinc->itemconfigure($macro, 2, -text => "macro");

$zinc->itemconfigure($macro, -connecteditem => $one_of_track_item);
foreach my $part (0..2) {
    $zinc->bind("$macro:$part", "<Enter>", [ \&borders, "on"]);
    $zinc->bind("$macro:$part", "<Leave>", [ \&borders, "off"]);
}
###################################################
# creation ministrip
###################################################
my $ministrip = $zinc->add("tabular", 1, 10,
			   -labelformat => "x153x80^0^0 x93x20^0^0 x63a0^0>1 a0a0>2>1 x33a0>3>1 a0a0^0>2",
			   -position => [100, 10]);
$zinc->itemconfigure($ministrip, 0 ,
		     -filled => 1,
		     -backcolor => "grey70",
		     -border => "contour",
		     -bordercolor => "green",
		     );
$zinc->itemconfigure($ministrip, 1 ,
		     -text => 'ministrip', -color => "darkgreen",
		     -backcolor => "grey40", 
		     );
$zinc->itemconfigure($ministrip, 2 ,
		     -text => 'field1', -color => "darkgreen",
		     -backcolor => "grey40",
		     );
$zinc->itemconfigure($ministrip, 3 ,
		     -text => 'field2', -color => "darkgreen",
		     -backcolor => "grey40",
		     );
$zinc->itemconfigure($ministrip, 4 ,
		     -text => 'f3', -color => "darkgreen",
		     -backcolor => "grey40",
		     );
$zinc->itemconfigure($ministrip, 5 ,
		     -text => 'field4', -color => "darkgreen",
		     -backcolor => "grey40",
		     );

foreach my $field (1..5) {
    $zinc->bind("$ministrip:$field", '<Enter>',
		sub {
		    $zinc->itemconfigure('current', $field,
					 -border => 'contour',
					 -filled => 1,
					 -color => 'white'
					 )
		    });
$zinc->bind("$ministrip:$field", '<Leave>',
    sub {$zinc->itemconfigure('current', $field,
			      -border => '',
			      -filled => 0,
			      -color => 'darkgreen'
			      )});
}

###################################################
# creation map
###################################################
$mw->videomap("load", Tk->findINC("demos/zinc_data/videomap_paris-w_90_2"), 0, "paris-w");
$mw->videomap("load", Tk->findINC("demos/zinc_data/videomap_orly"), 17, "orly");
$mw->videomap("load", Tk->findINC("demos/zinc_data/hegias_parouest_TE.vid"), 0, "paris-ouest");

my $map = $zinc->add("map", $radar,
		     -color => 'gray80');
$zinc->itemconfigure($map,
		     -mapinfo => 'orly');

my $map2 = $zinc->add("map", $radar,
		      -color => 'gray60',
		      -filled => 1,
		      -priority => 0,
		      -fillpattern => "AlphaStipple6");
$zinc->itemconfigure($map2,
		     -mapinfo => 'paris-ouest');

my $map3 = $zinc->add("map", $radar,
		      -color => 'gray50');
$zinc->itemconfigure($map3,
		     -mapinfo => "paris-w");


###################################################
# Création fonctions de contrôle à la souris
###################################################
new SimpleRadarControls($zinc);

###################################################
# Rafraichissement des pistes
###################################################
my $timer = $zinc->repeat($delay, [\&refresh, $zinc]);
$mw->OnDestroy(\&destroyTimersub ); # this is 

my $timerIsDead = 0;
sub destroyTimersub {
    $timerIsDead = 1;
    $mw->afterCancel($timer);
    # the timer is not really cancelled when using zinc-demos! 
}

sub refresh {
    my ($zinc) = @_;

    return if $pause;
    return if $timerIsDead;
    foreach my $t (values(%tracks)) {
	$t->{'x'} += $t->{'vx'} * $rate;
	$t->{'y'} += $t->{'vy'} * $rate;
	$zinc->itemconfigure($t->{'item'},
			     -position => [$t->{'x'}, $t->{'y'}]);
    }
}

sub borders {
    my($widget, $onoff) = @_;
    $onoff = "on" unless $onoff;
    my $contour = "noborder";
    $contour = "contour" if ($onoff eq 'on');
    $zinc->itemconfigure('current', 0, -border => $contour);
}


Tk::MainLoop();


Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/testGraphics.pl.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
#!/usr/bin/perl
#-----------------------------------------------------------------------------------
#
#      testGraphics.pl
#      Fichier test du module Graphics
#
#      Authors: Jean-Luc Vinot <vinot@cena.fr>
#
# $Id$
#-----------------------------------------------------------------------------------

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use Tk::Zinc::Graphics;
use Math::Trig;
use Getopt::Long;
use strict 'vars';


my $currenttransfo;
my $previousangle = 0;
my $rotate_angle = .1;
my $zoomfactor = .1;
my $curview;
my ($dx, $dy);

my $tabanchor = 'n';
my $tabalign = 'left';

my $font_9b = '7x13bold';
# the original font is not standard, even if it is fully free:
# my $font_9b = '-cenapii-bleriot mini-bold-r-normal--9-90-75-75-p-75-iso8859-15';

my %gradset = (# gradients zinc
	       'boitonglet' => '=axial 0|#ff7777|#ffff99',
	       'roundrect1' => '=axial 270|#a7ffa7;70 0|#ffffff;90 5|#00bd00;80 8|#b7ffb7;50 80|#ffffff;70 91|#00ac00;70 95|#006700;60 100',
	       'roundrect2' => '=axial 270|#00bd00;80 |#d7ffd7;60',
	       'roundrect3' => '=axial 270|#00bd00;100 0|#ffffff;100 14|#ffffff;100 16|#00bd00;90 25|#b7ffb7;60 100',
	       'roundrect4' => '=axial 0|#00bd00;100 0|#ffffff;100 20|#00bd00;50 30|#00bd00;90 80|#b7ffb7;60 100',
	       'roundrect4ed' => '=path 48 48|#e7ffe7;20 0 70|#007900;20',
	       'roundcurve2' => '=axial 270|#d7ffd7;60|#7777ff;80',
	       'roundcurve1' => '=axial 270|#2222ff;80 |#d7ffd7;60',
	       'roundcurve' => '=axial 270|#7777ff;80 |#d7ffd7;60',
	       'roundpolyg' => '=radial -15 -20|#ffb7b7;50|#bd6622;90',
	       'rpolyline' => '=axial 90|#ffff77;80 |#ff7700;60',
	       'pushbtn1' => '=axial 0|#cccccc;100 0|#ffffff;100 10|#5a5a6a;100 80|#aaaadd;100 100',
	       'pushbtn2' => '=axial 270|#ccccff;100 0|#ffffff;100 10|#5a5a7a;100 80|#bbbbee;100 100',
	       'pushbtn3' => '=radial -15 -15|#ffffff;100 0|#333344;100 100',
	       'pushbtn4' => '=axial 270|#ccccff;100 0|#ffffff;100 10|#7a7a9a;100 80|#bbbbee;100 100',
	       'conical_edge' => '=conical 0 0 -45|#ffffff;100 0|#888899;100 30|#555566;100 50|#888899;100 70|#ffffff;100 100',
	       'conical_ext' => '=conical 0 0 135|#ffffff;100 0|#777788;100 30|#444455;100 50|#777788;100 70|#ffffff;100 100',
	       'pushbtn_edge' => '=axial 140|#ffffff;100 0|#555566;100 100',
	       'pushbtn_edge2' => '=axial 92|#ffffff;100 0|#555566;100 100',
	       'logoshape2' => '=axial 270|#ffffff|#7192aa',
	       'logopoint2' => '=radial -20 -20|#ffffff 0|#f70000 48|#900000 80|#ab0000 100',
	       'logoptshad2' => '=path 0 0|#770000;64 0|#770000;70 78|#770000;0 100',
	      );


# contenu des pages exemples
my %pagesconf = ('Rectangle' => {'consigne' => {-itemtype => 'text',
						 -coords => [-285, 155],
						 -params => {-font => $font_9b,
							     -text => "Mouse button 1 drag objects,\nEscape key reset transfos.",
							     -color => '#2222cc',
							    },
					      },
				  # roudedrectangle simple + radius 20
				  'rr1' => {-itemtype => 'roundedrectangle',
					    -coords => [[-200, 30], [50, 130]],
					    -radius => 20,
					    -params => {-closed => 1,
							-filled => 1,
							-fillcolor => 'roundrect2',
							-linewidth => 2,
							-linecolor => '#000000',
							-priority => 20,
							-tags => ['move'],
						       },
					   },

				  # roudedrectangle 'carré' (radius automatique)
				  'rr2' => {-itemtype => 'roundedrectangle',
					    -coords => [[-250, -100], [-90, 60]],
					    -params => {-closed => 1,
							-filled => 1,
							-fillcolor => 'roundrect1',
							-linewidth => 3,
							-linecolor => '#000000',
							-priority => 30,
							-tags => ['move'],
						       },
					   },
				  # cas particulier -> hippodrome (radius = h/2)
				  'rr3' => {-itemtype => 'roundedrectangle',
						  -coords => [[-30, 80], [130, 160]],
						  -radius => 40,
						  -params => {-closed => 1,
							      -filled => 1,
							      -fillcolor => 'roundrect3',
							      -linewidth => 4,
							      -linecolor => '#000000',
							      -priority => 30,
							      -tags => ['move'],
							     },
					   },

				  # utilisation de l'option -corners (pétales de fleur)
				  'rr4a' => {-itemtype => 'roundedrectangle',
					     -coords => [[-30, -60], [110, 10]],
					     -radius => 40,
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'roundrect3',
							 -linewidth => 3,
							 -linecolor => '#000000',
							 -priority => 30,
							 -tags => ['move'],
							},
					     -corners => [1, 0, 1, 0],
					    },
				  'rr4b' => {-itemtype => 'roundedrectangle',
					     -coords => [[118, -68], [220, -132]],
					     -radius => 40,
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'roundrect3',
							 -linewidth => 3,
							 -linecolor => '#000000',
							 -priority => 30,
							 -tags => ['move'],
							},
					     -corners => [1, 0, 1, 0],
					    },
				  'rr4c' => {-itemtype => 'roundedrectangle',
					     -coords => [[118, -60], [190, 30]],
					     -radius => 40,
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'roundrect3',
							 -linewidth => 3,
							 -linecolor => '#000000',
							 -priority => 30,
							 -tags => ['move'],
							},
					     -corners => [0, 1, 0, 1],
					    },
				  'rr4d' => {-itemtype => 'roundedrectangle',
					     -coords => [[40, -152], [110, -68]],
					     -radius => 40,
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'roundrect3',
							 -linewidth => 3,
							 -linecolor => '#000000',
							 -priority => 30,
							 -tags => ['move'],
							},
					     -corners => [0, 1, 0, 1],
					    },

				  # groupe de 2 boutons avec bordure externe
				  'gr8' => {-itemtype => 'group',
					    -coords => [0, 0],
					    -params => {-priority => 10,
							-tags => ['move'],
							-atomic => 1,
						       },
					    -items => {'edge' => {-itemtype => 'roundedrectangle',
								  -coords => [[174, -36],[266, 146]],
								  -radius => 26,
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'roundrect4ed',
									      -linewidth => 1,
									      -linecolor => '#ffffff',
									      -priority => 20,
									     },
								 },
						       'top' => {-itemtype => 'roundedrectangle',
								    -coords => [[180, -30], [260, 53]],
								    -parentgroup => 'gr8',
								    -radius => 20,
								    -params => {-closed => 1,
										-filled => 1,
										-fillcolor => 'roundrect4',
										-linewidth => 2.5,
										-linecolor => '#000000',
										-priority => 30,
									       },
								    -corners => [1, 0, 0, 1],
								   },
						       'topico' => {-itemtype => 'curve',
								    -parentgroup => 'gr8',
								    -coords => [[220, -10],[200, 30],[240, 30]],
								    -params => {-closed => 1,
										-filled => 1,
										-fillcolor => '#ffff00;80',
										-linewidth => 1,
										-linecolor => '#007900;80',
										-priority => 50,
									       },
								   },
						       'bottom' => {-itemtype => 'roundedrectangle',
								    -parentgroup => 'gr8',
								    -coords => [[180, 57], [260, 140]],
								    -radius => 20,
								    -params => {-closed => 1,
										-filled => 1,
										-fillcolor => 'roundrect4',
										-linewidth => 2.5,
										-linecolor => '#000000',
										-priority => 30,
									       },
								    -corners => [0, 1, 1, 0],
								   },
						       'bottomico' => {-itemtype => 'curve',
								       -parentgroup => 'gr8',
								       -coords => [[220, 120],[240, 80],[200, 80]],
								       -params => {-closed => 1,
										   -filled => 1,
										   -fillcolor => '#ffff00;80',
										   -linewidth => 1,
										   -linecolor => '#007900;80',
										   -priority => 50,
										  },
								      },
						      },
					   },
				 },
		 'Hippodrome' => {'consigne' => {-itemtype => 'text',
						 -coords => [-285, 165],
						 -params => {-font => $font_9b,
							     -text => "Click hippo Buttons with mouse button 1.\n",
							     -color => '#2222cc',
							    },
						},
				  'hp1' => {-itemtype => 'group',
					    -coords => [-163, -40],
					    -params => {-priority => 40,
						       },
					    -items => {'edge' => {-itemtype => 'hippodrome',
								  -coords => [[-46, -86], [46, 86]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn_edge',
									      -linewidth => 1,
									      -linecolor => '#ffffff',
									      -priority => 10,
									     },
								 },
						       'form' => {-itemtype => 'hippodrome',
								  -coords => [[-40, -80], [40, 80]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn1',
									      -linewidth => 3,
									      -linecolor => '#000000',
									      -priority => 20,
									      -tags => ['b1','pushbtn'],
									     },
								 },
						       },
					   },

				   'hp2' => {-itemtype => 'group',
					     -coords => [-40, -40],
					     -params => {-priority => 40,
							},
					    -items => {'edge' => {-itemtype => 'hippodrome',
								  -coords => [[-46, -86], [46, 86]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn_edge',
									      -linewidth => 1,
									      -linecolor => '#ffffff',
									      -priority => 10,
									     },
								 },
						       'formT' => {-itemtype => 'hippodrome',
								   -coords => [[-40, -80], [40, -28]],
								   -params => {-closed => 1,
									       -filled => 1,
									       -fillcolor => 'pushbtn1',
									       -linewidth => 3,
									       -linecolor => '#000000',
									       -priority => 20,
									       -tags => ['b2t','pushbtn'],
									      },
								   -orientation => 'vertical',
								   -trunc => 'bottom',
								  },
						       'formC' => {-itemtype => 'hippodrome',
								   -coords => [[-40, -26.5], [40, 26.5]],
								   -params => {-closed => 1,
									       -filled => 1,
									       -fillcolor => 'pushbtn1',
									       -linewidth => 3,
									       -linecolor => '#000000',
									       -priority => 20,
									       -tags => ['b2c','pushbtn'],
									      },
								   -trunc => 'both',
								  },
						       'formB' => {-itemtype => 'hippodrome',
								   -coords => [[-40, 28], [40, 80]],
								   -params => {-closed => 1,
									       -filled => 1,
									       -fillcolor => 'pushbtn1',
									       -linewidth => 3,
									       -linecolor => '#000000',
									       -priority => 20,
									       -tags => ['b2b','pushbtn'],
									      },
								   -orientation => 'vertical',
								   -trunc => 'top',
								  },
						      },
					     },
				   'hp3edge' => {-itemtype => 'hippodrome',
						 -coords => [[-204, 96], [204, 144]],
						 -params => {-closed => 1,
							     -filled => 1,
							     -fillcolor => 'pushbtn_edge2',
							     -linewidth => 1,
							     -linecolor => '#ffffff',
							     -priority => 10,
							    },
						},
				  'hp3g' => {-itemtype => 'group',
					     -coords => [-160, 120],
					     -params => {-priority => 40,
							},
					    -items => {'form' => {-itemtype => 'hippodrome',
								  -coords => [[-40, -20], [40, 20]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn2',
									      -linewidth => 2,
									      -linecolor => '#000000',
									      -priority => 20,
									      -tags => ['b3g','pushbtn'],
									     },
								  -trunc => 'right',
								 },
						       'ico' => {-itemtype => 'curve',
								 -coords => [[-20, 0],[-4, 8],[-4, -8]],
								 -params => {-closed => 1,
									     -filled => 1,
									     -fillcolor => '#000000',
									     -linewidth => 1,
									     -linecolor => '#aaaaaa',
									     -relief => 'raised',
									     -priority => 30,
									     -tags => ['b3g','pushbtn','ico'],
									    },
								 -contours =>  [['add',-1,[[0, 0],[16, 8],[16, -8]]]],
								},
						      },
					     },
				  'hp3c1' => {-itemtype => 'group',
					      -coords => [-80, 120],
					      -params => {-priority => 40,
							 },
					    -items => {'form' => {-itemtype => 'hippodrome',
								  -coords => [[-38, -20], [39, 20]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn2',
									      -linewidth => 2,
									      -linecolor => '#000000',
									      -priority => 20,
									      -tags => ['b3c1','pushbtn'],
									     },
								  -trunc => 'both',
								 },
						       'ico' => {-itemtype => 'curve',
								 -coords => [[-8, 0],[8, 8],[8, -8]],
								 -params => {-closed => 1,
									     -filled => 1,
									     -fillcolor => '#000000',
									     -linewidth => 1,
									     -linecolor => '#aaaaaa',
									     -priority => 30,
									     -relief => 'raised',
									     -tags => ['b3c1','pushbtn','ico'],
									    },
								},
						       },
					      },
				  'hp3c2' => {-itemtype => 'group',
					      -coords => [0, 120],
					      -params => {-priority => 40,
							 },
					      -items => {'form' => {-itemtype => 'hippodrome',
								  -coords => [[-39, -20], [39, 20]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn2',
									      -linewidth => 2,
									      -linecolor => '#000000',
									      -priority => 20,
									      -tags => ['b3c2','pushbtn'],
									     },
								  -trunc => 'both',
								 },
						       'ico' => {-itemtype => 'rectangle',
								 -coords => [[-6, -6],[6, 6]],
								 -params => {-filled => 1,
									     -fillcolor => '#000000',
									     -linewidth => 1,
									     -linecolor => '#aaaaaa',
									     -priority => 30,
									     -tags => ['b3c2','pushbtn','ico'],
									    },
								},
						       },
					      },
				  'hp3C3' => {-itemtype => 'group',
					      -coords => [80, 120],
					      -params => {-priority => 40,
							 },
					      -items => {'form' => {-itemtype => 'hippodrome',
								    -coords => [[-39, -20], [39, 20]],
								    -params => {-closed => 1,
										-filled => 1,
										-fillcolor => 'pushbtn2',
										-linewidth => 2,
										-linecolor => '#000000',
										-priority => 20,
										-tags => ['b3c3','pushbtn'],
									       },
								    -trunc => 'both',
								   },
							 'ico' => {-itemtype => 'curve',
								   -coords => [[8, 0],[-8, -8],[-8, 8]],
								   -params => {-closed => 1,
									       -filled => 1,
									       -fillcolor => '#000000',
									       -linewidth => 1,
									       -linecolor => '#aaaaaa',
									       -priority => 30,
									       -relief => 'raised',
									       -tags => ['b3c3','pushbtn','ico'],
									      },
								  },
							},
					     },

				  'hp3D' => {-itemtype => 'group',
					     -coords => [160, 120],
					     -params => {-priority => 40,
							 },
					     -items => {'form' => {-itemtype => 'hippodrome',
								   -coords => [[-40, -20], [40, 20]],
								   -params => {-closed => 1,
									       -filled => 1,
									       -fillcolor => 'pushbtn2',
									       -linewidth => 2,
									       -linecolor => '#000000',
									       -priority => 20,
									       -tags => ['b3d','pushbtn'],
									      },
								   -trunc => 'left',
								  },
							'ico' => {-itemtype => 'curve',
								  -coords => [[20, 0],[4, -8],[4, 8]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => '#000000',
									      -linewidth => 1,
									      -linecolor => '#aaaaaa',
									      -priority => 30,
									      -relief => 'raised',
									      -tags => ['b3d','pushbtn','ico'],
									     },
								  -contours =>  [['add',-1,[[0,0],[-16, -8],[-16, 8]]]],
								 },
						       },
					    },

				  'hp4a' => {-itemtype => 'group',
					     -coords => [48, -97],
					     -params => {-priority => 40,
							},
					     -repeat => {-num => 2,
							 -dxy => [0, 64],
							},
					    -items => {'edge' => {-itemtype => 'hippodrome',
								  -coords => [[-29, -29], [29, 29]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn_edge',
									      -linewidth => 1,
									      -linecolor => '#ffffff',
									      -priority => 0,
									     },
								 },
						       'form' => {-itemtype => 'hippodrome',
								  -coords => [[-24, -24], [24, 24]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn3',
									      -linewidth => 3,
									      -linecolor => '#000000',
									      -priority => 30,
									      -tags => ['b4a','pushbtn'],
									     },
								 },
						      },
					    },

				  'hp4b' => {-itemtype => 'group',
					     -coords => [145, -65],
					     -params => {-priority => 40,
							},
					    -items => {'edge' => {-itemtype => 'hippodrome',
								  -coords => [[-60, -60], [60, 60]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'conical_edge',
									      -linewidth => 1,
									      -linecolor => '#ffffff',
									      -priority => 0,
									     },
								 },
						       'ext' => {-itemtype => 'hippodrome',
								 -coords => [[-53, -53], [53, 53]],
								 -params => {-closed => 1,
									     -filled => 1,
									     -fillcolor => 'conical_ext',
									     -linewidth => 3,
									     -linecolor => '#000000',
									     -priority => 10,
									     -tags => ['b4b','pushbtn'],
									    },
								},
						       'int' => {-itemtype => 'hippodrome',
								 -coords => [[-41, -41], [40, 40]],
								 -params => {-closed => 1,
									     -filled => 1,
									     -fillcolor => '=path 10 10|#ffffff 0|#ccccd0 50|#99999f 80|#99999f;0 100',
									     -linewidth => 0,
									     -linecolor => '#cccccc;80',
									     -priority => 30,
									     -tags => ['b4b','pushbtn'],
									    },
								},
						      },
					    },

				  'hp5' => {-itemtype => 'group',
					    -coords => [60, 25],
					    -params => {-priority => 40,
						       },
					    -rotate => 30,
					    -repeat => {-num => 4,
							-dxy => [45, 0],
						       },
					    -items => {'edge' => {-itemtype => 'hippodrome',
								  -coords => [[-19, -34], [19, 34]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn_edge',
									      -linewidth => 1,
									      -linecolor => '#ffffff',
									      -priority => 10,
									     },
								 },
						       'form' => {-itemtype => 'hippodrome',
								  -coords => [[-15, -30], [15, 30]],
								  -params => {-closed => 1,
									      -filled => 1,
									      -fillcolor => 'pushbtn1',
									      -linewidth => 2,
									      -linecolor => '#000000',
									      -priority => 20,
									      -tags => ['b5','pushbtn'],
									     },
								 },
						       },
					   },
				 },

		 'Polygone' => {'consigne' => {-itemtype => 'text',
						 -coords => [-285, 160],
						 -params => {-font => $font_9b,
							     -text => "Click and Drag inside Polygons for rotate them\nEscape key reset transfos.",
							     -color => '#2222cc',
							    },
					      },
				'triangle' => {-itemtype => 'group',
					       -coords => [-215, -95],
					       -items => {'form' => {-itemtype => 'polygone',
								     -coords => [0, 0],
								     -numsides => 3,
								     -radius => 78,
								     -corner_radius => 10,
								     -startangle => 90,
								     -params => {-closed => 1,
										 -filled => 1,
										 -fillcolor => 'roundpolyg',
										 -linewidth => 2,
										 -linecolor => '#330000',
										 -priority => 20,
										 -tags => ['p1', 'poly'],
										},
								    },
							  'text' => {-itemtype => 'text',
								     -coords => [0, -6],
								     -params => {-font => $font_9b,
										 -text => "Triangle",
										 -anchor => 'n',
										 -alignment => 'center',
										 -color => '#660000',
										 -priority => 50,
										},
								    },
							 },
					      },

				 'carre' => {-itemtype => 'group',
					     -coords => [-80, -75],
					     -items => {'form' => {-itemtype => 'polygone',
								   -coords => [0, 0],
								   -numsides => 4,
								   -radius => 70,
								   -corner_radius => 10,
								   -startangle => 90,
								   -params => {-closed => 1,
									       -filled => 1,
									       -fillcolor => 'roundpolyg',
									       -linewidth => 2,
									       -linecolor => '#330000',
									       -priority => 20,
									       -tags => ['p2', 'poly'],
									      },
								  },
							'text' => {-itemtype => 'text',
								   -coords => [0, -6],
								   -params => {-font => $font_9b,
									       -text => "Carré",
									       -anchor => 'n',
									       -alignment => 'center',
									       -color => '#660000',
									       -priority => 50,
									      },
								  },
						       },
					    },

				'pentagone' => {-itemtype => 'group',
						-coords => [65, -75],
						-items => {'form' => {-itemtype => 'polygone',
								      -coords => [0, 0],
								      -numsides => 5,
								      -radius => 70,
								      -corner_radius => 10,
								      -startangle => 270,
								      -params => {-closed => 1,
										  -filled => 1,
										  -fillcolor => 'roundpolyg',
										  -linewidth => 2,
										  -linecolor => '#330000',
										  -priority => 20,
										  -tags => ['p3', 'poly'],
										 },
								     },
							   'text' => {-itemtype => 'text',
								      -coords => [0, -6],
								      -params => {-font => $font_9b,
										  -text => "Pentagone",
										  -anchor => 'n',
										  -alignment => 'center',
										  -color => '#660000',
										  -priority => 50,
										 },
								     },
							  },
					       },

				'hexagone' => {-itemtype => 'group',
					       -coords => [210, -75],
					       -items => {'form' => {-itemtype => 'polygone',
								     -coords => [0, 0],
								     -numsides => 6,
								     -radius => 68,
								     -corner_radius => 10,
								     -params => {-closed => 1,
										 -filled => 1,
										 -fillcolor => 'roundpolyg',
										 -linewidth => 2,
										 -linecolor => '#330000',
										 -priority => 20,
										 -tags => ['p4', 'poly'],
										},
								    },
							  'text' => {-itemtype => 'text',
								     -coords => [0, -6],
								     -params => {-font => $font_9b,
										 -text => "Hexagone",
										 -anchor => 'n',
										 -alignment => 'center',
										 -color => '#660000',
										 -priority => 50,
										},
								    },
							 },
					      },

				'heptagone' => {-itemtype => 'group',
						-coords => [-215, 85],
						-items => {'form' => {-itemtype => 'polygone',
								      -coords => [0, 0],
								      -numsides => 7,
								      -radius => 64,
								      -corner_radius => 10,
								      -params => {-closed => 1,
										  -filled => 1,
										  -fillcolor => 'roundpolyg',
										  -linewidth => 2,
										  -linecolor => '#330000',
										  -priority => 20,
										  -tags => ['p5', 'poly'],
										 },
								     },
							   'text' => {-itemtype => 'text',
								      -coords => [0, -6],
								      -params => {-font => $font_9b,
										  -text => "Heptagone",
										  -anchor => 'n',
										  -alignment => 'center',
										  -color => '#660000',
										  -priority => 50,
										 },
								     },
							  },
					       },
				

				'octogone' => {-itemtype => 'group',
					       -coords => [-76, 85],
					       -items => {'form' => {-itemtype => 'polygone',
								     -coords => [0, 0],
								     -numsides => 8,
								     -radius => 64,
								     -corner_radius => 10,
								     -params => {-closed => 1,
										 -filled => 1,
										 -fillcolor => 'roundpolyg',
										 -linewidth => 2,
										 -linecolor => '#330000',
										 -priority => 20,
										 -tags => ['p6', 'poly'],
										},
								    },
							  'text' => {-itemtype => 'text',
								     -coords => [0, -6],
								     -params => {-font => $font_9b,
										 -text => "Octogone",
										 -anchor => 'n',
										 -alignment => 'center',
										 -color => '#660000',
										 -priority => 50,
										},
								    },
							 },
					      },

				'petagone' => {-itemtype => 'group',
					       -coords => [66, 85],
					       -items => {'form' => {-itemtype => 'polygone',
								     -coords => [0, 0],
								     -numsides => 32,
								     -radius => 64,
								     -corner_radius => 10,
								     -params => {-closed => 1,
										 -filled => 1,
										 -fillcolor => 'roundpolyg',
										 -linewidth => 2,
										 -linecolor => '#330000',
										 -priority => 20,
										 -tags => ['p7', 'poly'],
										},
								    },
							  'text' => {-itemtype => 'text',
								     -coords => [0, -6],
								     -params => {-font => $font_9b,
										 -text => "32 cotés...",
										 -anchor => 'n',
										 -alignment => 'center',
										 -color => '#660000',
										 -priority => 50,
										},
								    },
							 },
					      },

				'etoile' => {-itemtype => 'group',
					     -coords => [210, 85],
					     -items => {'form' => {-itemtype => 'polygone',
								   -coords => [0, 0],
								   -numsides => 5,
								   -radius => 92,
								   -inner_radius => 36,
								   -corner_radius => 10,
								   -startangle => 270,
								   -corners => [0,1,0,1,0,1,0,1,0,1],
								   -params => {-closed => 1,
									       -filled => 1,
									       -fillcolor => 'roundpolyg',
									       -linewidth => 2,
									       -linecolor => '#330000',
									       -priority => 20,
									       -tags => ['p8', 'poly'],
									      },
								  },
							'text' => {-itemtype => 'text',
								   -coords => [0, -6],
								   -params => {-font => $font_9b,
									       -text => "Etoile",
									       -anchor => 'n',
									       -alignment => 'center',
									       -color => '#660000',
									       -priority => 50,
									      },
								  },
						       },
					    },
			       },

		 'Polyline' => {'consigne' => {-itemtype => 'text',
						 -coords => [-285, 155],
						 -params => {-font => $font_9b,
							     -text => "Mouse button 1 drag objects,\nEscape key reset transfos.",
							     -color => '#2222cc',
							    },
					      },
				 'a' => {-itemtype => 'polyline',
					 -coords => [[-200, -115],[-200, -100],[-218, -115],[-280, -115],[-280, -16],
						     [-218, -16],[-200, -31],[-200, -17.5],[-150, -17.5],[-150,-115]],
					 -corners_radius => [0, 0, 42, 47, 47, 42, 0, 0, 0, 0, 0, 0],
					 -params => {-closed => 1,
						     -filled => 1,
						     -visible => 1,
						     -fillcolor => 'rpolyline',
						     -linewidth => 2,
						     -linecolor => '#000000',
						     -priority => 50,
						     -tags => ['move'],
						    },
					 -contours => [['add', -1, [[-230, -80],[-230, -50],[-200, -50],[-200, -80]],15]],
					 },
				 'b' => {-itemtype => 'polyline',
					 -coords => [[-138, -150],[-138, -17.5],[-88, -17.5],[-88, -31],[-70, -16],
						     [-8, -16],[-8, -115],[-70, -115],[-88, -100],[-88, -150]],
					 -corners_radius => [0, 0, 0, 0, 42, 47, 47, 42, 0, 0, 0, 0, 0, 0],
					 -params => {-closed => 1,
						     -filled => 1,
						     -visible => 1,
						     -fillcolor => 'rpolyline',
						     -linewidth => 2,
						     -linecolor => '#000000',
						     -priority => 50,
						     -tags => ['move'],
						    },
					 -contours => [['add', -1, [[-88, -80],[-88, -50],[-58, -50],[-58, -80]],15]],
					},
				 'c' => {-itemtype => 'polyline',
					 -coords => [[80, -76],[80, -110],[60, -115],[0, -115],[0, -16],
						     [60, -16],[80, -21],[80, -57],[50, -47],[50, -86]],
					 -corners_radius => [0, 0, 70, 47, 47, 70, 0, 0, 14, 14, 0, 0, 0,0 ],
					 -params => {-closed => 1,
						     -filled => 1,
						     -visible => 1,
						     -fillcolor => 'rpolyline',
						     -linewidth => 2,
						     -linecolor => '#000000',
						     -priority => 50,
						     -tags => ['move'],
						    },
					},
				 'spirale' => {-itemtype => 'polyline',
					      -coords => [[215, -144],[139, -144],[139, 0],[268, 0],[268, -116],
							   [162.5, -116],[162.5, -21],[248, -21],[248, -96],[183, -96],
							  [183, -40],[231,-40],[231, -80],[199, -80],[199, -55],[215, -55]],
					       -corners_radius => [0, 76, 68, 61, 55, 50, 45, 40, 35, 30, 26, 22, 18, 14, 11],
					       -params => {-closed => 1,
							   -filled => 1,
							   -visible => 1,
							   -fillcolor => 'rpolyline',
							   -linewidth => 2,
							   -linecolor => '#000000',
							   -priority => 50,
							   -tags => ['move'],
							  },
					      },
				 'logo' => {-itemtype => 'group',
					    -coords => [0, 0],
					    -params => {-priority => 30,
							-atomic => 1,
							-tags => ['move'],
							},
					    -items => {'tkzinc' => {-itemtype => 'polyline',
								    -coords => [[-150,10],[-44,10],[-44,68],[-28,51],[6,51],
										[-19,79],[3,109],[53,51],[5,51],[5,10],[140,10],
										[52,115],[96,115],[96,47],[196,47],[196,158],
										[155,158],[155,89],[139,89],[139,160],[101, 160],
										[101,132],[85,132],[85,160],[-42,160],[-2,115],
										[-30,115],[-46,91],[-46,115],[-76,115],[-76,51],
										[-98,51],[-98,115],[-130,115],[-130,51],[-150, 51]],
								    -corners_radius => [0,0,0,0,0,0,0,0,0,0,30,0,0,50,50,
											0,0,8,8,0,0,8,8,0,27],
								    -params => {-closed => 1,
										-filled => 1,
										-visible => 1,
										-fillcolor => 'logoshape2',
										-linewidth => 2.5,
										-linecolor => '#000000',
										-priority => 10,
										-fillrule => 'nonzero',
									       },

								    -contours => [['add', 1, [[245,88],[245,47],[190,47],[190,158],
											       [259,158],[259,117],[230,117],[230,88]],
										   5, undef, [0,0,55,55,0,0,15,15]]],
								   },
						       'shad' => {-itemtype => 'arc',
								   -coords => [[75, 91],[115,131]],
								   -params => {-priority => 20,
									       -filled => 1,
									       -linewidth => 0,
									       -fillcolor => 'logoptshad2',
									       -closed => 1,
									      },
								  },
						       'point' => {-itemtype => 'arc',
								   -coords => [[70, 86],[110,126]],
								   -params => {-priority => 50,
									       -filled => 1,
									       -linewidth => 1,
									       -linecolor => '#a10000',
									       -fillcolor => 'logopoint2',
									       -closed => 1,
									      },
								  },
						      },
					    },
				 },

		 'MultiContours' => {'consigne' => {-itemtype => 'text',
						 -coords => [-285, 155],
						 -params => {-font => $font_9b,
							     -text => "Mouse button 1 drag objects,\nEscape key reset transfos.",
							     -color => '#2222cc',
							    },
					      },
				     'mc1' => {-itemtype => 'roundedcurve',
					      -coords => [[-30, -170], [-130, 0],[70, 0]],
					      -radius => 14,
					      -params => {-closed => 1,
							  -filled => 1,
							  -fillcolor => 'roundcurve2',
							  -linewidth => 1,
							  -linecolor => '#000000',
							  -priority => 20,
							  -tags => ['move'],
							  -fillrule => 'odd',
							 },
					       -contours => [['add',1,[[-30,-138],[-100,-18],[40,-18]],8],
							     ['add',1,[[-30,-130],[ -92,-22],[32,-22]],5],
							     ['add',1,[[-30,-100],[ -68,-36],[8,-36]],5],
							     ['add',1,[[-30, -92],[ -60,-40],[0,-40]],3],],
					     },
				    'mc2' => {-itemtype => 'polyline',
					      -coords => [[-250,-80], [-240,-10],[-285,-10],[-285,80],
							  [-250, 80],[-250, 40],[-170, 40],[-170,80],
							  [-100,80],[-100,40],[-20,40],[-20,80],[30,80],
							  [-10, 0],[-74, -10],[-110, -80]],
					      -corners_radius => [24,4, 40, 20, 0, 40, 40, 0, 0, 40, 40, 0, 30, 75, 0, 104],
					      -params => {-closed => 1,
							  -filled => 1,
							  -fillcolor => 'roundcurve1',
							  -linewidth => 2,
							  -linecolor => '#000000',
							  -priority => 30,
							  -tags => ['move'],
							  },
					      -contours => [['add',-1,[[-240,-72],[-230,0],[-169,0],[-185, -72]],
							     0, undef, [16, 16, 0, 0]],
							    ['add', -1, [[-175,-72],[-159,0],[-78,0],[-116, -72]],
							     0, undef, [0, 0, 8, 88]],
							    ['add', 1, [[-245,45],[-245,115],[-175,115],[-175, 45]],
							     35],
							    ['add', -1, [[-225,65],[-225,95],[-195,95],[-195, 65]],
							     15],
							    ['add', 1, [[-95,45],[-95,115],[-25,115],[-25, 45]],
							     35],
							    ['add', -1, [[-75,65],[-75,95],[-45,95],[-45, 65]],
							     15],
							   ],
					     },
				    'mc3' => {-itemtype => 'roundedcurve',
					      -coords => [[-10, 170], [256, 170],[312, 60],[48, 60]],
					      -radius => 34,
					      -params => {-closed => 1,
							  -filled => 1,
							  -fillcolor => 'roundcurve2',
							  -linewidth => 2.5,
							  -linecolor => '#000000',
							  -priority => 40,
							  -tags => ['move'],
							 },
					      -contours => [['add', -1, [[58, 62],[12, 144],[60, 172],[104, 88]],27],
							    ['add', 1, [[48, 77],[48, 119],[90, 119],[90, 77]],21],
							    ['add', -1, [[244, 58],[198, 140],[246, 168],[290, 84]],27],
							    ['add', 1, [[213, 110],[213, 152],[255, 152],[255, 110]],21],
							    ['add', -1, [[150, 60],[150, 170],[160, 170],[160, 60]],0]],
					      },
				     'mc4' => {-itemtype => 'roundedcurve',
					      -coords => [[222, -150],[138, -150],[180, -50],[138, -150],
							  [80, -92],[180, -50],[80, -92],[80, -8],
							  [180, -50],[80, -8],[138, 50],[180, -50],
							  [138, 50],[222, 50],[179.8, -50],[222, 50],
							  [280, -8],[180, -50],[280, -8],[280, -92],
							  [180, -50],[280, -92],[222,-150],[180,-50]],
					      -radius => 28,
					      -params => {-closed => 1,
							  -filled => 1,
							  -fillcolor => 'roundcurve',
							  -linewidth => 2,
							  -linecolor => '#000000',
							  -priority => 30,
							  -tags => ['move'],
							 },
					      -contours => [['add', -1, [[160, -70],[160, -30],[200, -30],[200, -70]],20]],
					      },
				    },

		 'TabBox' => {'consigne' => {-itemtype => 'text',
					     -coords => [-285, 160],
					     -params => {-font => $font_9b,
							 -text => "Click on thumbnail to select page\nChange anchor or alignment tabs options with radio buttons.\n",
							 -color => '#2222cc',
							},
					    },

			      'exemple' => {-itemtype => 'text',
					    -coords => [-165, -105],
					    -params => {-font => $font_9b,
							-text => "",
							-alignment => 'left',
							-anchor => 'nw',
							-color => '#000000',
							-priority => 500,
							-width => 350,
							-tags => ['div2', 'fontname'],
						       },
					    },

			      'bo1' => {-itemtype => 'tabbox',
					-coords => [[-240, -160], [240, 100]],
					-radius => 8,
					-tabwidth => 72,
					-tabheight => 28,
					-numpages => 8,
					-anchor => 'n',
					-alignment => 'left',
					-overlap => 3,
					-params => {-closed => 1,
						    -priority => 100,
						    -filled => 1,
						    -fillcolor => '#ffffff',
						    -linewidth => 1.2,
						    -linecolor => '#000000',
						    -tags => ['div2', 'divider'],
						   },
					-tabtitles => {-text => ['A', 'B', 'C', 'D', 'E', 'F','G','H'],
						       -params => {-text => 'titre',
								   -color => '#2222cc',
								   -font => $font_9b,
								   -anchor => 'center',
								   -alignment => 'center',
								   -priority => 400,
								   -visible => 1,
								  },
						      },
				       },

			       'back' => {-itemtype => 'roundedrectangle',
					  -coords => [[-242, -162], [242, 102]],
					  -radius => 10,
					  -params => {-closed => 1,
						      -filled => 1,
						      -fillcolor => '#777777;80',
						      -linewidth => 1,
						      -linecolor => '#777777;80',
						     },
					 },

			       'anchor' => {-itemtype => 'text',
					    -coords => [-120, 115],
					    -params => {-text => 'tabs anchor',
							-color => '#2222cc',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
						       },
					   },

			       'anchorN' => {-itemtype => 'hippodrome',
					     -coords => [[-210, 125], [-165, 151]],
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'pushbtn4',
							 -linewidth => 1.5,
							 -linecolor => '#000000',
							 -priority => 20,
							 -tags => ['sel1','n','btn','selector'],
							},
					     -trunc => 'right',
					    },
			       'txtanN' => {-itemtype => 'text',
					    -coords => [-187, 138],
					    -params => {-text => 'N',
							-color => '#000000',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
							-tags => ['sel1','n','btntext','selector'],
						       },
					   },

			       'anchorE' => {-itemtype => 'hippodrome',
					     -coords => [[-163, 125], [-120, 151]],
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'pushbtn4',
							 -linewidth => 1.5,
							 -linecolor => '#000000',
							 -priority => 20,
							 -tags => ['sel1','e','btn','selector'],
							},
					     -trunc => 'both',
					    },
			       'txtanE' => {-itemtype => 'text',
					    -coords => [-141.5, 138],
					    -params => {-text => 'E',
							-color => '#000000',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
							-tags => ['sel1','e','btntext','selector'],
						       },
					   },

			       'anchorS' => {-itemtype => 'hippodrome',
					     -coords => [[-118, 125], [-75, 151]],
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'pushbtn4',
							 -linewidth => 1.5,
							 -linecolor => '#000000',
							 -priority => 20,
							 -tags => ['sel1','s','btn','selector'],
							},
					     -trunc => 'both',
					    },
			       'txtanS' => {-itemtype => 'text',
					    -coords => [-96.5, 138],
					    -params => {-text => 'S',
							-color => '#000000',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
							-tags => ['sel1','s','btntext','selector'],
						       },
					   },
			       'anchorW' => {-itemtype => 'hippodrome',
					     -coords => [[-73, 125], [-28, 151]],
					     -params => {-closed => 1,
							 -filled => 1,
							 -fillcolor => 'pushbtn4',
							 -linewidth => 1.5,
							 -linecolor => '#000000',
							 -priority => 20,
							 -tags => ['sel1','w','btn','selector'],
							},
					     -trunc => 'left',
					    },
			       'txtanW' => {-itemtype => 'text',
					    -coords => [-52, 138],
					    -params => {-text => 'W',
							-color => '#000000',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
							-tags => ['sel1','w','btntext','selector'],
						       },
					   },
			       'alignment' => {-itemtype => 'text',
					       -coords => [120, 115],
					       -params => {-text => 'tabs alignment',
							   -color => '#2222cc',
							   -font => $font_9b,
							   -anchor => 'center',
							   -alignment => 'center',
							   -priority => 40,
							  },
					      },
			       'alignG' => {-itemtype => 'hippodrome',
					    -coords => [[30, 125], [90, 151]],
					    -params => {-closed => 1,
							-filled => 1,
							-fillcolor => 'pushbtn4',
							-linewidth => 1.5,
							-linecolor => '#000000',
							-priority => 20,
							-tags => ['sel2','left','btn','selector'],
						       },
					    -trunc => 'right',
					   },
			       'txtalG' => {-itemtype => 'text',
					    -coords => [60, 138],
					    -params => {-text => 'left',
							-color => '#000000',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
							-tags => ['sel2','left','btntext','selector'],
						       },
					   },
			       'alignC' => {-itemtype => 'hippodrome',
					    -coords => [[92, 125], [148, 151]],
					    -params => {-closed => 1,
							-filled => 1,
							-fillcolor => 'pushbtn4',
							-linewidth => 1.5,
							-linecolor => '#000000',
							-priority => 20,
							-tags => ['sel2','center','btn','selector'],
						       },
					    -trunc => 'both',
					   },
			       'txtalC' => {-itemtype => 'text',
					    -coords => [120, 138],
					    -params => {-text => 'center',
							-color => '#000000',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
							-tags => ['sel2','center','btntext','selector'],
						       },
					   },
			       'alignD' => {-itemtype => 'hippodrome',
					    -coords => [[150, 125], [210, 151]],
					    -params => {-closed => 1,
							-filled => 1,
							-fillcolor => 'pushbtn4',
							-linewidth => 1.5,
							-linecolor => '#000000',
							-priority => 20,
							-tags => ['sel2','right','btn','selector'],
						       },
					    -trunc => 'left',
					   },
			       'txtalD' => {-itemtype => 'text',
					    -coords => [180, 138],
					    -params => {-text => 'right',
							-color => '#000000',
							-font => $font_9b,
							-anchor => 'center',
							-alignment => 'center',
							-priority => 40,
							-tags => ['sel2','right','btntext','selector'],
						       },
					   },
			      },

		 'PathLine' => {'consigne' => {-itemtype => 'text',
					       -coords => [-285, 155],
					       -params => {-font => $font_9b,
							   -text => "Mouse button 1 drag objects,\nEscape key reset transfos.",
							   -color => '#2222cc',
							  },
					      },
				'pl1' => {-itemtype => 'pathline',
					  -metacoords => {-type => 'polygone',
							  -coords => [0, 0],
							  -numsides => 12,
							  -radius => 200,
							  -inner_radius => 100,
							  -startangle => -8,
							 },
					  -linewidth => 20,
					  -closed => 1,
					  -graduate => {-type => 'linear',
							-colors => ['#ff0000', '#ff00ff', '#0000ff', '#00ffff',
								    '#00ff00', '#ffff00', '#ff0000'],
						       },
					  -params => {-priority => 100,
						      -tags => ['move'],
						     },
					 },

				'pl2' => {-itemtype => 'group',
					  -coords => [0, 0],
					  -params => {-priority => 200,
						      -atomic => 1,
						      -tags => ['move'],
						     },
					  -items => {'in' => {-itemtype => 'pathline',
							      -coords => [[30, -60],[-30, -60],[-30, -30],
									  [-60, -30],[-60, 30],[-30, 30],
									  [-30, 60],[30, 60],[30, 30],
									  [60, 30],[60, -30],[30, -30]],
							      -linewidth => 16,
							      -closed => 1,
							      -shifting => 'left',
							      -graduate => {-type => 'transversal',
									    -colors => ['#00aa77;100', '#00aa77;0'],
									   },
							      -params => {-priority => 10,
									  },
							     },

						     'out' => {-itemtype => 'pathline',
							       -coords => [[30, -60],[-30, -60],[-30, -30],
									   [-60, -30],[-60, 30],[-30, 30],
									   [-30, 60],[30, 60],[30, 30],
									   [60, 30],[60, -30],[30, -30]],
							       -linewidth => 10,
							       -closed => 1,
							       -shifting => 'in',
							       -graduate => {-type => 'transversal',
									     -colors => ['#00aa77;100', '#00aa77;0'],
									    },
							       -params => {-priority => 10,
									   },
							      },
						    },
					 },

				'pl3' => {-itemtype => 'group',
					  -coords => [0, 0],
					  -params => {-priority => 100,
						      -atomic => 1,
						      -tags => ['move'],
						     },
					  -items => {'back' => {-itemtype => 'arc',
								-coords => [[-150, -150],[150,150]],
								-params => {-priority => 10,
									    -closed => 1,
									    -filled => 1,
									    -fillcolor => '=radial 15 15|#ffffff;40|#aaaaff;10',
									    -linewidth => 0,
									    },
							       },
						     'light' => {-itemtype => 'pathline',
								 -metacoords => {-type => 'polygone',
										 -coords => [0, 0],
										 -numsides => 30,
										 -radius => 150,
										 -startangle => 240,
										},
								 -linewidth => 20,
								 -shifting => 'in',
								 -closed => 1,
								 -graduate => {-type => 'double',
									       -colors => [['#ffffff;0', '#222299;0', '#ffffff;0'],
											   ['#ffffff;100', '#222299;70', '#ffffff;100']],
									      },
								 -params => {-priority => 50,
									    },
								},
						     'bord' => {-itemtype => 'arc',
								-coords => [[-150, -150],[150,150]],
								-params => {-priority => 100,
									    -closed => 1,
									    -filled => 0,
									    -linewidth => 2,
									    -linecolor => '#000033;80'
									    },
							       },

						    },
					 },
			       },

		);

my %tabtable = ('n' => {-numpages => 8,
			-titles => ['A','B','C','D','E','F','G','H'],
			-names => ['ATOMIC GROUP :','BIND COMMAND :','CURVE ITEMS :','DISPLAY LIST :',
				   'EVENTS SENSITIVITY :','FIT COMMAND :','GROUP ITEMS','HASTAG COMMAND'],
			-texts => ["It may seem at first that there is a contradiction in this title, but there is not. [...] So groups have a feature, the atomic  attribute, that is used to seal a group so that events cannot propagate past it downward. If an item part of an atomic group is under the pointer, TkZinc will try to trigger bindings associated with the atomic group not with the item under the pointer. This improves greatly the metaphor of an indivisible item.",
				   "This widget command is similar to the Tk bind command except that it operates on TkZinc items instead of widgets. Another difference with the bind command is that only mouse and keyboard related events can be specified (such as Enter, Leave, ButtonPress, ButtonRelease, Motion, KeyPress, KeyRelease). The bind manual page is the most accurate place to look for a definition of sequence and command and for a general understanding of how the binding mecanism works.",
				   "Items of type curve display pathes of line segments and/or cubic bezier connected by their end points. A cubic Bezier is defined by four points. The first and last ones are the extremities of the cubic Bezier. The second and the third ones are control point (i.e. they must have a third ``coordinate'' with the value 'c'). If both control points are identical, one may be omitted. As a consequence, it is an error to have more than two succcessive control points or to start or finish a curve with a control point.",
				   "The items are arranged in a display list for each group. The display list imposes a total ordering among its items. The group display lists are connected in a tree identical to the group tree and form a hierarchical display list. The items are drawn by traversing the display list from the least visible item to the most visible one.The search to find the item that should receive an event is done in the opposite direction. In this way, items are drawn according to their relative stacking order and events are dispatched to the top-most item at a given location.",
				   "An item will catch an event if all the following conditions are satisfied: * the item -sensitive must be set to true (this is the default). * the item must be under the pointer location. * the item must be on top of the display list (at the pointer location). Beware that an other item with its -visible set to false DOES catch event before any underneath items. * the item must not be clipped (at the pointer location) * the item must not belong to an atomic group, since an atomic group catchs the event instead of the item.",
				   "This command fits a sequence of Bezier segments on the curve described by the vertices in coordList and returns a list of lists describing the points and control points for the generated segments. All the points on the fitted segments will be within error  distance from the given curve. coordList should be either a flat list of an even number of coordinates in x, y order or a list of lists of point coordinates X, Y. The returned list can be directly used to create or change a curve item contour.",
				   "Groups are very powerful items. They have no graphics of their own but are used to bundle items together so that they can be manipulated easily as a whole. Groups can modify in several way how items are displayed and how they react to events. They have many uses in TkZinc. The main usages are to bundle items, to interpose a new coordinate system in a hierarchy of items, to compose some specific attributes, to apply a clipping to their children items, to manage display",
				   "This command returns a boolean telling if the item specified by tagOrId has the specified tag. If more than one item is named by tagOrId, then the topmost in display list order is used to return the result. If no items are named by tagOrId, an error is raised.",
				  ],
		       },
		'e' => {-numpages => 5,
			-titles => ['I','J','K','L','M'],
			-names => ['ITEM IDS','JOINSTYLE ATTRIBUTE','K :','LOWER COMMAND','MAP ITEM :'],
			-texts => ["Each item is associated with a unique numerical id which is returned by the add  or clone  commands. All commands on items accept those ids as (often first) parameter in order to uniquely identify on which item they should operate. When an id has been allocated to an item, it is never collected even after the item has been destroyed, in a TkZinc session two items cannot have the same id. This property can be quite useful when used in conjonction with tags, which are described below.",
				   "Specifies the form of the joint between the curve segments. This attribute is only applicable if the curve outline relief is flat. The default value is round.",
				   "No TkZinc KeyWord with K initial letter...",
				   "Reorder all the items given by tagOrId so that they will be under the item given by belowThis. If tagOrId name more than one item, their relative order will be preserved. If tagOrId doesn't name an item, an error is raised. If  belowThis name more than one item, the bottom most them is used. If belowThis  doesn't name an item, an error is raised. If belowThis is omitted the items are put at the bottom most position of their respective groups.",
				   "Map items are typically used for displaying maps on a radar display view. Maps are not be sensitive to mouse or keyboard events, but have been designed to efficiently display large set of points, segments, arcs, and simple texts. A map item is associated to a mapinfo. This mapinfo entity can be either initialized with the videomap  command or more generally created and edited with a set of commands described in the The mapinfo related commands  section.",
				  ],
		       },
		's' => {-numpages => 8,
			-titles => ['N','O','P','Q','R','S','T','U'],
			-names => ['NUMPARTS COMMAND :','OVERLAP MANAGER :','PICKAPERTURE WIDGET OPTION :','Q :',
				   'RENDER WIDGET OPTION :','SMOOTH COMMAND','TAGS :', 'UNDERLINED ATTRIBUTE :'],
			-texts => ["This command tells how many fieldId are available for event bindings or for field configuration commands in the item specified by tagOrId. If more than one item is named by tagOrId, the topmost in display list order is used to return the result. If no items are named by tagOrId, an error is raised. This command returns always 0 for items which do not support fields. The command hasfields  may be used to decide whether an item has fields.",
				   "his option accepts an item id. It specifies if the label overlapping avoidance algorithm should be allowed to do its work on the track labels and which group should be considered to look for tracks. The default is to enable the avoidance algorithm in the root group (id 1). To disable the algorithm this option should be set to 0.",
				   "Specifies the size of an area around the pointer that is used to tell if the pointer is inside an item. This is useful to lessen the precision required when picking graphical elements. This value must be a positive integer. It defaults to 1.",
				   "No TkZinc KeyWord with Q initial letter...",
				   "Specifies whether to use or not the openGL rendering. When True, requires the GLX extension to the X server. Must be defined at widget creation time. This option is readonly and can be used to ask if the widget is drawing with the GLX extension or in plain X (to adapt the application code for example). The default value is false.",
				   "This command computes a sequence of Bezier segments that will smooth the polygon described by the vertices in coordList and returns a list of lists describing thr points and control points for the generated segments. coordList should be either a flat list of an even number of coordinates in x, y order, or a list of lists of point coordinates X, Y. The returned list can be used to create or change the contour of a curve item.",
				   "Apart from an id, an item can be associated with as many symbolic names as it may be needed by an application. Those names are called tags and can be any string which does not form a valid id (an integer). However the following characters may not be used to form a tag: . * ! ( ) & | :. Tags exists, and may be used in commands, even if no item are associated with them. In contrast an item id doesn't exist if its item is no longer around and thus it is illegal to use it.",
				   "Item Text attribute. If true, a thin line will be drawn under the text characters. The default value is false.",
				  ],
		       },
		'w' => {-numpages => 5,
			-titles => ['V','W','X','Y','Z'],
			-names => ['VERTEXAT COMMAND :','WAYPOINT ITEM :','X11, OpenGL and Windows :','Y...','ZINC an advanced scriptable Canvas :'],
			-texts => ["Return a list of values describing the vertex and edge closest to the window coordinates x and y in the item described by tagOrId. If  tagOrId describes more than one item, the first item in display list order that supports vertex picking is used. The list consists of the index of the contour containing the returned vertices, the index of the closest vertex and the index of a vertex next to the closest vertex that identify the closest edge (located between the two returned vertices).",
				   "Waypoints items have been initially designed for figuring out typical fixed position objects (i.e. beacons or fixes in the ATC vocabulary) with associated block of texts on a radar display for Air Traffic Control. They supports mouse event handling and interactions. However they may certainly be used by other kinds of radar view or even by other kind of plan view with many geographical objects and associated textual information.",
				   "TkZinc was firstly designed for X11 server. Since the 3.2.2 version, TkZinc also offers as a runtime option, the support for openGL rendering, giving access to features such as antialiasing, transparency, color gradients and even a new, openGL oriented, item type : triangles  . In order to use the openGL features, you need the support of the GLX extension on your X11 server. We also succeeded in using TkZinc with openGL on the Exceed X11 server (running on windows and developped by Hummingbird) with the 3D extension. ",
				   "No TkZinc KeyWord with Y initial letter...",
				   "TkZinc widgets are very similar to Tk Canvases in that they support structured graphics. But unlike the Canvas, TkZinc can structure the items in a hierarchy, has support for affine 2D transforms, clipping can be set for sub-trees of the item hierarchy, the item set is quite more powerful including field specific items for Air Traffic systems and new rendering techniques such as transparency and gradients. If needed, it is also possible to extend the item set in an additionnal dynamic library through the use of a C api.",
				  ],
		       },
	       );


# creation de la fenetre principale
my $mw = MainWindow->new();
$mw->geometry("700x560+0+0");
$mw->title('Test Graphics Module');


# creation du widget Zinc
my $zinc = $mw->Zinc(-render => 1,
		     -width => 700,
		     -height => 560,
		     -borderwidth => 0,
		     -lightangle => 140,
		     -borderwidth => 0,
		     -backcolor => '#cccccc',);
$zinc->pack(-fill => 'both', -expand => 1);


# initialise les gradients nommés
&setGradients($zinc, \%gradset);

# création de la vue principale
my $tgroup = $zinc->add('group', 1);
$zinc->coords($tgroup, [350, 240]);

# consigne globale
$zinc->add('text', 1,
	   -position => [50, 470],
	   -text => "Global interations :\n<Up>, <Down>, <Left> and <Right> keys move content of TabBox pages\n<Plus> and <Minus> keys zoom out and zoom in this page\n<Greater> and <Less> keys rotate this page\n<Escape> key reset transfos",
	   -font => $font_9b,
	   -color => '#555555',
	   -spacing => 2,
	   );

# Création des pages d'exemples
my ($shapes, $tcoords) = &tabBoxCoords([[-315, -210],[315, 210]],
				       -numpages => 7,
				       -overlap => 2,
				       -radius => 8,
				       -tabheight => 26,
				       -tabwidth => [92,100,82,82,82,120,80],
				      );

# to find some images (used as textures) needed by this demo
my $texture = $zinc->Photo('paper.gif', -file => Tk->findINC('demos/zinc_data/paper.gif'));

# création des items zinc correspondants
my $i = scalar(@{$shapes}) - 1;
my @pagenames = ('Rectangle', 'Hippodrome', 'Polygone', 'Polyline', 'PathLine', 'MultiContours', 'TabBox');
my @pagegroups;
foreach my $shape (reverse @{$shapes}) {
  my $divgroup = $zinc->add('group', $tgroup);

  # création de l'intercalaire
  my $divider = $zinc->add('curve', $divgroup,
			   $shape,
			   -closed => 1,
			   -priority => 10,
			   -linewidth => 1,
			   -linecolor => '#000000',
			   -filled => 1,
			   -tile => $texture,
			   -tags => ['div1', 'divider', $i, 'intercalaire'],
			  );

  # groupe page clippé
  my $page = $zinc->add('group', $divgroup,
			-priority => 100,
		       -tags => ['div1', $i, 'page'],
		       );
  my $clip = $zinc->add('rectangle', $page,
			[[-300, -170],[300, 195]],
			-linewidth => 1,
			-linecolor => '#000099',
			-filled => 1,
			-fillcolor => '#000000;4',
			);
  $zinc->itemconfigure($page, -clip => $clip);

  my $pgroup = $zinc->add('group', $page,
			  -tags => ['div1', $i, 'content'],
			 );

  push(@pagegroups, $pgroup);

  $tcoords->[$i]->[1] -= 6;

  # titre de l'intercalaire
  $zinc->add('text', $divgroup,
	     -position => $tcoords->[$i],
	     -text => $pagenames[$i],
	     -font => $font_9b,
	     -alignment => 'center',
	     -anchor => 'n',
	     -color => '#000099',
	     -priority => 200,
	     -tags => ['div1', 'divider', $i, 'titre'],
	    );
    $i--;
}

# création du contenu des pages
$i = 0;
foreach my $pagename (reverse @pagenames) {
  my $pagestyle = $pagesconf{$pagename};
  if ($pagestyle) {

    my $pgroup = $pagegroups[$i];
    while (my ($itemname, $itemstyle) = each(%{$pagestyle})) {
      my $group = ($itemname eq 'consigne') ? $zinc->group($pgroup) : $pgroup;
      $itemstyle->{'-name'} = $itemname;
      &buildZincItem($zinc, $group, %{$itemstyle});
    }
  }

  $i++;
}


# initialisation de la TabBox
&clickSelector('sel1','n');
&clickSelector('sel2','left');
&selectDivider('div1', 0);

# initialisation des bindings
&setBindings;


MainLoop;
#----------------------------------------------------------------------- fin de MAIN


sub setBindings {
  # grab keyboard
  $mw->Tk::focus();

  # plus,moins : Zoom++, Zoom--
  $mw->Tk::bind('<plus>', sub {viewZoom('up');});
  $mw->Tk::bind('<minus>', sub {viewZoom('down');});

  # Up, Down, Right, Left : Translate
  $mw->Tk::bind('<KeyPress-Up>', sub {viewTranslate('up');});
  $mw->Tk::bind('<KeyPress-Down>', sub {viewTranslate('down');});
  $mw->Tk::bind('<KeyPress-Left>', sub {viewTranslate('left');});
  $mw->Tk::bind('<KeyPress-Right>', sub {viewTranslate('right');});


  # >, < : Rotate counterclockwise et clockwise
  $mw->Tk::bind('<greater>', sub {viewRotate('cw');});
  $mw->Tk::bind('<less>', sub {viewRotate('ccw');});

  # Escape : reset transfos
  $mw->Tk::bind('<Escape>', sub {$zinc->treset('move');
				 $zinc->raise('move');
				 $zinc->treset($curview);});

  $zinc->bind('divider', '<1>', sub {&selectDivider();});

  $zinc->bind('selector', '<1>', sub {&clickSelector();});

  $zinc->bind('move', '<1>', sub {&mobileStart();});
  $zinc->bind('move', '<B1-Motion>', sub {&mobileMove();});
  $zinc->bind('move', '<ButtonRelease>', sub {&mobileStop();});

  $zinc->bind('pushbtn', '<1>', sub {&pushButton();});
  $zinc->bind('pushbtn', '<ButtonRelease>', sub {&pullButton();});

  $zinc->bind('poly', '<1>', sub {&startRotatePolygone();});
  $zinc->bind('poly', '<B1-Motion>', sub {&rotatePolygone();});
}


#-----------------------------------------------------------------------------------
# Callback sur evt CLICK des items tagés 'divider'
#-----------------------------------------------------------------------------------
sub selectDivider {
  my ($divname, $numpage) = @_;
  if (!defined $divname) {
    my @tags = $zinc->itemcget('current', -tags);
    $divname = $tags[0];
    $numpage = $tags[2];
  }

  $zinc->itemconfigure("($divname && titre)", -color => '#000099');
  $zinc->itemconfigure("($divname && intercalaire)", -linewidth => 1.4);
  $zinc->itemconfigure("($divname && page)", -visible => 0);

  my $divgroup = $zinc->group("($divname && $numpage)");
  $zinc->raise($divgroup);
  $curview = "($divname && $numpage && content)";
  $zinc->itemconfigure("($divname && $numpage && titre)", -color => '#000000');
  $zinc->itemconfigure("($divname && $numpage && intercalaire)", -linewidth => 2);
  $zinc->itemconfigure("($divname && $numpage && page)", -visible => 1);

  if ($divname eq 'div2') {
    my $fontname = $tabtable{$tabanchor}->{'-names'}->[$numpage];
    my $explain = $tabtable{$tabanchor}->{'-texts'}->[$numpage];
    my $text = $fontname."\n\n".$explain;
    $zinc->itemconfigure("($divname && fontname)",
			 -text => $text);
    $zinc->raise("($divname && fontname)");
  }
}


#-----------------------------------------------------------------------------------
# Callback sur evt CLICK des items tagés 'selector'
#-----------------------------------------------------------------------------------
sub clickSelector {
  my ($btngroup, $value) = @_;

  if (!defined $btngroup and !defined $value) {
    my @tags = $zinc->itemcget('current', -tags);
    $btngroup = $tags[0];
    $value = $tags[1];
  }

  $zinc->treset($btngroup);
  $zinc->itemconfigure("($btngroup && btntext)", -color => '#444444');
  $zinc->itemconfigure("($btngroup && $value && btntext)", -color => '#2222bb');
  $zinc->translate("($btngroup && $value)", 0, 1);

  if ($value eq 'n' or $value eq 'e' or $value eq 's' or $value eq 'w') {
    $tabanchor = $value;

  } elsif ($value eq 'left' or $value eq 'center' or $value eq 'right') {
    $tabalign = $value;
  }

  my $tabtable = $tabtable{$tabanchor};
  my $numpages = $tabtable->{'-numpages'};
  my %tabparams = (-radius => 8,
		   -tabwidth => 72,
		   -tabheight => 28,
		   -numpages => $numpages,
		   -anchor => $tabanchor,
		   -alignment => $tabalign,
		   -overlap => 3,
		  );

  my ($shapes, $tcoords) = &tabBoxCoords([[-240, -160], [240, 100]], %tabparams);

  for (my $index = 7; $index >= 0; $index--) {
    my $divgroup = $zinc->group("(div2 && $index && intercalaire)");
    $zinc->itemconfigure($divgroup, -visible => ($index < $numpages));

    if ($index >= $numpages) {
      $zinc->lower($divgroup);

    } else {
      $zinc->raise($divgroup);
      $zinc->itemconfigure("(div2 && $index)", -visible => 1);
      $zinc->coords("(div2 && $index && intercalaire)", $shapes->[$index]);
      if ($zinc->type("(div2 && $index && titre)")) {
	$zinc->coords("(div2 && $index && titre)", $tcoords->[$index]);
	$zinc->itemconfigure("(div2 && $index && titre)", -text => $tabtable->{'-titles'}->[$index]);
      }
    }

  }

  &selectDivider('div2', 0);
}


#-----------------------------------------------------------------------------------
# Callback sur evt CLICK des items tagés 'pushbtn'
#-----------------------------------------------------------------------------------
sub pushButton {
  my $tag = ($zinc->itemcget('current', -tags))[0];
  if (scalar $zinc->find('withtag', $tag) > 1 and
      !$zinc->find('withtag', "($tag && ico)")) {
    $tag = 'current';
  }
  $zinc->scale($tag, .975, .975);
  $zinc->translate($tag, 1, 1);

  if ($zinc->find('withtag', "($tag && ico)")) {
    my $oldcolor = $zinc->itemcget("($tag && ico)", -fillcolor);
    $zinc->itemconfigure('ico', -fillcolor => '#000000');

    my $newcolor = ($oldcolor eq '#000000') ?'#ffff00' : '#000000';
    $zinc->itemconfigure("($tag && ico)", -fillcolor => $newcolor);
  }
}

#-----------------------------------------------------------------------------------
# Callback sur evt RELEASE des items tagés 'pushbtn'
#-----------------------------------------------------------------------------------
sub pullButton {
  my $tag = ($zinc->itemcget('current', -tags))[0];
  $zinc->treset($tag);
}


#-----------------------------------------------------------------------------------
# Callback sur evt CATCH des items tagés 'poly'
# armement de rotation des polygones
#-----------------------------------------------------------------------------------
sub startRotatePolygone {
  my $ev = $zinc->XEvent;
  my ($xref, $yref) = $zinc->transform($zinc->group('current'), 1, [0, 0]);
  $previousangle = &lineAngle([$ev->x, $ev->y], [$xref, $yref]);
}

#-----------------------------------------------------------------------------------
# Callback sur evt MOTION des items tagés 'poly'
# rotation des polygones
#-----------------------------------------------------------------------------------
sub rotatePolygone {
  my $tag = ($zinc->itemcget('current', -tags))[0];
  my $ev = $zinc->XEvent;
  my ($xref, $yref) = $zinc->transform($zinc->group('current'), 1, [0, 0]);
  my $newangle = &lineAngle([$ev->x, $ev->y], [$xref, $yref]);

  $zinc->rotate($tag, deg2rad($newangle - $previousangle));
  $previousangle = $newangle;
}

#-----------------------------------------------------------------------------------
# Callback CATCH de sélection (début de déplacement) des items tagés 'move'
#-----------------------------------------------------------------------------------
sub mobileStart {
  my $ev = $zinc->XEvent;
  ($dx, $dy) = (0 - $ev->x, 0 - $ev->y);

  $zinc->raise('current');

}


#-----------------------------------------------------------------------------------
# Callback MOVE de déplacement des items tagés 'move'
#-----------------------------------------------------------------------------------
sub mobileMove {
    my $ev = $zinc->XEvent;
    $zinc->translate('current', $ev->x + $dx, $ev->y +$dy);
    ($dx, $dy) = (0 - $ev->x, 0 - $ev->y);

}


#-----------------------------------------------------------------------------------
# Callback RELEASE de relaché (fin de déplacement) des items tagés 'move'
#-----------------------------------------------------------------------------------
sub mobileStop {
  &mobileMove;
}


#-----------------------------------------------------------------------------------
# Callback sur evénément Tk <KeyPress> flèche gauche, haut, droite, bas
# pan (translation) du contenu de la page active (TabBox)
#-----------------------------------------------------------------------------------
sub viewTranslate {
  my $way = shift;

  my $dx = ($way eq 'left') ? -10 : ($way eq 'right') ? 10 : 0;
  my $dy = ($way eq 'up') ? -10 : ($way eq 'down') ? 10 : 0;

  $zinc->translate($curview, $dx, $dy);

}

#-----------------------------------------------------------------------------------
# Callback sur evénément Tk <KeyPress> "+" ou "-"
# zoom du contenu de la page active (TabBox)
#-----------------------------------------------------------------------------------
sub viewZoom {
  my $key = shift;
  my $scaleratio = ($key eq 'up') ? 1+$zoomfactor : 1-$zoomfactor;

  $zinc->scale($curview, $scaleratio, $scaleratio);

}


#-----------------------------------------------------------------------------------
# Callback sur evénément Tk <KeyPress> ">" ou "<"
# rotation du contenu de la page active (TabBox)
#-----------------------------------------------------------------------------------
sub viewRotate {
  my $way = shift;
  my $delta_angle = $rotate_angle;

  $delta_angle *= -1 if ($way eq 'cw');

  $zinc->rotate($curview, $delta_angle);

}



1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/textInput.pl.





































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

package textInput; # for avoiding symbol re-use between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


use Tk;
use Tk::Zinc;
use strict;

use Tk::Zinc::Text;  # the module for facilitating text input with zinc

my $mw = MainWindow->new();

###########################################
# Text zone
###########################################

my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2, -height => 4);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
'This toy-appli demonstrates the use of the
Tk::Zinc::Text module. This module is designed for
facilitating text input "a la emacs" on text items or on
fields of items such as tracks, waypoints or tabulars.');


###########################################
# Zinc
##########################################
my $zinc = $mw->Zinc(-width => 500, -height => 300,
		     -font => "10x20",
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

Tk::Zinc::Text->new ($zinc);  # for mapping text input bindings on item with a 'text' tag.


### creating a tabular with 3 fields, 2 of them being editable
my $labelformat1 = "130x100 x130x20+0+0 x130x20+0+20 x130x20+0+40";

my $x=120;
my $y=6;
my $track = $zinc->add('track',1, 3,
		       -position => [$x,$y],
		       -speedvector => [40, 10],
		       -labeldistance => 30,
		       -labelformat => $labelformat1,
		       -tags => 'text',
		       );
# moving the track, to display past positions
foreach my $i (0..5) {  $zinc->coords("$track",[$x+$i*10,$y+$i*2]); }

$zinc->itemconfigure($track, 0,
		     -border => "contour",
		     -text => "not editable",
		     -sensitive => 0,
		     );
$zinc->itemconfigure($track, 1,
		     -border => "contour",
		     -text => "editable",
		     -sensitive => 1,
		     );
$zinc->itemconfigure($track, 2,
		     -border => "contour",
		     -text => "editable too",
		     -alignment => "center",
		     -sensitive => 1,
		     );

# creating a text item, tagged with 'text', but not editable because
# it is not sensitive
$zinc->add('text', 1,
	   -position => [220,160],
	   -text => "this text is not
editable because it is
not sensitive",
	   -sensitive => 0,
	   -tags => ['text'],
	   );

# creating an editable text item
$zinc->add('text', 1,
	   -position => [50,230],
	   -text => "this text IS
editable",
	   -sensitive => 1,
	   -tags => ['text'],
	   );



Tk::MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/tiger.pl.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
#!/usr/bin/perl -w

# $Id$
# This simple demo has been developped by C. Mertz <mertz@intuilab.com>
 
####### This file has been initially generated from tiger.svg by SVG2zinc.pm Version: Revision: 1.10 
### the idea of using the shape extension (as possible with TkZinc 
### under linux) was from Daniel Etienne! Thx!

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


use Tk::Zinc;
use Tk::Zinc::Debug;

my $mw = MainWindow->new();
$mw->title('tiger generated from svg file');

my ($WIDTH,$HEIGHT) = (600,600);
my $zinc = $mw->Zinc(-width => $WIDTH, -height => $HEIGHT,
		     -borderwidth => 0,
                     -backcolor => "grey90",
		     -render => 1,
                     -reshape => 1,
                     -fullreshape => 1,
		      )->pack;


&Tk::Zinc::Debug::init($zinc, 
                       -optionsToDisplay => '-tags', 
                       -optionsFormat => 'row',
                      );

my $top_group = $zinc->add('group', 1);

$text = "
Drag-Button 1 for moving the tiger,
Drag-Button 2 for zooming the tiger,
Drag-Button 3 for rotating the tiger,
esc for getting help on Tk::Zinc::Debug functions.
";

my $clip= $zinc->add('curve',1,
                     [ [0,150], [150,0], [470,20], [580, 200], [600,300], [500,560], [50,550], [10,450] ],
                     -closed => 1, -visible => 0);

$zinc->itemconfigure(1, -clip => $clip);

$zinc->add('text', 1, -position => [51,521], -anchor => 'w',
	   -priority => 20, -text => $text, -color => "white");
$zinc->add('text', 1, -position => [50,520], -anchor => 'w',
	   -priority => 20, -text => $text, -color => "black");

$zinc->add('curve',$top_group,[[122.304, 84.285], [-122.304, 84.285, 'c'], [-122.203, 86.179, 'c'], [-123.027, 86.16], [-123.851, 86.141, 'c'], [-140.305, 38.066, 'c'], [-160.833, 40.309], [-160.833, 40.309, 'c'], [-143.05, 32.956, 'c'], [-122.304, 84.285]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[118.774, 81.262], [-118.774, 81.262, 'c'], [-119.323, 83.078, 'c'], [-120.092, 82.779], [-120.86, 82.481, 'c'], [-119.977, 31.675, 'c'], [-140.043, 26.801], [-140.043, 26.801, 'c'], [-120.82, 25.937, 'c'], [-118.774, 81.262]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[91.284, 123.59], [-91.284, 123.59, 'c'], [-89.648, 124.55, 'c'], [-90.118, 125.227], [-90.589, 125.904, 'c'], [-139.763, 113.102, 'c'], [-149.218, 131.459], [-149.218, 131.459, 'c'], [-145.539, 112.572, 'c'], [-91.284, 123.59]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[94.093, 133.801], [-94.093, 133.801, 'c'], [-92.237, 134.197, 'c'], [-92.471, 134.988], [-92.704, 135.779, 'c'], [-143.407, 139.121, 'c'], [-146.597, 159.522], [-146.597, 159.522, 'c'], [-149.055, 140.437, 'c'], [-94.093, 133.801]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[98.304, 128.276], [-98.304, 128.276, 'c'], [-96.526, 128.939, 'c'], [-96.872, 129.687], [-97.218, 130.435, 'c'], [-147.866, 126.346, 'c'], [-153.998, 146.064], [-153.998, 146.064, 'c'], [-153.646, 126.825, 'c'], [-98.304, 128.276]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[109.009, 110.072], [-109.009, 110.072, 'c'], [-107.701, 111.446, 'c'], [-108.34, 111.967], [-108.979, 112.488, 'c'], [-152.722, 86.634, 'c'], [-166.869, 101.676], [-166.869, 101.676, 'c'], [-158.128, 84.533, 'c'], [-109.009, 110.072]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[116.554, 114.263], [-116.554, 114.263, 'c'], [-115.098, 115.48, 'c'], [-115.674, 116.071], [-116.25, 116.661, 'c'], [-162.638, 95.922, 'c'], [-174.992, 112.469], [-174.992, 112.469, 'c'], [-168.247, 94.447, 'c'], [-116.554, 114.263]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[119.154, 118.335], [-119.154, 118.335, 'c'], [-117.546, 119.343, 'c'], [-118.036, 120.006], [-118.526, 120.669, 'c'], [-167.308, 106.446, 'c'], [-177.291, 124.522], [-177.291, 124.522, 'c'], [-173.066, 105.749, 'c'], [-119.154, 118.335]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[108.42, 118.949], [-108.42, 118.949, 'c'], [-107.298, 120.48, 'c'], [-107.999, 120.915], [-108.7, 121.35, 'c'], [-148.769, 90.102, 'c'], [-164.727, 103.207], [-164.727, 103.207, 'c'], [-153.862, 87.326, 'c'], [-108.42, 118.949]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[128.2, 90], [-128.2, 90, 'c'], [-127.6, 91.8, 'c'], [-128.4, 92], [-129.2, 92.2, 'c'], [-157.8, 50.2, 'c'], [-177.001, 57.8], [-177.001, 57.8, 'c'], [-161.8, 46, 'c'], [-128.2, 90]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[127.505, 96.979], [-127.505, 96.979, 'c'], [-126.53, 98.608, 'c'], [-127.269, 98.975], [-128.007, 99.343, 'c'], [-164.992, 64.499, 'c'], [-182.101, 76.061], [-182.101, 76.061, 'c'], [-169.804, 61.261, 'c'], [-127.505, 96.979]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[127.62, 101.349], [-127.62, 101.349, 'c'], [-126.498, 102.88, 'c'], [-127.199, 103.315], [-127.9, 103.749, 'c'], [-167.969, 72.502, 'c'], [-183.927, 85.607], [-183.927, 85.607, 'c'], [-173.062, 69.726, 'c'], [-127.62, 101.349]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.172);
$zinc->add('curve',$top_group,[[129.83, 103.065], [-129.327, 109.113, 'c'], [-128.339, 115.682, 'c'], [-126.6, 118.801], [-126.6, 118.801, 'c'], [-130.2, 131.201, 'c'], [-121.4, 144.401], [-121.4, 144.401, 'c'], [-121.8, 151.601, 'c'], [-120.2, 154.801], [-120.2, 154.801, 'c'], [-116.2, 163.201, 'c'], [-111.4, 164.001], [-107.516, 164.648, 'c'], [-98.793, 167.717, 'c'], [-88.932, 169.121], [-88.932, 169.121, 'c'], [-71.8, 183.201, 'c'], [-75, 196.001], [-75, 196.001, 'c'], [-75.4, 212.401, 'c'], [-79, 214.001], [-79, 214.001, 'c'], [-67.4, 202.801, 'c'], [-77, 219.601], [-81.4, 238.401], [-81.4, 238.401, 'c'], [-55.8, 216.801, 'c'], [-71.4, 235.201], [-81.4, 261.201], [-81.4, 261.201, 'c'], [-61.8, 242.801, 'c'], [-69, 251.201], [-72.2, 260.001], [-72.2, 260.001, 'c'], [-29, 232.801, 'c'], [-59.8, 262.401], [-59.8, 262.401, 'c'], [-51.8, 258.801, 'c'], [-47.4, 261.601], [-47.4, 261.601, 'c'], [-40.6, 260.401, 'c'], [-41.4, 262.001], [-41.4, 262.001, 'c'], [-62.2, 272.401, 'c'], [-65.8, 290.801], [-65.8, 290.801, 'c'], [-57.4, 280.801, 'c'], [-60.6, 291.601], [-60.2, 303.201], [-60.2, 303.201, 'c'], [-56.2, 281.601, 'c'], [-56.6, 319.201], [-56.6, 319.201, 'c'], [-37.4, 301.201, 'c'], [-49, 322.001], [-49, 338.801], [-49, 338.801, 'c'], [-33.8, 322.401, 'c'], [-40.2, 335.201], [-40.2, 335.201, 'c'], [-30.2, 326.401, 'c'], [-34.2, 341.601], [-34.2, 341.601, 'c'], [-35, 352.001, 'c'], [-30.6, 340.801], [-30.6, 340.801, 'c'], [-14.6, 310.201, 'c'], [-20.6, 336.401], [-20.6, 336.401, 'c'], [-21.4, 355.601, 'c'], [-16.6, 340.801], [-16.6, 340.801, 'c'], [-16.2, 351.201, 'c'], [-7, 358.401], [-7, 358.401, 'c'], [-8.2, 307.601, 'c'], [4.6, 343.601], [8.6, 360.001], [8.6, 360.001, 'c'], [11.4, 350.801, 'c'], [11, 345.601], [11, 345.601, 'c'], [25.8, 329.201, 'c'], [19, 353.601], [19, 353.601, 'c'], [34.2, 330.801, 'c'], [31, 344.001], [31, 344.001, 'c'], [23.4, 360.001, 'c'], [25, 364.801], [25, 364.801, 'c'], [41.8, 330.001, 'c'], [43, 328.401], [43, 328.401, 'c'], [41, 370.802, 'c'], [51.8, 334.801], [51.8, 334.801, 'c'], [57.4, 346.801, 'c'], [54.6, 351.201], [54.6, 351.201, 'c'], [62.6, 343.201, 'c'], [61.8, 340.001], [61.8, 340.001, 'c'], [66.4, 331.801, 'c'], [69.2, 345.401], [69.2, 345.401, 'c'], [71, 354.801, 'c'], [72.6, 351.601], [72.6, 351.601, 'c'], [76.6, 375.602, 'c'], [77.8, 352.801], [77.8, 352.801, 'c'], [79.4, 339.201, 'c'], [72.2, 327.601], [72.2, 327.601, 'c'], [73, 324.401, 'c'], [70.2, 320.401], [70.2, 320.401, 'c'], [83.8, 342.001, 'c'], [76.6, 313.201], [76.6, 313.201, 'c'], [87.801, 321.201, 'c'], [89.001, 321.201], [89.001, 321.201, 'c'], [75.4, 298.001, 'c'], [84.2, 302.801], [84.2, 302.801, 'c'], [79, 292.401, 'c'], [97.001, 304.401], [97.001, 304.401, 'c'], [81, 288.401, 'c'], [98.601, 298.001], [98.601, 298.001, 'c'], [106.601, 304.401, 'c'], [99.001, 294.401], [99.001, 294.401, 'c'], [84.6, 278.401, 'c'], [106.601, 296.401], [106.601, 296.401, 'c'], [118.201, 312.801, 'c'], [119.001, 315.601], [119.001, 315.601, 'c'], [109.001, 286.401, 'c'], [104.601, 283.601], [104.601, 283.601, 'c'], [113.001, 247.201, 'c'], [154.201, 262.801], [154.201, 262.801, 'c'], [161.001, 280.001, 'c'], [165.401, 261.601], [165.401, 261.601, 'c'], [178.201, 255.201, 'c'], [189.401, 282.801], [189.401, 282.801, 'c'], [193.401, 269.201, 'c'], [192.601, 266.401], [192.601, 266.401, 'c'], [199.401, 267.601, 'c'], [198.601, 266.401], [198.601, 266.401, 'c'], [211.801, 270.801, 'c'], [213.001, 270.001], [213.001, 270.001, 'c'], [219.801, 276.801, 'c'], [220.201, 273.201], [220.201, 273.201, 'c'], [229.401, 276.001, 'c'], [227.401, 272.401], [227.401, 272.401, 'c'], [236.201, 288.001, 'c'], [236.601, 291.601], [239.001, 277.601], [241.001, 280.401], [241.001, 280.401, 'c'], [242.601, 272.801, 'c'], [241.801, 271.601], [241.001, 270.401, 'c'], [261.801, 278.401, 'c'], [266.601, 299.201], [268.601, 307.601], [268.601, 307.601, 'c'], [274.601, 292.801, 'c'], [273.001, 288.801], [273.001, 288.801, 'c'], [278.201, 289.601, 'c'], [278.601, 294.001], [278.601, 294.001, 'c'], [282.601, 270.801, 'c'], [277.801, 264.801], [277.801, 264.801, 'c'], [282.201, 264.001, 'c'], [283.401, 267.601], [283.401, 260.401], [283.401, 260.401, 'c'], [290.601, 261.201, 'c'], [290.601, 258.801], [290.601, 258.801, 'c'], [295.001, 254.801, 'c'], [297.001, 259.601], [297.001, 259.601, 'c'], [284.601, 224.401, 'c'], [303.001, 243.601], [303.001, 243.601, 'c'], [310.201, 254.401, 'c'], [306.601, 235.601], [303.001, 216.801, 'c'], [299.001, 215.201, 'c'], [303.801, 214.801], [303.801, 214.801, 'c'], [304.601, 211.201, 'c'], [302.601, 209.601], [300.601, 208.001, 'c'], [303.801, 209.601, 'c'], [303.801, 209.601], [303.801, 209.601, 'c'], [308.601, 213.601, 'c'], [303.401, 191.601], [303.401, 191.601, 'c'], [309.801, 193.201, 'c'], [297.801, 164.001], [297.801, 164.001, 'c'], [300.601, 161.601, 'c'], [296.601, 153.201], [296.601, 153.201, 'c'], [304.601, 157.601, 'c'], [307.401, 156.001], [307.401, 156.001, 'c'], [307.001, 154.401, 'c'], [303.801, 150.401], [303.801, 150.401, 'c'], [282.201, 95.6, 'c'], [302.601, 117.601], [302.601, 117.601, 'c'], [314.451, 131.151, 'c'], [308.051, 108.351], [308.051, 108.351, 'c'], [298.94, 84.341, 'c'], [299.717, 80.045], [-129.83, 103.065]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1);
$zinc->add('curve',$top_group,[[299.717, 80.245], [300.345, 80.426, 'c'], [302.551, 81.55, 'c'], [303.801, 83.2], [303.801, 83.2, 'c'], [310.601, 94, 'c'], [305.401, 75.6], [305.401, 75.6, 'c'], [296.201, 46.8, 'c'], [305.001, 58], [305.001, 58, 'c'], [311.001, 65.2, 'c'], [307.801, 51.6], [303.936, 35.173, 'c'], [301.401, 28.8, 'c'], [301.401, 28.8], [301.401, 28.8, 'c'], [313.001, 33.6, 'c'], [286.201, -6], [295.001, -2.4], [295.001, -2.4, 'c'], [275.401, -42, 'c'], [253.801, -47.2], [245.801, -53.2], [245.801, -53.2, 'c'], [284.201, -91.2, 'c'], [271.401, -128], [271.401, -128, 'c'], [264.601, -133.2, 'c'], [255.001, -124], [255.001, -124, 'c'], [248.601, -119.2, 'c'], [242.601, -120.8], [242.601, -120.8, 'c'], [211.801, -119.6, 'c'], [209.801, -119.6], [207.801, -119.6, 'c'], [173.001, -156.8, 'c'], [107.401, -139.2], [107.401, -139.2, 'c'], [102.201, -137.2, 'c'], [97.801, -138.4], [97.801, -138.4, 'c'], [79.4, -154.4, 'c'], [30.6, -131.6], [30.6, -131.6, 'c'], [20.6, -129.6, 'c'], [19, -129.6], [17.4, -129.6, 'c'], [14.6, -129.6, 'c'], [6.6, -123.2], [-1.4, -116.8, 'c'], [-1.8, -116, 'c'], [-3.8, -114.4], [-3.8, -114.4, 'c'], [-20.2, -103.2, 'c'], [-25, -102.4], [-25, -102.4, 'c'], [-36.6, -96, 'c'], [-41, -86], [-44.6, -84.8], [-44.6, -84.8, 'c'], [-46.2, -77.6, 'c'], [-46.6, -76.4], [-46.6, -76.4, 'c'], [-51.4, -72.8, 'c'], [-52.2, -67.2], [-52.2, -67.2, 'c'], [-61, -61.2, 'c'], [-60.6, -56.8], [-60.6, -56.8, 'c'], [-62.2, -51.6, 'c'], [-63, -46.8], [-63, -46.8, 'c'], [-70.2, -42, 'c'], [-69.4, -39.2], [-69.4, -39.2, 'c'], [-77, -25.2, 'c'], [-75.8, -18.4], [-75.8, -18.4, 'c'], [-82.2, -18.8, 'c'], [-85, -16.4], [-85, -16.4, 'c'], [-85.8, -11.6, 'c'], [-87.4, -11.2], [-87.4, -11.2, 'c'], [-90.2, -10, 'c'], [-87.8, -6], [-87.8, -6, 'c'], [-89.4, -3.2, 'c'], [-89.8, -1.6], [-89.8, -1.6, 'c'], [-89, 1.2, 'c'], [-93.4, 6.8], [-93.4, 6.8, 'c'], [-99.8, 25.6, 'c'], [-97.8, 30.8], [-97.8, 30.8, 'c'], [-97.4, 35.6, 'c'], [-100.2, 37.2], [-100.2, 37.2, 'c'], [-103.8, 36.8, 'c'], [-95.4, 48.8], [-95.4, 48.8, 'c'], [-94.6, 50, 'c'], [-97.8, 52.4], [-97.8, 52.4, 'c'], [-115, 56, 'c'], [-117.4, 72.4], [-117.4, 72.4, 'c'], [-131, 87.2, 'c'], [-131, 92.4], [-131, 94.705, 'c'], [-130.729, 97.852, 'c'], [-130.03, 102.465], [-130.03, 102.465, 'c'], [-130.6, 110.801, 'c'], [-103, 111.601], [-75.4, 112.401, 'c'], [299.717, 80.245, 'c'], [299.717, 80.245]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#cc7226", -filled => 1);

$zinc->add('curve',$top_group,[[115.6, 102.6], [-140.6, 63.2, 'c'], [-126.2, 119.601, 'c'], [-126.2, 119.601], [-117.4, 154.001, 'c'], [12.2, 116.401, 'c'], [12.2, 116.401], [12.2, 116.401, 'c'], [181.001, 86, 'c'], [192.201, 82], [203.401, 78, 'c'], [298.601, 84.4, 'c'], [298.601, 84.4], [293.001, 67.6], [228.201, 21.2, 'c'], [209.001, 44.4, 'c'], [195.401, 40.4], [181.801, 36.4, 'c'], [184.201, 46, 'c'], [181.001, 46.8], [177.801, 47.6, 'c'], [138.601, 22.8, 'c'], [132.201, 23.6], [125.801, 24.4, 'c'], [100.459, 0.649, 'c'], [115.401, 32.4], [131.401, 66.4, 'c'], [57, 71.6, 'c'], [40.2, 60.4], [23.4, 49.2, 'c'], [47.4, 78.8, 'c'], [47.4, 78.8], [65.8, 98.8, 'c'], [31.4, 82, 'c'], [31.4, 82], [-3, 69.2, 'c'], [-27, 94.8, 'c'], [-30.2, 95.6], [-33.4, 96.4, 'c'], [-38.2, 99.6, 'c'], [-39, 93.2], [-39.8, 86.8, 'c'], [-47.31, 70.099, 'c'], [-79, 96.4], [-99, 113.001, 'c'], [-112.8, 91, 'c'], [-112.8, 91], [-115.6, 102.6]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");
$zinc->add('curve',$top_group,[[133.51, 25.346], [127.11, 26.146, 'c'], [101.743, 2.407, 'c'], [116.71, 34.146], [133.31, 69.346, 'c'], [58.31, 73.346, 'c'], [41.51, 62.146], [24.709, 50.946, 'c'], [48.71, 80.546, 'c'], [48.71, 80.546], [67.11, 100.546, 'c'], [32.709, 83.746, 'c'], [32.709, 83.746], [-1.691, 70.946, 'c'], [-25.691, 96.546, 'c'], [-28.891, 97.346], [-32.091, 98.146, 'c'], [-36.891, 101.346, 'c'], [-37.691, 94.946], [-38.491, 88.546, 'c'], [-45.87, 72.012, 'c'], [-77.691, 98.146], [-98.927, 115.492, 'c'], [-112.418, 94.037, 'c'], [-112.418, 94.037], [-115.618, 104.146], [-140.618, 64.346, 'c'], [-125.546, 122.655, 'c'], [-125.546, 122.655], [-116.745, 157.056, 'c'], [13.509, 118.146, 'c'], [13.509, 118.146], [13.509, 118.146, 'c'], [182.31, 87.746, 'c'], [193.51, 83.746], [204.71, 79.746, 'c'], [299.038, 86.073, 'c'], [299.038, 86.073], [293.51, 68.764], [228.71, 22.364, 'c'], [210.31, 46.146, 'c'], [196.71, 42.146], [183.11, 38.146, 'c'], [185.51, 47.746, 'c'], [182.31, 48.546], [179.11, 49.346, 'c'], [139.91, 24.546, 'c'], [133.51, 25.346]],  -closed => 1, -fillcolor => "#e87f3a", -filled => 1, -linecolor => "#e87f3a");
$zinc->add('curve',$top_group,[[134.819, 27.091], [128.419, 27.891, 'c'], [103.685, 3.862, 'c'], [118.019, 35.891], [134.219, 72.092, 'c'], [59.619, 75.092, 'c'], [42.819, 63.892], [26.019, 52.692, 'c'], [50.019, 82.292, 'c'], [50.019, 82.292], [68.419, 102.292, 'c'], [34.019, 85.492, 'c'], [34.019, 85.492], [-0.381, 72.692, 'c'], [-24.382, 98.292, 'c'], [-27.582, 99.092], [-30.782, 99.892, 'c'], [-35.582, 103.092, 'c'], [-36.382, 96.692], [-37.182, 90.292, 'c'], [-44.43, 73.925, 'c'], [-76.382, 99.892], [-98.855, 117.983, 'c'], [-112.036, 97.074, 'c'], [-112.036, 97.074], [-115.636, 105.692], [-139.436, 66.692, 'c'], [-124.891, 125.71, 'c'], [-124.891, 125.71], [-116.091, 160.11, 'c'], [14.819, 119.892, 'c'], [14.819, 119.892], [14.819, 119.892, 'c'], [183.619, 89.492, 'c'], [194.819, 85.492], [206.019, 81.492, 'c'], [299.474, 87.746, 'c'], [299.474, 87.746], [294.02, 69.928], [229.219, 23.528, 'c'], [211.619, 47.891, 'c'], [198.019, 43.891], [184.419, 39.891, 'c'], [186.819, 49.491, 'c'], [183.619, 50.292], [180.419, 51.092, 'c'], [141.219, 26.291, 'c'], [134.819, 27.091]],  -closed => 1, -fillcolor => "#ea8c4d", -filled => 1, -linecolor => "#ea8c4d");
$zinc->add('curve',$top_group,[[136.128, 28.837], [129.728, 29.637, 'c'], [104.999, 5.605, 'c'], [119.328, 37.637], [136.128, 75.193, 'c'], [60.394, 76.482, 'c'], [44.128, 65.637], [27.328, 54.437, 'c'], [51.328, 84.037, 'c'], [51.328, 84.037], [69.728, 104.037, 'c'], [35.328, 87.237, 'c'], [35.328, 87.237], [0.928, 74.437, 'c'], [-23.072, 100.037, 'c'], [-26.272, 100.837], [-29.472, 101.637, 'c'], [-34.272, 104.837, 'c'], [-35.072, 98.437], [-35.872, 92.037, 'c'], [-42.989, 75.839, 'c'], [-75.073, 101.637], [-98.782, 120.474, 'c'], [-111.655, 100.11, 'c'], [-111.655, 100.11], [-115.655, 107.237], [-137.455, 70.437, 'c'], [-124.236, 128.765, 'c'], [-124.236, 128.765], [-115.436, 163.165, 'c'], [16.128, 121.637, 'c'], [16.128, 121.637], [16.128, 121.637, 'c'], [184.928, 91.237, 'c'], [196.129, 87.237], [207.329, 83.237, 'c'], [299.911, 89.419, 'c'], [299.911, 89.419], [294.529, 71.092], [229.729, 24.691, 'c'], [212.929, 49.637, 'c'], [199.329, 45.637], [185.728, 41.637, 'c'], [188.128, 51.237, 'c'], [184.928, 52.037], [181.728, 52.837, 'c'], [142.528, 28.037, 'c'], [136.128, 28.837]],  -closed => 1, -fillcolor => "#ec9961", -filled => 1, -linecolor => "#ec9961");
$zinc->add('curve',$top_group,[[137.438, 30.583], [131.037, 31.383, 'c'], [106.814, 7.129, 'c'], [120.637, 39.383], [137.438, 78.583, 'c'], [62.237, 78.583, 'c'], [45.437, 67.383], [28.637, 56.183, 'c'], [52.637, 85.783, 'c'], [52.637, 85.783], [71.037, 105.783, 'c'], [36.637, 88.983, 'c'], [36.637, 88.983], [2.237, 76.183, 'c'], [-21.763, 101.783, 'c'], [-24.963, 102.583], [-28.163, 103.383, 'c'], [-32.963, 106.583, 'c'], [-33.763, 100.183], [-34.563, 93.783, 'c'], [-41.548, 77.752, 'c'], [-73.763, 103.383], [-98.709, 122.965, 'c'], [-111.273, 103.146, 'c'], [-111.273, 103.146], [-115.673, 108.783], [-135.473, 73.982, 'c'], [-123.582, 131.819, 'c'], [-123.582, 131.819], [-114.782, 166.22, 'c'], [17.437, 123.383, 'c'], [17.437, 123.383], [17.437, 123.383, 'c'], [186.238, 92.983, 'c'], [197.438, 88.983], [208.638, 84.983, 'c'], [300.347, 91.092, 'c'], [300.347, 91.092], [295.038, 72.255], [230.238, 25.855, 'c'], [214.238, 51.383, 'c'], [200.638, 47.383], [187.038, 43.383, 'c'], [189.438, 52.983, 'c'], [186.238, 53.783], [183.038, 54.583, 'c'], [143.838, 29.783, 'c'], [137.438, 30.583]],  -closed => 1, -fillcolor => "#eea575", -filled => 1, -linecolor => "#eea575");
$zinc->add('curve',$top_group,[[138.747, 32.328], [132.347, 33.128, 'c'], [106.383, 9.677, 'c'], [121.947, 41.128], [141.147, 79.928, 'c'], [63.546, 80.328, 'c'], [46.746, 69.128], [29.946, 57.928, 'c'], [53.946, 87.528, 'c'], [53.946, 87.528], [72.346, 107.528, 'c'], [37.946, 90.728, 'c'], [37.946, 90.728], [3.546, 77.928, 'c'], [-20.454, 103.528, 'c'], [-23.654, 104.328], [-26.854, 105.128, 'c'], [-31.654, 108.328, 'c'], [-32.454, 101.928], [-33.254, 95.528, 'c'], [-40.108, 79.665, 'c'], [-72.454, 105.128], [-98.636, 125.456, 'c'], [-110.891, 106.183, 'c'], [-110.891, 106.183], [-115.691, 110.328], [-133.691, 77.128, 'c'], [-122.927, 134.874, 'c'], [-122.927, 134.874], [-114.127, 169.274, 'c'], [18.746, 125.128, 'c'], [18.746, 125.128], [18.746, 125.128, 'c'], [187.547, 94.728, 'c'], [198.747, 90.728], [209.947, 86.728, 'c'], [300.783, 92.764, 'c'], [300.783, 92.764], [295.547, 73.419], [230.747, 27.019, 'c'], [215.547, 53.128, 'c'], [201.947, 49.128], [188.347, 45.128, 'c'], [190.747, 54.728, 'c'], [187.547, 55.528], [184.347, 56.328, 'c'], [145.147, 31.528, 'c'], [138.747, 32.328]],  -closed => 1, -fillcolor => "#f1b288", -filled => 1, -linecolor => "#f1b288");
$zinc->add('curve',$top_group,[[140.056, 34.073], [133.655, 34.873, 'c'], [107.313, 11.613, 'c'], [123.255, 42.873], [143.656, 82.874, 'c'], [64.855, 82.074, 'c'], [48.055, 70.874], [31.255, 59.674, 'c'], [55.255, 89.274, 'c'], [55.255, 89.274], [73.655, 109.274, 'c'], [39.255, 92.474, 'c'], [39.255, 92.474], [4.855, 79.674, 'c'], [-19.145, 105.274, 'c'], [-22.345, 106.074], [-25.545, 106.874, 'c'], [-30.345, 110.074, 'c'], [-31.145, 103.674], [-31.945, 97.274, 'c'], [-38.668, 81.578, 'c'], [-71.145, 106.874], [-98.564, 127.947, 'c'], [-110.509, 109.219, 'c'], [-110.509, 109.219], [-115.709, 111.874], [-131.709, 81.674, 'c'], [-122.273, 137.929, 'c'], [-122.273, 137.929], [-113.473, 172.329, 'c'], [20.055, 126.874, 'c'], [20.055, 126.874], [20.055, 126.874, 'c'], [188.856, 96.474, 'c'], [200.056, 92.474], [211.256, 88.474, 'c'], [301.22, 94.437, 'c'], [301.22, 94.437], [296.056, 74.583], [231.256, 28.183, 'c'], [216.856, 54.874, 'c'], [203.256, 50.874], [189.656, 46.873, 'c'], [192.056, 56.474, 'c'], [188.856, 57.274], [185.656, 58.074, 'c'], [146.456, 33.273, 'c'], [140.056, 34.073]],  -closed => 1, -fillcolor => "#f3bf9c", -filled => 1, -linecolor => "#f3bf9c");
$zinc->add('curve',$top_group,[[141.365, 35.819], [134.965, 36.619, 'c'], [107.523, 13.944, 'c'], [124.565, 44.619], [146.565, 84.219, 'c'], [66.164, 83.819, 'c'], [49.364, 72.619], [32.564, 61.419, 'c'], [56.564, 91.019, 'c'], [56.564, 91.019], [74.964, 111.019, 'c'], [40.564, 94.219, 'c'], [40.564, 94.219], [6.164, 81.419, 'c'], [-17.836, 107.019, 'c'], [-21.036, 107.819], [-24.236, 108.619, 'c'], [-29.036, 111.819, 'c'], [-29.836, 105.419], [-30.636, 99.019, 'c'], [-37.227, 83.492, 'c'], [-69.836, 108.619], [-98.491, 130.438, 'c'], [-110.127, 112.256, 'c'], [-110.127, 112.256], [-115.727, 113.419], [-130.128, 85.019, 'c'], [-121.618, 140.983, 'c'], [-121.618, 140.983], [-112.818, 175.384, 'c'], [21.364, 128.619, 'c'], [21.364, 128.619], [21.364, 128.619, 'c'], [190.165, 98.219, 'c'], [201.365, 94.219], [212.565, 90.219, 'c'], [301.656, 96.11, 'c'], [301.656, 96.11], [296.565, 75.746], [231.765, 29.346, 'c'], [218.165, 56.619, 'c'], [204.565, 52.619], [190.965, 48.619, 'c'], [193.365, 58.219, 'c'], [190.165, 59.019], [186.965, 59.819, 'c'], [147.765, 35.019, 'c'], [141.365, 35.819]],  -closed => 1, -fillcolor => "#f5ccb0", -filled => 1, -linecolor => "#f5ccb0");
$zinc->add('curve',$top_group,[[142.674, 37.565], [136.274, 38.365, 'c'], [108.832, 15.689, 'c'], [125.874, 46.365], [147.874, 85.965, 'c'], [67.474, 85.565, 'c'], [50.674, 74.365], [33.874, 63.165, 'c'], [57.874, 92.765, 'c'], [57.874, 92.765], [76.274, 112.765, 'c'], [41.874, 95.965, 'c'], [41.874, 95.965], [7.473, 83.165, 'c'], [-16.527, 108.765, 'c'], [-19.727, 109.565], [-22.927, 110.365, 'c'], [-27.727, 113.565, 'c'], [-28.527, 107.165], [-29.327, 100.765, 'c'], [-35.786, 85.405, 'c'], [-68.527, 110.365], [-98.418, 132.929, 'c'], [-109.745, 115.293, 'c'], [-109.745, 115.293], [-115.745, 114.965], [-129.346, 88.564, 'c'], [-120.963, 144.038, 'c'], [-120.963, 144.038], [-112.163, 178.438, 'c'], [22.673, 130.365, 'c'], [22.673, 130.365], [22.673, 130.365, 'c'], [191.474, 99.965, 'c'], [202.674, 95.965], [213.874, 91.965, 'c'], [302.093, 97.783, 'c'], [302.093, 97.783], [297.075, 76.91], [232.274, 30.51, 'c'], [219.474, 58.365, 'c'], [205.874, 54.365], [192.274, 50.365, 'c'], [194.674, 59.965, 'c'], [191.474, 60.765], [188.274, 61.565, 'c'], [149.074, 36.765, 'c'], [142.674, 37.565]],  -closed => 1, -fillcolor => "#f8d8c4", -filled => 1, -linecolor => "#f8d8c4");
$zinc->add('curve',$top_group,[[143.983, 39.31], [137.583, 40.11, 'c'], [110.529, 17.223, 'c'], [127.183, 48.11], [149.183, 88.91, 'c'], [68.783, 87.31, 'c'], [51.983, 76.11], [35.183, 64.91, 'c'], [59.183, 94.51, 'c'], [59.183, 94.51], [77.583, 114.51, 'c'], [43.183, 97.71, 'c'], [43.183, 97.71], [8.783, 84.91, 'c'], [-15.217, 110.51, 'c'], [-18.417, 111.31], [-21.618, 112.11, 'c'], [-26.418, 115.31, 'c'], [-27.218, 108.91], [-28.018, 102.51, 'c'], [-34.346, 87.318, 'c'], [-67.218, 112.11], [-98.345, 135.42, 'c'], [-109.363, 118.329, 'c'], [-109.363, 118.329], [-115.764, 116.51], [-128.764, 92.51, 'c'], [-120.309, 147.093, 'c'], [-120.309, 147.093], [-111.509, 181.493, 'c'], [23.983, 132.11, 'c'], [23.983, 132.11], [23.983, 132.11, 'c'], [192.783, 101.71, 'c'], [203.983, 97.71], [215.183, 93.71, 'c'], [302.529, 99.456, 'c'], [302.529, 99.456], [297.583, 78.074], [232.783, 31.673, 'c'], [220.783, 60.11, 'c'], [207.183, 56.11], [193.583, 52.11, 'c'], [195.983, 61.71, 'c'], [192.783, 62.51], [189.583, 63.31, 'c'], [150.383, 38.51, 'c'], [143.983, 39.31]],  -closed => 1, -fillcolor => "#fae5d7", -filled => 1, -linecolor => "#fae5d7");
$zinc->add('curve',$top_group,[[145.292, 41.055], [138.892, 41.855, 'c'], [112.917, 18.411, 'c'], [128.492, 49.855], [149.692, 92.656, 'c'], [70.092, 89.056, 'c'], [53.292, 77.856], [36.492, 66.656, 'c'], [60.492, 96.256, 'c'], [60.492, 96.256], [78.892, 116.256, 'c'], [44.492, 99.456, 'c'], [44.492, 99.456], [10.092, 86.656, 'c'], [-13.908, 112.256, 'c'], [-17.108, 113.056], [-20.308, 113.856, 'c'], [-25.108, 117.056, 'c'], [-25.908, 110.656], [-26.708, 104.256, 'c'], [-32.905, 89.232, 'c'], [-65.908, 113.856], [-98.273, 137.911, 'c'], [-108.982, 121.365, 'c'], [-108.982, 121.365], [-115.782, 118.056], [-128.582, 94.856, 'c'], [-119.654, 150.147, 'c'], [-119.654, 150.147], [-110.854, 184.547, 'c'], [25.292, 133.856, 'c'], [25.292, 133.856], [25.292, 133.856, 'c'], [194.093, 103.456, 'c'], [205.293, 99.456], [216.493, 95.456, 'c'], [302.965, 101.128, 'c'], [302.965, 101.128], [298.093, 79.237], [233.292, 32.837, 'c'], [222.093, 61.856, 'c'], [208.493, 57.856], [194.893, 53.855, 'c'], [197.293, 63.456, 'c'], [194.093, 64.256], [190.892, 65.056, 'c'], [151.692, 40.255, 'c'], [145.292, 41.055]],  -closed => 1, -fillcolor => "#fcf2eb", -filled => 1, -linecolor => "#fcf2eb");
$zinc->add('curve',$top_group,[[115.8, 119.601], [-128.6, 97.6, 'c'], [-119, 153.201, 'c'], [-119, 153.201], [-110.2, 187.601, 'c'], [26.6, 135.601, 'c'], [26.6, 135.601], [26.6, 135.601, 'c'], [195.401, 105.2, 'c'], [206.601, 101.2], [217.801, 97.2, 'c'], [303.401, 102.8, 'c'], [303.401, 102.8], [298.601, 80.4], [233.801, 34, 'c'], [223.401, 63.6, 'c'], [209.801, 59.6], [196.201, 55.6, 'c'], [198.601, 65.2, 'c'], [195.401, 66], [192.201, 66.8, 'c'], [153.001, 42, 'c'], [146.601, 42.8], [140.201, 43.6, 'c'], [114.981, 19.793, 'c'], [129.801, 51.6], [152.028, 99.307, 'c'], [69.041, 89.227, 'c'], [54.6, 79.6], [37.8, 68.4, 'c'], [61.8, 98, 'c'], [61.8, 98], [80.2, 118.001, 'c'], [45.8, 101.2, 'c'], [45.8, 101.2], [11.4, 88.4, 'c'], [-12.6, 114.001, 'c'], [-15.8, 114.801], [-19, 115.601, 'c'], [-23.8, 118.801, 'c'], [-24.6, 112.401], [-25.4, 106, 'c'], [-31.465, 91.144, 'c'], [-64.6, 115.601], [-98.2, 140.401, 'c'], [-108.6, 124.401, 'c'], [-108.6, 124.401], [-115.8, 119.601]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");
$zinc->add('curve',$top_group,[[74.2, 149.601], [-74.2, 149.601, 'c'], [-81.4, 161.201, 'c'], [-60.6, 174.401], [-60.6, 174.401, 'c'], [-59.2, 175.801, 'c'], [-77.2, 171.601], [-77.2, 171.601, 'c'], [-83.4, 169.601, 'c'], [-85, 159.201], [-85, 159.201, 'c'], [-89.8, 154.801, 'c'], [-94.6, 149.201], [-99.4, 143.601, 'c'], [-74.2, 149.601, 'c'], [-74.2, 149.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");
$zinc->add('curve',$top_group,[[65.8, 102], [65.8, 102, 'c'], [83.498, 128.821, 'c'], [82.9, 133.601], [81.6, 144.001, 'c'], [81.4, 153.601, 'c'], [84.6, 157.601], [87.801, 161.601, 'c'], [96.601, 194.801, 'c'], [96.601, 194.801], [96.601, 194.801, 'c'], [96.201, 196.001, 'c'], [108.601, 158.001], [108.601, 158.001, 'c'], [120.201, 142.001, 'c'], [100.201, 123.601], [100.201, 123.601, 'c'], [65, 94.8, 'c'], [65.8, 102]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");
$zinc->add('curve',$top_group,[[54.2, 176.401], [-54.2, 176.401, 'c'], [-43, 183.601, 'c'], [-57.4, 214.801], [-51, 212.401], [-51, 212.401, 'c'], [-51.8, 223.601, 'c'], [-55, 226.001], [-47.8, 222.801], [-47.8, 222.801, 'c'], [-43, 230.801, 'c'], [-47, 235.601], [-47, 235.601, 'c'], [-30.2, 243.601, 'c'], [-31, 250.001], [-31, 250.001, 'c'], [-24.6, 242.001, 'c'], [-28.6, 235.601], [-32.6, 229.201, 'c'], [-39.8, 233.201, 'c'], [-39, 214.801], [-47.8, 218.001], [-47.8, 218.001, 'c'], [-42.2, 209.201, 'c'], [-42.2, 202.801], [-50.2, 205.201], [-50.2, 205.201, 'c'], [-34.731, 178.623, 'c'], [-45.4, 177.201], [-51.4, 176.401, 'c'], [-54.2, 176.401, 'c'], [-54.2, 176.401]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");
$zinc->add('curve',$top_group,[[21.8, 193.201], [-21.8, 193.201, 'c'], [-19, 188.801, 'c'], [-21.8, 189.601], [-24.6, 190.401, 'c'], [-55.8, 205.201, 'c'], [-61.8, 214.801], [-61.8, 214.801, 'c'], [-27.4, 190.401, 'c'], [-21.8, 193.201]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");
$zinc->add('curve',$top_group,[[11.4, 201.201], [-11.4, 201.201, 'c'], [-8.6, 196.801, 'c'], [-11.4, 197.601], [-14.2, 198.401, 'c'], [-45.4, 213.201, 'c'], [-51.4, 222.801], [-51.4, 222.801, 'c'], [-17, 198.401, 'c'], [-11.4, 201.201]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");
$zinc->add('curve',$top_group,[[1.8, 186.001], [1.8, 186.001, 'c'], [4.6, 181.601, 'c'], [1.8, 182.401], [-1, 183.201, 'c'], [-32.2, 198.001, 'c'], [-38.2, 207.601], [-38.2, 207.601, 'c'], [-3.8, 183.201, 'c'], [1.8, 186.001]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");
$zinc->add('curve',$top_group,[[21.4, 229.601], [-21.4, 229.601, 'c'], [-21.4, 223.601, 'c'], [-24.2, 224.401], [-27, 225.201, 'c'], [-63, 242.801, 'c'], [-69, 252.401], [-69, 252.401, 'c'], [-27, 226.801, 'c'], [-21.4, 229.601]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");
$zinc->add('curve',$top_group,[[20.2, 218.801], [-20.2, 218.801, 'c'], [-19, 214.001, 'c'], [-21.8, 214.801], [-23.8, 214.801, 'c'], [-50.2, 226.401, 'c'], [-56.2, 236.001], [-56.2, 236.001, 'c'], [-26.6, 214.401, 'c'], [-20.2, 218.801]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");
$zinc->add('curve',$top_group,[[34.6, 266.401], [-44.6, 274.001], [-44.6, 274.001, 'c'], [-34.2, 266.401, 'c'], [-30.6, 267.601], [-30.6, 267.601, 'c'], [-37.4, 278.801, 'c'], [-38.2, 284.001], [-38.2, 284.001, 'c'], [-27.8, 271.201, 'c'], [-22.2, 271.601], [-22.2, 271.601, 'c'], [-14.6, 272.001, 'c'], [-14.6, 282.801], [-14.6, 282.801, 'c'], [-9, 272.401, 'c'], [-5.8, 272.801], [-5.8, 272.801, 'c'], [-4.6, 279.201, 'c'], [-5.8, 286.001], [-5.8, 286.001, 'c'], [-1.8, 278.401, 'c'], [2.2, 280.001], [2.2, 280.001, 'c'], [8.6, 278.001, 'c'], [7.8, 289.601], [7.8, 289.601, 'c'], [7.8, 300.001, 'c'], [7, 302.801], [7, 302.801, 'c'], [12.6, 276.401, 'c'], [15, 276.001], [15, 276.001, 'c'], [23, 274.801, 'c'], [27.8, 283.601], [27.8, 283.601, 'c'], [23.8, 276.001, 'c'], [28.6, 278.001], [28.6, 278.001, 'c'], [39.4, 279.601, 'c'], [42.6, 286.401], [42.6, 286.401, 'c'], [35.8, 274.401, 'c'], [41.4, 277.601], [41.4, 277.601, 'c'], [48.2, 277.601, 'c'], [49.4, 284.001], [49.4, 284.001, 'c'], [57.8, 305.201, 'c'], [59.8, 306.801], [59.8, 306.801, 'c'], [52.2, 285.201, 'c'], [53.8, 285.201], [53.8, 285.201, 'c'], [51.8, 273.201, 'c'], [57, 288.001], [57, 288.001, 'c'], [53.8, 274.001, 'c'], [59.4, 274.801], [65, 275.601, 'c'], [69.4, 285.601, 'c'], [77.8, 283.201], [77.8, 283.201, 'c'], [87.401, 288.801, 'c'], [89.401, 219.601], [-34.6, 266.401]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");
$zinc->add('curve',$top_group,[[29.8, 173.601], [-29.8, 173.601, 'c'], [-15, 167.601, 'c'], [25, 173.601], [25, 173.601, 'c'], [32.2, 174.001, 'c'], [39, 165.201], [45.8, 156.401, 'c'], [72.6, 149.201, 'c'], [79, 151.201], [88.601, 157.601], [89.401, 158.801], [89.401, 158.801, 'c'], [101.801, 169.201, 'c'], [102.201, 176.801], [102.601, 184.401, 'c'], [87.801, 232.401, 'c'], [78.2, 248.401], [68.6, 264.401, 'c'], [59, 276.801, 'c'], [39.8, 274.401], [39.8, 274.401, 'c'], [19, 270.401, 'c'], [-6.6, 274.401], [-6.6, 274.401, 'c'], [-35.8, 272.801, 'c'], [-38.6, 264.801], [-41.4, 256.801, 'c'], [-27.4, 241.601, 'c'], [-27.4, 241.601], [-27.4, 241.601, 'c'], [-23, 233.201, 'c'], [-24.2, 218.801], [-25.4, 204.401, 'c'], [-25, 176.401, 'c'], [-29.8, 173.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");
$zinc->add('curve',$top_group,[[7.8, 175.601], [0.6, 194.001, 'c'], [-29, 259.201, 'c'], [-29, 259.201], [-31, 260.801, 'c'], [-16.34, 266.846, 'c'], [-6.2, 264.401], [4.746, 261.763, 'c'], [45, 266.001, 'c'], [45, 266.001], [68.6, 250.401, 'c'], [81.4, 206.001, 'c'], [81.4, 206.001], [81.4, 206.001, 'c'], [91.801, 182.001, 'c'], [74.2, 178.801], [56.6, 175.601, 'c'], [-7.8, 175.601, 'c'], [-7.8, 175.601]],  -closed => 1, -fillcolor => "#e5668c", -filled => 1, -linecolor => "#e5668c");
$zinc->add('curve',$top_group,[[9.831, 206.497], [-6.505, 193.707, 'c'], [-4.921, 181.906, 'c'], [-7.8, 175.601], [-7.8, 175.601, 'c'], [54.6, 182.001, 'c'], [65.8, 161.201], [70.041, 153.326, 'c'], [84.801, 184.001, 'c'], [84.4, 193.601], [84.4, 193.601, 'c'], [21.4, 208.001, 'c'], [6.6, 196.801], [-9.831, 206.497]],  -closed => 1, -fillcolor => "#b23259", -filled => 1, -linecolor => "#b23259");
$zinc->add('curve',$top_group,[[5.4, 222.801], [-5.4, 222.801, 'c'], [-3.4, 230.001, 'c'], [-5.8, 234.001], [-5.8, 234.001, 'c'], [-7.4, 234.801, 'c'], [-8.6, 235.201], [-8.6, 235.201, 'c'], [-7.4, 238.801, 'c'], [-1.4, 240.401], [-1.4, 240.401, 'c'], [0.6, 244.801, 'c'], [3, 245.201], [5.4, 245.601, 'c'], [10.2, 251.201, 'c'], [14.2, 250.001], [18.2, 248.801, 'c'], [29.4, 244.801, 'c'], [29.4, 244.801], [29.4, 244.801, 'c'], [35, 241.601, 'c'], [43.8, 245.201], [43.8, 245.201, 'c'], [46.175, 244.399, 'c'], [46.6, 240.401], [47.1, 235.701, 'c'], [50.2, 232.001, 'c'], [52.2, 230.001], [54.2, 228.001, 'c'], [63.8, 215.201, 'c'], [62.6, 214.801], [61.4, 214.401, 'c'], [-5.4, 222.801, 'c'], [-5.4, 222.801]],  -closed => 1, -fillcolor => "#a5264c", -filled => 1, -linecolor => "#a5264c");
$zinc->add('curve',$top_group,[[9.8, 174.401], [-9.8, 174.401, 'c'], [-12.6, 196.801, 'c'], [-9.4, 205.201], [-6.2, 213.601, 'c'], [-7, 215.601, 'c'], [-7.8, 219.601], [-8.6, 223.601, 'c'], [-4.2, 233.601, 'c'], [1.4, 239.601], [13.4, 241.201], [13.4, 241.201, 'c'], [28.6, 237.601, 'c'], [37.8, 240.401], [37.8, 240.401, 'c'], [46.794, 241.744, 'c'], [50.2, 226.801], [50.2, 226.801, 'c'], [55, 220.401, 'c'], [62.2, 217.601], [69.4, 214.801, 'c'], [76.6, 173.201, 'c'], [72.6, 165.201], [68.6, 157.201, 'c'], [54.2, 152.801, 'c'], [38.2, 168.401], [22.2, 184.001, 'c'], [20.2, 167.201, 'c'], [-9.8, 174.401]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ff727f", -filled => 1);
$zinc->add('curve',$top_group,[[8.2, 249.201], [-8.2, 249.201, 'c'], [-9, 247.201, 'c'], [-13.4, 246.801], [-13.4, 246.801, 'c'], [-35.8, 243.201, 'c'], [-44.2, 230.801], [-44.2, 230.801, 'c'], [-51, 225.201, 'c'], [-46.6, 236.801], [-46.6, 236.801, 'c'], [-36.2, 257.201, 'c'], [-29.4, 260.001], [-29.4, 260.001, 'c'], [-13, 264.001, 'c'], [-8.2, 249.201]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);


$zinc->add('curve',$top_group,[[71.742, 185.229], [72.401, 177.323, 'c'], [74.354, 168.709, 'c'], [72.6, 165.201], [66.154, 152.307, 'c'], [49.181, 157.695, 'c'], [38.2, 168.401], [22.2, 184.001, 'c'], [20.2, 167.201, 'c'], [-9.8, 174.401], [-9.8, 174.401, 'c'], [-11.545, 188.364, 'c'], [-10.705, 198.376], [-10.705, 198.376, 'c'], [26.6, 186.801, 'c'], [27.4, 192.401], [27.4, 192.401, 'c'], [29, 189.201, 'c'], [38.2, 189.201], [47.4, 189.201, 'c'], [70.142, 188.029, 'c'], [71.742, 185.229]],  -closed => 1, -fillcolor => "#cc3f4c", -filled => 1, -linecolor => "#cc3f4c");
$zinc->add('curve',$top_group,[[28.6, 175.201], [28.6, 175.201, 'c'], [33.4, 180.001, 'c'], [29.8, 189.601], [29.8, 189.601, 'c'], [15.4, 205.601, 'c'], [17.4, 219.601]],  -closed => 0, -linecolor => "#a51926", -linewidth => 2);
$zinc->add('curve',$top_group,[[19.4, 260.001], [-19.4, 260.001, 'c'], [-23.8, 247.201, 'c'], [-15, 254.001], [-15, 254.001, 'c'], [-10.2, 256.001, 'c'], [-11.4, 257.601], [-12.6, 259.201, 'c'], [-18.2, 263.201, 'c'], [-19.4, 260.001]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);
$zinc->add('curve',$top_group,[[14.36, 261.201], [-14.36, 261.201, 'c'], [-17.88, 250.961, 'c'], [-10.84, 256.401], [-10.84, 256.401, 'c'], [-6.419, 258.849, 'c'], [-7.96, 259.281], [-12.52, 260.561, 'c'], [-7.96, 263.121, 'c'], [-14.36, 261.201]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);
$zinc->add('curve',$top_group,[[9.56, 261.201], [-9.56, 261.201, 'c'], [-13.08, 250.961, 'c'], [-6.04, 256.401], [-6.04, 256.401, 'c'], [-1.665, 258.711, 'c'], [-3.16, 259.281], [-6.52, 260.561, 'c'], [-3.16, 263.121, 'c'], [-9.56, 261.201]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);
$zinc->add('curve',$top_group,[[2.96, 261.401], [-2.96, 261.401, 'c'], [-6.48, 251.161, 'c'], [0.56, 256.601], [0.56, 256.601, 'c'], [4.943, 258.933, 'c'], [3.441, 259.481], [0.48, 260.561, 'c'], [3.441, 263.321, 'c'], [-2.96, 261.401]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);
$zinc->add('curve',$top_group,[[3.52, 261.321], [3.52, 261.321, 'c'], [0, 251.081, 'c'], [7.041, 256.521], [7.041, 256.521, 'c'], [10.881, 258.121, 'c'], [9.921, 259.401], [8.961, 260.681, 'c'], [9.921, 263.241, 'c'], [3.52, 261.321]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);
$zinc->add('curve',$top_group,[[10.2, 262.001], [10.2, 262.001, 'c'], [5.4, 249.601, 'c'], [14.6, 256.001], [14.6, 256.001, 'c'], [19.4, 258.001, 'c'], [18.2, 259.601], [17, 261.201, 'c'], [18.2, 264.401, 'c'], [10.2, 262.001]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);
$zinc->add('curve',$top_group,[[18.2, 244.801], [-18.2, 244.801, 'c'], [-5, 242.001, 'c'], [1, 245.201], [1, 245.201, 'c'], [7, 246.401, 'c'], [8.2, 246.001], [9.4, 245.601, 'c'], [12.6, 245.201, 'c'], [12.6, 245.201]],  -closed => 0, -linecolor => "#a5264c", -linewidth => 2);
$zinc->add('curve',$top_group,[[15.8, 253.601], [15.8, 253.601, 'c'], [27.8, 240.001, 'c'], [39.8, 244.401], [46.816, 246.974, 'c'], [45.8, 243.601, 'c'], [46.6, 240.801], [47.4, 238.001, 'c'], [47.6, 233.801, 'c'], [52.6, 230.801]],  -closed => 0, -linecolor => "#a5264c", -linewidth => 2);
$zinc->add('curve',$top_group,[[33, 237.601], [33, 237.601, 'c'], [29, 226.801, 'c'], [26.2, 239.601], [23.4, 252.401, 'c'], [20.2, 256.001, 'c'], [18.6, 258.801], [18.6, 258.801, 'c'], [18.6, 264.001, 'c'], [27, 263.601], [27, 263.601, 'c'], [37.8, 263.201, 'c'], [38.2, 260.401], [38.6, 257.601, 'c'], [37, 246.001, 'c'], [33, 237.601]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);
$zinc->add('curve',$top_group,[[47, 244.801], [47, 244.801, 'c'], [50.6, 242.401, 'c'], [53, 243.601]],  -closed => 0, -linecolor => "#a5264c", -linewidth => 2);
$zinc->add('curve',$top_group,[[53.5, 228.401], [53.5, 228.401, 'c'], [56.4, 223.501, 'c'], [61.2, 222.701]],  -closed => 0, -linecolor => "#a5264c", -linewidth => 2);
$zinc->add('curve',$top_group,[[25.8, 265.201], [-25.8, 265.201, 'c'], [-7.8, 268.401, 'c'], [-3.4, 266.801], [-3.4, 266.801, 'c'], [5.4, 266.801, 'c'], [-3, 268.801], [-3, 268.801, 'c'], [-15.8, 268.801, 'c'], [-23.8, 267.601], [-23.8, 267.601, 'c'], [-35.4, 262.001, 'c'], [-25.8, 265.201]],  -closed => 1, -fillcolor => "#b2b2b2", -filled => 1, -linecolor => "#b2b2b2");
$zinc->add('curve',$top_group,[[11.8, 172.001], [-11.8, 172.001, 'c'], [5.8, 172.001, 'c'], [7.8, 172.801], [7.8, 172.801, 'c'], [15, 203.601, 'c'], [11.4, 211.201], [11.4, 211.201, 'c'], [10.2, 214.001, 'c'], [7.4, 208.401], [7.4, 208.401, 'c'], [-11, 175.601, 'c'], [-14.2, 173.601], [-17.4, 171.601, 'c'], [-13, 172.001, 'c'], [-11.8, 172.001]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-88.9, 169.301], [-88.9, 169.301, 'c'], [-80, 171.001, 'c'], [-67.4, 173.601], [-67.4, 173.601, 'c'], [-62.6, 196.001, 'c'], [-59.4, 200.801], [-56.2, 205.601, 'c'], [-59.8, 205.601, 'c'], [-63.4, 202.801], [-67, 200.001, 'c'], [-81.8, 186.001, 'c'], [-83.8, 181.601], [-85.8, 177.201, 'c'], [-88.9, 169.301, 'c'], [-88.9, 169.301]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-67.039, 173.818], [-67.039, 173.818, 'c'], [-61.239, 175.366, 'c'], [-60.23, 177.581], [-59.222, 179.795, 'c'], [-61.432, 183.092, 'c'], [-61.432, 183.092], [-61.432, 183.092, 'c'], [-62.432, 186.397, 'c'], [-63.634, 184.235], [-64.836, 182.072, 'c'], [-67.708, 174.412, 'c'], [-67.039, 173.818]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-67, 173.601], [-67, 173.601, 'c'], [-63.4, 178.801, 'c'], [-59.8, 178.801], [-56.2, 178.801, 'c'], [-55.818, 178.388, 'c'], [-53, 179.001], [-48.4, 180.001, 'c'], [-48.8, 178.001, 'c'], [-42.2, 179.201], [-39.56, 179.681, 'c'], [-37, 178.801, 'c'], [-34.2, 180.001], [-31.4, 181.201, 'c'], [-28.2, 180.401, 'c'], [-27, 178.401], [-25.8, 176.401, 'c'], [-21, 172.201, 'c'], [-21, 172.201], [-21, 172.201, 'c'], [-33.8, 174.001, 'c'], [-36.6, 174.801], [-36.6, 174.801, 'c'], [-59, 176.001, 'c'], [-67, 173.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-22.4, 173.801], [-22.4, 173.801, 'c'], [-28.85, 177.301, 'c'], [-29.25, 179.701], [-29.65, 182.101, 'c'], [-24, 185.801, 'c'], [-24, 185.801], [-24, 185.801, 'c'], [-21.25, 190.401, 'c'], [-20.65, 188.001], [-20.05, 185.601, 'c'], [-21.6, 174.201, 'c'], [-22.4, 173.801]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-59.885, 179.265], [-59.885, 179.265, 'c'], [-52.878, 190.453, 'c'], [-52.661, 179.242], [-52.661, 179.242, 'c'], [-52.104, 177.984, 'c'], [-53.864, 177.962], [-59.939, 177.886, 'c'], [-58.418, 173.784, 'c'], [-59.885, 179.265]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-52.707, 179.514], [-52.707, 179.514, 'c'], [-44.786, 190.701, 'c'], [-45.422, 179.421], [-45.422, 179.421, 'c'], [-45.415, 179.089, 'c'], [-47.168, 178.936], [-51.915, 178.522, 'c'], [-51.57, 174.004, 'c'], [-52.707, 179.514]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-45.494, 179.522], [-45.494, 179.522, 'c'], [-37.534, 190.15, 'c'], [-38.203, 180.484], [-38.203, 180.484, 'c'], [-38.084, 179.251, 'c'], [-39.738, 178.95], [-43.63, 178.244, 'c'], [-43.841, 174.995, 'c'], [-45.494, 179.522]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-38.618, 179.602], [-38.618, 179.602, 'c'], [-30.718, 191.163, 'c'], [-30.37, 181.382], [-30.37, 181.382, 'c'], [-28.726, 180.004, 'c'], [-30.472, 179.782], [-36.29, 179.042, 'c'], [-35.492, 174.588, 'c'], [-38.618, 179.602]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffcc", -filled => 1, -linewidth => 0.5);

$zinc->add('curve',$top_group,[[-74.792, 183.132], [-82.45, 181.601], [-85.05, 176.601, 'c'], [-87.15, 170.451, 'c'], [-87.15, 170.451], [-87.15, 170.451, 'c'], [-80.8, 171.451, 'c'], [-68.3, 174.251], [-68.3, 174.251, 'c'], [-67.424, 177.569, 'c'], [-65.952, 183.364], [-74.792, 183.132]],  -closed => 1, -fillcolor => "#e5e5b2", -filled => 1, -linecolor => "#e5e5b2");

$zinc->add('curve',$top_group,[[-9.724, 178.47], [-11.39, 175.964, 'c'], [-12.707, 174.206, 'c'], [-13.357, 173.8], [-16.37, 171.917, 'c'], [-12.227, 172.294, 'c'], [-11.098, 172.294], [-11.098, 172.294, 'c'], [5.473, 172.294, 'c'], [7.356, 173.047], [7.356, 173.047, 'c'], [7.88, 175.289, 'c'], [8.564, 178.68], [8.564, 178.68, 'c'], [-1.524, 176.67, 'c'], [-9.724, 178.47]],  -closed => 1, -fillcolor => "#e5e5b2", -filled => 1, -linecolor => "#e5e5b2");

$zinc->add('curve',$top_group,[[43.88, 40.321], [71.601, 44.281, 'c'], [97.121, 8.641, 'c'], [98.881, -1.04], [100.641, -10.72, 'c'], [90.521, -22.6, 'c'], [90.521, -22.6], [91.841, -25.68, 'c'], [87.001, -39.76, 'c'], [81.721, -49], [76.441, -58.24, 'c'], [60.54, -57.266, 'c'], [43, -58.24], [27.16, -59.12, 'c'], [8.68, -35.8, 'c'], [7.36, -34.04], [6.04, -32.28, 'c'], [12.2, 6.001, 'c'], [13.52, 11.721], [14.84, 17.441, 'c'], [12.2, 43.841, 'c'], [12.2, 43.841], [46.44, 34.741, 'c'], [16.16, 36.361, 'c'], [43.88, 40.321]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[8.088, -33.392], [6.792, -31.664, 'c'], [12.84, 5.921, 'c'], [14.136, 11.537], [15.432, 17.153, 'c'], [12.84, 43.073, 'c'], [12.84, 43.073], [45.512, 34.193, 'c'], [16.728, 35.729, 'c'], [43.944, 39.617], [71.161, 43.505, 'c'], [96.217, 8.513, 'c'], [97.945, -0.992], [99.673, -10.496, 'c'], [89.737, -22.16, 'c'], [89.737, -22.16], [91.033, -25.184, 'c'], [86.281, -39.008, 'c'], [81.097, -48.08], [75.913, -57.152, 'c'], [60.302, -56.195, 'c'], [43.08, -57.152], [27.528, -58.016, 'c'], [9.384, -35.12, 'c'], [8.088, -33.392]],  -closed => 1, -fillcolor => "#ea8e51", -filled => 1, -linecolor => "#ea8e51");

$zinc->add('curve',$top_group,[[8.816, -32.744], [7.544, -31.048, 'c'], [13.48, 5.841, 'c'], [14.752, 11.353], [16.024, 16.865, 'c'], [13.48, 42.305, 'c'], [13.48, 42.305], [44.884, 33.145, 'c'], [17.296, 35.097, 'c'], [44.008, 38.913], [70.721, 42.729, 'c'], [95.313, 8.385, 'c'], [97.009, -0.944], [98.705, -10.272, 'c'], [88.953, -21.72, 'c'], [88.953, -21.72], [90.225, -24.688, 'c'], [85.561, -38.256, 'c'], [80.473, -47.16], [75.385, -56.064, 'c'], [60.063, -55.125, 'c'], [43.16, -56.064], [27.896, -56.912, 'c'], [10.088, -34.44, 'c'], [8.816, -32.744]],  -closed => 1, -fillcolor => "#efaa7c", -filled => 1, -linecolor => "#efaa7c");

$zinc->add('curve',$top_group,[[9.544, -32.096], [8.296, -30.432, 'c'], [14.12, 5.761, 'c'], [15.368, 11.169], [16.616, 16.577, 'c'], [14.12, 41.537, 'c'], [14.12, 41.537], [43.556, 32.497, 'c'], [17.864, 34.465, 'c'], [44.072, 38.209], [70.281, 41.953, 'c'], [94.409, 8.257, 'c'], [96.073, -0.895], [97.737, -10.048, 'c'], [88.169, -21.28, 'c'], [88.169, -21.28], [89.417, -24.192, 'c'], [84.841, -37.504, 'c'], [79.849, -46.24], [74.857, -54.976, 'c'], [59.824, -54.055, 'c'], [43.24, -54.976], [28.264, -55.808, 'c'], [10.792, -33.76, 'c'], [9.544, -32.096]],  -closed => 1, -fillcolor => "#f4c6a8", -filled => 1, -linecolor => "#f4c6a8");

$zinc->add('curve',$top_group,[[10.272, -31.448], [9.048, -29.816, 'c'], [14.76, 5.681, 'c'], [15.984, 10.985], [17.208, 16.289, 'c'], [14.76, 40.769, 'c'], [14.76, 40.769], [42.628, 31.849, 'c'], [18.432, 33.833, 'c'], [44.136, 37.505], [69.841, 41.177, 'c'], [93.505, 8.129, 'c'], [95.137, -0.848], [96.769, -9.824, 'c'], [87.385, -20.84, 'c'], [87.385, -20.84], [88.609, -23.696, 'c'], [84.121, -36.752, 'c'], [79.225, -45.32], [74.329, -53.888, 'c'], [59.585, -52.985, 'c'], [43.32, -53.888], [28.632, -54.704, 'c'], [11.496, -33.08, 'c'], [10.272, -31.448]],  -closed => 1, -fillcolor => "#f9e2d3", -filled => 1, -linecolor => "#f9e2d3");

$zinc->add('curve',$top_group,[[44.2, 36.8], [69.4, 40.4, 'c'], [92.601, 8, 'c'], [94.201, -0.8], [95.801, -9.6, 'c'], [86.601, -20.4, 'c'], [86.601, -20.4], [87.801, -23.2, 'c'], [83.4, -36, 'c'], [78.6, -44.4], [73.8, -52.8, 'c'], [59.346, -51.914, 'c'], [43.4, -52.8], [29, -53.6, 'c'], [12.2, -32.4, 'c'], [11, -30.8], [9.8, -29.2, 'c'], [15.4, 5.6, 'c'], [16.6, 10.8], [17.8, 16, 'c'], [15.4, 40, 'c'], [15.4, 40], [40.9, 31.4, 'c'], [19, 33.2, 'c'], [44.2, 36.8]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[90.601, 2.8], [90.601, 2.8, 'c'], [62.8, 10.4, 'c'], [51.2, 8.8], [51.2, 8.8, 'c'], [35.4, 2.2, 'c'], [26.6, 24], [26.6, 24, 'c'], [23, 31.2, 'c'], [21, 33.2], [19, 35.2, 'c'], [90.601, 2.8, 'c'], [90.601, 2.8]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[94.401, 0.6], [94.401, 0.6, 'c'], [65.4, 12.8, 'c'], [55.4, 12.4], [55.4, 12.4, 'c'], [39, 7.8, 'c'], [30.6, 22.4], [30.6, 22.4, 'c'], [22.2, 31.6, 'c'], [19, 33.2], [19, 33.2, 'c'], [18.6, 34.8, 'c'], [25, 30.8], [35.4, 36], [35.4, 36, 'c'], [50.2, 45.6, 'c'], [59.8, 29.6], [59.8, 29.6, 'c'], [63.8, 18.4, 'c'], [63.8, 16.4], [63.8, 14.4, 'c'], [85, 8.8, 'c'], [86.601, 8.4], [88.201, 8, 'c'], [94.801, 3.8, 'c'], [94.401, 0.6]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[47, 36.514], [40.128, 36.514, 'c'], [31.755, 32.649, 'c'], [31.755, 26.4], [31.755, 20.152, 'c'], [40.128, 13.887, 'c'], [47, 13.887], [53.874, 13.887, 'c'], [59.446, 18.952, 'c'], [59.446, 25.2], [59.446, 31.449, 'c'], [53.874, 36.514, 'c'], [47, 36.514]],  -closed => 1, -fillcolor => "#99cc32", -filled => 1, -linecolor => "#99cc32");

$zinc->add('curve',$top_group,[[43.377, 19.83], [38.531, 20.552, 'c'], [33.442, 22.055, 'c'], [33.514, 21.839], [35.054, 17.22, 'c'], [41.415, 13.887, 'c'], [47, 13.887], [51.296, 13.887, 'c'], [55.084, 15.865, 'c'], [57.32, 18.875], [57.32, 18.875, 'c'], [52.004, 18.545, 'c'], [43.377, 19.83]],  -closed => 1, -fillcolor => "#659900", -filled => 1, -linecolor => "#659900");

$zinc->add('curve',$top_group,[[55.4, 19.6], [55.4, 19.6, 'c'], [51, 16.4, 'c'], [51, 18.6], [51, 18.6, 'c'], [54.6, 23, 'c'], [55.4, 19.6]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[45.4, 27.726], [42.901, 27.726, 'c'], [40.875, 25.7, 'c'], [40.875, 23.2], [40.875, 20.701, 'c'], [42.901, 18.675, 'c'], [45.4, 18.675], [47.9, 18.675, 'c'], [49.926, 20.701, 'c'], [49.926, 23.2], [49.926, 25.7, 'c'], [47.9, 27.726, 'c'], [45.4, 27.726]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-58.6, 14.4], [-58.6, 14.4, 'c'], [-61.8, -6.8, 'c'], [-59.4, -11.2], [-59.4, -11.2, 'c'], [-48.6, -21.2, 'c'], [-49, -24.8], [-49, -24.8, 'c'], [-49.4, -42.8, 'c'], [-50.6, -43.6], [-51.8, -44.4, 'c'], [-59.4, -50.4, 'c'], [-65.4, -44], [-65.4, -44, 'c'], [-75.8, -26, 'c'], [-75, -19.6], [-75, -17.6], [-75, -17.6, 'c'], [-82.6, -18, 'c'], [-84.2, -16], [-84.2, -16, 'c'], [-85.4, -10.8, 'c'], [-86.6, -10.4], [-86.6, -10.4, 'c'], [-89.4, -8, 'c'], [-87.4, -5.2], [-87.4, -5.2, 'c'], [-89.4, -2.8, 'c'], [-89, 1.2], [-81.4, 5.2], [-81.4, 5.2, 'c'], [-79.4, 19.6, 'c'], [-68.6, 24.8], [-63.764, 27.129, 'c'], [-60.6, 20.4, 'c'], [-58.6, 14.4]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[-59.6, 12.56], [-59.6, 12.56, 'c'], [-62.48, -6.52, 'c'], [-60.32, -10.48], [-60.32, -10.48, 'c'], [-50.6, -19.48, 'c'], [-50.96, -22.72], [-50.96, -22.72, 'c'], [-51.32, -38.92, 'c'], [-52.4, -39.64], [-53.48, -40.36, 'c'], [-60.32, -45.76, 'c'], [-65.72, -40], [-65.72, -40, 'c'], [-75.08, -23.8, 'c'], [-74.36, -18.04], [-74.36, -16.24], [-74.36, -16.24, 'c'], [-81.2, -16.6, 'c'], [-82.64, -14.8], [-82.64, -14.8, 'c'], [-83.72, -10.12, 'c'], [-84.8, -9.76], [-84.8, -9.76, 'c'], [-87.32, -7.6, 'c'], [-85.52, -5.08], [-85.52, -5.08, 'c'], [-87.32, -2.92, 'c'], [-86.96, 0.68], [-80.12, 4.28], [-80.12, 4.28, 'c'], [-78.32, 17.24, 'c'], [-68.6, 21.92], [-64.248, 24.015, 'c'], [-61.4, 17.96, 'c'], [-59.6, 12.56]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[-51.05, -42.61], [-52.14, -43.47, 'c'], [-59.63, -49.24, 'c'], [-65.48, -43], [-65.48, -43, 'c'], [-75.62, -25.45, 'c'], [-74.84, -19.21], [-74.84, -17.26], [-74.84, -17.26, 'c'], [-82.25, -17.65, 'c'], [-83.81, -15.7], [-83.81, -15.7, 'c'], [-84.98, -10.63, 'c'], [-86.15, -10.24], [-86.15, -10.24, 'c'], [-88.88, -7.9, 'c'], [-86.93, -5.17], [-86.93, -5.17, 'c'], [-88.88, -2.83, 'c'], [-88.49, 1.07], [-81.08, 4.97], [-81.08, 4.97, 'c'], [-79.13, 19.01, 'c'], [-68.6, 24.08], [-63.886, 26.35, 'c'], [-60.8, 19.79, 'c'], [-58.85, 13.94], [-58.85, 13.94, 'c'], [-61.97, -6.73, 'c'], [-59.63, -11.02], [-59.63, -11.02, 'c'], [-49.1, -20.77, 'c'], [-49.49, -24.28], [-49.49, -24.28, 'c'], [-49.88, -41.83, 'c'], [-51.05, -42.61]],  -closed => 1, -fillcolor => "#eb955c", -filled => 1, -linecolor => "#eb955c");

$zinc->add('curve',$top_group,[[-51.5, -41.62], [-52.48, -42.54, 'c'], [-59.86, -48.08, 'c'], [-65.56, -42], [-65.56, -42, 'c'], [-75.44, -24.9, 'c'], [-74.68, -18.82], [-74.68, -16.92], [-74.68, -16.92, 'c'], [-81.9, -17.3, 'c'], [-83.42, -15.4], [-83.42, -15.4, 'c'], [-84.56, -10.46, 'c'], [-85.7, -10.08], [-85.7, -10.08, 'c'], [-88.36, -7.8, 'c'], [-86.46, -5.14], [-86.46, -5.14, 'c'], [-88.36, -2.86, 'c'], [-87.98, 0.94], [-80.76, 4.74], [-80.76, 4.74, 'c'], [-78.86, 18.42, 'c'], [-68.6, 23.36], [-64.006, 25.572, 'c'], [-61, 19.18, 'c'], [-59.1, 13.48], [-59.1, 13.48, 'c'], [-62.14, -6.66, 'c'], [-59.86, -10.84], [-59.86, -10.84, 'c'], [-49.6, -20.34, 'c'], [-49.98, -23.76], [-49.98, -23.76, 'c'], [-50.36, -40.86, 'c'], [-51.5, -41.62]],  -closed => 1, -fillcolor => "#f2b892", -filled => 1, -linecolor => "#f2b892");

$zinc->add('curve',$top_group,[[-51.95, -40.63], [-52.82, -41.61, 'c'], [-60.09, -46.92, 'c'], [-65.64, -41], [-65.64, -41, 'c'], [-75.26, -24.35, 'c'], [-74.52, -18.43], [-74.52, -16.58], [-74.52, -16.58, 'c'], [-81.55, -16.95, 'c'], [-83.03, -15.1], [-83.03, -15.1, 'c'], [-84.14, -10.29, 'c'], [-85.25, -9.92], [-85.25, -9.92, 'c'], [-87.84, -7.7, 'c'], [-85.99, -5.11], [-85.99, -5.11, 'c'], [-87.84, -2.89, 'c'], [-87.47, 0.81], [-80.44, 4.51], [-80.44, 4.51, 'c'], [-78.59, 17.83, 'c'], [-68.6, 22.64], [-64.127, 24.794, 'c'], [-61.2, 18.57, 'c'], [-59.35, 13.02], [-59.35, 13.02, 'c'], [-62.31, -6.59, 'c'], [-60.09, -10.66], [-60.09, -10.66, 'c'], [-50.1, -19.91, 'c'], [-50.47, -23.24], [-50.47, -23.24, 'c'], [-50.84, -39.89, 'c'], [-51.95, -40.63]],  -closed => 1, -fillcolor => "#f8dcc8", -filled => 1, -linecolor => "#f8dcc8");

$zinc->add('curve',$top_group,[[-59.6, 12.46], [-59.6, 12.46, 'c'], [-62.48, -6.52, 'c'], [-60.32, -10.48], [-60.32, -10.48, 'c'], [-50.6, -19.48, 'c'], [-50.96, -22.72], [-50.96, -22.72, 'c'], [-51.32, -38.92, 'c'], [-52.4, -39.64], [-53.16, -40.68, 'c'], [-60.32, -45.76, 'c'], [-65.72, -40], [-65.72, -40, 'c'], [-75.08, -23.8, 'c'], [-74.36, -18.04], [-74.36, -16.24], [-74.36, -16.24, 'c'], [-81.2, -16.6, 'c'], [-82.64, -14.8], [-82.64, -14.8, 'c'], [-83.72, -10.12, 'c'], [-84.8, -9.76], [-84.8, -9.76, 'c'], [-87.32, -7.6, 'c'], [-85.52, -5.08], [-85.52, -5.08, 'c'], [-87.32, -2.92, 'c'], [-86.96, 0.68], [-80.12, 4.28], [-80.12, 4.28, 'c'], [-78.32, 17.24, 'c'], [-68.6, 21.92], [-64.248, 24.015, 'c'], [-61.4, 17.86, 'c'], [-59.6, 12.46]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[-62.7, 6.2], [-62.7, 6.2, 'c'], [-84.3, -4, 'c'], [-85.2, -4.8], [-85.2, -4.8, 'c'], [-76.1, 3.4, 'c'], [-75.3, 3.4], [-74.5, 3.4, 'c'], [-62.7, 6.2, 'c'], [-62.7, 6.2]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-79.8, 0], [-79.8, 0, 'c'], [-61.4, 3.6, 'c'], [-61.4, 8], [-61.4, 10.912, 'c'], [-61.643, 24.331, 'c'], [-67, 22.8], [-75.4, 20.4, 'c'], [-71.8, 6, 'c'], [-79.8, 0]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-71.4, 3.8], [-71.4, 3.8, 'c'], [-62.422, 5.274, 'c'], [-61.4, 8], [-60.8, 9.6, 'c'], [-60.137, 17.908, 'c'], [-65.6, 19], [-70.152, 19.911, 'c'], [-72.382, 9.69, 'c'], [-71.4, 3.8]],  -closed => 1, -fillcolor => "#99cc32", -filled => 1, -linecolor => "#99cc32");

$zinc->add('curve',$top_group,[[14.595, 46.349], [14.098, 44.607, 'c'], [15.409, 44.738, 'c'], [17.2, 44.2], [19.2, 43.6, 'c'], [31.4, 39.8, 'c'], [32.2, 37.2], [33, 34.6, 'c'], [46.2, 39, 'c'], [46.2, 39], [48, 39.8, 'c'], [52.4, 42.4, 'c'], [52.4, 42.4], [57.2, 43.6, 'c'], [63.8, 44, 'c'], [63.8, 44], [66.2, 45, 'c'], [69.6, 47.8, 'c'], [69.6, 47.8], [84.2, 58, 'c'], [96.601, 50.8, 'c'], [96.601, 50.8], [116.601, 44.2, 'c'], [110.601, 27, 'c'], [110.601, 27], [107.601, 18, 'c'], [110.801, 14.6, 'c'], [110.801, 14.6], [111.001, 10.8, 'c'], [118.201, 17.2, 'c'], [118.201, 17.2], [120.801, 21.4, 'c'], [121.601, 26.4, 'c'], [121.601, 26.4], [129.601, 37.6, 'c'], [126.201, 19.8, 'c'], [126.201, 19.8], [126.401, 18.8, 'c'], [123.601, 15.2, 'c'], [123.601, 14], [123.601, 12.8, 'c'], [121.801, 9.4, 'c'], [121.801, 9.4], [118.801, 6, 'c'], [121.201, -1, 'c'], [121.201, -1], [123.001, -14.8, 'c'], [120.801, -13, 'c'], [120.801, -13], [119.601, -14.8, 'c'], [110.401, -4.8, 'c'], [110.401, -4.8], [108.201, -1.4, 'c'], [102.201, 0.2, 'c'], [102.201, 0.2], [99.401, 2, 'c'], [96.001, 0.6, 'c'], [96.001, 0.6], [93.401, 0.2, 'c'], [87.801, 7.2, 'c'], [87.801, 7.2], [90.601, 7, 'c'], [93.001, 11.4, 'c'], [95.401, 11.6], [97.801, 11.8, 'c'], [99.601, 9.2, 'c'], [101.201, 8.6], [102.801, 8, 'c'], [105.601, 13.8, 'c'], [105.601, 13.8], [106.001, 16.4, 'c'], [100.401, 21.2, 'c'], [100.401, 21.2], [100.001, 25.8, 'c'], [98.401, 24.2, 'c'], [98.401, 24.2], [95.401, 23.6, 'c'], [94.201, 27.4, 'c'], [93.201, 32], [92.201, 36.6, 'c'], [88.001, 37, 'c'], [88.001, 37], [86.401, 44.4, 'c'], [85.2, 41.4, 'c'], [85.2, 41.4], [85, 35.8, 'c'], [79, 41.6, 'c'], [79, 41.6], [77.8, 43.6, 'c'], [73.2, 41.4, 'c'], [73.2, 41.4], [66.4, 39.4, 'c'], [68.8, 37.4, 'c'], [68.8, 37.4], [70.6, 35.2, 'c'], [81.8, 37.4, 'c'], [81.8, 37.4], [84, 35.8, 'c'], [76, 31.8, 'c'], [76, 31.8], [75.4, 30, 'c'], [76.4, 25.6, 'c'], [76.4, 25.6], [77.6, 22.4, 'c'], [84.4, 16.8, 'c'], [84.4, 16.8], [93.801, 15.6, 'c'], [91.001, 14, 'c'], [91.001, 14], [84.801, 8.8, 'c'], [79, 16.4, 'c'], [79, 16.4], [76.8, 22.6, 'c'], [59.4, 37.6, 'c'], [59.4, 37.6], [54.6, 41, 'c'], [57.2, 34.2, 'c'], [53.2, 37.6], [49.2, 41, 'c'], [28.6, 32, 'c'], [28.6, 32], [17.038, 30.807, 'c'], [14.306, 46.549, 'c'], [10.777, 43.429], [10.777, 43.429, 'c'], [16.195, 51.949, 'c'], [14.595, 46.349]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[209.401, -120], [209.401, -120, 'c'], [183.801, -112, 'c'], [181.001, -93.2], [181.001, -93.2, 'c'], [178.601, -70.4, 'c'], [199.001, -52.8], [199.001, -52.8, 'c'], [199.401, -46.4, 'c'], [201.401, -43.2], [201.401, -43.2, 'c'], [199.801, -38.4, 'c'], [218.601, -46], [245.801, -54.4], [245.801, -54.4, 'c'], [252.201, -56.8, 'c'], [257.401, -65.6], [262.601, -74.4, 'c'], [277.801, -93.2, 'c'], [274.201, -118.4], [274.201, -118.4, 'c'], [275.401, -129.6, 'c'], [269.401, -130], [269.401, -130, 'c'], [261.001, -131.6, 'c'], [253.801, -124], [253.801, -124, 'c'], [247.001, -120.8, 'c'], [244.601, -121.2], [209.401, -120]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[264.022, -120.99], [264.022, -120.99, 'c'], [266.122, -129.92, 'c'], [261.282, -125.08], [261.282, -125.08, 'c'], [254.242, -119.36, 'c'], [246.761, -119.36], [246.761, -119.36, 'c'], [232.241, -117.16, 'c'], [227.841, -103.96], [227.841, -103.96, 'c'], [223.881, -77.12, 'c'], [231.801, -71.4], [231.801, -71.4, 'c'], [236.641, -63.92, 'c'], [243.681, -70.52], [250.722, -77.12, 'c'], [266.222, -107.35, 'c'], [264.022, -120.99]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[263.648, -120.632], [263.648, -120.632, 'c'], [265.738, -129.376, 'c'], [260.986, -124.624], [260.986, -124.624, 'c'], [254.074, -119.008, 'c'], [246.729, -119.008], [246.729, -119.008, 'c'], [232.473, -116.848, 'c'], [228.153, -103.888], [228.153, -103.888, 'c'], [224.265, -77.536, 'c'], [232.041, -71.92], [232.041, -71.92, 'c'], [236.793, -64.576, 'c'], [243.705, -71.056], [250.618, -77.536, 'c'], [265.808, -107.24, 'c'], [263.648, -120.632]],  -closed => 1, -fillcolor => "#323232", -filled => 1, -linecolor => "#323232");

$zinc->add('curve',$top_group,[[263.274, -120.274], [263.274, -120.274, 'c'], [265.354, -128.832, 'c'], [260.69, -124.168], [260.69, -124.168, 'c'], [253.906, -118.656, 'c'], [246.697, -118.656], [246.697, -118.656, 'c'], [232.705, -116.536, 'c'], [228.465, -103.816], [228.465, -103.816, 'c'], [224.649, -77.952, 'c'], [232.281, -72.44], [232.281, -72.44, 'c'], [236.945, -65.232, 'c'], [243.729, -71.592], [250.514, -77.952, 'c'], [265.394, -107.13, 'c'], [263.274, -120.274]],  -closed => 1, -fillcolor => "#666666", -filled => 1, -linecolor => "#666666");

$zinc->add('curve',$top_group,[[262.9, -119.916], [262.9, -119.916, 'c'], [264.97, -128.288, 'c'], [260.394, -123.712], [260.394, -123.712, 'c'], [253.738, -118.304, 'c'], [246.665, -118.304], [246.665, -118.304, 'c'], [232.937, -116.224, 'c'], [228.777, -103.744], [228.777, -103.744, 'c'], [225.033, -78.368, 'c'], [232.521, -72.96], [232.521, -72.96, 'c'], [237.097, -65.888, 'c'], [243.753, -72.128], [250.41, -78.368, 'c'], [264.98, -107.02, 'c'], [262.9, -119.916]],  -closed => 1, -fillcolor => "#999999", -filled => 1, -linecolor => "#999999");

$zinc->add('curve',$top_group,[[262.526, -119.558], [262.526, -119.558, 'c'], [264.586, -127.744, 'c'], [260.098, -123.256], [260.098, -123.256, 'c'], [253.569, -117.952, 'c'], [246.633, -117.952], [246.633, -117.952, 'c'], [233.169, -115.912, 'c'], [229.089, -103.672], [229.089, -103.672, 'c'], [225.417, -78.784, 'c'], [232.761, -73.48], [232.761, -73.48, 'c'], [237.249, -66.544, 'c'], [243.777, -72.664], [250.305, -78.784, 'c'], [264.566, -106.91, 'c'], [262.526, -119.558]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[262.151, -119.2], [262.151, -119.2, 'c'], [264.201, -127.2, 'c'], [259.801, -122.8], [259.801, -122.8, 'c'], [253.401, -117.6, 'c'], [246.601, -117.6], [246.601, -117.6, 'c'], [233.401, -115.6, 'c'], [229.401, -103.6], [229.401, -103.6, 'c'], [225.801, -79.2, 'c'], [233.001, -74], [233.001, -74, 'c'], [237.401, -67.2, 'c'], [243.801, -73.2], [250.201, -79.2, 'c'], [264.151, -106.8, 'c'], [262.151, -119.2]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[50.6, 84], [50.6, 84, 'c'], [30.2, 64.8, 'c'], [22.2, 64], [22.2, 64, 'c'], [-12.2, 60, 'c'], [-27, 78], [-27, 78, 'c'], [-9.4, 57.6, 'c'], [18.2, 63.2], [18.2, 63.2, 'c'], [-3.4, 58.8, 'c'], [-15.8, 62], [-15.8, 62, 'c'], [-32.6, 62, 'c'], [-42.2, 76], [-45, 80.8], [-45, 80.8, 'c'], [-41, 66, 'c'], [-22.6, 60], [-22.6, 60, 'c'], [0.2, 55.2, 'c'], [11, 60], [11, 60, 'c'], [-10.6, 53.2, 'c'], [-20.6, 55.2], [-20.6, 55.2, 'c'], [-51, 52.8, 'c'], [-63.8, 79.2], [-63.8, 79.2, 'c'], [-59.8, 64.8, 'c'], [-45, 57.6], [-45, 57.6, 'c'], [-31.4, 48.8, 'c'], [-11, 51.6], [-11, 51.6, 'c'], [3.4, 54.8, 'c'], [8.6, 57.2], [13.8, 59.6, 'c'], [12.6, 56.8, 'c'], [4.2, 52], [4.2, 52, 'c'], [-1.4, 42, 'c'], [-15.4, 42.4], [-15.4, 42.4, 'c'], [-58.2, 46, 'c'], [-68.6, 58], [-68.6, 58, 'c'], [-55, 46.8, 'c'], [-44.6, 44], [-44.6, 44, 'c'], [-22.2, 36, 'c'], [-13.8, 36.8], [-13.8, 36.8, 'c'], [11, 37.8, 'c'], [18.6, 33.8], [18.6, 33.8, 'c'], [7.4, 38.8, 'c'], [10.6, 42], [13.8, 45.2, 'c'], [20.6, 52.8, 'c'], [20.6, 54], [20.6, 55.2, 'c'], [44.8, 77.3, 'c'], [48.4, 81.7], [50.6, 84]],  -closed => 1, -fillcolor => "#992600", -filled => 1, -linecolor => "#992600");

$zinc->add('curve',$top_group,[[189, 278], [189, 278, 'c'], [173.5, 241.5, 'c'], [161, 232], [161, 232, 'c'], [187, 248, 'c'], [190.5, 266], [190.5, 266, 'c'], [190.5, 276, 'c'], [189, 278]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[236, 285.5], [236, 285.5, 'c'], [209.5, 230.5, 'c'], [191, 206.5], [191, 206.5, 'c'], [234.5, 244, 'c'], [239.5, 270.5], [240, 276], [237, 273.5], [237, 273.5, 'c'], [236.5, 282.5, 'c'], [236, 285.5]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[292.5, 237], [292.5, 237, 'c'], [230, 177.5, 'c'], [228.5, 175], [228.5, 175, 'c'], [289, 241, 'c'], [292, 248.5], [292, 248.5, 'c'], [290, 239.5, 'c'], [292.5, 237]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[104, 280.5], [104, 280.5, 'c'], [123.5, 228.5, 'c'], [142.5, 251], [142.5, 251, 'c'], [157.5, 261, 'c'], [157, 264], [157, 264, 'c'], [153, 257.5, 'c'], [135, 258], [135, 258, 'c'], [116, 255, 'c'], [104, 280.5]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[294.5, 153], [294.5, 153, 'c'], [249.5, 124.5, 'c'], [242, 123], [230.193, 120.639, 'c'], [291.5, 152, 'c'], [296.5, 162.5], [296.5, 162.5, 'c'], [298.5, 160, 'c'], [294.5, 153]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[143.801, 259.601], [143.801, 259.601, 'c'], [164.201, 257.601, 'c'], [171.001, 250.801], [175.401, 254.401], [193.001, 216.001], [196.601, 221.201], [196.601, 221.201, 'c'], [211.001, 206.401, 'c'], [210.201, 198.401], [209.401, 190.401, 'c'], [223.001, 204.401, 'c'], [223.001, 204.401], [223.001, 204.401, 'c'], [222.201, 192.801, 'c'], [229.401, 199.601], [229.401, 199.601, 'c'], [227.001, 184.001, 'c'], [235.401, 192.001], [235.401, 192.001, 'c'], [224.864, 161.844, 'c'], [247.401, 187.601], [253.001, 194.001, 'c'], [248.601, 187.201, 'c'], [248.601, 187.201], [248.601, 187.201, 'c'], [222.601, 139.201, 'c'], [244.201, 153.601], [244.201, 153.601, 'c'], [246.201, 130.801, 'c'], [245.001, 126.401], [243.801, 122.001, 'c'], [241.801, 99.6, 'c'], [237.001, 94.4], [232.201, 89.2, 'c'], [237.401, 87.6, 'c'], [243.001, 92.8], [243.001, 92.8, 'c'], [231.801, 68.8, 'c'], [245.001, 80.8], [245.001, 80.8, 'c'], [241.401, 65.6, 'c'], [237.001, 62.8], [237.001, 62.8, 'c'], [231.401, 45.6, 'c'], [246.601, 56.4], [246.601, 56.4, 'c'], [242.201, 44, 'c'], [239.001, 40.8], [239.001, 40.8, 'c'], [227.401, 13.2, 'c'], [234.601, 18], [239.001, 21.6], [239.001, 21.6, 'c'], [232.201, 7.6, 'c'], [238.601, 12], [245.001, 16.4, 'c'], [245.001, 16, 'c'], [245.001, 16], [245.001, 16, 'c'], [223.801, -17.2, 'c'], [244.201, 0.4], [244.201, 0.4, 'c'], [236.042, -13.518, 'c'], [232.601, -20.4], [232.601, -20.4, 'c'], [213.801, -40.8, 'c'], [228.201, -34.4], [233.001, -32.8], [233.001, -32.8, 'c'], [224.201, -42.8, 'c'], [216.201, -44.4], [208.201, -46, 'c'], [218.601, -52.4, 'c'], [225.001, -50.4], [231.401, -48.4, 'c'], [247.001, -40.8, 'c'], [247.001, -40.8], [247.001, -40.8, 'c'], [259.801, -22, 'c'], [263.801, -21.6], [263.801, -21.6, 'c'], [243.801, -29.2, 'c'], [249.801, -21.2], [249.801, -21.2, 'c'], [264.201, -7.2, 'c'], [257.001, -7.6], [257.001, -7.6, 'c'], [251.001, -0.4, 'c'], [255.801, 8.4], [255.801, 8.4, 'c'], [237.342, -9.991, 'c'], [252.201, 15.6], [259.001, 32], [259.001, 32, 'c'], [234.601, 7.2, 'c'], [245.801, 29.2], [245.801, 29.2, 'c'], [263.001, 52.8, 'c'], [265.001, 53.2], [267.001, 53.6, 'c'], [271.401, 62.4, 'c'], [271.401, 62.4], [267.001, 60.4], [272.201, 69.2], [272.201, 69.2, 'c'], [261.001, 57.2, 'c'], [267.001, 70.4], [272.601, 84.8], [272.601, 84.8, 'c'], [252.201, 62.8, 'c'], [265.801, 92.4], [265.801, 92.4, 'c'], [249.401, 87.2, 'c'], [258.201, 104.4], [258.201, 104.4, 'c'], [256.601, 120.401, 'c'], [257.001, 125.601], [257.401, 130.801, 'c'], [258.601, 159.201, 'c'], [254.201, 167.201], [249.801, 175.201, 'c'], [260.201, 194.401, 'c'], [262.201, 198.401], [264.201, 202.401, 'c'], [267.801, 213.201, 'c'], [259.001, 204.001], [250.201, 194.801, 'c'], [254.601, 200.401, 'c'], [256.601, 209.201], [258.601, 218.001, 'c'], [264.601, 233.601, 'c'], [263.801, 239.201], [263.801, 239.201, 'c'], [262.601, 240.401, 'c'], [259.401, 236.801], [259.401, 236.801, 'c'], [244.601, 214.001, 'c'], [246.201, 228.401], [246.201, 228.401, 'c'], [245.001, 236.401, 'c'], [241.801, 245.201], [241.801, 245.201, 'c'], [238.601, 256.001, 'c'], [238.601, 247.201], [238.601, 247.201, 'c'], [235.401, 230.401, 'c'], [232.601, 238.001], [229.801, 245.601, 'c'], [226.201, 251.601, 'c'], [223.401, 254.001], [220.601, 256.401, 'c'], [215.401, 233.601, 'c'], [214.201, 244.001], [214.201, 244.001, 'c'], [202.201, 231.601, 'c'], [197.401, 248.001], [185.801, 264.401], [185.801, 264.401, 'c'], [185.401, 252.001, 'c'], [184.201, 258.001], [184.201, 258.001, 'c'], [154.201, 264.001, 'c'], [143.801, 259.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[109.401, -97.2], [109.401, -97.2, 'c'], [97.801, -105.2, 'c'], [93.801, -104.8], [89.801, -104.4, 'c'], [121.401, -113.6, 'c'], [162.601, -86], [162.601, -86, 'c'], [167.401, -83.2, 'c'], [171.001, -83.6], [171.001, -83.6, 'c'], [174.201, -81.2, 'c'], [171.401, -77.6], [171.401, -77.6, 'c'], [162.601, -68, 'c'], [173.801, -56.8], [173.801, -56.8, 'c'], [192.201, -50, 'c'], [186.601, -58.8], [186.601, -58.8, 'c'], [197.401, -54.8, 'c'], [199.801, -50.8], [202.201, -46.8, 'c'], [201.001, -50.8, 'c'], [201.001, -50.8], [201.001, -50.8, 'c'], [194.601, -58, 'c'], [188.601, -63.2], [188.601, -63.2, 'c'], [183.401, -65.2, 'c'], [180.601, -73.6], [177.801, -82, 'c'], [175.401, -92, 'c'], [179.801, -95.2], [179.801, -95.2, 'c'], [175.801, -90.8, 'c'], [176.601, -94.8], [177.401, -98.8, 'c'], [181.001, -102.4, 'c'], [182.601, -102.8], [184.201, -103.2, 'c'], [200.601, -119, 'c'], [207.401, -119.4], [207.401, -119.4, 'c'], [198.201, -118, 'c'], [195.201, -119], [192.201, -120, 'c'], [165.601, -131.4, 'c'], [159.601, -132.6], [159.601, -132.6, 'c'], [142.801, -139.2, 'c'], [154.801, -137.2], [154.801, -137.2, 'c'], [190.601, -133.4, 'c'], [208.801, -120.2], [208.801, -120.2, 'c'], [201.601, -128.6, 'c'], [183.201, -135.6], [183.201, -135.6, 'c'], [161.001, -148.2, 'c'], [125.801, -143.2], [125.801, -143.2, 'c'], [108.001, -140, 'c'], [100.201, -138.2], [100.201, -138.2, 'c'], [97.601, -138.8, 'c'], [97.001, -139.2], [96.401, -139.6, 'c'], [84.6, -148.6, 'c'], [57, -141.6], [57, -141.6, 'c'], [40, -137, 'c'], [31.4, -132.2], [31.4, -132.2, 'c'], [16.2, -131, 'c'], [12.6, -127.8], [12.6, -127.8, 'c'], [-6, -113.2, 'c'], [-8, -112.4], [-10, -111.6, 'c'], [-21.4, -104, 'c'], [-22.2, -103.6], [-22.2, -103.6, 'c'], [2.4, -110.2, 'c'], [4.8, -112.6], [7.2, -115, 'c'], [24.6, -117.6, 'c'], [27, -116.2], [29.4, -114.8, 'c'], [37.8, -115.4, 'c'], [28.2, -114.8], [28.2, -114.8, 'c'], [103.801, -100, 'c'], [104.601, -98], [105.401, -96, 'c'], [109.401, -97.2, 'c'], [109.401, -97.2]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[180.801, -106.4], [180.801, -106.4, 'c'], [170.601, -113.8, 'c'], [168.601, -113.8], [166.601, -113.8, 'c'], [154.201, -124, 'c'], [150.001, -123.6], [145.801, -123.2, 'c'], [133.601, -133.2, 'c'], [106.201, -125], [106.201, -125, 'c'], [105.601, -127, 'c'], [109.201, -127.8], [109.201, -127.8, 'c'], [115.601, -130, 'c'], [116.001, -130.6], [116.001, -130.6, 'c'], [136.201, -134.8, 'c'], [143.401, -131.2], [143.401, -131.2, 'c'], [152.601, -128.6, 'c'], [158.801, -122.4], [158.801, -122.4, 'c'], [170.001, -119.2, 'c'], [173.201, -120.2], [173.201, -120.2, 'c'], [182.001, -118, 'c'], [182.401, -116.2], [182.401, -116.2, 'c'], [188.201, -113.2, 'c'], [186.401, -110.6], [186.401, -110.6, 'c'], [186.801, -109, 'c'], [180.801, -106.4]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[168.33, -108.509], [169.137, -107.877, 'c'], [170.156, -107.779, 'c'], [170.761, -106.97], [170.995, -106.656, 'c'], [170.706, -106.33, 'c'], [170.391, -106.233], [169.348, -105.916, 'c'], [168.292, -106.486, 'c'], [167.15, -105.898], [166.748, -105.691, 'c'], [166.106, -105.873, 'c'], [165.553, -106.022], [163.921, -106.463, 'c'], [162.092, -106.488, 'c'], [160.401, -105.8], [158.416, -106.929, 'c'], [156.056, -106.345, 'c'], [153.975, -107.346], [153.917, -107.373, 'c'], [153.695, -107.027, 'c'], [153.621, -107.054], [150.575, -108.199, 'c'], [146.832, -107.916, 'c'], [144.401, -110.2], [141.973, -110.612, 'c'], [139.616, -111.074, 'c'], [137.188, -111.754], [135.37, -112.263, 'c'], [133.961, -113.252, 'c'], [132.341, -114.084], [130.964, -114.792, 'c'], [129.507, -115.314, 'c'], [127.973, -115.686], [126.11, -116.138, 'c'], [124.279, -116.026, 'c'], [122.386, -116.546], [122.293, -116.571, 'c'], [122.101, -116.227, 'c'], [122.019, -116.254], [121.695, -116.362, 'c'], [121.405, -116.945, 'c'], [121.234, -116.892], [119.553, -116.37, 'c'], [118.065, -117.342, 'c'], [116.401, -117], [115.223, -118.224, 'c'], [113.495, -117.979, 'c'], [111.949, -118.421], [108.985, -119.269, 'c'], [105.831, -117.999, 'c'], [102.801, -119], [106.914, -120.842, 'c'], [111.601, -119.61, 'c'], [115.663, -121.679], [117.991, -122.865, 'c'], [120.653, -121.763, 'c'], [123.223, -122.523], [123.71, -122.667, 'c'], [124.401, -122.869, 'c'], [124.801, -122.2], [124.935, -122.335, 'c'], [125.117, -122.574, 'c'], [125.175, -122.546], [127.625, -121.389, 'c'], [129.94, -120.115, 'c'], [132.422, -119.049], [132.763, -118.903, 'c'], [133.295, -119.135, 'c'], [133.547, -118.933], [135.067, -117.717, 'c'], [137.01, -117.82, 'c'], [138.401, -116.6], [140.099, -117.102, 'c'], [141.892, -116.722, 'c'], [143.621, -117.346], [143.698, -117.373, 'c'], [143.932, -117.032, 'c'], [143.965, -117.054], [145.095, -117.802, 'c'], [146.25, -117.531, 'c'], [147.142, -117.227], [147.48, -117.112, 'c'], [148.143, -116.865, 'c'], [148.448, -116.791], [149.574, -116.515, 'c'], [150.43, -116.035, 'c'], [151.609, -115.852], [151.723, -115.834, 'c'], [151.908, -116.174, 'c'], [151.98, -116.146], [153.103, -115.708, 'c'], [154.145, -115.764, 'c'], [154.801, -114.6], [154.936, -114.735, 'c'], [155.101, -114.973, 'c'], [155.183, -114.946], [156.21, -114.608, 'c'], [156.859, -113.853, 'c'], [157.96, -113.612], [158.445, -113.506, 'c'], [159.057, -112.88, 'c'], [159.633, -112.704], [162.025, -111.973, 'c'], [163.868, -110.444, 'c'], [166.062, -109.549], [166.821, -109.239, 'c'], [167.697, -109.005, 'c'], [168.33, -108.509]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[91.696, -122.739], [89.178, -124.464, 'c'], [86.81, -125.57, 'c'], [84.368, -127.356], [84.187, -127.489, 'c'], [83.827, -127.319, 'c'], [83.625, -127.441], [82.618, -128.05, 'c'], [81.73, -128.631, 'c'], [80.748, -129.327], [80.209, -129.709, 'c'], [79.388, -129.698, 'c'], [78.88, -129.956], [76.336, -131.248, 'c'], [73.707, -131.806, 'c'], [71.2, -133], [71.882, -133.638, 'c'], [73.004, -133.394, 'c'], [73.6, -134.2], [73.795, -133.92, 'c'], [74.033, -133.636, 'c'], [74.386, -133.827], [76.064, -134.731, 'c'], [77.914, -134.884, 'c'], [79.59, -134.794], [81.294, -134.702, 'c'], [83.014, -134.397, 'c'], [84.789, -134.125], [85.096, -134.078, 'c'], [85.295, -133.555, 'c'], [85.618, -133.458], [87.846, -132.795, 'c'], [90.235, -133.32, 'c'], [92.354, -132.482], [93.945, -131.853, 'c'], [95.515, -131.03, 'c'], [96.754, -129.755], [97.006, -129.495, 'c'], [96.681, -129.194, 'c'], [96.401, -129], [96.789, -129.109, 'c'], [97.062, -128.903, 'c'], [97.173, -128.59], [97.257, -128.351, 'c'], [97.257, -128.049, 'c'], [97.173, -127.81], [97.061, -127.498, 'c'], [96.782, -127.397, 'c'], [96.408, -127.346], [95.001, -127.156, 'c'], [96.773, -128.536, 'c'], [96.073, -128.088], [94.8, -127.274, 'c'], [95.546, -125.868, 'c'], [94.801, -124.6], [94.521, -124.794, 'c'], [94.291, -125.012, 'c'], [94.401, -125.4], [94.635, -124.878, 'c'], [94.033, -124.588, 'c'], [93.865, -124.272], [93.48, -123.547, 'c'], [92.581, -122.132, 'c'], [91.696, -122.739]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[59.198, -115.391], [56.044, -116.185, 'c'], [52.994, -116.07, 'c'], [49.978, -117.346], [49.911, -117.374, 'c'], [49.688, -117.027, 'c'], [49.624, -117.054], [48.258, -117.648, 'c'], [47.34, -118.614, 'c'], [46.264, -119.66], [45.351, -120.548, 'c'], [43.693, -120.161, 'c'], [42.419, -120.648], [42.095, -120.772, 'c'], [41.892, -121.284, 'c'], [41.591, -121.323], [40.372, -121.48, 'c'], [39.445, -122.429, 'c'], [38.4, -123], [40.736, -123.795, 'c'], [43.147, -123.764, 'c'], [45.609, -124.148], [45.722, -124.166, 'c'], [45.867, -123.845, 'c'], [46, -123.845], [46.136, -123.845, 'c'], [46.266, -124.066, 'c'], [46.4, -124.2], [46.595, -123.92, 'c'], [46.897, -123.594, 'c'], [47.154, -123.848], [47.702, -124.388, 'c'], [48.258, -124.198, 'c'], [48.798, -124.158], [48.942, -124.148, 'c'], [49.067, -123.845, 'c'], [49.2, -123.845], [49.336, -123.845, 'c'], [49.467, -124.156, 'c'], [49.6, -124.156], [49.736, -124.155, 'c'], [49.867, -123.845, 'c'], [50, -123.845], [50.136, -123.845, 'c'], [50.266, -124.066, 'c'], [50.4, -124.2], [51.092, -123.418, 'c'], [51.977, -123.972, 'c'], [52.799, -123.793], [53.837, -123.566, 'c'], [54.104, -122.418, 'c'], [55.178, -122.12], [59.893, -120.816, 'c'], [64.03, -118.671, 'c'], [68.393, -116.584], [68.7, -116.437, 'c'], [68.91, -116.189, 'c'], [68.8, -115.8], [69.067, -115.8, 'c'], [69.38, -115.888, 'c'], [69.57, -115.756], [70.628, -115.024, 'c'], [71.669, -114.476, 'c'], [72.366, -113.378], [72.582, -113.039, 'c'], [72.253, -112.632, 'c'], [72.02, -112.684], [67.591, -113.679, 'c'], [63.585, -114.287, 'c'], [59.198, -115.391]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[45.338, -71.179], [43.746, -72.398, 'c'], [43.162, -74.429, 'c'], [42.034, -76.221], [41.82, -76.561, 'c'], [42.094, -76.875, 'c'], [42.411, -76.964], [42.971, -77.123, 'c'], [43.514, -76.645, 'c'], [43.923, -76.443], [45.668, -75.581, 'c'], [47.203, -74.339, 'c'], [49.2, -74.2], [51.19, -71.966, 'c'], [55.45, -71.581, 'c'], [55.457, -68.2], [55.458, -67.341, 'c'], [54.03, -68.259, 'c'], [53.6, -67.4], [51.149, -68.403, 'c'], [48.76, -68.3, 'c'], [46.38, -69.767], [45.763, -70.148, 'c'], [46.093, -70.601, 'c'], [45.338, -71.179]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[17.8, -123.756], [17.935, -123.755, 'c'], [24.966, -123.522, 'c'], [24.949, -123.408], [24.904, -123.099, 'c'], [17.174, -122.05, 'c'], [16.81, -122.22], [16.646, -122.296, 'c'], [9.134, -119.866, 'c'], [9, -120], [9.268, -120.135, 'c'], [17.534, -123.756, 'c'], [17.8, -123.756]],  -closed => 1, -fillcolor => "#cc7226", -filled => 1, -linecolor => "#cc7226");

$zinc->add('curve',$top_group,[[33.2, -114], [33.2, -114, 'c'], [18.4, -112.2, 'c'], [14, -111], [9.6, -109.8, 'c'], [-9, -102.2, 'c'], [-12, -100.2], [-12, -100.2, 'c'], [-25.4, -94.8, 'c'], [-42.4, -74.8], [-42.4, -74.8, 'c'], [-34.8, -78.2, 'c'], [-32.6, -81], [-32.6, -81, 'c'], [-19, -93.6, 'c'], [-19.2, -91], [-19.2, -91, 'c'], [-7, -99.6, 'c'], [-7.6, -97.4], [-7.6, -97.4, 'c'], [16.8, -108.6, 'c'], [14.8, -105.4], [14.8, -105.4, 'c'], [36.4, -110, 'c'], [35.4, -108], [35.4, -108, 'c'], [54.2, -103.6, 'c'], [51.4, -103.4], [51.4, -103.4, 'c'], [45.6, -102.2, 'c'], [52, -98.6], [52, -98.6, 'c'], [48.6, -94.2, 'c'], [43.2, -98.2], [37.8, -102.2, 'c'], [40.8, -100, 'c'], [35.8, -99], [35.8, -99, 'c'], [33.2, -98.2, 'c'], [28.6, -102.2], [28.6, -102.2, 'c'], [23, -106.8, 'c'], [14.2, -103.2], [14.2, -103.2, 'c'], [-16.4, -90.6, 'c'], [-18.4, -90], [-18.4, -90, 'c'], [-22, -87.2, 'c'], [-24.4, -83.6], [-24.4, -83.6, 'c'], [-30.2, -79.2, 'c'], [-33.2, -77.8], [-33.2, -77.8, 'c'], [-46, -66.2, 'c'], [-47.2, -64.8], [-47.2, -64.8, 'c'], [-50.6, -59.6, 'c'], [-51.4, -59.2], [-51.4, -59.2, 'c'], [-45, -63, 'c'], [-43, -65], [-43, -65, 'c'], [-29, -75, 'c'], [-23.6, -75.8], [-23.6, -75.8, 'c'], [-19.2, -78.8, 'c'], [-18.4, -80.2], [-18.4, -80.2, 'c'], [-4, -89.4, 'c'], [0.2, -89.4], [0.2, -89.4, 'c'], [9.4, -84.2, 'c'], [11.8, -91.2], [11.8, -91.2, 'c'], [17.6, -93, 'c'], [23.2, -91.8], [23.2, -91.8, 'c'], [26.4, -94.4, 'c'], [25.6, -96.6], [25.6, -96.6, 'c'], [27.2, -98.4, 'c'], [28.2, -94.6], [28.2, -94.6, 'c'], [31.6, -91, 'c'], [36.4, -93], [36.4, -93, 'c'], [40.4, -93.2, 'c'], [38.4, -90.8], [38.4, -90.8, 'c'], [34, -87, 'c'], [22.2, -86.8], [22.2, -86.8, 'c'], [9.8, -86.2, 'c'], [-6.6, -78.6], [-6.6, -78.6, 'c'], [-36.4, -68.2, 'c'], [-45.6, -57.8], [-45.6, -57.8, 'c'], [-52, -49, 'c'], [-57.4, -47.8], [-57.4, -47.8, 'c'], [-63.2, -47, 'c'], [-69.2, -39.6], [-69.2, -39.6, 'c'], [-59.4, -45.4, 'c'], [-50.4, -45.4], [-50.4, -45.4, 'c'], [-46.4, -47.8, 'c'], [-50.2, -44.2], [-50.2, -44.2, 'c'], [-53.8, -36.6, 'c'], [-52.2, -31.2], [-52.2, -31.2, 'c'], [-52.8, -26, 'c'], [-53.6, -24.4], [-53.6, -24.4, 'c'], [-61.4, -11.6, 'c'], [-61.4, -9.2], [-61.4, -6.8, 'c'], [-60.2, 3, 'c'], [-59.8, 3.6], [-59.4, 4.2, 'c'], [-60.8, 2, 'c'], [-57, 4.4], [-53.2, 6.8, 'c'], [-50.4, 8.4, 'c'], [-49.6, 11.2], [-48.8, 14, 'c'], [-51.6, 5.8, 'c'], [-51.8, 4], [-52, 2.2, 'c'], [-56.2, -5, 'c'], [-55.4, -7.4], [-55.4, -7.4, 'c'], [-54.4, -6.4, 'c'], [-53.6, -5], [-53.6, -5, 'c'], [-54.2, -5.6, 'c'], [-53.6, -9.2], [-53.6, -9.2, 'c'], [-52.8, -14.4, 'c'], [-51.4, -17.6], [-50, -20.8, 'c'], [-48, -24.6, 'c'], [-47.6, -25.4], [-47.2, -26.2, 'c'], [-47.2, -32, 'c'], [-45.8, -29.4], [-42.4, -26.8], [-42.4, -26.8, 'c'], [-45.2, -29.4, 'c'], [-43, -31.6], [-43, -31.6, 'c'], [-44, -37.2, 'c'], [-42.2, -39.8], [-42.2, -39.8, 'c'], [-35.2, -48.2, 'c'], [-33.6, -49.2], [-32, -50.2, 'c'], [-33.4, -49.8, 'c'], [-33.4, -49.8], [-33.4, -49.8, 'c'], [-27.4, -54, 'c'], [-33.2, -52.4], [-33.2, -52.4, 'c'], [-37.2, -50.8, 'c'], [-40.2, -50.8], [-40.2, -50.8, 'c'], [-47.8, -48.8, 'c'], [-43.8, -53], [-39.8, -57.2, 'c'], [-29.8, -62.6, 'c'], [-26, -62.4], [-25.2, -60.8], [-14, -63.2], [-15.2, -62.4], [-15.2, -62.4, 'c'], [-15.4, -62.6, 'c'], [-11.2, -63], [-7, -63.4, 'c'], [-1.2, -62, 'c'], [0.2, -63.8], [1.6, -65.6, 'c'], [5, -66.6, 'c'], [4.6, -65.2], [4.2, -63.8, 'c'], [4, -61.8, 'c'], [4, -61.8], [4, -61.8, 'c'], [9, -67.6, 'c'], [8.4, -65.4], [7.8, -63.2, 'c'], [-0.4, -58, 'c'], [-1.8, -51.8], [8.6, -60], [12.2, -63], [12.2, -63, 'c'], [15.8, -60.8, 'c'], [16, -62.4], [16.2, -64, 'c'], [20.8, -69.8, 'c'], [22, -69.6], [23.2, -69.4, 'c'], [25.2, -72.2, 'c'], [25, -69.6], [24.8, -67, 'c'], [32.4, -61.6, 'c'], [32.4, -61.6], [32.4, -61.6, 'c'], [35.6, -63.4, 'c'], [37, -62], [38.4, -60.6, 'c'], [42.6, -81.8, 'c'], [42.6, -81.8], [67.6, -92.4], [111.201, -95.8], [94.201, -102.6], [33.2, -114]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[20.895, 54.407], [22.437, 55.87, 'c'], [49.4, 84.8, 'c'], [49.4, 84.8], [84.6, 121.401, 'c'], [56.6, 87.2, 'c'], [56.6, 87.2], [49, 82.4, 'c'], [39.8, 63.6, 'c'], [39.8, 63.6], [38.6, 60.8, 'c'], [53.8, 70.8, 'c'], [53.8, 70.8], [57.8, 71.6, 'c'], [71.4, 90.8, 'c'], [71.4, 90.8], [64.6, 88.4, 'c'], [69.4, 95.6, 'c'], [69.4, 95.6], [72.2, 97.6, 'c'], [92.601, 113.201, 'c'], [92.601, 113.201], [96.201, 117.201, 'c'], [100.201, 118.801, 'c'], [100.201, 118.801], [114.201, 113.601, 'c'], [107.801, 126.801, 'c'], [107.801, 126.801], [110.201, 133.601, 'c'], [115.801, 122.001, 'c'], [115.801, 122.001], [127.001, 105.2, 'c'], [110.601, 107.601, 'c'], [110.601, 107.601], [80.6, 110.401, 'c'], [73.8, 94.4, 'c'], [73.8, 94.4], [71.4, 92, 'c'], [80.2, 94.4, 'c'], [80.2, 94.4], [88.601, 96.4, 'c'], [73, 82, 'c'], [73, 82], [75.4, 82, 'c'], [84.6, 88.8, 'c'], [84.6, 88.8], [95.001, 98, 'c'], [97.001, 96, 'c'], [97.001, 96], [115.001, 87.2, 'c'], [125.401, 94.8, 'c'], [125.401, 94.8], [127.401, 96.4, 'c'], [121.801, 103.2, 'c'], [123.401, 108.401], [125.001, 113.601, 'c'], [129.801, 126.001, 'c'], [129.801, 126.001], [127.401, 127.601, 'c'], [127.801, 138.401, 'c'], [127.801, 138.401], [144.601, 161.601, 'c'], [135.001, 159.601, 'c'], [135.001, 159.601], [119.401, 159.201, 'c'], [134.201, 166.801, 'c'], [134.201, 166.801], [137.401, 168.801, 'c'], [146.201, 176.001, 'c'], [146.201, 176.001], [143.401, 174.801, 'c'], [141.801, 180.001, 'c'], [141.801, 180.001], [146.601, 184.001, 'c'], [143.801, 188.801, 'c'], [143.801, 188.801], [137.801, 190.001, 'c'], [136.601, 194.001, 'c'], [136.601, 194.001], [143.401, 202.001, 'c'], [133.401, 202.401, 'c'], [133.401, 202.401], [137.001, 206.801, 'c'], [132.201, 218.801, 'c'], [132.201, 218.801], [127.401, 218.801, 'c'], [121.001, 224.401, 'c'], [121.001, 224.401], [123.401, 229.201, 'c'], [113.001, 234.801, 'c'], [113.001, 234.801], [104.601, 236.401, 'c'], [107.401, 243.201, 'c'], [107.401, 243.201], [99.401, 249.201, 'c'], [97.001, 265.201, 'c'], [97.001, 265.201], [96.201, 275.601, 'c'], [93.801, 278.801, 'c'], [99.001, 276.801], [104.201, 274.801, 'c'], [103.401, 262.401, 'c'], [103.401, 262.401], [98.601, 246.801, 'c'], [141.401, 230.801, 'c'], [141.401, 230.801], [145.401, 229.201, 'c'], [146.201, 224.001, 'c'], [146.201, 224.001], [148.201, 224.401, 'c'], [157.001, 232.001, 'c'], [157.001, 232.001], [164.601, 243.201, 'c'], [165.001, 234.001, 'c'], [165.001, 234.001], [166.201, 230.401, 'c'], [164.601, 224.401, 'c'], [164.601, 224.401], [170.601, 202.801, 'c'], [156.601, 196.401, 'c'], [156.601, 196.401], [146.601, 162.801, 'c'], [160.601, 171.201, 'c'], [160.601, 171.201], [163.401, 176.801, 'c'], [174.201, 182.001, 'c'], [174.201, 182.001], [177.801, 179.601], [176.201, 174.801, 'c'], [184.601, 168.801, 'c'], [184.601, 168.801], [187.401, 175.201, 'c'], [193.401, 167.201, 'c'], [193.401, 167.201], [197.001, 142.801, 'c'], [209.401, 157.201, 'c'], [209.401, 157.201], [213.401, 158.401, 'c'], [214.601, 151.601, 'c'], [214.601, 151.601], [218.201, 141.201, 'c'], [214.601, 127.601, 'c'], [214.601, 127.601], [218.201, 127.201, 'c'], [227.801, 133.201, 'c'], [227.801, 133.201], [230.601, 129.601, 'c'], [221.401, 112.801, 'c'], [225.401, 115.201], [229.401, 117.601, 'c'], [233.801, 119.201, 'c'], [233.801, 119.201], [234.601, 117.201, 'c'], [224.601, 104.801, 'c'], [224.601, 104.801], [220.201, 102, 'c'], [215.001, 81.6, 'c'], [215.001, 81.6], [222.201, 85.2, 'c'], [212.201, 70, 'c'], [212.201, 70], [212.201, 66.8, 'c'], [218.201, 55.6, 'c'], [218.201, 55.6], [217.401, 48.8, 'c'], [218.201, 49.2, 'c'], [218.201, 49.2], [221.001, 50.4, 'c'], [229.001, 52, 'c'], [222.201, 45.6], [215.401, 39.2, 'c'], [223.001, 34.4, 'c'], [223.001, 34.4], [227.401, 31.6, 'c'], [213.801, 32, 'c'], [213.801, 32], [208.601, 27.6, 'c'], [209.001, 23.6, 'c'], [209.001, 23.6], [217.001, 25.6, 'c'], [202.601, 11.2, 'c'], [200.201, 7.6], [197.801, 4, 'c'], [207.401, -1.2, 'c'], [207.401, -1.2], [220.601, -4.8, 'c'], [209.001, -8, 'c'], [209.001, -8], [189.401, -7.6, 'c'], [200.201, -18.4, 'c'], [200.201, -18.4], [206.201, -18, 'c'], [204.601, -20.4, 'c'], [204.601, -20.4], [199.401, -21.6, 'c'], [189.801, -28, 'c'], [189.801, -28], [185.801, -31.6, 'c'], [189.401, -30.8, 'c'], [189.401, -30.8], [206.201, -29.6, 'c'], [177.401, -40.8, 'c'], [177.401, -40.8], [185.401, -40.8, 'c'], [167.401, -51.2, 'c'], [167.401, -51.2], [165.401, -52.8, 'c'], [162.201, -60.4, 'c'], [162.201, -60.4], [156.201, -65.6, 'c'], [151.401, -72.4, 'c'], [151.401, -72.4], [151.001, -76.8, 'c'], [146.201, -81.6, 'c'], [146.201, -81.6], [134.601, -95.2, 'c'], [129.001, -94.8, 'c'], [129.001, -94.8], [114.201, -98.4, 'c'], [109.001, -97.6, 'c'], [109.001, -97.6], [56.2, -93.2], [29.8, -80.4, 'c'], [37.6, -59.4, 'c'], [37.6, -59.4], [44, -51, 'c'], [53.2, -54.8, 'c'], [53.2, -54.8], [57.8, -61, 'c'], [69.4, -58.8, 'c'], [69.4, -58.8], [89.801, -55.6, 'c'], [87.201, -59.2, 'c'], [87.201, -59.2], [84.801, -63.8, 'c'], [68.6, -70, 'c'], [68.4, -70.6], [68.2, -71.2, 'c'], [59.4, -74.6, 'c'], [59.4, -74.6], [56.4, -75.8, 'c'], [52, -85, 'c'], [52, -85], [48.8, -88.4, 'c'], [64.6, -82.6, 'c'], [64.6, -82.6], [63.4, -81.6, 'c'], [70.8, -77.6, 'c'], [70.8, -77.6], [88.201, -78.6, 'c'], [98.801, -67.8, 'c'], [98.801, -67.8], [109.601, -51.2, 'c'], [109.801, -59.4, 'c'], [109.801, -59.4], [112.601, -68.8, 'c'], [100.801, -90, 'c'], [100.801, -90], [101.201, -92, 'c'], [109.401, -85.4, 'c'], [109.401, -85.4], [110.801, -87.4, 'c'], [111.601, -81.6, 'c'], [111.601, -81.6], [111.801, -79.2, 'c'], [115.601, -71.2, 'c'], [115.601, -71.2], [118.401, -58.2, 'c'], [122.001, -65.6, 'c'], [122.001, -65.6], [126.601, -56.2], [128.001, -53.6, 'c'], [122.001, -46, 'c'], [122.001, -46], [121.801, -43.2, 'c'], [122.601, -43.4, 'c'], [117.001, -35.8], [111.401, -28.2, 'c'], [114.801, -23.8, 'c'], [114.801, -23.8], [113.401, -17.2, 'c'], [122.201, -17.6, 'c'], [122.201, -17.6], [124.801, -15.4, 'c'], [128.201, -15.4, 'c'], [128.201, -15.4], [130.001, -13.4, 'c'], [132.401, -14, 'c'], [132.401, -14], [134.001, -17.8, 'c'], [140.201, -15.8, 'c'], [140.201, -15.8], [141.601, -18.2, 'c'], [149.801, -18.6, 'c'], [149.801, -18.6], [150.801, -21.2, 'c'], [151.201, -22.8, 'c'], [154.601, -23.4], [158.001, -24, 'c'], [133.401, -67, 'c'], [133.401, -67], [139.801, -67.8, 'c'], [131.601, -80.2, 'c'], [131.601, -80.2], [129.401, -86.8, 'c'], [140.801, -72.2, 'c'], [143.001, -70.8], [145.201, -69.4, 'c'], [146.201, -67.2, 'c'], [144.601, -67.4], [143.001, -67.6, 'c'], [141.201, -65.4, 'c'], [142.601, -65.2], [144.001, -65, 'c'], [157.001, -50, 'c'], [160.401, -39.8], [163.801, -29.6, 'c'], [169.801, -25.6, 'c'], [176.001, -19.6], [182.201, -13.6, 'c'], [181.401, 10.6, 'c'], [181.401, 10.6], [181.001, 19.4, 'c'], [187.001, 30, 'c'], [187.001, 30], [189.001, 33.8, 'c'], [184.801, 52, 'c'], [184.801, 52], [182.801, 54.2, 'c'], [184.201, 55, 'c'], [184.201, 55], [185.201, 56.2, 'c'], [192.001, 69.4, 'c'], [192.001, 69.4], [190.201, 69.2, 'c'], [193.801, 72.8, 'c'], [193.801, 72.8], [199.001, 78.8, 'c'], [192.601, 75.8, 'c'], [192.601, 75.8], [186.601, 74.2, 'c'], [193.601, 84, 'c'], [193.601, 84], [194.801, 85.8, 'c'], [185.801, 81.2, 'c'], [185.801, 81.2], [176.601, 80.6, 'c'], [188.201, 87.8, 'c'], [188.201, 87.8], [196.801, 95, 'c'], [185.401, 90.6, 'c'], [185.401, 90.6], [180.801, 88.8, 'c'], [184.001, 95.6, 'c'], [184.001, 95.6], [187.201, 97.2, 'c'], [204.401, 104.2, 'c'], [204.401, 104.2], [204.801, 108.001, 'c'], [201.801, 113.001, 'c'], [201.801, 113.001], [202.201, 117.001, 'c'], [200.001, 120.401, 'c'], [200.001, 120.401], [198.801, 128.601, 'c'], [198.201, 129.401, 'c'], [198.201, 129.401], [194.001, 129.601, 'c'], [186.601, 143.401, 'c'], [186.601, 143.401], [184.801, 146.001, 'c'], [174.601, 158.001, 'c'], [174.601, 158.001], [172.601, 165.001, 'c'], [154.601, 157.801, 'c'], [154.601, 157.801], [148.001, 161.201, 'c'], [150.001, 157.801, 'c'], [150.001, 157.801], [149.601, 155.601, 'c'], [154.401, 149.601, 'c'], [154.401, 149.601], [161.401, 147.001, 'c'], [158.801, 136.201, 'c'], [158.801, 136.201], [162.801, 134.801, 'c'], [151.601, 132.001, 'c'], [151.801, 130.801], [152.001, 129.601, 'c'], [157.801, 128.201, 'c'], [157.801, 128.201], [165.801, 126.201, 'c'], [161.401, 123.801, 'c'], [161.401, 123.801], [160.801, 119.801, 'c'], [163.801, 114.201, 'c'], [163.801, 114.201], [175.401, 113.401, 'c'], [163.801, 97.2, 'c'], [163.801, 97.2], [153.001, 89.6, 'c'], [152.001, 83.8, 'c'], [152.001, 83.8], [164.601, 75.6, 'c'], [156.401, 63.2, 'c'], [156.601, 59.6], [156.801, 56, 'c'], [158.001, 34.4, 'c'], [158.001, 34.4], [156.001, 28.2, 'c'], [153.001, 14.6, 'c'], [153.001, 14.6], [155.201, 9.4, 'c'], [162.601, -3.2, 'c'], [162.601, -3.2], [165.401, -7.4, 'c'], [174.201, -12.2, 'c'], [172.001, -15.2], [169.801, -18.2, 'c'], [162.001, -16.4, 'c'], [162.001, -16.4], [154.201, -17.8, 'c'], [154.801, -12.6, 'c'], [154.801, -12.6], [153.201, -11.6, 'c'], [152.401, -6.6, 'c'], [152.401, -6.6], [151.68, 1.333, 'c'], [142.801, 7.6, 'c'], [142.801, 7.6], [131.601, 13.8, 'c'], [140.801, 17.8, 'c'], [140.801, 17.8], [146.801, 24.4, 'c'], [137.001, 24.6, 'c'], [137.001, 24.6], [126.001, 22.8, 'c'], [134.201, 33, 'c'], [134.201, 33], [145.001, 45.8, 'c'], [142.001, 48.6, 'c'], [142.001, 48.6], [131.801, 49.6, 'c'], [144.401, 58.8, 'c'], [144.401, 58.8], [144.401, 58.8, 'c'], [143.601, 56.8, 'c'], [143.801, 58.6], [144.001, 60.4, 'c'], [147.001, 64.6, 'c'], [147.801, 66.6], [148.601, 68.6, 'c'], [144.601, 68.8, 'c'], [144.601, 68.8], [145.201, 78.4, 'c'], [129.801, 74.2, 'c'], [129.801, 74.2], [129.801, 74.2, 'c'], [129.801, 74.2, 'c'], [128.201, 74.4], [126.601, 74.6, 'c'], [115.401, 73.8, 'c'], [109.601, 71.6], [103.801, 69.4, 'c'], [97.001, 69.4, 'c'], [97.001, 69.4], [97.001, 69.4, 'c'], [93.001, 71.2, 'c'], [85.4, 71], [77.8, 70.8, 'c'], [69.8, 73.6, 'c'], [69.8, 73.6], [65.4, 73.2, 'c'], [74, 68.8, 'c'], [74.2, 69], [74.4, 69.2, 'c'], [80, 63.6, 'c'], [72, 64.2], [50.203, 65.835, 'c'], [39.4, 55.6, 'c'], [39.4, 55.6], [37.4, 54.2, 'c'], [34.8, 51.4, 'c'], [34.8, 51.4], [24.8, 49.4, 'c'], [36.2, 63.8, 'c'], [36.2, 63.8], [37.4, 65.2, 'c'], [36, 66.2, 'c'], [36, 66.2], [35.2, 64.6, 'c'], [27.4, 59.2, 'c'], [27.4, 59.2], [24.589, 58.227, 'c'], [23.226, 56.893, 'c'], [20.895, 54.407]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-3, 42.8], [-3, 42.8, 'c'], [8.6, 48.4, 'c'], [11.2, 51.2], [13.8, 54, 'c'], [27.8, 65.4, 'c'], [27.8, 65.4], [27.8, 65.4, 'c'], [22.4, 63.4, 'c'], [19.8, 61.6], [17.2, 59.8, 'c'], [6.4, 51.6, 'c'], [6.4, 51.6], [6.4, 51.6, 'c'], [2.6, 45.6, 'c'], [-3, 42.8]],  -closed => 1, -fillcolor => "#4c0000", -filled => 1, -linecolor => "#4c0000");

$zinc->add('curve',$top_group,[[-61.009, 11.603], [-60.672, 11.455, 'c'], [-61.196, 8.743, 'c'], [-61.4, 8.2], [-62.422, 5.474, 'c'], [-71.4, 4, 'c'], [-71.4, 4], [-71.627, 5.365, 'c'], [-71.682, 6.961, 'c'], [-71.576, 8.599], [-71.576, 8.599, 'c'], [-66.708, 14.118, 'c'], [-61.009, 11.603]],  -closed => 1, -fillcolor => "#99cc32", -filled => 1, -linecolor => "#99cc32");

$zinc->add('curve',$top_group,[[-61.009, 11.403], [-61.458, 11.561, 'c'], [-61.024, 8.669, 'c'], [-61.2, 8.2], [-62.222, 5.474, 'c'], [-71.4, 3.9, 'c'], [-71.4, 3.9], [-71.627, 5.265, 'c'], [-71.682, 6.861, 'c'], [-71.576, 8.499], [-71.576, 8.499, 'c'], [-67.308, 13.618, 'c'], [-61.009, 11.403]],  -closed => 1, -fillcolor => "#659900", -filled => 1, -linecolor => "#659900");

$zinc->add('curve',$top_group,[[-65.4, 11.546], [-66.025, 11.546, 'c'], [-66.531, 10.406, 'c'], [-66.531, 9], [-66.531, 7.595, 'c'], [-66.025, 6.455, 'c'], [-65.4, 6.455], [-64.775, 6.455, 'c'], [-64.268, 7.595, 'c'], [-64.268, 9], [-64.268, 10.406, 'c'], [-64.775, 11.546, 'c'], [-65.4, 11.546]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-65.4, 9]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-111, 109.601], [-111, 109.601, 'c'], [-116.6, 119.601, 'c'], [-91.8, 113.601], [-91.8, 113.601, 'c'], [-77.8, 112.401, 'c'], [-75.4, 110.001], [-74.2, 110.801, 'c'], [-65.834, 113.734, 'c'], [-63, 114.401], [-56.2, 116.001, 'c'], [-47.8, 106, 'c'], [-47.8, 106], [-47.8, 106, 'c'], [-43.2, 95.5, 'c'], [-40.4, 95.5], [-37.6, 95.5, 'c'], [-40.8, 97.1, 'c'], [-40.8, 97.1], [-40.8, 97.1, 'c'], [-47.4, 107.201, 'c'], [-47, 108.801], [-47, 108.801, 'c'], [-52.2, 128.801, 'c'], [-68.2, 129.601], [-68.2, 129.601, 'c'], [-84.35, 130.551, 'c'], [-83, 136.401], [-83, 136.401, 'c'], [-74.2, 134.001, 'c'], [-71.8, 136.401], [-71.8, 136.401, 'c'], [-61, 136.001, 'c'], [-69, 142.401], [-75.8, 154.001], [-75.8, 154.001, 'c'], [-75.66, 157.919, 'c'], [-85.8, 154.401], [-95.6, 151.001, 'c'], [-105.9, 138.101, 'c'], [-105.9, 138.101], [-105.9, 138.101, 'c'], [-121.85, 123.551, 'c'], [-111, 109.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-112.2, 113.601], [-112.2, 113.601, 'c'], [-114.2, 123.201, 'c'], [-77.4, 112.801], [-77.4, 112.801, 'c'], [-73, 112.801, 'c'], [-70.6, 113.601], [-68.2, 114.401, 'c'], [-56.2, 117.201, 'c'], [-54.2, 116.001], [-54.2, 116.001, 'c'], [-61.4, 129.601, 'c'], [-73, 128.001], [-73, 128.001, 'c'], [-86.2, 129.601, 'c'], [-85.8, 134.401], [-85.8, 134.401, 'c'], [-81.8, 141.601, 'c'], [-77, 144.001], [-77, 144.001, 'c'], [-74.2, 146.401, 'c'], [-74.6, 149.601], [-75, 152.801, 'c'], [-77.8, 154.401, 'c'], [-79.8, 155.201], [-81.8, 156.001, 'c'], [-85, 152.801, 'c'], [-86.6, 152.801], [-88.2, 152.801, 'c'], [-96.6, 146.401, 'c'], [-101, 141.601], [-105.4, 136.801, 'c'], [-113.8, 124.801, 'c'], [-113.4, 122.001], [-113, 119.201, 'c'], [-112.2, 113.601, 'c'], [-112.2, 113.601]],  -closed => 1, -fillcolor => "#e59999", -filled => 1, -linecolor => "#e59999");

$zinc->add('curve',$top_group,[[-109, 131.051], [-106.4, 135.001, 'c'], [-103.2, 139.201, 'c'], [-101, 141.601], [-96.6, 146.401, 'c'], [-88.2, 152.801, 'c'], [-86.6, 152.801], [-85, 152.801, 'c'], [-81.8, 156.001, 'c'], [-79.8, 155.201], [-77.8, 154.401, 'c'], [-75, 152.801, 'c'], [-74.6, 149.601], [-74.2, 146.401, 'c'], [-77, 144.001, 'c'], [-77, 144.001], [-80.066, 142.468, 'c'], [-82.806, 138.976, 'c'], [-84.385, 136.653], [-84.385, 136.653, 'c'], [-84.2, 139.201, 'c'], [-89.4, 138.401], [-94.6, 137.601, 'c'], [-99.8, 134.801, 'c'], [-101.4, 131.601], [-103, 128.401, 'c'], [-105.4, 126.001, 'c'], [-103.8, 129.601], [-102.2, 133.201, 'c'], [-99.8, 136.801, 'c'], [-98.2, 137.201], [-96.6, 137.601, 'c'], [-97, 138.801, 'c'], [-99.4, 138.401], [-101.8, 138.001, 'c'], [-104.6, 137.601, 'c'], [-109, 132.401]],  -closed => 1, -fillcolor => "#b26565", -filled => 1, -linecolor => "#b26565");

$zinc->add('curve',$top_group,[[-111.6, 110.001], [-111.6, 110.001, 'c'], [-109.8, 96.4, 'c'], [-108.6, 92.4], [-108.6, 92.4, 'c'], [-109.4, 85.6, 'c'], [-107, 81.4], [-104.6, 77.2, 'c'], [-102.6, 71, 'c'], [-99.6, 65.6], [-96.6, 60.2, 'c'], [-96.4, 56.2, 'c'], [-92.4, 54.6], [-88.4, 53, 'c'], [-82.4, 44.4, 'c'], [-79.6, 43.4], [-76.8, 42.4, 'c'], [-77, 43.2, 'c'], [-77, 43.2], [-77, 43.2, 'c'], [-70.2, 28.4, 'c'], [-56.6, 32.4], [-56.6, 32.4, 'c'], [-72.8, 29.6, 'c'], [-57, 20.2], [-57, 20.2, 'c'], [-61.8, 21.3, 'c'], [-58.5, 14.3], [-56.299, 9.632, 'c'], [-56.8, 16.4, 'c'], [-67.8, 28.2], [-67.8, 28.2, 'c'], [-72.8, 36.8, 'c'], [-78, 39.8], [-83.2, 42.8, 'c'], [-95.2, 49.8, 'c'], [-96.4, 53.6], [-97.6, 57.4, 'c'], [-100.8, 63.2, 'c'], [-102.8, 64.8], [-104.8, 66.4, 'c'], [-107.6, 70.6, 'c'], [-108, 74], [-108, 74, 'c'], [-109.2, 78, 'c'], [-110.6, 79.2], [-112, 80.4, 'c'], [-112.2, 83.6, 'c'], [-112.2, 85.6], [-112.2, 87.6, 'c'], [-114.2, 90.4, 'c'], [-114, 92.8], [-114, 92.8, 'c'], [-113.2, 111.801, 'c'], [-113.6, 113.801], [-111.6, 110.001]],  -closed => 1, -fillcolor => "#992600", -filled => 1, -linecolor => "#992600");

$zinc->add('curve',$top_group,[[-120.2, 114.601], [-120.2, 114.601, 'c'], [-122.2, 113.201, 'c'], [-126.6, 119.201], [-126.6, 119.201, 'c'], [-119.3, 152.201, 'c'], [-119.3, 153.601], [-119.3, 153.601, 'c'], [-118.2, 151.501, 'c'], [-119.5, 144.301], [-120.8, 137.101, 'c'], [-121.7, 124.401, 'c'], [-121.7, 124.401], [-120.2, 114.601]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[-98.6, 54], [-98.6, 54, 'c'], [-116.2, 57.2, 'c'], [-115.8, 86.4], [-116.6, 111.201], [-116.6, 111.201, 'c'], [-117.8, 85.6, 'c'], [-119, 84], [-120.2, 82.4, 'c'], [-116.2, 71.2, 'c'], [-119.4, 77.2], [-119.4, 77.2, 'c'], [-133.4, 91.2, 'c'], [-125.4, 112.401], [-125.4, 112.401, 'c'], [-123.9, 115.701, 'c'], [-126.9, 111.101], [-126.9, 111.101, 'c'], [-131.5, 98.5, 'c'], [-130.4, 92.1], [-130.4, 92.1, 'c'], [-130.2, 89.9, 'c'], [-128.3, 87.1], [-128.3, 87.1, 'c'], [-119.7, 75.4, 'c'], [-117, 73.1], [-117, 73.1, 'c'], [-115.2, 58.7, 'c'], [-99.8, 53.5], [-99.8, 53.5, 'c'], [-94.1, 51.2, 'c'], [-98.6, 54]],  -closed => 1, -fillcolor => "#992600", -filled => 1, -linecolor => "#992600");

$zinc->add('curve',$top_group,[[40.8, -12.2], [41.46, -12.554, 'c'], [41.451, -13.524, 'c'], [42.031, -13.697], [43.18, -14.041, 'c'], [43.344, -15.108, 'c'], [43.862, -15.892], [44.735, -17.211, 'c'], [44.928, -18.744, 'c'], [45.51, -20.235], [45.782, -20.935, 'c'], [45.809, -21.89, 'c'], [45.496, -22.55], [44.322, -25.031, 'c'], [43.62, -27.48, 'c'], [42.178, -29.906], [41.91, -30.356, 'c'], [41.648, -31.15, 'c'], [41.447, -31.748], [40.984, -33.132, 'c'], [39.727, -34.123, 'c'], [38.867, -35.443], [38.579, -35.884, 'c'], [39.104, -36.809, 'c'], [38.388, -36.893], [37.491, -36.998, 'c'], [36.042, -37.578, 'c'], [35.809, -36.552], [35.221, -33.965, 'c'], [36.232, -31.442, 'c'], [37.2, -29], [36.418, -28.308, 'c'], [36.752, -27.387, 'c'], [36.904, -26.62], [37.614, -23.014, 'c'], [36.416, -19.662, 'c'], [35.655, -16.188], [35.632, -16.084, 'c'], [35.974, -15.886, 'c'], [35.946, -15.824], [34.724, -13.138, 'c'], [33.272, -10.693, 'c'], [31.453, -8.312], [30.695, -7.32, 'c'], [29.823, -6.404, 'c'], [29.326, -5.341], [28.958, -4.554, 'c'], [28.55, -3.588, 'c'], [28.8, -2.6], [25.365, 0.18, 'c'], [23.115, 4.025, 'c'], [20.504, 7.871], [20.042, 8.551, 'c'], [20.333, 9.76, 'c'], [20.884, 10.029], [21.697, 10.427, 'c'], [22.653, 9.403, 'c'], [23.123, 8.557], [23.512, 7.859, 'c'], [23.865, 7.209, 'c'], [24.356, 6.566], [24.489, 6.391, 'c'], [24.31, 5.972, 'c'], [24.445, 5.851], [27.078, 3.504, 'c'], [28.747, 0.568, 'c'], [31.2, -1.8], [33.15, -2.129, 'c'], [34.687, -3.127, 'c'], [36.435, -4.14], [36.743, -4.319, 'c'], [37.267, -4.07, 'c'], [37.557, -4.265], [39.31, -5.442, 'c'], [39.308, -7.478, 'c'], [39.414, -9.388], [39.464, -10.272, 'c'], [39.66, -11.589, 'c'], [40.8, -12.2]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[31.959, -16.666], [32.083, -16.743, 'c'], [31.928, -17.166, 'c'], [32.037, -17.382], [32.199, -17.706, 'c'], [32.602, -17.894, 'c'], [32.764, -18.218], [32.873, -18.434, 'c'], [32.71, -18.814, 'c'], [32.846, -18.956], [35.179, -21.403, 'c'], [35.436, -24.427, 'c'], [34.4, -27.4], [35.424, -28.02, 'c'], [35.485, -29.282, 'c'], [35.06, -30.129], [34.207, -31.829, 'c'], [34.014, -33.755, 'c'], [33.039, -35.298], [32.237, -36.567, 'c'], [30.659, -37.811, 'c'], [29.288, -36.508], [28.867, -36.108, 'c'], [28.546, -35.321, 'c'], [28.824, -34.609], [28.888, -34.446, 'c'], [29.173, -34.3, 'c'], [29.146, -34.218], [29.039, -33.894, 'c'], [28.493, -33.67, 'c'], [28.487, -33.398], [28.457, -31.902, 'c'], [27.503, -30.391, 'c'], [28.133, -29.062], [28.905, -27.433, 'c'], [29.724, -25.576, 'c'], [30.4, -23.8], [29.166, -21.684, 'c'], [30.199, -19.235, 'c'], [28.446, -17.358], [28.31, -17.212, 'c'], [28.319, -16.826, 'c'], [28.441, -16.624], [28.733, -16.138, 'c'], [29.139, -15.732, 'c'], [29.625, -15.44], [29.827, -15.319, 'c'], [30.175, -15.317, 'c'], [30.375, -15.441], [30.953, -15.803, 'c'], [31.351, -16.29, 'c'], [31.959, -16.666]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[94.771, -26.977], [96.16, -25.185, 'c'], [96.45, -22.39, 'c'], [94.401, -21], [94.951, -17.691, 'c'], [98.302, -19.67, 'c'], [100.401, -20.2], [100.292, -20.588, 'c'], [100.519, -20.932, 'c'], [100.802, -20.937], [101.859, -20.952, 'c'], [102.539, -21.984, 'c'], [103.601, -21.8], [104.035, -23.357, 'c'], [105.673, -24.059, 'c'], [106.317, -25.439], [108.043, -29.134, 'c'], [107.452, -33.407, 'c'], [104.868, -36.653], [104.666, -36.907, 'c'], [104.883, -37.424, 'c'], [104.759, -37.786], [104.003, -39.997, 'c'], [101.935, -40.312, 'c'], [100.001, -41], [98.824, -44.875, 'c'], [98.163, -48.906, 'c'], [96.401, -52.6], [94.787, -52.85, 'c'], [94.089, -54.589, 'c'], [92.752, -55.309], [91.419, -56.028, 'c'], [90.851, -54.449, 'c'], [90.892, -53.403], [90.899, -53.198, 'c'], [91.351, -52.974, 'c'], [91.181, -52.609], [91.105, -52.445, 'c'], [90.845, -52.334, 'c'], [90.845, -52.2], [90.846, -52.065, 'c'], [91.067, -51.934, 'c'], [91.201, -51.8], [90.283, -50.98, 'c'], [88.86, -50.503, 'c'], [88.565, -49.358], [87.611, -45.648, 'c'], [90.184, -42.523, 'c'], [91.852, -39.322], [92.443, -38.187, 'c'], [91.707, -36.916, 'c'], [90.947, -35.708], [90.509, -35.013, 'c'], [90.617, -33.886, 'c'], [90.893, -33.03], [91.645, -30.699, 'c'], [93.236, -28.96, 'c'], [94.771, -26.977]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[57.611, -8.591], [56.124, -6.74, 'c'], [52.712, -4.171, 'c'], [55.629, -2.243], [55.823, -2.114, 'c'], [56.193, -2.11, 'c'], [56.366, -2.244], [58.387, -3.809, 'c'], [60.39, -4.712, 'c'], [62.826, -5.294], [62.95, -5.323, 'c'], [63.224, -4.856, 'c'], [63.593, -5.017], [65.206, -5.72, 'c'], [67.216, -5.662, 'c'], [68.4, -7], [72.167, -6.776, 'c'], [75.732, -7.892, 'c'], [79.123, -9.2], [80.284, -9.648, 'c'], [81.554, -10.207, 'c'], [82.755, -10.709], [84.131, -11.285, 'c'], [85.335, -12.213, 'c'], [86.447, -13.354], [86.58, -13.49, 'c'], [86.934, -13.4, 'c'], [87.201, -13.4], [87.161, -14.263, 'c'], [88.123, -14.39, 'c'], [88.37, -15.012], [88.462, -15.244, 'c'], [88.312, -15.64, 'c'], [88.445, -15.742], [90.583, -17.372, 'c'], [91.503, -19.39, 'c'], [90.334, -21.767], [90.049, -22.345, 'c'], [89.8, -22.963, 'c'], [89.234, -23.439], [88.149, -24.35, 'c'], [87.047, -23.496, 'c'], [86, -23.8], [85.841, -23.172, 'c'], [85.112, -23.344, 'c'], [84.726, -23.146], [83.867, -22.707, 'c'], [82.534, -23.292, 'c'], [81.675, -22.854], [80.313, -22.159, 'c'], [79.072, -21.99, 'c'], [77.65, -21.613], [77.338, -21.531, 'c'], [76.56, -21.627, 'c'], [76.4, -21], [76.266, -21.134, 'c'], [76.118, -21.368, 'c'], [76.012, -21.346], [74.104, -20.95, 'c'], [72.844, -20.736, 'c'], [71.543, -19.044], [71.44, -18.911, 'c'], [70.998, -19.09, 'c'], [70.839, -18.955], [69.882, -18.147, 'c'], [69.477, -16.913, 'c'], [68.376, -16.241], [68.175, -16.118, 'c'], [67.823, -16.286, 'c'], [67.629, -16.157], [66.983, -15.726, 'c'], [66.616, -15.085, 'c'], [65.974, -14.638], [65.645, -14.409, 'c'], [65.245, -14.734, 'c'], [65.277, -14.99], [65.522, -16.937, 'c'], [66.175, -18.724, 'c'], [65.6, -20.6], [67.677, -23.12, 'c'], [70.194, -25.069, 'c'], [72, -27.8], [72.015, -29.966, 'c'], [72.707, -32.112, 'c'], [72.594, -34.189], [72.584, -34.382, 'c'], [72.296, -35.115, 'c'], [72.17, -35.462], [71.858, -36.316, 'c'], [72.764, -37.382, 'c'], [71.92, -38.106], [70.516, -39.309, 'c'], [69.224, -38.433, 'c'], [68.4, -37], [66.562, -36.61, 'c'], [64.496, -35.917, 'c'], [62.918, -37.151], [61.911, -37.938, 'c'], [61.333, -38.844, 'c'], [60.534, -39.9], [59.549, -41.202, 'c'], [59.884, -42.638, 'c'], [59.954, -44.202], [59.96, -44.33, 'c'], [59.645, -44.466, 'c'], [59.645, -44.6], [59.646, -44.735, 'c'], [59.866, -44.866, 'c'], [60, -45], [59.294, -45.626, 'c'], [59.019, -46.684, 'c'], [58, -47], [58.305, -48.092, 'c'], [57.629, -48.976, 'c'], [56.758, -49.278], [54.763, -49.969, 'c'], [53.086, -48.057, 'c'], [51.194, -47.984], [50.68, -47.965, 'c'], [50.213, -49.003, 'c'], [49.564, -49.328], [49.132, -49.544, 'c'], [48.428, -49.577, 'c'], [48.066, -49.311], [47.378, -48.807, 'c'], [46.789, -48.693, 'c'], [46.031, -48.488], [44.414, -48.052, 'c'], [43.136, -46.958, 'c'], [41.656, -46.103], [40.171, -45.246, 'c'], [39.216, -43.809, 'c'], [38.136, -42.489], [37.195, -41.337, 'c'], [37.059, -38.923, 'c'], [38.479, -38.423], [40.322, -37.773, 'c'], [41.626, -40.476, 'c'], [43.592, -40.15], [43.904, -40.099, 'c'], [44.11, -39.788, 'c'], [44, -39.4], [44.389, -39.291, 'c'], [44.607, -39.52, 'c'], [44.8, -39.8], [45.658, -38.781, 'c'], [46.822, -38.444, 'c'], [47.76, -37.571], [48.73, -36.667, 'c'], [50.476, -37.085, 'c'], [51.491, -36.088], [53.02, -34.586, 'c'], [52.461, -31.905, 'c'], [54.4, -30.6], [53.814, -29.287, 'c'], [53.207, -28.01, 'c'], [52.872, -26.583], [52.59, -25.377, 'c'], [53.584, -24.18, 'c'], [54.795, -24.271], [56.053, -24.365, 'c'], [56.315, -25.124, 'c'], [56.8, -26.2], [57.067, -25.933, 'c'], [57.536, -25.636, 'c'], [57.495, -25.42], [57.038, -23.033, 'c'], [56.011, -21.04, 'c'], [55.553, -18.609], [55.494, -18.292, 'c'], [55.189, -18.09, 'c'], [54.8, -18.2], [54.332, -14.051, 'c'], [50.28, -11.657, 'c'], [47.735, -8.492], [47.332, -7.99, 'c'], [47.328, -6.741, 'c'], [47.737, -6.338], [49.14, -4.951, 'c'], [51.1, -6.497, 'c'], [52.8, -7], [53.013, -8.206, 'c'], [53.872, -9.148, 'c'], [55.204, -9.092], [55.46, -9.082, 'c'], [55.695, -9.624, 'c'], [56.019, -9.754], [56.367, -9.892, 'c'], [56.869, -9.668, 'c'], [57.155, -9.866], [58.884, -11.061, 'c'], [60.292, -12.167, 'c'], [62.03, -13.356], [62.222, -13.487, 'c'], [62.566, -13.328, 'c'], [62.782, -13.436], [63.107, -13.598, 'c'], [63.294, -13.985, 'c'], [63.617, -14.17], [63.965, -14.37, 'c'], [64.207, -14.08, 'c'], [64.4, -13.8], [63.754, -13.451, 'c'], [63.75, -12.494, 'c'], [63.168, -12.292], [62.393, -12.024, 'c'], [61.832, -11.511, 'c'], [61.158, -11.064], [60.866, -10.871, 'c'], [60.207, -11.119, 'c'], [60.103, -10.94], [59.505, -9.912, 'c'], [58.321, -9.474, 'c'], [57.611, -8.591]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[2.2, -58], [2.2, -58, 'c'], [-7.038, -60.872, 'c'], [-18.2, -35.2], [-18.2, -35.2, 'c'], [-20.6, -30, 'c'], [-23, -28], [-25.4, -26, 'c'], [-36.6, -22.4, 'c'], [-38.6, -18.4], [-49, -2.4], [-49, -2.4, 'c'], [-34.2, -18.4, 'c'], [-31, -20.8], [-31, -20.8, 'c'], [-23, -29.2, 'c'], [-26.2, -22.4], [-26.2, -22.4, 'c'], [-40.2, -11.6, 'c'], [-39, -2.4], [-39, -2.4, 'c'], [-44.6, 12, 'c'], [-45.4, 14], [-45.4, 14, 'c'], [-29.4, -18, 'c'], [-27, -19.2], [-24.6, -20.4, 'c'], [-23.4, -20.4, 'c'], [-24.6, -16.8], [-25.8, -13.2, 'c'], [-26.2, 3.2, 'c'], [-29, 5.2], [-29, 5.2, 'c'], [-21, -15.2, 'c'], [-21.8, -18.4], [-21.8, -18.4, 'c'], [-18.6, -22, 'c'], [-16.2, -16.8], [-17.4, -0.8], [-13, 11.2], [-13, 11.2, 'c'], [-15.4, 0, 'c'], [-13.8, -15.6], [-13.8, -15.6, 'c'], [-15.8, -26, 'c'], [-11.8, -20.4], [-7.8, -14.8, 'c'], [1.8, -8.8, 'c'], [1.8, -4], [1.8, -4, 'c'], [-3.4, -21.6, 'c'], [-12.6, -26.4], [-16.6, -20.4], [-17.8, -22.4], [-17.8, -22.4, 'c'], [-21.4, -23.2, 'c'], [-17, -30], [-12.6, -36.8, 'c'], [-13, -37.6, 'c'], [-13, -37.6], [-13, -37.6, 'c'], [-6.6, -30.4, 'c'], [-5, -30.4], [-5, -30.4, 'c'], [8.2, -38, 'c'], [9.4, -13.6], [9.4, -13.6, 'c'], [16.2, -28, 'c'], [7, -34.8], [7, -34.8, 'c'], [-7.8, -36.8, 'c'], [-6.6, -42], [0.6, -54.4], [4.2, -59.6, 'c'], [2.6, -56.8, 'c'], [2.6, -56.8]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-17.8, -41.6], [-17.8, -41.6, 'c'], [-30.6, -41.6, 'c'], [-33.8, -36.4], [-41, -26.8], [-41, -26.8, 'c'], [-23.8, -36.8, 'c'], [-19.8, -38], [-15.8, -39.2, 'c'], [-17.8, -41.6, 'c'], [-17.8, -41.6]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-57.8, -35.2], [-57.8, -35.2, 'c'], [-59.8, -34, 'c'], [-60.2, -31.2], [-60.6, -28.4, 'c'], [-63, -28, 'c'], [-62.2, -25.2], [-61.4, -22.4, 'c'], [-59.4, -20, 'c'], [-59.4, -24], [-59.4, -28, 'c'], [-57.8, -30, 'c'], [-57, -31.2], [-56.2, -32.4, 'c'], [-54.6, -36.8, 'c'], [-57.8, -35.2]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-66.6, 26], [-66.6, 26, 'c'], [-75, 22, 'c'], [-78.2, 18.4], [-81.4, 14.8, 'c'], [-80.948, 19.966, 'c'], [-85.8, 19.6], [-91.647, 19.159, 'c'], [-90.6, 3.2, 'c'], [-90.6, 3.2], [-94.6, 10.8], [-94.6, 10.8, 'c'], [-95.8, 25.2, 'c'], [-87.8, 22.8], [-83.893, 21.628, 'c'], [-82.6, 23.2, 'c'], [-84.2, 24], [-85.8, 24.8, 'c'], [-78.6, 25.2, 'c'], [-81.4, 26.8], [-84.2, 28.4, 'c'], [-69.8, 23.2, 'c'], [-72.2, 33.6], [-66.6, 26]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-79.2, 40.4], [-79.2, 40.4, 'c'], [-94.6, 44.8, 'c'], [-98.2, 35.2], [-98.2, 35.2, 'c'], [-103, 37.6, 'c'], [-100.8, 40.6], [-98.6, 43.6, 'c'], [-97.4, 44, 'c'], [-97.4, 44], [-97.4, 44, 'c'], [-92, 45.2, 'c'], [-92.6, 46], [-93.2, 46.8, 'c'], [-95.6, 50.2, 'c'], [-95.6, 50.2], [-95.6, 50.2, 'c'], [-85.4, 44.2, 'c'], [-79.2, 40.4]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[149.201, 118.601], [148.774, 120.735, 'c'], [147.103, 121.536, 'c'], [145.201, 122.201], [143.284, 121.243, 'c'], [140.686, 118.137, 'c'], [138.801, 120.201], [138.327, 119.721, 'c'], [137.548, 119.661, 'c'], [137.204, 118.999], [136.739, 118.101, 'c'], [137.011, 117.055, 'c'], [136.669, 116.257], [136.124, 114.985, 'c'], [135.415, 113.619, 'c'], [135.601, 112.201], [137.407, 111.489, 'c'], [138.002, 109.583, 'c'], [137.528, 107.82], [137.459, 107.563, 'c'], [137.03, 107.366, 'c'], [137.23, 107.017], [137.416, 106.694, 'c'], [137.734, 106.467, 'c'], [138.001, 106.2], [137.866, 106.335, 'c'], [137.721, 106.568, 'c'], [137.61, 106.548], [137, 106.442, 'c'], [137.124, 105.805, 'c'], [137.254, 105.418], [137.839, 103.672, 'c'], [139.853, 103.408, 'c'], [141.201, 104.6], [141.457, 104.035, 'c'], [141.966, 104.229, 'c'], [142.401, 104.2], [142.351, 103.621, 'c'], [142.759, 103.094, 'c'], [142.957, 102.674], [143.475, 101.576, 'c'], [145.104, 102.682, 'c'], [145.901, 102.07], [146.977, 101.245, 'c'], [148.04, 100.546, 'c'], [149.118, 101.149], [150.927, 102.162, 'c'], [152.636, 103.374, 'c'], [153.835, 105.115], [154.41, 105.949, 'c'], [154.65, 107.23, 'c'], [154.592, 108.188], [154.554, 108.835, 'c'], [153.173, 108.483, 'c'], [152.83, 109.412], [152.185, 111.16, 'c'], [154.016, 111.679, 'c'], [154.772, 113.017], [154.97, 113.366, 'c'], [154.706, 113.67, 'c'], [154.391, 113.768], [153.98, 113.896, 'c'], [153.196, 113.707, 'c'], [153.334, 114.16], [154.306, 117.353, 'c'], [151.55, 118.031, 'c'], [149.201, 118.601]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[139.6, 138.201], [139.593, 136.463, 'c'], [137.992, 134.707, 'c'], [139.201, 133.001], [139.336, 133.135, 'c'], [139.467, 133.356, 'c'], [139.601, 133.356], [139.736, 133.356, 'c'], [139.867, 133.135, 'c'], [140.001, 133.001], [141.496, 135.217, 'c'], [145.148, 136.145, 'c'], [145.006, 138.991], [144.984, 139.438, 'c'], [143.897, 140.356, 'c'], [144.801, 141.001], [142.988, 142.349, 'c'], [142.933, 144.719, 'c'], [142.001, 146.601], [140.763, 146.315, 'c'], [139.551, 145.952, 'c'], [138.401, 145.401], [138.753, 143.915, 'c'], [138.636, 142.231, 'c'], [139.456, 140.911], [139.89, 140.213, 'c'], [139.603, 139.134, 'c'], [139.6, 138.201]],  -closed => 1, -fillcolor => "#ffffff", -filled => 1, -linecolor => "#ffffff");

$zinc->add('curve',$top_group,[[-26.6, 129.201], [-26.6, 129.201, 'c'], [-43.458, 139.337, 'c'], [-29.4, 124.001], [-20.6, 114.401, 'c'], [-10.6, 108.801, 'c'], [-10.6, 108.801], [-10.6, 108.801, 'c'], [-0.2, 104.4, 'c'], [3.4, 103.2], [7, 102, 'c'], [22.2, 96.8, 'c'], [25.4, 96.4], [28.6, 96, 'c'], [38.2, 92, 'c'], [45, 96], [51.8, 100, 'c'], [59.8, 104.4, 'c'], [59.8, 104.4], [59.8, 104.4, 'c'], [43.4, 96, 'c'], [39.8, 98.4], [36.2, 100.8, 'c'], [29, 100.4, 'c'], [23, 103.6], [23, 103.6, 'c'], [8.2, 108.001, 'c'], [5, 110.001], [1.8, 112.001, 'c'], [-8.6, 123.601, 'c'], [-10.2, 122.801], [-11.8, 122.001, 'c'], [-9.8, 121.601, 'c'], [-8.6, 118.801], [-7.4, 116.001, 'c'], [-9.4, 114.401, 'c'], [-17.4, 120.801], [-25.4, 127.201, 'c'], [-26.6, 129.201, 'c'], [-26.6, 129.201]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-19.195, 123.234], [-19.195, 123.234, 'c'], [-17.785, 110.194, 'c'], [-9.307, 111.859], [-9.307, 111.859, 'c'], [-1.081, 107.689, 'c'], [1.641, 105.721], [1.641, 105.721, 'c'], [9.78, 104.019, 'c'], [11.09, 103.402], [29.569, 94.702, 'c'], [44.288, 99.221, 'c'], [44.835, 98.101], [45.381, 96.982, 'c'], [65.006, 104.099, 'c'], [68.615, 108.185], [69.006, 108.628, 'c'], [58.384, 102.588, 'c'], [48.686, 100.697], [40.413, 99.083, 'c'], [18.811, 100.944, 'c'], [7.905, 106.48], [4.932, 107.989, 'c'], [-4.013, 113.773, 'c'], [-6.544, 113.662], [-9.075, 113.55, 'c'], [-19.195, 123.234, 'c'], [-19.195, 123.234]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-23, 148.801], [-23, 148.801, 'c'], [-38.2, 146.401, 'c'], [-21.4, 144.801], [-21.4, 144.801, 'c'], [-3.4, 142.801, 'c'], [0.6, 137.601], [0.6, 137.601, 'c'], [14.2, 128.401, 'c'], [17, 128.001], [19.8, 127.601, 'c'], [49.8, 120.401, 'c'], [50.2, 118.001], [50.6, 115.601, 'c'], [56.2, 115.601, 'c'], [57.8, 116.401], [59.4, 117.201, 'c'], [58.6, 118.401, 'c'], [55.8, 119.201], [53, 120.001, 'c'], [21.8, 136.401, 'c'], [15.4, 137.601], [9, 138.801, 'c'], [-2.6, 146.401, 'c'], [-7.4, 147.601], [-12.2, 148.801, 'c'], [-23, 148.801, 'c'], [-23, 148.801]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-3.48, 141.403], [-3.48, 141.403, 'c'], [-12.062, 140.574, 'c'], [-3.461, 139.755], [-3.461, 139.755, 'c'], [5.355, 136.331, 'c'], [7.403, 133.668], [7.403, 133.668, 'c'], [14.367, 128.957, 'c'], [15.8, 128.753], [17.234, 128.548, 'c'], [31.194, 124.861, 'c'], [31.399, 123.633], [31.604, 122.404, 'c'], [65.67, 109.823, 'c'], [70.09, 113.013], [73.001, 115.114, 'c'], [63.1, 113.437, 'c'], [53.466, 117.847], [52.111, 118.467, 'c'], [18.258, 133.054, 'c'], [14.981, 133.668], [11.704, 134.283, 'c'], [5.765, 138.174, 'c'], [3.307, 138.788], [0.85, 139.403, 'c'], [-3.48, 141.403, 'c'], [-3.48, 141.403]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-11.4, 143.601], [-11.4, 143.601, 'c'], [-6.2, 143.201, 'c'], [-7.4, 144.801], [-8.6, 146.401, 'c'], [-11, 145.601, 'c'], [-11, 145.601], [-11.4, 143.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-18.6, 145.201], [-18.6, 145.201, 'c'], [-13.4, 144.801, 'c'], [-14.6, 146.401], [-15.8, 148.001, 'c'], [-18.2, 147.201, 'c'], [-18.2, 147.201], [-18.6, 145.201]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-29, 146.801], [-29, 146.801, 'c'], [-23.8, 146.401, 'c'], [-25, 148.001], [-26.2, 149.601, 'c'], [-28.6, 148.801, 'c'], [-28.6, 148.801], [-29, 146.801]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-36.6, 147.601], [-36.6, 147.601, 'c'], [-31.4, 147.201, 'c'], [-32.6, 148.801], [-33.8, 150.401, 'c'], [-36.2, 149.601, 'c'], [-36.2, 149.601], [-36.6, 147.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[1.8, 108.001], [1.8, 108.001, 'c'], [6.2, 108.001, 'c'], [5, 109.601], [3.8, 111.201, 'c'], [0.6, 110.801, 'c'], [0.6, 110.801], [1.8, 108.001]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-8.2, 113.601], [-8.2, 113.601, 'c'], [-1.694, 111.46, 'c'], [-4.2, 114.801], [-5.4, 116.401, 'c'], [-7.8, 115.601, 'c'], [-7.8, 115.601], [-8.2, 113.601]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-19.4, 118.401], [-19.4, 118.401, 'c'], [-14.2, 118.001, 'c'], [-15.4, 119.601], [-16.6, 121.201, 'c'], [-19, 120.401, 'c'], [-19, 120.401], [-19.4, 118.401]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-27, 124.401], [-27, 124.401, 'c'], [-21.8, 124.001, 'c'], [-23, 125.601], [-24.2, 127.201, 'c'], [-26.6, 126.401, 'c'], [-26.6, 126.401], [-27, 124.401]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-33.8, 129.201], [-33.8, 129.201, 'c'], [-28.6, 128.801, 'c'], [-29.8, 130.401], [-31, 132.001, 'c'], [-33.4, 131.201, 'c'], [-33.4, 131.201], [-33.8, 129.201]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[5.282, 135.598], [5.282, 135.598, 'c'], [12.203, 135.066, 'c'], [10.606, 137.195], [9.009, 139.325, 'c'], [5.814, 138.26, 'c'], [5.814, 138.26], [5.282, 135.598]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[15.682, 130.798], [15.682, 130.798, 'c'], [22.603, 130.266, 'c'], [21.006, 132.395], [19.409, 134.525, 'c'], [16.214, 133.46, 'c'], [16.214, 133.46], [15.682, 130.798]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[26.482, 126.398], [26.482, 126.398, 'c'], [33.403, 125.866, 'c'], [31.806, 127.995], [30.209, 130.125, 'c'], [27.014, 129.06, 'c'], [27.014, 129.06], [26.482, 126.398]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[36.882, 121.598], [36.882, 121.598, 'c'], [43.803, 121.066, 'c'], [42.206, 123.195], [40.609, 125.325, 'c'], [37.414, 124.26, 'c'], [37.414, 124.26], [36.882, 121.598]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[9.282, 103.598], [9.282, 103.598, 'c'], [16.203, 103.066, 'c'], [14.606, 105.195], [13.009, 107.325, 'c'], [9.014, 107.06, 'c'], [9.014, 107.06], [9.282, 103.598]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[19.282, 100.398], [19.282, 100.398, 'c'], [26.203, 99.866, 'c'], [24.606, 101.995], [23.009, 104.125, 'c'], [18.614, 103.86, 'c'], [18.614, 103.86], [19.282, 100.398]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-3.4, 140.401], [-3.4, 140.401, 'c'], [1.8, 140.001, 'c'], [0.6, 141.601], [-0.6, 143.201, 'c'], [-3, 142.401, 'c'], [-3, 142.401], [-3.4, 140.401]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-76.6, 41.2], [-76.6, 41.2, 'c'], [-81, 50, 'c'], [-81.4, 53.2], [-81.4, 53.2, 'c'], [-80.6, 44.4, 'c'], [-79.4, 42.4], [-78.2, 40.4, 'c'], [-76.6, 41.2, 'c'], [-76.6, 41.2]],  -closed => 1, -fillcolor => "#992600", -filled => 1, -linecolor => "#992600");

$zinc->add('curve',$top_group,[[-95, 55.2], [-95, 55.2, 'c'], [-98.2, 69.6, 'c'], [-97.8, 72.4], [-97.8, 72.4, 'c'], [-99, 60.8, 'c'], [-98.6, 59.6], [-98.2, 58.4, 'c'], [-95, 55.2, 'c'], [-95, 55.2]],  -closed => 1, -fillcolor => "#992600", -filled => 1, -linecolor => "#992600");

$zinc->add('curve',$top_group,[[-74.2, -19.4], [-74.4, -16.2], [-76.6, -16], [-76.6, -16, 'c'], [-62.4, -3.4, 'c'], [-61.8, 4.2], [-61.8, 4.2, 'c'], [-61, -4, 'c'], [-74.2, -19.4]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-70.216, -18.135], [-70.647, -18.551, 'c'], [-70.428, -19.296, 'c'], [-70.836, -19.556], [-71.645, -20.072, 'c'], [-69.538, -20.129, 'c'], [-69.766, -20.845], [-70.149, -22.051, 'c'], [-69.962, -22.072, 'c'], [-70.084, -23.348], [-70.141, -23.946, 'c'], [-69.553, -25.486, 'c'], [-69.168, -25.926], [-67.722, -27.578, 'c'], [-69.046, -30.51, 'c'], [-67.406, -32.061], [-67.102, -32.35, 'c'], [-66.726, -32.902, 'c'], [-66.441, -33.32], [-65.782, -34.283, 'c'], [-64.598, -34.771, 'c'], [-63.648, -35.599], [-63.33, -35.875, 'c'], [-63.531, -36.702, 'c'], [-62.962, -36.61], [-62.248, -36.495, 'c'], [-61.007, -36.625, 'c'], [-61.052, -35.784], [-61.165, -33.664, 'c'], [-62.494, -31.944, 'c'], [-63.774, -30.276], [-63.323, -29.572, 'c'], [-63.781, -28.937, 'c'], [-64.065, -28.38], [-65.4, -25.76, 'c'], [-65.211, -22.919, 'c'], [-65.385, -20.079], [-65.39, -19.994, 'c'], [-65.697, -19.916, 'c'], [-65.689, -19.863], [-65.336, -17.528, 'c'], [-64.752, -15.329, 'c'], [-63.873, -13.1], [-63.507, -12.17, 'c'], [-63.036, -11.275, 'c'], [-62.886, -10.348], [-62.775, -9.662, 'c'], [-62.672, -8.829, 'c'], [-63.08, -8.124], [-61.045, -5.234, 'c'], [-62.354, -2.583, 'c'], [-61.185, 0.948], [-60.978, 1.573, 'c'], [-59.286, 3.487, 'c'], [-59.749, 3.326], [-62.262, 2.455, 'c'], [-62.374, 2.057, 'c'], [-62.551, 1.304], [-62.697, 0.681, 'c'], [-63.027, -0.696, 'c'], [-63.264, -1.298], [-63.328, -1.462, 'c'], [-63.499, -3.346, 'c'], [-63.577, -3.468], [-65.09, -5.85, 'c'], [-63.732, -5.674, 'c'], [-65.102, -8.032], [-66.53, -8.712, 'c'], [-67.496, -9.816, 'c'], [-68.619, -10.978], [-68.817, -11.182, 'c'], [-67.674, -11.906, 'c'], [-67.855, -12.119], [-68.947, -13.408, 'c'], [-70.1, -14.175, 'c'], [-69.764, -15.668], [-69.609, -16.358, 'c'], [-69.472, -17.415, 'c'], [-70.216, -18.135]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-73.8, -16.4], [-73.8, -16.4, 'c'], [-73.4, -9.6, 'c'], [-71, -8], [-68.6, -6.4, 'c'], [-69.8, -7.2, 'c'], [-73, -8.4], [-76.2, -9.6, 'c'], [-75, -10.4, 'c'], [-75, -10.4], [-75, -10.4, 'c'], [-77.8, -10, 'c'], [-75.4, -8], [-73, -6, 'c'], [-69.4, -3.6, 'c'], [-71, -3.6], [-72.6, -3.6, 'c'], [-80.2, -7.6, 'c'], [-80.2, -10.4], [-80.2, -13.2, 'c'], [-81.2, -17.3, 'c'], [-81.2, -17.3], [-81.2, -17.3, 'c'], [-80.1, -18.1, 'c'], [-75.3, -18], [-75.3, -18, 'c'], [-73.9, -17.3, 'c'], [-73.8, -16.4]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-74.6, 2.2], [-74.6, 2.2, 'c'], [-83.12, -0.591, 'c'], [-101.6, 2.8], [-101.6, 2.8, 'c'], [-92.569, 0.722, 'c'], [-73.8, 3], [-63.5, 4.25, 'c'], [-74.6, 2.2, 'c'], [-74.6, 2.2]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-72.502, 2.129], [-72.502, 2.129, 'c'], [-80.748, -1.389, 'c'], [-99.453, 0.392], [-99.453, 0.392, 'c'], [-90.275, -0.897, 'c'], [-71.774, 2.995], [-61.62, 5.131, 'c'], [-72.502, 2.129, 'c'], [-72.502, 2.129]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-70.714, 2.222], [-70.714, 2.222, 'c'], [-78.676, -1.899, 'c'], [-97.461, -1.514], [-97.461, -1.514, 'c'], [-88.213, -2.118, 'c'], [-70.052, 3.14], [-60.086, 6.025, 'c'], [-70.714, 2.222, 'c'], [-70.714, 2.222]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-69.444, 2.445], [-69.444, 2.445, 'c'], [-76.268, -1.862, 'c'], [-93.142, -2.96], [-93.142, -2.96, 'c'], [-84.803, -2.79, 'c'], [-68.922, 3.319], [-60.206, 6.672, 'c'], [-69.444, 2.445, 'c'], [-69.444, 2.445]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[45.84, 12.961], [45.84, 12.961, 'c'], [44.91, 13.605, 'c'], [45.124, 12.424], [45.339, 11.243, 'c'], [73.547, -1.927, 'c'], [77.161, -1.677], [77.161, -1.677, 'c'], [46.913, 11.529, 'c'], [45.84, 12.961]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[42.446, 13.6], [42.446, 13.6, 'c'], [41.57, 14.315, 'c'], [41.691, 13.121], [41.812, 11.927, 'c'], [68.899, -3.418, 'c'], [72.521, -3.452], [72.521, -3.452, 'c'], [43.404, 12.089, 'c'], [42.446, 13.6]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[39.16, 14.975], [39.16, 14.975, 'c'], [38.332, 15.747, 'c'], [38.374, 14.547], [38.416, 13.348, 'c'], [58.233, -2.149, 'c'], [68.045, -4.023], [68.045, -4.023, 'c'], [50.015, 4.104, 'c'], [39.16, 14.975]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[36.284, 16.838], [36.284, 16.838, 'c'], [35.539, 17.532, 'c'], [35.577, 16.453], [35.615, 15.373, 'c'], [53.449, 1.426, 'c'], [62.28, -0.26], [62.28, -0.26, 'c'], [46.054, 7.054, 'c'], [36.284, 16.838]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[4.6, 164.801], [4.6, 164.801, 'c'], [-10.6, 162.401, 'c'], [6.2, 160.801], [6.2, 160.801, 'c'], [24.2, 158.801, 'c'], [28.2, 153.601], [28.2, 153.601, 'c'], [41.8, 144.401, 'c'], [44.6, 144.001], [47.4, 143.601, 'c'], [63.8, 140.001, 'c'], [64.2, 137.601], [64.6, 135.201, 'c'], [70.6, 132.801, 'c'], [72.2, 133.601], [73.8, 134.401, 'c'], [73.8, 143.601, 'c'], [71, 144.401], [68.2, 145.201, 'c'], [49.4, 152.401, 'c'], [43, 153.601], [36.6, 154.801, 'c'], [25, 162.401, 'c'], [20.2, 163.601], [15.4, 164.801, 'c'], [4.6, 164.801, 'c'], [4.6, 164.801]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[77.6, 127.401], [77.6, 127.401, 'c'], [74.6, 129.001, 'c'], [73.4, 131.601], [73.4, 131.601, 'c'], [67, 142.201, 'c'], [52.8, 145.401], [52.8, 145.401, 'c'], [29.8, 154.401, 'c'], [22, 156.401], [22, 156.401, 'c'], [8.6, 161.401, 'c'], [1.2, 160.601], [1.2, 160.601, 'c'], [-5.8, 160.801, 'c'], [0.4, 162.401], [0.4, 162.401, 'c'], [20.6, 160.401, 'c'], [24, 158.601], [24, 158.601, 'c'], [39.6, 153.401, 'c'], [42.6, 150.801], [45.6, 148.201, 'c'], [63.8, 143.201, 'c'], [66, 141.201], [68.2, 139.201, 'c'], [78, 130.801, 'c'], [77.6, 127.401]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[18.882, 158.911], [18.882, 158.911, 'c'], [24.111, 158.685, 'c'], [22.958, 160.234], [21.805, 161.784, 'c'], [19.357, 160.91, 'c'], [19.357, 160.91], [18.882, 158.911]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[11.68, 160.263], [11.68, 160.263, 'c'], [16.908, 160.037, 'c'], [15.756, 161.586], [14.603, 163.136, 'c'], [12.155, 162.263, 'c'], [12.155, 162.263], [11.68, 160.263]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[1.251, 161.511], [1.251, 161.511, 'c'], [6.48, 161.284, 'c'], [5.327, 162.834], [4.174, 164.383, 'c'], [1.726, 163.51, 'c'], [1.726, 163.51], [1.251, 161.511]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-6.383, 162.055], [-6.383, 162.055, 'c'], [-1.154, 161.829, 'c'], [-2.307, 163.378], [-3.46, 164.928, 'c'], [-5.908, 164.054, 'c'], [-5.908, 164.054], [-6.383, 162.055]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[35.415, 151.513], [35.415, 151.513, 'c'], [42.375, 151.212, 'c'], [40.84, 153.274], [39.306, 155.336, 'c'], [36.047, 154.174, 'c'], [36.047, 154.174], [35.415, 151.513]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[45.73, 147.088], [45.73, 147.088, 'c'], [51.689, 143.787, 'c'], [51.155, 148.849], [50.885, 151.405, 'c'], [46.362, 149.749, 'c'], [46.362, 149.749], [45.73, 147.088]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[54.862, 144.274], [54.862, 144.274, 'c'], [62.021, 140.573, 'c'], [60.287, 146.035], [59.509, 148.485, 'c'], [55.493, 146.935, 'c'], [55.493, 146.935], [54.862, 144.274]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[64.376, 139.449], [64.376, 139.449, 'c'], [68.735, 134.548, 'c'], [69.801, 141.21], [70.207, 143.748, 'c'], [65.008, 142.11, 'c'], [65.008, 142.11], [64.376, 139.449]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[26.834, 155.997], [26.834, 155.997, 'c'], [32.062, 155.77, 'c'], [30.91, 157.32], [29.757, 158.869, 'c'], [27.308, 157.996, 'c'], [27.308, 157.996], [26.834, 155.997]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[62.434, 34.603], [62.434, 34.603, 'c'], [61.708, 35.268, 'c'], [61.707, 34.197], [61.707, 33.127, 'c'], [79.191, 19.863, 'c'], [88.034, 18.479], [88.034, 18.479, 'c'], [71.935, 25.208, 'c'], [62.434, 34.603]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[65.4, 98.4], [65.4, 98.4, 'c'], [87.401, 120.801, 'c'], [96.601, 124.401], [96.601, 124.401, 'c'], [105.801, 135.601, 'c'], [101.801, 161.601], [101.801, 161.601, 'c'], [98.601, 169.201, 'c'], [95.401, 148.401], [95.401, 148.401, 'c'], [98.601, 123.201, 'c'], [87.401, 139.201], [87.401, 139.201, 'c'], [79, 129.301, 'c'], [85.4, 129.601], [85.4, 129.601, 'c'], [88.601, 131.601, 'c'], [89.001, 130.001], [89.401, 128.401, 'c'], [81.4, 114.801, 'c'], [64.2, 100.4], [47, 86, 'c'], [65.4, 98.4, 'c'], [65.4, 98.4]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[7, 137.201], [7, 137.201, 'c'], [6.8, 135.401, 'c'], [8.6, 136.201], [10.4, 137.001, 'c'], [104.601, 143.201, 'c'], [136.201, 167.201], [136.201, 167.201, 'c'], [91.001, 144.001, 'c'], [7, 137.201]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[17.4, 132.801], [17.4, 132.801, 'c'], [17.2, 131.001, 'c'], [19, 131.801], [20.8, 132.601, 'c'], [157.401, 131.601, 'c'], [181.001, 164.001], [181.001, 164.001, 'c'], [159.001, 138.801, 'c'], [17.4, 132.801]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[29, 128.801], [29, 128.801, 'c'], [28.8, 127.001, 'c'], [30.6, 127.801], [32.4, 128.601, 'c'], [205.801, 115.601, 'c'], [229.401, 148.001], [229.401, 148.001, 'c'], [219.801, 122.401, 'c'], [29, 128.801]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[39, 124.001], [39, 124.001, 'c'], [38.8, 122.201, 'c'], [40.6, 123.001], [42.4, 123.801, 'c'], [164.601, 85.2, 'c'], [188.201, 117.601], [188.201, 117.601, 'c'], [174.801, 93, 'c'], [39, 124.001]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-19, 146.801], [-19, 146.801, 'c'], [-19.2, 145.001, 'c'], [-17.4, 145.801], [-15.6, 146.601, 'c'], [2.2, 148.801, 'c'], [4.2, 187.601], [4.2, 187.601, 'c'], [-3, 145.601, 'c'], [-19, 146.801]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-27.8, 148.401], [-27.8, 148.401, 'c'], [-28, 146.601, 'c'], [-26.2, 147.401], [-24.4, 148.201, 'c'], [-10.2, 143.601, 'c'], [-13, 182.401], [-13, 182.401, 'c'], [-11.8, 147.201, 'c'], [-27.8, 148.401]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-35.8, 148.801], [-35.8, 148.801, 'c'], [-36, 147.001, 'c'], [-34.2, 147.801], [-32.4, 148.601, 'c'], [-17, 149.201, 'c'], [-29.4, 171.601], [-29.4, 171.601, 'c'], [-19.8, 147.601, 'c'], [-35.8, 148.801]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[11.526, 104.465], [11.526, 104.465, 'c'], [11.082, 106.464, 'c'], [12.631, 105.247], [28.699, 92.622, 'c'], [61.141, 33.72, 'c'], [116.826, 28.086], [116.826, 28.086, 'c'], [78.518, 15.976, 'c'], [11.526, 104.465]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[22.726, 102.665], [22.726, 102.665, 'c'], [21.363, 101.472, 'c'], [23.231, 100.847], [25.099, 100.222, 'c'], [137.541, 27.72, 'c'], [176.826, 35.686], [176.826, 35.686, 'c'], [149.719, 28.176, 'c'], [22.726, 102.665]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[1.885, 108.767], [1.885, 108.767, 'c'], [1.376, 110.366, 'c'], [3.087, 109.39], [12.062, 104.27, 'c'], [15.677, 47.059, 'c'], [59.254, 45.804], [59.254, 45.804, 'c'], [26.843, 31.09, 'c'], [1.885, 108.767]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-18.038, 119.793], [-18.038, 119.793, 'c'], [-19.115, 121.079, 'c'], [-17.162, 120.825], [-6.916, 119.493, 'c'], [14.489, 78.222, 'c'], [58.928, 83.301], [58.928, 83.301, 'c'], [26.962, 68.955, 'c'], [-18.038, 119.793]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-6.8, 113.667], [-6.8, 113.667, 'c'], [-7.611, 115.136, 'c'], [-5.742, 114.511], [4.057, 111.237, 'c'], [17.141, 66.625, 'c'], [61.729, 63.078], [61.729, 63.078, 'c'], [27.603, 55.135, 'c'], [-6.8, 113.667]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-25.078, 124.912], [-25.078, 124.912, 'c'], [-25.951, 125.954, 'c'], [-24.369, 125.748], [-16.07, 124.669, 'c'], [1.268, 91.24, 'c'], [37.264, 95.354], [37.264, 95.354, 'c'], [11.371, 83.734, 'c'], [-25.078, 124.912]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-32.677, 130.821], [-32.677, 130.821, 'c'], [-33.682, 131.866, 'c'], [-32.091, 131.748], [-27.923, 131.439, 'c'], [2.715, 98.36, 'c'], [21.183, 113.862], [21.183, 113.862, 'c'], [9.168, 95.139, 'c'], [-32.677, 130.821]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[36.855, 98.898], [36.855, 98.898, 'c'], [35.654, 97.543, 'c'], [37.586, 97.158], [39.518, 96.774, 'c'], [160.221, 39.061, 'c'], [198.184, 51.927], [198.184, 51.927, 'c'], [172.243, 41.053, 'c'], [36.855, 98.898]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[3.4, 163.201], [3.4, 163.201, 'c'], [3.2, 161.401, 'c'], [5, 162.201], [6.8, 163.001, 'c'], [22.2, 163.601, 'c'], [9.8, 186.001], [9.8, 186.001, 'c'], [19.4, 162.001, 'c'], [3.4, 163.201]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[13.8, 161.601], [13.8, 161.601, 'c'], [13.6, 159.801, 'c'], [15.4, 160.601], [17.2, 161.401, 'c'], [35, 163.601, 'c'], [37, 202.401], [37, 202.401, 'c'], [29.8, 160.401, 'c'], [13.8, 161.601]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[20.6, 160.001], [20.6, 160.001, 'c'], [20.4, 158.201, 'c'], [22.2, 159.001], [24, 159.801, 'c'], [48.6, 163.201, 'c'], [72.2, 195.601], [72.2, 195.601, 'c'], [36.6, 158.801, 'c'], [20.6, 160.001]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[28.225, 157.972], [28.225, 157.972, 'c'], [27.788, 156.214, 'c'], [29.678, 156.768], [31.568, 157.322, 'c'], [52.002, 155.423, 'c'], [90.099, 189.599], [90.099, 189.599, 'c'], [43.924, 154.656, 'c'], [28.225, 157.972]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[38.625, 153.572], [38.625, 153.572, 'c'], [38.188, 151.814, 'c'], [40.078, 152.368], [41.968, 152.922, 'c'], [76.802, 157.423, 'c'], [128.499, 192.399], [128.499, 192.399, 'c'], [54.324, 150.256, 'c'], [38.625, 153.572]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-1.8, 142.001], [-1.8, 142.001, 'c'], [-2, 140.201, 'c'], [-0.2, 141.001], [1.6, 141.801, 'c'], [55, 144.401, 'c'], [85.4, 171.201], [85.4, 171.201, 'c'], [50.499, 146.426, 'c'], [-1.8, 142.001]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-11.8, 146.001], [-11.8, 146.001, 'c'], [-12, 144.201, 'c'], [-10.2, 145.001], [-8.4, 145.801, 'c'], [16.2, 149.201, 'c'], [39.8, 181.601], [39.8, 181.601, 'c'], [4.2, 144.801, 'c'], [-11.8, 146.001]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[49.503, 148.962], [49.503, 148.962, 'c'], [48.938, 147.241, 'c'], [50.864, 147.655], [52.79, 148.068, 'c'], [87.86, 150.004, 'c'], [141.981, 181.098], [141.981, 181.098, 'c'], [64.317, 146.704, 'c'], [49.503, 148.962]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[57.903, 146.562], [57.903, 146.562, 'c'], [57.338, 144.841, 'c'], [59.264, 145.255], [61.19, 145.668, 'c'], [96.26, 147.604, 'c'], [150.381, 178.698], [150.381, 178.698, 'c'], [73.317, 143.904, 'c'], [57.903, 146.562]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[67.503, 141.562], [67.503, 141.562, 'c'], [66.938, 139.841, 'c'], [68.864, 140.255], [70.79, 140.668, 'c'], [113.86, 145.004, 'c'], [203.582, 179.298], [203.582, 179.298, 'c'], [82.917, 138.904, 'c'], [67.503, 141.562]],  -closed => 1, -linecolor => "#000000", -fillcolor => "#ffffff", -filled => 1, -linewidth => 0.1);

$zinc->add('curve',$top_group,[[-43.8, 148.401], [-43.8, 148.401, 'c'], [-38.6, 148.001, 'c'], [-39.8, 149.601], [-41, 151.201, 'c'], [-43.4, 150.401, 'c'], [-43.4, 150.401], [-43.8, 148.401]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-13, 162.401], [-13, 162.401, 'c'], [-7.8, 162.001, 'c'], [-9, 163.601], [-10.2, 165.201, 'c'], [-12.6, 164.401, 'c'], [-12.6, 164.401], [-13, 162.401]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-21.8, 162.001], [-21.8, 162.001, 'c'], [-16.6, 161.601, 'c'], [-17.8, 163.201], [-19, 164.801, 'c'], [-21.4, 164.001, 'c'], [-21.4, 164.001], [-21.8, 162.001]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-117.169, 150.182], [-117.169, 150.182, 'c'], [-112.124, 151.505, 'c'], [-113.782, 152.624], [-115.439, 153.744, 'c'], [-117.446, 152.202, 'c'], [-117.446, 152.202], [-117.169, 150.182]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-115.169, 140.582], [-115.169, 140.582, 'c'], [-110.124, 141.905, 'c'], [-111.782, 143.024], [-113.439, 144.144, 'c'], [-115.446, 142.602, 'c'], [-115.446, 142.602], [-115.169, 140.582]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-122.369, 136.182], [-122.369, 136.182, 'c'], [-117.324, 137.505, 'c'], [-118.982, 138.624], [-120.639, 139.744, 'c'], [-122.646, 138.202, 'c'], [-122.646, 138.202], [-122.369, 136.182]],  -closed => 1, -fillcolor => "#000000", -filled => 1, -linecolor => "#000000");

$zinc->add('curve',$top_group,[[-42.6, 211.201], [-42.6, 211.201, 'c'], [-44.2, 211.201, 'c'], [-48.2, 213.201], [-50.2, 213.201, 'c'], [-61.4, 216.801, 'c'], [-67, 226.801], [-67, 226.801, 'c'], [-54.6, 217.201, 'c'], [-42.6, 211.201]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[45.116, 303.847], [45.257, 304.105, 'c'], [45.312, 304.525, 'c'], [45.604, 304.542], [46.262, 304.582, 'c'], [47.495, 304.883, 'c'], [47.37, 304.247], [46.522, 299.941, 'c'], [45.648, 295.004, 'c'], [41.515, 293.197], [40.876, 292.918, 'c'], [39.434, 293.331, 'c'], [39.36, 294.215], [39.233, 295.739, 'c'], [39.116, 297.088, 'c'], [39.425, 298.554], [39.725, 299.975, 'c'], [41.883, 299.985, 'c'], [42.8, 298.601], [43.736, 300.273, 'c'], [44.168, 302.116, 'c'], [45.116, 303.847]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[34.038, 308.581], [34.786, 309.994, 'c'], [34.659, 311.853, 'c'], [36.074, 312.416], [36.814, 312.71, 'c'], [38.664, 311.735, 'c'], [38.246, 310.661], [37.444, 308.6, 'c'], [37.056, 306.361, 'c'], [35.667, 304.55], [35.467, 304.288, 'c'], [35.707, 303.755, 'c'], [35.547, 303.427], [34.953, 302.207, 'c'], [33.808, 301.472, 'c'], [32.4, 301.801], [31.285, 304.004, 'c'], [32.433, 306.133, 'c'], [33.955, 307.842], [34.091, 307.994, 'c'], [33.925, 308.37, 'c'], [34.038, 308.581]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-5.564, 303.391], [-5.672, 303.014, 'c'], [-5.71, 302.551, 'c'], [-5.545, 302.23], [-5.014, 301.197, 'c'], [-4.221, 300.075, 'c'], [-4.558, 299.053], [-4.906, 297.997, 'c'], [-6.022, 298.179, 'c'], [-6.672, 298.748], [-7.807, 299.742, 'c'], [-7.856, 301.568, 'c'], [-8.547, 302.927], [-8.743, 303.313, 'c'], [-8.692, 303.886, 'c'], [-9.133, 304.277], [-9.607, 304.698, 'c'], [-10.047, 306.222, 'c'], [-9.951, 306.793], [-9.898, 307.106, 'c'], [-10.081, 317.014, 'c'], [-9.859, 316.751], [-9.24, 316.018, 'c'], [-6.19, 306.284, 'c'], [-6.121, 305.392], [-6.064, 304.661, 'c'], [-5.332, 304.196, 'c'], [-5.564, 303.391]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-31.202, 296.599], [-28.568, 294.1, 'c'], [-25.778, 291.139, 'c'], [-26.22, 287.427], [-26.336, 286.451, 'c'], [-28.111, 286.978, 'c'], [-28.298, 287.824], [-29.1, 291.449, 'c'], [-31.139, 294.11, 'c'], [-33.707, 296.502], [-35.903, 298.549, 'c'], [-37.765, 304.893, 'c'], [-38, 305.401], [-34.303, 300.145, 'c'], [-32.046, 297.399, 'c'], [-31.202, 296.599]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-44.776, 290.635], [-44.253, 290.265, 'c'], [-44.555, 289.774, 'c'], [-44.338, 289.442], [-43.385, 287.984, 'c'], [-42.084, 286.738, 'c'], [-42.066, 285], [-42.063, 284.723, 'c'], [-42.441, 284.414, 'c'], [-42.776, 284.638], [-43.053, 284.822, 'c'], [-43.395, 284.952, 'c'], [-43.503, 285.082], [-45.533, 287.531, 'c'], [-46.933, 290.202, 'c'], [-48.376, 293.014], [-48.559, 293.371, 'c'], [-49.703, 297.862, 'c'], [-49.39, 297.973], [-49.151, 298.058, 'c'], [-47.431, 293.877, 'c'], [-47.221, 293.763], [-45.958, 293.077, 'c'], [-45.946, 291.462, 'c'], [-44.776, 290.635]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-28.043, 310.179], [-27.599, 309.31, 'c'], [-26.023, 308.108, 'c'], [-26.136, 307.219], [-26.254, 306.291, 'c'], [-25.786, 304.848, 'c'], [-26.698, 305.536], [-27.955, 306.484, 'c'], [-31.404, 307.833, 'c'], [-31.674, 313.641], [-31.7, 314.212, 'c'], [-28.726, 311.519, 'c'], [-28.043, 310.179]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-13.6, 293.001], [-13.2, 292.333, 'c'], [-12.492, 292.806, 'c'], [-12.033, 292.543], [-11.385, 292.171, 'c'], [-10.774, 291.613, 'c'], [-10.482, 290.964], [-9.512, 288.815, 'c'], [-7.743, 286.995, 'c'], [-7.6, 284.601], [-9.091, 283.196, 'c'], [-9.77, 285.236, 'c'], [-10.4, 286.201], [-11.723, 284.554, 'c'], [-12.722, 286.428, 'c'], [-14.022, 286.947], [-14.092, 286.975, 'c'], [-14.305, 286.628, 'c'], [-14.38, 286.655], [-15.557, 287.095, 'c'], [-16.237, 288.176, 'c'], [-17.235, 288.957], [-17.406, 289.091, 'c'], [-17.811, 288.911, 'c'], [-17.958, 289.047], [-18.61, 289.65, 'c'], [-19.583, 289.975, 'c'], [-19.863, 290.657], [-20.973, 293.364, 'c'], [-24.113, 295.459, 'c'], [-26, 303.001], [-25.619, 303.91, 'c'], [-21.488, 296.359, 'c'], [-21.001, 295.661], [-20.165, 294.465, 'c'], [-20.047, 297.322, 'c'], [-18.771, 296.656], [-18.72, 296.629, 'c'], [-18.534, 296.867, 'c'], [-18.4, 297.001], [-18.206, 296.721, 'c'], [-17.988, 296.492, 'c'], [-17.6, 296.601], [-17.6, 296.201, 'c'], [-17.734, 295.645, 'c'], [-17.533, 295.486], [-16.296, 294.509, 'c'], [-16.38, 293.441, 'c'], [-15.6, 292.201], [-15.142, 292.99, 'c'], [-14.081, 292.271, 'c'], [-13.6, 293.001]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[46.2, 347.401], [46.2, 347.401, 'c'], [53.6, 327.001, 'c'], [49.2, 315.801], [49.2, 315.801, 'c'], [60.6, 337.401, 'c'], [56, 348.601], [56, 348.601, 'c'], [55.6, 338.201, 'c'], [51.6, 333.201], [51.6, 333.201, 'c'], [47.6, 346.001, 'c'], [46.2, 347.401]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[31.4, 344.801], [31.4, 344.801, 'c'], [36.8, 336.001, 'c'], [28.8, 317.601], [28.8, 317.601, 'c'], [28, 338.001, 'c'], [21.2, 349.001], [21.2, 349.001, 'c'], [35.4, 328.801, 'c'], [31.4, 344.801]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[21.4, 342.801], [21.4, 342.801, 'c'], [21.2, 322.801, 'c'], [21.6, 319.801], [21.6, 319.801, 'c'], [17.8, 336.401, 'c'], [7.6, 346.001], [7.6, 346.001, 'c'], [22, 334.001, 'c'], [21.4, 342.801]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[11.8, 310.801], [11.8, 310.801, 'c'], [17.8, 324.401, 'c'], [7.8, 342.801], [7.8, 342.801, 'c'], [14.2, 330.601, 'c'], [9.4, 323.601], [9.4, 323.601, 'c'], [12, 320.201, 'c'], [11.8, 310.801]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-7.4, 342.401], [-7.4, 342.401, 'c'], [-8.4, 326.801, 'c'], [-6.6, 324.601], [-6.6, 324.601, 'c'], [-6.4, 318.201, 'c'], [-6.8, 317.201], [-6.8, 317.201, 'c'], [-2.8, 311.001, 'c'], [-2.6, 318.401], [-2.6, 318.401, 'c'], [-1.2, 326.201, 'c'], [1.6, 330.801], [1.6, 330.801, 'c'], [5.2, 336.201, 'c'], [5, 342.601], [5, 342.601, 'c'], [-5, 312.401, 'c'], [-7.4, 342.401]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-11, 314.801], [-11, 314.801, 'c'], [-17.6, 325.601, 'c'], [-19.4, 344.601], [-19.4, 344.601, 'c'], [-20.8, 338.401, 'c'], [-17, 324.001], [-17, 324.001, 'c'], [-12.8, 308.601, 'c'], [-11, 314.801]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-32.8, 334.601], [-32.8, 334.601, 'c'], [-27.8, 329.201, 'c'], [-26.4, 324.201], [-26.4, 324.201, 'c'], [-22.8, 308.401, 'c'], [-29.2, 317.001], [-29.2, 317.001, 'c'], [-29, 325.001, 'c'], [-37.2, 332.401], [-37.2, 332.401, 'c'], [-32.4, 330.001, 'c'], [-32.8, 334.601]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-38.6, 329.601], [-38.6, 329.601, 'c'], [-35.2, 312.201, 'c'], [-34.4, 311.401], [-34.4, 311.401, 'c'], [-32.6, 308.001, 'c'], [-35.4, 311.201], [-35.4, 311.201, 'c'], [-44.2, 330.401, 'c'], [-48.2, 337.001], [-48.2, 337.001, 'c'], [-40.2, 327.801, 'c'], [-38.6, 329.601]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-44.4, 313.001], [-44.4, 313.001, 'c'], [-32.8, 290.601, 'c'], [-54.6, 316.401], [-54.6, 316.401, 'c'], [-43.6, 306.601, 'c'], [-44.4, 313.001]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[-59.8, 298.401], [-59.8, 298.401, 'c'], [-55, 279.601, 'c'], [-52.4, 279.801], [-52.4, 279.801, 'c'], [-44.2, 270.801, 'c'], [-50.8, 281.401], [-50.8, 281.401, 'c'], [-56.8, 291.001, 'c'], [-56.2, 300.801], [-56.2, 300.801, 'c'], [-56.8, 291.201, 'c'], [-59.8, 298.401]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[270.5, 287], [270.5, 287, 'c'], [258.5, 277, 'c'], [256, 273.5], [256, 273.5, 'c'], [269.5, 292, 'c'], [269.5, 299], [269.5, 299, 'c'], [272, 291.5, 'c'], [270.5, 287]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[276, 265], [276, 265, 'c'], [255, 250, 'c'], [251.5, 242.5], [251.5, 242.5, 'c'], [278, 272, 'c'], [278, 276.5], [278, 276.5, 'c'], [278.5, 267.5, 'c'], [276, 265]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[293, 111], [293, 111, 'c'], [281, 103, 'c'], [279.5, 105], [279.5, 105, 'c'], [290, 111.5, 'c'], [292.5, 120], [292.5, 120, 'c'], [291, 111, 'c'], [293, 111]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");

$zinc->add('curve',$top_group,[[301.5, 191.5], [284, 179.5], [284, 179.5, 'c'], [303, 196.5, 'c'], [303.5, 200.5], [301.5, 191.5]],  -closed => 1, -fillcolor => "#cccccc", -filled => 1, -linecolor => "#cccccc");



### translating ojects for making them all visibles
$zinc->translate($top_group, 200, 150);


### on ajoute quelques binding bien pratiques pour la mise au point

my $i=0;

$zinc->Tk::bind('<ButtonPress-1>', [\&press, \&motion]);
$zinc->Tk::bind('<ButtonRelease-1>', [\&release]);
$zinc->Tk::bind('<ButtonPress-2>', [\&press, \&zoom]);
$zinc->Tk::bind('<ButtonRelease-2>', [\&release]);
$zinc->Tk::bind('<ButtonPress-3>', [\&press, \&rotate]);
$zinc->Tk::bind('<ButtonRelease-3>', [\&release]);


&Tk::MainLoop;


##### bindings for moving, rotating, scaling the items
my ($cur_x, $cur_y, $cur_angle);
sub press {
    my ($zinc, $action) = @_;
    my $ev = $zinc->XEvent();
    $cur_x = $ev->x;
    $cur_y = $ev->y;
    $cur_angle = atan2($cur_y, $cur_x);
    $zinc->Tk::bind('<Motion>', [$action]);
}

sub motion {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @res = $zinc->transform($top_group, [$lx, $ly, $cur_x, $cur_y]);
    $zinc->translate($top_group, $res[0] - $res[2], $res[1] - $res[3]);
    $cur_x = $lx;
    $cur_y = $ly;
    $i++;
}

sub zoom {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $maxx;
    my $maxy;
    my $sx;
    my $sy;
    
    if ($lx > $cur_x) {
	$maxx = $lx;
    } else {
	$maxx = $cur_x;
    }
    if ($ly > $cur_y) {
	$maxy = $ly
    } else {
	$maxy = $cur_y;
    }
    return if ($maxx == 0 || $maxy == 0);
    $sx = 1.0 + ($lx - $cur_x)/$maxx;
    $sy = 1.0 + ($ly - $cur_y)/$maxy;
    $cur_x = $lx;
    $cur_y = $ly;
    $zinc->scale($top_group, $sx, $sx); #$sy);
}

sub rotate {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $langle;
    
    $langle = atan2($ly, $lx);
    $zinc->rotate($top_group, -($langle - $cur_angle));
    $cur_angle = $langle;
}

sub release {
    my ($zinc) = @_;
    $zinc->Tk::bind('<Motion>', '');
}

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/tkZincLogo.pl.











































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/usr/bin/perl
# $Id$
# this simple demo has been adapted by C. Mertz <mertz@cena.fr> from the original
# work of JL. Vinot <vinot@cena.fr>

package tkZincLogo; # for avoiding symbol collision between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;
use Tk::Zinc::Logo; # this module implements a class which instances are Zinc logo!

my $defaultfont = '-adobe-helvetica-bold-r-normal--*-140-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $text = $mw->Scrolled(qw/Text -relief sunken -borderwidth 2 -setgrid true
	      -height 7 -scrollbars ''/);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
	      'This tkZinc logo should used openGL for a correct rendering!
   You can transform this logo with your mouse:
     Drag-Button 1 for moving the logo,
     Drag-Button 2 for zooming the logo,
     Drag-Button 3 for rotating the logo,
     Shift-Drag-Button 1 for modifying the logo transparency,
     Shift-Drag-Button 2 for modifying the logo gradient.'
	      );

my $zinc = $mw->Zinc(-width => 350, -height => 250,
		     -render => 1,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

my $group = $zinc->add('group', 1, );


my $logo = Tk::Zinc::Logo->new(-widget => $zinc,
			       -parent => $group,
			       -position => [40, 70],
			       -priority => 800,
			       -scale => [.6, .6],
			       );


$zinc->Tk::bind('<ButtonPress-1>', [\&press, \&motion]);
$zinc->Tk::bind('<ButtonRelease-1>', [\&release]);
    
$zinc->Tk::bind('<ButtonPress-2>', [\&press, \&zoom]);
$zinc->Tk::bind('<ButtonRelease-2>', [\&release]);

$zinc->Tk::bind('<ButtonPress-3>', [\&press, \&rotate]);
$zinc->Tk::bind('<ButtonRelease-3>', [\&release]);


$zinc->Tk::bind('<Shift-ButtonPress-1>', [\&press, \&modifyAlpha]);
$zinc->Tk::bind('<Shift-ButtonRelease-1>', [\&release]);

$zinc->Tk::bind('<Shift-ButtonPress-2>', [\&press, \&modifyGradient]);
$zinc->Tk::bind('<Shift-ButtonRelease-2>', [\&release]);


#
# Controls for the window transform.
#
my ($cur_x, $cur_y, $cur_angle);
sub press {
    my ($zinc, $action) = @_;
    my $ev = $zinc->XEvent();
    $cur_x = $ev->x;
    $cur_y = $ev->y;
    $cur_angle = atan2($cur_y, $cur_x);
    $zinc->Tk::bind('<Motion>', [$action]);
}

sub modifyAlpha {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $xrate = $lx /  $zinc->cget(-width);

    $xrate = 0 if $xrate < 0;
    $xrate = 1 if $xrate > 1;

    my $alpha = $xrate * 100;
    $zinc->itemconfigure($group, -alpha => $alpha);
}

sub modifyGradient {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $ly = $ev->y;
    my $yrate = $ly /  $zinc->cget(-height);

    $yrate = 0 if $yrate < 0;
    $yrate = 1 if $yrate > 1;
    my $gradientpercent = sprintf ("%d", $yrate * 100);

    $zinc->itemconfigure ('zinc_shape', -fillcolor => "=axial 270|#ffffff 0 28|#66848c $gradientpercent|#7192aa");    
}


sub motion {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @res;
    
    @res = $zinc->transform($group, [$lx, $ly, $cur_x, $cur_y]);
    $zinc->translate($group, $res[0] - $res[2], $res[1] - $res[3]);
    $cur_x = $lx;
    $cur_y = $ly;
}

sub zoom {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $maxx;
    my $maxy;
    my $sx;
    my $sy;
    
    if ($lx > $cur_x) {
	$maxx = $lx;
    } else {
	$maxx = $cur_x;
    }
    if ($ly > $cur_y) {
	$maxy = $ly
    } else {
	$maxy = $cur_y;
    }
    return if ($maxx == 0 || $maxy == 0);
    $sx = 1.0 + ($lx - $cur_x)/$maxx;
    $sy = 1.0 + ($ly - $cur_y)/$maxy;
    $cur_x = $lx;
    $cur_y = $ly;
    $zinc->scale($group, $sx, $sy);
}

sub rotate {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $langle;
    
    $langle = atan2($ly, $lx);
    $zinc->rotate($group, -($langle - $cur_angle));
    $cur_angle = $langle;
}

sub release {
    my ($zinc) = @_;
    $zinc->Tk::bind('<Motion>', '');
}

Tk::MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/transforms.pl.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
#!/usr/bin/perl -w

# $Id$
# This simple demo has been developped by P. Lecoanet <lecoanet@cena.fr>

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

#
# TODO:
#
# Ajouter la construction des items manquants
#

use Tk;
use Tk::Zinc;

my $currentgroup;
my $currentitem;
my $mw = MainWindow->new();
my $top = 1;

my $inactiveAxisColor = 'black';
my $activeAxisColor = 'red';
my $worldAxisColor = '#a5a5a5';

my $itemtype;
my $composerot = 1;
my $composescale = 1;
my $drag = 0;

my $logo = $mw->Photo(-file => Tk->findINC('demos/zinc_data/zinc_anti.gif'));

my $text = $mw->Text(-relief => 'sunken',
		     -borderwidth => 2,
		     -height => 12);
$text->pack(-expand => 0, -fill => 'x');
$text->insert('0.0', 'Items are always added to the current group.
The available commands are:
   Button 1       on the background, add an item with initial translation
   Button 2       on the background, add a group with initial translation
   Button 1       on item/group axes, select/deselect that item space
   Drag Button 1  on item/group axes, translate that item space
   Del            reset the transformation
   Shift-Del      reset a group direct children transformations
   PageUp/Down    scale up/down
   End/Home       rotate right/left
   Ins            swap the Y axis
   4 arrows       translate in the 4 directions');
$text->configure(-state => 'disabled');

my $zinc = $mw->Zinc(-borderwidth => 3,
		     -highlightthickness => 0,
		     -relief => 'sunken',
		     -render => 0,
		     -takefocus => 1);
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => 500, -height => 500);

my $rc = $mw->Frame()->pack(-expand => 0, -fill => 'x');
my $option = $rc->Optionmenu(-options => ['rectangle', 'arc',
					  'curve',
					  'icon', 'tabular',
					  'text', 'track',
					  'triangles', 'waypoint'],
#			     -command => sub { $zinc->Tk::focus(); },
			     -variable => \$itemtype)->grid(-row => 0,
							    -column => 1,
							    -sticky => 'w');

$rc->Button(-text => 'Add item',
	    -command => \&additem)->grid(-row => 0,
					 -column => 2,
					 -padx => 10,
					 -sticky => 'ew');
$rc->Button(-text => 'Add group',
	    -command => \&addgroup)->grid(-row => 0,
					  -column => 3,
					  -padx => 10,
					  -sticky => 'ew');
$rc->Button(-text => 'Remove',
	    -command => \&removeitem)->grid(-row => 0,
					    -column => 4,
					    -padx => 10,
					    -sticky => 'ew');

$rc->Checkbutton(-text => '-composescale',
		 -command => \&togglecomposescale,
		 -variable => \$composescale)->grid(-row => 0,
						    -column => 6,
						    -sticky => 'w');

$rc->Checkbutton(-text => '-composesrotation',
		 -command => \&togglecomposerot,
		 -variable => \$composerot)->grid(-row => 1,
						  -column => 6,
						  -sticky => 'w');


my $world = $zinc->add('group', $top);
$zinc->add('curve', $top, [0, 0, 80, 0],
	   -linewidth => 3,
	   -linecolor => $worldAxisColor,
	   -lastend => [6,8,3],
	   -tags => ["axis:$world"]);
$zinc->add('curve', $top, [0, 0, 0, 80],
	   -linewidth => 3,
	   -linecolor => $worldAxisColor,
	   -lastend => [6,8,3],
	   -tags => ["axis:$world"]);
$zinc->add('rectangle', $top, [-2, -2, 2, 2],
	   -filled => 1,
	   -fillcolor => $worldAxisColor,
	   -linecolor => $worldAxisColor,
	   -linewidth => 3,
	   -tags => ["axis:$world"]);
$zinc->add('text', $top,
	   -text => "This is the origin\nof the world",
	   -anchor => 's',
	   -color => $worldAxisColor,
	   -alignment => 'center',
	   -tags => ["axis:$world", 'text']);


$currentgroup = $world;

$zinc->Tk::bind('<1>', [\&mouseadd, 'item']);
$zinc->Tk::bind('<2>', [\&mouseadd, 'group']);
$zinc->Tk::bind('<Up>', \&moveup);
$zinc->Tk::bind('<Left>', \&moveleft);
$zinc->Tk::bind('<Right>', \&moveright);
$zinc->Tk::bind('<Down>', \&movedown);
$zinc->Tk::bind('<Next>', \&scaledown);
$zinc->Tk::bind('<Prior>', \&scaleup);
$zinc->Tk::bind('<Delete>', \&reset);
$zinc->Tk::bind('<Shift-Delete>', \&resetchildren);
$zinc->Tk::bind('<End>', \&rotateleft);
$zinc->Tk::bind('<Home>', \&rotateright);
$zinc->Tk::bind('<Insert>', \&swapaxis);

$zinc->Tk::bind('<Configure>', [\&resize]);

$zinc->Tk::focus();
$zinc->focusFollowsMouse();


MainLoop();

sub resize {
  my $ev = $zinc->XEvent();
  my $x = $ev->w/2;
  my $y = $ev->h/2;

  $zinc->treset($world);
  $zinc->treset("axis:$world");
  $zinc->translate($world, $x, $y);
  $zinc->translate("axis:$world", $x, $y);
}

sub swapaxis {
  if (defined($currentitem)) {
    $zinc->scale($currentitem, 1, -1);
    $zinc->scale("axisgrp:$currentitem", 1, -1);
  }
}

sub togglecomposerot {
  if (defined($currentitem)) {
    $zinc->itemconfigure($currentitem, -composerotation => $composerot);
    $zinc->itemconfigure("axisgrp:$currentitem", -composerotation => $composerot);
  }
}

sub togglecomposescale {
  my $bool;

  if (defined($currentitem)) {
    $zinc->itemconfigure($currentitem, -composescale => $composescale);
    $zinc->itemconfigure("axisgrp:$currentitem", -composescale => $composescale);
  }
}

sub dragitem {
  $drag = 1;
  return if (!defined($currentitem));

  my $ev = $zinc->XEvent();
  my $group = $zinc->group($currentitem);
  my ($x, $y) = $zinc->transform($group, [$ev->x, $ev->y]);

  $zinc->treset($currentitem);
  $zinc->treset("axisgrp:$currentitem");
  $zinc->translate($currentitem, $x, $y);
  $zinc->translate("axisgrp:$currentitem", $x, $y);
}

sub select {
  my @tags = $zinc->gettags('current');
  my $t;
  foreach $t (@tags) {
    if ($t =~ '^axis:(\d+)') {
      changeitem($1);
    }
  }
}

sub changeitem {
  my ($item) = @_;

  if (defined($currentitem) && !$drag) {
    $zinc->itemconfigure("axis:$currentitem && !text",
			 -linecolor => $inactiveAxisColor,
			 -fillcolor => $inactiveAxisColor);
    if ($currentitem != $currentgroup) {
      $zinc->itemconfigure("axis:$currentitem && !text",
			   -linewidth => 1);
    }
  }
  if (!defined($currentitem) || ($item != $currentitem)) {
    $zinc->itemconfigure("axis:$item && !text",
			 -linecolor => $activeAxisColor,
			 -fillcolor => $activeAxisColor,
			 -linewidth => 3);
    $currentitem = $item;
    $composerot = $zinc->itemcget($currentitem, -composerotation);
    $zinc->itemconfigure("axisgrp:$currentitem", -composerotation => $composerot);
    $composescale = $zinc->itemcget($currentitem, -composescale);
    $zinc->itemconfigure("axisgrp:$currentitem", -composescale => $composescale);
  }
  elsif (!$drag) {
    $currentitem = undef;
    $composerot = $composescale = 1;
  }
  $drag = 0;
}

sub selectgroup {
  my @tags = $zinc->gettags('current');
  my $t;
  foreach $t (@tags) {
    if ($t =~ '^axis:(\d+)') {
      changegroup($1);
    }
  }
}

sub changegroup {
  my ($grp) = @_;

  changeitem($grp);
  $zinc->itemconfigure("axis:$currentgroup && !text",
		       -linewidth => 1);
  if (defined($currentitem)) {
    $currentgroup = $currentitem;
  }
  else {
    $currentgroup = $world;
  }

  $zinc->itemconfigure("axis:$currentgroup && !text",
		       -linewidth => 3);
}

sub reset {
  if (defined($currentitem)) {
    $zinc->treset($currentitem);
    $zinc->treset("axisgrp:$currentitem");
  }
}

sub resetchildren {
  my @children;

  if (defined($currentitem) && ($zinc->type($currentitem) eq 'group')) {
    @children = $zinc->addtag('rt', 'withtag', 'all', $currentitem, 0);
    $zinc->treset('rt');
    $zinc->dtag('rt', 'rt');
  }
}

sub moveup {
  move(0, 20);
}

sub movedown {
  move(0, -20);
}

sub moveright {
  move(20, 0);
}

sub moveleft {
  move(-20, 0);
}

sub move {
  my ($dx, $dy) = @_;

  if (defined($currentitem)) {
    $zinc->translate($currentitem, $dx, $dy);
    $zinc->translate("axisgrp:$currentitem", $dx, $dy);
  }
}

sub scaleup {
  scale(1.1, 1.1);
}

sub scaledown {
  scale(0.9, 0.9);
}

sub scale {
  my ($dx, $dy) = @_;

  if (defined($currentitem)) {
    $zinc->scale($currentitem, $dx, $dy);
    $zinc->scale("axisgrp:$currentitem", $dx, $dy);
  }
}

sub rotateleft {
  rotate(-3.14159/18);
}

sub rotateright {
  rotate(3.14159/18);
}

sub rotate {
  my ($angle) = @_;

  if (defined($currentitem)) {
    $zinc->rotate($currentitem, $angle);
    $zinc->rotate("axisgrp:$currentitem", $angle);
  }
}

sub newrect {
  return $zinc->add('rectangle', $currentgroup,
		    [-15, -15, 15, 15],
		    -filled => 1,
		    -linewidth => 0,
		    -fillcolor => 'tan');
}

sub newarc {
  return $zinc->add('arc', $currentgroup,
		    [-25, -15, 25, 15],
		    -filled => 1,
		    -linewidth => 0,
		    -fillcolor => 'tan');
}

sub newcurve {
  return $zinc->add('curve', $currentgroup,
		    [-15, -15, -15, 15, 15, 15, 15, -15],
		    -filled => 1,
		    -linewidth => 0,
		    -fillcolor => 'tan');
}

sub newtext {
  my $item = $zinc->add('text', $currentgroup,
			-anchor => 's');
  $zinc->itemconfigure($item, -text => "Item id: $item");
  return $item;
}

sub newicon {
  my $item = $zinc->add('icon', $currentgroup,
			-image => $logo,
			-anchor => 'center');

  return $item;
}

sub newtriangles {
  my $item = $zinc->add('triangles', $currentgroup,
			[-25, 15, -10, -15, 5, 15,
			 20, -15, 35, 15, 50, -30],
			-colors => ['tan', 'wheat', 'tan', 'wheat']);
  return $item;
}

sub newtrack {
  my $labelformat = "x80x50+0+0 a0a0^0^0 a0a0^0>1 a0a0>2>1 x30a0>3>1 a0a0^0>2";

  my $item=$zinc->add('track', $currentgroup, 6,
		      -labelformat => $labelformat,
		      -speedvector => [30, -15],
		      -markersize => 20);
  $zinc->itemconfigure($item, 0,
		       -filled => 0,
		       -bordercolor => 'DarkGreen',
		       -border => 'contour');
  $zinc->itemconfigure($item, 1,
		       -filled => 1,
		       -backcolor => 'gray60',
		       -text => 'AFR6128');
  $zinc->itemconfigure($item, 2,
		       -filled => 0,
		       -backcolor => 'gray65',
		       -text => '390');
  $zinc->itemconfigure($item, 3,
		       -filled => 0,
		       -backcolor => 'gray65',
		       -text => '/');
  $zinc->itemconfigure($item, 4,
		       -filled => 0,
		       -backcolor => 'gray65',
		       -text => '350');
  $zinc->itemconfigure($item, 5,
		       -filled => 0,
		       -backcolor => 'gray65',
		       -text => 'TUR');
  return $item;
}

sub newwaypoint {
  my $labelformat = "a0a0+0+0 a0a0>0^1";

  my $item=$zinc->add('waypoint', $currentgroup, 2,
		      -labelformat => $labelformat);
  $zinc->itemconfigure($item, 0,
		       -filled => 1,
		       -backcolor => 'DarkGreen',
		       -text => 'TUR');
  $zinc->itemconfigure($item, 1,
		       -text => '>>>');
  return $item;
}

sub newtabular {
  my $labelformat = "f700f600+0+0 f700a0^0^0 f700a0^0>1 f700a0^0>2 f700a0^0>3 f700a0^0>4 f700a0^0>5";

  my $item=$zinc->add('tabular', $currentgroup, 7,
		      -labelformat => $labelformat);
  $zinc->itemconfigure($item, 0,
		       -filled => 1,
		       -border => 'contour',
		       -bordercolor => 'black',
		       -backcolor => 'gray60');
  $zinc->itemconfigure($item, 1,
		       -alignment => 'center',
		       -text => 'AFR6128');
  $zinc->itemconfigure($item, 2,
		       -alignment => 'center',
		       -text => '390');
  $zinc->itemconfigure($item, 3,
		       -alignment => 'center',
		       -text => '370');
  $zinc->itemconfigure($item, 4,
		       -alignment => 'center',
		       -text => '350');
  $zinc->itemconfigure($item, 5,
		       -alignment => 'center',
		       -text => '330');
  $zinc->itemconfigure($item, 6,
		       -alignment => 'center',
		       -text => 'TUR');
  return $item;
}

sub addaxes {
  my ($item, $length, $command, $infront) = @_;

  my $axesgroup = $zinc->add('group', $currentgroup,
			     -tags => ["axisgrp:$item"]);
  $zinc->add('curve', $axesgroup, [0, 0, $length, 0],
	     -linewidth => 2,
	     -lastend => [6,8,3],
	     -tags => ["axis:$item"]);
  $zinc->add('curve', $axesgroup, [0, 0, 0, $length],
	     -linewidth => 2,
	     -lastend => [6,8,3],
	     -tags => ["axis:$item"]);
  $zinc->add('rectangle', $axesgroup, [-2, -2, 2, 2],
	     -filled => 1,
	     -linewidth => 0,
	     -composescale => 0,
	     -tags => ["axis:$item"]);
  if ($infront) {
    $zinc->raise($item, $axesgroup);
  }
  $zinc->bind("axis:$item", '<B1-Motion>', \&dragitem);
  $zinc->bind("axis:$item", '<ButtonRelease-1>', $command);
}

sub additem {
  my $item;
  my $length = 25;
  my $itemontop = 0;

  if ($itemtype eq 'rectangle') {
    $item = newrect();
  }
  elsif ($itemtype eq 'arc') {
    $item = newarc();
  }
  elsif ($itemtype eq 'curve') {
    $item = newcurve();
  }
  elsif ($itemtype eq 'triangles') {
    $item = newtriangles();
  }
  elsif ($itemtype eq 'icon') {
    $item = newicon();
  }
  elsif ($itemtype eq 'text') {
    $item = newtext();
  }
  elsif ($itemtype eq 'track') {
    $item = newtrack();
    $itemontop = 1;
  }
  elsif ($itemtype eq 'waypoint') {
    $item = newwaypoint();
    $itemontop = 1;
  }
  elsif ($itemtype eq 'tabular') {
    $item = newtabular();
  }

  addaxes($item, 25, \&select, $itemontop);
  changeitem($item);
}

sub addgroup {
  my $item = $zinc->add('group', $currentgroup);

  addaxes($item, 80, \&selectgroup, 1);
  changegroup($item);
}

sub mouseadd {
  my ($w, $itemorgrp) = @_;
  my $ev = $zinc->XEvent();
  my ($x, $y) = $zinc->transform($currentgroup, [$ev->x, $ev->y]);
  my $item = $zinc->find('withtag', 'current');

  if (defined($item)) {
    my @tags = $zinc->gettags($item);
    foreach my $t (@tags) {
      return if ($t =~ '^axis');
    }
  }
  if ($itemorgrp eq 'group') {
    addgroup();
  }
  else {
    additem();
  }
  $zinc->translate($currentitem, $x, $y);
  $zinc->translate("axisgrp:$currentitem", $x, $y);
}

sub removeitem {
  if (defined($currentitem)) {
    $zinc->remove($currentitem, "axisgrp:$currentitem");
    if ($currentitem == $currentgroup) {
      $currentgroup = $world;
    }
    $currentitem = undef;
    $composescale = $composerot = 1;
  }
}

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/translation.pl.

































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/perl
# $Id$
# This simple demo has been developped by C. Schlienger <celine@intuilab.com>

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


use Tk;
use Tk::Zinc;
use strict;


my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();

###########################################
# Text zone
###########################################

my $text = $mw->Scrolled(qw/Text -relief sunken -borderwidth 2 -setgrid true
	      -height 6 -scrollbars e/);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
	      'This toy-appli shows translations on waypoint items.
The following operations are possible:
   Click "Up" for up translation
   Click "Left" for left translation
   Click "Right" for right translation
   Click "Down" for down translation' );

###########################################
# Zinc
###########################################
my $zinc_width=600;
my $zinc_height=400;
my $zinc = $mw->Zinc(-width => $zinc_width, -height => $zinc_height,
		     -font => "10x20",
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

###########################################
# Waypoints
###########################################

my $wp_group = $zinc->add('group', 1, -visible => 1);

my $p1=[200, 200];
my $wp1 = $zinc->add('waypoint',$wp_group, 1,
		    -position => $p1,
		    -connectioncolor => 'green',
		    -symbolcolor => 'blue',
		    -labelformat => 'x20x18+0+0',
		    -leaderwidth=>'0',
		    -labeldx=>'-20'
		   );
$zinc->itemconfigure($wp1, 0,
		     -text => "DO",
		    );

my $p2=[300, 300];
my $wp2 = $zinc->add('waypoint',$wp_group, 1,
		     -position => $p2,
		     -connecteditem => $wp1,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'-20',
		     #-labeldy=>'30'
		    );

$zinc->itemconfigure($wp2, 0,
		     -text => "RE",
		    );

my $p3=[400, 150];
my $wp3 = $zinc->add('waypoint', $wp_group, 2,
		     -position => $p3,
		     -connecteditem => $wp2,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'20',
		     -labeldy=>'+10'
		    );
$zinc->itemconfigure($wp3, 0,
		     -text => "MI",
		    );

###################################################
# control panel
###################################################
my $rc = $mw->Frame()->pack();
my $up=$rc->Button(-width => 2, 
		   -height => 2,
		   -text => 'Up',
		   -command=>sub{
		     #--------------------------------
		     # Up translation
		     #--------------------------------
		     $zinc->translate("$wp_group",0,-10);
		   })->grid(-row => 0,
			    -column => 1);

my $left=$rc->Button(-width => 2, 
		     -height => 2,
		     -text => 'Left',
		     -command=>sub{
		       #--------------------------------
		       # Left translation
		       #--------------------------------
		       $zinc->translate("$wp_group",-10,0);
		     })->grid(-row => 1,
			      -column => 0);

my $right=$rc->Button(-width => 2, 
		      -height => 2,
		      -text => 'Right',
		      -command=>sub{
			#--------------------------------
			# Right translation
			#--------------------------------
			$zinc->translate("$wp_group",10,0);
		      })->grid(-row => 1,
			       -column => 2);

my $down=$rc->Button(-width => 2, 
		     -height => 2,
		     -text => 'Down',
		     -command=>sub{
		       #--------------------------------
		       # Down translation
		       #--------------------------------
		       $zinc->translate("$wp_group",0,10);
		     })->grid(-row => 2,
			      -column => 1);




MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/triangles.pl.





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr and N. Banoun banoun@cena.fr

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;
use strict;


my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 300,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -render => 1,
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

# 6 equilateral triangles around a point 
$zinc->add('text', 1,
	     -position => [ 5,10 ],
	     -text => "Triangles item without transparency");

my ($x0,$y0) = (200,150);
my @coords=($x0,$y0);
for my $i (0..6) {
    my $angle =  $i * 6.28/6;
    push @coords, ($x0 + 100 * cos ($angle), $y0 - 100 * sin ($angle) );
}

my $tr1 = $zinc->add('triangles', 1,
		     \@coords,
		     -fan => 1,
		     -colors => ['white', 'yellow', 'magenta', 'blue', 'cyan', 'green', 'red', 'yellow'],
		     -visible => 1,			    
		     );

$zinc->add('text', 1,
	   -position => [ 370, 10 ],
	   -text => "Triangles item with transparency");


# using the clone method to make a copy and then modify the clone'colors
my $tr2 = $zinc->clone($tr1);
$zinc->translate($tr2,300,0);
$zinc->itemconfigure($tr2,
		     -colors => ['white;50', 'yellow;50', 'magenta;50', 'blue;50', 'cyan;50', 'green;50', 'red;50', 'yellow;50'],
		     );



MainLoop;

		    
	   

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/usedamage.pl.











































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/usr/bin/perl -w
#
# Use damage test
#
# $Id$
# this simple test has been developped by A.Lemort lemort@intuilab.com


use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use strict;
use Tk;
use Tk::Zinc;
use Tk::LabFrame;
use Time::HiRes;


#
# Mainwindow
#
my $mw = new MainWindow();
$mw->title("10.000 rectangles and a drag-n-droppable circle");

#
# Text zone
#
my $text = $mw->Scrolled(qw/Text -relief sunken -borderwidth 2 -setgrid true -height 8 -scrollbars e/);
$text->pack(-expand => 1, -fill => 'both');

$text->insert('0.0',
              'This toy-app illustrates how the -usedamage property can increase TkZinc performance.
The Following operations are possible:
   Press "0" to desactivate OpenGL optimization
   Press "1" to activate OpenGL optimization (same result as the old GL_DAMAGE compilation flag). These optimizations work well with Nvidia cards but it creates a strange trail effect with other cards (black trails)
   Press "2" to activate OpenGL optimization. These optimizations are a bit slower but they have a much better compatibility'
	      );

#
# Zinc
#
my $zinc = $mw->Zinc(
		     -render => 1,
		     -usedamage => 0,
		     -relief => 'flat',
		     -borderwidth => 0,
		     -highlightthickness => 0,
		     -width => 700,
		     -height => 600,
		     )->pack(
			     -expand => 1,
			     -fill => 'both',
			     );

# Seed our random generator
srand(1234567890);

# Add a lot of rectangles
my $Nrect = 10000;
foreach my $i (0...$Nrect) {
    $zinc->add('rectangle', 1, [50 + rand()*500, 50 + rand()*500, 50 + rand()*500, 50 + rand()*500], -filled => 1, -fillcolor => 'blue');
}

# Add a label
my $label = $zinc->add('text', 1, -position => [5, 10], -text => 'usedamage=0: Without OpenGL optimization');

# Add a moveable circle
my $circle = $zinc->add('arc', 1, [0,0,50,50], -filled => 1, -fillcolor => 'red', -linewidth => 2);
$zinc->translate($circle, 50, 50);

# Add bindings to move our circle
my ($X, $Y);
$zinc->bind($circle, '<ButtonPress-1>',[\&press, Ev('x'), Ev('y')]);
$zinc->bind($circle, '<B1-Motion>', [\&motion, Ev('x'), Ev('y')]);


# Add bindings to change the value of usedamage
$mw->bind('<KeyPress-0>', sub {
    # No optimization
    $zinc->configure(-usedamage => 0);
    $zinc->itemconfigure($label, -text => 'usedamage=0: Without OpenGL optimization');
});
$mw->bind('<KeyPress-1>', sub {
    # OpenGL optimization (best with Nvidia
    $zinc->configure(-usedamage => 1);
    $zinc->itemconfigure($label, -text => 'usedamage=1: With OpenGL optimization (better performance but works only with Nvidia cards)');
});
$mw->bind('<KeyPress-2>', sub {
    # OpenGL optimization (best with Nvidia
    $zinc->configure(-usedamage => 2);
    $zinc->itemconfigure($label, -text => 'usedamage=2: With OpenGL optimization (a bit slower but much better compatibility)');
});


#
# Commands
#

# Benchmark data
my $N = 50;
my $delta = 550/$N;

my $commandFrame = $mw->Frame()->pack(-expand => 1, -fill => 'both');
my $commandFrameTitle = $commandFrame->LabFrame(
                                                -label => 'Automatic benchmark: trasnlate our circle from top-left to bottom-right ('.$N.' steps)',
                                                )->pack(
                                                        -side => 'bottom',
                                                        -fill => 'both',
                                                        -expand => 1,
                                                        );

foreach my $i (0...2) {
   my $value = $i;
   
   # Label: display result
   my $label = $commandFrameTitle->Label(
                                         -text => 'Press button to start benchmark',
                                         )->grid(
                                                 -row => $i,
                                                 -column => 1,
                                                 );

   my $button = $commandFrameTitle->Button(
                                           -text => 'Test usedamage='.$value,
                                           -command => sub {
                                             benchmarkUsedamage($label, $value);
                                           },
                                           )->grid(
                                                   -row => $i,
                                                   -column => 0,
                                                   );
}


# Mainloop
MainLoop;



#
# Press
# 
sub press {
    my ($zinc, $x, $y) = @_;
    $X = $x;
    $Y = $y;
}


#
# Motion
#
sub motion {
    my ($zinc, $x, $y) = @_;
    $zinc->translate($circle, $x - $X, $y - $Y);
    $X = $x;
    $Y = $y;
}


#
# Benchmark usedamage
#
sub benchmarkUsedamage {
   my ($label, $usedamage) = @_;

   # Get usedamage value
   my $previousValue = $zinc->cget('-usedamage');

   # Force redisplay
   $zinc->tset($circle, 1, 0, 0, 1, 0, 0);
   $zinc->itemconfigure($circle, -sensitive => 0);
   $zinc->configure(-usedamage => $usedamage);
   $zinc->update();

   # Get current time
   my ($s0, $micros0) = Time::HiRes::gettimeofday();
   
   # Move our circle
   foreach my $i (1...$N) {
      $zinc->translate($circle, $delta, $delta);
      $zinc->update();
   }

   # Get current time
   my ($s, $micros) = Time::HiRes::gettimeofday();
   
   # Calculate delta time in ms
   my $time = ($s - $s0)*1000 + ($micros - $micros0)/1000;
   
   # Display time
   $label->configure(-text => $time.' ms');
   
   # Restore usedamage
   $zinc->configure(-usedamage => $previousValue);
   $zinc->itemconfigure($circle, -sensitive => 1);
}

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/wheelOfFortune.pl.













































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#!/usr/bin/perl
#
# This short script tries to demonstrate with a simple example what you can 
# do with Tk Zinc widget, in particular how to use group item, clipping, and
# transformations. 
# $Id$
# this demo has been developped by D. Etienne etienne@cena.fr
#

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk; 
# Zinc module is loaded...
use Tk::Zinc;


# We create a classical root widget called MainWindow; then we create Zinc 
# widget child with size, color and relief attributes, and we display it using
# the geometry manager called 'pack'.
my $mw = MainWindow->new;
$mw->geometry("320x565");
$mw->resizable(0,0);
my $zinc = $mw->Zinc(-width => 300, -height => 500, -backcolor => 'gray70',
		     -borderwidth => 3, -relief => 'sunken');
$zinc->pack;

# Then we create a gray filled rectangle, in which we will display explain text.
$zinc->add('rectangle', 1 , [10, 400, 290, 490],
	   -linewidth => 0,
	   -filled => 1,
	   -fillcolor => 'gray80',
	   );
my $text = $zinc->add('text', 1,
		      -position => [150, 445],
		      -anchor => 'center',
		      );

# Create the Wheel object (see Wheel.pm)
my $wheel = Wheel->new($zinc, 150, 500, 100);

# Display comment
&comment("Strike any key to begin");

# Create Tk binding
$mw->Tk::bind('<Key>', \&openmode);



MainLoop;



# Callback bound to '<Key>' event when wheel is unmapped
sub openmode {
    return if $wheel->ismoving;
    # set binding to unmap the wheel
    $mw->Tk::bind('<Key>', \&closemode);
    # set binding to rotate the hand
    $zinc->bind($wheel, '<1>', sub {$wheel->rotatehand(300)});
    # map the wheel
    $wheel->show(150, 150);
    # and then inform user
    &comment("Click on the wheel to rotate the hand.\n".
	     "Strike any other key to hide the wheel.");
}

# Callback bound to '<Key>' event when wheel is already mapped 
sub closemode {
    return if $wheel->ismoving;
    # set binding to map the wheel
    $mw->Tk::bind('<Key>', \&openmode);
    # unmap the wheel
    $wheel->hide(150, 400);
    # and then inform user
    &comment("Strike any key to show the wheel");
}

# Just display comment 
sub comment {
    my $string = shift;
    $zinc->itemconfigure($text, -text => $string);
}



#=============================================================================
#                 Wheel  Class
#=============================================================================
package Wheel;

use strict 'vars';
use Carp;


#====================
# Object constructor
#====================
sub new {
    my ($proto, $widget, $x, $y, $radius) = @_;
  
    # object attributes
    my $self = {
	'widget' => $widget,   # widget reference
	'origin' => [$x, $y],  # origin coordinates
	'radius' => $radius,   # wheel radius
	'topgroup' => undef,   # top Group item
	'itemclip' => undef,   # id of item which clips the wheel
	'hand' => undef,       # id of item wich represents the hand
	'angle' => 60,         # the angle between hand and jackpot
	'stepsnumber' => 10,   # animations parameters
	'afterdelay' => 60,
	'shrinkrate' => 0.8,   # zoom parameters
	'zoomrate' => 1.1   
	};
    bless $self;    
    
    # First, we create a new Group item for the wheel. Why a Group item ?
    # At least two reasons. Wheel object consists of several Zinc items,  
    # we'll see below; it moves when it is mapped or unmapped, grows when  
    # you hit the jackpot. So, it's more easy to apply such transformations 
    # to a structured items set, using Group capability, rather than apply 
    # to each item separately or using canvas-like Tags mechanism.
    # Second reason refers to clipping. When it is mapped or unmapped, wheel 
    # object is drawn inside a circle with variant radius; clipping is a 
    # specific property of Group item

    # That's why we create a Group item in the top group, and set its
    # coordinates.
    $self->{topgroup} = $widget->add('group', 1, -visible => 0);
    $widget->coords($self->{topgroup}, [$x, $y]);
    # All the following items will be created in this group...
    
    # Create the invisible Arc item used to clip the wheel, centered on the
    # group origin.
    $self->{itemclip} = $widget->add('arc',  $self->{topgroup},
				     [-$radius, -$radius, $radius, $radius],
				     -visible => 0,
				     );
    $widget->itemconfigure($self->{topgroup}, -clip => $self->{itemclip});

    # Create the wheel with 6 filled Arc items centered on the group origin
    my $i = 0;
    for my $color (qw(magenta blue cyan green yellow red)) {
	$widget->add('arc',  $self->{topgroup},
		     [-$radius, -$radius, $radius, $radius],
		     -visible => 1,
		     -filled => 1,
		     -closed => 1,
		     -extent => 60,
		     -pieslice => 1,
		     -fillcolor => $color,
		     -linewidth => 0,
		     -startangle => 60*$i ,
		     -tags => [$self],
		     );
	$i++;
    }
    
    # Create the Text item representing the jackpot.
    $widget->add('text', $self->{topgroup},
		 -position => [0, -$radius+20],
		 -font =>
		 '-adobe-helvetica-bold-o-normal--34-240-100-100-p-182-iso8859-1',
		 -anchor => 'center',
		 -text => "\$",
		 );
    
    # Create the closed Curve item representing the hand.
    # In order to make processing easier, its rotation axis will be placed
    # on the group origin.
    $self->{hand} = $widget->add('curve', $self->{topgroup},
				 [0, -$radius + 10, 20, -$radius + 40,
				  6, -$radius + 40, 20, 10,
				  -20, 10, -6, -$radius + 40,
				  -20, -$radius + 40],
				 -linewidth => 3,
				 -linecolor => 'gray40',
				 -filled => 1,
				 -fillcolor => 'gray80',
				 -closed => 1,
				 -tags => [$self]);
    # Then, we apply rotation to the hand using the Zinc 'rotation' method.
    $widget->rotate($self->{hand}, 3.1416/3);
    
    # Then we unmap the wheel; in fact, Group item is translated and its
    # clipping circle is shrunk to a point.
    $self->_clipAndTranslate($self->{shrinkrate}**$self->{stepsnumber});

    return $self;
    
}

#================
# Public methods
#================

# Return 1 if wheel is moving (opening or closing animation)
sub ismoving {
    my $self = shift;
    return 1 if $self->{opening} or $self->{closing};
}

# Display wheel with animation effect
sub show {
    my ($self, $x, $y) = @_;
    # simple lock management
    return if $self->{opening} or $self->{closing};
    $self->{opening} = 1;
    # start animation 
    $self->_open($x, $y, 0);
}


# Unmap wheel with animation effect
sub hide {
    my ($self, $x, $y) = @_;
    # simple lock management
    return if $self->{opening} or $self->{closing};
    $self->{closing} = 1;
    # start animation
    $self->_close($x, $y, 0);
}


# Just rotate the hand with animation effect.
sub rotatehand {
    my $self = shift;
    my $angle = shift;
    return if $self->{turning};
    $angle = 360 unless $angle;
    $self->{angle} += $angle;
    if ($self->{angle} % 360 == 0) {
	$self->{fortune} = 1;
    }
    $self->_rotatehand(2*3.1416*$angle/360);   
}


#=================
# Private methods
#=================

# Generate opening animation; see below _clipAndTranslate method for
# Zinc specific use.
sub _open {
    my ($self, $x, $y, $cnt) = @_;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};
    # first step of animation
    if ($cnt == 0) {
	$widget->itemconfigure($group, -visible => 1);
	my @pos = $widget->coords($group);
	$x = ($x - $pos[0])/$self->{stepsnumber};
	$y = ($y - $pos[1])/$self->{stepsnumber};
    # last step
    } elsif ($cnt == $self->{stepsnumber}) {
	$self->{opening} = undef;
	return;
    }
    $cnt++;
    # move and grow the wheel
    $self->_clipAndTranslate(1/$self->{shrinkrate}, $x, $y);
    # process the animation using the 'after' Tk defering method
    $widget->after($self->{afterdelay}, sub {$self->_open($x, $y, $cnt)});
}


# Generate closing animation; see below _clipAndTranslate method for
# Zinc specific use.
sub _close {
    my ($self, $x, $y, $cnt) = @_;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};
    # first step of animation
    if ($cnt == 0) {
	my @pos = $widget->coords($group);
	$x = ($x - $pos[0])/$self->{stepsnumber};
	$y = ($y - $pos[1])/$self->{stepsnumber};
    # last step
    } elsif ($cnt == $self->{stepsnumber}) {
	$widget->itemconfigure($group, -visible => 0);
	$self->{closing} = undef;
	return;
    }
    $cnt++;
    # move and shrink the wheel
    $self->_clipAndTranslate($self->{shrinkrate}, $x, $y);
    # process the animation using the 'after' Tk defering method
    $widget->after($self->{afterdelay}, sub {$self->_close($x, $y, $cnt)});
}


# Generate hand rotation animation.
sub _rotatehand {
    my ($self, $angle, $cnt) = @_;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};
    $self->{turning} = 1;
    # first step of animation
    if (not $cnt) {
	$angle /= $self->{stepsnumber};
    # last step
    } elsif ($cnt == $self->{stepsnumber}) {
	if ($self->{fortune}) {
	    $self->_fortune;
	} else {
	    $self->{turning} = undef;
	}
	return;
    }
    $cnt++;
    # use 'rotation' Zinc method.
    $widget->rotate($self->{hand}, $angle);
    
    # process the animation using the 'after' Tk defering method
    $widget->after($self->{afterdelay}, sub {$self->_rotatehand($angle, $cnt)});
        
}

# Generate growing animation to notify jackpot
sub _fortune {
    my ($self, $cnt) = @_;
    $cnt = 0 unless $cnt;
    my $zf;
    my $widget = $self->{widget};
    my $group = $self->{topgroup};
    my @pos = $widget->coords($group);
    # last step of animation
    if ($cnt == 6) {
	$self->{fortune} = undef;
	$self->{turning} = undef;
	return;
    # event steps : wheel grows
    } elsif ($cnt == 0 or $cnt % 2 == 0) {
	$zf = $self->{zoomrate};
    # odd steps : wheel is shrunk
    } else {
	$zf = 1/$self->{zoomrate};
    }
    $cnt++;
    
    # Now, we apply scale transformation to the Group item, using the 'scale'
    # Zinc method. Note that we reset group coords before scaling it, in order
    # that the origin of the transformation corresponds to the center of the
    # wheel. When scale is done, we restore previous coords of group.
    $widget->coords($group, [0, 0]);
    $widget->scale($group, $zf, $zf);
    $widget->coords($group, \@pos);
    
    # process the animation using the 'after' Tk defering method
    $widget->after(100, sub {$self->_fortune($cnt)});
    
}

# Update group clipping and translation, using 'scale' and 'translate'
# Zinc methods.
sub _clipAndTranslate {
    
    my ($self, $shrinkfactor, $x, $y) = @_;
    $x = 0 unless $x;
    $y = 0 unless $y;
    $self->{widget}->scale($self->{itemclip}, $shrinkfactor, $shrinkfactor);
    if ($Tk::Zinc::VERSION lt "3.297") {
	$self->{widget}->translate($self->{topgroup}, $x, $y);
    } else {
	my ($xc, $yc) = $self->{widget}->coords($self->{topgroup});
	$self->{widget}->coords($self->{topgroup}, [$xc + $x, $yc + $y]);
    }

}


1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/window-contours.pl.

































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/perl -w
# $Id$
# This simple demo has been developped by C. Mertz <mertz@cena.fr>

package window_contours; # for avoiding symbol collision between different demos

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

use Tk;
use Tk::Zinc;

use strict;

my $mw = MainWindow->new();


# Creating the zinc widget
my $zinc = $mw->Zinc(-width => 600, -height => 500,
		     -font => "9x15", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

# The explanation displayed when running this demo
$zinc->add('text', 1,
	   -position=> [10,10],
	   -text => 'These "windows" are simply rectangles holed by 4 smaller
rectangles. The text appears behind the window glasses.
You can drag text or "windows".',
	   -font => "10x20",
	   );

# Text in background
my $backtext = $zinc->add('text', 1,
			  -position=> [50,200],
			  -text => "This  text  appears\nthrough holes of  curves",
			  -font => "-adobe-helvetica-bold-o-normal--34-240-100-100-p-182-iso8859-1",
			  );

my $window = $zinc->add('curve', 1, [100,100 , 300,100, 300,400 , 100,400 ],
			-closed => 1, -visible => 1, -filled => 1,
			-fillcolor => "grey66",
			);

my $aGlass= $zinc->add('rectangle', 1, [120,120 , 190,240]);
$zinc->contour($window, 'add', +1, $aGlass);

$zinc->translate($aGlass, 90,0);
$zinc->contour($window, 'add', +1, $aGlass);

$zinc->translate($aGlass, 0,140);
$zinc->contour($window, 'add', +1, $aGlass);

$zinc->translate($aGlass, -90,0);
$zinc->contour($window, 'add', +1, $aGlass);

# deleting $aGlass which is no more usefull
$zinc->remove($aGlass);

# cloning $window
my $window2 = $zinc->clone($window);

# changing its background, moving it and scaling it!
$zinc->itemconfigure($window2, -fillcolor => "grey50");
$zinc->translate($window2, 30,50);
$zinc->scale($window, 0.8, 0.8);




# adding drag and drop callback to the two windows and backtext
foreach my $item ($window, $window2, $backtext) {
    # Some bindings for dragging the items
    $zinc->bind($item, '<ButtonPress-1>' => [\&press, $item, \&motion]);
    $zinc->bind($item, '<ButtonRelease-1>' => \&release);
}

# callback for starting a drag
my ($x_orig, $y_orig);
sub press {
    my ($zinc, $item, $action) = @_;
    my $ev = $zinc->XEvent();
    $x_orig = $ev->x;
    $y_orig = $ev->y;
    $zinc->Tk::bind('<Motion>', [$action, $item]);
}

# Callback for moving an item
sub motion {
    my ($zinc, $item) = @_;
    my $ev = $zinc->XEvent();
    my $x = $ev->x;
    my $y = $ev->y;

    $zinc->translate($item, $x-$x_orig, $y-$y_orig);
    $x_orig = $x;
    $y_orig = $y;
}


# Callback when releasing the mouse button. It removes any motion callback
sub release {
    my ($zinc) = @_;
    $zinc->Tk::bind('<Motion>', '');
}


Tk::MainLoop();


1;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_lib/zoom.pl.









































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/perl
# $Id$
# This simple demo has been developped by C. Schlienger <celine@intuilab.com>

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);


use Tk;
use Tk::Zinc;
use strict;


my $defaultfont = '-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*';
my $mw = MainWindow->new();

###########################################
# Text zone
###########################################

my $text = $mw->Text(-relief => 'sunken', -borderwidth => 2, -height => 4);
$text->pack(qw/-expand yes -fill both/);

$text->insert('0.0',
	      'This toy-appli shows zoom actions on waypoint and curve items.
The following operations are possible:
   Click "-" to zoom out
   Click "+" to zoom in ' );

###########################################
# Zinc
###########################################
my $zinc_width=600;
my $zinc_height=500;
my $zinc = $mw->Zinc(-width => $zinc_width, -height => $zinc_height,
		     -font => "10x20",
		     -borderwidth => 3, -relief => 'sunken',
		     )->pack;

###########################################
# Waypoints and sector
###########################################

my $wp_group = $zinc->add('group', 1, -visible => 1);

my $p1=[200, 100];
my $wp1 = $zinc->add('waypoint',$wp_group, 1,
		    -position => $p1,
		    -connectioncolor => 'green',
		    -symbolcolor => 'blue',
		    -labelformat => 'x20x18+0+0',
		    -leaderwidth=>'0',
		    -labeldx=>'-20'
		   );
$zinc->itemconfigure($wp1, 0,
		     -text => "DO",
		    );

my $p2=[300, 150];
my $wp2 = $zinc->add('waypoint',$wp_group, 1,
		     -position => $p2,
		     -connecteditem => $wp1,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'-20',
		    );

$zinc->itemconfigure($wp2, 0,
		     -text => "RE",
		    );

my $p3=[400, 50];
my $wp3 = $zinc->add('waypoint', $wp_group, 2,
		     -position => $p3,
		     -connecteditem => $wp2,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'20',
		     -labeldy=>'+10'
		    );
$zinc->itemconfigure($wp3, 0,
		     -text => "MI",
		    );

my $p4=[350, 450];
my $wp4 = $zinc->add('waypoint', $wp_group, 2,
			     -position => $p4,
			     -connecteditem => $wp2,
			     -connectioncolor => 'blue',
			     -symbolcolor => 'blue',
		    -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldy=>'-15'
		    );
$zinc->itemconfigure($wp4, 0,
		     -text => "FA",
		    );

		    
my $p5=[300, 250];
my $wp5 = $zinc->add('waypoint', $wp_group, 2,
		     -position => $p5,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldy=>'-15'
		    );
$zinc->itemconfigure($wp5, 0,
		     -text => "SOL",
		    );


my $p6=[170, 240];
my $wp6 = $zinc->add('waypoint', $wp_group, 2,
		     -position => $p6,
		     -connecteditem => $wp5,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'-20'
		    );
$zinc->itemconfigure($wp6, 0,
		     -text => "LA",
		    );

my $p7=[550, 200];
my $wp7 = $zinc->add('waypoint', $wp_group, 2,
		     -position => $p7,
		     -connecteditem => $wp5,
		     -connectioncolor => 'blue',
		     -symbolcolor => 'blue',
		     -labelformat => 'x20x18+0+0',
		     -leaderwidth=>'0',
		     -labeldx=>'20'
		    );
$zinc->itemconfigure($wp7, 0,
		     -text => "SI",
		    );


my $sector = $zinc ->add('curve',$wp_group,[300,0,400,50,500,100,550,200,550,400,350,450,170,240,200,100,300,0]);

###################################################
# control panel
###################################################
my $rc = $mw->Frame()->pack();

#the reference of the scale function is top-left corner of the zinc object
#so we first translate the group to zoom in order to put its center on top-left corner
#change the scale of the group
#translate the group to put it back at the center of the zinc object 

my $minus=$rc->Button(-width => 2, 
		      -height => 2,
		      -text => '-',
		      -command=>sub{
			$zinc->translate($wp_group,-$zinc_width/2,-$zinc_height/2);
			$zinc->scale($wp_group,0.8,0.8);
			$zinc->translate($wp_group, $zinc_width/2,$zinc_height/2);
		      })->pack(-side=>'left');


my $plus=$rc->Button(-width => 2, 
		     -height => 2,
		     -text => '+',
		     -command=>sub{
		       $zinc->translate($wp_group, -$zinc_width/2,-$zinc_height/2);
		       $zinc->scale($wp_group,1.2,1.2);
		       $zinc->translate($wp_group,$zinc_width/2,$zinc_height/2);
		     })->pack(-side => 'right');



MainLoop;

Added jni/tkzinc/Perl/demos/Tk/demos/zinc_pm/SimpleRadarControls.pm.























































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
package SimpleRadarControls;

# $Id$
# This simple radar has been initially developped by P. Lecoanet <lecoanet@cena.fr>
# It has been adapted by C. Mertz <mertz@cena.fr> for demo purpose.
# Thanks to Dunnigan,Jack [Edm]" <Jack.Dunnigan@EC.gc.ca> for a bug correction.


use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

$top = 1;

sub new {
    my $proto = shift;
    my $type = ref($proto) || $proto;
    my ($zinc) = @_;
    my $self = {};

    $self{'zinc'} = $zinc;
    $self{'cur_x'} = 0;
    $self{'cur_y'} = 0;
    $self{'cur_angle'} = 0;
    $self{'corner_x'} = 0;
    $self{'corner_y'} = 0;
    
    $self{'tlbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'tlbbox'}, [-3, -3, +3, +3]);
    $self{'trbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'trbbox'}, [-3, -3, +3, +3]);
    $self{'blbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'blbbox'}, [-3, -3, +3, +3]);
    $self{'brbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'brbbox'}, [-3, -3, +3, +3]);
    $zinc->add('rectangle', $top, [0, 0, 1, 1],
	       -linecolor => 'red', -tags => 'lasso',
	       -visible => 0, -sensitive => 0);

    $zinc->Tk::bind('<Shift-ButtonPress-1>', [\&start_lasso, $self]);
    $zinc->Tk::bind('<Shift-ButtonRelease-1>', [\&fin_lasso, $self]);

    $zinc->Tk::bind('<ButtonPress-2>', sub { my $ev = $zinc->XEvent();
					     my @closest = $zinc->find('closest',
								      $ev->x, $ev->y);
					     print "at point=$closest[0]\n" });
    
    $zinc->Tk::bind('<ButtonPress-3>', [\&press, $self, \&motion]);
    $zinc->Tk::bind('<ButtonRelease-3>', [\&release, $self]);
    
    $zinc->Tk::bind('<Shift-ButtonPress-3>', [\&press, $self, \&zoom]);
    $zinc->Tk::bind('<Shift-ButtonRelease-3>', [\&release, $self]);
    
    $zinc->Tk::bind('<Control-ButtonPress-3>', [\&press, $self, \&rotate]);
    $zinc->Tk::bind('<Control-ButtonRelease-3>', [\&release, $self]);
    
    $zinc->Tk::bind('current', '<Enter>', [\&showbox, $self]);
    $zinc->Tk::bind('current', '<Leave>', [\&hidebox, $self]);

    bless ($self, $type);
    return $self;
}

#
# Controls for the window transform.
#
sub press {
    my ($zinc, $self, $action) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;

    $self->{'cur_x'} = $lx;
    $self->{'cur_y'} = $ly;
    $self->{'cur_angle'} = atan2($ly, $lx);
    $zinc->Tk::bind('<Motion>', [$action, $self]);
}

sub motion {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @it;
    my @res;
    
    @it = $zinc->find('withtag', 'controls');
    if (scalar(@it) == 0) {
	return;
    }
    @res = $zinc->transform($it[0], [$lx, $ly, $self->{'cur_x'}, $self->{'cur_y'}]);
    $zinc->translate('controls', $res[0] - $res[2], $res[1] - $res[3]);
    $self->{'cur_x'} = $lx;
    $self->{'cur_y'} = $ly;
}

sub zoom {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $maxx;
    my $maxy;
    my $sx;
    my $sy;
    
    if ($lx > $self->{'cur_x'}) {
	$maxx = $lx;
    } else {
	$maxx = $self->{'cur_x'};
    }
    if ($ly > $self->{'cur_y'}) {
	$maxy = $ly
    } else {
	$maxy = $self->{'cur_y'};
    }
    #avoid illegal division by zero
    return unless ($maxx && $maxy);

    $sx = 1.0 + ($lx - $self->{'cur_x'})/$maxx;
    $sy = 1.0 + ($ly - $self->{'cur_y'})/$maxy;
    $self->{'cur_x'} = $lx if ($lx>0); # avoid ZnTransfoDecompose :singular matrix
    $self->{'cur_y'} = $ly if ($ly>0); # error messages
    $zinc->scale('controls', $sx, $sy);
#   $main::scale *= $sx;
#   main::update_transform($zinc);
}

sub rotate {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $langle;
    
    $langle = atan2($ly, $lx);
    $zinc->rotate('controls', -($langle - $self->{'cur_angle'}));
    $self->{'cur_angle'} = $langle;
}

sub release {
    my ($zinc, $self) = @_;
    $zinc->Tk::bind('<Motion>', '');
}

sub start_lasso {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @coords;
    
    $self->{'cur_x'} = $lx;
    $self->{'cur_y'} = $ly;
    $self->{'corner_x'} = $lx;
    $self->{'corner_y'} = $ly;
    @coords = $zinc->transform($top, [$lx, $ly]);
    $zinc->coords('lasso', [$coords[0], $coords[1], $coords[0], $coords[1]]);
    $zinc->itemconfigure('lasso', -visible => 1);
    $zinc->raise('lasso');
    $zinc->Tk::bind('<Motion>', [\&lasso, $self]);
}

sub lasso {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @coords;
    
    $self->{'corner_x'} = $lx;
    $self->{'corner_y'} = $ly;
    @coords = $zinc->transform($top, [$self->{'cur_x'}, $self->{'cur_y'}, $lx, $ly]);
    $zinc->coords('lasso', [$coords[0], $coords[1], $coords[2], $coords[3]]);
}

sub fin_lasso {
    my ($zinc, $self) = @_;
    my $enclosed;
    my $overlapping;
    
    $zinc->Tk::bind('<Motion>', '');
    $zinc->itemconfigure('lasso', -visible => 0);
    $enclosed = join(', ', $zinc->find('enclosed',
				       $self->{'cur_x'}, $self->{'cur_y'},
				       $self->{'corner_x'}, $self->{'corner_y'}));
    $overlapping = join(', ', $zinc->find('overlapping',
					  $self->{'cur_x'}, $self->{'cur_y'},
					  $self->{'corner_x'}, $self->{'corner_y'}));
    print "enclosed=$enclosed, overlapping=$overlapping\n";
}

sub showbox {
    my ($zinc, $self) = @_;
    my @coords;
    my @it;
    
    if (! $zinc->hastag('current', 'currentbbox')) {
	@it = $zinc->find('withtag', 'current');
	if (scalar(@it) == 0) {
	    return;
	}
	@coords = $zinc->transform($top, $zinc->bbox('current'));

	$zinc->coords($self->{'tlbbox'}, [$coords[0], $coords[1]]);
	$zinc->coords($self->{'trbbox'}, [$coords[2], $coords[1]]);
	$zinc->coords($self->{'brbbox'}, [$coords[2], $coords[3]]);
	$zinc->coords($self->{'blbbox'}, [$coords[0], $coords[3]]);
	$zinc->itemconfigure('currentbbox', -visible => 1);
    }
}

sub hidebox {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @next;
    
    @next = $zinc->find('closest', $lx, $ly);
    if ((scalar(@next) == 0) ||
	! $zinc->hastag($next[0], 'currentbbox') ||
	$zinc->hastag('current', 'currentbbox')) {
	$zinc->itemconfigure('currentbbox', -visible => 0);
    }
}


Added jni/tkzinc/Perl/demos/t/no-test.t.

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
#!/usr/bin/perl

BEGIN { $| = 1; print "1..1\n"; }
END {print "ok 1\n";}

print "No test for zinc demos, since they are by themselves Tk::Zinc tests\n";

1;

Added jni/tkzinc/Perl/demos/zinc-demos.













































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
#!/usr/bin/perl -w

#$id: $

eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
    if 0; # not running under some shell

require 5.004;

use Tk 800.000;
use Tk::Zinc;   # only for getting $Tk::Zinc::VERSION
use lib Tk->findINC('demos/widget_lib');
use Tk::widgets qw/Dialog ErrorDialog ROText/;
use WidgetDemo;
use subs qw/invoke lsearch see_code see_vars show_stat view_widget_code/;
use vars qw/$MW $FONT $WIDTRIB/;
use vars qw/$CODE $CODE_RERUN $CODE_TEXT $VARS $VIEW $VIEW_TEXT/;
use vars qw/$BRAKES $LIGHTS $OIL $SOBER $TRANS $WIPERS/;
use vars qw/$COLOR $FONT_STYLE $POINT_SIZE $DEMO_FILE %DEMO_DESCRIPTION/;
use strict;

use vars qw( $VERSION );
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);

my $version = $Tk::Zinc::VERSION;
print "Tkzinc version: $version\n";

$MW = Tk::MainWindow->new;
$MW->configure(-menu => my $menubar = $MW->Menu);

{
    package WidgetWrap;
    @WidgetWrap::ISA = qw/Tk::MainWindow/;

    # This magic conspires with widget's AUTOLOAD subroutine to make user
    # contributed demonstrations that don't use WidgetDemo embed properly.
    # The trick works because widget creates a superclass of Tk::MainWindow
    # which invokes WidgetDemo() implicitly. You loose if you bypass the
    # inheritance mechanism and call Tk::MainWindow directly.

    sub new {
	my ($name) = $::DEMO_FILE =~ m#([^/]+).pl$#;
	$::MW->WidgetDemo(-name => $name, -text => $::DEMO_DESCRIPTION{$name} || "" );
    }
}

@MainWindow::ISA = 'WidgetWrap';

$MW->title('TkZinc Perl demonstrations');
$FONT = '-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*';
my $widget_lib = Tk->findINC('demos/widget_lib');
# the previous simple statement $zinc_lib = Tk->findINC('demos/zinc_lib');
# found in some cases such old directory empty (e.g. after a previous package de-installation)
# So now, we look for a non-empty demos/zinc_lib directory (ie containing one of the demo!)
my $zinc_lib = Tk->findINC('demos/zinc_lib/tiger.pl');
($zinc_lib) = $zinc_lib =~ /(.*)\/tiger\.pl/;
my $wd = "$widget_lib/WidgetDemo.pm";
$WIDTRIB = Tk->findINC('demos/zinc_contrib_lib/README');
($WIDTRIB) = $WIDTRIB =~ /(.*)\/README/;
unless (Tk::tainting) {
    $WIDTRIB = $ENV{WIDTRIB} if defined $ENV{WIDTRIB};
    $WIDTRIB = $ARGV[0] if defined $ARGV[0];
}

# The code below creates the main window, consisting of a menu bar
# and a text widget that explains how to use the program, plus lists
# all of the demos as hypertext items.

my $file = $menubar->cascade(qw/-label File -underline 0 -menuitems/ =>
    [
      [cascade    => '~View', -menuitems =>
        [
          [command  => '~zinc-demos', -command => [\&view_widget_code, __FILE__]],
          [command  => '~WidgetDemo', -command => [\&view_widget_code, $wd]],
        ], # end cascade menuitems
      ], # end view cascade
      '',
      [command    => '~Quit', -command => [\&exit]],
    ]);

my $help = $menubar->cascade(qw/-label Help -underline 0 -menuitems/ =>
    [
      [command    => '~About'],
    ]);

my $T = $MW->Scrolled('ROText',
    -scrollbars => 'e',		
    -wrap       => 'word',
    -width      => 60,
    -height     => 30,
    -font       => $FONT,
    -setgrid    => 1,
)->grid(qw/-sticky nsew/);
$MW->gridRowconfigure(   0, -weight => 1); # allow expansion in both ...
$MW->gridColumnconfigure(0, -weight => 1); # ... X and Y dimensions

my $STATUS_VAR;
my $status = $MW->Label(-textvariable => \$STATUS_VAR, qw/-anchor w/);
$status->grid(qw/-sticky ew/);

# Create a bunch of tags to use in the text widget, such as those for
# section titles and demo descriptions.  Also define the bindings for
# tags.

$T->tagConfigure(qw/title -font -*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*/);
$T->tagConfigure(qw/demo -lmargin1 1c -lmargin2 1c -foreground blue/);

if ($MW->depth  == 1) {
    $T->tagConfigure(qw/hot -background black -foreground white/);
    $T->tagConfigure(qw/visited -lmargin1 1c -lmargin2 1c -underline 1/);
} else {
    $T->tagConfigure(qw/hot -relief raised -borderwidth 1 -foreground red/);
    $T->tagConfigure(qw/visited -lmargin1 1c -lmargin2 1c -foreground/ =>
	    '#303080');
}

$T->tagBind(qw/demo <ButtonRelease-1>/ => \&invoke);
my $last_line = '';
$T->tagBind(qw/demo <Enter>/ => [sub {
	my($text, $sv) = @_;
	my $e = $text->XEvent;
	my($x, $y) = ($e->x, $e->y);
	$last_line = $text->index("\@$x,$y linestart");
	$text->tagAdd('hot', $last_line, "$last_line lineend");
	$text->configure(qw/-cursor hand2/);
	show_stat $sv, $text, $text->index('current');
    }, \$STATUS_VAR]
);
$T->tagBind(qw/demo <Leave>/ => [sub {
	my($text, $sv) = @_;
	$text->tagRemove(qw/hot 1.0 end/);
	$text->configure(qw/-cursor xterm/);
	$$sv = '';
    }, \$STATUS_VAR]
);
$T->tagBind(qw/demo <Motion>/ => [sub {
	my($text, $sv) = @_;
	my $e = $text->XEvent;
	my($x, $y) = ($e->x, $e->y);
	my $new_line = $text->index("\@$x,$y linestart");
	if ($new_line ne $last_line) {
	    $text->tagRemove(qw/hot 1.0 end/);
	    $last_line = $new_line;
	    $text->tagAdd('hot', $last_line, "$last_line lineend");
	}
	show_stat $sv, $text, $text->index('current');
    }, \$STATUS_VAR]
);

# Create the text for the text widget.

$T->insert('end', "TkZinc perl Demonstrations ($version)\n", 'title');
$T->insert('end',
"\nThis application provides a front end for several short scripts in perl/Tk that demonstrate what you can do with the TkZinc widget.  Each of the numbered lines below describes a demonstration;  you can click on it to invoke the demonstration.  Once the demonstration window appears, you can click the \"See Code\" button to see the Perl/Tk code that created the demonstration.\n");

$T->insert('end', "\n", '', "Small applications\n", 'title');
$T->insert('end', "1. A simple animated application \"the Wheel of Fortune\".\n", [qw/demo demo-wheelOfFortune/]);
$T->insert('end', "2. A simple radar display.\n", [qw/demo demo-simpleradar/]);
$T->insert('end', "3. Zetris a clone of the famous tetris game (requires openGL.)\n", [qw/demo demo-Zetris/]);
$T->insert('end', "4. ATC sample fake electronic strips (nicer with openGL.)\n", [qw/demo demo-groups_in_ATC_strips/]);
$T->insert('end', "5. The famous tiger using the X11 shape extension. (nicer with openGL)\n", [qw/demo demo-tiger/]);
$T->insert('end', "6. A magic lens based on Graphics.pm. (nicer with openGL)\n", [qw/demo demo-MagicLens/]);


$T->insert('end', "\n", '', "All Items\n", 'title');
$T->insert('end', "1. Examples of all items.\n", [qw/demo demo-items/]);
$T->insert('end', "2. All items options (and their types).\n", [qw/demo demo-all_options/]);
$T->insert('end', "3. Examples of line style and line termination.\n", [qw/demo demo-lines/]);
$T->insert('end', "4. Curves with multiple contours.\n", [qw/demo demo-contours/]);
$T->insert('end', "5. Examples of labelformat.\n", [qw/demo demo-labelformat/]);
$T->insert('end', "6. Use of mapinfos.\n", [qw/demo demo-mapinfo/]);
$T->insert('end', "7. Curves with cubic bezier control points.\n", [qw/demo demo-curve_bezier/]);
$T->insert('end', "8. Curves with multiple contours and various fillrule.\n", [qw/demo demo-fillrule/]);


$T->insert('end', "\n", '', "Groups, Priority, Clipping and PathTags\n", 'title');
$T->insert('end', "1. Groups and Priorities.\n", [qw/demo demo-groups_priority/]);
$T->insert('end', "2. Clipping examples (with simple or multiple contours).\n", [qw/demo demo-clipping/]);
$T->insert('end', "3. Group atomicity.\n", [qw/demo demo-atomic-groups/]);
$T->insert('end', "4. \"Windows\" with four glasses using curve with multiple contours.\n", [qw/demo demo-window-contours/]);
$T->insert('end', "5. A counter quite impossible to do without clipping (requires openGL).\n", [qw/demo demo-counter/]);
$T->insert('end', "6. Using pathTags.\n", [qw/demo demo-path_tags/]);

$T->insert('end', "\n", '', "Interactions\n", 'title');
$T->insert('end', "1. Simple interaction on a track.\n", [qw/demo demo-simple_interaction_track/]);
$T->insert('end', "2. Text input in a text item and a track item.\n", [qw/demo demo-textInput/]);


$T->insert('end', "\n", '', "Transformation\n", 'title');
$T->insert('end', "1. Translating.\n", [qw/demo demo-translation/]);
$T->insert('end', "2. Rotating.\n",    [qw/demo demo-rotation/]);
$T->insert('end', "3. Zooming.\n",     [qw/demo demo-zoom/]);
$T->insert('end', "4. Transformation testbed.\n",     [qw/demo demo-transforms/]);
$T->insert('end', "5. Zooming/Rotating icon and text. (even without openGL)\n",     [qw/demo demo-icon_zoom_resize/]);

$T->insert('end', "\n", '', "Use of openGL\n", 'title');
$T->insert('end', "1. A zoomable/rotatable TkZinc Logo (better with openGL).\n",  [qw/demo demo-tkZincLogo/]);
$T->insert('end', "2. Axial color variation on the X axis (requires openGL).\n", [qw/demo demo-color-x/]);
$T->insert('end', "3. Axial color variation on the Y axis (requires openGL).\n", [qw/demo demo-color-y/]);
$T->insert('end', "4. Circular color variation (requires openGL).\n", [qw/demo demo-color-circular/]);
$T->insert('end', "5. Path and Conical color variations (requires openGL).\n", [qw/demo demo-color-path-and-conic/]);
$T->insert('end', "6. The triangles item (requires openGL).\n",  [qw/demo demo-triangles/]);
$T->insert('end', "7. A set of demos based on Graphics.pm module (really better with openGL).\n",  [qw/demo demo-testGraphics/]);
$T->insert('end', "8. OpenGL optimization (requires openGL).\n", [qw/demo demo-usedamage/]);


$T->insert('end', "\n", '', "User Contributed Demonstrations\n", 'title');
opendir(C, $WIDTRIB) or warn "Cannot open $WIDTRIB: $!";
my(@dirent) = grep /^.+\.pl$/, sort(readdir C);
closedir C;
unshift @dirent, 'TEMPLATE.pl';	# I want it first
my $i = 0;
while ($_ = shift @dirent) {
    next if /TEMPLATE\.pl/ and $i != 0;
    unless (open(C, "$WIDTRIB/$_")) {
	warn "Cannot open $_: $!" unless /TEMPLATE\.pl/;
	next;
    }
    my($name) = /^(.*)\.pl$/;
    $_ = <C>; $_ = <C>; 
    my($title) = /^#\s*(.*)$/;
    $DEMO_DESCRIPTION{$name} = $title;
    close C;
    $T->insert('end', ++$i . ". $title\n", ['demo', "demo-$name"]);
}

# Create all the dialogs required by this demonstration.

my $DIALOG_ABOUT = $MW->Dialog(
    -title          => 'About zinc-demos',
    -bitmap         => 'info',
    -default_button => 'OK',
    -buttons        => ['OK'],
    -text           => "TkZinc Perl demonstrations\n\nPerl Version $]" .
		       "\nTk Version $Tk::VERSION" .
                       "\nTkZinc Version $Tk::Zinc::VERSION\n",
);
$help->cget(-menu)->entryconfigure('About',
    -command => [$DIALOG_ABOUT => 'Show'],
);

my $DIALOG_ICON = $MW->Dialog(
    -title          => 'Bitmap Menu Entry',
    -bitmap         => undef,
    -default_button => 'OK',
    -buttons        => ['OK'],
    -text           => 'The menu entry you invoked displays a bitmap rather than a text string.  Other than this, it is just like any other menu entry.',
);
$DIALOG_ICON->configure(-bitmap => undef); # keep -w from complaining

MainLoop;

sub AUTOLOAD {

    # This routine handles the loading of most demo methods.

    my($demo) = @_;

    $T->Busy;
    {
	$DEMO_FILE = "$WIDTRIB/${demo}.pl" if -f "$WIDTRIB/${demo}.pl";
	$DEMO_FILE = "$zinc_lib/${demo}.pl" if -f "$zinc_lib/${demo}.pl";
	if (defined $DEMO_FILE) {
	    do $DEMO_FILE ;
	} else { warn "No such demo: $demo.pl in either $WIDTRIB/ or $zinc_lib/\n"; }
	warn $@ if $@;
    }
    $T->Unbusy;
    goto &$::AUTOLOAD if defined &$::AUTOLOAD;

} # end AUTOLOAD

sub invoke {

    # This procedure is called when the user clicks on a demo description.

    my($text) = @_;

    my $index = $text->index('current');
    my @tags = $T->tagNames($index);
    my $i = lsearch('demo\-.*', @tags);
    return if $i < 0;
    my($demo) = $tags[$i] =~ /demo-(.*)/;
    $T->tagAdd('visited', "$index linestart", "$index lineend");
    {
	no strict 'refs';
	&$demo($demo);
    }

} # end invoke

sub lsearch {

    # Search the list using the supplied regular expression and return it's
    # ordinal, or -1 if not found.

    my($regexp, @list) = @_;
    my($i);

    for ($i=0; $i<=$#list; $i++) {
        return $i if $list[$i] =~ /$regexp/;
    }
    return -1;

} # end lsearch

sub see_code {

    # This procedure creates a toplevel window that displays the code for
    # a demonstration and allows it to be edited and reinvoked.

    my($demo) = @_;

    my $file = "${demo}.pl";
    if (not Exists $CODE) {
	$CODE = $MW->Toplevel;
	my $code_buttons = $CODE->Frame;
	$code_buttons->pack(qw/-side bottom -fill x/);
	my $code_buttons_dismiss = $code_buttons->Button(
            -text    => 'Dismiss',
            -command => [$CODE => 'withdraw'],
	);
	$CODE_RERUN = $code_buttons->Button(-text => 'Rerun Demo');
	$CODE_TEXT = $CODE->Scrolled('Text',
				     qw/-scrollbars e -height 40 -setgrid 1/);
	$code_buttons_dismiss->pack(qw/-side left -expand 1/);
	$CODE_RERUN->pack(qw/-side left -expand 1/);
	$CODE_TEXT->pack(qw/-side left -expand 1 -fill both/);
    } else {
	$CODE->deiconify;
	$CODE->raise;
    }
    $CODE_RERUN->configure(-command => sub {
	eval $CODE_TEXT->get(qw/1.0 end/);
	{
	    no strict 'refs';
	    &$demo($demo);
	}
    });
    $CODE->iconname($file);
    $file = "$WIDTRIB/${demo}.pl" if -f "$WIDTRIB/${demo}.pl";
    $file = "$zinc_lib/${demo}.pl" if -f "$zinc_lib/${demo}.pl";
    $CODE->title("Demo code: $file");
    $CODE_TEXT->delete(qw/1.0 end/);
    open(CODE, "<$file") or warn "Cannot open demo file $file: $!";
    {
	local $/ = undef;
	$CODE_TEXT->insert('1.0', <CODE>);
    }
    close CODE;
    $CODE_TEXT->markSet(qw/insert 1.0/);

} # end see_code

sub see_vars {

    # Create a top-level window that displays a bunch of global variable values
    # and keeps the display up-to-date even when the variables change value.
    # $args is a pointer to a list of list of 2:
    #
    #   ["variable description", \$VAR]
    #
    # The old trick of passing a string to serve as the description and a soft
    # reference to the variable no longer works with lexicals and use strict.

    my($parent, $args) = @_;

    $VARS->destroy if Exists($VARS);
    $VARS = $parent->Toplevel;
    $VARS->geometry('+300+300');
    $VARS->title('Variable Values');
    $VARS->iconname('Variables');

    my $title = $VARS->Label(
        -text   => 'Variable Values:',
        -width  => 20,
        -anchor => 'center',
        -font   => '-*-helvetica-medium-r-normal--*-180-*-*-*-*-*-*',
    );
    $title->pack(qw/-side top -fill x/);
    my($label, $var);
    foreach my $i (@$args) {
	($label, $var) = @$i;
	my $wf = $VARS->Frame->pack(qw/-anchor w/);
	$wf->Label(-text => "$label: ")->pack(qw/-side left/);
	$wf->Label(-textvariable => $var)->pack(qw/-side left/);
    }
    $VARS->Button(-text => 'OK', -command => [$VARS => 'destroy'])->
        pack(qw/-side bottom -pady 2/);

} # end see_vars

sub show_stat {

    # Display name of current demonstration.  $sv is a reference to the
    # status Label -textvariable, $text is the Text widget reference and
    # $index is the demonstration index in the Text widget.

    my($sv, $text, $index) = @_;

    my @tags = $text->tagNames($index);
    my $i = lsearch('demo\-.*', @tags);
    return if $i < 0;
    my($demo) = $tags[$i] =~ /demo-(.*)/;
    $$sv = "Click Button-1 to run the \"$demo\" demonstration.";

} # end show_stat

sub view_widget_code {

    # Expose a file's innards to the world too, but only for viewing.

    my($widget) = @_;

    if (not Exists $VIEW) {
	$VIEW = $MW->Toplevel;
	$VIEW->iconname('widget');
	my $view_buttons = $VIEW->Frame;
	$view_buttons->pack(qw/-side bottom -expand 1 -fill x/);
	my $view_buttons_dismiss = $view_buttons->Button(
            -text    => 'Dismiss',
            -command => [$VIEW => 'withdraw'],
	);
	$view_buttons_dismiss->pack(qw/-side left -expand 1/);
	$VIEW_TEXT = $VIEW->Scrolled('Text',
				     qw/-scrollbars e -height 40 -setgrid 1/);
	$VIEW_TEXT->pack(qw/-side left -expand 1 -fill both/);
    } else {
	$VIEW->deiconify;
	$VIEW->raise;
    }
    $VIEW->title("Demo code: $widget");
    $VIEW_TEXT->configure(qw/-state normal/);
    $VIEW_TEXT->delete(qw/1.0 end/);
    open(VIEW, "<$widget") or warn "Cannot open demo file $widget: $!";
    {
	local $/ = undef;
	$VIEW_TEXT->insert('1.0', <VIEW>);
    }
    close VIEW;
    $VIEW_TEXT->markSet(qw/insert 1.0/);
    $VIEW_TEXT->configure(qw/-state disabled/);

} # end view_widget_code

__END__

=head1 NAME

zinc-demos - Demonstration of TkZinc widget functionnality

=head1 SYNOPSYS

  zinc-demos [ directory ]

=head1 DESCRIPTION

This script demonstrates the various functions offered by Tk Zinc widget.
This file only contains code to
generate the main window for the application, which invokes individual
demonstrations.  The code for the actual demonstrations is contained in
separate ".pl" files in the "zinc_lib" directory, which are autoloaded
by this script as needed.

widget looks in the directory specified on the command line to load user
contributed demonstrations.  If no directory name is specified when widget is
invoked and the environment variable WIDTRIB is defined then demonstrations
are loaded from the WIDTRIB directory. If WIDTRIB is undefined then widget
defaults to the released user contributed directory, "zinc_contrib_lib".

=head2 History

 #
 # Stephen O. Lidie, LUCC, 96/03/11.  lusol@Lehigh.EDU
 # Stephen O. Lidie, LUCC, 97/01/01.  lusol@Lehigh.EDU
 # Stephen O. Lidie, LUCC, 97/02/11.  lusol@Lehigh.EDU
 # Stephen O. Lidie, LUCC, 97/06/07.  lusol@Lehigh.EDU
 #     Update for Tk402.00x.  Total revamp:  WidgetDemo, Scrolled, released
 #     composites, -menuitems, qw//, etcetera.  Perl 5.004 required.
 # Stephen O. Lidie, LUCC, 98/03/10.  lusol@Lehigh.EDU
 #     Update for Tk8.
 # Stephen O. Lidie, LUCC, 98/06/26.  Stephen.O.Lidie@Lehigh.EDU
 #     Add Common Dialogs for Tk800.007.
 # Stephen.O.Lidie@Lehigh.EDU, 1999/11/29, Lehigh University.
 #     Demo some "dash patch" changes.
 # Stephen.O.Lidie@Lehigh.EDU, 2000/01/11, Lehigh University.
 #     Update menubar to Tk 8, fix color palette Menubutton demo.
 # Stephen.O.Lidie@Lehigh.EDU, 2000/07/06, Lehigh University.
 #     Remove inswt() from widget and styles.pl to show the proper Perl/Tk
 #     idiom for inserting Text tags.  Various and sundry cleanups.
 # Christophe Mertz <mertz@cena.fr>, 2002/03/06, CENA fr
 #     adaptation for zinc demos purposes.

=head1 AUTHOR

Steve Lidie <Stephen.O.Lidie@Lehigh.EDU> and slight adaptation by Christophe Mertz <mertz@cena.fr>

=head1 SEE ALSO

The zinc documentation is available as a pdf file refman.pdf and as an html pages refman/index.html

=cut

Added jni/tkzinc/Perl/export2cpan.



































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/usr/bin/perl

#
# If we want to extract a release right out of the repository
# just pass the release tag as first parameter and the script
# will leave a tarball in the current directory after chewing
# a moment in /tmp.
# the first argument should be a CVS tag looking like cpan_3_2_95
# or cpan_3_295. The second underscore will be removed for computing the
# 

# In the other case (no parameters) the script supposes we are
# in the Perl subdir of a Tkzinc working directory and it will
# setup zinc-perl for compilation in export2cpan/tk-zinc-<version>.
# The source files are taken from the working directory. This is
# the anticipated behavior when developping/testing or making
# a debian package from the rules file.
# this script has been provided by mertz @ intuilab dot com
# $Id$

use strict;

my $ZINC_PREFIX = 'tk-zinc';
my $DEFAULT_SERVER = 'cvs.tkzinc.org';
my $DEFAULT_CVS_MODULE = '/srv/tkzinc/cvsroot';
my $TMP = '/tmp/forCPAN';

# computing major, minor and patchlevel from var defined in ../configure.in
sub version4cpan {
    my $configure_in = "../configure.in";
    
    open(FD, "<$configure_in") or die "Could not open file $configure_in";
    
    my ($major, $minor, $patchlevel);
    while (<FD>) {
	if (/^MAJOR_VERSION=(\d+)/)
	    {
		$major = $1;
	    }
	elsif (/^MINOR_VERSION=(\d+)/)
	    {
		$minor = $1;
	    }
	elsif (/^PATCHLEVEL=(\d+)/)
	    {
		$patchlevel = $1;
	    }
    }

    close (FD);
    
    print "PATCHLEVEL: $patchlevel\n";
    return sprintf ("%d.%d%02d", $major,$minor,$patchlevel);
}

sub filesubst {
    my ($fileIn, $fileOut, $key, $val) = @_;

    open(FDIN, "<$fileIn") or die "Could not open input file $fileIn";
    open(FDOUT, ">$fileOut") or die "Could not open output file $fileOut";

    while (<FDIN>) {
	if (/$key/) {
	    s/$key/$val/g;
	}
	print FDOUT $_;
    }

    close(FDIN);
    close(FDOUT);
}

my $VERSION;
my $FROM_CVS = (scalar(@ARGV) != 0);
my $DIR_FROM_CVS;
my $CWD;
chomp($CWD = `pwd`);
#
# See if parameters are given (there should be a cvs tag
# and may be the repository machine).
#
if ($FROM_CVS) {
    my $tag_version;
    my $cvstag = $ARGV[0];
    my $server = $DEFAULT_SERVER;
    if (scalar(@ARGV) == 2) {
	$server = $ARGV[1];
    }
    print "Building a CPAN release tarball from tag $cvstag.\n";
    $cvstag =~ /^.*?([\d_]+)$/;
    my $tag_version = $1;
    if ($tag_version =~ /(\d+)_(\d+)_(\d+)/) {
	$tag_version = "$1_$2$3";
    }
    $VERSION = version4cpan;   # version computed from the source directory
    $DIR_FROM_CVS = "$ZINC_PREFIX-$VERSION";
    system("rm -rf $TMP");
    system ("mkdir $TMP");
    chdir("$TMP");
    # the following command always fail with cvs 1.11.1p1 !!
     my $command = "cd $TMP; cvs -d $server:$DEFAULT_CVS_MODULE export -r $cvstag -d $DIR_FROM_CVS Tkzinc";
    # my $command = "cd $TMP; cvs -d /pii/repository export -r $cvstag -d $DIR_FROM_CVS Tkzinc";
    print "$command\n";
    my $error = system($command);
    die "CVS extraction did not succeed" if $error;
    chdir("$DIR_FROM_CVS/Perl");
    my $EXTRACTED_VERSION = version4cpan; # version gotten from the tagged CVS files
    if ($EXTRACTED_VERSION ne $VERSION) {
	print "Oops! the tag version '$tag_version' does not match the version '$VERSION' in the sources, aborting\n";
	exit(1);
    }
    system ("cd $TMP/$DIR_FROM_CVS; ./configure");
}
else {
    $VERSION = version4cpan;
    print "cd ..; ./configure\n";
    system ("cd ..; ./configure"); # for creating  Makefile.pl from xxx.in files
}

print "VERSION $VERSION\n";

# using rsync if available rather than cp
my $CP = 'cp -r';
my $CPonlyIfDifferent = 'cp -r';
my $RSYNC = 0;
if (-x '/usr/bin/rsync') {
  $CP = '/usr/bin/rsync -rp';        # the --delete option has been removed to avoid deleting Makefile in demos
  $CPonlyIfDifferent = '/usr/bin/rsync -rc';
#  print "\$CP = '$CP'\n";
  $RSYNC = 1;
} elsif (-x '/usr/local/bin/rsync') {
  $CP = '/usr/local/bin/rsync -rp';  # the --delete option has been removed to avoid deleting Makefile in demos
  $CPonlyIfDifferent = '/usr/local/bin/rsync -rc';
#  print "\$CP = '$CP'\n";
  $RSYNC = 1;
}

my $EXPORT_DIR = '../export2cpan';
my $VERSION_DIR = "$ZINC_PREFIX-$VERSION";

if (-d "$EXPORT_DIR/$VERSION_DIR" and !$RSYNC) {
    system("rm -rf $EXPORT_DIR/$VERSION_DIR");
}

if (! -d $EXPORT_DIR) {
    mkdir($EXPORT_DIR);
}
if (! -d "$EXPORT_DIR/$VERSION_DIR") {
  mkdir("$EXPORT_DIR/$VERSION_DIR");
}
symlink ("$EXPORT_DIR/$VERSION_DIR", "$EXPORT_DIR/$ZINC_PREFIX");

my @files=('t', 'Zinc.xs', 'demos', 'README', 'Zinc');


foreach my $f (@files) {
    system("$CP $f $EXPORT_DIR/$VERSION_DIR");
}

# modifying the $VERSION of Zinc.pm with the correctly perl formated version scheme.
&filesubst ('Zinc.pm', "$EXPORT_DIR/$VERSION_DIR/Zinc.pm", '^\$VERSION *=.*;', "\$VERSION = $VERSION;");
&filesubst ('Makefile.PL', "$EXPORT_DIR/$VERSION_DIR/Makefile.PL", '^my \$VERSION *=.*;', "my \$VERSION = $VERSION;");

system("$CP ../Copyright $EXPORT_DIR/$VERSION_DIR");
system("$CP ../generic/*.c $EXPORT_DIR/$VERSION_DIR");
system("$CP ../generic/*.h $EXPORT_DIR/$VERSION_DIR");
system("$CP ../win/*.c $EXPORT_DIR/$VERSION_DIR");


#
# If working for an exported copy, build a tarball in the
# current dir.
#
if ($FROM_CVS) {
    chdir("$EXPORT_DIR/$VERSION_DIR");
    
    #
    # Remove the .cvsignore files
    system('find . -name .cvsignore | xargs rm -f');

    #
    # Create the MANIFEST file
    use ExtUtils::Manifest qw( mkmanifest );
    $ExtUtils::Manifest::Quiet = 1;
    &mkmanifest();

    chdir('..');

    system("tar zcf $TMP/$ZINC_PREFIX-$VERSION.tar.gz $VERSION_DIR");
    chdir($CWD);
    print "The tarball is in $TMP/$ZINC_PREFIX-$VERSION.tar.gz\n";
    print "You may want to clean up after testing in $TMP/$DIR_FROM_CVS\n";
}

Added jni/tkzinc/Perl/t/AnimatedGradient.t.





















































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz  mertz@intuilab.com
#

# this test mainly does funny effects when openGL is on


# testing all the import

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 18;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}

use strict;
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 200, -height => 200, -backcolor => "white",
                     -render => 1)->pack;

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");


$zinc->after(10, \&proceedTests);

Tk::MainLoop;

sub proceedTests {

$zinc->add('text', 1, -position => [10,5], -text => 
"the gradient fills a rectangle 
which is clipped by the curve 
made of two circles...\n"x5);
 

my $circle1 = $zinc->add('arc', 1, [20,20,180,180]);
my $circle2 = $zinc->add('arc', 1, [70,70,130,130]);

my $curve = $zinc->add('curve', 1, [], 
                       -fillcolor => 'red', -filled => 1, -linewidth => 1);
$zinc->contour($curve, 'add', 1, $circle1);
$zinc->contour($curve, 'add', -1, $circle2);

$zinc->remove($circle1);
$zinc->remove($circle2);

my $gradient;
for (1..4) { 
  for (my $i = 0; $i <=360; $i++) {
    $gradient = "=axial $i | red | white 50 | blue";
    $zinc->itemconfigure($curve, -fillcolor => $gradient); 
    $zinc->update;
  }
}
pass("turning gradient one side");

for (1..4) {
  for (1..100) {
    $zinc->translate($curve,0.5,0.5);
    $zinc->update;
  }
  for (1..800) {
    $zinc->rotate($curve, 3.14159/400, 100,100);
    $zinc->update;
  }
  for (1..100) {
    $zinc->translate($curve,0.5,0.5);
    $zinc->update;
  }
  
  for (1..400) {
    $zinc->translate($curve,-0.5,-0.5);
    $zinc->update;
  }
  for (1..200) {
    $zinc->translate($curve,0.5,0.5);
    $zinc->update;
  }
  pass ("shaking the circle around");
}

for (1..4) { 
  for (my $i = 359; $i > 0; $i--) {
    $gradient = "=axial $i | red | white 50 | blue";
    $zinc->itemconfigure($curve, -fillcolor => $gradient); 
    $zinc->update;
  }
}
pass("turning gradient the other side");


my $gr = $zinc->add('group', 1);
my $rect = $zinc->add('rectangle', $gr, [0,-480,200,180], -filled => 1,
                      -fillcolor => "=axial 90 |blue|white 10|red 20|white 30|blue 40|white 50|red 60|white 70|blue 80|white 90|red");

$zinc->chggroup($curve, $gr);
$zinc->itemconfigure($curve, -visible => 0);

$zinc->itemconfigure($gr, -clip => $curve);


pass("displaying a translated rectangle filled with froggy colors and clipped by two circles");
for (1..2) {
  for (my $i = 0; $i<500 ; $i++) {
    $zinc->translate($rect, 0,1);
    $zinc->update;
  }
  for (my $i = 0; $i<500 ; $i++) {
    $zinc->translate($rect, 0,-1);
    $zinc->update;
  }
  pass ("a thousand translation");
}

$zinc->translate($rect, 0,250);


for (1..1000) {
  $zinc->scale($rect, 1, 0.998, 100,100);
  $zinc->update;
}
pass("a thousand scaling down");


for (1..360) {
  $zinc->rotate($rect, 3.14159/180, 100,100);
  $zinc->update;
}
pass("360 rotation of 1°");


for (1..360) {
  $zinc->rotate($rect, -3.14159/180, 100,100);
  $zinc->update;
}
pass("360 rotation of 1°");


for (1..360) {
  $zinc->rotate($rect, -3.14159/180, 100,100);
  $zinc->update;
}


for (1..1000) {
  $zinc->scale($rect, 1, 1/0.998, 100,100);
  $zinc->update;
}
pass("a thousand scaling up");



for (1..4) {
  for my $i (0..200) {
    $zinc->itemconfigure($gr, -alpha => (200-$i)/2);
    $zinc->update;
  }
  for my $i (0..200) {
    $zinc->itemconfigure($gr, -alpha => $i/2);
    $zinc->update;
  }
  pass("fade out/in in 400 steps");
}

exit;

}

Added jni/tkzinc/Perl/t/Bbox-curve-multi-contour.t.

































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/perl -w 

#
# $Id$
# Author: Christophe Mertz  mertz@intuilab.com, adapted from a script 
# reported by Daniel Etienne for a bug report in Tk::Zinc 3.3.0
#

use strict;

# testing all the import

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 4;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}
use Tk;

my $mw = MainWindow->new;
my $zinc = $mw->Zinc(-render => 1, -width => 800, -height => 500);
$zinc->pack;
like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");

my $n = 8;

##  test cannot be run directly since $zinc->update does not work properly 
##  when not in a  mainloop
##  so I use a timer to trigger tests after entering the mainloop

$zinc->after(10, \&testExecute);  

Tk::MainLoop;

sub testExecute {

    # first
    my $group = $zinc->add('group', 1);
    $zinc->coords($group, [100, 250]);

    my $curve = $zinc->add('curve', $group, [],
                           -fillrule => 'nonzero',
                           -closed => 1,
                           -filled => 1,
                           -fillcolor => 'black',
                           -linecolor => 'red',
                           );
    my $arc = $zinc->add('arc', $group, [-50, -50, 50, 50]);
    $zinc->contour($curve, 'add', 1, $arc);
    $zinc->remove($arc);
    
    for (1..$n) {
        my $arc = $zinc->add('arc', $group, [-15, -70, 15, -40]);
        $zinc->rotate($arc, ($_-1)*(360/$n), 'degree');
        $zinc->contour($curve, 'add', 1, $arc);
        $zinc->remove($arc);
    }
    
    ok(&similarFlatArray ([$zinc->bbox($group)],
                          [28,178, 172, 322],   # beware this coordinates are
                          # not exactly the good one
                          [2,2,   2,2 ],
                          ),
       "bbox of left figure");
    
    
     # second
    $group = $zinc->add('group', 1);
    $zinc->coords($group, [350, 250]);
    
    $curve = $zinc->add('curve', $group, [],
                        -fillrule => 'nonzero',
                        -closed => 1,
                        -filled => 1,
                        -fillcolor => 'black',
                        -linecolor => 'red',
                        );
    $arc = $zinc->add('arc', $group, [-30, -30, 30, 30]);
    $zinc->contour($curve, 'add', 1, $arc);
    $zinc->remove($arc);
    
    for (1..$n) {
        my $arc = $zinc->add('arc', $group, [-15, -70, 15, -40]);
        $zinc->rotate($arc, ($_-1)*(360/$n), 'degree');
        $zinc->contour($curve, 'add', 1, $arc);
        $zinc->remove($arc);
    }
    &showbbox($group);
    ok(&similarFlatArray ([$zinc->bbox($group)],
                          [278,178, 422,322],   # beware this coordinates are 
                          # not exactly the good one
                          [2,2,   2,2 ],
                          ),
       "bbox of middle figure");
    
    
    # third
    $group = $zinc->add('group', 1);
    $zinc->coords($group, [600, 250]);
    
    $curve = $zinc->add('curve', $group, [],
                        -fillrule => 'nonzero',
                        -closed => 1,
                        -filled => 1,
                        -fillcolor => 'black',
                        -linecolor => 'red',
                        );
    $arc = $zinc->add('arc', $group, [-30, -30, 30, 30]);
    $zinc->contour($curve, 'add', 1, $arc);
    $zinc->remove($arc);
    $n = 3*$n;
    for (1..$n) {
        $arc = $zinc->add('arc', $group, [-5, -70, 5, -40]);
        $zinc->rotate($arc, ($_-1)*(360/$n), 'degree');
        $zinc->contour($curve, 'add', 1, $arc);
        $zinc->remove($arc);
    }
    &showbbox($group);
    ok(&similarFlatArray ([$zinc->bbox($group)],
                          [528,178, 672, 322],   # beware this coordinates are 
                          # not exactly the good one
                          [2,2,   2,2 ],
                          ),
       "bbox of right figure");
    
    diag("############## end of text test");
    exit;

}




sub showbbox {
    my @b = $zinc->bbox(shift);
#    print "bbox @b\n";
    $zinc->add('rectangle', 1, [@b],
	       -filled => 0, -linecolor => 'green', -tags => ['bbox']);
}

## ref1 is the gotten array
## ref2 is the expected array
sub similarFlatArray {
  my ($ref1, $ref2, $deltaref)= @_;
  diag ("waiting a reference for \$ref1"), return 0 unless ref ($ref1) eq 'ARRAY';
  diag ("waiting a reference for \$ref2"), return 0 unless ref ($ref2) eq 'ARRAY';
  diag ("waiting a reference for \$deltaref"), return 0 unless ref ($deltaref) eq 'ARRAY';
  
  my @array1 = @{$ref1};
  my @array2 = @{$ref2};
  my @deltaarray = @{$deltaref};
  diag ("arrays gotten, expected and deltas are not of same length,".$#array1.",".$#array2.",".$#deltaarray), return 0 
    unless ($#array1 == $#array2) and ($#array2 == $#deltaarray);
  for my $i (0.. $#array1) {
    my $a = $array1[$i];
    my $b = $array2[$i];
    my $delta = $deltaarray[$i];
    diag ("waiting a numeric value for elt $i of gotten array"), return 0 
      unless &numerical($a);
    diag ("waiting a numeric value for elt $i of expected array"), return 0 
      unless &numerical($b);
    diag ("waiting a numeric value for elt $i of deltas array"), return 0 
      unless &numerical($delta);
        
    diag ("delta > $delta between elt $i of gotten array ($a) and expected array ($b)"), return 0 
      if (abs($a-$b) > $delta) ;
  }
  return 1;
}

sub numerical {
  my ($v) = @_;
  return 0 unless defined $v;
  ### this really works!!
  return $v eq $v*1;
}

Added jni/tkzinc/Perl/t/Bbox.t.





































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing all the import

BEGIN {
    if (!eval q{
        use Test::More tests => 12;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
        use Tk::Font;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}


$mw = MainWindow->new();
$zinc = $mw->Zinc(-width => 400, -height => 400)->pack;
like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");

my $coords = [ [10,10], [40, 40] ];


my $font = $zinc->fontCreate('font20pixels', -size => -20);
#my @metrics = $zinc->fontMetrics('font20pixels');
#print "metrics = @metrics\n";
my $linespace = $zinc->fontMetrics('font20pixels', -linespace);

my $txt1 = $zinc->add('text', 1, 
                      -font => 'font20pixels',
                      -alignment => 'center',
                      #-text => 'text', # an empty text
                      -position => [30,25],
                     );
#print "bbox=(", join(',', $zinc->bbox($txt1)),")\n";

# from v3.30 the bbox of an empty text is ()
ok(&similarFlatArray ([$zinc->bbox($txt1)],
                      [],
                      [],
                     ),
   "bbox of empty text");

my $width = $zinc->fontMeasure('font20pixels', 'dummy');
#print "width = $width\n";
my $txt2 = $zinc->add('text', 1, 
                      -font => 'font20pixels',
                      -alignment => 'left',
                      -text => 'dummy',
                      -position => [200,100],
                     );
# print "bbox=(", join(',', $zinc->bbox($txt2)),")\n";

ok(&similarFlatArray ([$zinc->bbox($txt2)],
                      [200,100, 200+$width, 100+$linespace],
                      [4,4,   4,4 ],
                     ),
   "bbox of 'dummy' text");

my $txt3 = $zinc->add('text', 1, 
                      -font => 'font20pixels',
                      -alignment => 'center',
                      -text => 'dummy',
                      -position => [200,200],
                     );
# print "bbox=(", join(',', $zinc->bbox($txt3)),")\n";

ok(&similarFlatArray ([$zinc->bbox($txt3)],
                      [200,200, 200+$width, 200+$linespace],
                      [4,4,   4,4 ],
                     ),
   "bbox of 'dummy' aligned-centered text");

my $txt4 = $zinc->add('text', 1, 
                      -font => 'font20pixels',
                      -anchor => 'center',
                      -text => 'dummy',
                      -position => [200,100],
                     );
# print "bbox=(", join(',', $zinc->bbox($txt4)),")\n";

ok(&similarFlatArray ([$zinc->bbox($txt4)],
                      [200-$width/2,100-$linespace/2, 200+$width/2, 100+$linespace/2],
                      [4,4,   4,4 ],
                     ),
   "bbox of 'dummy' centered text");


### testing bbox of fields or labels of track/waypoint and tabular items
my $track = $zinc->add('track', 1, 4, -position => [56, 78]);
# print "bbox11=(", $bbox,")\n";

is($zinc->bbox(-label, $track), (),
   "bbox of a track label without labelformat is ()");

my $bbox = $zinc->bbox(-field, 0, $track);
#print "bbox22=(", $bbox,")\n";

is( $bbox, undef, "bbox of a track field without labelformat is undef");


$zinc->itemconfigure($track, -labelformat => 'x20x18+0+0');
#print "bbox=(", join(',', $zinc->bbox(-label, $track)),")\n";

$bbox = eval { $zinc->bbox(-field, 4, $track) } ;
#print "bbox=(", $bbox,")\n";

is( $bbox, (), 
    "bbox of a track field which field is out of bound is undef");

my $wpt = $zinc->add('waypoint', 1, 0, -position => [561, 781]);
#print "wpt bbox=(", join(',', $zinc->bbox($wpt)),")\n";
ok(&similarFlatArray ([ $zinc->bbox($wpt) ],
                      [ 561,781,  561,781],
                      [5,5,   5,5],
                      ),
   "coords of a waypoint without label");


my $tab = $zinc->add('tabular', 1, 1, -position => [61, 81]);
is_deeply([ $zinc->bbox($tab) ],
	  [ ],
	  "bbox of a tabular without labelformat");

#print "tab bbox=(", join(',', $zinc->bbox(-label, $tab)),")\n";
is_deeply([ $zinc->bbox(-label, $tab) ],
	  [ ],
	  "bbox of a tabular without labelformat");

#print "tab bbox=(", join(',', $zinc->bbox(-field, 0, $tab)),")\n";
is_deeply([ $zinc->bbox(-field, 0, $tab) ],
	  [ ],
	  "bbox of a tabular field without labelformat");


# $zinc->itemconfigure($tab, -labelformat => 'x20x18+0+0');
# is_deeply([ $zinc->coords($tab) ],
# 	  [ 61,81 ],
# 	  "coords of a tabular with a labelformat");




sub similarPoints {
  my ($ref1, $ref2)= @_;
  diag ("waiting a reference for \$ref1" . ref ($ref1)), return 0 unless ref ($ref1) eq 'ARRAY';
  diag ("waiting a reference for \$ref2"), return 0 unless ref ($ref2) eq 'ARRAY';

  my @array1 = @{$ref1};
  my @array2 = @{$ref2};

  diag ("arrays for \$ref1 and \$ref2 are not of same length"), return 0 
    unless scalar @array1 == @array2;

  for my $i (0.. $#array1) {
    my $pt1 = $array1[$i];
    my $pt2 = $array2[$i];
    diag ("waiting a reference to a point in elt $i \$ref1"), return 0 
      unless ref $pt1 eq 'ARRAY';
    my (@pt1) = @{$pt1};
    diag ("waiting a reference to a point (x,y) in elt $i \$ref1"), return 0 
      unless scalar @pt1 == 2 and &numerical($pt1[0]) and &numerical($pt1[1]) ;
    
    diag ("waiting a reference to a point in elt $i \$ref1"), return 0 
      unless ref $pt2 eq 'ARRAY';
    my (@pt2) = @{$pt2};
    diag ("waiting a reference to a point (x,y) in elt $i \$ref2"), return 0 
      unless scalar @pt2 == 2 and &numerical($pt2[0]) and &numerical($pt2[1]) ;
    
    diag ("delta > 0.001 between x of pt$i"), return 0 if abs($pt1[0]-$pt2[0]) > 0.001;
    diag ("delta > 0.001 between y of pt$i"), return 0 if abs($pt1[1]-$pt2[1]) > 0.001;
  }
  return 1;
}

## ref1 is the obtained array
## ref2 is the expected array
sub similarFlatArray {
  my ($ref1, $ref2, $deltaref)= @_;
  diag ("waiting a reference for \$ref1"), return 0 unless ref ($ref1) eq 'ARRAY';
  diag ("waiting a reference for \$ref2"), return 0 unless ref ($ref2) eq 'ARRAY';
  diag ("waiting a reference for \$deltaref"), return 0 unless ref ($deltaref) eq 'ARRAY';
  
  my @array1 = @{$ref1};
  my @array2 = @{$ref2};
  my @deltaarray = @{$deltaref};
  diag ("arrays obtained, expected and deltas are not of same length,".$#array1.",".$#array2.",".$#deltaarray), return 0 
    unless ($#array1 == $#array2) and ($#array2 == $#deltaarray);
  for my $i (0.. $#array1) {
    my $a = $array1[$i];
    my $b = $array2[$i];
    my $delta = $deltaarray[$i];
    diag ("waiting a numeric value for elt $i of obtained array"), return 0 
      unless &numerical($a);
    diag ("waiting a numeric value for elt $i of expected array"), return 0 
      unless &numerical($b);
    diag ("waiting a numeric value for elt $i of deltas array"), return 0 
      unless &numerical($delta);
        
    diag ("delta > $delta between elt $i of obtained array ($a) and expected array ($b)"), return 0 
      if (abs($a-$b) > $delta) ;
  }
  return 1;
}


sub numerical {
  my ($v) = @_;
  return 0 unless defined $v;
  ### this really works!!
  return $v eq $v*1;
  }


diag("############## bbox test");


Added jni/tkzinc/Perl/t/Coords.t.























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing all the import

BEGIN {
    if (!eval q{
        use Test::More tests => 26;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}


$mw = MainWindow->new();
$zinc = $mw->Zinc(-width => 100, -height => 100);

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");

my $rect = $zinc->add('rectangle', 1, [10,20,40,50]);


is_deeply([ $zinc->coords($rect) ],
	  [ [10,20], [40, 50] ],
	  "coords are list of arrays");

is_deeply([ $zinc->coords($rect,0) ],
	  [ [10,20], [40, 50] ],
	  "coords of first contour is a list of arrays");

is_deeply([ $zinc->coords($rect,0,0) ],
	  [ 10,20 ],
	  "coords of one point of a contour is a list of two numbers");

is_deeply([ $zinc->coords($rect,0,1) ],
	  [ 40,50 ],
	  "coords of one point of a contour is a list of two numbers");

my $curve = $zinc->add('curve', 1, [ [10,20] ,[40,50,'c'], [90,10,'c'], [30,60] ]);

is_deeply([ $zinc->coords($curve) ],
	  [ [10,20] ,[40,50,'c'], [90,10,'c'], [30,60] ],
	  "coords of a curve is a list of arrays");

is_deeply([ $zinc->coords($curve,0) ],
	  [ [10,20] ,[40,50,'c'], [90,10,'c'], [30,60] ],
	  "coords of contour 0 of a curve is a list of arrays");

is_deeply([ $zinc->coords($curve,0,0) ],
	  [ 10,20 ],
	  "coords of first point of contour 0 of a curve is list of two numbers");

is_deeply([ $zinc->coords($curve,0,1) ],
	  [ 40,50,'c' ],
	  "coords of a control point of a curve contour is list of three elements");



## testing empty curves, and adding/removing contours
my $emptyCurve = $zinc->add('curve', 1, [ ]);

is_deeply([ $zinc->coords($emptyCurve) ],
	  [  ],
	  "coords of an empty curve is an empty list");

# adding a contour
$zinc->contour($emptyCurve, 'add', 0, [ [1,1], [100,100], [200,100] ]);
is_deeply([ $zinc->coords($emptyCurve) ],
	  [  [1,1], [100,100], [200,100] ],
	  "coords of a no more empty curve");

$zinc->contour($emptyCurve, 'add', 0, [ [80,90], [-100,-100], [-200,100] ]);
is_deeply([ $zinc->coords($emptyCurve, 1) ],
	  [  [80,90], [-100,-100], [-200,100] ],
	  "coords of a second contour in a curve");

# removing first contour (which can be the second one!!
$zinc->contour($emptyCurve, 'remove', 0);
is_deeply([ $zinc->coords($emptyCurve, 0) ],
	  [  [1,1], [100,100], [200,100] ],   # contours order is re-organised by tkzinc!!
#	  [  [80,90], [-100,-100], [-200,100] ],
	  "coords of remaining contour in the curve");

# removing the last contour
$zinc->contour($emptyCurve, 'remove', 0);
is_deeply([ $zinc->coords($emptyCurve, 0) ],
	  [   ],
	  "coords of contour in the curve which is now empty");





my $text = $zinc->add('text', 1, -position => [10,20], -text => 'test');

is_deeply([ $zinc->coords($text) ],
	  [ 10,20 ],
	  "coords of a text");

is_deeply([ $zinc->coords($text,0) ],
	  [ 10,20 ],
	  "coords of text contour");

is_deeply([ $zinc->coords($text,0,0) ],
	  [ 10,20 ],
	  "coords of text contour first point");


my $group = $zinc->add('group', 1);

is_deeply([ $zinc->coords($group) ],
	  [ 0,0 ],
	  "coords of a empty group, not moved");

$zinc->translate($group, 23, 45);
#my @coords = @{$zinc->coords($group)}[0];
#print "coords = @coords", $coords[0][0], $coords[0][1], "\n";
is_deeply([ $zinc->coords($group) ],
	  [ 23,45 ],
	  "coords of a empty group, translated");


my $track = $zinc->add('track', 1, 0, -position => [56, 78]);
is_deeply([ $zinc->coords($track) ],
	  [ 56,78 ],
	  "coords of a track");

my $wpt = $zinc->add('waypoint', 1, 0, -position => [561, 781]);
is_deeply([ $zinc->coords($wpt) ],
	  [ 561,781 ],
	  "coords of a waypoint");

my $tab = $zinc->add('tabular', 1, 1, -position => [61, 81]);
is_deeply([ $zinc->coords($tab) ],
	  [ 61,81 ],
	  "coords of a empty tabular");
$zinc->itemconfigure($tab, -labelformat => 'x20x18+0+0');
is_deeply([ $zinc->coords($tab) ],
	  [ 61,81 ],
	  "coords of a tabular with a labelformat");


my $arc = $zinc->add('arc', 1, [13,31, 42,24]);
is_deeply([ $zinc->coords($arc) ],
	  [ [13,31],  [42,24] ],
	  "coords of an arc");

my $tri = $zinc->add('triangles', 1, [ [10,20],  [30,40], [50,60], [70,80], [90,99] ]);
is_deeply([ $zinc->coords($tri) ],
	  [ [10,20],  [30,40], [50,60], [70,80], [90,99] ],
	  "coords of an triangle");

my $photoMickey = $zinc->Photo('mickey.gif', -file => Tk->findINC("demos/images/mickey.gif"));
my $icon = $zinc->add('icon', 1, -position => [20,100], -image => $photoMickey);
is_deeply([ $zinc->coords($icon) ],
	  [ 20,100 ],
	  "coords of an icon");

diag("############## coords test");


Added jni/tkzinc/Perl/t/Images.t.

















































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing all the -tile, -image, -mask, -fillpattern, -linepattern widget and items options 

# this script can be used with an optionnal argument, an integer giving
# the delay in seconds during which the graphic updates will be displayed
# this is usefull for visual inspection!

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 36;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	$mw = MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}


$zinc = $mw->Zinc(-render => 1,
		  -width => 400, -height => 400)->pack;

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");

##  test cannot be run directly since $zinc->update does not work properly 
##  when not in a  mainloop
##  so I use a timer to trigger tests after entering the mainloop

$zinc->after(10, \&testExecute);  

Tk::MainLoop;

sub testExecute {

#### creating different images, bitmaps and pixmaps...
my $photoMickey = $zinc->Photo('mickey.gif', -file => Tk->findINC("demos/images/mickey.gif"));
like ($photoMickey, qr/^Tk::Photo=HASH/ , "creating a Tk::Photo with a .gif");

my $bitmap = $zinc->Bitmap('file.xbm', -file => Tk->findINC("file.xbm"));
like ($bitmap, qr/^Tk::Bitmap=HASH/ , "creating a Tk::Bitmap with a .xbm");

my $xpm = $zinc->Photo('QuitPB.xpm', -file => Tk->findINC("demos/images/QuitPB.xpm"));
like ($xpm, qr/^Tk::Photo=HASH/ , "creating a Tk::Photo with a .xpm");

#### tiling Tk::Zinc
$zinc->configure(-tile => $xpm);
if ($Tk::VERSION < 804) {
  is ($zinc->cget(-tile), "QuitPB.xpm", "verifying Tk::Zinc -tile option value");
} else {
  is ($zinc->cget(-tile), $xpm, "verifying Tk::Zinc -tile option value");
}

&wait ("-tile of Tk::Zinc with QuitPB.xpm");

$zinc->configure(-tile => $photoMickey);
if ($Tk::VERSION < 804) {
  is ($zinc->cget(-tile), "mickey.gif", "verifying Tk::Zinc -tile option value");
} else {
  is ($zinc->cget(-tile), $photoMickey, "verifying Tk::Zinc -tile option value");
}
&wait ("-tile of Tk::Zinc with mickey.gif");

# modifying the Tk::Photo to see if the Tk::Zinc -tile changes
$photoMickey->read( Tk->findINC("demos/images/earth.gif") );
&wait ("-tile of Tk::Zinc should display the earth VISUAL INSPECTION!"); sleep 1;
# going back to the "real" mickey
$photoMickey->read( Tk->findINC("demos/images/mickey.gif") );
&wait ("-tile of Tk::Zinc should display mickey again VISUAL INSPECTION!"); sleep 1;

$zinc->configure(-tile => "");
if ($Tk::VERSION < 804) {
  is ($zinc->cget(-tile), "", "removing Tk::Zinc -tile");
} else {
  is ($zinc->cget(-tile), undef, "removing Tk::Zinc -tile");
}
&wait ("-tile of Tk::Zinc with nothing");



#### rectangle item
my $rect1 = $zinc->add('rectangle', 1, [10,10,190,190], -filled => 1);


$zinc->itemconfigure($rect1, -tile => $xpm);

if ($Tk::Zinc::VERSION < 3.302) {
  is ($zinc->itemcget($rect1, -tile), "QuitPB.xpm", "verifying rectangle -tile option value");
} else {
  # cget return an image object since release 3.3.2
  is ($zinc->itemcget($rect1, -tile), $xpm, "verifying rectangle -tile option value");
}
&wait ("-tile of rectangle with QuitPB.xpm");

$zinc->itemconfigure($rect1, -tile => $photoMickey);
if ($Tk::Zinc::VERSION < 3.302) {
  is ($zinc->itemcget($rect1, -tile), "mickey.gif", "verifying rectangle -tile option value");
} else {
  # cget return an image object since release 3.3.2
  is ($zinc->itemcget($rect1, -tile), $photoMickey, "verifying rectangle -tile option value");
}

&wait ("-tile of rectangle with mickey");

# modifying the Tk::Photo to see if the rectangle -tile changes
$photoMickey->read( Tk->findINC("demos/images/earth.gif") );
&wait ("-tile of rectangle should display the earth VISUAL INSPECTION!"); sleep 1;
# going back to the "real" mickey
$photoMickey->read( Tk->findINC("demos/images/mickey.gif") );
&wait ("-tile of rectangle should display mickey again VISUAL INSPECTION!"); sleep 1;


$zinc->itemconfigure($rect1, -tile => "");
is ($zinc->itemcget($rect1, -tile), "", "removing rectangle -tile");
&wait ("-tile of rectangle with nothing");

TODO: {
    local $TODO = "because it makes Tk::Zinc dying" if 1;

    # the next line makes Tk::Zinc (v3.29x) dying... so I comment it out the 3 next lines 
    # $zinc->itemconfigure($rect1, -fillpattern => $bitmap);
    # is ($zinc->itemcget($rect1, -fillpattern), $bitmap, "verifying rectangle -fillpattern option value as a Tk::Bitmap");
    # &wait ("displaying a rectangle with -fillpattern as a Tk::Bitmap");
}

$zinc->itemconfigure($rect1, -fillpattern => 'AlphaStipple3');
is ($zinc->itemcget($rect1, -fillpattern), 'AlphaStipple3', "verifying rectangle -fillpattern option value");
&wait ("-fillpattern of rectangle with 'AlphaStipple3'");

$zinc->itemconfigure($rect1, -fillpattern => "");
is ($zinc->itemcget($rect1, -fillpattern), "", "removing rectangle -fillpattern");
&wait ("-fillpattern of rectangle with nothing");


$zinc->itemconfigure($rect1, -filled => 0,-linepattern => 'AlphaStipple3', -linecolor => "red");
is ($zinc->itemcget($rect1, -linepattern), 'AlphaStipple3', "verifying rectangle -linepattern option value");
&wait ("-linepattern of rectangle with 'AlphaStipple3'");

$zinc->itemconfigure($rect1, -linepattern => "");
is ($zinc->itemcget($rect1, -linepattern), "", "removing rectangle -linepattern");
&wait ("-linepattern of rectangle with nothing");

$zinc->remove($rect1);

#####  icon item
my $icon1 = $zinc->add('icon', 1, -position => [20,100], -image => $photoMickey);
&wait ("displaying an icon");

$zinc->remove($icon1);

my $icon2 = $zinc->add('icon', 1, -position => [40,100]);

SKIP: {
    skip "with Tk::Zinc < 3.295", 4 if ($Tk::Zinc::VERSION < 3.295);

    $zinc->itemconfigure($icon2, -image => $bitmap);

    &wait ("displaying an icon with -image as a Tk::Bitmap");
    if ($Tk::Zinc::VERSION < 3.302) {
      is ($zinc->itemcget($icon2, -image), 'file.xbm', "verifying icon -image option value as file.xbm");
    } else {
      # cget return an image object since release 3.3.2
      is ($zinc->itemcget($icon2, -image), $bitmap, "verifying icon -image option value as file.xbm");
    }
$zinc->itemconfigure($icon2, -image => "");

    $zinc->itemconfigure($icon2, -image => '@'.Tk->findINC("openfile.xbm"));
    if ($Tk::Zinc::VERSION < 3.302) {
      is ($zinc->itemcget($icon2, -image), '@'.Tk->findINC("openfile.xbm"),"verifying icon -image option value as @/path/openfile.xbm");
    } else {
      # cget return an image object since release 3.3.2
      is ($zinc->itemcget($icon2, -image), undef,"verifying icon -image option value as @/path/openfile.xbm");
    }
    &wait ("displaying an icon with -image as a \@filename.xbm");
}
$zinc->remove($icon2);

my $icon3 = $zinc->add('icon', 1, -position => [60,100], -mask => '@'.Tk->findINC("openfolder.xbm"),
		       -color => "red");
is ($zinc->itemcget($icon3, -mask), '@'.Tk->findINC("openfolder.xbm"),"verifying icon -mask option value as \@/path/openfolder.xbm");
&wait ("displaying an icon with -mask as a \@filename.xbm");

$zinc->itemconfigure($icon3, -image => "");
is ($zinc->itemcget($icon3, -image), "", "removing icon -image");

TODO: {
    local $TODO = "because it makes Tk::Zinc dying" if 1;

    # the next line makes Tk::Zinc (v3.29x) dying... so I comment it out the 3 next lines 
    # $zinc->itemconfigure($icon3, -mask => $bitmap);
    # is ($zinc->itemcget($icon3, -mask), $bitmap, "verifying icon -mask option value as a Tk::Bitmap");
    # &wait ("displaying an icon with -mask as a Tk::Bitmap");
}

$zinc->remove($icon3);

# We should also test that changing the content of a Tk::Photo should change the display of an icon


diag("############## Images test");
exit;

}


sub wait {
    $zinc->update;
    ok (1, $_[0]);

    my $delay = $ARGV[0];
    if (defined $delay) {
	$zinc->update;
	if ($delay =~ /^\d+$/) {
	    sleep $delay;
	} else {
	    sleep 1;
	}
    }
    
}



Added jni/tkzinc/Perl/t/Import.t.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing all the import

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 6;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}

require_ok( 'Tk::Zinc' );
require_ok( 'Tk::Zinc::Debug' );
require_ok( 'Tk::Zinc::Trace' );
# require_ok( 'Tk::Zinc::TraceErrors' ); # incompatible with the previous one
# we do not test the previous, as it should be equivalent!
require_ok( 'Tk::Zinc::Graphics' );
require_ok( 'Tk::Zinc::Logo' );
require_ok( 'Tk::Zinc::Text' );
diag("############## all imports");

Added jni/tkzinc/Perl/t/Maps.t.









































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz  mertz@intuilab.com
#

# this test mainly does funny effects when openGL is on


# testing all the import

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 2;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}

use strict;
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 800, -height => 600, -backcolor => "white",
                     -render => 0)->pack;

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");


$zinc->add('text', 1, -position => [10,5], -text => 
"this is a simple sample of a mapitem in TkZinc");

$zinc->after(10, \&proceedTest);

Tk::MainLoop;

sub proceedTest {
 
$zinc->mapinfo('first', 'create');

my $k = 10;
foreach (0..70) {
foreach my $j (0..80) {
  $zinc->mapinfo('first', 'add', 'line', 'simple', 1, 10, 10+$j*$k, 790, 10+$j*$k);
  $zinc->mapinfo('first', 'add', 'line', 'simple', 1, 10+$j*$k, 10, 10+$j*$k, 790);
}
}

$zinc->add('map', 1, -mapinfo => 'first');


$zinc->mapinfo('second', 'create');

$k = 30;
foreach (0..70) {
foreach my $j (0..80) {
  $zinc->mapinfo('first', 'add', 'line', 'dashed', 1, 10, 5+$j*$k, 790, 5+$j*$k);
  $zinc->mapinfo('first', 'add', 'line', 'mixed', 1, 5+$j*$k, 10, 5+$j*$k, 790);
  $zinc->mapinfo('first', 'add', 'line', 'simple', 1, 10, 5+$j*$k, 790, 5+$j*$k);
  $zinc->mapinfo('first', 'add', 'line', 'simple', 1, 5+$j*$k, 10, 5+$j*$k, 790);
}
}

$zinc->add('map', 1, -color => 'red', -mapinfo => 'second');

&pass("map is displayed");
$zinc->after(1000, sub {exit});

}


Added jni/tkzinc/Perl/t/PreviousKnownBugs.t.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing all the import

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 2;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}

#use Tk::Zinc;

$mw = MainWindow->new();
$zinc = $mw->Zinc(-width => 100, -height => 100);

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");

# following bug detected by A. Lemort
my $curve = $zinc->add('curve', 1, [[0, 0], [0, 100, 'c'], [100,100, 'c'], [100, 0]]) ;
$zinc->coords($curve,  [[500,0], [500, 100], [600, 100], [600, 0]]);

my @coords = $zinc->coords($curve,0);


is_deeply([ @coords ],
          [ [500,0], [500, 100], [600, 100], [600, 0] ],
          "lemort bug 17 sept 2003 v3.2.94; testing correct value");



diag("############## all known bugs");

Added jni/tkzinc/Perl/t/Scale_clipped_group.t.





















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz  mertz@intuilab.com, adapted from a script 
# reported by Daniel Etienne for a bug report in Tk::Zinc 3.2.96
#

use strict;

# testing all the import

BEGIN {
    if (!eval q{
        use Test::More tests => 1;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}
use Tk;

my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-render => 0)->pack(-expand => 1, -fill => "both");


# creating the father group 1 and 2
my $fatherGroup1=$zinc->add("group", 1);
my $fatherGroup2=$zinc->add("group", 1);

$zinc->coords($fatherGroup1, [50,100]);
$zinc->coords($fatherGroup2, [200,100]);

# creating subGroup 1 and 2
my $subGroup1=$zinc->add("group", $fatherGroup1);
my $subGroup2=$zinc->add("group", $fatherGroup2);

# creating null sized rectangle 1 to clip the subgroup 1
my $rectangle1 = $zinc->add("rectangle", $subGroup1, [ [0, 0], [0, 0] ]);

$zinc->itemconfigure($subGroup1, -clip => $rectangle1);

# creating an icon in the sub-group
my $surroundimgfile = Tk->findINC("Tk.xbm");

my $surroundimg = $zinc->Bitmap(-file => $surroundimgfile,
				-foreground => 'sienna',
				);
my $icon1 = $zinc->add("icon", $subGroup1,
                       -image => $surroundimg,
                      );
my $icon2 = $zinc->add("icon", $subGroup2,
                       -image => $surroundimg,
                      );


## scaling fatherGroup1 makes an image visible on 3.2.96/3.3.2 TkZinc version
$zinc->scale($fatherGroup1, 0.8, 0.8);

##  test cannot be run directly since $zinc->update does not work properly 
##  when not in a  mainloop
##  so I use a timer to trigger tests after entering the mainloop

$zinc->after(10, \&testExecute);  

Tk::MainLoop;

sub testExecute {


    &wait ("You should see ONLY ONE ptk ICON (a camel), please INSPECT VISUALY!"); sleep 2;

    diag("############## Scale clipped group test");
    exit;

}


sub wait {
    $zinc->update;
    ok (1, $_[0]);

    my $delay = $ARGV[0];
    if (defined $delay) {
	$zinc->update;
	if ($delay =~ /^\d+$/) {
	    sleep $delay;
	} else {
	    sleep 1;
	}
    }
}


Added jni/tkzinc/Perl/t/Test/Builder.pm.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
package Test::Builder;

use 5.004;

# $^C was only introduced in 5.005-ish.  We do this to prevent
# use of uninitialized value warnings in older perls.
$^C ||= 0;

use strict;
use vars qw($VERSION $CLASS);
$VERSION = '0.17';
$CLASS = __PACKAGE__;

my $IsVMS = $^O eq 'VMS';

# Make Test::Builder thread-safe for ithreads.
BEGIN {
    use Config;
    if( $] >= 5.008 && $Config{useithreads} ) {
        require threads;
        require threads::shared;
        threads::shared->import;
    }
    else {
        *share = sub { 0 };
        *lock  = sub { 0 };
    }
}

use vars qw($Level);
my($Test_Died) = 0;
my($Have_Plan) = 0;
my $Original_Pid = $$;
my $Curr_Test = 0;      share($Curr_Test);
my @Test_Results = ();  share(@Test_Results);
my @Test_Details = ();  share(@Test_Details);


=head1 NAME

Test::Builder - Backend for building test libraries

=head1 SYNOPSIS

  package My::Test::Module;
  use Test::Builder;
  require Exporter;
  @ISA = qw(Exporter);
  @EXPORT = qw(ok);

  my $Test = Test::Builder->new;
  $Test->output('my_logfile');

  sub import {
      my($self) = shift;
      my $pack = caller;

      $Test->exported_to($pack);
      $Test->plan(@_);

      $self->export_to_level(1, $self, 'ok');
  }

  sub ok {
      my($test, $name) = @_;

      $Test->ok($test, $name);
  }


=head1 DESCRIPTION

Test::Simple and Test::More have proven to be popular testing modules,
but they're not always flexible enough.  Test::Builder provides the a
building block upon which to write your own test libraries I<which can
work together>.

=head2 Construction

=over 4

=item B<new>

  my $Test = Test::Builder->new;

Returns a Test::Builder object representing the current state of the
test.

Since you only run one test per program, there is B<one and only one>
Test::Builder object.  No matter how many times you call new(), you're
getting the same object.  (This is called a singleton).

=cut

my $Test;
sub new {
    my($class) = shift;
    $Test ||= bless ['Move along, nothing to see here'], $class;
    return $Test;
}

=back

=head2 Setting up tests

These methods are for setting up tests and declaring how many there
are.  You usually only want to call one of these methods.

=over 4

=item B<exported_to>

  my $pack = $Test->exported_to;
  $Test->exported_to($pack);

Tells Test::Builder what package you exported your functions to.
This is important for getting TODO tests right.

=cut

my $Exported_To;
sub exported_to {
    my($self, $pack) = @_;

    if( defined $pack ) {
        $Exported_To = $pack;
    }
    return $Exported_To;
}

=item B<plan>

  $Test->plan('no_plan');
  $Test->plan( skip_all => $reason );
  $Test->plan( tests => $num_tests );

A convenient way to set up your tests.  Call this and Test::Builder
will print the appropriate headers and take the appropriate actions.

If you call plan(), don't call any of the other methods below.

=cut

sub plan {
    my($self, $cmd, $arg) = @_;

    return unless $cmd;

    if( $Have_Plan ) {
        die sprintf "You tried to plan twice!  Second plan at %s line %d\n",
          ($self->caller)[1,2];
    }

    if( $cmd eq 'no_plan' ) {
        $self->no_plan;
    }
    elsif( $cmd eq 'skip_all' ) {
        return $self->skip_all($arg);
    }
    elsif( $cmd eq 'tests' ) {
        if( $arg ) {
            return $self->expected_tests($arg);
        }
        elsif( !defined $arg ) {
            die "Got an undefined number of tests.  Looks like you tried to ".
                "say how many tests you plan to run but made a mistake.\n";
        }
        elsif( !$arg ) {
            die "You said to run 0 tests!  You've got to run something.\n";
        }
    }
    else {
        require Carp;
        my @args = grep { defined } ($cmd, $arg);
        Carp::croak("plan() doesn't understand @args");
    }

    return 1;
}

=item B<expected_tests>

    my $max = $Test->expected_tests;
    $Test->expected_tests($max);

Gets/sets the # of tests we expect this test to run and prints out
the appropriate headers.

=cut

my $Expected_Tests = 0;
sub expected_tests {
    my($self, $max) = @_;

    if( defined $max ) {
        $Expected_Tests = $max;
        $Have_Plan      = 1;

        $self->_print("1..$max\n") unless $self->no_header;
    }
    return $Expected_Tests;
}


=item B<no_plan>

  $Test->no_plan;

Declares that this test will run an indeterminate # of tests.

=cut

my($No_Plan) = 0;
sub no_plan {
    $No_Plan    = 1;
    $Have_Plan  = 1;
}

=item B<has_plan>

  $plan = $Test->has_plan
  
Find out whether a plan has been defined. $plan is either C<undef> (no plan has been set), C<no_plan> (indeterminate # of tests) or an integer (the number of expected tests).

=cut

sub has_plan {
	return($Expected_Tests) if $Expected_Tests;
	return('no_plan') if $No_Plan;
	return(undef);
};


=item B<skip_all>

  $Test->skip_all;
  $Test->skip_all($reason);

Skips all the tests, using the given $reason.  Exits immediately with 0.

=cut

my $Skip_All = 0;
sub skip_all {
    my($self, $reason) = @_;

    my $out = "1..0";
    $out .= " # Skip $reason" if $reason;
    $out .= "\n";

    $Skip_All = 1;

    $self->_print($out) unless $self->no_header;
    exit(0);
}

=back

=head2 Running tests

These actually run the tests, analogous to the functions in
Test::More.

$name is always optional.

=over 4

=item B<ok>

  $Test->ok($test, $name);

Your basic test.  Pass if $test is true, fail if $test is false.  Just
like Test::Simple's ok().

=cut

sub ok {
    my($self, $test, $name) = @_;

    # $test might contain an object which we don't want to accidentally
    # store, so we turn it into a boolean.
    $test = $test ? 1 : 0;

    unless( $Have_Plan ) {
        require Carp;
        Carp::croak("You tried to run a test without a plan!  Gotta have a plan.");
    }

    lock $Curr_Test;
    $Curr_Test++;

    $self->diag(<<ERR) if defined $name and $name =~ /^[\d\s]+$/;
    You named your test '$name'.  You shouldn't use numbers for your test names.
    Very confusing.
ERR

    my($pack, $file, $line) = $self->caller;

    my $todo = $self->todo($pack);

    my $out;
    my $result = {};
    share($result);

    unless( $test ) {
        $out .= "not ";
        @$result{ 'ok', 'actual_ok' } = ( ( $todo ? 1 : 0 ), 0 );
    }
    else {
        @$result{ 'ok', 'actual_ok' } = ( 1, $test );
    }

    $out .= "ok";
    $out .= " $Curr_Test" if $self->use_numbers;

    if( defined $name ) {
        $name =~ s|#|\\#|g;     # # in a name can confuse Test::Harness.
        $out   .= " - $name";
        $result->{name} = $name;
    }
    else {
        $result->{name} = '';
    }

    if( $todo ) {
        my $what_todo = $todo;
        $out   .= " # TODO $what_todo";
        $result->{reason} = $what_todo;
        $result->{type}   = 'todo';
    }
    else {
        $result->{reason} = '';
        $result->{type}   = '';
    }

    $Test_Results[$Curr_Test-1] = $result;
    $out .= "\n";

    $self->_print($out);

    unless( $test ) {
        my $msg = $todo ? "Failed (TODO)" : "Failed";
        $self->diag("    $msg test ($file at line $line)\n");
    } 

    return $test ? 1 : 0;
}

=item B<is_eq>

  $Test->is_eq($got, $expected, $name);

Like Test::More's is().  Checks if $got eq $expected.  This is the
string version.

=item B<is_num>

  $Test->is_num($got, $expected, $name);

Like Test::More's is().  Checks if $got == $expected.  This is the
numeric version.

=cut

sub is_eq {
    my($self, $got, $expect, $name) = @_;
    local $Level = $Level + 1;

    if( !defined $got || !defined $expect ) {
        # undef only matches undef and nothing else
        my $test = !defined $got && !defined $expect;

        $self->ok($test, $name);
        $self->_is_diag($got, 'eq', $expect) unless $test;
        return $test;
    }

    return $self->cmp_ok($got, 'eq', $expect, $name);
}

sub is_num {
    my($self, $got, $expect, $name) = @_;
    local $Level = $Level + 1;

    if( !defined $got || !defined $expect ) {
        # undef only matches undef and nothing else
        my $test = !defined $got && !defined $expect;

        $self->ok($test, $name);
        $self->_is_diag($got, '==', $expect) unless $test;
        return $test;
    }

    return $self->cmp_ok($got, '==', $expect, $name);
}

sub _is_diag {
    my($self, $got, $type, $expect) = @_;

    foreach my $val (\$got, \$expect) {
        if( defined $$val ) {
            if( $type eq 'eq' ) {
                # quote and force string context
                $$val = "'$$val'"
            }
            else {
                # force numeric context
                $$val = $$val+0;
            }
        }
        else {
            $$val = 'undef';
        }
    }

    return $self->diag(sprintf <<DIAGNOSTIC, $got, $expect);
         got: %s
    expected: %s
DIAGNOSTIC

}    

=item B<isnt_eq>

  $Test->isnt_eq($got, $dont_expect, $name);

Like Test::More's isnt().  Checks if $got ne $dont_expect.  This is
the string version.

=item B<isnt_num>

  $Test->is_num($got, $dont_expect, $name);

Like Test::More's isnt().  Checks if $got ne $dont_expect.  This is
the numeric version.

=cut

sub isnt_eq {
    my($self, $got, $dont_expect, $name) = @_;
    local $Level = $Level + 1;

    if( !defined $got || !defined $dont_expect ) {
        # undef only matches undef and nothing else
        my $test = defined $got || defined $dont_expect;

        $self->ok($test, $name);
        $self->_cmp_diag('ne', $got, $dont_expect) unless $test;
        return $test;
    }

    return $self->cmp_ok($got, 'ne', $dont_expect, $name);
}

sub isnt_num {
    my($self, $got, $dont_expect, $name) = @_;
    local $Level = $Level + 1;

    if( !defined $got || !defined $dont_expect ) {
        # undef only matches undef and nothing else
        my $test = defined $got || defined $dont_expect;

        $self->ok($test, $name);
        $self->_cmp_diag('!=', $got, $dont_expect) unless $test;
        return $test;
    }

    return $self->cmp_ok($got, '!=', $dont_expect, $name);
}


=item B<like>

  $Test->like($this, qr/$regex/, $name);
  $Test->like($this, '/$regex/', $name);

Like Test::More's like().  Checks if $this matches the given $regex.

You'll want to avoid qr// if you want your tests to work before 5.005.

=item B<unlike>

  $Test->unlike($this, qr/$regex/, $name);
  $Test->unlike($this, '/$regex/', $name);

Like Test::More's unlike().  Checks if $this B<does not match> the
given $regex.

=cut

sub like {
    my($self, $this, $regex, $name) = @_;

    local $Level = $Level + 1;
    $self->_regex_ok($this, $regex, '=~', $name);
}

sub unlike {
    my($self, $this, $regex, $name) = @_;

    local $Level = $Level + 1;
    $self->_regex_ok($this, $regex, '!~', $name);
}

=item B<maybe_regex>

  $Test->maybe_regex(qr/$regex/);
  $Test->maybe_regex('/$regex/');

Convenience method for building testing functions that take regular
expressions as arguments, but need to work before perl 5.005.

Takes a quoted regular expression produced by qr//, or a string
representing a regular expression.

Returns a Perl value which may be used instead of the corresponding
regular expression, or undef if it's argument is not recognised.

For example, a version of like(), sans the useful diagnostic messages,
could be written as:

  sub laconic_like {
      my ($self, $this, $regex, $name) = @_;
      my $usable_regex = $self->maybe_regex($regex);
      die "expecting regex, found '$regex'\n"
          unless $usable_regex;
      $self->ok($this =~ m/$usable_regex/, $name);
  }

=cut


sub maybe_regex {
	my ($self, $regex) = @_;
    my $usable_regex = undef;
    if( ref $regex eq 'Regexp' ) {
        $usable_regex = $regex;
    }
    # Check if it looks like '/foo/'
    elsif( my($re, $opts) = $regex =~ m{^ /(.*)/ (\w*) $ }sx ) {
        $usable_regex = length $opts ? "(?$opts)$re" : $re;
    };
    return($usable_regex)
};

sub _regex_ok {
    my($self, $this, $regex, $cmp, $name) = @_;

    local $Level = $Level + 1;

    my $ok = 0;
    my $usable_regex = $self->maybe_regex($regex);
    unless (defined $usable_regex) {
        $ok = $self->ok( 0, $name );
        $self->diag("    '$regex' doesn't look much like a regex to me.");
        return $ok;
    }

    {
        local $^W = 0;
        my $test = $this =~ /$usable_regex/ ? 1 : 0;
        $test = !$test if $cmp eq '!~';
        $ok = $self->ok( $test, $name );
    }

    unless( $ok ) {
        $this = defined $this ? "'$this'" : 'undef';
        my $match = $cmp eq '=~' ? "doesn't match" : "matches";
        $self->diag(sprintf <<DIAGNOSTIC, $this, $match, $regex);
                  %s
    %13s '%s'
DIAGNOSTIC

    }

    return $ok;
}

=item B<cmp_ok>

  $Test->cmp_ok($this, $type, $that, $name);

Works just like Test::More's cmp_ok().

    $Test->cmp_ok($big_num, '!=', $other_big_num);

=cut

sub cmp_ok {
    my($self, $got, $type, $expect, $name) = @_;

    my $test;
    {
        local $^W = 0;
        local($@,$!);   # don't interfere with $@
                        # eval() sometimes resets $!
        $test = eval "\$got $type \$expect";
    }
    local $Level = $Level + 1;
    my $ok = $self->ok($test, $name);

    unless( $ok ) {
        if( $type =~ /^(eq|==)$/ ) {
            $self->_is_diag($got, $type, $expect);
        }
        else {
            $self->_cmp_diag($got, $type, $expect);
        }
    }
    return $ok;
}

sub _cmp_diag {
    my($self, $got, $type, $expect) = @_;
    
    $got    = defined $got    ? "'$got'"    : 'undef';
    $expect = defined $expect ? "'$expect'" : 'undef';
    return $self->diag(sprintf <<DIAGNOSTIC, $got, $type, $expect);
    %s
        %s
    %s
DIAGNOSTIC
}

=item B<BAILOUT>

    $Test->BAILOUT($reason);

Indicates to the Test::Harness that things are going so badly all
testing should terminate.  This includes running any additional test
scripts.

It will exit with 255.

=cut

sub BAILOUT {
    my($self, $reason) = @_;

    $self->_print("Bail out!  $reason");
    exit 255;
}

=item B<skip>

    $Test->skip;
    $Test->skip($why);

Skips the current test, reporting $why.

=cut

sub skip {
    my($self, $why) = @_;
    $why ||= '';

    unless( $Have_Plan ) {
        require Carp;
        Carp::croak("You tried to run tests without a plan!  Gotta have a plan.");
    }

    lock($Curr_Test);
    $Curr_Test++;

    my %result;
    share(%result);
    %result = (
        'ok'      => 1,
        actual_ok => 1,
        name      => '',
        type      => 'skip',
        reason    => $why,
    );
    $Test_Results[$Curr_Test-1] = \%result;

    my $out = "ok";
    $out   .= " $Curr_Test" if $self->use_numbers;
    $out   .= " # skip $why\n";

    $Test->_print($out);

    return 1;
}


=item B<todo_skip>

  $Test->todo_skip;
  $Test->todo_skip($why);

Like skip(), only it will declare the test as failing and TODO.  Similar
to

    print "not ok $tnum # TODO $why\n";

=cut

sub todo_skip {
    my($self, $why) = @_;
    $why ||= '';

    unless( $Have_Plan ) {
        require Carp;
        Carp::croak("You tried to run tests without a plan!  Gotta have a plan.");
    }

    lock($Curr_Test);
    $Curr_Test++;

    my %result;
    share(%result);
    %result = (
        'ok'      => 1,
        actual_ok => 0,
        name      => '',
        type      => 'todo_skip',
        reason    => $why,
    );

    $Test_Results[$Curr_Test-1] = \%result;

    my $out = "not ok";
    $out   .= " $Curr_Test" if $self->use_numbers;
    $out   .= " # TODO & SKIP $why\n";

    $Test->_print($out);

    return 1;
}


=begin _unimplemented

=item B<skip_rest>

  $Test->skip_rest;
  $Test->skip_rest($reason);

Like skip(), only it skips all the rest of the tests you plan to run
and terminates the test.

If you're running under no_plan, it skips once and terminates the
test.

=end _unimplemented

=back


=head2 Test style

=over 4

=item B<level>

    $Test->level($how_high);

How far up the call stack should $Test look when reporting where the
test failed.

Defaults to 1.

Setting $Test::Builder::Level overrides.  This is typically useful
localized:

    {
        local $Test::Builder::Level = 2;
        $Test->ok($test);
    }

=cut

sub level {
    my($self, $level) = @_;

    if( defined $level ) {
        $Level = $level;
    }
    return $Level;
}

$CLASS->level(1);


=item B<use_numbers>

    $Test->use_numbers($on_or_off);

Whether or not the test should output numbers.  That is, this if true:

  ok 1
  ok 2
  ok 3

or this if false

  ok
  ok
  ok

Most useful when you can't depend on the test output order, such as
when threads or forking is involved.

Test::Harness will accept either, but avoid mixing the two styles.

Defaults to on.

=cut

my $Use_Nums = 1;
sub use_numbers {
    my($self, $use_nums) = @_;

    if( defined $use_nums ) {
        $Use_Nums = $use_nums;
    }
    return $Use_Nums;
}

=item B<no_header>

    $Test->no_header($no_header);

If set to true, no "1..N" header will be printed.

=item B<no_ending>

    $Test->no_ending($no_ending);

Normally, Test::Builder does some extra diagnostics when the test
ends.  It also changes the exit code as described in Test::Simple.

If this is true, none of that will be done.

=cut

my($No_Header, $No_Ending) = (0,0);
sub no_header {
    my($self, $no_header) = @_;

    if( defined $no_header ) {
        $No_Header = $no_header;
    }
    return $No_Header;
}

sub no_ending {
    my($self, $no_ending) = @_;

    if( defined $no_ending ) {
        $No_Ending = $no_ending;
    }
    return $No_Ending;
}


=back

=head2 Output

Controlling where the test output goes.

It's ok for your test to change where STDOUT and STDERR point to,
Test::Builder's default output settings will not be affected.

=over 4

=item B<diag>

    $Test->diag(@msgs);

Prints out the given $message.  Normally, it uses the failure_output()
handle, but if this is for a TODO test, the todo_output() handle is
used.

Output will be indented and marked with a # so as not to interfere
with test output.  A newline will be put on the end if there isn't one
already.

We encourage using this rather than calling print directly.

Returns false.  Why?  Because diag() is often used in conjunction with
a failing test (C<ok() || diag()>) it "passes through" the failure.

    return ok(...) || diag(...);

=for blame transfer
Mark Fowler <mark@twoshortplanks.com>

=cut

sub diag {
    my($self, @msgs) = @_;
    return unless @msgs;

    # Prevent printing headers when compiling (i.e. -c)
    return if $^C;

    # Escape each line with a #.
    foreach (@msgs) {
        $_ = 'undef' unless defined;
        s/^/# /gms;
    }

    push @msgs, "\n" unless $msgs[-1] =~ /\n\Z/;

    local $Level = $Level + 1;
    my $fh = $self->todo ? $self->todo_output : $self->failure_output;
    local($\, $", $,) = (undef, ' ', '');
    print $fh @msgs;

    return 0;
}

=begin _private

=item B<_print>

    $Test->_print(@msgs);

Prints to the output() filehandle.

=end _private

=cut

sub _print {
    my($self, @msgs) = @_;

    # Prevent printing headers when only compiling.  Mostly for when
    # tests are deparsed with B::Deparse
    return if $^C;

    local($\, $", $,) = (undef, ' ', '');
    my $fh = $self->output;

    # Escape each line after the first with a # so we don't
    # confuse Test::Harness.
    foreach (@msgs) {
        s/\n(.)/\n# $1/sg;
    }

    push @msgs, "\n" unless $msgs[-1] =~ /\n\Z/;

    print $fh @msgs;
}


=item B<output>

    $Test->output($fh);
    $Test->output($file);

Where normal "ok/not ok" test output should go.

Defaults to STDOUT.

=item B<failure_output>

    $Test->failure_output($fh);
    $Test->failure_output($file);

Where diagnostic output on test failures and diag() should go.

Defaults to STDERR.

=item B<todo_output>

    $Test->todo_output($fh);
    $Test->todo_output($file);

Where diagnostics about todo test failures and diag() should go.

Defaults to STDOUT.

=cut

my($Out_FH, $Fail_FH, $Todo_FH);
sub output {
    my($self, $fh) = @_;

    if( defined $fh ) {
        $Out_FH = _new_fh($fh);
    }
    return $Out_FH;
}

sub failure_output {
    my($self, $fh) = @_;

    if( defined $fh ) {
        $Fail_FH = _new_fh($fh);
    }
    return $Fail_FH;
}

sub todo_output {
    my($self, $fh) = @_;

    if( defined $fh ) {
        $Todo_FH = _new_fh($fh);
    }
    return $Todo_FH;
}

sub _new_fh {
    my($file_or_fh) = shift;

    my $fh;
    unless( UNIVERSAL::isa($file_or_fh, 'GLOB') ) {
        $fh = do { local *FH };
        open $fh, ">$file_or_fh" or 
            die "Can't open test output log $file_or_fh: $!";
    }
    else {
        $fh = $file_or_fh;
    }

    return $fh;
}

unless( $^C ) {
    # We dup STDOUT and STDERR so people can change them in their
    # test suites while still getting normal test output.
    open(TESTOUT, ">&STDOUT") or die "Can't dup STDOUT:  $!";
    open(TESTERR, ">&STDERR") or die "Can't dup STDERR:  $!";

    # Set everything to unbuffered else plain prints to STDOUT will
    # come out in the wrong order from our own prints.
    _autoflush(\*TESTOUT);
    _autoflush(\*STDOUT);
    _autoflush(\*TESTERR);
    _autoflush(\*STDERR);

    $CLASS->output(\*TESTOUT);
    $CLASS->failure_output(\*TESTERR);
    $CLASS->todo_output(\*TESTOUT);
}

sub _autoflush {
    my($fh) = shift;
    my $old_fh = select $fh;
    $| = 1;
    select $old_fh;
}


=back


=head2 Test Status and Info

=over 4

=item B<current_test>

    my $curr_test = $Test->current_test;
    $Test->current_test($num);

Gets/sets the current test # we're on.

You usually shouldn't have to set this.

=cut

sub current_test {
    my($self, $num) = @_;

    lock($Curr_Test);
    if( defined $num ) {
        unless( $Have_Plan ) {
            require Carp;
            Carp::croak("Can't change the current test number without a plan!");
        }

        $Curr_Test = $num;
        if( $num > @Test_Results ) {
            my $start = @Test_Results ? $#Test_Results + 1 : 0;
            for ($start..$num-1) {
                my %result;
                share(%result);
                %result = ( ok        => 1, 
                            actual_ok => undef, 
                            reason    => 'incrementing test number', 
                            type      => 'unknown', 
                            name      => undef 
                          );
                $Test_Results[$_] = \%result;
            }
        }
    }
    return $Curr_Test;
}


=item B<summary>

    my @tests = $Test->summary;

A simple summary of the tests so far.  True for pass, false for fail.
This is a logical pass/fail, so todos are passes.

Of course, test #1 is $tests[0], etc...

=cut

sub summary {
    my($self) = shift;

    return map { $_->{'ok'} } @Test_Results;
}

=item B<details>

    my @tests = $Test->details;

Like summary(), but with a lot more detail.

    $tests[$test_num - 1] = 
            { 'ok'       => is the test considered a pass?
              actual_ok  => did it literally say 'ok'?
              name       => name of the test (if any)
              type       => type of test (if any, see below).
              reason     => reason for the above (if any)
            };

'ok' is true if Test::Harness will consider the test to be a pass.

'actual_ok' is a reflection of whether or not the test literally
printed 'ok' or 'not ok'.  This is for examining the result of 'todo'
tests.  

'name' is the name of the test.

'type' indicates if it was a special test.  Normal tests have a type
of ''.  Type can be one of the following:

    skip        see skip()
    todo        see todo()
    todo_skip   see todo_skip()
    unknown     see below

Sometimes the Test::Builder test counter is incremented without it
printing any test output, for example, when current_test() is changed.
In these cases, Test::Builder doesn't know the result of the test, so
it's type is 'unkown'.  These details for these tests are filled in.
They are considered ok, but the name and actual_ok is left undef.

For example "not ok 23 - hole count # TODO insufficient donuts" would
result in this structure:

    $tests[22] =    # 23 - 1, since arrays start from 0.
      { ok        => 1,   # logically, the test passed since it's todo
        actual_ok => 0,   # in absolute terms, it failed
        name      => 'hole count',
        type      => 'todo',
        reason    => 'insufficient donuts'
      };

=cut

sub details {
    return @Test_Results;
}

=item B<todo>

    my $todo_reason = $Test->todo;
    my $todo_reason = $Test->todo($pack);

todo() looks for a $TODO variable in your tests.  If set, all tests
will be considered 'todo' (see Test::More and Test::Harness for
details).  Returns the reason (ie. the value of $TODO) if running as
todo tests, false otherwise.

todo() is pretty part about finding the right package to look for
$TODO in.  It uses the exported_to() package to find it.  If that's
not set, it's pretty good at guessing the right package to look at.

Sometimes there is some confusion about where todo() should be looking
for the $TODO variable.  If you want to be sure, tell it explicitly
what $pack to use.

=cut

sub todo {
    my($self, $pack) = @_;

    $pack = $pack || $self->exported_to || $self->caller(1);

    no strict 'refs';
    return defined ${$pack.'::TODO'} ? ${$pack.'::TODO'}
                                     : 0;
}

=item B<caller>

    my $package = $Test->caller;
    my($pack, $file, $line) = $Test->caller;
    my($pack, $file, $line) = $Test->caller($height);

Like the normal caller(), except it reports according to your level().

=cut

sub caller {
    my($self, $height) = @_;
    $height ||= 0;

    my @caller = CORE::caller($self->level + $height + 1);
    return wantarray ? @caller : $caller[0];
}

=back

=cut

=begin _private

=over 4

=item B<_sanity_check>

  _sanity_check();

Runs a bunch of end of test sanity checks to make sure reality came
through ok.  If anything is wrong it will die with a fairly friendly
error message.

=cut

#'#
sub _sanity_check {
    _whoa($Curr_Test < 0,  'Says here you ran a negative number of tests!');
    _whoa(!$Have_Plan and $Curr_Test, 
          'Somehow your tests ran without a plan!');
    _whoa($Curr_Test != @Test_Results,
          'Somehow you got a different number of results than tests ran!');
}

=item B<_whoa>

  _whoa($check, $description);

A sanity check, similar to assert().  If the $check is true, something
has gone horribly wrong.  It will die with the given $description and
a note to contact the author.

=cut

sub _whoa {
    my($check, $desc) = @_;
    if( $check ) {
        die <<WHOA;
WHOA!  $desc
This should never happen!  Please contact the author immediately!
WHOA
    }
}

=item B<_my_exit>

  _my_exit($exit_num);

Perl seems to have some trouble with exiting inside an END block.  5.005_03
and 5.6.1 both seem to do odd things.  Instead, this function edits $?
directly.  It should ONLY be called from inside an END block.  It
doesn't actually exit, that's your job.

=cut

sub _my_exit {
    $? = $_[0];

    return 1;
}


=back

=end _private

=cut

$SIG{__DIE__} = sub {
    # We don't want to muck with death in an eval, but $^S isn't
    # totally reliable.  5.005_03 and 5.6.1 both do the wrong thing
    # with it.  Instead, we use caller.  This also means it runs under
    # 5.004!
    my $in_eval = 0;
    for( my $stack = 1;  my $sub = (CORE::caller($stack))[3];  $stack++ ) {
        $in_eval = 1 if $sub =~ /^\(eval\)/;
    }
    $Test_Died = 1 unless $in_eval;
};

sub _ending {
    my $self = shift;

    _sanity_check();

    # Don't bother with an ending if this is a forked copy.  Only the parent
    # should do the ending.
    do{ _my_exit($?) && return } if $Original_Pid != $$;

    # Bailout if plan() was never called.  This is so
    # "require Test::Simple" doesn't puke.
    do{ _my_exit(0) && return } if !$Have_Plan && !$Test_Died;

    # Figure out if we passed or failed and print helpful messages.
    if( @Test_Results ) {
        # The plan?  We have no plan.
        if( $No_Plan ) {
            $self->_print("1..$Curr_Test\n") unless $self->no_header;
            $Expected_Tests = $Curr_Test;
        }

        # 5.8.0 threads bug.  Shared arrays will not be auto-extended 
        # by a slice.  Worse, we have to fill in every entry else
        # we'll get an "Invalid value for shared scalar" error
        for my $idx ($#Test_Results..$Expected_Tests-1) {
            my %empty_result = ();
            share(%empty_result);
            $Test_Results[$idx] = \%empty_result
              unless defined $Test_Results[$idx];
        }

        my $num_failed = grep !$_->{'ok'}, @Test_Results[0..$Expected_Tests-1];
        $num_failed += abs($Expected_Tests - @Test_Results);

        if( $Curr_Test < $Expected_Tests ) {
            $self->diag(<<"FAIL");
Looks like you planned $Expected_Tests tests but only ran $Curr_Test.
FAIL
        }
        elsif( $Curr_Test > $Expected_Tests ) {
            my $num_extra = $Curr_Test - $Expected_Tests;
            $self->diag(<<"FAIL");
Looks like you planned $Expected_Tests tests but ran $num_extra extra.
FAIL
        }
        elsif ( $num_failed ) {
            $self->diag(<<"FAIL");
Looks like you failed $num_failed tests of $Expected_Tests.
FAIL
        }

        if( $Test_Died ) {
            $self->diag(<<"FAIL");
Looks like your test died just after $Curr_Test.
FAIL

            _my_exit( 255 ) && return;
        }

        _my_exit( $num_failed <= 254 ? $num_failed : 254  ) && return;
    }
    elsif ( $Skip_All ) {
        _my_exit( 0 ) && return;
    }
    elsif ( $Test_Died ) {
        $self->diag(<<'FAIL');
Looks like your test died before it could output anything.
FAIL
    }
    else {
        $self->diag("No tests run!\n");
        _my_exit( 255 ) && return;
    }
}

END {
    $Test->_ending if defined $Test and !$Test->no_ending;
}

=head1 THREADS

In perl 5.8.0 and later, Test::Builder is thread-safe.  The test
number is shared amongst all threads.  This means if one thread sets
the test number using current_test() they will all be effected.

=head1 EXAMPLES

CPAN can provide the best examples.  Test::Simple, Test::More,
Test::Exception and Test::Differences all use Test::Builder.

=head1 SEE ALSO

Test::Simple, Test::More, Test::Harness

=head1 AUTHORS

Original code by chromatic, maintained by Michael G Schwern
E<lt>schwern@pobox.comE<gt>

=head1 COPYRIGHT

Copyright 2002 by chromatic E<lt>chromatic@wgz.orgE<gt>,
                  Michael G Schwern E<lt>schwern@pobox.comE<gt>.

This program is free software; you can redistribute it and/or 
modify it under the same terms as Perl itself.

See F<http://www.perl.com/perl/misc/Artistic.html>

=cut

1;

Added jni/tkzinc/Perl/t/Test/Harness.pm.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
# -*- Mode: cperl; cperl-indent-level: 4 -*-
# $Id$

package Test::Harness;

require 5.004;
use Test::Harness::Straps;
use Test::Harness::Assert;
use Exporter;
use Benchmark;
use Config;
use strict;

use vars qw($VERSION $Verbose $Switches $Have_Devel_Corestack $Curtest
            $Columns $verbose $switches $ML $Strap
            @ISA @EXPORT @EXPORT_OK $Last_ML_Print
           );

# Backwards compatibility for exportable variable names.
*verbose  = *Verbose;
*switches = *Switches;

$Have_Devel_Corestack = 0;

$VERSION = '2.30';

$ENV{HARNESS_ACTIVE} = 1;

END {
    # For VMS.
    delete $ENV{HARNESS_ACTIVE};
}

# Some experimental versions of OS/2 build have broken $?
my $Ignore_Exitcode = $ENV{HARNESS_IGNORE_EXITCODE};

my $Files_In_Dir = $ENV{HARNESS_FILELEAK_IN_DIR};

my $Ok_Slow = $ENV{HARNESS_OK_SLOW};

$Strap = Test::Harness::Straps->new;

@ISA = ('Exporter');
@EXPORT    = qw(&runtests);
@EXPORT_OK = qw($verbose $switches);

$Verbose  = $ENV{HARNESS_VERBOSE} || 0;
$Switches = "-w";
$Columns  = $ENV{HARNESS_COLUMNS} || $ENV{COLUMNS} || 80;
$Columns--;             # Some shells have trouble with a full line of text.


=head1 NAME

Test::Harness - run perl standard test scripts with statistics

=head1 SYNOPSIS

  use Test::Harness;

  runtests(@test_files);

=head1 DESCRIPTION

B<STOP!> If all you want to do is write a test script, consider using
Test::Simple.  Otherwise, read on.

(By using the Test module, you can write test scripts without
knowing the exact output this module expects.  However, if you need to
know the specifics, read on!)

Perl test scripts print to standard output C<"ok N"> for each single
test, where C<N> is an increasing sequence of integers. The first line
output by a standard test script is C<"1..M"> with C<M> being the
number of tests that should be run within the test
script. Test::Harness::runtests(@tests) runs all the testscripts
named as arguments and checks standard output for the expected
C<"ok N"> strings.

After all tests have been performed, runtests() prints some
performance statistics that are computed by the Benchmark module.

=head2 The test script output

The following explains how Test::Harness interprets the output of your
test program.

=over 4

=item B<'1..M'>

This header tells how many tests there will be.  For example, C<1..10>
means you plan on running 10 tests.  This is a safeguard in case your
test dies quietly in the middle of its run.

It should be the first non-comment line output by your test program.

In certain instances, you may not know how many tests you will
ultimately be running.  In this case, it is permitted for the 1..M
header to appear as the B<last> line output by your test (again, it
can be followed by further comments).

Under B<no> circumstances should 1..M appear in the middle of your
output or more than once.


=item B<'ok', 'not ok'.  Ok?>

Any output from the testscript to standard error is ignored and
bypassed, thus will be seen by the user. Lines written to standard
output containing C</^(not\s+)?ok\b/> are interpreted as feedback for
runtests().  All other lines are discarded.

C</^not ok/> indicates a failed test.  C</^ok/> is a successful test.


=item B<test numbers>

Perl normally expects the 'ok' or 'not ok' to be followed by a test
number.  It is tolerated if the test numbers after 'ok' are
omitted. In this case Test::Harness maintains temporarily its own
counter until the script supplies test numbers again. So the following
test script

    print <<END;
    1..6
    not ok
    ok
    not ok
    ok
    ok
    END

will generate

    FAILED tests 1, 3, 6
    Failed 3/6 tests, 50.00% okay

=item B<test names>

Anything after the test number but before the # is considered to be
the name of the test.

  ok 42 this is the name of the test

Currently, Test::Harness does nothing with this information.

=item B<Skipping tests>

If the standard output line contains the substring C< # Skip> (with
variations in spacing and case) after C<ok> or C<ok NUMBER>, it is
counted as a skipped test.  If the whole testscript succeeds, the
count of skipped tests is included in the generated output.
C<Test::Harness> reports the text after C< # Skip\S*\s+> as a reason
for skipping.

  ok 23 # skip Insufficient flogiston pressure.

Similarly, one can include a similar explanation in a C<1..0> line
emitted if the test script is skipped completely:

  1..0 # Skipped: no leverage found

=item B<Todo tests>

If the standard output line contains the substring C< # TODO> after
C<not ok> or C<not ok NUMBER>, it is counted as a todo test.  The text
afterwards is the thing that has to be done before this test will
succeed.

  not ok 13 # TODO harness the power of the atom

=begin _deprecated

Alternatively, you can specify a list of what tests are todo as part
of the test header.

  1..23 todo 5 12 23

This only works if the header appears at the beginning of the test.

This style is B<deprecated>.

=end _deprecated

These tests represent a feature to be implemented or a bug to be fixed
and act as something of an executable "thing to do" list.  They are
B<not> expected to succeed.  Should a todo test begin succeeding,
Test::Harness will report it as a bonus.  This indicates that whatever
you were supposed to do has been done and you should promote this to a
normal test.

=item B<Bail out!>

As an emergency measure, a test script can decide that further tests
are useless (e.g. missing dependencies) and testing should stop
immediately. In that case the test script prints the magic words

  Bail out!

to standard output. Any message after these words will be displayed by
C<Test::Harness> as the reason why testing is stopped.

=item B<Comments>

Additional comments may be put into the testing output on their own
lines.  Comment lines should begin with a '#', Test::Harness will
ignore them.

  ok 1
  # Life is good, the sun is shining, RAM is cheap.
  not ok 2
  # got 'Bush' expected 'Gore'

=item B<Anything else>

Any other output Test::Harness sees it will silently ignore B<BUT WE
PLAN TO CHANGE THIS!> If you wish to place additional output in your
test script, please use a comment.

=back


=head2 Taint mode

Test::Harness will honor the C<-T> in the #! line on your test files.  So
if you begin a test with:

    #!perl -T

the test will be run with taint mode on.


=head2 Configuration variables.

These variables can be used to configure the behavior of
Test::Harness.  They are exported on request.

=over 4

=item B<$Test::Harness::verbose>

The global variable $Test::Harness::verbose is exportable and can be
used to let runtests() display the standard output of the script
without altering the behavior otherwise.

=item B<$Test::Harness::switches>

The global variable $Test::Harness::switches is exportable and can be
used to set perl command line options used for running the test
script(s). The default value is C<-w>.

=back


=head2 Failure

It will happen, your tests will fail.  After you mop up your ego, you
can begin examining the summary report:

  t/base..............ok
  t/nonumbers.........ok
  t/ok................ok
  t/test-harness......ok
  t/waterloo..........dubious
          Test returned status 3 (wstat 768, 0x300)
  DIED. FAILED tests 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
          Failed 10/20 tests, 50.00% okay
  Failed Test  Stat Wstat Total Fail  Failed  List of Failed
  -----------------------------------------------------------------------
  t/waterloo.t    3   768    20   10  50.00%  1 3 5 7 9 11 13 15 17 19
  Failed 1/5 test scripts, 80.00% okay. 10/44 subtests failed, 77.27% okay.

Everything passed but t/waterloo.t.  It failed 10 of 20 tests and
exited with non-zero status indicating something dubious happened.

The columns in the summary report mean:

=over 4

=item B<Failed Test>

The test file which failed.

=item B<Stat>

If the test exited with non-zero, this is its exit status.

=item B<Wstat>

The wait status of the test I<umm, I need a better explanation here>.

=item B<Total>

Total number of tests expected to run.

=item B<Fail>

Number which failed, either from "not ok" or because they never ran.

=item B<Failed>

Percentage of the total tests which failed.

=item B<List of Failed>

A list of the tests which failed.  Successive failures may be
abbreviated (ie. 15-20 to indicate that tests 15, 16, 17, 18, 19 and
20 failed).

=back


=head2 Functions

Test::Harness currently only has one function, here it is.

=over 4

=item B<runtests>

  my $allok = runtests(@test_files);

This runs all the given @test_files and divines whether they passed
or failed based on their output to STDOUT (details above).  It prints
out each individual test which failed along with a summary report and
a how long it all took.

It returns true if everything was ok.  Otherwise it will die() with
one of the messages in the DIAGNOSTICS section.

=for _private

This is just _run_all_tests() plus _show_results()

=cut

sub runtests {
    my(@tests) = @_;

    local ($\, $,);

    my($tot, $failedtests) = _run_all_tests(@tests);
    _show_results($tot, $failedtests);

    my $ok = _all_ok($tot);

    assert(($ok xor keys %$failedtests), 
           q{ok status jives with $failedtests});

    return $ok;
}

=begin _private

=item B<_all_ok>

  my $ok = _all_ok(\%tot);

Tells you if this test run is overall successful or not.

=cut

sub _all_ok {
    my($tot) = shift;

    return $tot->{bad} == 0 && ($tot->{max} || $tot->{skipped}) ? 1 : 0;
}

=item B<_globdir>

  my @files = _globdir $dir;

Returns all the files in a directory.  This is shorthand for backwards
compatibility on systems where glob() doesn't work right.

=cut

sub _globdir { 
    opendir DIRH, shift; 
    my @f = readdir DIRH; 
    closedir DIRH; 

    return @f;
}

=item B<_run_all_tests>

  my($total, $failed) = _run_all_tests(@test_files);

Runs all the given @test_files (as runtests()) but does it quietly (no
report).  $total is a hash ref summary of all the tests run.  Its keys
and values are this:

    bonus           Number of individual todo tests unexpectedly passed
    max             Number of individual tests ran
    ok              Number of individual tests passed
    sub_skipped     Number of individual tests skipped
    todo            Number of individual todo tests

    files           Number of test files ran
    good            Number of test files passed
    bad             Number of test files failed
    tests           Number of test files originally given
    skipped         Number of test files skipped

If $total->{bad} == 0 and $total->{max} > 0, you've got a successful
test.

$failed is a hash ref of all the test scripts which failed.  Each key
is the name of a test script, each value is another hash representing
how that script failed.  Its keys are these:

    name        Name of the test which failed
    estat       Script's exit value
    wstat       Script's wait status
    max         Number of individual tests
    failed      Number which failed
    percent     Percentage of tests which failed
    canon       List of tests which failed (as string).

Needless to say, $failed should be empty if everything passed.

B<NOTE> Currently this function is still noisy.  I'm working on it.

=cut

#'#
sub _run_all_tests {
    my(@tests) = @_;
    local($|) = 1;
    my(%failedtests);

    # Test-wide totals.
    my(%tot) = (
                bonus    => 0,
                max      => 0,
                ok       => 0,
                files    => 0,
                bad      => 0,
                good     => 0,
                tests    => scalar @tests,
                sub_skipped  => 0,
                todo     => 0,
                skipped  => 0,
                bench    => 0,
               );

    my @dir_files = _globdir $Files_In_Dir if defined $Files_In_Dir;
    my $t_start = new Benchmark;

    my $width = _leader_width(@tests);
    foreach my $tfile (@tests) {
        $Last_ML_Print = 0;  # so each test prints at least once
        my($leader, $ml) = _mk_leader($tfile, $width);
        local $ML = $ml;
        print $leader;

        $tot{files}++;

        $Strap->{_seen_header} = 0;
        my %results = $Strap->analyze_file($tfile) or
          do { warn "$Strap->{error}\n";  next };

        # state of the current test.
        my @failed = grep { !$results{details}[$_-1]{ok} }
                     1..@{$results{details}};
        my %test = (
                    ok          => $results{ok},
                    'next'      => $Strap->{'next'},
                    max         => $results{max},
                    failed      => \@failed,
                    bonus       => $results{bonus},
                    skipped     => $results{skip},
                    skip_reason => $results{skip_reason},
                    skip_all    => $Strap->{skip_all},
                    ml          => $ml,
                   );

        $tot{bonus}       += $results{bonus};
        $tot{max}         += $results{max};
        $tot{ok}          += $results{ok};
        $tot{todo}        += $results{todo};
        $tot{sub_skipped} += $results{skip};

        my($estatus, $wstatus) = @results{qw(exit wait)};

        if ($results{passing}) {
            if ($test{max} and $test{skipped} + $test{bonus}) {
                my @msg;
                push(@msg, "$test{skipped}/$test{max} skipped: $test{skip_reason}")
                    if $test{skipped};
                push(@msg, "$test{bonus}/$test{max} unexpectedly succeeded")
                    if $test{bonus};
                print "$test{ml}ok\n        ".join(', ', @msg)."\n";
            } elsif ($test{max}) {
                print "$test{ml}ok\n";
            } elsif (defined $test{skip_all} and length $test{skip_all}) {
                print "skipped\n        all skipped: $test{skip_all}\n";
                $tot{skipped}++;
            } else {
                print "skipped\n        all skipped: no reason given\n";
                $tot{skipped}++;
            }
            $tot{good}++;
        }
        else {
            # List unrun tests as failures.
            if ($test{'next'} <= $test{max}) {
                push @{$test{failed}}, $test{'next'}..$test{max};
            }
            # List overruns as failures.
            else {
                my $details = $results{details};
                foreach my $overrun ($test{max}+1..@$details)
                {
                    next unless ref $details->[$overrun-1];
                    push @{$test{failed}}, $overrun
                }
            }

            if ($wstatus) {
                $failedtests{$tfile} = _dubious_return(\%test, \%tot, 
                                                       $estatus, $wstatus);
                $failedtests{$tfile}{name} = $tfile;
            }
            elsif($results{seen}) {
                if (@{$test{failed}} and $test{max}) {
                    my ($txt, $canon) = canonfailed($test{max},$test{skipped},
                                                    @{$test{failed}});
                    print "$test{ml}$txt";
                    $failedtests{$tfile} = { canon   => $canon,
                                             max     => $test{max},
                                             failed  => scalar @{$test{failed}},
                                             name    => $tfile, 
                                             percent => 100*(scalar @{$test{failed}})/$test{max},
                                             estat   => '',
                                             wstat   => '',
                                           };
                } else {
                    print "Don't know which tests failed: got $test{ok} ok, ".
                          "expected $test{max}\n";
                    $failedtests{$tfile} = { canon   => '??',
                                             max     => $test{max},
                                             failed  => '??',
                                             name    => $tfile, 
                                             percent => undef,
                                             estat   => '', 
                                             wstat   => '',
                                           };
                }
                $tot{bad}++;
            } else {
                print "FAILED before any test output arrived\n";
                $tot{bad}++;
                $failedtests{$tfile} = { canon       => '??',
                                         max         => '??',
                                         failed      => '??',
                                         name        => $tfile,
                                         percent     => undef,
                                         estat       => '', 
                                         wstat       => '',
                                       };
            }
        }

        if (defined $Files_In_Dir) {
            my @new_dir_files = _globdir $Files_In_Dir;
            if (@new_dir_files != @dir_files) {
                my %f;
                @f{@new_dir_files} = (1) x @new_dir_files;
                delete @f{@dir_files};
                my @f = sort keys %f;
                print "LEAKED FILES: @f\n";
                @dir_files = @new_dir_files;
            }
        }
    }
    $tot{bench} = timediff(new Benchmark, $t_start);

    $Strap->_restore_PERL5LIB;

    return(\%tot, \%failedtests);
}

=item B<_mk_leader>

  my($leader, $ml) = _mk_leader($test_file, $width);

Generates the 't/foo........' $leader for the given $test_file as well
as a similar version which will overwrite the current line (by use of
\r and such).  $ml may be empty if Test::Harness doesn't think you're
on TTY.

The $width is the width of the "yada/blah.." string.

=cut

sub _mk_leader {
    my($te, $width) = @_;
    chomp($te);
    $te =~ s/\.\w+$/./;

    if ($^O eq 'VMS') { $te =~ s/^.*\.t\./\[.t./s; }
    my $blank = (' ' x 77);
    my $leader = "$te" . '.' x ($width - length($te));
    my $ml = "";

    $ml = "\r$blank\r$leader"
      if -t STDOUT and not $ENV{HARNESS_NOTTY} and not $Verbose;

    return($leader, $ml);
}

=item B<_leader_width>

  my($width) = _leader_width(@test_files);

Calculates how wide the leader should be based on the length of the
longest test name.

=cut

sub _leader_width {
    my $maxlen = 0;
    my $maxsuflen = 0;
    foreach (@_) {
        my $suf    = /\.(\w+)$/ ? $1 : '';
        my $len    = length;
        my $suflen = length $suf;
        $maxlen    = $len    if $len    > $maxlen;
        $maxsuflen = $suflen if $suflen > $maxsuflen;
    }
    # + 3 : we want three dots between the test name and the "ok"
    return $maxlen + 3 - $maxsuflen;
}


sub _show_results {
    my($tot, $failedtests) = @_;

    my $pct;
    my $bonusmsg = _bonusmsg($tot);

    if (_all_ok($tot)) {
        print "All tests successful$bonusmsg.\n";
    } elsif (!$tot->{tests}){
        die "FAILED--no tests were run for some reason.\n";
    } elsif (!$tot->{max}) {
        my $blurb = $tot->{tests}==1 ? "script" : "scripts";
        die "FAILED--$tot->{tests} test $blurb could be run, ".
            "alas--no output ever seen\n";
    } else {
        $pct = sprintf("%.2f", $tot->{good} / $tot->{tests} * 100);
        my $percent_ok = 100*$tot->{ok}/$tot->{max};
        my $subpct = sprintf " %d/%d subtests failed, %.2f%% okay.",
                              $tot->{max} - $tot->{ok}, $tot->{max}, 
                              $percent_ok;

        my($fmt_top, $fmt) = _create_fmts($failedtests);

        # Now write to formats
        for my $script (sort keys %$failedtests) {
          $Curtest = $failedtests->{$script};
          write;
        }
        if ($tot->{bad}) {
            $bonusmsg =~ s/^,\s*//;
            print "$bonusmsg.\n" if $bonusmsg;
            die "Failed $tot->{bad}/$tot->{tests} test scripts, $pct% okay.".
                "$subpct\n";
        }
    }

    printf("Files=%d, Tests=%d, %s\n",
           $tot->{files}, $tot->{max}, timestr($tot->{bench}, 'nop'));
}


my %Handlers = ();
$Strap->{callback} = sub {
    my($self, $line, $type, $totals) = @_;
    print $line if $Verbose;

    my $meth = $Handlers{$type};
    $meth->($self, $line, $type, $totals) if $meth;
};


$Handlers{header} = sub {
    my($self, $line, $type, $totals) = @_;

    warn "Test header seen more than once!\n" if $self->{_seen_header};

    $self->{_seen_header}++;

    warn "1..M can only appear at the beginning or end of tests\n"
      if $totals->{seen} && 
         $totals->{max}  < $totals->{seen};
};

$Handlers{test} = sub {
    my($self, $line, $type, $totals) = @_;

    my $curr = $totals->{seen};
    my $next = $self->{'next'};
    my $max  = $totals->{max};
    my $detail = $totals->{details}[-1];

    if( $detail->{ok} ) {
        _print_ml_less("ok $curr/$max");

        if( $detail->{type} eq 'skip' ) {
            $totals->{skip_reason} = $detail->{reason}
              unless defined $totals->{skip_reason};
            $totals->{skip_reason} = 'various reasons'
              if $totals->{skip_reason} ne $detail->{reason};
        }
    }
    else {
        _print_ml("NOK $curr");
    }

    if( $curr > $next ) {
        print "Test output counter mismatch [test $curr]\n";
    }
    elsif( $curr < $next ) {
        print "Confused test output: test $curr answered after ".
              "test ", $next - 1, "\n";
    }

};

$Handlers{bailout} = sub {
    my($self, $line, $type, $totals) = @_;

    die "FAILED--Further testing stopped" .
      ($self->{bailout_reason} ? ": $self->{bailout_reason}\n" : ".\n");
};


sub _print_ml {
    print join '', $ML, @_ if $ML;
}


# For slow connections, we save lots of bandwidth by printing only once
# per second.
sub _print_ml_less {
    if( !$Ok_Slow || $Last_ML_Print != time ) {
        _print_ml(@_);
        $Last_ML_Print = time;
    }
}

sub _bonusmsg {
    my($tot) = @_;

    my $bonusmsg = '';
    $bonusmsg = (" ($tot->{bonus} subtest".($tot->{bonus} > 1 ? 's' : '').
               " UNEXPECTEDLY SUCCEEDED)")
        if $tot->{bonus};

    if ($tot->{skipped}) {
        $bonusmsg .= ", $tot->{skipped} test"
                     . ($tot->{skipped} != 1 ? 's' : '');
        if ($tot->{sub_skipped}) {
            $bonusmsg .= " and $tot->{sub_skipped} subtest"
                         . ($tot->{sub_skipped} != 1 ? 's' : '');
        }
        $bonusmsg .= ' skipped';
    }
    elsif ($tot->{sub_skipped}) {
        $bonusmsg .= ", $tot->{sub_skipped} subtest"
                     . ($tot->{sub_skipped} != 1 ? 's' : '')
                     . " skipped";
    }

    return $bonusmsg;
}

# Test program go boom.
sub _dubious_return {
    my($test, $tot, $estatus, $wstatus) = @_;
    my ($failed, $canon, $percent) = ('??', '??');

    printf "$test->{ml}dubious\n\tTest returned status $estatus ".
           "(wstat %d, 0x%x)\n",
           $wstatus,$wstatus;
    print "\t\t(VMS status is $estatus)\n" if $^O eq 'VMS';

    if (corestatus($wstatus)) { # until we have a wait module
        if ($Have_Devel_Corestack) {
            Devel::CoreStack::stack($^X);
        } else {
            print "\ttest program seems to have generated a core\n";
        }
    }

    $tot->{bad}++;

    if ($test->{max}) {
        if ($test->{'next'} == $test->{max} + 1 and not @{$test->{failed}}) {
            print "\tafter all the subtests completed successfully\n";
            $percent = 0;
            $failed = 0;        # But we do not set $canon!
        }
        else {
            push @{$test->{failed}}, $test->{'next'}..$test->{max};
            $failed = @{$test->{failed}};
            (my $txt, $canon) = canonfailed($test->{max},$test->{skipped},@{$test->{failed}});
            $percent = 100*(scalar @{$test->{failed}})/$test->{max};
            print "DIED. ",$txt;
        }
    }

    return { canon => $canon,  max => $test->{max} || '??',
             failed => $failed, 
             percent => $percent,
             estat => $estatus, wstat => $wstatus,
           };
}


sub _create_fmts {
    my($failedtests) = @_;

    my $failed_str = "Failed Test";
    my $middle_str = " Stat Wstat Total Fail  Failed  ";
    my $list_str = "List of Failed";

    # Figure out our longest name string for formatting purposes.
    my $max_namelen = length($failed_str);
    foreach my $script (keys %$failedtests) {
        my $namelen = length $failedtests->{$script}->{name};
        $max_namelen = $namelen if $namelen > $max_namelen;
    }

    my $list_len = $Columns - length($middle_str) - $max_namelen;
    if ($list_len < length($list_str)) {
        $list_len = length($list_str);
        $max_namelen = $Columns - length($middle_str) - $list_len;
        if ($max_namelen < length($failed_str)) {
            $max_namelen = length($failed_str);
            $Columns = $max_namelen + length($middle_str) + $list_len;
        }
    }

    my $fmt_top = "format STDOUT_TOP =\n"
                  . sprintf("%-${max_namelen}s", $failed_str)
                  . $middle_str
                  . $list_str . "\n"
                  . "-" x $Columns
                  . "\n.\n";

    my $fmt = "format STDOUT =\n"
              . "@" . "<" x ($max_namelen - 1)
              . "  @>> @>>>> @>>>> @>>> ^##.##%  "
              . "^" . "<" x ($list_len - 1) . "\n"
              . '{ $Curtest->{name}, $Curtest->{estat},'
              . '  $Curtest->{wstat}, $Curtest->{max},'
              . '  $Curtest->{failed}, $Curtest->{percent},'
              . '  $Curtest->{canon}'
              . "\n}\n"
              . "~~" . " " x ($Columns - $list_len - 2) . "^"
              . "<" x ($list_len - 1) . "\n"
              . '$Curtest->{canon}'
              . "\n.\n";

    eval $fmt_top;
    die $@ if $@;
    eval $fmt;
    die $@ if $@;

    return($fmt_top, $fmt);
}

{
    my $tried_devel_corestack;

    sub corestatus {
        my($st) = @_;

        my $did_core;
        eval { # we may not have a WCOREDUMP
            local $^W = 0;  # *.ph files are often *very* noisy
            require 'wait.ph';
            $did_core = WCOREDUMP($st);
        };
        if( $@ ) {
            $did_core = $st & 0200;
        }

        eval { require Devel::CoreStack; $Have_Devel_Corestack++ } 
          unless $tried_devel_corestack++;

        return $did_core;
    }
}

sub canonfailed ($$@) {
    my($max,$skipped,@failed) = @_;
    my %seen;
    @failed = sort {$a <=> $b} grep !$seen{$_}++, @failed;
    my $failed = @failed;
    my @result = ();
    my @canon = ();
    my $min;
    my $last = $min = shift @failed;
    my $canon;
    if (@failed) {
        for (@failed, $failed[-1]) { # don't forget the last one
            if ($_ > $last+1 || $_ == $last) {
                if ($min == $last) {
                    push @canon, $last;
                } else {
                    push @canon, "$min-$last";
                }
                $min = $_;
            }
            $last = $_;
        }
        local $" = ", ";
        push @result, "FAILED tests @canon\n";
        $canon = join ' ', @canon;
    } else {
        push @result, "FAILED test $last\n";
        $canon = $last;
    }

    push @result, "\tFailed $failed/$max tests, ";
    if ($max) {
	push @result, sprintf("%.2f",100*(1-$failed/$max)), "% okay";
    } else {
	push @result, "?% okay";
    }
    my $ender = 's' x ($skipped > 1);
    my $good = $max - $failed - $skipped;
    if ($skipped) {
	my $skipmsg = " (less $skipped skipped test$ender: $good okay, ";
	if ($max) {
	    my $goodper = sprintf("%.2f",100*($good/$max));
	    $skipmsg .= "$goodper%)";
	} else {
	    $skipmsg .= "?%)";
	}
	push @result, $skipmsg;
    }
    push @result, "\n";
    my $txt = join "", @result;
    ($txt, $canon);
}

=end _private

=back

=cut


1;
__END__


=head1 EXPORT

C<&runtests> is exported by Test::Harness by default.

C<$verbose> and C<$switches> are exported upon request.


=head1 DIAGNOSTICS

=over 4

=item C<All tests successful.\nFiles=%d,  Tests=%d, %s>

If all tests are successful some statistics about the performance are
printed.

=item C<FAILED tests %s\n\tFailed %d/%d tests, %.2f%% okay.>

For any single script that has failing subtests statistics like the
above are printed.

=item C<Test returned status %d (wstat %d)>

Scripts that return a non-zero exit status, both C<$? E<gt>E<gt> 8>
and C<$?> are printed in a message similar to the above.

=item C<Failed 1 test, %.2f%% okay. %s>

=item C<Failed %d/%d tests, %.2f%% okay. %s>

If not all tests were successful, the script dies with one of the
above messages.

=item C<FAILED--Further testing stopped: %s>

If a single subtest decides that further testing will not make sense,
the script dies with this message.

=back

=head1 ENVIRONMENT

=over 4

=item C<HARNESS_ACTIVE>

Harness sets this before executing the individual tests.  This allows
the tests to determine if they are being executed through the harness
or by any other means.

=item C<HARNESS_COLUMNS>

This value will be used for the width of the terminal. If it is not
set then it will default to C<COLUMNS>. If this is not set, it will
default to 80. Note that users of Bourne-sh based shells will need to
C<export COLUMNS> for this module to use that variable.

=item C<HARNESS_COMPILE_TEST>

When true it will make harness attempt to compile the test using
C<perlcc> before running it.

B<NOTE> This currently only works when sitting in the perl source
directory!

=item C<HARNESS_FILELEAK_IN_DIR>

When set to the name of a directory, harness will check after each
test whether new files appeared in that directory, and report them as

  LEAKED FILES: scr.tmp 0 my.db

If relative, directory name is with respect to the current directory at
the moment runtests() was called.  Putting absolute path into 
C<HARNESS_FILELEAK_IN_DIR> may give more predictable results.

=item C<HARNESS_IGNORE_EXITCODE>

Makes harness ignore the exit status of child processes when defined.

=item C<HARNESS_NOTTY>

When set to a true value, forces it to behave as though STDOUT were
not a console.  You may need to set this if you don't want harness to
output more frequent progress messages using carriage returns.  Some
consoles may not handle carriage returns properly (which results in a
somewhat messy output).

=item C<HARNESS_OK_SLOW>

If true, the C<ok> messages are printed out only every second.
This reduces output and therefore may for example help testing
over slow connections.

=item C<HARNESS_PERL_SWITCHES>

Its value will be prepended to the switches used to invoke perl on
each test.  For example, setting C<HARNESS_PERL_SWITCHES> to C<-W> will
run all tests with all warnings enabled.

=item C<HARNESS_VERBOSE>

If true, Test::Harness will output the verbose results of running
its tests.  Setting $Test::Harness::verbose will override this.

=back

=head1 EXAMPLE

Here's how Test::Harness tests itself

  $ cd ~/src/devel/Test-Harness
  $ perl -Mblib -e 'use Test::Harness qw(&runtests $verbose);
    $verbose=0; runtests @ARGV;' t/*.t
  Using /home/schwern/src/devel/Test-Harness/blib
  t/base..............ok
  t/nonumbers.........ok
  t/ok................ok
  t/test-harness......ok
  All tests successful.
  Files=4, Tests=24, 2 wallclock secs ( 0.61 cusr + 0.41 csys = 1.02 CPU)

=head1 SEE ALSO

L<Test> and L<Test::Simple> for writing test scripts, L<Benchmark> for
the underlying timing routines, L<Devel::CoreStack> to generate core
dumps from failed tests and L<Devel::Cover> for test coverage
analysis.

=head1 AUTHORS

Either Tim Bunce or Andreas Koenig, we don't know. What we know for
sure is, that it was inspired by Larry Wall's TEST script that came
with perl distributions for ages. Numerous anonymous contributors
exist.  Andreas Koenig held the torch for many years, and then
Michael G Schwern.

Current maintainer is Andy Lester C<< <andy@petdance.com> >>.

=head1 LICENSE

This program is free software; you can redistribute it and/or 
modify it under the same terms as Perl itself.

See L<http://www.perl.com/perl/misc/Artistic.html>

=head1 TODO

Provide a way of running tests quietly (ie. no printing) for automated
validation of tests.  This will probably take the form of a version
of runtests() which rather than printing its output returns raw data
on the state of the tests.  (Partially done in Test::Harness::Straps)

Document the format.

Fix HARNESS_COMPILE_TEST without breaking its core usage.

Figure a way to report test names in the failure summary.

Rework the test summary so long test names are not truncated as badly.
(Partially done with new skip test styles)

Deal with VMS's "not \nok 4\n" mistake.

Add option for coverage analysis.

Trap STDERR.

Implement Straps total_results()

Remember exit code

Completely redo the print summary code.

Implement Straps callbacks.  (experimentally implemented)

Straps->analyze_file() not taint clean, don't know if it can be

Fix that damned VMS nit.

HARNESS_TODOFAIL to display TODO failures

Add a test for verbose.

Change internal list of test results to a hash.

Fix stats display when there's an overrun.

Fix so perls with spaces in the filename work.

=for _private

Keeping whittling away at _run_all_tests()

=for _private

Clean up how the summary is printed.  Get rid of those damned formats.

=head1 BUGS

HARNESS_COMPILE_TEST currently assumes it's run from the Perl source
directory.

=cut

Added jni/tkzinc/Perl/t/Test/Harness/Assert.pm.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# $Id$

package Test::Harness::Assert;

use strict;
require Exporter;
use vars qw($VERSION @EXPORT @ISA);

$VERSION = '0.01';

@ISA = qw(Exporter);
@EXPORT = qw(assert);


=head1 NAME

Test::Harness::Assert - simple assert

=head1 SYNOPSIS

  ### FOR INTERNAL USE ONLY ###

  use Test::Harness::Assert;

  assert( EXPR, $name );

=head1 DESCRIPTION

A simple assert routine since we don't have Carp::Assert handy.

B<For internal use by Test::Harness ONLY!>

=head2 Functions

=over 4

=item B<assert>

  assert( EXPR, $name );

If the expression is false the program aborts.

=cut

sub assert ($;$) {
    my($assert, $name) = @_;

    unless( $assert ) {
        require Carp;
        my $msg = 'Assert failed';
        $msg .= " - '$name'" if defined $name;
        $msg .= '!';
        Carp::croak($msg);
    }

}

=head1 AUTHOR

Michael G Schwern E<lt>schwern@pobox.comE<gt>

=head1 SEE ALSO

L<Carp::Assert>

=cut

1;

Added jni/tkzinc/Perl/t/Test/Harness/Iterator.pm.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package Test::Harness::Iterator;

use strict;
use vars qw($VERSION);
$VERSION = 0.01;


=head1 NAME

Test::Harness::Iterator - Internal Test::Harness Iterator

=head1 SYNOPSIS

  use Test::Harness::Iterator;
  use Test::Harness::Iterator;
  my $it = Test::Harness::Iterator->new(\*TEST);
  my $it = Test::Harness::Iterator->new(\@array);

  my $line = $it->next;


=head1 DESCRIPTION

B<FOR INTERNAL USE ONLY!>

This is a simple iterator wrapper for arrays and filehandles.

=cut

sub new {
    my($proto, $thing) = @_;

    my $self = {};
    if( ref $thing eq 'GLOB' ) {
        bless $self, 'Test::Harness::Iterator::FH';
        $self->{fh} = $thing;
    }
    elsif( ref $thing eq 'ARRAY' ) {
        bless $self, 'Test::Harness::Iterator::ARRAY';
        $self->{idx}   = 0;
        $self->{array} = $thing;
    }
    else {
        warn "Can't iterate with a ", ref $thing;
    }

    return $self;
}

package Test::Harness::Iterator::FH;
sub next {
    my $fh = $_[0]->{fh};
    return scalar <$fh>;
}


package Test::Harness::Iterator::ARRAY;
sub next {
    my $self = shift;
    return $self->{array}->[$self->{idx}++];
}

Added jni/tkzinc/Perl/t/Test/Harness/Straps.pm.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
# -*- Mode: cperl; cperl-indent-level: 4 -*-
# $Id$

package Test::Harness::Straps;

use strict;
use vars qw($VERSION);
use Config;
$VERSION = '0.15';

use Test::Harness::Assert;
use Test::Harness::Iterator;

# Flags used as return values from our methods.  Just for internal 
# clarification.
my $TRUE  = (1==1);
my $FALSE = !$TRUE;
my $YES   = $TRUE;
my $NO    = $FALSE;


=head1 NAME

Test::Harness::Straps - detailed analysis of test results

=head1 SYNOPSIS

  use Test::Harness::Straps;

  my $strap = Test::Harness::Straps->new;

  # Various ways to interpret a test
  my %results = $strap->analyze($name, \@test_output);
  my %results = $strap->analyze_fh($name, $test_filehandle);
  my %results = $strap->analyze_file($test_file);

  # UNIMPLEMENTED
  my %total = $strap->total_results;

  # Altering the behavior of the strap  UNIMPLEMENTED
  my $verbose_output = $strap->dump_verbose();
  $strap->dump_verbose_fh($output_filehandle);


=head1 DESCRIPTION

B<THIS IS ALPHA SOFTWARE> in that the interface is subject to change
in incompatible ways.  It is otherwise stable.

Test::Harness is limited to printing out its results.  This makes
analysis of the test results difficult for anything but a human.  To
make it easier for programs to work with test results, we provide
Test::Harness::Straps.  Instead of printing the results, straps
provide them as raw data.  You can also configure how the tests are to
be run.

The interface is currently incomplete.  I<Please> contact the author
if you'd like a feature added or something change or just have
comments.

=head1 Construction

=head2 C<new>

  my $strap = Test::Harness::Straps->new;

Initialize a new strap.

=cut

sub new {
    my($proto) = shift;
    my($class) = ref $proto || $proto;

    my $self = bless {}, $class;
    $self->_init;

    return $self;
}

=head2 C<_init>

  $strap->_init;

Initialize the internal state of a strap to make it ready for parsing.

=cut

sub _init {
    my($self) = shift;

    $self->{_is_vms}   = $^O eq 'VMS';
    $self->{_is_win32} = $^O eq 'Win32';
}

=head1 Analysis

=head2 C<analyze>

  my %results = $strap->analyze($name, \@test_output);

Analyzes the output of a single test, assigning it the given C<$name>
for use in the total report.  Returns the C<%results> of the test.
See L<Results>.

C<@test_output> should be the raw output from the test, including
newlines.

=cut

sub analyze {
    my($self, $name, $test_output) = @_;

    my $it = Test::Harness::Iterator->new($test_output);
    return $self->_analyze_iterator($name, $it);
}


sub _analyze_iterator {
    my($self, $name, $it) = @_;

    $self->_reset_file_state;
    $self->{file} = $name;
    my %totals  = (
                   max      => 0,
                   seen     => 0,

                   ok       => 0,
                   todo     => 0,
                   skip     => 0,
                   bonus    => 0,

                   details  => []
                  );

    # Set them up here so callbacks can have them.
    $self->{totals}{$name}         = \%totals;
    while( defined(my $line = $it->next) ) {
        $self->_analyze_line($line, \%totals);
        last if $self->{saw_bailout};
    }

    $totals{skip_all} = $self->{skip_all} if defined $self->{skip_all};

    my $passed = ($totals{max} == 0 && defined $totals{skip_all}) ||
                 ($totals{max} && $totals{seen} &&
                  $totals{max} == $totals{seen} && 
                  $totals{max} == $totals{ok});
    $totals{passing} = $passed ? 1 : 0;

    return %totals;
}


sub _analyze_line {
    my($self, $line, $totals) = @_;

    my %result = ();

    $self->{line}++;

    my $type;
    if( $self->_is_header($line) ) {
        $type = 'header';

        $self->{saw_header}++;

        $totals->{max} += $self->{max};
    }
    elsif( $self->_is_test($line, \%result) ) {
        $type = 'test';

        $totals->{seen}++;
        $result{number} = $self->{'next'} unless $result{number};

        # sometimes the 'not ' and the 'ok' are on different lines,
        # happens often on VMS if you do:
        #   print "not " unless $test;
        #   print "ok $num\n";
        if( $self->{saw_lone_not} && 
            ($self->{lone_not_line} == $self->{line} - 1) ) 
        {
            $result{ok} = 0;
        }

        my $pass = $result{ok};
        $result{type} = 'todo' if $self->{todo}{$result{number}};

        if( $result{type} eq 'todo' ) {
            $totals->{todo}++;
            $pass = 1;
            $totals->{bonus}++ if $result{ok}
        }
        elsif( $result{type} eq 'skip' ) {
            $totals->{skip}++;
            $pass = 1;
        }

        $totals->{ok}++ if $pass;

        if( $result{number} > 100000 && $result{number} > $self->{max} ) {
            warn "Enormous test number seen [test $result{number}]\n";
            warn "Can't detailize, too big.\n";
        }
        else {
            $totals->{details}[$result{number} - 1] = 
                               {$self->_detailize($pass, \%result)};
        }

        # XXX handle counter mismatch
    }
    elsif ( $self->_is_bail_out($line, \$self->{bailout_reason}) ) {
        $type = 'bailout';
        $self->{saw_bailout} = 1;
    }
    else {
        $type = 'other';
    }

    $self->{callback}->($self, $line, $type, $totals) if $self->{callback};

    $self->{'next'} = $result{number} + 1 if $type eq 'test';
}

=head2 C<analyze_fh>

  my %results = $strap->analyze_fh($name, $test_filehandle);

Like C<analyze>, but it reads from the given filehandle.

=cut

sub analyze_fh {
    my($self, $name, $fh) = @_;

    my $it = Test::Harness::Iterator->new($fh);
    $self->_analyze_iterator($name, $it);
}

=head2 C<analyze_file>

  my %results = $strap->analyze_file($test_file);

Like C<analyze>, but it runs the given C<$test_file> and parses its
results.  It will also use that name for the total report.

=cut

sub analyze_file {
    my($self, $file) = @_;

    unless( -e $file ) {
        $self->{error} = "$file does not exist";
        return;
    }

    unless( -r $file ) {
        $self->{error} = "$file is not readable";
        return;
    }

    local $ENV{PERL5LIB} = $self->_INC2PERL5LIB;

    my $cmd = $self->{_is_vms}   ? "MCR $^X" :
              $self->{_is_win32} ? Win32::GetShortPathName($^X)
                                 : $^X;

    my $switches = $self->_switches($file);

    # *sigh* this breaks under taint, but open -| is unportable.
    unless( open(FILE, "$cmd $switches $file|") ) {
        print "can't run $file. $!\n";
        return;
    }

    my %results = $self->analyze_fh($file, \*FILE);
    my $exit = close FILE;
    $results{'wait'} = $?;
    if( $? && $self->{_is_vms} ) {
        eval q{use vmsish "status"; $results{'exit'} = $?};
    }
    else {
        $results{'exit'} = _wait2exit($?);
    }
    $results{passing} = 0 unless $? == 0;

    $self->_restore_PERL5LIB();

    return %results;
}


eval { require POSIX; &POSIX::WEXITSTATUS(0) };
if( $@ ) {
    *_wait2exit = sub { $_[0] >> 8 };
}
else {
    *_wait2exit = sub { POSIX::WEXITSTATUS($_[0]) }
}


=head2 C<_switches>

  my $switches = $self->_switches($file);

Formats and returns the switches necessary to run the test.

=cut

sub _switches {
    my($self, $file) = @_;

    local *TEST;
    open(TEST, $file) or print "can't open $file. $!\n";
    my $first = <TEST>;
    my $s = $Test::Harness::Switches || '';
    $s .= " $ENV{'HARNESS_PERL_SWITCHES'}"
      if exists $ENV{'HARNESS_PERL_SWITCHES'};

    if ($first =~ /^#!.*\bperl.*\s-\w*([Tt]+)/) {
        # When taint mode is on, PERL5LIB is ignored.  So we need to put
        # all that on the command line as -Is.
        $s .= join " ", qq[ "-$1"], map {qq["-I$_"]} $self->_filtered_INC;
    }
    elsif ($^O eq 'MacOS') {
        # MacPerl's putenv is broken, so it will not see PERL5LIB.
        $s .= join " ", map {qq["-I$_"]} $self->_filtered_INC;
    }

    close(TEST) or print "can't close $file. $!\n";

    return $s;
}


=head2 C<_INC2PERL5LIB>

  local $ENV{PERL5LIB} = $self->_INC2PERL5LIB;

Takes the current value of C<@INC> and turns it into something suitable
for putting onto C<PERL5LIB>.

=cut

sub _INC2PERL5LIB {
    my($self) = shift;

    $self->{_old5lib} = $ENV{PERL5LIB};

    return join $Config{path_sep}, $self->_filtered_INC;
}

=head2 C<_filtered_INC>

  my @filtered_inc = $self->_filtered_INC;

Shortens C<@INC> by removing redundant and unnecessary entries.
Necessary for OSes with limited command line lengths, like VMS.

=cut

sub _filtered_INC {
    my($self, @inc) = @_;
    @inc = @INC unless @inc;

    # VMS has a 255-byte limit on the length of %ENV entries, so
    # toss the ones that involve perl_root, the install location
    # for VMS
    if( $self->{_is_vms} ) {
        @inc = grep !/perl_root/i, @inc;
    }

    return @inc;
}


=head2 C<_restore_PERL5LIB>

  $self->_restore_PERL5LIB;

This restores the original value of the C<PERL5LIB> environment variable.
Necessary on VMS, otherwise a no-op.

=cut

sub _restore_PERL5LIB {
    my($self) = shift;

    return unless $self->{_is_vms};

    if (defined $self->{_old5lib}) {
        $ENV{PERL5LIB} = $self->{_old5lib};
    }
}

=head1 Parsing

Methods for identifying what sort of line you're looking at.

=head2 C<_is_comment>

  my $is_comment = $strap->_is_comment($line, \$comment);

Checks if the given line is a comment.  If so, it will place it into
C<$comment> (sans #).

=cut

sub _is_comment {
    my($self, $line, $comment) = @_;

    if( $line =~ /^\s*\#(.*)/ ) {
        $$comment = $1;
        return $YES;
    }
    else {
        return $NO;
    }
}

=head2 C<_is_header>

  my $is_header = $strap->_is_header($line);

Checks if the given line is a header (1..M) line.  If so, it places how
many tests there will be in C<< $strap->{max} >>, a list of which tests
are todo in C<< $strap->{todo} >> and if the whole test was skipped
C<< $strap->{skip_all} >> contains the reason.

=cut

# Regex for parsing a header.  Will be run with /x
my $Extra_Header_Re = <<'REGEX';
                       ^
                        (?: \s+ todo \s+ ([\d \t]+) )?      # optional todo set
                        (?: \s* \# \s* ([\w:]+\s?) (.*) )?     # optional skip with optional reason
REGEX

sub _is_header {
    my($self, $line) = @_;

    if( my($max, $extra) = $line =~ /^1\.\.(\d+)(.*)/ ) {
        $self->{max}  = $max;
        assert( $self->{max} >= 0,  'Max # of tests looks right' );

        if( defined $extra ) {
            my($todo, $skip, $reason) = $extra =~ /$Extra_Header_Re/xo;

            $self->{todo} = { map { $_ => 1 } split /\s+/, $todo } if $todo;

            if( $self->{max} == 0 ) {
                $reason = '' unless defined $skip and $skip =~ /^Skip/i;
            }

            $self->{skip_all} = $reason;
        }

        return $YES;
    }
    else {
        return $NO;
    }
}

=head2 C<_is_test>

  my $is_test = $strap->_is_test($line, \%test);

Checks if the $line is a test report (ie. 'ok/not ok').  Reports the
result back in C<%test> which will contain:

  ok            did it succeed?  This is the literal 'ok' or 'not ok'.
  name          name of the test (if any)
  number        test number (if any)

  type          'todo' or 'skip' (if any)
  reason        why is it todo or skip? (if any)

If will also catch lone 'not' lines, note it saw them 
C<< $strap->{saw_lone_not} >> and the line in C<< $strap->{lone_not_line} >>.

=cut

my $Report_Re = <<'REGEX';
                 ^
                  (not\ )?               # failure?
                  ok\b
                  (?:\s+(\d+))?         # optional test number
                  \s*
                  (.*)                  # and the rest
REGEX

my $Extra_Re = <<'REGEX';
                 ^
                  (.*?) (?:(?:[^\\]|^)# (.*))?
                 $
REGEX

sub _is_test {
    my($self, $line, $test) = @_;

    # We pulverize the line down into pieces in three parts.
    if( my($not, $num, $extra)    = $line  =~ /$Report_Re/ox ) {
        my($name, $control) = split /(?:[^\\]|^)#/, $extra if $extra;
        my($type, $reason)  = $control =~ /^\s*(\S+)(?:\s+(.*))?$/ if $control;

        $test->{number} = $num;
        $test->{ok}     = $not ? 0 : 1;
        $test->{name}   = $name;

        if( defined $type ) {
            $test->{type}   = $type =~ /^TODO$/i ? 'todo' :
                              $type =~ /^Skip/i  ? 'skip' : 0;
        }
        else {
            $test->{type} = '';
        }
        $test->{reason} = $reason;

        return $YES;
    }
    else{
        # Sometimes the "not " and "ok" will be on seperate lines on VMS.
        # We catch this and remember we saw it.
        if( $line =~ /^not\s+$/ ) {
            $self->{saw_lone_not} = 1;
            $self->{lone_not_line} = $self->{line};
        }

        return $NO;
    }
}

=head2 C<_is_bail_out>

  my $is_bail_out = $strap->_is_bail_out($line, \$reason);

Checks if the line is a "Bail out!".  Places the reason for bailing
(if any) in $reason.

=cut

sub _is_bail_out {
    my($self, $line, $reason) = @_;

    if( $line =~ /^Bail out!\s*(.*)/i ) {
        $$reason = $1 if $1;
        return $YES;
    }
    else {
        return $NO;
    }
}

=head2 C<_reset_file_state>

  $strap->_reset_file_state;

Resets things like C<< $strap->{max} >> , C<< $strap->{skip_all} >>,
etc. so it's ready to parse the next file.

=cut

sub _reset_file_state {
    my($self) = shift;

    delete @{$self}{qw(max skip_all todo)};
    $self->{line}       = 0;
    $self->{saw_header} = 0;
    $self->{saw_bailout}= 0;
    $self->{saw_lone_not} = 0;
    $self->{lone_not_line} = 0;
    $self->{bailout_reason} = '';
    $self->{'next'}       = 1;
}

=head1 Results

The C<%results> returned from C<analyze()> contain the following
information:

  passing           true if the whole test is considered a pass 
                    (or skipped), false if its a failure

  exit              the exit code of the test run, if from a file
  wait              the wait code of the test run, if from a file

  max               total tests which should have been run
  seen              total tests actually seen
  skip_all          if the whole test was skipped, this will 
                      contain the reason.

  ok                number of tests which passed 
                      (including todo and skips)

  todo              number of todo tests seen
  bonus             number of todo tests which 
                      unexpectedly passed

  skip              number of tests skipped

So a successful test should have max == seen == ok.


There is one final item, the details.

  details           an array ref reporting the result of 
                    each test looks like this:

    $results{details}[$test_num - 1] = 
            { ok        => is the test considered ok?
              actual_ok => did it literally say 'ok'?
              name      => name of the test (if any)
              type      => 'skip' or 'todo' (if any)
              reason    => reason for the above (if any)
            };

Element 0 of the details is test #1.  I tried it with element 1 being
#1 and 0 being empty, this is less awkward.

=head2 C<_detailize>

  my %details = $strap->_detailize($pass, \%test);

Generates the details based on the last test line seen.  C<$pass> is
true if it was considered to be a passed test.  C<%test> is the results
of the test you're summarizing.

=cut

sub _detailize {
    my($self, $pass, $test) = @_;

    my %details = ( ok         => $pass,
                    actual_ok  => $test->{ok}
                  );

    assert( !(grep !defined $details{$_}, keys %details),
            'test contains the ok and actual_ok info' );

    # We don't want these to be undef because they are often
    # checked and don't want the checker to have to deal with
    # uninitialized vars.
    foreach my $piece (qw(name type reason)) {
        $details{$piece} = defined $test->{$piece} ? $test->{$piece} : '';
    }

    return %details;
}

=head1 EXAMPLES

See F<examples/mini_harness.plx> for an example of use.

=head1 AUTHOR

Michael G Schwern C<< <schwern@pobox.com> >>, currently maintained by
Andy Lester C<< <andy@petdance.com> >>.

=head1 SEE ALSO

L<Test::Harness>

=cut


1;

Added jni/tkzinc/Perl/t/Test/More.pm.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
package Test::More;

use 5.004;

use strict;
use Test::Builder;


# Can't use Carp because it might cause use_ok() to accidentally succeed
# even though the module being used forgot to use Carp.  Yes, this
# actually happened.
sub _carp {
    my($file, $line) = (caller(1))[1,2];
    warn @_, " at $file line $line\n";
}



require Exporter;
use vars qw($VERSION @ISA @EXPORT %EXPORT_TAGS $TODO);
$VERSION = '0.47';
@ISA    = qw(Exporter);
@EXPORT = qw(ok use_ok require_ok
             is isnt like unlike is_deeply
             cmp_ok
             skip todo todo_skip
             pass fail
             eq_array eq_hash eq_set
             $TODO
             plan
             can_ok  isa_ok
             diag
            );

my $Test = Test::Builder->new;


# 5.004's Exporter doesn't have export_to_level.
sub _export_to_level
{
      my $pkg = shift;
      my $level = shift;
      (undef) = shift;                  # redundant arg
      my $callpkg = caller($level);
      $pkg->export($callpkg, @_);
}


=head1 NAME

Test::More - yet another framework for writing test scripts

=head1 SYNOPSIS

  use Test::More tests => $Num_Tests;
  # or
  use Test::More qw(no_plan);
  # or
  use Test::More skip_all => $reason;

  BEGIN { use_ok( 'Some::Module' ); }
  require_ok( 'Some::Module' );

  # Various ways to say "ok"
  ok($this eq $that, $test_name);

  is  ($this, $that,    $test_name);
  isnt($this, $that,    $test_name);

  # Rather than print STDERR "# here's what went wrong\n"
  diag("here's what went wrong");

  like  ($this, qr/that/, $test_name);
  unlike($this, qr/that/, $test_name);

  cmp_ok($this, '==', $that, $test_name);

  is_deeply($complex_structure1, $complex_structure2, $test_name);

  SKIP: {
      skip $why, $how_many unless $have_some_feature;

      ok( foo(),       $test_name );
      is( foo(42), 23, $test_name );
  };

  TODO: {
      local $TODO = $why;

      ok( foo(),       $test_name );
      is( foo(42), 23, $test_name );
  };

  can_ok($module, @methods);
  isa_ok($object, $class);

  pass($test_name);
  fail($test_name);

  # Utility comparison functions.
  eq_array(\@this, \@that);
  eq_hash(\%this, \%that);
  eq_set(\@this, \@that);

  # UNIMPLEMENTED!!!
  my @status = Test::More::status;

  # UNIMPLEMENTED!!!
  BAIL_OUT($why);


=head1 DESCRIPTION

B<STOP!> If you're just getting started writing tests, have a look at
Test::Simple first.  This is a drop in replacement for Test::Simple
which you can switch to once you get the hang of basic testing.

The purpose of this module is to provide a wide range of testing
utilities.  Various ways to say "ok" with better diagnostics,
facilities to skip tests, test future features and compare complicated
data structures.  While you can do almost anything with a simple
C<ok()> function, it doesn't provide good diagnostic output.


=head2 I love it when a plan comes together

Before anything else, you need a testing plan.  This basically declares
how many tests your script is going to run to protect against premature
failure.

The preferred way to do this is to declare a plan when you C<use Test::More>.

  use Test::More tests => $Num_Tests;

There are rare cases when you will not know beforehand how many tests
your script is going to run.  In this case, you can declare that you
have no plan.  (Try to avoid using this as it weakens your test.)

  use Test::More qw(no_plan);

In some cases, you'll want to completely skip an entire testing script.

  use Test::More skip_all => $skip_reason;

Your script will declare a skip with the reason why you skipped and
exit immediately with a zero (success).  See L<Test::Harness> for
details.

If you want to control what functions Test::More will export, you
have to use the 'import' option.  For example, to import everything
but 'fail', you'd do:

  use Test::More tests => 23, import => ['!fail'];

Alternatively, you can use the plan() function.  Useful for when you
have to calculate the number of tests.

  use Test::More;
  plan tests => keys %Stuff * 3;

or for deciding between running the tests at all:

  use Test::More;
  if( $^O eq 'MacOS' ) {
      plan skip_all => 'Test irrelevant on MacOS';
  }
  else {
      plan tests => 42;
  }

=cut

sub plan {
    my(@plan) = @_;

    my $caller = caller;

    $Test->exported_to($caller);

    my @imports = ();
    foreach my $idx (0..$#plan) {
        if( $plan[$idx] eq 'import' ) {
            my($tag, $imports) = splice @plan, $idx, 2;
            @imports = @$imports;
            last;
        }
    }

    $Test->plan(@plan);

    __PACKAGE__->_export_to_level(1, __PACKAGE__, @imports);
}

sub import {
    my($class) = shift;
    goto &plan;
}


=head2 Test names

By convention, each test is assigned a number in order.  This is
largely done automatically for you.  However, it's often very useful to
assign a name to each test.  Which would you rather see:

  ok 4
  not ok 5
  ok 6

or

  ok 4 - basic multi-variable
  not ok 5 - simple exponential
  ok 6 - force == mass * acceleration

The later gives you some idea of what failed.  It also makes it easier
to find the test in your script, simply search for "simple
exponential".

All test functions take a name argument.  It's optional, but highly
suggested that you use it.


=head2 I'm ok, you're not ok.

The basic purpose of this module is to print out either "ok #" or "not
ok #" depending on if a given test succeeded or failed.  Everything
else is just gravy.

All of the following print "ok" or "not ok" depending on if the test
succeeded or failed.  They all also return true or false,
respectively.

=over 4

=item B<ok>

  ok($this eq $that, $test_name);

This simply evaluates any expression (C<$this eq $that> is just a
simple example) and uses that to determine if the test succeeded or
failed.  A true expression passes, a false one fails.  Very simple.

For example:

    ok( $exp{9} == 81,                   'simple exponential' );
    ok( Film->can('db_Main'),            'set_db()' );
    ok( $p->tests == 4,                  'saw tests' );
    ok( !grep !defined $_, @items,       'items populated' );

(Mnemonic:  "This is ok.")

$test_name is a very short description of the test that will be printed
out.  It makes it very easy to find a test in your script when it fails
and gives others an idea of your intentions.  $test_name is optional,
but we B<very> strongly encourage its use.

Should an ok() fail, it will produce some diagnostics:

    not ok 18 - sufficient mucus
    #     Failed test 18 (foo.t at line 42)

This is actually Test::Simple's ok() routine.

=cut

sub ok ($;$) {
    my($test, $name) = @_;
    $Test->ok($test, $name);
}

=item B<is>

=item B<isnt>

  is  ( $this, $that, $test_name );
  isnt( $this, $that, $test_name );

Similar to ok(), is() and isnt() compare their two arguments
with C<eq> and C<ne> respectively and use the result of that to
determine if the test succeeded or failed.  So these:

    # Is the ultimate answer 42?
    is( ultimate_answer(), 42,          "Meaning of Life" );

    # $foo isn't empty
    isnt( $foo, '',     "Got some foo" );

are similar to these:

    ok( ultimate_answer() eq 42,        "Meaning of Life" );
    ok( $foo ne '',     "Got some foo" );

(Mnemonic:  "This is that."  "This isn't that.")

So why use these?  They produce better diagnostics on failure.  ok()
cannot know what you are testing for (beyond the name), but is() and
isnt() know what the test was and why it failed.  For example this
test:

    my $foo = 'waffle';  my $bar = 'yarblokos';
    is( $foo, $bar,   'Is foo the same as bar?' );

Will produce something like this:

    not ok 17 - Is foo the same as bar?
    #     Failed test (foo.t at line 139)
    #          got: 'waffle'
    #     expected: 'yarblokos'

So you can figure out what went wrong without rerunning the test.

You are encouraged to use is() and isnt() over ok() where possible,
however do not be tempted to use them to find out if something is
true or false!

  # XXX BAD!  $pope->isa('Catholic') eq 1
  is( $pope->isa('Catholic'), 1,        'Is the Pope Catholic?' );

This does not check if C<$pope->isa('Catholic')> is true, it checks if
it returns 1.  Very different.  Similar caveats exist for false and 0.
In these cases, use ok().

  ok( $pope->isa('Catholic') ),         'Is the Pope Catholic?' );

For those grammatical pedants out there, there's an C<isn't()>
function which is an alias of isnt().

=cut

sub is ($$;$) {
    $Test->is_eq(@_);
}

sub isnt ($$;$) {
    $Test->isnt_eq(@_);
}

*isn't = \&isnt;


=item B<like>

  like( $this, qr/that/, $test_name );

Similar to ok(), like() matches $this against the regex C<qr/that/>.

So this:

    like($this, qr/that/, 'this is like that');

is similar to:

    ok( $this =~ /that/, 'this is like that');

(Mnemonic "This is like that".)

The second argument is a regular expression.  It may be given as a
regex reference (i.e. C<qr//>) or (for better compatibility with older
perls) as a string that looks like a regex (alternative delimiters are
currently not supported):

    like( $this, '/that/', 'this is like that' );

Regex options may be placed on the end (C<'/that/i'>).

Its advantages over ok() are similar to that of is() and isnt().  Better
diagnostics on failure.

=cut

sub like ($$;$) {
    $Test->like(@_);
}


=item B<unlike>

  unlike( $this, qr/that/, $test_name );

Works exactly as like(), only it checks if $this B<does not> match the
given pattern.

=cut

sub unlike {
    $Test->unlike(@_);
}


=item B<cmp_ok>

  cmp_ok( $this, $op, $that, $test_name );

Halfway between ok() and is() lies cmp_ok().  This allows you to
compare two arguments using any binary perl operator.

    # ok( $this eq $that );
    cmp_ok( $this, 'eq', $that, 'this eq that' );

    # ok( $this == $that );
    cmp_ok( $this, '==', $that, 'this == that' );

    # ok( $this && $that );
    cmp_ok( $this, '&&', $that, 'this || that' );
    ...etc...

Its advantage over ok() is when the test fails you'll know what $this
and $that were:

    not ok 1
    #     Failed test (foo.t at line 12)
    #     '23'
    #         &&
    #     undef

It's also useful in those cases where you are comparing numbers and
is()'s use of C<eq> will interfere:

    cmp_ok( $big_hairy_number, '==', $another_big_hairy_number );

=cut

sub cmp_ok($$$;$) {
    $Test->cmp_ok(@_);
}


=item B<can_ok>

  can_ok($module, @methods);
  can_ok($object, @methods);

Checks to make sure the $module or $object can do these @methods
(works with functions, too).

    can_ok('Foo', qw(this that whatever));

is almost exactly like saying:

    ok( Foo->can('this') && 
        Foo->can('that') && 
        Foo->can('whatever') 
      );

only without all the typing and with a better interface.  Handy for
quickly testing an interface.

No matter how many @methods you check, a single can_ok() call counts
as one test.  If you desire otherwise, use:

    foreach my $meth (@methods) {
        can_ok('Foo', $meth);
    }

=cut

sub can_ok ($@) {
    my($proto, @methods) = @_;
    my $class = ref $proto || $proto;

    unless( @methods ) {
        my $ok = $Test->ok( 0, "$class->can(...)" );
        $Test->diag('    can_ok() called with no methods');
        return $ok;
    }

    my @nok = ();
    foreach my $method (@methods) {
        local($!, $@);  # don't interfere with caller's $@
                        # eval sometimes resets $!
        eval { $proto->can($method) } || push @nok, $method;
    }

    my $name;
    $name = @methods == 1 ? "$class->can('$methods[0]')" 
                          : "$class->can(...)";
    
    my $ok = $Test->ok( !@nok, $name );

    $Test->diag(map "    $class->can('$_') failed\n", @nok);

    return $ok;
}

=item B<isa_ok>

  isa_ok($object, $class, $object_name);
  isa_ok($ref,    $type,  $ref_name);

Checks to see if the given $object->isa($class).  Also checks to make
sure the object was defined in the first place.  Handy for this sort
of thing:

    my $obj = Some::Module->new;
    isa_ok( $obj, 'Some::Module' );

where you'd otherwise have to write

    my $obj = Some::Module->new;
    ok( defined $obj && $obj->isa('Some::Module') );

to safeguard against your test script blowing up.

It works on references, too:

    isa_ok( $array_ref, 'ARRAY' );

The diagnostics of this test normally just refer to 'the object'.  If
you'd like them to be more specific, you can supply an $object_name
(for example 'Test customer').

=cut

sub isa_ok ($$;$) {
    my($object, $class, $obj_name) = @_;

    my $diag;
    $obj_name = 'The object' unless defined $obj_name;
    my $name = "$obj_name isa $class";
    if( !defined $object ) {
        $diag = "$obj_name isn't defined";
    }
    elsif( !ref $object ) {
        $diag = "$obj_name isn't a reference";
    }
    else {
        # We can't use UNIVERSAL::isa because we want to honor isa() overrides
        local($@, $!);  # eval sometimes resets $!
        my $rslt = eval { $object->isa($class) };
        if( $@ ) {
            if( $@ =~ /^Can't call method "isa" on unblessed reference/ ) {
                if( !UNIVERSAL::isa($object, $class) ) {
                    my $ref = ref $object;
                    $diag = "$obj_name isn't a '$class' it's a '$ref'";
                }
            } else {
                die <<WHOA;
WHOA! I tried to call ->isa on your object and got some weird error.
This should never happen.  Please contact the author immediately.
Here's the error.
$@
WHOA
            }
        }
        elsif( !$rslt ) {
            my $ref = ref $object;
            $diag = "$obj_name isn't a '$class' it's a '$ref'";
        }
    }
            
      

    my $ok;
    if( $diag ) {
        $ok = $Test->ok( 0, $name );
        $Test->diag("    $diag\n");
    }
    else {
        $ok = $Test->ok( 1, $name );
    }

    return $ok;
}


=item B<pass>

=item B<fail>

  pass($test_name);
  fail($test_name);

Sometimes you just want to say that the tests have passed.  Usually
the case is you've got some complicated condition that is difficult to
wedge into an ok().  In this case, you can simply use pass() (to
declare the test ok) or fail (for not ok).  They are synonyms for
ok(1) and ok(0).

Use these very, very, very sparingly.

=cut

sub pass (;$) {
    $Test->ok(1, @_);
}

sub fail (;$) {
    $Test->ok(0, @_);
}

=back

=head2 Diagnostics

If you pick the right test function, you'll usually get a good idea of
what went wrong when it failed.  But sometimes it doesn't work out
that way.  So here we have ways for you to write your own diagnostic
messages which are safer than just C<print STDERR>.

=over 4

=item B<diag>

  diag(@diagnostic_message);

Prints a diagnostic message which is guaranteed not to interfere with
test output.  Handy for this sort of thing:

    ok( grep(/foo/, @users), "There's a foo user" ) or
        diag("Since there's no foo, check that /etc/bar is set up right");

which would produce:

    not ok 42 - There's a foo user
    #     Failed test (foo.t at line 52)
    # Since there's no foo, check that /etc/bar is set up right.

You might remember C<ok() or diag()> with the mnemonic C<open() or
die()>.

B<NOTE> The exact formatting of the diagnostic output is still
changing, but it is guaranteed that whatever you throw at it it won't
interfere with the test.

=cut

sub diag {
    $Test->diag(@_);
}


=back

=head2 Module tests

You usually want to test if the module you're testing loads ok, rather
than just vomiting if its load fails.  For such purposes we have
C<use_ok> and C<require_ok>.

=over 4

=item B<use_ok>

   BEGIN { use_ok($module); }
   BEGIN { use_ok($module, @imports); }

These simply use the given $module and test to make sure the load
happened ok.  It's recommended that you run use_ok() inside a BEGIN
block so its functions are exported at compile-time and prototypes are
properly honored.

If @imports are given, they are passed through to the use.  So this:

   BEGIN { use_ok('Some::Module', qw(foo bar)) }

is like doing this:

   use Some::Module qw(foo bar);

don't try to do this:

   BEGIN {
       use_ok('Some::Module');

       ...some code that depends on the use...
       ...happening at compile time...
   }

instead, you want:

  BEGIN { use_ok('Some::Module') }
  BEGIN { ...some code that depends on the use... }


=cut

sub use_ok ($;@) {
    my($module, @imports) = @_;
    @imports = () unless @imports;

    my $pack = caller;

    local($@,$!);   # eval sometimes interferes with $!
    eval <<USE;
package $pack;
require $module;
'$module'->import(\@imports);
USE

    my $ok = $Test->ok( !$@, "use $module;" );

    unless( $ok ) {
        chomp $@;
        $Test->diag(<<DIAGNOSTIC);
    Tried to use '$module'.
    Error:  $@
DIAGNOSTIC

    }

    return $ok;
}

=item B<require_ok>

   require_ok($module);

Like use_ok(), except it requires the $module.

=cut

sub require_ok ($) {
    my($module) = shift;

    my $pack = caller;

    local($!, $@); # eval sometimes interferes with $!
    eval <<REQUIRE;
package $pack;
require $module;
REQUIRE

    my $ok = $Test->ok( !$@, "require $module;" );

    unless( $ok ) {
        chomp $@;
        $Test->diag(<<DIAGNOSTIC);
    Tried to require '$module'.
    Error:  $@
DIAGNOSTIC

    }

    return $ok;
}

=back

=head2 Conditional tests

Sometimes running a test under certain conditions will cause the
test script to die.  A certain function or method isn't implemented
(such as fork() on MacOS), some resource isn't available (like a 
net connection) or a module isn't available.  In these cases it's
necessary to skip tests, or declare that they are supposed to fail
but will work in the future (a todo test).

For more details on the mechanics of skip and todo tests see
L<Test::Harness>.

The way Test::More handles this is with a named block.  Basically, a
block of tests which can be skipped over or made todo.  It's best if I
just show you...

=over 4

=item B<SKIP: BLOCK>

  SKIP: {
      skip $why, $how_many if $condition;

      ...normal testing code goes here...
  }

This declares a block of tests that might be skipped, $how_many tests
there are, $why and under what $condition to skip them.  An example is
the easiest way to illustrate:

    SKIP: {
        eval { require HTML::Lint };

        skip "HTML::Lint not installed", 2 if $@;

        my $lint = new HTML::Lint;
        isa_ok( $lint, "HTML::Lint" );

        $lint->parse( $html );
        is( $lint->errors, 0, "No errors found in HTML" );
    }

If the user does not have HTML::Lint installed, the whole block of
code I<won't be run at all>.  Test::More will output special ok's
which Test::Harness interprets as skipped, but passing, tests.
It's important that $how_many accurately reflects the number of tests
in the SKIP block so the # of tests run will match up with your plan.

It's perfectly safe to nest SKIP blocks.  Each SKIP block must have
the label C<SKIP>, or Test::More can't work its magic.

You don't skip tests which are failing because there's a bug in your
program, or for which you don't yet have code written.  For that you
use TODO.  Read on.

=cut

#'#
sub skip {
    my($why, $how_many) = @_;

    unless( defined $how_many ) {
        # $how_many can only be avoided when no_plan is in use.
        _carp "skip() needs to know \$how_many tests are in the block"
          unless $Test::Builder::No_Plan;
        $how_many = 1;
    }

    for( 1..$how_many ) {
        $Test->skip($why);
    }

    local $^W = 0;
    last SKIP;
}


=item B<TODO: BLOCK>

    TODO: {
        local $TODO = $why if $condition;

        ...normal testing code goes here...
    }

Declares a block of tests you expect to fail and $why.  Perhaps it's
because you haven't fixed a bug or haven't finished a new feature:

    TODO: {
        local $TODO = "URI::Geller not finished";

        my $card = "Eight of clubs";
        is( URI::Geller->your_card, $card, 'Is THIS your card?' );

        my $spoon;
        URI::Geller->bend_spoon;
        is( $spoon, 'bent',    "Spoon bending, that's original" );
    }

With a todo block, the tests inside are expected to fail.  Test::More
will run the tests normally, but print out special flags indicating
they are "todo".  Test::Harness will interpret failures as being ok.
Should anything succeed, it will report it as an unexpected success.
You then know the thing you had todo is done and can remove the
TODO flag.

The nice part about todo tests, as opposed to simply commenting out a
block of tests, is it's like having a programmatic todo list.  You know
how much work is left to be done, you're aware of what bugs there are,
and you'll know immediately when they're fixed.

Once a todo test starts succeeding, simply move it outside the block.
When the block is empty, delete it.


=item B<todo_skip>

    TODO: {
        todo_skip $why, $how_many if $condition;

        ...normal testing code...
    }

With todo tests, it's best to have the tests actually run.  That way
you'll know when they start passing.  Sometimes this isn't possible.
Often a failing test will cause the whole program to die or hang, even
inside an C<eval BLOCK> with and using C<alarm>.  In these extreme
cases you have no choice but to skip over the broken tests entirely.

The syntax and behavior is similar to a C<SKIP: BLOCK> except the
tests will be marked as failing but todo.  Test::Harness will
interpret them as passing.

=cut

sub todo_skip {
    my($why, $how_many) = @_;

    unless( defined $how_many ) {
        # $how_many can only be avoided when no_plan is in use.
        _carp "todo_skip() needs to know \$how_many tests are in the block"
          unless $Test::Builder::No_Plan;
        $how_many = 1;
    }

    for( 1..$how_many ) {
        $Test->todo_skip($why);
    }

    local $^W = 0;
    last TODO;
}

=item When do I use SKIP vs. TODO?

B<If it's something the user might not be able to do>, use SKIP.
This includes optional modules that aren't installed, running under
an OS that doesn't have some feature (like fork() or symlinks), or maybe
you need an Internet connection and one isn't available.

B<If it's something the programmer hasn't done yet>, use TODO.  This
is for any code you haven't written yet, or bugs you have yet to fix,
but want to put tests in your testing script (always a good idea).


=back

=head2 Comparison functions

Not everything is a simple eq check or regex.  There are times you
need to see if two arrays are equivalent, for instance.  For these
instances, Test::More provides a handful of useful functions.

B<NOTE> These are NOT well-tested on circular references.  Nor am I
quite sure what will happen with filehandles.

=over 4

=item B<is_deeply>

  is_deeply( $this, $that, $test_name );

Similar to is(), except that if $this and $that are hash or array
references, it does a deep comparison walking each data structure to
see if they are equivalent.  If the two structures are different, it
will display the place where they start differing.

Barrie Slaymaker's Test::Differences module provides more in-depth
functionality along these lines, and it plays well with Test::More.

B<NOTE> Display of scalar refs is not quite 100%

=cut

use vars qw(@Data_Stack);
my $DNE = bless [], 'Does::Not::Exist';
sub is_deeply {
    my($this, $that, $name) = @_;

    my $ok;
    if( !ref $this || !ref $that ) {
        $ok = $Test->is_eq($this, $that, $name);
    }
    else {
        local @Data_Stack = ();
        if( _deep_check($this, $that) ) {
            $ok = $Test->ok(1, $name);
        }
        else {
            $ok = $Test->ok(0, $name);
            $ok = $Test->diag(_format_stack(@Data_Stack));
        }
    }

    return $ok;
}

sub _format_stack {
    my(@Stack) = @_;

    my $var = '$FOO';
    my $did_arrow = 0;
    foreach my $entry (@Stack) {
        my $type = $entry->{type} || '';
        my $idx  = $entry->{'idx'};
        if( $type eq 'HASH' ) {
            $var .= "->" unless $did_arrow++;
            $var .= "{$idx}";
        }
        elsif( $type eq 'ARRAY' ) {
            $var .= "->" unless $did_arrow++;
            $var .= "[$idx]";
        }
        elsif( $type eq 'REF' ) {
            $var = "\${$var}";
        }
    }

    my @vals = @{$Stack[-1]{vals}}[0,1];
    my @vars = ();
    ($vars[0] = $var) =~ s/\$FOO/     \$got/;
    ($vars[1] = $var) =~ s/\$FOO/\$expected/;

    my $out = "Structures begin differing at:\n";
    foreach my $idx (0..$#vals) {
        my $val = $vals[$idx];
        $vals[$idx] = !defined $val ? 'undef' : 
                      $val eq $DNE  ? "Does not exist"
                                    : "'$val'";
    }

    $out .= "$vars[0] = $vals[0]\n";
    $out .= "$vars[1] = $vals[1]\n";

    $out =~ s/^/    /msg;
    return $out;
}


=item B<eq_array>

  eq_array(\@this, \@that);

Checks if two arrays are equivalent.  This is a deep check, so
multi-level structures are handled correctly.

=cut

#'#
sub eq_array  {
    my($a1, $a2) = @_;
    return 1 if $a1 eq $a2;

    my $ok = 1;
    my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2;
    for (0..$max) {
        my $e1 = $_ > $#$a1 ? $DNE : $a1->[$_];
        my $e2 = $_ > $#$a2 ? $DNE : $a2->[$_];

        push @Data_Stack, { type => 'ARRAY', idx => $_, vals => [$e1, $e2] };
        $ok = _deep_check($e1,$e2);
        pop @Data_Stack if $ok;

        last unless $ok;
    }
    return $ok;
}

sub _deep_check {
    my($e1, $e2) = @_;
    my $ok = 0;

#    my $eq;
    {
        # Quiet uninitialized value warnings when comparing undefs.
        local $^W = 0; 

        if( $e1 eq $e2 ) {
            $ok = 1;
        }
        else {
            if( UNIVERSAL::isa($e1, 'ARRAY') and
                UNIVERSAL::isa($e2, 'ARRAY') )
            {
                $ok = eq_array($e1, $e2);
            }
            elsif( UNIVERSAL::isa($e1, 'HASH') and
                   UNIVERSAL::isa($e2, 'HASH') )
            {
                $ok = eq_hash($e1, $e2);
            }
            elsif( UNIVERSAL::isa($e1, 'REF') and
                   UNIVERSAL::isa($e2, 'REF') )
            {
                push @Data_Stack, { type => 'REF', vals => [$e1, $e2] };
                $ok = _deep_check($$e1, $$e2);
                pop @Data_Stack if $ok;
            }
            elsif( UNIVERSAL::isa($e1, 'SCALAR') and
                   UNIVERSAL::isa($e2, 'SCALAR') )
            {
                push @Data_Stack, { type => 'REF', vals => [$e1, $e2] };
                $ok = _deep_check($$e1, $$e2);
            }
            else {
                push @Data_Stack, { vals => [$e1, $e2] };
                $ok = 0;
            }
        }
    }

    return $ok;
}


=item B<eq_hash>

  eq_hash(\%this, \%that);

Determines if the two hashes contain the same keys and values.  This
is a deep check.

=cut

sub eq_hash {
    my($a1, $a2) = @_;
    return 1 if $a1 eq $a2;

    my $ok = 1;
    my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2;
    foreach my $k (keys %$bigger) {
        my $e1 = exists $a1->{$k} ? $a1->{$k} : $DNE;
        my $e2 = exists $a2->{$k} ? $a2->{$k} : $DNE;

        push @Data_Stack, { type => 'HASH', idx => $k, vals => [$e1, $e2] };
        $ok = _deep_check($e1, $e2);
        pop @Data_Stack if $ok;

        last unless $ok;
    }

    return $ok;
}

=item B<eq_set>

  eq_set(\@this, \@that);

Similar to eq_array(), except the order of the elements is B<not>
important.  This is a deep check, but the irrelevancy of order only
applies to the top level.

B<NOTE> By historical accident, this is not a true set comparision.
While the order of elements does not matter, duplicate elements do.

=cut

# We must make sure that references are treated neutrally.  It really
# doesn't matter how we sort them, as long as both arrays are sorted
# with the same algorithm.
sub _bogus_sort { local $^W = 0;  ref $a ? 0 : $a cmp $b }

sub eq_set  {
    my($a1, $a2) = @_;
    return 0 unless @$a1 == @$a2;

    # There's faster ways to do this, but this is easiest.
    return eq_array( [sort _bogus_sort @$a1], [sort _bogus_sort @$a2] );
}

=back


=head2 Extending and Embedding Test::More

Sometimes the Test::More interface isn't quite enough.  Fortunately,
Test::More is built on top of Test::Builder which provides a single,
unified backend for any test library to use.  This means two test
libraries which both use Test::Builder B<can be used together in the
same program>.

If you simply want to do a little tweaking of how the tests behave,
you can access the underlying Test::Builder object like so:

=over 4

=item B<builder>

    my $test_builder = Test::More->builder;

Returns the Test::Builder object underlying Test::More for you to play
with.

=cut

sub builder {
    return Test::Builder->new;
}

=back


=head1 NOTES

Test::More is B<explicitly> tested all the way back to perl 5.004.

Test::More is thread-safe for perl 5.8.0 and up.

=head1 BUGS and CAVEATS

=over 4

=item Making your own ok()

If you are trying to extend Test::More, don't.  Use Test::Builder
instead.

=item The eq_* family has some caveats.

=item Test::Harness upgrades

no_plan and todo depend on new Test::Harness features and fixes.  If
you're going to distribute tests that use no_plan or todo your
end-users will have to upgrade Test::Harness to the latest one on
CPAN.  If you avoid no_plan and TODO tests, the stock Test::Harness
will work fine.

If you simply depend on Test::More, it's own dependencies will cause a
Test::Harness upgrade.

=back


=head1 HISTORY

This is a case of convergent evolution with Joshua Pritikin's Test
module.  I was largely unaware of its existence when I'd first
written my own ok() routines.  This module exists because I can't
figure out how to easily wedge test names into Test's interface (along
with a few other problems).

The goal here is to have a testing utility that's simple to learn,
quick to use and difficult to trip yourself up with while still
providing more flexibility than the existing Test.pm.  As such, the
names of the most common routines are kept tiny, special cases and
magic side-effects are kept to a minimum.  WYSIWYG.


=head1 SEE ALSO

L<Test::Simple> if all this confuses you and you just want to write
some tests.  You can upgrade to Test::More later (it's forward
compatible).

L<Test::Differences> for more ways to test complex data structures.
And it plays well with Test::More.

L<Test> is the old testing module.  Its main benefit is that it has
been distributed with Perl since 5.004_05.

L<Test::Harness> for details on how your test results are interpreted
by Perl.

L<Test::Unit> describes a very featureful unit testing interface.

L<Test::Inline> shows the idea of embedded testing.

L<SelfTest> is another approach to embedded testing.


=head1 AUTHORS

Michael G Schwern E<lt>schwern@pobox.comE<gt> with much inspiration
from Joshua Pritikin's Test module and lots of help from Barrie
Slaymaker, Tony Bowden, chromatic and the perl-qa gang.


=head1 COPYRIGHT

Copyright 2001 by Michael G Schwern E<lt>schwern@pobox.comE<gt>.

This program is free software; you can redistribute it and/or 
modify it under the same terms as Perl itself.

See F<http://www.perl.com/perl/misc/Artistic.html>

=cut

1;

Added jni/tkzinc/Perl/t/TestLog.pm.





































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
package TestLog;

# $Id$
# These test facilities has been developped by C. Mertz <mertz@cena.fr>

use IO::Handle;    # for autoflushing the logs
use Carp;

use Exporter;
@ISA = qw(Exporter);

use vars qw( $VERSION @ISA);
($VERSION) = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/);
@EXPORT = qw( openLog setZincLog log test_eval test_no_eval printableItem printableArray printableList
	      equal_flat_arrays nequal_cplx_arrays);
use strict;

use constant ERROR => '--an error--';

my $selected_loglevel;

sub openLog {
    my ($outfile, $loglevel, $no_logfile) = @_;

    $selected_loglevel = $loglevel;
    if (defined $no_logfile && $no_logfile) {
      open LOG, "> /dev/null";
    }
    else {
      if ( open LOG, "$outfile.prev" ) {
	close LOG;
	unlink "$outfile.prev";
      }
      if ( open LOG, $outfile ) {
	close LOG;
	link $outfile, "$outfile.prev";
	unlink "$outfile";
      }
      
      open LOG,"> $outfile";
      autoflush LOG 1;  # autoflush is important so that logs are up-to-date if Zinc crashes!
    }
}



### print log information to the logfile
### if $level is <= than selected_loglevel (def = 0) then print log on the stdout
###  - a loglevel of -100 means an error to be logged with #### prefix
###  - a loglevel of -10 means an error in the test to be logged with ## prefix
###  - a loglevel of 0 means an message to be usually printed (and logged in any case)
###  - a loglevel greater than 1 is for trace only


sub log {
    my ($loglevel, @strgs) = @_;
    if ($loglevel <= $selected_loglevel) {
	print "#### " if $loglevel == -100;
	print "## " if $loglevel == -10;
	print @strgs;
    }
    print LOG "#### " if $loglevel == -100;
    print LOG "## " if $loglevel == -10;
    print LOG @strgs;
} # end log

my $zinc;
## to init the $zinc
sub setZincLog {
    ($zinc)=@_;
}


my %method_with_tagOrId =
    ("anchorxy" => 1, "bbox" => 1, "bind" => 1, "chggroup" => 1,
     "clone" => 1, "contour" => 1, "coords"=> 1, "cursor" => 1,
     "dchars" => 1, "dtag" => 1, "focus" => 1, "gettags" => 1,
     "group" => 1, # blabla... to complete
     "itemcget" => 1, "itemconfigure" => 1, # blabla... to complete
     "remove" => 1,
     );

###  evaluate $zinc->$method(@args); and verifies that NO ERROR occurs
###  - a loglevel of -100 means an error to be logged with #### prefix
###  - a loglevel of -10 means an error in the test, to be logged with ##
###  - a loglevel of of 0 or greater is for trace only (usefull when an error occurs)
sub test_eval {
    my ($loglevel, $method, @args) = @_;

    my @strs;
    my $start_index = 0;
    my $string2log = "\$zinc->$method (";
    if (scalar @args) {
	if ($method_with_tagOrId{$method} and $args[0] =~ /^\d+$/) {
	    my $type = $zinc->type($args[0]);
	    $string2log .= &printableItem($args[0]) . " (a". ucfirst($type) . ")";
	} else {
	    $string2log .= &printableItem($args[0]) ;
	    }
	$string2log .= ", " if $#args > 0 ;
	my $rest = &printableList(@args[1..$#args]);
	$rest =~ s/^\(//;   ### suppressing the first ( char
	$string2log .= $rest;
    } else {
	$string2log .= ")";
    }
    if ($method eq 'itemcget' or $method eq 'get') {
	$string2log .=  "; #  :=  " ;
    } else {
	$string2log .=  ";\n";
    }
    &log ($loglevel, $string2log);
    
    my (@res, $res);
    if (wantarray()) {
	@res = eval { $zinc->$method (@args) } ;
	if ($method eq 'itemcget' or $method eq 'get') {
	    &log ($loglevel, printableList(@res) . "\n" );
	}
    } else {
	$res = eval { $zinc->$method (@args) } ;
	if ($method eq 'itemcget' or $method eq 'get') {
	    &log ($loglevel, &printableItem($res) . "\n");
	}
    }
    
    if ($@) { # in case of error, logging!
	&log (-100, "Error while evaluating: $string2log;");
	&log (-100, $@);
	my $msgl = &Carp::longmess;
	my ($msg2) = $msgl =~ /.*?( at .*)/s ; 
	&log (-100, "\t$msg2");
	return (ERROR);
    } else {
	if (wantarray()) {
	    return @res;
	}
	else {
	    return $res;
	}
    }
} # end of test_eval

###  evaluate $zinc->$method(@args); and verifies that AN ERROR occurs
###  - a loglevel of -100 means an NO error to be loggued with #### prefix
###  - a loglevel of -10 means NO error in the test to be loggued with ## prefix
###  - a loglevel of of 0 or greater is for trace only if NO error occured
sub test_no_eval {
    my ($reason, $loglevel, $method, @args) = @_;

    my @strs;
    my $start_index = 0;
    my $string2log = "\$zinc->$method (";
    if (scalar @args) {
	if ($method_with_tagOrId{$method} and $args[0] =~ /^\d+$/) {
	    my $type = $zinc->type($args[0]);
	    $string2log .= &printableItem($args[0]) . " (a". ucfirst($type) . ")";
	} else {
	    $string2log .= &printableItem($args[0]) ;
	    }
	$string2log .= ", " if $#args > 0 ;
	my $rest = &printableList(@args[1..$#args]);
	$rest =~ s/^\(//;   ### suppressing the first ( char
	$string2log .= $rest;
    } else {
	$string2log .= ")";
    }
    
    eval { $zinc->$method (@args) } ;

    # in case of NO error, logging!
    if ($@) {
#	print "errormsg=$@"; 
	my ($error_msg) = $@ =~ /(.*)\s*at \/usr\//;
	$error_msg = $@ if !defined $error_msg ;
	&log ($loglevel, "  # When $reason : $string2log;\n  # the error msg is: $error_msg\n");
    } else {
	&log (-100, "An error SHOULD have occured  while evaluating:\n####\t$string2log;\n####\tbecause $reason\n");
    }
} # end of test_no_eval


### return a printable string of something in a readable form
sub printableItem {
    my ($value) = @_;
    my $ref = ref($value);
    if ($ref eq 'ARRAY') {
	return printableArray ( @{$value} );
    }
    elsif ($ref eq 'Tk::Photo') {
	return 'Tk::Photo("'. $value->cget(-file) . '")';
    }
    elsif ($ref eq '') {  # scalar 
	if (defined $value) {
	    if ($value eq '') {
		return  "''";
	    } elsif ($value =~ /^-[a-zA-Z_]+$/) {
		## for the -attribut
		return $value;
	    } elsif ($value =~ /\s/
		     or $value =~ /[a-zA-Z]/
		     or $value =~ /^[\W]$/ ) {
		return "'$value'";
	    }  else {
		return $value;
	    }
	}
	else {
	    return "undef";
	}
    }
    else { # some  class instance
	return $value;
    }
} # end printableItem

### to print an array of something
sub printableArray {
    my (@values) = @_;
    if (! scalar @values) {
	return "[]";
    }
    else {  # the array is not empty
	my $res = "[ ";
	while (@values) {
	    my $value = shift @values;
	    $res .= &printableItem($value);
	    next unless (@values); 
	    if ($value =~ /^-\w+/) {
		$res .= " => ";
	    } elsif (@_) {
		$res .= ", ";
	    }
	    
	}
	return ($res . " ]") ;
    }
} # end printableArray

sub printableList {
    my $res = "(";
    while (@_) {
	my $v = shift @_;
	$res .= &printableItem($v);
	if (defined $v and $v =~ /^-\w+/ and @_) {
	    $res .= " => ";
	} elsif (@_) {
	    $res .= ", ";
	}
    }
    return $res . ")";
} # end printableList


## return 1 if arrays of scalars have the same length and every items are eq 
sub equal_flat_arrays {
    my ($refArray1, $refArray2) = @_;
    my @array1 = @{$refArray1};
    my @array2 = @{$refArray2};

    return 0 if ($#array1 != $#array2);

    for my $i (0..$#array1) {
	return 0 if ($array1[$i] ne $array2[$i]);
    }
    return 1;
} # equal_arrays


## return 0 if arrays of anything are equal
## return 'length' if their length are different
## return xx if some elements are différents
## arrays may be arrays of arrays of arrays ...
sub nequal_cplx_arrays {
    my ($refArray1, $refArray2) = @_;
    my @array1 = @{$refArray1};
    my @array2 = @{$refArray2};

#    print "array1=", &printableArray(@array1), "\narray2=",&printableArray(@array2),"\n";
    return 'length' if ($#array1 != $#array2);

    for my $i (0..$#array1) {
	my $el1 = $array1[$i];
	my $el2 = $array2[$i];
	
	if (ref($el1)) {
#	    print "REF el1=",ref($el1),"\n";
	    if (!ref($el2)) {
		return "elts at index $i are different: $el1 != $el2\n";
	    } elsif (ref($el2) ne ref($el1)) {
		return "elts at index $i are of different type: ".
		    ref($el2), " ne ", ref($el1), "\n";
	    } elsif (ref($el2) eq 'ARRAY') {
		if (my $res = &nequal_cplx_arrays ($el1,$el2)) {
		    return "elts at index $i are different: $res";
		}
	    }
	} elsif (ref($el2) or $el1 ne $el2) {
	    return "elts at index $i are different $el1 != $el2\n";
	}
    }
    return 0;
} # nequal_cplx_arrays


1;

Added jni/tkzinc/Perl/t/Text.t.





















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing all the import

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 5;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}


$mw = MainWindow->new();
$zinc = $mw->Zinc(-width => 100, -height => 100);

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");

# following a mail in zinc@tls.cena.fr (23 sept 2003) by A. Lemort
# we verify that the -width attribute of text items is converted as an integer
my $text = $zinc->add('text', 1, -position => [10,10], -text => "text");

&ok ($zinc->itemconfigure($text, -width => 10.1) or 1, "setting width to 10.1");
&is ($zinc->itemcget($text, -width), 10, "width attribute was converted to an integer");
&ok ($zinc->itemconfigure($text, -width => 9.9) or 1, "setting width to 10.9");
&is ($zinc->itemcget($text, -width), 9, "width attribute was converted to lower integer");



diag("############## text items test");

Added jni/tkzinc/Perl/t/Text2.t.































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing text item

# this script can be used with an optionnal argument, an integer giving
# the delay in seconds during which the graphic updates will be displayed
# this is usefull for visual inspection!

my $mw;
BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 69;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	$mw = MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}

use strict;

my $zinc = $mw->Zinc(-render => 1,
		     -width => 400, -height => 1200)->pack;

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");


my $g1 = $zinc->add('group',1, -tags => "gr1");


my $TEXT = "";

my @families = $mw->fontFamilies;
#print "families=@families\n";

my $family="courier";
if ( grep /^verdana$/i , @families) {
    $family = "verdana";
#    $family = "helvetica";
} elsif ( grep /^helvetica$/i , @families) {
    $family = "helvetica";
} elsif  ( grep /^arial$/i , @families) {
    $family = "arial";
}
#print "family=$family\n";

my $topLevel = $mw->Toplevel();
$topLevel->title("testing all ascii glyphs of $family");

my $zinc0 = $topLevel->Zinc(-render => 1,
			    -width => 300, 
			    -height => 400,)->pack;
like  ($zinc0, qr/^Tk::Zinc=HASH/ , "zinc0 has been created");

$zinc0->fontCreate("fonta", -family => $family, -size => -20, -weight => 'normal');

## doing updates after the mainloop is launched
## this avoids the bug #32 described in http://bugzilla.tkzinc.org/show_bug.cgi?id=32
## and the bug #48 http://bugzilla.tkzinc.org/show_bug.cgi?id=48

$zinc->after(10, \&testExecute);  

Tk::MainLoop;


sub testExecute {

    foreach my $row (2..15) {
        my $string = "";
        foreach my $col (0..15) {
            my $val = $row*16+$col;
            $string .= chr($val) unless $val == 127;
        }
        $zinc0->add('text', 1, -position => [10,$row*20-40], 
                    -text => $string, -font => 'fonta');
        &pass("adding text item n°$row with a $family font of size 20 and normal weight");
    }
    $zinc0->update;
    
    
    # creating text items with many different fonts:

    my $size = 8;
    my $y = 10 ;

    $zinc->fontCreate("font$size", -family => $family, -size => -$size, -weight => 'normal');


    # creating text items with many different fonts:
    $zinc->add('text', $g1, -position => [10,$y],  -tags => ["txt$size"], -font => "font$size",
               -text => "$size pixels $family");
    $zinc->remove('txt8');
    $zinc->fontDelete("font$size");
    $zinc->fontCreate("font$size", -family => $family, -size => -$size, -weight => 'normal');
    $zinc->add('text', $g1, -position => [10,$y],  -tags => ["txt$size"], -font => "font$size",
               -text => "$size pixels $family");
    




    foreach my $size (9..60) {
        $zinc->fontCreate("font$size", -family => $family, -size => -$size, -weight => 'normal');
        $zinc->add('text', $g1, -position => [10,$y],  -tags => ["txt$size"], -font => "font$size",
                   -text => "$size pixels $family");
        $zinc->update;
        
        # deleting both the font and the text item and recreating it 10 times
        foreach my $count (1..10) {
            $zinc->fontDelete("font$size");
            $zinc->remove('txt8');
            $zinc->fontCreate("font$size", -family => $family, -size => -$size, -weight => 'normal');
            $zinc->add('text', $g1, -position => [10,$y],  -tags => ["txt$size"], -font => "font$size",
                       -text => "$size pixels $family");
            $zinc->update;
        }
        &pass("creating and deleting 10 times a text item with a $family font of size $size");
        $y += $size;
    }


    &wait;

    # we should certainly test much much other things!

    diag("############## end of text test");
    exit;
}



sub wait {
    $zinc->update;
    ok (1, $_[0]);

    my $delay = $ARGV[0];
    if (defined $delay) {
	$zinc->update;
	if ($delay =~ /^\d+$/) {
	    sleep $delay;
	} else {
	    sleep 1;
	}
    }
    
}



Added jni/tkzinc/Perl/t/Transformations.t.

































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing all the import

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 21;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}


$mw = MainWindow->new();
$zinc = $mw->Zinc(-width => 100, -height => 100);
my $coords = [ [10,10], [40, 40] ];

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");

my $g = $zinc->add('group',1);
$zinc->scale($g,2,2);
my $rect1 = $zinc->add('rectangle', $g, [10,10,40,40]);

# todo : add a test for the to-come method to get a transform!

is_deeply([ $zinc->coords($rect1) ],
	  [ [10,10], [40, 40] ],
	  "coords are not modified by the group transform!");

is_deeply([
	   $zinc->transform(1, $g, [100, 100, 300, 500] )
	    ],
	  [ 50, 50, 150, 250 ],
	  "transform from window coordinates to group"); 

is_deeply([
	   $zinc->transform($g, 1, [$zinc->coords($rect1)] )
	    ],
	  [ [20,20], [80, 80] ],
	  "transform to window coordinates"); 


# question suggested by D. Etienne (30 sept 2003):
# is it possible to get the window coordinate of a transformed item?
# the answer is of course yes and it is verified here.
my $rect2 = $zinc->add('rectangle', 1, [10,10,40,40]);

# applying a transform to the rectangle:
$zinc->scale($rect2, 2,2);

# todo : add a test for the to-come method to get a transform!

is_deeply([ $zinc->coords($rect1) ],
	  [ [10,10], [40, 40] ],
	  "coords are not modified by the item transform!");

is_deeply([
	   $zinc->transform(1, $rect2, [100, 100, 300, 500] )
	    ],
	  [ 50, 50, 150, 250 ],
	  "transform window coordinates with same transform than rect2 "); 
is_deeply([
	   $zinc->transform($rect2, 1, [$zinc->coords($rect2)] )
	    ],
	  [ [20,20], [80, 80] ],
	  "transform rect2 coordinates to window coordinates, with group 1"); 

is_deeply([
	   $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
	    ],
	  [ [20,20], [80, 80] ],
	  "transform rect2 coordinates to window coordinates with 'device'"); 

$zinc->scale(1, 0.5, 0.5);

is_deeply([
	   $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
	    ],
	  [ [10,10], [40, 40] ],
	  "transform rect2 coordinates to window coordinates with 'device'"); 

# setting the top group transformation to the id, with a translation with tset
$zinc->tset(1,   1,0, 0,1, -20,-10);
is_deeply([
	   $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
	    ],
	  [ [0,10], [60, 70] ],
	  "rect2 window coordinates with 'device' after topgroup transfo setting"); 

# restting top group transformation
$zinc->treset(1);
is_deeply([
	   $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
	    ],
	  [ [20,20], [80, 80] ],
	  "rect2 window coordinates with 'device' after topgroup treset"); 

# resetting the rect2 trasnformation
$zinc->treset($rect2);
is_deeply([
	   $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
	    ],
	  [ [10,10], [40, 40] ],
	  "rect2 window coordinates with 'device' after rect2 treset"); 

$zinc->treset($rect2);
$zinc->skew($rect2, 10,00);
$zinc->skew($rect2, -10,00);
ok(&similarPoints ([
                    $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
                   ],
                   [ [10, 10], [40, 40] ]),
   "rect2 window coordinates with 'device' after rect2 skew (back and forth)");


$zinc->treset($rect2);
$zinc->skew($rect2, -10,00);
$zinc->skew($rect2, 10,00);
ok(&similarPoints ([
                    $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
                   ],
                   [ [10, 10], [40, 40] ]),
   "rect2 window coordinates with 'device' after rect2 skew (forth and back)");


$zinc->treset($rect2);
$zinc->translate($rect2, 34,43);
$zinc->translate($rect2, 15,15, 'absolute'); # the previous relative translation will be overridden
is_deeply([
           $zinc->transform($rect2, 'device', [$zinc->coords($rect2)] )
          ],
	  [ [25,25], [55, 55] ],
	  "rect2 window coordinates with 'device' after rect2 absolute translation"); 

if (0) {
$zinc->treset($rect2);
print "0     ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, 3.14159);
print "+3.14 ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, -3.14159, 0);
print "0     ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, 180, 1);
print "180   ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, -3.14159, 100, 200);
print "0     ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, -3.14159, 0, 100, 200);
print "3.14  ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, 180, 1, 100, 200);
print "0     ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, 180, 1, 100, 200, 300);
print "3.14  ", $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, 180, 1, 100, 200, 300, 600);
print $zinc->tget($rect2, 'rotation'), "\n";
$zinc->rotate($rect2, 180, 1, 100, 200, 300, 600, 900);
print $zinc->tget($rect2, 'rotation'), "\n";
}

$zinc->treset($rect2);
$zinc->translate($rect2, 40,50);
$zinc->scale($rect2, 2,3);
$zinc->rotate($rect2, 3.1415/2);

my ($m00, $m01, $m10, $m11, $m20, $m21) = $zinc->tget($rect2);
#print "matrix: $m00, $m01, $m10, $m11, $m20, $m21\n";
ok(&similarFlatArray ([$zinc->tget($rect2)],
                      [0,     2,     -3,    0,     -150, 80],
                      [0.001, 0.001, 0.001, 0.001, 1,    1]),
   "tget of rect2");

my ($xTranslate, $yTranslate, $xScale, $yScale, $angle, $skew) = $zinc->tget($rect2, 'all');
#print "matrix: $xTranslate, $yTranslate, $xScale, $yScale, $angle, $skew\n";
ok(&similarFlatArray ([$zinc->tget($rect2,'all')],
                      [-150,   80,     2,     3,  3.14159/2, 0    ],
                      [1,       1, 0.001, 0.001,  0.001,     0.001]),
   "tget 'all' of rect2");


($xTranslate, $yTranslate) = $zinc->tget($rect2, 'translation');
#print "translate: $xTranslate, $yTranslate\n";
ok(&similarFlatArray ([$zinc->tget($rect2,'translation')],
                      [-150,   80],
                      [1,      1 ]),
   "tget 'translation' of rect2");

($xScale, $yScale) = $zinc->tget($rect2, 'scale');
#print "scale: $xScale, $yScale\n";
ok(&similarFlatArray ([$zinc->tget($rect2,'scale')],
                      [2,     3,   ],
                      [0.001, 0.001]),
   "tget 'scale' of rect2");

($m00, $m01, $m10, $m11, $m20, $m21) = $zinc->tget($rect2, 'rotation');
ok(&similarFlatArray ([$zinc->tget($rect2,'rotation')],
                      [3.14159/2],
                      [0.001    ]),
   "tget 'rotation' of rect2");

#$zinc->skew($rect2, 10,0);
ok(&similarFlatArray ([$zinc->tget($rect2,'skew')],
                      [0],
                      [0.001    ]),
   "tget 'skew' of rect2");


sub similarPoints {
  my ($ref1, $ref2)= @_;
  diag ("waiting a reference for \$ref1" . ref ($ref1)), return 0 unless ref ($ref1) eq 'ARRAY';
  diag ("waiting a reference for \$ref2"), return 0 unless ref ($ref2) eq 'ARRAY';

  my @array1 = @{$ref1};
  my @array2 = @{$ref2};

  diag ("arrays for \$ref1 and \$ref2 are not of same length"), return 0 
    unless scalar @array1 == @array2;

  for my $i (0.. $#array1) {
    my $pt1 = $array1[$i];
    my $pt2 = $array2[$i];
    diag ("waiting a reference to a point in elt $i \$ref1"), return 0 
      unless ref $pt1 eq 'ARRAY';
    my (@pt1) = @{$pt1};
    diag ("waiting a reference to a point (x,y) in elt $i \$ref1"), return 0 
      unless scalar @pt1 == 2 and &numerical($pt1[0]) and &numerical($pt1[1]) ;
    
    diag ("waiting a reference to a point in elt $i \$ref1"), return 0 
      unless ref $pt2 eq 'ARRAY';
    my (@pt2) = @{$pt2};
    diag ("waiting a reference to a point (x,y) in elt $i \$ref2"), return 0 
      unless scalar @pt2 == 2 and &numerical($pt2[0]) and &numerical($pt2[1]) ;
    
    diag ("delta > 0.001 between x of pt$i"), return 0 if abs($pt1[0]-$pt2[0]) > 0.001;
    diag ("delta > 0.001 between y of pt$i"), return 0 if abs($pt1[1]-$pt2[1]) > 0.001;
  }
  return 1;
}

sub similarFlatArray {
  my ($ref1, $ref2, $deltaref)= @_;
  diag ("waiting a reference for \$ref1"), return 0 unless ref ($ref1) eq 'ARRAY';
  diag ("waiting a reference for \$ref2"), return 0 unless ref ($ref2) eq 'ARRAY';
  diag ("waiting a reference for \$deltaref"), return 0 unless ref ($deltaref) eq 'ARRAY';
  
  my @array1 = @{$ref1};
  my @array2 = @{$ref2};
  my @deltaarray = @{$deltaref};
  diag ("arrays for \$ref1 and \$ref2 and \$deltaref are not of same length,".$#array1.",".$#array2.",".$#deltaarray), return 0 
    unless ($#array1 == $#array2) and ($#array2 == $#deltaarray);
  for my $i (0.. $#array1) {
    my $a = $array1[$i];
    my $b = $array2[$i];
    my $delta = $deltaarray[$i];
    diag ("waiting a numeric value for elt $i of \$ref1"), return 0 
      unless &numerical($a);
    diag ("waiting a numeric value for elt $i of \$ref2"), return 0 
      unless &numerical($b);
    diag ("waiting a numeric value for elt $i of \$deltaref"), return 0 
      unless &numerical($delta);
        
    diag ("delta > $delta between elt $i of \$ref1 ($a) and \$ref2 ($b)"), return 0 
      if (abs($a-$b) > $delta) ;
  }
  return 1;
}


sub numerical {
  my ($v) = @_;
  return 0 unless defined $v;
  ### this really works!!
  return $v eq $v*1;
  }


diag("############## transformations test");


Added jni/tkzinc/Perl/t/find.t.

















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing find methods

# this script can be used with an optionnal argument, an integer giving
# the delay in seconds during which the graphic updates will be displayed
# this is usefull for visual inspection!

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 22;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc;
 	1;
    }) {
        print "unable to load Tk::Zinc";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
 	$mw = MainWindow->new();
 	1;
    }) {
        print "# tests only work properly when it is possible to create a mainwindow in your env\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}


$zinc = $mw->Zinc(-render => 0,
		  -width => 400, -height => 400)->pack;

like  ($zinc, qr/^Tk::Zinc=HASH/ , "zinc has been created");


### creating rectangles:
$g1 = $zinc->add('group',1, -tags => "gr1");
$text = $zinc->add('text', $g1, -position => [-100,-100]);
$g2 = $zinc->add('group',$g1, -tags => "gr2");

$rect11 = $zinc->add('rectangle', $g2, [ 10,10,40,40]);
$rect12 = $zinc->add('rectangle', $g2, [ 50,10,80,40]);
$rect13 = $zinc->add('rectangle', $g2, [ 90,10,120,40]);
$rect21 = $zinc->add('rectangle', $g2, [ 10,50,40,80]);
$rect22 = $zinc->add('rectangle', $g2, [ 50,50,80,80], -tags => 'middle');
$rect23 = $zinc->add('rectangle', $g2, [ 90,50,120,80]);
$rect31 = $zinc->add('rectangle', $g2, [ 10,90,40,120]);
$rect32 = $zinc->add('rectangle', $g2, [ 50,90,80,120]);
$rect33 = $zinc->add('rectangle', $g2, [ 90,90,120,120]);
$zinc->update;

my @list;

@list = $zinc->find('overlapping', 20,20,110,110, $g2);
&ok (&eq_array (\@list ,
		[ $rect33, $rect32, $rect31, $rect23, $rect22,  $rect21, $rect13, $rect12,  $rect11, ]),
     "find overlapping all rectangles");

@list = $zinc->find('enclosed', 20,20,110,110, $g2);
&ok (&eq_array (\@list ,
		[ $rect22 ]),
     "find enclosed  the middle rectangle");

@list = $zinc->find('enclosed', 0,0,110,110, $g2);
&ok (&eq_array (\@list ,
		[ $rect22 , $rect21, $rect12, $rect11 ]),
     "find enclosed  the 4 left up rectangles");

@list = $zinc->find('ancestor', $rect33);
&ok (&eq_array (\@list ,
		[ $g2 , $g1, 1 ]),
     "find ancestor of one rectangle");

@list = $zinc->find('withtag', ".gr1.");
#print "@list\n";
&ok (&eq_array (\@list ,
		[ $g2, $text, ]),
     "find direct descendant of group tagged gr1");

@list = $zinc->find('withtag', ".gr1*");
#print "@list\n";
&is_deeply ( [ @list ] ,
	     [ $g2, ($zinc->find('withtag', ".gr1.gr2*"), $text ) ],
	     "find all descendant of group tagged gr1");

&is_deeply ( [ ($zinc->find('withtag', ".gr1.gr2*")) ],
	     [ ($zinc->find('withtag', "*gr2*")) ],
	     "comparing full pathtag and reduced pathtag to a group");

&is_deeply ( [ ($zinc->find('withtag', ".gr1.gr2.middle")) ],
	     [ ($zinc->find('withtag', "*gr2.middle")) ],
	     "comparing full pathtag and reduced pathtag to a rectangle");

&is_deeply ( [ ($zinc->find('withtag', ".gr1.gr2.middle")) ],
	     [ ($zinc->find('withtag', "*middle")) ],
	     "comparing full pathtag and reduced pathtag to a rectangle");

&is_deeply ( [ ($zinc->find('withtag', ".gr1.gr2.middle")) ],
	     [ ($zinc->find('withtag', "middle")) ],
	     "comparing full pathtag and reduced pathtag to a rectangle");

&is_deeply ( [ ($zinc->find('withtype', "group")) ],
	     [ $g1, $g2 ],
	     "find with type 'group'");

&is_deeply ( [ ($zinc->find('withtype', "group", ".$g1.")) ],
	     [ $g2 ],
	     "find with type 'group' starting from g1");

&is_deeply ( [ ($zinc->find('withtype', "group", ".$g1.")) ],
	     [ ($zinc->find('withtype', "group", ".$g1*")) ],
	     "find with type 'group' starting from g1");

&is_deeply ( [ ($zinc->find('withtype', "rectangle")) ],
	     [ $rect33, $rect32, $rect31, $rect23, $rect22,  $rect21, $rect13, $rect12,  $rect11, ],
	     "find with type 'rectangle'");
&is_deeply ( [ ($zinc->find('withtype', "rectangle", ".$g1*")) ],
	     [ ($zinc->find('withtype', "rectangle")) ],
	     "find with type 'rectangle' starting from .g1*");


## testing overlapping find with atomic group (for testig the bug 
##   reported by D. Etienne the 11th June 04
$zinc->itemconfigure($g2, -atomic => 1);
@list = $zinc->find('overlapping', 20,20,110,110);
#print "overlapping17 (",join (',', @list),")   \$g2=$g2\n";
&ok (&eq_array (\@list ,
		[ $g2 ]),
     "find overlapping when group becomes atomic, without specifying starting group");

@list = $zinc->find('overlapping', 20,20,110,110,1);
#print "overlapping18 (",join (',', @list),")   \$g2=$g2\n";
&ok (&eq_array (\@list ,
		[ $g2 ]),
     "find overlapping when group becomes atomic, starting from group 1");

@list = $zinc->find('overlapping', 20,20,110,110,1,1);
&ok (&eq_array (\@list ,
		[ $g2 ]),
     "find overlapping when group becomes atomic, recursively, starting from group 1");


## testing enclosing find with atomic group
@list = $zinc->find('enclosed', 0,0,200,200);
#print "enclosing20 (",join (',', @list),")   \$g2=$g2\n";
&ok (&eq_array (\@list ,
		[ $g2 ]),
     "find enclosed when group becomes atomic, without specifying starting group");

@list = $zinc->find('enclosed', 0,0,200,200,  1);
#print "enclosing21 (",join (',', @list),")   \$g2=$g2\n";
&ok (&eq_array (\@list ,
		[ $g2 ]),
     "find enclosed when group becomes atomic, starting from group 1");

@list = $zinc->find('enclosed', 0,2,200,200,  1,1);
#print "enclosing22 (",join (',', @list),")   \$g2=$g2\n";
&ok (&eq_array (\@list ,
		[ $g2 ]),
     "find enclosed when group becomes atomic, recursively, starting from group 1");

# Tk::MainLoop;



sub wait {
    $zinc->update;
    ok (1, $_[0]);

    my $delay = $ARGV[0];
    if (defined $delay) {
	$zinc->update;
	if ($delay =~ /^\d+$/) {
	    sleep $delay;
	} else {
	    sleep 1;
	}
    }
    
}



diag("############## Images test");

Added jni/tkzinc/Perl/t/test-methods.pl.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
#!/usr/bin/perl -w
# $Id$
# This non-regression test has been developped by C. Mertz <mertz@cena.fr>

use Tk;
use Tk::Zinc;
use Getopt::Long;
use TestLog;

use strict;

use constant ERROR => '--an error--';


# the following list be coherent with the treatments done in the TEST section.
my @testsList = (
		 1 => 'test_contour_and_coords (quick)',
		 2 => 'test_forbidden_operations_on_root_group (quick)',
		 3 => 'test_errors (quick)',
		 4 => 'test_bboxes (quick)',
		 5 => 'test_gradient_coding (quick)',
		 );
my %testsHash;
{ my @tests = @testsList;
  while (@tests) {
      my $num = shift (@tests);
      my $comment = shift (@tests);
      $testsHash{ $num } = $comment;
  }
}

unshift (@INC, "/usr/lib/perl5/Tk");  # for getting Tk some images;

# les variables positionnées en fonction des options de la ligne de commande
my $opt_log = 0;
my $opt_trace = "";
my $opt_render = -1;
my $opt_type = 0;
my $outfile;
my $opt_tests = "all";

# on récupère les options
Getopt::Long::Configure('pass_through');
my $optstatus = GetOptions('log=i' => \$opt_log,
			   'out=s' => \$outfile,
			   'trace=s' => \$opt_trace,
			   'render:s' => \$opt_render,
			   'type=s' => \$opt_type,
			   'help' => \&usage,
			   'tests:s' => \$opt_tests,
			   );

# on teste la validité de l'option -render!
if ($opt_render eq '') {
    print "-render option have no value!\n";
    &usage;
}
$opt_render = 1 if $opt_render == -1;
unless ($opt_render==0 or $opt_render==1 or $opt_render==2) {
    print "-render option value must be 0, 1 or 2!\n";
    &usage;
}


$outfile = "methods-$Tk::Zinc::VERSION.log" if (!defined $outfile);

&openLog($outfile, $opt_log);

sub usage {
    my ($text) = @_;
    print $text,"\n" if (defined $text);
    print "test-methods [options]\n";
    print "       A non-regression test suite for zinc.\n";
    print "       Some exhaustive test of TkZinc methods. Of course everything is not tested yet\n";
    print " options are:\n";
    print " -help           to print this short help\n";
    print " -log <n>        trace level, defaulted to 0; higher level trace more infos\n";
    print " -out filename   the log filename. defaulted to methods-<version><-rendering>.log\n";
    print "      NB: the previous log file is always renamed with a .prev suffix\n";
    print " -render 0|1|2   to select the render option of TkZinc (defaulted to 1)\n";
    print " -trace <an_item_option>  to better trace usage of an option\n";
    print " -type <a_zinc_item_type> to limits tests to this item type.\n";
    print " -tests to get the list of available tests.\n";
    print " -tests i,j,k... to define the list of tests to pass.\n";
    exit;
}

my $mw = MainWindow->new();

&log (0, "testing Zinc-perl Version=" . $Tk::Zinc::VERSION . " - ", $mw->zinc(), "\n");

## must be done after the LOG file is open
my @tests = &parseTestsOpt($opt_tests);
my %tests;
foreach my $t (@tests) {$tests{$t} = $t }


# The explanation displayed when running this demo
my $label=$mw->Label(-text => "This is a non-regression test, testing
some sets of methods!",
		     -justify => 'left')->pack(-padx => 10, -pady => 10);


# Creating the zinc widget
my $zinc = $mw->Zinc(-width => 500, -height => 500,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 0, -relief => 'sunken',
		     -render => $opt_render,
		     )->pack;

&setZincLog($zinc);

sub test_gradient_coding {
    &log (0, "#----  Start of test_gradient_coding ----\n");
    my $log_level = 2 ;
    ### CM to be done!

    ### first testing legal gradient
    foreach (0..2) {
	my $i=0;
	foreach my $g ("red", "bLue","#ff00ff","rgb:12/34/56","CIEXYZ:1.2/0.9/3.4",
		       "CIEuvY:0.5/.4/0.9", "CIExyY:.52/0.1/0.8", "CIELab:99.1/43./56.1",
		       "CIELuv:88/-1/-2.1", "TekHVC:345/1.2/100",
		       ) {
	    ## first simple color, with different X legal coding
	    &test_eval ($log_level, "gname", $g,"grad".$i);
	    $i++;
	    ## the same color with transparency
	    my $transparency = ($i * 4) % 101;
	    &test_eval ($log_level, "gname", "$g;$transparency","grad".$i);
	    $i++;	
	}

	## different axial gradient without the gradient type at the beginning
	foreach my $g ("red|blue", "red |blue", "red | blue",
		       "red|green|blue", "red |green|blue", "red |green |blue", "red | green|blue"
		       , "red |green| blue", "red |green | blue", "red | green | blue") {
	    ## first simple color, with different X legal coding
	    &test_eval ($log_level, "gname", $g,"grad".$i);
	    $i++;
	}
	## different axial gradient with explicit gradient type at the beginning
	## and different angle value!
	foreach my $angle qw(0 12 90 271 360) {
	    foreach my $g ("=axial $angle |red|blue",
			   "=axial $angle | red|blue",
			   "=axial $angle | red |blue",
			   "=axial $angle | red | blue",
			   "=axial $angle | red|green|blue",
			   "=axial $angle |red |green|blue",
			   "=axial $angle |red |green |blue",
			   "=axial $angle |red | green|blue",
			   "red |green| blue",
			   "red |green | blue",
			   "red | green | blue",
			   ) {
		## first simple color, with different X legal coding
		&test_eval ($log_level, "gname", $g,"grad".$i);
		$i++;
	    }
	}
	# and now deleting unused named gradient
	foreach my $j (0..$i-1) {
	    &test_eval ($log_level, "gdelete", "grad".$j);
	}
    }

    ### and now testing illegal gradient
    my $i=-1;
    &test_no_eval ("X color name with blank inside",
		   $log_level, "gname", "navy blue","grad".$i++);
    &test_no_eval ("bad gradient type",
		   $log_level, "gname", "=badtype 1 |red|blue","grad".$i++);
    &test_no_eval ("axial gradient with excessive parameters",
		   $log_level, "gname", "=axial 67 1 |red|blue","grad".$i++);
    &test_no_eval ("radial gradient with excessive parameters",
		   $log_level, "gname", "=radial 30 32 1 |red|blue","grad".$i++);
    &test_no_eval ("path gradient with excessive parameters",
		   $log_level, "gname", "=path 30 32 1 |red|blue","grad".$i++);
    ## testing bad types for gradient type
    # to be done
    foreach my $j (0..$i-1) {
	&test_eval ($log_level, "gdelete", "grad".$j);
    }
    
    &log (0, "#----  End of test_gradient_coding  -----\n");
} # end of test_gradient_coding
    
## TkZinc bbox method doesn't return correct values for bbox. This test
# function tries to find out in which cases these bbox are wrong
sub test_bboxes {
    &log (0, "#----  Start of test_bboxes ----\n");
    &creating_items; # to know exactly which items exists at the beginning of this test

    # Rectangles
    &bbox_must_be($zinc->add('rectangle', 1, [100,200,300,400]),
		  [100,200,300,400], "a simple rectangle");
    &bbox_must_be($zinc->add('rectangle', 1, [300,400,100,200]),
		  [100,200,300,400], "a simple reversed rectangle");
    
    # Rectangles with linewidth = 2, 3, 4 and 5
    &bbox_must_be($zinc->add('rectangle', 1, [100,200,300,400], -linewidth =>2),
		  [100,200,300,400], "a simple rectangle with linewidth of 2");
    &bbox_must_be($zinc->add('rectangle', 1, [100,200,300,400], -linewidth =>3),
		  [100,200,300,400], "a simple rectangle with linewidth of 3");
    &bbox_must_be($zinc->add('rectangle', 1, [100,200,300,400], -linewidth =>4),
		  [100,200,300,400], "a simple rectangle with linewidth of 4");
    &bbox_must_be($zinc->add('rectangle', 1, [100,200,300,400], -linewidth =>5),
		  [100,200,300,400], "a simple rectangle with linewidth of 5");
    
    # Rectangular curves
    &bbox_must_be($zinc->add('curve', 1, [ [100,200], [300,200], [300,400], [100,400] ],
			     -linewidth =>0),
		  [100,200,300,400], "a rectangular curve of linewidth => 0");
    &bbox_must_be($zinc->add('curve', 1, [ [100,200], [300,200], [300,400], [100,400] ]),
		  [100,200,300,400], "a rectangular curve of linewidth => 1");
    &bbox_must_be($zinc->add('curve', 1, [ [100,200], [300,200], [300,400], [100,400] ],
			     -linewidth => 2),
		  [100,200,300,400], "a rectangular curve of linewidth => 2");
    &bbox_must_be($zinc->add('curve', 1, [ [100,200], [300,200], [300,400], [100,400] ],
			     -linewidth => 3),
		  [100,200,300,400], "a rectangular curve of linewidth => 3");
    &bbox_must_be($zinc->add('curve', 1, [ [100,200], [300,200], [300,400], [100,400] ],
			     -linewidth => 5),
		  [100,200,300,400], "a rectangular curve");

    # triangular curves (with a sharp angle)
    &bbox_must_be($zinc->add('curve', 1, [ [0,0], [100,0], [0,10] ]),
		  [0,0,100,10], "a triangular curve of linewidth => 1)");

    # Arcs
    &bbox_must_be($zinc->add('arc', 1, [100,200,300,400]),
		  [100,200,300,400], "an arc");
    &bbox_must_be($zinc->add('arc', 1, [100,200,300,400], -linewidth => 2),
		  [100,200,300,400], "an arc of linewidth => 2");
    &bbox_must_be($zinc->add('arc', 1, [100,200,300,400], -linewidth => 3),
		  [100,200,300,400], "an arc of linewidth => 3");
    

    &log (0, "#----  End of test_bboxes  -----\n");
} # end of test_bboxes

sub bbox_must_be {
    my ($item, $bbox_ref, $explanation) = @_;
    my @computed_bbox=$zinc->bbox($item);
    my @theoritical_bbox = @{$bbox_ref};
    unless (&equal_flat_arrays (\@theoritical_bbox, \@computed_bbox)) {
	&log(-10, "bad bbox of $explanation:\n  ## computed = ", &printableArray(\@computed_bbox),
	     " theoritical = ", &printableArray(\@theoritical_bbox), "\n");
    }
} # end of bbox_must_be


sub test_contour_and_coords {
    &log (0, "#----  Start of test_contour_and_coords ----\n");
    my $log_level = 2 ;

    $zinc->add('rectangle', 1, [ [100,200], [400,300] ], -tags => ['rect1']);
    my $contour_rect = [ [100,200], [100,300], [400,300], [400,200] ];
    my $rev_contour_rect = [ [100,200], [400,200], [400,300], [100,300] ];

    $zinc->add('rectangle', 1, [ 100,200, 400,300 ], -tags => ['rect2']);
    &verify_coords_of_contour ('eq','rect1', 'rect2', 0);
    &verify_coords_of_contour_points ('eq','rect1', 'rect2', 0);


    $zinc->add('arc', 1, [ [100,200], [400,300] ], -tags => ['arc1']);
    $zinc->add('arc', 1, [ 100,200, 400,300 ], -tags => ['arc2']);
    &verify_coords_of_contour ('eq','arc1', 'arc2', 0);
    &verify_coords_of_contour_points ('eq','arc1', 'arc2', 0);

    my $contour1 = [ [100,200], [400,300,'c'], [500,100], [350,10, 'c'], [300,500,'c'], [50,100] ];
    my $contour2 = [  100,200,   400,300,       500,100,   350,10,        300,500,       50,100 ];
    my $contour3 = [ [100,200], [400,300],     [500,100], [350,10],      [300,500],     [50,100]];
    $zinc->add('curve', 1, $contour1, -tags => ['curve1']);
    $zinc->add('curve', 1, $contour2, -tags => ['curve2']);
    $zinc->add('curve', 1, $contour3, -tags => ['curve3']);
    &verify_coords_of_contour ('ne','curve1', 'curve2', 0);
    &verify_coords_of_contour_points ('ne','curve1', 'curve2', 0);
    
    &verify_coords_of_contour ('eq','curve2', 'curve3', 0);
    &verify_coords_of_contour_points ('ne','curve2', 'curve3', 0);

    ## testing contours
    $zinc->add('curve', 1, [], -tags => ['curve_contour_0']);
    $zinc->add('curve', 1, [], -tags => ['curve_contour_plus']);
    $zinc->add('curve', 1, [], -tags => ['curve_contour_minus']);
    $zinc->contour('curve_contour_0','add',0, $contour1);
    $zinc->contour('curve_contour_plus','add',+1, $contour1);
    $zinc->contour('curve_contour_minus','add',-1, $contour1);
    &verify_coords_of_contour ('eq','curve1', 'curve_contour_0', 0);
    &verify_coords_of_contour ('ne','curve_contour_plus', 'curve_contour_minus', 0);
    if (&nequal_cplx_arrays ($zinc->coords('curve_contour_0',0),
			     $zinc->coords('curve_contour_minus',0))) {
	&verify_coords_of_contour ('eq','curve1', 'curve_contour_plus', 0);
    } else {
	&verify_coords_of_contour ('eq','curve1', 'curve_contour_minus', 0);
    }
    $zinc->add('curve', 1, [], -tags => ['curve_contour_minus_plus']);
    $zinc->contour('curve_contour_minus_plus','add',1,
		   [$zinc->coords('curve_contour_minus',0)]);
    &verify_coords_of_contour ('eq','curve1', 'curve_contour_minus_plus', 0);

    ## the following curves are similar, because the first contour is
    ## always set counterclockwise
    $zinc->add('curve', 1, $contour_rect, -tags => ['curve_rect_coords']);
    $zinc->add('curve', 1, $rev_contour_rect, -tags => ['curve_rect_coords_reversed']);
    &verify_coords_of_contour ('ne','curve_rect_coords', 'curve_rect_coords_reversed', 0); # we should test they are reversed
    
    $zinc->add('curve', 1, [], -tags => ['curve_rect_0']);
    $zinc->add('curve', 1, [], -tags => ['curve_rect_plus']);
    $zinc->add('curve', 1, [], -tags => ['curve_rect_minus']);

    ## the following lines are errors: we cannot add an item as contour with flag 0
    &test_no_eval ("adding a contour from a rectangle with flag=0",
		   $log_level, "contour", 'curve_rect_0','add',0, 'rect1');
    &test_no_eval ("adding a contour from an arc with flag=0",
		   $log_level, "contour", 'curve_rect_0','add',0, 'arc1');
    
    $zinc->contour('curve_rect_plus','add',1, 'rect1');
    $zinc->contour('curve_rect_minus','add',-1, 'rect1');
    &verify_coords_of_contour ('ne','curve_rect_plus', 'curve_rect_minus', 0);
    &verify_coords_of_contour ('eq','curve_rect_coords', 'curve_rect_plus', 0);
    &verify_coords_of_contour ('eq','curve_rect_coords_reversed', 'curve_rect_minus', 0);

    $zinc->add('tabular',1, 2, -tags => ['tabular1']);
    $zinc->add('track',1, 2, -tags => ['track1']);
    $zinc->add('waypoint',1, 2, -tags => ['waypoint1']);
    $zinc->add('reticle',1, -tags => ['reticle1']);

    ## we test now the following errors: we cannot use a track, waypoint, reticle, map as a contour
    &test_eval ($log_level, "contour", 'curve_rect_0','add',1, 'tabular1');
    &test_no_eval ("using the contour of a track",
		   $log_level, "contour", 'curve_rect_0','add',1, 'track1');
    &test_no_eval ("using the contour of a waypoint",
		   $log_level, "contour", 'curve_rect_0','add',1, 'waypoint1');
    &test_no_eval ("using the contour of a reticle",
		   $log_level, "contour", 'curve_rect_0','add',1, 'reticle1');

    ## we test now the following errors: we cannot add a contour to track, waypoint, rectangle...
    &test_no_eval ("adding a contour to a track",
		   $log_level, "contour", 'track1','add',1, 'rect1');
    &test_no_eval ("adding a contour to a waypoint",
		   $log_level, "contour", 'waypoint1','add',1, 'rect1');
    &test_no_eval ("adding a contour to a rectangle",
		   $log_level, "contour", 'rect1','add',1, 'rect2');

    &test_no_eval ("adding a contour with a malformed list",
		   $log_level, "contour", 'curve_rect_0','add',1, [1]);
    &test_no_eval ("adding a contour with a malformed list",
		   $log_level, "contour", 'curve_rect_0','add',1, [1, 2, 3]);
    &test_no_eval ("adding a contour with a malformed list",
		   $log_level, "contour", 'curve_rect_0','add',1, [1, 2, 'c']);
    &test_no_eval ("adding a contour with a malformed list",
		   $log_level, "contour", 'curve_rect_0','add',1, [1, 2, [3, 4] ]);
    &test_no_eval ("adding a contour with a malformed list",
		   $log_level, "contour", 'curve_rect_0','add',1, [1, 2, [3, 4], [5, 6] ]);

    # we should test here what happens when successive points are identical in a curve

    # we should test here what happens when the last point is identical to the first point in a curve
    
    &log (0, "#----  End of test_contour_and_coords  -----\n");
} # end of test_contour_and_coords



sub test_forbidden_operations_on_root_group {
    &log (0, "#----  Start of test_forbidden_operations_on_root_group ----\n");
    my $log_level = 2 ;

    my @all_items =  $zinc->find('withtag',".1*");
    print "Items before deleting 1: @all_items\n";
    &test_no_eval ("removing the root group",
		   $log_level, "remove", 1); ## cannot delete root group
    @all_items =  $zinc->find('withtag',".1*");
    print "Items after deleting 1: @all_items\n";
    $zinc->add('group', 1, -tags => "g2");
    # cannot chggroup root group:    
    &test_no_eval ("changing the group of the root group",
		   $log_level, "chggroup", 1,"g2");
    # cannot clone root group
    &test_no_eval ("cloning the root group",
		   $log_level, "clone", 1);
    
    &log (0, "#----  End of test_forbidden_operations_on_root_group  -----\n");
} # end of test_forbidden_operations_on_root_group


### tests all errors as defined in the refman
sub test_errors {
    &log (0, "#----  Start of test_errors ----\n");
    my $log_level = 2 ;

    &creating_items;

    ## add method with bad argument
    # In a curve, it is an error to have more than two succcessive control points
    # or to start or finish a curve with a control point.
    &test_no_eval ("having more than two succcessive control points",
		   $log_level, "add", 'curve', 1,
		   [ [10,20], [30,40,'c'], [50,60,'c'], [70,80,'c'], [90,100] ]);
    &test_no_eval ("starting a curve with a control point",
		   $log_level, "add", 'curve', 1,
		   [ [30,40,'c'], [50,60], [70,80], [90,100] ]);
    &test_no_eval ("finishing a curve with a control point",
		   $log_level, "add", 'curve', 1,
		   [ [30,40,], [50,60,'c'], [70,80], [90,100,'c'] ]);
    
    # Text indices
    # sel.first Refers to the first character of the selection in the item.
    # If the selection is not in the item, this form returns an error.
     &test_no_eval ("refering to sel.first in a text item without selection",
		   $log_level, "insert", 'text', 'sel.first', "string");
    # sel.last Refers to the last character of the selection in the item.
    # If the selection is not in the item, this form returns an error.
     &test_no_eval ("refering to sel.last in a text item without selection",
		   $log_level, "insert", 'text', 'sel.last', "string");
 
    # If no item is named by tagOrId or if the item doesn t support anchors,
    # an error is raised.
    &test_no_eval ("refering no item by tagOrId with anchorxy",
		   $log_level, "anchorxy", 'bad_tag', 'rectangle');

    # If the item doesn't support anchors, an error is raised.
    &test_no_eval ("refering item that does not support anchors",
		   $log_level, "anchorxy", 'rectangle', 'ne');

    # If the item doesn't support anchors, an error is raised.
    &test_no_eval ("refering a bad anchor name",
		   $log_level, "anchorxy", 'text', 'not_an_anchor');

#    If the command parameter is omitted, bind returns the command associated
#    with tagOrId and sequence or an error is raised if there is no such binding.
    &test_no_eval ("refering a non-existing bindind with bind",
		   $log_level, "bind", 'text', 'badseq');

#    $zinc->contour(tagOrId, operatorAndFlag, coordListOrTagOrId);
    # An error is generated if items are not of a correct type or if the
    # coordinate list is malformed.
    # tested in &test_contour_and_coords
    
#    If no items are named by tagOrId, an error is raised.
    &test_no_eval ("refering a non-existing item with hasanchors",
		   $log_level, "hasanchors", 'badtag');

#    If no items are named by tagOrId, an error is raised.
    &test_no_eval ("refering a non-existing item with hasfields",
		   $log_level, "hasfields", 'badtag');

    # If no items are named by tagOrId, an error is raised.
    &test_no_eval ("refering a non-existing item with hastag",
		   $log_level, "hastag", 'badtag', 'atag');

    # If field is given, it must be a valid field index for the item or
    # an error will be reported.
    &test_no_eval ("accessing a non existing track field",
		   $log_level, "itemcget", 'track', 111, -text);

    # If the attribute is not available for the field or item type,
    # an error is reported.
    &test_no_eval ("accessing a non existing curve attribute",
		   $log_level, "itemcget", 'curve', -bad_attribute);
    &test_no_eval ("accessing a non existing attribute of a track field",
		   $log_level, "itemcget", 'track', 1, -bad_attribute);

    # If field is given, it must be a valid field index for the item or an
    # error will be reported.
    &test_no_eval ("modifying a non existing track field",
		   $log_level, "itemconfigure", 'track', 111, -text => "foo");
    # If an attribute does not belong to the item or field, an error is reported:
    &test_no_eval ("modifying a non existing curve attribute",
		   $log_level, "itemconfigure", 'curve', -bad_attribute => "foo");
    &test_no_eval ("modifying a non existing attribute of a track field",
		   $log_level, "itemconfigure", 'track', 1, -bad_attribute => "foo");

#    If tagOrId doesn t name an item, an error is raised.
    &test_no_eval ("lowering  a non-existing item with lower",
		   $log_level, "lower", 'badtag', 'track');
#    If belowThis doesn t name an item, an error is raised.
    &test_no_eval ("lowering  an existing below an non-existing item with lower",
		   $log_level, "lower", 'track', 'badtag');

#    If no items are named by tagOrId, an error is raised.
    &test_no_eval ("refering a non-existing item with numparts",
		   $log_level, "numparts", 'badtag');

#    If tagOrId describes neither a named transform nor an item, an error is raised.
    &test_no_eval ("refering a non-existing item with rotate",
		   $log_level, "rotate", 'badtag', 180);
#    If tagOrId describes neither a named transform nor an item, an error is raised.
    &test_no_eval ("refering a non-existing item with scale",
		   $log_level, "scale", 'badtag', 2,2);
#    If tagOrId describes neither a named transform nor an item, an error is raised.
    &test_no_eval ("refering a non-existing item with translate",
		   $log_level, "translate", 'badtag', 200,200);

    # If the given name is not found among the named transforms, an error is raised.
    &test_no_eval ("refering a non-existing named transform item with tdelete",
		   $log_level, "tdelete", 'badNamedTransform');

# ->transform ??

    # If tagOrId describes neither a named transform nor an item, an error is raised.
    &test_no_eval ("refering a non-existing named transform or item with treset",
		   $log_level, "treset", 'badNamedTransform');

    # If tagOrId doesn t describe any item or if the transform named tName
    # doesn't exist, an error is raised.
    &test_eval ($log_level, "tsave", "text", "namedTransfrom");
    &test_no_eval ("refering a non-existing item with trestore",
		   $log_level, "trestore", 'badTag', 'namedTransform');
    &test_no_eval ("refering a non-existing named transform with trestore",
		   $log_level, "trestore", 'track', 'badNamedTransform');

    # If tagOrId doesn t describe any item, an error is raised.
    &test_no_eval ("refering a non-existing item with tsave",
		   $log_level, "tsave", 'badTag', 'otherNamedTransform');

    # If no items are named by tagOrId, an error is raised.
    &test_no_eval ("refering a non-existing item with type",
		   $log_level, "type", 'badTag');
    
    &log (0, "#----  End of test_errors  -----\n");
} # end of test_errors

sub creating_items {
    # first removing all remaining items
    foreach my $tag qw(group track waypoint tabular text icon reticle map
			rectangle arc curve triangles window) {
	$zinc->remove($tag);
    }
    # and then creating items
    $zinc->add('group', 1, -tags => ['group']);
    $zinc->add('track', 1, 5, -position => [100,200], -tags => ['track']);
    $zinc->add('waypoint', 1, 5, -position => [200,100], -tags => ['waypoint']);
    $zinc->add('tabular', 1, 5, -position => [100,20], -tags => ['tabular']);
    $zinc->add('text',1, -tags => ['text']);
    $zinc->add('icon', 1, -tags => ['icon']);
    $zinc->add('reticle', 1, -tags => ['reticle']);
    $zinc->add('map', 1, -tags => ['map']);
    $zinc->add('rectangle', 1, [400,400 , 450,220], -tags => ['rectangle']);
    $zinc->add('arc', 1, [10,10 , 50,50], -tags => ['arc']);
    $zinc->add('curve', 1, [30,0 , 150,10, 100,110, 10,100, 50,140], -tags => ['curve']);
    $zinc->add('triangles', 1, [200,200 , 300,200 , 300,300, 200,300],
		-colors => ["blue;50", "red;20", "green;80"], -tags => ['triangles']);
    $zinc->add('window', 1, -tags => ['window']);
    foreach my $tag qw(group track waypoint tabular text icon reticle map
			rectangle arc curve triangles window) {
#	my $contour = $zinc->contour($tag);
#	print "$tag := $contour\n";
    }
    
} # end creating_items


sub verify_coords_of_contour {
    my ($predicat, $id1, $id2, $contour) = @_;
    my @contour1 = $zinc->coords($id1,$contour);
    my @contour2 = $zinc->coords($id2,$contour);
#    print "contour1: ", &printableArray (@contour1), "\n";
#    print "contour2: ", &printableArray (@contour2), "\n";
    my $res = &nequal_cplx_arrays (\@contour1, \@contour2);
#    print "res=$res\n";
    if ($predicat eq 'eq') {
	if ($res) {
	    &log(-100, "coords of $id1($contour) and $id2($contour) are not equal:\n\t".
		 &printableArray(@contour1)."\n\t".&printableArray(@contour2)."\n");
	} else {
	    &log(1, "  # coords of $id1($contour) and $id2($contour) are OK ($predicat)\n");
	}
    } elsif ($predicat eq 'ne') {
	if (!$res)  {
	    &log(-10, "coords of $id1($contour) and $id2($contour) should not be equal\n");
	} else {
	    &log(1, "  # coords of $id1($contour) and $id2($contour) are OK ($predicat)\n");
	}
    } else {
	&log(-100, "unknown predicat: $predicat\n");
    }
} # end of verify_coords_of_contour;


sub verify_coords_of_contour_points {
    my ($predicat, $id1, $id2, $contour) = @_;
    my @contour1 = $zinc->coords($id1,$contour);

    my $nequal=0;
    for (my $i = 0; $i < $#contour1; $i++) {
	my @coords1 = $zinc->coords($id1,0,$i);
	my @coords2 = $zinc->coords($id2,0,$i);
	my $res = &equal_flat_arrays ( \@coords1, \@coords2 );
	if ($predicat eq 'eq') {
	    if (!$res) {
		&log(-100, "coords of $id1($contour,$i) and $id2($contour,$i) are not equal:\n\t$res");
	    }
	} elsif ($predicat eq 'ne') {
	    if (!$res) {
		$nequal=$res;
		last;
	    }
	} else {
	    &log(-100, "unknown predicat: $predicat\n");
	 }   
    }
    if ($predicat eq 'neq' and !$nequal)  {
	&log(-100, "coords of $id1($contour,i) and $id2($contour,i) should not be all equal\n");
    } else {
	&log(1, "  # coords of $id1($contour,i) and $id2($contour,i) are OK ($predicat)\n");
    }
} # end of verify_coords_of_contour_points;


sub parseTestsOpt {
    my ($opt) = @_;
    my @tests;
    if ($opt eq '') {
	print "Availables tests are:\n";
	while (@testsList) {
	    my $i = shift @testsList;
	    my $comment = shift @testsList;
	    print "\t$i => $comment\n";
	}
	exit;
    } elsif ( $opt eq 'all' ) { ## default!
	&log (0, "  # all tests will be passed through\n");
	@tests = sort keys %testsHash;
    } elsif ( $opt =~ /^\d+(,\d+)*$/ ) {
	@tests = split (/,/ , $opt);
	my $testnumb = (scalar @testsList) / 2;
	foreach my $test (@tests) {
	    die "tests num must not exceed $testnumb" if $test > $testnumb;
	}
	&log(0,  "Test to be done:\n");
	foreach my $test (@tests) {
	    &log(0,  "\t # $test => " . $testsHash{$test} . "\n");
	}
    } else {
	print "bad -tests value. Must be a list of integer separated by ,\n";
	&usage;
    }
    return @tests;
} # end of parseTestsOpt

# ---------- TEST ------------------
# the following code must be coherent with the tests list described
# on the very beginning of this file (see @testsList definition)

if ($tests{1}) {
    &test_contour_and_coords ();
}

if ($tests{2}) {
    &test_forbidden_operations_on_root_group ();
}

if ($tests{3}) {
    &test_errors; 
}

if ($tests{4}) {
    &test_bboxes;
}

if ($tests{5}) {
    &test_gradient_coding;
}

### we should also test multicontour curves
if ($tests{5}) {
#    &test_coords;
}

# #### &test_fonts;  ## and specially big fonts with render = 1;
# #### &test_path_tags;
# #### &test_illegal_tags;

# #### &test_illegal_call
# for example:
#  calling a methode for an non-existing item
#  getting coords, contours, fields, etc... of non-existing index
#
#  cloning, deleting topgroup
#

&log (0, "#---- End of test_method ----\n");

#MainLoop();

Added jni/tkzinc/Perl/t/test-no-crash.pl.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
#!/usr/bin/perl -w
# $Id$
# This non-regression / memory leak test has been developped by Christophe Mertz <mertz@intuilab.com>

use Tk;
use Tk::Zinc;
use Getopt::Long;
use TestLog;

use strict;

use constant ERROR => '--an error--';


# the following list be coherent with the treatments done in the TEST section.
my @testsList = (
		 1 => 'test_mapitems (quick)',
		 2 => 'test_every_field_attributes (long)',
		 3 => 'test_attributes (medium)',
		 4 => 'test_cloning (quick)',
		 5 => 'test_coords (quick)',
		 );
my %testsHash;
{ my @tests = @testsList;
  while (@tests) {
      my $num = shift (@tests);
      my $comment = shift (@tests);
      $testsHash{ $num } = $comment;
  }
}

# les variables positionnées en fonction des options de la ligne de commande
my $opt_log = 0;
my $opt_trace = "";
my $opt_render = -1;
my $opt_type = 0;
my $outfile;
my $opt_tests = "all";
my $opt_memoryleak = 0;

# on récupère les options
Getopt::Long::Configure('pass_through');
my $optstatus = GetOptions('log=i' => \$opt_log,
			   'out=s' => \$outfile,
			   'trace=s' => \$opt_trace,
			   'render:s' => \$opt_render,
			   'type=s' => \$opt_type,
			   'help' => \&usage,
			   'memoryleak' => \$opt_memoryleak,
			   'tests:s' => \$opt_tests,
			   );

# on teste la validité de l'option -render!
if ($opt_render eq '') {
    print "-render option have no value!\n";
    &usage;
}
$opt_render = 1 if $opt_render == -1;
unless ($opt_render==0 or $opt_render==1 or $opt_render==2) {
    print "-render option value must be 0, 1 or 2!\n";
    &usage;
}


$outfile = "no-crash-$Tk::Zinc::VERSION.log" if (!defined $outfile);

## in case of memoryleak test, logs are not written in a file
##  and logs are limited to high level logs on the standard output
##  (only those with a loglevel <= -1000 will be written on stdout)
my $nolog_file = 0;
if ($opt_memoryleak) {
  $opt_log = -1000;
  my $nolog_file = 1;
}




&openLog($outfile, $opt_log, $nolog_file);

sub usage {
    my ($text) = @_;
    print $text,"\n" if (defined $text);
    print "test-no-crash [options]\n";
    print "       A non-regression test suite for zinc.\n";
    print "       Some exhaustive test of zinc. Of course everything is not tested yet\n";
    print " options are:\n";
    print " -help           to print this short help\n";
    print " -log <n>        trace level, defaulted to 0; higher level trace more infos\n";
    print " -out filename   the log filename. defaulted to no-crash.log\n";
    print "      NB: the previous log file is always renamed with a .prev suffix\n";
    print " -memoryleak     to try to detect some memoryleak between first iteration of the test \n";
    print "                 and the following iteration. This test NEVER finish automatically\n";
    print "                 it is up to the tester to stop the memoryleak test after\n";
    print "                 a significative number of iterations\n";
    print " -render 0|1|2   to select the render option of zinc (defaulted to 1)\n";
    print " -trace <an_item_option>  to better trace usage of an option\n";
    print " -type <a_zinc_item_type> to limits tests to this item type.\n";
    print " -tests to get the list of available tests.\n";
    print " -tests i,j,k... to define the list of tests to pass.\n";
    exit;
}

my $mw = MainWindow->new();

&log (-1000, "#testing Zinc-perl Version=" . $Tk::Zinc::VERSION . " - ", $mw->zinc(), "\n");

## must be done after the LOG file is open:

my @tests = &parseTestsOpt($opt_tests);
my %tests;
foreach my $t (@tests) {$tests{$t} = $t }


# The explanation displayed when running this demo
my $label=$mw->Label(-text => "This is a non-regression test, testing that
zinc is not core-dumping! It can also be used for detecting memory leaks",
		     -justify => 'left')->pack(-padx => 10, -pady => 10);


# Creating the zinc widget
my $zinc = $mw->Zinc(-width => 500, -height => 500,
		     -trackmanagedhistorysize => 10,
		     -font => "10x20", # usually fonts are sets in resources
		                       # but for this example it is set in the code!
		     -borderwidth => 0, -relief => 'sunken',
		     -render => $opt_render,
		     )->pack;

&setZincLog($zinc);


my %itemtypes;
my @itemtypes = qw(arc tabular track waypoint
		   curve rectangle triangles
		   group icon map reticle text window
		   );

if ($opt_type) { @itemtypes = ($opt_type); }

foreach my $type (@itemtypes) { $itemtypes{$type}=1 }

#### some global variables needed as attributes values
my ($text1, $text2, $text3, $text4);
my ($image1, $image2, $image3, $image4);

&creating_items ("unused");
&verifying_item_completion;

sub creating_items {
    # first removing all remaining items
    foreach my $item (&test_eval (1, 'find', 'withtag', 'all')) {
	&test_eval (1, "remove", $item);
    }


    my $labelformat = "x82x60+0+0 x60a0^0^0 x32a0^0>1 a0a0>2>1 x32a0>3>1"; 
    # and then creating items
    &test_eval (1, "add", 'group', 1);
    &test_eval (1, "add", 'group', 1);
    &test_eval (1, "add", 'icon', 1);
    &test_eval (1, "add", 'map', 1);
    &test_eval (1, "add", 'map', 1);
    &test_eval (1, "add", 'reticle', 1);
    $text1 = &test_eval (1, "add", 'text', 1,  -position => [300,120], -text => "hello world1");
    $text2 = &test_eval (1, "add", 'text', 1,  -position => [350,170], -text => "hello world2");
    $text3 = &test_eval (1, "add", 'text', 1,  -position => [400,220], -text => "hello world3");
    &test_eval (1, "add", 'window', 1);
#    &test_eval (1, "add", 'track', 1, 5, -position => [100,200]);
    &test_eval (1, "add", 'track', 1, 5, -position => [100,200], -labelformat => $labelformat);
    &test_eval (1, "add", 'waypoint', 1, 5, -position => [200,100], -labelformat => $labelformat);
    &test_eval (1, "add", 'tabular', 1, 5, -position => [100,20], -labelformat => $labelformat);
    &test_eval (1, "add", 'group', 1);

    &test_eval (1, "mapinfo", 'mapinfo1', 'create');
    &test_eval (1, "mapinfo", 'mapinfo2', 'create');
    &test_eval (1, "mapinfo", 'mapinfo3', 'create');
    
#$zinc->itemconfigure ('tabular', -labelformat => "200x10");
#$zinc->update;



    &test_eval (1, "add", 'arc', 1, [10,10 , 50,50]);
    &test_eval (1, "add", 'curve', 1, [30,0 , 150,10, 100,110, 10,100, 50,140]);
    &test_eval (1, "add", 'rectangle', 1, [400,400 , 450,220]);
    &test_eval (1, "add", 'triangles', 1, [200,200 , 300,200 , 300,300, 200,300],
		-colors => ["blue;50", "red;20", "green;80"]);
    
    # images are initialised ONLY ONCE! (to avoid memoryleaks)
    $image1 = $zinc->Photo(-file => Tk::findINC("Tk/icon.gif") ) unless $image1;
    $image2 = $zinc->Photo(-file => Tk::findINC("Tk/Xcamel.gif") ) unless $image2;
    $image3 = $zinc->Photo(-file => Tk::findINC("Tk/tranicon.gif") ) unless $image3;
    $image4 = $zinc->Photo(-file => Tk::findINC("Tk/anim.gif") ) unless $image4;

    &creating_datas;  # some of the data are using items!
} # end creating_items

# verifies that we create an item of every existing type
sub verifying_item_completion {
    my @all_types = $zinc->add();  ## this use of add is not documented yet XXX!
    my @all_items = $zinc->find ('withtag', 'all');
    my %created_item_types;
    foreach my $item (@all_items) {
	$created_item_types{$zinc->type($item)} = 1;
    }
    foreach my $type (@all_types) {
	if (defined $created_item_types{$type}) {
	    delete $created_item_types{$type};
	}
	else {
	    &log(-100, "item type \"type\" which exist in Zinc is not tested!\n");
	}
    }
    foreach my $type (sort keys %created_item_types) {
	&log(-100, "This tested item type \"$type\" is supposed not to exist in Zinc!\n");
    }
}


my %options;
my %types;


foreach my $itemType (@itemtypes) {
    my ($anItem) = $zinc->find('withtype', $itemType);
    if (!defined $anItem) { &log (-10, "no item $itemType\n"); next;};
    my @options = $zinc->itemconfigure($anItem);
    foreach my $elem (@options) {
	my ($optionName, $optionType, $readOnly, $empty, $optionValue) = @$elem;
	$options{$itemType}{$optionName} = [$optionType, $readOnly, $empty, $optionValue];
	$types{$optionType} = 1;
    }
}

my %fieldOptions;

{
my ($aTrack) = $zinc->find('withtype', 'track');
if (!defined $aTrack) { &log (-10, "no item track\n") }
else {
    my @fieldOptions = $zinc->itemconfigure($aTrack, 0);
    for my $elem (@fieldOptions) {
	my ($optionName, $optionType, $readOnly, $empty, $optionValue) = @$elem;
	$fieldOptions{$optionName} = [$optionType, $readOnly, $empty, $optionValue];
	$types{$optionType} = 1;
    }
}
}

foreach my $type (sort keys %types) {
#    print "$type\n";
}

# a hash giving samples of valid data for attributes types
my %typesValues;

# the following hash associated to types valid value that should be all different from
# default value and from value initiated when creating items (see up...)
my %typesNonStandardValues;

# a hash giving samples of NOT valid data for attributes types
my %typesIllegalValues;

sub creating_datas {
  return if defined $typesValues{'alignment'};
  %typesValues =
	('alignment' => ['left', 'right', 'center'],
	 'alpha' => [0, 50, 100, 23],
	 'anchor' => ['n', 's', 'e', 'w', 'nw', 'ne', 'sw', 'se', 'center'],
	 'angle' => [0, 90, 180, 270, 360, 12, 93, 178, 272, 359],
	 'autoalignment' => ['lll', 'llr', 'llc', 'lrl', 'lrr', 'lrc', 'lcl', 'lcr', 'lcc',
			     'rll', 'rlr', 'rlc', 'rrl', 'rrr', 'rrc', 'rcl', 'rcr', 'rcc',
			     'cll', 'clr', 'clc', 'crl', 'crr', 'crc', 'ccl', 'ccr', 'ccc',
			     '-',],
	 'boolean' => [0..1],
	 'bitmap' => ['AlphaStipple0', 'AlphaStipple3', 'AlphaStipple14', 'AlphaStipple11', 'AlphaStipple7'], ####?!
	 'bitmaplist' => [['AlphaStipple0', 'AlphaStipple3', 'AlphaStipple14', 'AlphaStipple11', 'AlphaStipple7'], ['AlphaStipple0']], ##TBC
	 'capstyle' => ['butt', 'projecting', 'round'],
	 'gradient' => ['green', 'LemonChiffon', '#c84', '#4488cc', '#888ccc444', 'red'], ## TBC
	 'gradientlist' => [['green'], ['LemonChiffon'], ['#c84'], ['#4488cc'], ['#888ccc444'],
			    ['red', 'green'], ['red', 'green', 'blue'],
			    ['red;50', 'green;50', 'blue;50'],
			    ['blue;0', 'green;50', 'red;90'],
			    ], ## TBC
	 'dimension' => [0..5, 10, 50, 100, 0.0, 5.5, 100.5, 4.5],  ## and floats ?!
	 'edgelist' => ['left', 'right', 'top', 'bottom', 'contour', 'oblique', 'counteroblique'], ## +combinations!
         'filerule', => ['odd', 'negative','positive', 'abs_ge_eq2'],
	 'font' => ['10x20', '6x10', '6x12', '6x13'],
	 'image' => [$image1, $image2, $image3], ## TBC
	 'integer' => [-10000, -100, -1, 0, 1, 10, 10000], ## pour quoi?
	 'item' => [$text1, $text2],
	 'joinstyle' => ['bevel', 'miter', 'round'],
	 'labelformat' => ["200x10", ## BUG BUG
#		       "200x100 x100x20+0+0 x100x20+0+20 x200x40+100+20"
			   ],
	 'leaderanchors' => ["%10x30", "|0|0", "%40x20", "|1|1", "|100|100", "%67x21" ], ## TBC! non exchaustif!! BUG non conforme à la doc
	 # illegal et fait planter: "%50" 
	 'lineend' => [ [10,10,10], [10,100,10], [100,10,10], [10,10,100], [100,10,100] ],
	 'lineshape' => ['straight', 'rightlightning', 'leftlightning', 'rightcorner', 'leftcorner', 'doublerightcorner', 'doubleleftcorner'],
	 'linestyle' => ['dotted', 'simple', 'dashed', 'mixed', 'dotted'],
	 'mapinfo' => ['mapinfo1','mapinfo2','mapinfo3'], ## TBC
#     'number' => [2.3, 1.0, 5.6, 2.1],
	 'point' => [ [0,0] , [10,10], [20,20], [30,30], [20,20], [0,0] , [10,10] ],
	 'priority' => [ 1, 10, 50, 1000, 10000 ],  # positif ou nul
	 'relief' => ['flat', 'groove', 'raised', 'ridge', 'sunken',
		      'roundraised', 'roundsunken', 'roundgroove',
		      'roundridge', 'sunkenrule', 'raisedrule'],
	 'string' => ['teststring', 'short', 'veryverylongstring'],
	 'taglist' => [ [1], [1..2], ['a','b'], ['tag1','tag2','tag3']],
	 'unsignedint' => [ 0..5 , 10, 20, 30, 100 ],
	 'window' => [], ## TBC
	 );
    
# the following valid value associated to types should be all different from
# default value and from value initiated when creating items (see up...)
    %typesNonStandardValues = 
	('alignment' => 'right',
	 'alpha' => 50,
	 'anchor' => 'w',
	 'angle' => 45,
	 'autoalignment' => 'llc',
	 'bitmap' => 'AlphaStipple14',
	 'bitmaplist' => ['AlphaStipple0', 'AlphaStipple3', 'AlphaStipple14', 'AlphaStipple11', 'AlphaStipple7'],
	 'capstyle' => 'butt',
	 'gradient' => 'LemonChiffon',
	 'gradientlist' => ['red;50', 'green;50', 'blue;50'],
	 'dimension' => 45,
	 'edgelist' => 'contour',
	 'font' => '6x10',
         'fillrule' => 'nonzero',
	 'image' => $image4,
	 'integer' => 7,
	 'item' => $text3,
	 'joinstyle' => 'miter',
	 'labelformat' => "200x30", ## BUG BUG
	 'leaderanchors' => "%10x45", ## BUG BUG
	 'lineend' => [13,7,20],
	 'lineshape' => 'rightlightning',
	 'linestyle' => 'dotted',
	 'mapinfo' => 'mapinfo2', ## TBC
	 'number' => 7.6,
	 'point' => [100,100],
	 'priority' => 50,
	 'relief' => 'groove',
	 'string' => 'notsoshort',
	 'taglist' => ['tag1','tag11','tag111'],
	 'unsignedint' => 7, # 22,    # 22 is to high for -visiblehistorysize and 5 is, the default value for reticle -period
	 'window' => undef, ### TBC
	 );
    
    %typesIllegalValues =
	('alpha' => [0..100],
	 'anchor' => ['n', 's', 'e', 'w'], ##TBC
	 'angle' => [0..360],
	 'boolean' => [0..1],
	 'capstyle' => [],
	 'dimension' => [0..100],
	 'font' => ['10x20', '6x10', '6x12', '6x13'],
	 'leaderanchors' => ["%50"  ], ## TBC! non exchaustif!! BUG non
	 'relief' => ['flat', 'groove', 'raised', 'ridge', 'sunken',
		      'roundraised', 'roundsunken', 'roundgroove',
		      'roundridge', 'sunkenrule', 'raisedrule'],
	 );
}

$mw->Button(-text => "Exit",
	    -command => sub { exit },
	    )->pack(-pady => 4);

sub test_attributes {
    &log (-1000, "#---- Start of test_attributes ----\n");
    foreach my $type (@itemtypes) {
	my @items = $zinc->find('withtype', $type);
	&log (0, "#--------- Testing ", (1+$#items), " ",$type," attributes ----------------\n");
	if ($#items == -1) {
	    &log (-100, "No such item: $type\n");
	    next;
	}
        &log(0,"no such type '$type'\n"), next unless defined $options{$type};
#        print $options{$type}, "\t\t", %{$options{$type}}, "\n";
	my %theoptions = %{$options{$type}};
	foreach my $item (@items) {
	    ## il faudrait tester les options selon un ordre défini à l'avance
	    ## en passant par plusieurs occurences pour les options et en forçant
	    ## certaines valeurs, par exemple les valeurs booléennees... (visible/sensible/filled)
	    my @boolean_attributes;
	    my %boolean_attributes;
	    foreach my $option (sort keys %theoptions) {
		my ($optionType, $readOnly, $empty, $optionValue) = @{$theoptions{$option}};
		if ($optionType eq 'boolean') {
		    next if $option eq -composerotation;
		    next if $option eq -composescale;
		    next if $option =~ /-\w+sensitive/ ;   # to get rid of many track options!
		    next if $option =~ /-filled\w+/ ;      # to get rid of many track options!
		    next if $option =~ /-speed\w+/ ;      # to get rid of many track options!
		    next if $option =~ /-\w+history/ ;      # to get rid of many track options!
		    push @boolean_attributes, $option;
		    $boolean_attributes{$option}=1;
		}
	    }
	    &log (0, "# $type (id $item) : ", ((2**(1+$#boolean_attributes)) , " Combinations (", join (', ' , @boolean_attributes),")\n"));
	    foreach my $i (0 .. (2**(1+$#boolean_attributes) -1) ) {
		my $format = "%0" . ($#{boolean_attributes} +1) . "b";
		my $binary = sprintf ($format,$i);
		&log (0, "# $i/", (2**(1+$#boolean_attributes)), "  $binary\n");
		my @binary = split (//,$binary);
		foreach my $j (0 .. $#boolean_attributes) {
		    &test_eval (0, "itemconfigure", $item, $boolean_attributes[$j] => $binary[$j] );
#		    &log (0, "setting $type ($item) ", $boolean_attributes[$j], " to ", $binary[$j], "\n");
		}
		foreach my $option (sort keys %theoptions) {
		    next if ($option eq -numfields); # BUG? makes the appli stop
		    next if ($option eq "-clip" and $type = "group"); # BUG? This test cannot be random clipping item must belong to the group
		    next if ($boolean_attributes{$option}); # skipping boolean attributes which are exhaustively tested

		    my ($optionType, $readOnly, $empty, $optionValue) = @{$theoptions{$option}};
		    my $typeValues = $typesValues{$optionType};
		    if (!defined $typeValues) {&log (-100, "No values for type $optionType (option $option)\n");next;}
		    my @values = @{$typeValues};

		    if (!@values) {&log (-100, "No values for type $optionType (option $option)\n");next;}
			

		    my $valueRef = ref ($values[0]);
		    my $previous_val;
		    my @previous_val;

		    if ($valueRef eq '') {
			$previous_val = $zinc->itemcget($item, $option);
		    }
		    else {
			@previous_val = $zinc->itemcget($item, $option);
		    }
		    &log (1, "#**  itemconfigure of $item ($type), $option => ",&printableList (@values),"\n");
		    my $log_lev = ($opt_trace eq $option || $opt_trace eq $optionType ) ? 0 : 2 ;
		    foreach my $value (@values) {
			&test_eval ($log_lev, "itemconfigure", $item, $option => $value);
			$zinc->update;
			$zinc->after(10);
		    }
		    
		    if ($valueRef eq '') {
			&test_eval ($log_lev, "itemconfigure", $item, $option => $previous_val);
		    }
		    else {
			&test_eval ($log_lev, "itemconfigure", $item, $option => \@previous_val);
		    }
		    
		}
	    }
	}
    }
    &log (0, "#---- End of test_attributes ----\n");
} # end test_attributes


# test2: configurer les fields des track / waypoint / tabular
#        jouer avec les labelformats

# test3: tester toutes les fonctions aléatoirement selon les signatures


# test4: tester qu'en clonant on obtient bien une copie de tous les attributs

sub test_cloning {
    &log (-1000, "#---- Start of test_cloning ----\n");
    &creating_items;
    foreach my $type (@itemtypes) {
	my ($item) = $zinc->find('withtype', $type);
	&log (0, "#--------- Cloning and testing item ",$type," $item ----------------\n");
	if (!defined $item) { &log (-10, "No such item: $type\n"); next;};
	my $clone = &test_eval(1, "clone", $item);

	&log (0, "#---- Modifying the clone $clone\n");
	&test_a_clone ($type, $item, $clone);
	&test_enclosed_overlapping_closest($type, 'original', $item, $zinc->bbox ($item));
	&test_enclosed_overlapping_closest($type, 'clone', $clone, $zinc->bbox ($clone));
	&log (0, "#---- Modifying the original\n");
	&test_a_clone ($type, $clone, $item);
	&test_enclosed_overlapping_closest($type, 'original', $item, $zinc->bbox ($item));
	&test_enclosed_overlapping_closest($type, 'clone', $clone, $zinc->bbox ($clone));
	&log (0, "#---- Deleting the original\n");
	&test_eval (1, "remove", $item);
	&test_every_attributes_once($type,$clone);
	&log (0, "#---- Deleting the clone\n");
	&test_eval (1, "remove", $clone);
    }
    # tester le find enclosed / overlapping avec un rectangle un peu plus grand que la bbox
    # tester le closest avec le centre de la bbox
    
    # faire la même chose que juste avant, mais en interchangeant clone et original
    # tester le find enclosed / overlapping avec un rectangle un peu plus grand que la bbox
    # tester le closest avec le centre de la bbox
    
    # supprimer l'item original

    # tester le find enclosed / overlapping avec un rectangle un peu plus grand que la bbox
    # tester le closest avec le centre de la bbox

    # modifier tous les attributs du clone
    # supprimer le clone

    # tester le find enclosed / overlapping avec un rectangle un peu plus grand que la bbox
    # tester le closest avec le centre de la bbox
     
    &log (0, "#---- End of test_cloning ----\n");
} # end test_cloning

## teste le find enclosed / overlapping avec un rectangle un peu plus grand
#  que la bbox donnée en paramètre.
#  si $item est différent de '', vérifie que l'item est enclosed/overlapping 
## Vérifie aussi le fonctionnement ud closest pour le centre de la bbox
sub test_enclosed_overlapping_closest {
    my ($type, $clone_or_original, $item, @bbox) = @_;
    if ($#bbox == -1) {
	&log(-100, "Undef bbox of a $type ($clone_or_original)\n");
    }
    else {
	@bbox = ( $bbox[0]-10, $bbox[1]-10, $bbox[2]+10, $bbox[3]+10 );
	my @items = &test_eval (1, "find", 'enclosed', @bbox);
	goto TESTOVERLAPPING if ($item eq '');
	foreach my $i (@items) {
	    goto TESTOVERLAPPING if ($i eq $item); # the item is included!
	}
	&log(-100, "The $type ($clone_or_original) is not enclosed in its bbox!\n");
  TESTOVERLAPPING:
#	@items = $zinc->find ('overlapping', @bbox);
	@items = &test_eval (1, "find", 'overlapping', @bbox);
	goto TESTCLOSEST if ($item eq '');
	foreach my $i (@items) {
	    goto TESTCLOSEST if ($i eq $item);
	}
	&log(-100, "The $type ($clone_or_original) is not overlapping its bbox!\n");
  TESTCLOSEST:
	my $x = ($bbox[0] + $bbox[2] )/2;
	my $y = ($bbox[1] + $bbox[3] )/2;
#	my $closest = $zinc->find ('closest', $x,$y);
	my $closest = &test_eval (1, "find", 'closest', $x,$y);
    }
} # end test_enclosed_overlapping_closest

sub test_a_clone {
    my ($type, $original, $clone) = @_;
    my %theoptions = %{$options{$type}};
    foreach my $option (sort keys %theoptions) {
	next if ($option eq -numfields); # BUG? makes the appli stop
	next if ($option eq "-clip" and $type = "group"); # BUG? This test cannot be random. Clipping item must belong to the group
        next if ($option eq '-connecteditem'); ## XXX this test should be corrected implemented,
	my ($optionType, $readOnly, $empty, $optionValue) = @{$theoptions{$option}};
	my $value = $typesNonStandardValues{$optionType};
	if ($optionType ne 'boolean' && !defined $value) {
	    &log (-100, "No value for type $optionType (option $option)\n");
	    next;
	}
	
	my $valueRef = ref ($value);
	my $previous_val;
	my @previous_val;
	
	# memoryzing previous value of the clone 
	if ($valueRef eq '') {
	    $previous_val = &test_eval (2, "itemcget", $clone, $option);
	}
	else {
	    @previous_val = &test_eval (2, "itemcget", $clone, $option);
	}

	# in the case of boolean, we must always take the not value:
	if ($optionType eq 'boolean') { $value = !$previous_val }
	
	my $log_lev = ($opt_trace eq $option || $opt_trace eq $optionType) ? 0 : 2 ;
	&test_eval ($log_lev, "itemconfigure", $clone, $option => $value);
	$zinc->update;

	if ($valueRef eq 'ARRAY') {  # the value is a list
	    my @original_value = &test_eval (2, "itemcget", $original, $option);
	    my @clone_value = &test_eval (1, "itemcget", $clone, $option);
	    if ( &equal_flat_arrays (\@original_value, \@clone_value) ) {
		&log (-100, "Modified cloned $type gets the same value for $option (type $optionType) ". &printableArray(@original_value) . "\n");
	    }
	}
	else {  # the value is either a scalar or a class instance
	    my $original_value = &test_eval (2, "itemcget", $original, $option);
	    my $clone_value = &test_eval (2, "itemcget", $clone, $option);
	    if (defined $original_value && $original_value eq $clone_value) {
#		print "ORIGIN = ",$original_value, " $original_value CLONE = ",$clone_value,"\n";
		&log (-100, "Modified cloned $type gets the same value for $option (type $optionType) " .
		      "(original=cloned: " . &printableItem($original_value) .
		      "?=" . &printableItem($previous_val) .
		      " :previous)\n");
	    }
	}
	
	# setting back the previous value
	if ($valueRef eq '') {
	    &test_eval (1, "itemconfigure", $clone, $option => $previous_val);
	}
	else {
	    &test_eval (1, "itemconfigure", $clone, $option => \@previous_val);
	}
	
    }
} # end test_a_clone

sub test_every_attributes_once {
    my ($type, $item) = @_;
    my %theoptions = %{$options{$type}};
    foreach my $option (sort keys %theoptions) {
	next if ($option eq -numfields); # BUG? makes the appli stop
	next if ($option eq "-clip" and $type = "group"); # BUG? This test cannot be random. Clipping item must belong to the group
        next if ($option eq '-connecteditem'); ## XXX this test should be corrected implemented,
	my ($optionType, $readOnly, $empty, $optionValue) = @{$theoptions{$option}};
	my $value = $typesNonStandardValues{$optionType};
	if ($optionType ne 'boolean' && !defined $value) {
	    &log (-100, "No value for type $optionType (option $option)\n");
	    next;
	}
	# in the case of boolean, we must always take the not value:
	if ($optionType eq 'boolean') { $value = !$zinc->itemcget($item, $option) }
	
	my $log_lev = ($opt_trace eq $option || $opt_trace eq $optionType) ? 0 : 2 ;
	&test_eval ($log_lev, "itemconfigure", $item, $option => $value);
	$zinc->update;
    }
} # end test_every_attributes_once


sub test_every_field_attributes {
    &log (-1000, "#---- Start of test_every_field_attributes ----\n");
    foreach my $type qw(waypoint track tabular) {
	next unless $itemtypes{$type};
	my %theoptions = %fieldOptions;
	my @items = $zinc->find('withtype', $type);
	&log (0, "#--------- Testing field attributes of ", (1+$#items), " ",$type,"(s) ----------------\n");
	if ($#items == -1) {
	    &log (-100, "No such item: $type\n");
	    next;
	}
	foreach my $item (@items) {
	    ## il faudrait tester les options selon un ordre défini à l'avance
	    ## en passant par plusieurs occurences pour les options et en forçant
	    ## certaines valeurs, par exemple les valeurs booléennees... (visible/sensible/filled)
	    my @boolean_attributes;
	    my %boolean_attributes;
	    foreach my $option (sort keys %theoptions) {
		my ($optionType, $readOnly, $empty, $optionValue) = @{$theoptions{$option}};
		if ($optionType eq 'boolean') {
#		    next if $option =~ /-\w+sensitive/ ;   # to get rid of many track options!
#		    next if $option =~ /-filled\w+/ ;      # to get rid of many track options!
#		    next if $option =~ /-speed\w+/ ;      # to get rid of many track options!
#		    next if $option =~ /-\w+history/ ;      # to get rid of many track options!
		    push @boolean_attributes, $option;
		    $boolean_attributes{$option}=1;
		}
	    }
	    &log (0, "# $type (id $item) : ", ((2**(1+$#boolean_attributes)) , " Combinations (", join (', ' , @boolean_attributes),")\n"));
	    foreach my $i (0 .. (2**(1+$#boolean_attributes) -1) ) {
		my $format = "%0" . ($#{boolean_attributes} +1) . "b";
		my $binary = sprintf ($format,$i);
		&log (0, "# $i/", (2**(1+$#boolean_attributes)), "  $binary\n");
		my @binary = split (//,$binary);
		foreach my $j (0 .. $#boolean_attributes) {
		    &log (0, "# setting $type ($item) field 0..",$zinc->itemcget($item, -numfields)-1,  " ", $boolean_attributes[$j], " to ", $binary[$j], "\n");
		    foreach my $field (0 .. $zinc->itemcget($item, -numfields)-1 ) {
			&test_eval (1, "itemconfigure", $item, $field, $boolean_attributes[$j] => $binary[$j] );
		    }
		}
		foreach my $field (0 .. $zinc->itemcget($item, -numfields)-1 ) {
		    foreach my $option (sort keys %theoptions) {
			next if ($boolean_attributes{$option}); # skipping boolean attributes which are exhaustively tested
			
			my ($optionType, $readOnly, $empty, $optionValue) = @{$theoptions{$option}};

			my $typeValues = $typesValues{$optionType};
			if (!defined $typeValues) {&log (-100, "No values for type $optionType (option $option)\n");next;}
			my @values = @{$typeValues};
			
			if (!@values) {&log (-100, "No values for type $optionType (option $option)\n");next;}
			

			my $valueRef = ref ($values[0]);
			my $previous_val;
			my @previous_val;
			
			if ($valueRef eq '') {
			    $previous_val = &test_eval (1, "itemcget", $item, $field, $option);
			}
			else {
			    @previous_val = &test_eval (1, "itemcget", $item, $field, $option);
			}
			&log (1, "#**  itemconfigure ($item ($type), $field, $option => ",&printableList (@values),"\n");
			foreach my $value (@values) {
			    my $log_lev = ($opt_trace eq $option || $opt_trace eq $optionType) ? 0 : 2 ;
			    &test_eval ($log_lev, "itemconfigure", $item, $field, $option => $value);
			    $zinc->update;
			    $zinc->after(10);
			}
			
			if ($valueRef ne 'ARRAY') {
			    &test_eval (1, "itemconfigure", $item, $field, $option => $previous_val);
			}
			else {
			    &test_eval (1, "itemconfigure", $item, $field, $option => \@previous_val);
			}
		    
		    }}
	    }
	}
    }
    &log (0, "#---- End of test_every_field_attributes ----\n");
} # end test_every_field_attributes


sub createMapInfo {
    my ($name, $N,$deltaN, $radius, $centerX,$centerY) = @_;
    &test_eval (1, "mapinfo", $name, 'create'); 

    my @lineTypes=(qw/simple dashed dotted mixed marked/), 
    my $deltaAngle=6.283/$N;
    for (my $i = 0; $i < $N; $i++) {
	my $x1 = $centerX + $radius * sin($i * $deltaAngle); 
	my $y1 = $centerY + $radius * cos($i * $deltaAngle);
	my $x2 = $centerX+ $radius * sin( ($i + $deltaN) * $deltaAngle); 
	my $y2 = $centerY + $radius * cos( ($i + $deltaN)* $deltaAngle);
	my $linetype = $lineTypes[$i%5];
	$mw->mapinfo($name, 'add', 'line', $linetype, 1+$i%3, +$x1,$y1,$x2,$y2);
    }
} # end of createMapInfo

sub test_mapitems {
    my @mapinfoNames = @_;
    &log (-1000, "#---- Start of test_mapitems ----\n");
    my @maps = $zinc->find('withtype', 'map');
    my $counter=0;
    foreach my $map (@maps) {
	&test_eval (1, "itemconfigure", $map, -mapinfo => $mapinfoNames[$counter]);
	if ($counter == $#maps) { $counter=0 }
	$counter++;
    }
    &log (0, "#---- End of test_mapitems ----\n");
} # end test_mapitems

## testing the returned value of coords
sub test_coords {
    &log (-1000, "#---- Start of test_coords ----\n");
    foreach my $it ($zinc->find('withtag','*')) {
	$zinc->remove($it);
    }
    ## creationg again items
    &creating_items;
    foreach my $type ($zinc->add()) {
	next if $type eq 'map'; ## map item does not support coords method
	my ($it) = $zinc->find('withtype',$type);
	my @coordsAll= &test_eval (1, "coords", $it);
	my $coordsAll = &printableArray(@coordsAll);
	&log (1, "=> $coordsAll\n");
	my @coordsContour= &test_eval (1, "coords", $it,0); # all items have 1 contour
	my $coordsContour = &printableArray(@coordsContour);
	&log (1,"=> $coordsContour\n");
	my @coordsPoint= &test_eval (1, "coords", $it,0,0); # all items have 1 contour with at least one point
	my $coordsPoint = &printableArray(@coordsPoint);
	&log (1,"=> $coordsPoint\n");
    }
    &log (0, "#---- End of test_coords ----\n");
}
    
sub parseTestsOpt {
    my ($opt) = @_;
    my @tests;
    if ($opt eq '') {
	print "Availables tests are:\n";
	while (@testsList) {
	    my $i = shift @testsList;
	    my $comment = shift @testsList;
	    print "\t$i => $comment\n";
	}
	exit;
    } elsif ( $opt eq 'all' ) { ## default!
	&log (0, "# all tests will be passed through\n");
	@tests = sort keys %testsHash;
    } elsif ( $opt =~ /^\d+(,\d+)*$/ ) {
	@tests = split (/,/ , $opt);
	my $testnumb = (scalar @testsList) / 2;
	foreach my $test (@tests) {
	    die "tests num must not exceed $testnumb" if $test > $testnumb;
	}
	&log(0,  "# Tests to be done:\n");
	foreach my $test (@tests) {
	    &log(0,  "\t# $test => " . $testsHash{$test} . "\n");
	}
    } else {
	print "bad -tests value. Must be a list of integer separated by ,\n";
	&usage;
    }
    return @tests;
} # end of parseTestsOpt



# ---------- TEST ------------------
# the following code must be coherent with the tests list described
# on the very beginning of this file (see @testsList definition)

&createMapInfo ('firstmap', 50, 20, 200, 200, 300);
&createMapInfo ('secondmap', 12, 3, 200, 300, 50);

sub theTest {
  if ($tests{1}) {
    &test_mapitems ('firstmap', 'secondmap'); # should be done before really testing map items attributes
  }
  # #### &test_labelcontent; # should be done before really testing track/waypoint/tabular items attributes
  
  if ($tests{2}) {
    &test_every_field_attributes;
  }
  
  if ($tests{3}) {
    &test_attributes; # on peut configurer tous les attributs
  }

  ### we SHOULD test that setting a bad type value ofr an option does not core dump zinc!

  if ($tests{4}) {
    &test_cloning; # we test that cloning items and modifiyng/removing them does not core dump
  }

  ### we should also test multicontour curves
  if ($tests{5}) {
    &test_coords;
  }

# #### &test_fonts;  ## and specially big fonts with render = 1;
# #### &test_path_tags;
# #### &test_illegal_tags;

# #### &test_illegal_call
# for example:
#  calling a method for an non-existing item
#  getting coords, contours, fields, etc... of non-existing index
#
#  cloning, deleting topgroup
#
}

sub getMemoryUsage {
  open (PROC, "/proc/$$/status");
  my ($totalMemory,$dataMemory);
  while (<PROC>) {
    if (/^VmSize:\s+(\d+)/) {
      $totalMemory = $1;
    }
    elsif (/^VmData:\s+(\d+)/) {
      $dataMemory = $1;
      last;
    }
  }
  close PROC;
  return ($totalMemory,$dataMemory);
}



if ($opt_memoryleak) {
  my $iteration = 0;
  while (1) {
    my ($total,$data) = &getMemoryUsage;
    ## get here the current memory state
    &log(-1000, "#---- MemoryState iteration=$iteration totalMemory=$total  dataMemory=$data ----\n");
    $iteration++;
    &theTest;
  }
} else {
  &theTest;
}


&log (0, "#---- End of test_no_crash ----\n");

MainLoop();

Added jni/tkzinc/Perl/t/testdoc.pl.





































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#!/usr/bin/perl -w
# $Id$
# This script verifies the conformity of the reference manual with
# some types informations available inside ZincTk
# It has been developped by C. Mertz <mertz@cena.fr>

# limitations: this script makes some very strong assumptions
#              on the latex Zinc reference manual formating!
#              However if the formating changes, it should be
#              simple to modify the &scanDoc function!
#
# What this script currently does:
#  - verifies that all Zinc options are documented
#  - verifies that all items attributes (and their type) are documented
#  - verifies that all field attributes options (and their type) are documented
#  - verifies that all documented options and attributes really exists
#  - verifies that all documented types are refered to in the doc
# It also checks that options, attributes and types are documented in alphabetical order
# It is heavily based on meta information available directly from zinc
#
# How to use it:
#   testdoc.pl path_to_refman.tex

use Tk;
use Tk::Zinc;

use strict;

print "------- Testing conformity of refman.tex and meta-information from zinc Version $Tk::Zinc::VERSION\n";

my $mw = MainWindow->new();

# Creating the zinc widget
# NB: this widget will not be displayed! It is only used for creating items
# and getting some internal information about attributes/options and types.

my $zinc = $mw->Zinc(-width => 1, -height => 1,);

# Creating an instance of every item type
my %itemtypes;

# These Items have fields! So the number of fields must be given at creation time
foreach my $type qw(tabular track waypoint) {
    $itemtypes{$type} = $zinc->add($type, 1, 1);
}

# These items needs no specific initial values
foreach my $type qw(group icon map reticle text window) {
    $itemtypes{$type} = $zinc->add($type, 1);
}

# These items needs some coordinates at creation time
# However curves usually needs more than 2 points.
foreach my $type qw(arc curve rectangle) {
    $itemtypes{$type} = $zinc->add($type, 1, [0,0 , 1,1]);
}
# Triangles item needs at least 3 points for the coordinates 
foreach my $type qw(triangles) {
    $itemtypes{$type} = $zinc->add($type, 1, [0,0 , 1,1 , 2,2]);
}


my %zinc2doc;  # a hash recording every discrepency between attribute/option
               # type between the doc and TkZinc
my %documentedOptions;
my %itemAttributeDoc;
my %documentedTypes;
my %usedTypes; # hash recording all refered types in the doc

die "missing refman.tex path_name as unique argument to this script" unless defined $ARGV[0];


&scanDoc ($ARGV[0]);

sub scanDoc {
    my ($filename) = @_;
    open (DOC, $filename) or die "unable to open " . $filename . "\n";
    my $current_item = 0;
    my $prev_attribute = 0;
    my $prev_type = 0;

    while (<DOC>) {
	if ( /^\\attribute\{(\w+)\}\{(\w+)\}\{(\w+)\}/ ) {
	    my $item = $1;
	    my $attribute = $2;
	    my $type = $3;
	    $itemAttributeDoc{$item}{-$attribute} = $type;
	    if ($item eq $current_item) {
		if ($attribute lt $prev_attribute) {
		    print "W: attributes $prev_attribute and $attribute are not in alphabetical order for $item\n";
		}
	    }
	    else {
		$current_item = $item;
		$prev_attribute = $attribute;
	    }
	}
	elsif ( /^\\option\{(\w+)\}\{(\w+)\}\{(\w+)\}/ ) {
	    my $optionName = $1;
	    my $databaseName = $2;
	    my $databaseClass = $3;
	    $documentedOptions{-$optionName} = $databaseClass;
	}
	elsif ( /^\\attrtype\{(\w+)\}/ ) {
	    my $type = $1;
	    $documentedTypes{$type} = $type;
	    if ($type lt $prev_type) {
		print "W: type $prev_type and $type are not in alphabetical order\n";
	    }
	    $prev_type = $type;
	}
    }
}

sub testAllOptions {
    my @options = $zinc->configure();
    my %options;
    # we use this hashtable to check that all documented options
    # are matching all existing options in TkZinc
    
    for my $elem (@options) {
	my ($optionName, $optionDatabaseName, $optionClass, $default, $optionValue) = @$elem;
	$options{$optionName} = [$optionClass, $default, "", $optionValue];
    }

    foreach my $optionName (sort keys %options) {
	my ($optionType, $readOnly, $empty, $optionValue) = @{$options{$optionName}};
	# $empty is for provision by Zinc

	if (!defined $documentedOptions{$optionName}) {
	    print "E: $optionName ($optionType) of Zinc IS NOT DOCUMENTED!\n";
	    $options{$optionName} = undef;
	    next;
	}
	if ($documentedOptions{$optionName} ne $optionType) {
	    print "W: $optionName has type $optionType inside ZincTk and type $documentedOptions{$optionName} inside Doc\n";
	    $zinc2doc{$optionType}=$documentedOptions{$optionName};
	}
#	$attributes{$attributeName} = undef;
	$documentedOptions{$optionName} = undef;
    }
    
    foreach my $unexistingDocOpt (sort keys %documentedOptions) {
	if (defined $documentedOptions{$unexistingDocOpt}) {
	    print "E: The Documented Option \"$unexistingDocOpt\" DOES NOT EXIST!\n";
	}
    }
}

sub testAllAttributes {
    my ($item) = @_;

    my %documentedAttributes = %{$itemAttributeDoc{$item}}; 
    my @attributes = $zinc->itemconfigure($itemtypes{$item});

    my %attributes;
    # we use this hashtable to check that all documented attributes
    # are matching all existing attributes in TkZinc

    # verifying that all referenced types are defined
    # and storing used types
    foreach my $attribute (sort keys %documentedAttributes) {
	my $type = $documentedAttributes{$attribute};
	$usedTypes{$type} = 1;
	print "E: type $type ($attribute of $item) is not documented\n" unless $documentedTypes{$type};
    }
    
    foreach my $elem (@attributes) {
	my ($attributeName, $attributeType, $readOnly, $empty, $attributeValue) = @$elem;
	$attributes{$attributeName} = [$attributeType, $readOnly, $empty, $attributeValue];
    }

    foreach my $attributeName (keys %attributes) {
	my ($attributeType, $readOnly, $empty, $attributeValue) = @{$attributes{$attributeName}};
	# $empty is for provision by Zinc
	
	if (!defined $documentedAttributes{$attributeName}) {
	    print "E: $attributeName ($attributeType) of item $item IS NOT DOCUMENTED!\n";
	    $attributes{$attributeName} = undef;
	    next;
	}

	if ($documentedAttributes{$attributeName} ne $attributeType) {
	    print "W: $attributeName has type $attributeType inside ZincTk and type $documentedAttributes{$attributeName} inside Doc\n";
	    $zinc2doc{$attributeType}=$documentedAttributes{$attributeName};
	}
#	$attributes{$attributeName} = undef;
	$documentedAttributes{$attributeName} = undef;
    }
    
    foreach my $unexistingDocAttr (sort keys %documentedAttributes) {
	if (defined $documentedAttributes{$unexistingDocAttr}) {
	    print "E: The Documented Attribute \"$unexistingDocAttr\" DOES NOT EXIST!\n";
	}
    }
}


sub testFieldAttributes {
    my %documentedAttributes = %{$itemAttributeDoc{"field"}}; 
    my @attributes = $zinc->itemconfigure($itemtypes{track},0);

    my %attributes;
    # we use this hashtable to check that all documented fields attributes
    # are matching all existing fields attributes in TkZinc
    
    # verifying that all referenced types are defined
    # and storing used types
    foreach my $attribute (sort keys %documentedAttributes) {
	my $type = $documentedAttributes{$attribute};
	$usedTypes{$type} = 1;
	print "E: type $type ($attribute of 'field') is not documented\n" unless $documentedTypes{$type};
    }
    

    foreach my $elem (@attributes) {
	my ($attributeName, $attributeType, $readOnly, $empty, $attributeValue) = @$elem;
	$attributes{$attributeName} = [$attributeType, $readOnly, $empty, $attributeValue];
    }

    foreach my $attributeName (keys %attributes) {
	my ($attributeType, $readOnly, $empty, $attributeValue) = @{$attributes{$attributeName}};
	# $empty is for provision by Zinc
	
	if (!defined $documentedAttributes{$attributeName}) {
	    print "E: $attributeName ($attributeType) of field IS NOT DOCUMENTED!\n";
	    $attributes{$attributeName} = undef;
	    next;
	}

	if ($documentedAttributes{$attributeName} ne $attributeType) {
	    print "W: $attributeName of field has type $attributeType inside ZincTk and type $documentedAttributes{$attributeName} inside Doc\n";
	    $zinc2doc{$attributeType}=$documentedAttributes{$attributeName};
	}
	$documentedAttributes{$attributeName} = undef;
    }
    
    foreach my $unexistingDocAttr (sort keys %documentedAttributes) {
	if (defined $documentedAttributes{$unexistingDocAttr}) {
	    print "E: The Documented Field Attribute \"$unexistingDocAttr\" DOES NOT EXIST!\n";
	}
    }
}

sub verifyingAllDefinedTypesAreUsed {
    foreach my $type (sort keys %documentedTypes) {
	print "W: documented type $type is never refered to in the doc\n" unless $usedTypes{$type};
    }
}

print "--- TkZinc Options -----------------------------------------\n";
&testAllOptions;
print "--- Field Attributes ---------------------------------------\n";

&testFieldAttributes;

foreach my $type (sort keys %itemtypes) {
    print "--- Item $type -------------------------------------------------\n";
    &testAllAttributes($type);
}

&verifyingAllDefinedTypesAreUsed;

print "------- Summary of type discrepencies between Doc and Zinc --------\n";
printf "%15s |%15s\n", "zinctype","doctype";
foreach my $typezinc (sort keys %zinc2doc) {
    printf "%15s |%15s\n", $typezinc,$zinc2doc{$typezinc};
}


# MainLoop();


1;

Added jni/tkzinc/Perl/t/traceutils.t.

























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/perl -w

#
# $Id$
# Author: Christophe Mertz
#

# testing Tk::Zinc::TraceUtils utilities

#use Tk::Zinc::TraceUtils;
use strict;

BEGIN {
    if (!eval q{
#        use Test::More qw(no_plan);
        use Test::More tests => 15;
        1;
    }) {
        print "# tests only work properly with installed Test::More module\n";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
    if (!eval q{
	use Tk::Zinc::TraceUtils;
 	1;
    }) {
        print "unable to load Tk::Zinc::TraceUtils";
        print "1..1\n";
        print "ok 1\n";
        exit;
    }
}



#### creating different images, bitmaps and pixmaps...

my $arg;

$arg = "1";
is (&Item ($arg), $arg, "testing " . $arg);

SKIP: {
    my $mw;
    skip "not able to create a MainWindow", 3 if !eval q{$mw = MainWindow->new()} ;
    require Tk::Font;
    my $font = $mw->fontCreate("testfont", -family => "Helvetica");
    
    like ($font, qr/^testfont/, "font creation");
    is (&Item ($font), "'testfont'", "testing " . "testfont"); # not so sure about this result!
    is (&List (-font => $font), "(-font => 'testfont')", "(-font => afont)");
}

$arg = "()";
is (&List (eval $arg), $arg, "empty list: ". $arg);

$arg = "(-option_without_value)";
is (&List (eval $arg), $arg, $arg);

$arg = "(1, 2, 3, 4)";
is (&List (eval $arg), $arg, $arg);

$arg = "(-1, -2, -3, -4)";
is (&List (eval $arg), $arg, $arg);

$arg = "(1.2, -2, .01, -1.2e+22, 1.02e+34)";
is (&List (eval $arg), ($arg =~ s/\.01/0.01/ , $arg ), $arg);

$arg = "(1.2, -2, .01, -1.2e+022, 1.02e+034)";
my $correctedArg = "(1.2, -2, 0.01, -1.2e+22, 1.02e+34)";
is (&List (eval $arg), $correctedArg, $arg);

$arg = "('-1aa' => -2, '-a b', -1.2)";
is (&List (eval $arg), $arg, $arg);

$arg = "(-option => -2, -option2 => -1.2, -option3)";
is (&List (eval $arg), $arg, $arg);

$arg = "('icon', 1, -priority => 210, -visible => 1)";
is (&List (eval $arg), $arg, $arg);

$arg = "('text', 1, -font => '-adobe-helvetica-bold-r-normal-*-120-*-*-*-*-*-*')";
is (&List (eval $arg), $arg, $arg);


$arg = "-option, -2, -option2, -1.2, -option3";
is (&Array (eval "(".$arg.")"), "[".$arg."]", "[".$arg."]");



diag("############## Tk::Zinc::TraceUtils test");

Added jni/tkzinc/Python/demos/paper.gif.

cannot compute difference between binary files

Added jni/tkzinc/Python/demos/testGraphics.py.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
#-----------------------------------------------------------------------------------
#
#      testGraphics.py
#      Fichier test du module Graphics
#
#      Authors: Jean-Luc Vinot <vinot@cena.fr> Guilaume Vidon <vidon@ath.cena.fr>
#
# $Id$
#-----------------------------------------------------------------------------------
import sys

try :
    import IPython.ultraTB
    sys.excepthook = IPython.ultraTB.FormattedTB(mode = 'Verbose',
                                                 color_scheme = 'Linux',
                                                 call_pdb = 1)
except ImportError:
    pass

VERSION = "1.13"

import Tkinter
import Zinc
import Zinc.pictorial as pictorial 
from Zinc.geometry import *
from Zinc.graphics import  build_zinc_item, tabbox_coords, lpts2coords, coords2lpts
import math
import getopt

currenttransfo = None
previousangle = 0
rotate_angle = .1
zoomfactor = .1
curview = None
dx,  dy = 0, 0

tabanchor = 'n'
tabalign = 'left'

font_9b = '7x13bold'
# the original font is not standard, even if it is fully free:
# font_9b = '-cenapii-bleriot mini-bold-r-normal--9-90-75-75-p-75-iso8859-15'

gradset = {
    'boitonglet' : '=axial 0|#ff7777|#ffff99',
    'roundrect1' : '=axial 270|#a7ffa7;70 0|#ffffff;90 5|#00bd00;80 8|#b7ffb7;50 80|#ffffff;70 91|#00ac00;70 95|#006700;60 100',
    'roundrect2' : '=axial 270|#00bd00;80 |#d7ffd7;60',
    'roundrect3' : '=axial 270|#00bd00;100 0|#ffffff;100 14|#ffffff;100 16|#00bd00;90 25|#b7ffb7;60 100',
    'roundrect4' : '=axial 0|#00bd00;100 0|#ffffff;100 20|#00bd00;50 30|#00bd00;90 80|#b7ffb7;60 100',
    'roundrect4ed' : '=path 48 48|#e7ffe7;20 0 70|#007900;20',
    'roundcurve2' : '=axial 270|#d7ffd7;60|#7777ff;80',
    'roundcurve1' : '=axial 270|#2222ff;80 |#d7ffd7;60',
    'roundcurve' : '=axial 270|#7777ff;80 |#d7ffd7;60',
    'roundpolyg' : '=radial -15 -20|#ffb7b7;50|#bd6622;90',
    'rpolyline' : '=axial 90|#ffff77;80 |#ff7700;60',
    'pushbtn1' : '=axial 0|#cccccc;100 0|#ffffff;100 10|#5a5a6a;100 80|#aaaadd;100 100',
    'pushbtn2' : '=axial 270|#ccccff;100 0|#ffffff;100 10|#5a5a7a;100 80|#bbbbee;100 100',
    'pushbtn3' : '=radial -15 -15|#ffffff;100 0|#333344;100 100',
    'pushbtn4' : '=axial 270|#ccccff;100 0|#ffffff;100 10|#7a7a9a;100 80|#bbbbee;100 100',
    'conical_edge' : '=conical 0 0 -45|#ffffff;100 0|#888899;100 30|#555566;100 50|#888899;100 70|#ffffff;100 100',
    'conical_ext' : '=conical 0 0 135|#ffffff;100 0|#777788;100 30|#444455;100 50|#777788;100 70|#ffffff;100 100',
    'pushbtn_edge' : '=axial 140|#ffffff;100 0|#555566;100 100',
    'pushbtn_edge2' : '=axial 92|#ffffff;100 0|#555566;100 100',
    'logoshape2' : '=axial 270|#ffffff|#7192aa',
    'logopoint2' : '=radial -20 -20|#ffffff 0|#f70000 48|#900000 80|#ab0000 100',
    'logoptshad2' : '=path 0 0|#770000;64 0|#770000;70 78|#770000;0 100'}


# contenu des pages exemples
pagesconf = {'Rectangle' : {'consigne' : {'itemtype' : 'text',
                                          'coords' : (-285, 155),
                                          'params' : {'font' : font_9b,
                                                      'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
                                                      'color' : '#2222cc',
                                                      },
                                          },
                            # roudedrectangle simple + radius 20
                            'rr1' : {'itemtype' : 'roundedrectangle',
                                     'coords' : ((-200, 30), (50, 130)),
                                     'radius' : 20,
                                     'params' : {'closed' : 1,
                                                 'filled' : 1,
                                                 'fillcolor' : 'roundrect2',
                                                 'linewidth' : 2,
                                                 'linecolor' : '#000000',
                                                 'priority' : 20,
                                                 'tags' : ('move'),
                                                 },
                                     },
                            # roudedrectangle 'carré' (radius automatique)
                            'rr2' : {'itemtype' : 'roundedrectangle',
                                     'coords' : ((-250, -100), (-90, 60)),
                                     'params' : {'closed' : 1,
                                                 'filled' : 1,
                                                 'fillcolor' : 'roundrect1',
                                                 'linewidth' : 3,
                                                 'linecolor' : '#000000',
                                                 'priority' : 30,
                                                 'tags' : ('move'),
                                                 },
                                     },
                            # cas particulier -> hippodrome (radius = h/2)
                            'rr3' : {'itemtype' : 'roundedrectangle',
                                     'coords' : ((-30, 80), (130, 160)),
                                     'radius' : 40,
                                     'params' : {'closed' : 1,
                                                 'filled' : 1,
                                                 'fillcolor' : 'roundrect3',
                                                 'linewidth' : 4,
                                                 'linecolor' : '#000000',
                                                 'priority' : 30,
                                                 'tags' : ('move'),
                                                 },
                                     },
                            'rr4a' : {'itemtype' : 'roundedrectangle',
                                      'coords' : ((-30, -60), (110, 10)),
                                      'radius' : 40,
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'roundrect3',
                                                  'linewidth' : 3,
                                                  'linecolor' : '#000000',
                                                  'priority' : 30,
                                                  'tags' : ('move'),
                                                  },
                                      'corners' : (1, 0, 1, 0),
                                      },
                            'rr4b' : {'itemtype' : 'roundedrectangle',
                                      'coords' : ((118, -68), (220, -132)),
                                      'radius' : 40,
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'roundrect3',
                                                  'linewidth' : 3,
                                                  'linecolor' : '#000000',
                                                  'priority' : 30,
                                                  'tags' : ('move',),
                                                },
                                      'corners' : (1, 0, 1, 0),
                                      },
                            'rr4c' : {'itemtype' : 'roundedrectangle',
                                      'coords' : ((118, -60), (190, 30)),
                                      'radius' : 40,
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'roundrect3',
                                                  'linewidth' : 3,
                                                  'linecolor' : '#000000',
                                                  'priority' : 30,
                                                  'tags' : ('move',),
                                                  },
                                      'corners' : (0, 1, 0, 1),
                                      },
                            'rr4d' : {'itemtype' : 'roundedrectangle',
                                      'coords' : ((40, -152), (110, -68)),
                                      'radius' : 40,
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'roundrect3',
                                                  'linewidth' : 3,
                                                  'linecolor' : '#000000',
                                                  'priority' : 30,
                                                  'tags' : ('move'),
                                                  },
                                      'corners' : (0, 1, 0, 1),
                                      },
                            'gr8' : {'itemtype' : 'group',
                                     'coords' : (0, 0),
                                     'params' : {'priority' : 10,
                                                 'tags' : ('move'),
                                                 'atomic' : 1,
                                                 },
                                     'items' : {'edge' : {'itemtype' : 'roundedrectangle',
                                                          'coords' : ((174, -36), (266, 146)),
                                                          'radius' : 26,
                                                          'params' : {'closed' : 1,
                                                                      'filled' : 1,
                                                                      'fillcolor' : 'roundrect4ed',
                                                                      'linewidth' : 1,
                                                                      'linecolor' : '#ffffff',
                                                                      'priority' : 20,
                                                                      },
                                                          },
                                                'top' : {'itemtype' : 'roundedrectangle',
                                                         'coords' : ((180, -30), (260, 53)),
                                                         'parentgroup' : 'gr8',
                                                         'radius' : 20,
                                                         'params' : {'closed' : 1,
                                                                     'filled' : 1,
                                                                     'fillcolor' : 'roundrect4',
                                                                     'linewidth' : 2.5,
                                                                     'linecolor' : '#000000',
                                                                     'priority' : 30,
                                                                     },
                                                         'corners' : (1, 0, 0, 1),
                                                         },
                                                'topico' : {'itemtype' : 'curve',
                                                            'parentgroup' : 'gr8',
                                                            'coords' : ((220, -10), (200, 30),(240, 30)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : '#ffff00;80',
                                                                        'linewidth' : 1,
                                                                        'linecolor' : '#007900;80',
                                                                        'priority' : 50,
                                                                        },
                                                            },
                                                'bottom' : {'itemtype' : 'roundedrectangle',
                                                            'parentgroup' : 'gr8',
                                                            'coords' : ((180, 57), (260, 140)),
                                                            'radius' : 20,
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'roundrect4',
                                                                        'linewidth' : 2.5,
                                                                        'linecolor' : '#000000',
                                                                        'priority' : 30,
                                                                        },
                                                            'corners' : (0, 1, 1, 0),
                                                            },
                                                'bottomico' : {'itemtype' : 'curve',
                                                               'parentgroup' : 'gr8',
                                                               'coords' : ((220, 120),(240, 80),(200, 80)),
                                                               'params' : {'closed' : 1,
                                                                           'filled' : 1,
                                                                           'fillcolor' : '#ffff00;80',
                                                                           'linewidth' : 1,
                                                                           'linecolor' : '#007900;80',
                                                                           'priority' : 50,
                                                                           },
                                                               },
                                                },
                                     },
                            },
             'Hippodrome' : {'consigne' : {'itemtype' : 'text',
                                           'coords' : (-285, 165),
                                           'params' : {'font' : font_9b,
                                                       'text' : "Click hippo Buttons with mouse button 1.\n",
                                                       'color' : '#2222cc',
                                                       },
                                           },
                             'hp1' : {'itemtype' : 'group',
                                      'coords' : (-163, -40),
                                      'params' : {'priority' : 40,
                                                  },
                                      'items' : {'edge' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-46, -86), (46, 86)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : 'pushbtn_edge',
                                                                       'linewidth' : 1,
                                                                       'linecolor' : '#ffffff',
                                                                       'priority' : 10,
                                                                       },
                                                           },
                                                 'form' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-40, -80), (40, 80)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : 'pushbtn1',
                                                                       'linewidth' : 3,
                                                                       'linecolor' : '#000000',
                                                                       'priority' : 20,
                                                                       'tags' : ('b1','pushbtn'),
                                                                       },
                                                           },
                                                 },
                                      },
                             'hp2' : {'itemtype' : 'group',
                                      'coords' : (-40, -40),
                                      'params' : {'priority' : 40,
                                                  },
                                      'items' : {'edge' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-46, -86), (46, 86)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : 'pushbtn_edge',
                                                                       'linewidth' : 1,
                                                                       'linecolor' : '#ffffff',
                                                                       'priority' : 10,
                                                                       },
                                                           },
                                                 'formT' : {'itemtype' : 'hippodrome',
                                                            'coords' : ((-40, -80), (40, -28)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'pushbtn1',
                                                                        'linewidth' : 3,
                                                                        'linecolor' : '#000000',
                                                                        'priority' : 20,
                                                                        'tags' : ('b2t','pushbtn'),
                                                                        },
                                                            'orientation' : 'vertical',
                                                            'trunc' : 'bottom',
                                                            },
                                                 'formC' : {'itemtype' : 'hippodrome',
                                                            'coords' : ((-40, -26.5), (40, 26.5)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'pushbtn1',
                                                                        'linewidth' : 3,
                                                                        'linecolor' : '#000000',
                                                                        'priority' : 20,
                                                                        'tags' : ('b2c','pushbtn'),
                                                                        },
                                                            'trunc' : 'both',
                                                            },
                                                 'formB' : {'itemtype' : 'hippodrome',
                                                            'coords' : ((-40, 28), (40, 80)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'pushbtn1',
                                                                        'linewidth' : 3,
                                                                        'linecolor' : '#000000',
                                                                        'priority' : 20,
                                                                        'tags' : ('b2b','pushbtn'),
                                                                        },
                                                            'orientation' : 'vertical',
                                                            'trunc' : 'top',
                                                            },
                                                 },
                                      },
                             'hp3edge' : {'itemtype' : 'hippodrome',
                                          'coords' : ((-204, 96), (204, 144)),
                                          'params' : {'closed' : 1,
                                                      'filled' : 1,
                                                      'fillcolor' : 'pushbtn_edge2',
                                                      'linewidth' : 1,
                                                      'linecolor' : '#ffffff',
                                                      'priority' : 10,
                                                      },
                                          },
                             'hp3g' : {'itemtype' : 'group',
                                       'coords' : (-160, 120),
                                       'params' : {'priority' : 40,
                                                   },
                                       'items' : {'form' : {'itemtype' : 'hippodrome',
                                                            'coords' : ((-40, -20), (40, 20)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'pushbtn2',
                                                                        'linewidth' : 2,
                                                                        'linecolor' : '#000000',
                                                                        'priority' : 20,
                                                                        'tags' : ('b3g', 'pushbtn'),
                                                                        },
                                                            'trunc' : 'right',
                                                            },
                                                  'ico' : {'itemtype' : 'curve',
                                                           'coords' : ((-20, 0), (-4, 8), (-4, -8)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : '#000000',
                                                                       'linewidth' : 1,
                                                                       'linecolor' : '#aaaaaa',
                                                                       'relief' : 'raised',
                                                                       'priority' : 30,
                                                                       'tags' : ('b3g', 'pushbtn', 'ico'),
                                                                       },
                                                           'contours' :  [['add',-1,((0, 0),(16, 8),(16, -8))]]
                                                           },
                                                  },
                                       },
                             'hp3c1' : {'itemtype' : 'group',
                                        'coords' : (-80, 120),
                                        'params' : {'priority' : 40,
                                                    },
                                        'items' : {'form' : {'itemtype' : 'hippodrome',
                                                             'coords' : ((-38, -20), (39, 20)),
                                                             'params' : {'closed' : 1,
                                                                         'filled' : 1,
                                                                         'fillcolor' : 'pushbtn2',
                                                                         'linewidth' : 2,
                                                                         'linecolor' : '#000000',
                                                                         'priority' : 20,
                                                                         'tags' : ('b3c1', 'pushbtn'),
                                                                         },
                                                             'trunc' : 'both',
                                                             },
                                                   'ico' : {'itemtype' : 'curve',
                                                            'coords' : ((-8, 0), (8, 8), (8, -8)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : '#000000',
                                                                        'linewidth' : 1,
                                                                        'linecolor' : '#aaaaaa',
                                                                        'priority' : 30,
                                                                        'relief' : 'raised',
                                                                        'tags' : ('b3c1','pushbtn','ico'),
                                                                        },
                                                            },
                                                   },
                                        },
                             'hp3c2' : {'itemtype' : 'group',
                                        'coords' : (0, 120),
                                        'params' : {'priority' : 40,
                                                    },
                                        'items' : {'form' : {'itemtype' : 'hippodrome',
                                                             'coords' : ((-39, -20), (39, 20)),
                                                             'params' : {'closed' : 1,
                                                                         'filled' : 1,
                                                                         'fillcolor' : 'pushbtn2',
                                                                         'linewidth' : 2,
                                                                         'linecolor' : '#000000',
                                                                         'priority' : 20,
                                                                         'tags' : ('b3c2', 'pushbtn'),
                                                                         },
                                                                'trunc' : 'both',
                                                             },
                                                   'ico' : {'itemtype' : 'rectangle',
                                                            'coords' : ((-6, -6), (6, 6)),
                                                            'params' : {'filled' : 1,
                                                                        'fillcolor' : '#000000',
                                                                        'linewidth' : 1,
                                                                        'linecolor' : '#aaaaaa',
                                                                        'priority' : 30,
                                                                        'tags' : ('b3c2', 'pushbtn', 'ico'),
                                                                        },
                                                            },
                                                   },
                                        },
                             'hp3C3' : {'itemtype' : 'group',
                                        'coords' : (80, 120),
                                        'params' : {'priority' : 40,
                                                    },
                                        'items' : {'form' : {'itemtype' : 'hippodrome',
                                                             'coords' : ((-39, -20), (39, 20)),
                                                             'params' : {'closed' : 1,
                                                                         'filled' : 1,
                                                                         'fillcolor' : 'pushbtn2',
                                                                         'linewidth' : 2,
                                                                         'linecolor' : '#000000',
                                                                         'priority' : 20,
                                                                         'tags' : ('b3c3', 'pushbtn'),
                                                                         },
                                                             'trunc' : 'both',
                                                             },
                                                   'ico' : {'itemtype' : 'curve',
                                                            'coords' : ((8, 0), (-8, -8), (-8, 8)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : '#000000',
                                                                        'linewidth' : 1,
                                                                        'linecolor' : '#aaaaaa',
                                                                        'priority' : 30,
                                                                        'relief' : 'raised',
                                                                        'tags' : ('b3c3', 'pushbtn', 'ico'),
                                                                        },
                                                            },
                                                   },
                                        },
                             
                            'hp3D' : {'itemtype' : 'group',
                                      'coords' : (160, 120),
                                      'params' : {'priority' : 40,
                                                  },
                                      'items' : {'form' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-40, -20), (40, 20)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : 'pushbtn2',
                                                                       'linewidth' : 2,
                                                                       'linecolor' : '#000000',
                                                                       'priority' : 20,
                                                                       'tags' : ('b3d', 'pushbtn'),
                                                                       },
                                                           'trunc' : 'left',
                                                           },
                                                 'ico' : {'itemtype' : 'curve',
                                                          'coords' : ((20, 0), (4, -8), (4, 8)),
                                                          'params' : {'closed' : 1,
                                                                      'filled' : 1,
                                                                      'fillcolor' : '#000000',
                                                                      'linewidth' : 1,
                                                                      'linecolor' : '#aaaaaa',
                                                                      'priority' : 30,
                                                                      'relief' : 'raised',
                                                                      'tags' : ('b3d', 'pushbtn', 'ico'),
                                                                      },
                                                          'contours' :  [['add', -1, ((0,0), (-16, -8), (-16, 8))]],
                                                          },
                                                 },
                                      },
                             
                             'hp4a' : {'itemtype' : 'group',
                                       'coords' : (48, -97),
                                       'params' : {'priority' : 40,
                                                   },
                                       'repeat' : {'num' : 2,
                                                   'dxy' : (0, 64),
                                                   },
                                       'items' : {'edge' : {'itemtype' : 'hippodrome',
                                                            'coords' : ((-29, -29), (29, 29)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'pushbtn_edge',
                                                                        'linewidth' : 1,
                                                                        'linecolor' : '#ffffff',
                                                                        'priority' : 0,
                                                                        },
                                                            },
                                                  'form' : {'itemtype' : 'hippodrome',
                                                            'coords' : ((-24, -24), (24, 24)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'pushbtn3',
                                                                        'linewidth' : 3,
                                                                        'linecolor' : '#000000',
                                                                        'priority' : 30,
                                                                        'tags' : ('b4a','pushbtn'),
                                                                        },
                                                            },
                                                  },
                                       },
                             
                             'hp4b' : {'itemtype' : 'group',
                                       'coords' : (145, -65),
                                       'params' : {'priority' : 40,
                                                   },
                                       'items' : {'edge' : {'itemtype' : 'hippodrome',
                                                            'coords' : ((-60, -60), (60, 60)),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'conical_edge',
                                                                        'linewidth' : 1,
                                                                        'linecolor' : '#ffffff',
                                                                        'priority' : 0,
                                                                        },
                                                            },
                                                  'ext' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-53, -53), (53, 53)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : 'conical_ext',
                                                                       'linewidth' : 3,
                                                                       'linecolor' : '#000000',
                                                                       'priority' : 10,
                                                                       'tags' : ('b4b','pushbtn'),
                                                                       },
                                                           },
                                                  'int' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-41, -41), (40, 40)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : '=path 10 10|#ffffff 0|#ccccd0 50|#99999f 80|#99999f;0 100',
                                                                       'linewidth' : 0,
                                                                       'linecolor' : '#cccccc;80',
                                                                       'priority' : 30,
                                                                       'tags' : ('b4b','pushbtn'),
                                                                       },
                                                           },
                                                  },
                                       },
                             
                             'hp5' : {'itemtype' : 'group',
                                      'coords' : (60, 25),
                                      'params' : {'priority' : 40,
                                                  },
                                      'rotate' : 30,
                                      'repeat' : {'num' : 4,
                                                  'dxy' : (45, 0),
                                                  },
                                      'items' : {'edge' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-19, -34), (19, 34)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : 'pushbtn_edge',
                                                                       'linewidth' : 1,
                                                                       'linecolor' : '#ffffff',
                                                                       'priority' : 10,
                                                                       },
                                                           },
                                                 'form' : {'itemtype' : 'hippodrome',
                                                           'coords' : ((-15, -30), (15, 30)),
                                                           'params' : {'closed' : 1,
                                                                       'filled' : 1,
                                                                       'fillcolor' : 'pushbtn1',
                                                                       'linewidth' : 2,
                                                                       'linecolor' : '#000000',
                                                                       'priority' : 20,
                                                                       'tags' : ('b5', 'pushbtn'),
                                                                       },
                                                           },
                                                 },
                                      },
                             },

             'Polygone' : {'consigne' : {'itemtype' : 'text',
                                         'coords' : (-285, 160),
                                         'params' : {'font' : font_9b,
                                                     'text' : "Click and Drag inside Polygons for rotate them\nEscape key reset transfos.",
                                                     'color' : '#2222cc',
                                                     },
                                         },
                           'triangle' : {'itemtype' : 'group',
                                         'coords' : (-215, -95),
                                         'items' : {'form' : {'itemtype' : 'polygone',
                                                              'coords' : (0, 0),
                                                              'numsides' : 3,
                                                              'radius' : 78,
                                                              'corner_radius' : 10,
                                                              'startangle' : 90,
                                                              'params' : {'closed' : 1,
                                                                          'filled' : 1,
                                                                          'fillcolor' : 'roundpolyg',
                                                                          'linewidth' : 2,
                                                                          'linecolor' : '#330000',
                                                                          'priority' : 20,
                                                                          'tags' : ('p1', 'poly'),
                                                                          },
                                                              },
                                                    'text' : {'itemtype' : 'text',
                                                              'coords' : (0, -6),
                                                              'params' : {'font' : font_9b,
                                                                          'text' : "Triangle",
                                                                          'anchor' : 'n',
                                                                          'alignment' : 'center',
                                                                          'color' : '#660000',
                                                                          'priority' : 50,
                                                                          },
                                                              },
                                                    },
                                         },
                           
				 'carre' : {'itemtype' : 'group',
                                            'coords' : (-80, -75),
                                            'items' : {'form' : {'itemtype' : 'polygone',
                                                                 'coords' : (0, 0),
                                                                 'numsides' : 4,
                                                                 'radius' : 70,
                                                                 'corner_radius' : 10,
                                                                 'startangle' : 90,
                                                                 'params' : {'closed' : 1,
                                                                             'filled' : 1,
                                                                             'fillcolor' : 'roundpolyg',
                                                                             'linewidth' : 2,
                                                                             'linecolor' : '#330000',
                                                                             'priority' : 20,
                                                                             'tags' : ('p2', 'poly'),
                                                                             },
                                                                 },
                                                       'text' : {'itemtype' : 'text',
                                                                 'coords' : (0, -6),
                                                                 'params' : {'font' : font_9b,
                                                                             'text' : "Carré",
                                                                             'anchor' : 'n',
                                                                             'alignment' : 'center',
                                                                             'color' : '#660000',
                                                                             'priority' : 50,
                                                                             },
                                                                 },
						       },
					    },
                           
                           'pentagone' : {'itemtype' : 'group',
                                          'coords' : (65, -75),
                                          'items' : {'form' : {'itemtype' : 'polygone',
                                                               'coords' : (0, 0),
                                                               'numsides' : 5,
                                                               'radius' : 70,
                                                               'corner_radius' : 10,
                                                               'startangle' : 270,
                                                               'params' : {'closed' : 1,
                                                                           'filled' : 1,
                                                                           'fillcolor' : 'roundpolyg',
                                                                           'linewidth' : 2,
                                                                           'linecolor' : '#330000',
                                                                           'priority' : 20,
                                                                           'tags' : ('p3', 'poly'),
                                                                           },
                                                               },
                                                     'text' : {'itemtype' : 'text',
                                                               'coords' : (0, -6),
                                                               'params' : {'font' : font_9b,
                                                                           'text' : "Pentagone",
                                                                           'anchor' : 'n',
                                                                           'alignment' : 'center',
                                                                           'color' : '#660000',
                                                                           'priority' : 50,
                                                                           },
                                                               },
                                                     },
                                          },
                           
                           'hexagone' : {'itemtype' : 'group',
                                         'coords' : (210, -75),
                                         'items' : {'form' : {'itemtype' : 'polygone',
                                                              'coords' : (0, 0),
                                                              'numsides' : 6,
                                                              'radius' : 68,
                                                              'corner_radius' : 10,
                                                              'params' : {'closed' : 1,
                                                                          'filled' : 1,
                                                                          'fillcolor' : 'roundpolyg',
                                                                          'linewidth' : 2,
                                                                          'linecolor' : '#330000',
                                                                          'priority' : 20,
                                                                          'tags' : ('p4', 'poly'),
                                                                          },
                                                              },
                                                    'text' : {'itemtype' : 'text',
                                                              'coords' : (0, -6),
                                                              'params' : {'font' : font_9b,
                                                                          'text' : "Hexagone",
                                                                          'anchor' : 'n',
                                                                          'alignment' : 'center',
                                                                          'color' : '#660000',
                                                                          'priority' : 50,
                                                                          },
                                                              },
                                                    },
                                         },

                           'heptagone' : {'itemtype' : 'group',
                                          'coords' : (-215, 85),
                                          'items' : {'form' : {'itemtype' : 'polygone',
                                                               'coords' : (0, 0),
                                                               'numsides' : 7,
                                                               'radius' : 64,
                                                               'corner_radius' : 10,
                                                               'params' : {'closed' : 1,
                                                                           'filled' : 1,
                                                                           'fillcolor' : 'roundpolyg',
                                                                           'linewidth' : 2,
                                                                           'linecolor' : '#330000',
                                                                           'priority' : 20,
                                                                           'tags' : ('p5', 'poly'),
                                                                           },
                                                                },
                                                     'text' : {'itemtype' : 'text',
                                                               'coords' : (0, -6),
                                                               'params' : {'font' : font_9b,
                                                                           'text' : "Heptagone",
                                                                           'anchor' : 'n',
                                                                           'alignment' : 'center',
                                                                           'color' : '#660000',
                                                                           'priority' : 50,
                                                                           },
                                                               },
                                                     },
                                          },
                           

                           'octogone' : {'itemtype' : 'group',
                                         'coords' : (-76, 85),
                                         'items' : {'form' : {'itemtype' : 'polygone',
                                                              'coords' : (0, 0),
                                                              'numsides' : 8,
                                                              'radius' : 64,
                                                              'corner_radius' : 10,
                                                              'params' : {'closed' : 1,
                                                                          'filled' : 1,
                                                                          'fillcolor' : 'roundpolyg',
                                                                          'linewidth' : 2,
                                                                          'linecolor' : '#330000',
                                                                          'priority' : 20,
                                                                          'tags' : ('p6', 'poly'),
                                                                        },
                                                              },
                                                    'text' : {'itemtype' : 'text',
                                                              'coords' : (0, -6),
                                                              'params' : {'font' : font_9b,
                                                                          'text' : "Octogone",
                                                                          'anchor' : 'n',
                                                                          'alignment' : 'center',
                                                                          'color' : '#660000',
                                                                          'priority' : 50,
                                                                          },
                                                              },
                                                    },
                                         },
                           
                           'petagone' : {'itemtype' : 'group',
                                         'coords' : (66, 85),
                                         'items' : {'form' : {'itemtype' : 'polygone',
                                                              'coords' : (0, 0),
                                                              'numsides' : 32,
                                                              'radius' : 64,
                                                              'corner_radius' : 10,
                                                              'params' : {'closed' : 1,
                                                                          'filled' : 1,
                                                                          'fillcolor' : 'roundpolyg',
                                                                          'linewidth' : 2,
                                                                          'linecolor' : '#330000',
                                                                          'priority' : 20,
                                                                          'tags' : ('p7', 'poly'),
                                                                          },
                                                              },
                                                    'text' : {'itemtype' : 'text',
                                                              'coords' : (0, -6),
                                                              'params' : {'font' : font_9b,
                                                                          'text' : "32 cotés...",
                                                                          'anchor' : 'n',
                                                                          'alignment' : 'center',
                                                                          'color' : '#660000',
                                                                          'priority' : 50,
                                                                          },
                                                              },
                                                    },
                                         },

                           'etoile' : {'itemtype' : 'group',
                                       'coords' : (210, 85),
                                       'items' : {'form' : {'itemtype' : 'polygone',
                                                            'coords' : (0, 0),
                                                            'numsides' : 5,
                                                            'radius' : 92,
                                                            'inner_radius' : 36,
                                                            'corner_radius' : 10,
                                                            'startangle' : 270,
                                                            'corners' : (0, 1, 0, 1, 0, 1, 0, 1, 0, 1),
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'fillcolor' : 'roundpolyg',
                                                                        'linewidth' : 2,
                                                                        'linecolor' : '#330000',
                                                                        'priority' : 20,
                                                                        'tags' : ('p8', 'poly'),
                                                                        },
                                                            },
                                                  'text' : {'itemtype' : 'text',
                                                            'coords' : (0, -6),
                                                            'params' : {'font' : font_9b,
                                                                        'text' : "Etoile",
                                                                        'anchor' : 'n',
                                                                        'alignment' : 'center',
                                                                        'color' : '#660000',
                                                                        'priority' : 50,
                                                                        },
                                                            },
                                                  },
                                       },
                           },

             'Polyline' : {'consigne' : {'itemtype' : 'text',
                                         'coords' : (-285, 155),
                                         'params' : {'font' : font_9b,
                                                     'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
                                                     'color' : '#2222cc',
                                                     },
                                         },
                           'a' : {'itemtype' : 'polyline',
                                  'coords' : ((-200, -115), (-200, -100), (-218, -115), (-280, -115), (-280, -16),
                                              (-218, -16), (-200, -31), (-200, -17.5), (-150, -17.5), (-150,-115)),
                                  'corners_radius' : (0, 0, 42, 47, 47, 42, 0, 0, 0, 0, 0, 0),
                                  'params' : {'closed' : 1,
                                              'filled' : 1,
                                              'visible' : 1,
                                              'fillcolor' : 'rpolyline',
                                              'linewidth' : 2,
                                              'linecolor' : '#000000',
                                              'priority' : 50,
                                              'tags' : ('move'),
                                              },
                                  'contours' : [['add', -1, ((-230, -80), (-230, -50), (-200, -50), (-200, -80)),15]],
                                  },
                           'b' : {'itemtype' : 'polyline',
                                  'coords' : ((-138, -150), (-138, -17.5), (-88, -17.5), (-88, -31), (-70, -16),
                                              (-8, -16), (-8, -115), (-70, -115), (-88, -100), (-88, -150)),
                                  'corners_radius' : (0, 0, 0, 0, 42, 47, 47, 42, 0, 0, 0, 0, 0, 0),
                                  'params' : {'closed' : 1,
                                              'filled' : 1,
                                              'visible' : 1,
                                              'fillcolor' : 'rpolyline',
                                              'linewidth' : 2,
                                              'linecolor' : '#000000',
                                              'priority' : 50,
                                              'tags' : ('move'),
                                              },
                                  'contours' : [['add', -1, ((-88, -80), (-88, -50), (-58, -50), (-58, -80)), 15]],
                                  },
                           'c' : {'itemtype' : 'polyline',
                                  'coords' : ((80, -76), (80, -110), (60, -115), (0, -115), (0, -16),
                                              (60, -16), (80, -21), (80, -57), (50, -47), (50, -86)),
                                  'corners_radius' : (0, 0, 70, 47, 47, 70, 0, 0, 14, 14, 0, 0, 0,0 ),
                                  'params' : {'closed' : 1,
                                              'filled' : 1,
                                              'visible' : 1,
                                              'fillcolor' : 'rpolyline',
                                              'linewidth' : 2,
                                              'linecolor' : '#000000',
                                              'priority' : 50,
                                              'tags' : ('move'),
                                              },
                                  },
                           'spirale' : {'itemtype' : 'polyline',
                                        'coords' : ((215, -144), (139, -144), (139, 0), (268, 0), (268, -116),
                                                    (162.5, -116), (162.5, -21), (248, -21), (248, -96), (183, -96),
                                                    (183, -40), (231,-40), (231, -80), (199, -80), (199, -55), (215, -55)),
                                        'corners_radius' : (0, 76, 68, 61, 55, 50, 45, 40, 35, 30, 26, 22, 18, 14, 11),
                                        'params' : {'closed' : 1,
                                                    'filled' : 1,
                                                    'visible' : 1,
                                                    'fillcolor' : 'rpolyline',
                                                    'linewidth' : 2,
                                                    'linecolor' : '#000000',
                                                    'priority' : 50,
                                                    'tags' : ('move'),
                                                    },
                                        },
                           'logo' : {'itemtype' : 'group',
                                     'coords' : (0, 0),
                                     'params' : {'priority' : 30,
                                                 'atomic' : 1,
                                                 'tags' : ('move'),
                                                 },
                                     'items' : {'tkzinc' : {'itemtype' : 'polyline',
                                                            'coords' : ((-150,10), (-44,10), (-44,68), (-28,51), (6,51),
                                                                        (-19,79), (3,109), (53,51), (5,51), (5,10), (140,10),
                                                                        (52,115), (96,115), (96,47), (196,47), (196,158),
                                                                        (155,158), (155,89), (139,89), (139,160), (101, 160),
                                                                        (101,132), (85,132), (85,160), (-42,160), (-2,115),
                                                                        (-30,115), (-46,91), (-46,115), (-76,115), (-76,51),
                                                                        (-98,51), (-98,115), (-130,115), (-130,51), (-150, 51)),
                                                            'corners_radius' : [0,0,0,0,0,0,0,0,0,0,30,0,0,50,50,
                                                                                0,0,8,8,0,0,8,8,0,27],
                                                            'params' : {'closed' : 1,
                                                                        'filled' : 1,
                                                                        'visible' : 1,
                                                                        'fillcolor' : 'logoshape2',
                                                                        'linewidth' : 2.5,
                                                                        'linecolor' : '#000000',
                                                                        'priority' : 10,
                                                                        'fillrule' : 'nonzero',
                                                                        },
                                                            
                                                            'contours' : [['add', 1, ((245,88), (245,47), (190,47), (190,158),
                                                                                      (259,158), (259,117), (230,117), (230,88)),
                                                                           5, None, (0,0,55,55,0,0,15,15)]],
                                                            },
                                                'shad' : {'itemtype' : 'arc',
                                                          'coords' : ((75, 91), (115,131)),
                                                          'params' : {'priority' : 20,
                                                                      'filled' : 1,
                                                                      'linewidth' : 0,
                                                                      'fillcolor' : 'logoptshad2',
                                                                      'closed' : 1,
                                                                      },
                                                          },
                                                'point' : {'itemtype' : 'arc',
                                                           'coords' : ((70, 86), (110,126)),
                                                           'params' : {'priority' : 50,
                                                                       'filled' : 1,
                                                                       'linewidth' : 1,
                                                                       'linecolor' : '#a10000',
                                                                       'fillcolor' : 'logopoint2',
                                                                       'closed' : 1,
                                                                       },
                                                           },
                                                },
                                     },
                           },
             
             'MultiContours' : {'consigne' : {'itemtype' : 'text',
                                              'coords' : (-285, 155),
                                              'params' : {'font' : font_9b,
                                                          'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
                                                          'color' : '#2222cc',
                                                          },
					      },
                                'mc1' : {'itemtype' : 'roundedcurve',
                                         'coords' : ((-30, -170), (-130, 0), (70, 0)),
                                         'radius' : 14,
                                         'params' : {'closed' : 1,
                                                     'filled' : 1,
                                                     'fillcolor' : 'roundcurve2',
                                                     'linewidth' : 1,
                                                     'linecolor' : '#000000',
                                                     'priority' : 20,
                                                     'tags' : ('move'),
                                                     'fillrule' : 'odd',
                                                     },
                                         'contours' : [['add', 1,((-30,-138), (-100,-18), (40,-18)), 8],
                                                       ['add', 1,((-30,-130), ( -92,-22), (32,-22)), 5],
                                                       ['add', 1,((-30,-100), ( -68,-36), (8,-36)), 5],
                                                       ['add', 1,((-30, -92), ( -60,-40), (0,-40)), 3],],
                                         },
                                'mc2' : {'itemtype' : 'polyline',
                                         'coords' : ((-250,-80), (-240,-10), (-285,-10), (-285,80),
                                                     (-250, 80), (-250, 40), (-170, 40), (-170,80),
                                                     (-100,80), (-100,40), (-20,40), (-20,80), (30,80),
                                                     (-10, 0), (-74, -10), (-110, -80)),
                                         'corners_radius' : (24,4, 40, 20, 0, 40, 40, 0, 0, 40, 40, 0, 30, 75, 0, 104),
                                         'params' : {'closed' : 1,
                                                     'filled' : 1,
                                                     'fillcolor' : 'roundcurve1',
                                                     'linewidth' : 2,
                                                     'linecolor' : '#000000',
                                                     'priority' : 30,
                                                     'tags' : ('move'),
                                                     },
                                         'contours' : [['add',-1,((-240,-72), (-230,0), (-169,0), (-185, -72)),
                                                        0, None, (16, 16, 0, 0)],
                                                       ['add', -1, ((-175,-72), (-159,0), (-78,0), (-116, -72)),
                                                        0, None, (0, 0, 8, 88)],
                                                       ['add', 1, ((-245,45), (-245,115), (-175,115), (-175, 45)),
                                                        35],
                                                       ['add', -1, ((-225,65), (-225,95), (-195,95), (-195, 65)),
                                                        15],
                                                       ['add', 1, ((-95,45), (-95,115), (-25,115), (-25, 45)),
                                                        35],
                                                       ['add', -1, ((-75,65), (-75,95), (-45,95), (-45, 65)),
                                                        15],
                                                       ],
                                         },
                                'mc3' : {'itemtype' : 'roundedcurve',
                                         'coords' : ((-10, 170), (256, 170), (312, 60), (48, 60)),
                                         'radius' : 34,
                                         'params' : {'closed' : 1,
                                                     'filled' : 1,
                                                     'fillcolor' : 'roundcurve2',
                                                     'linewidth' : 2.5,
                                                     'linecolor' : '#000000',
                                                     'priority' : 40,
                                                     'tags' : ('move'),
                                                     },
                                         'contours' : [['add', -1, ((58, 62), (12, 144), (60, 172), (104, 88)), 27],
                                                       ['add', 1, ((48, 77), (48, 119), (90, 119), (90, 77)), 21],
                                                       ['add', -1, ((244, 58), (198, 140), (246, 168), (290, 84)), 27],
                                                       ['add', 1, ((213, 110), (213, 152), (255, 152), (255, 110)), 21],
                                                       ['add', -1, ((150, 60), (150, 170), (160, 170), (160, 60)), 0]],
                                         },
                                'mc4' : {'itemtype' : 'roundedcurve',
                                         'coords' : ((222, -150), (138, -150), (180, -50), (138, -150),
                                                     (80, -92), (180, -50), (80, -92), (80, -8),
                                                     (180, -50), (80, -8), (138, 50), (180, -50),
                                                     (138, 50), (222, 50), (179.8, -50), (222, 50),
                                                     (280, -8), (180, -50), (280, -8), (280, -92),
                                                     (180, -50), (280, -92), (222,-150), (180,-50)),
                                         'radius' : 28,
                                         'params' : {'closed' : 1,
                                                     'filled' : 1,
                                                     'fillcolor' : 'roundcurve',
                                                     'linewidth' : 2,
                                                     'linecolor' : '#000000',
                                                     'priority' : 30,
                                                     'tags' : ('move'),
                                                     },
                                         'contours' : [['add', -1, ((160, -70), (160, -30), (200, -30), (200, -70)), 20]],
                                         },
                                },
             
             'TabBox' : {'consigne' : {'itemtype' : 'text',
                                       'coords' : (-285, 160),
                                       'params' : {'font' : font_9b,
                                                   'text' : "Click on thumbnail to select page\nChange anchor or alignment tabs options with radio buttons.\n",
                                                   'color' : '#2222cc',
                                                   },
                                       },
                         
                         'exemple' : {'itemtype' : 'text',
                                      'coords' : (-165, -105),
                                      'params' : {'font' : font_9b,
                                                  'text' : "",
                                                  'alignment' : 'left',
                                                  'anchor' : 'nw',
                                                  'color' : '#000000',
                                                  'priority' : 500,
                                                  'width' : 350,
                                                  'tags' : ('div2', 'fontname'),
                                                  },
                                      },
                         
                         'bo1' : {'itemtype' : 'tabbox',
                                  'coords' : ((-240, -160), (240, 100)),
                                  'radius' : 8,
                                  'tabwidth' : 72,
                                  'tabheight' : 28,
                                  'numpages' : 8,
                                  'anchor' : 'n',
                                  'alignment' : 'left',
                                  'overlap' : 3,
                                  'params' : {'closed' : 1,
                                              'priority' : 100,
                                              'filled' : 1,
                                              'fillcolor' : '#ffffff',
                                              'linewidth' : 1.2,
                                              'linecolor' : '#000000',
                                              'tags' : ('div2', 'divider'),
                                              },
                                  'tabtitles' : {'text' : ('A', 'B', 'C', 'D', 'E', 'F','G','H'),
                                                 'params' : {'text' : 'titre',
                                                             'color' : '#2222cc',
                                                             'font' : font_9b,
                                                             'anchor' : 'center',
                                                             'alignment' : 'center',
                                                             'priority' : 400,
                                                             'visible' : 1,
                                                             },
                                                 },
                                  },
                         
                         'back' : {'itemtype' : 'roundedrectangle',
                                   'coords' : ((-242, -162), (242, 102)),
                                   'radius' : 10,
                                   'params' : {'closed' : 1,
                                               'filled' : 1,
                                               'fillcolor' : '#777777;80',
                                               'linewidth' : 1,
                                               'linecolor' : '#777777;80',
                                               },
                                   },
                         
                         'anchor' : {'itemtype' : 'text',
                                     'coords' : (-120, 115),
                                     'params' : {'text' : 'tabs anchor',
                                                 'color' : '#2222cc',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 },
                                     },
                         
                         'anchorN' : {'itemtype' : 'hippodrome',
                                      'coords' : ((-210, 125), (-165, 151)),
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'pushbtn4',
                                                  'linewidth' : 1.5,
                                                  'linecolor' : '#000000',
                                                  'priority' : 20,
                                                  'tags' : ('sel1', 'n', 'btn', 'selector'),
                                                  },
                                      'trunc' : 'right',
                                      },
                         'txtanN' : {'itemtype' : 'text',
                                     'coords' : (-187, 138),
                                     'params' : {'text' : 'N',
                                                 'color' : '#000000',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 'tags' : ('sel1', 'n', 'btntext', 'selector'),
                                                 },
                                     },

                         'anchorE' : {'itemtype' : 'hippodrome',
                                      'coords' : ((-163, 125), (-120, 151)),
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'pushbtn4',
                                                  'linewidth' : 1.5,
                                                  'linecolor' : '#000000',
                                                  'priority' : 20,
                                                  'tags' : ('sel1', 'e', 'btn', 'selector'),
							},
                                      'trunc' : 'both',
                                    },
                         'txtanE' : {'itemtype' : 'text',
                                     'coords' : (-141.5, 138),
                                     'params' : {'text' : 'E',
                                                 'color' : '#000000',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 'tags' : ('sel1', 'e', 'btntext', 'selector'),
                                                },
                                     },

                         'anchorS' : {'itemtype' : 'hippodrome',
                                      'coords' : ((-118, 125), (-75, 151)),
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'pushbtn4',
                                                  'linewidth' : 1.5,
                                                  'linecolor' : '#000000',
                                                  'priority' : 20,
                                                  'tags' : ('sel1', 's', 'btn', 'selector'),
                                                  },
                                      'trunc' : 'both',
                                      },
                         'txtanS' : {'itemtype' : 'text',
                                     'coords' : (-96.5, 138),
                                     'params' : {'text' : 'S',
                                                 'color' : '#000000',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 'tags' : ('sel1', 's', 'btntext', 'selector'),
                                                 },
                                     },
                         'anchorW' : {'itemtype' : 'hippodrome',
                                      'coords' : ((-73, 125), (-28, 151)),
                                      'params' : {'closed' : 1,
                                                  'filled' : 1,
                                                  'fillcolor' : 'pushbtn4',
                                                  'linewidth' : 1.5,
                                                  'linecolor' : '#000000',
                                                  'priority' : 20,
                                                  'tags' : ('sel1', 'w', 'btn', 'selector'),
                                                  },
                                      'trunc' : 'left',
                                      },
                         'txtanW' : {'itemtype' : 'text',
                                     'coords' : (-52, 138),
                                     'params' : {'text' : 'W',
                                                 'color' : '#000000',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 'tags' : ('sel1', 'w', 'btntext', 'selector'),
                                                 },
                                     },
                         'alignment' : {'itemtype' : 'text',
                                        'coords' : (120, 115),
                                        'params' : {'text' : 'tabs alignment',
                                                    'color' : '#2222cc',
                                                    'font' : font_9b,
                                                    'anchor' : 'center',
                                                    'alignment' : 'center',
                                                    'priority' : 40,
                                                    },
                                        },
                         'alignG' : {'itemtype' : 'hippodrome',
                                     'coords' : ((30, 125), (90, 151)),
                                     'params' : {'closed' : 1,
                                                 'filled' : 1,
                                                 'fillcolor' : 'pushbtn4',
                                                 'linewidth' : 1.5,
                                                 'linecolor' : '#000000',
                                                 'priority' : 20,
                                                'tags' : ('sel2', 'left', 'btn', 'selector'),
                                                 },
                                     'trunc' : 'right',
                                     },
                         'txtalG' : {'itemtype' : 'text',
                                     'coords' : (60, 138),
                                     'params' : {'text' : 'left',
                                                 'color' : '#000000',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 'tags' : ('sel2', 'left', 'btntext', 'selector'),
                                                 },
                                     },
                         'alignC' : {'itemtype' : 'hippodrome',
                                     'coords' : ((92, 125), (148, 151)),
                                     'params' : {'closed' : 1,
                                                 'filled' : 1,
                                                 'fillcolor' : 'pushbtn4',
                                                 'linewidth' : 1.5,
                                                 'linecolor' : '#000000',
                                                 'priority' : 20,
                                                 'tags' : ('sel2', 'center', 'btn', 'selector'),
                                                 },
                                     'trunc' : 'both',
                                     },
                         'txtalC' : {'itemtype' : 'text',
                                     'coords' : (120, 138),
                                     'params' : {'text' : 'center',
                                                 'color' : '#000000',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 'tags' : ('sel2', 'center', 'btntext', 'selector'),
                                                 },
                                     },
                         'alignD' : {'itemtype' : 'hippodrome',
                                     'coords' : ((150, 125), (210, 151)),
                                     'params' : {'closed' : 1,
                                                 'filled' : 1,
                                                 'fillcolor' : 'pushbtn4',
                                                 'linewidth' : 1.5,
                                                 'linecolor' : '#000000',
                                                 'priority' : 20,
                                                 'tags' : ('sel2', 'right', 'btn', 'selector'),
                                                 },
                                     'trunc' : 'left',
                                     },
                         'txtalD' : {'itemtype' : 'text',
                                     'coords' : (180, 138),
                                     'params' : {'text' : 'right',
                                                 'color' : '#000000',
                                                 'font' : font_9b,
                                                 'anchor' : 'center',
                                                 'alignment' : 'center',
                                                 'priority' : 40,
                                                 'tags' : ('sel2', 'right', 'btntext', 'selector'),
                                                 },
                                     },
                         },
             
             'PathLine' : {'consigne' : {'itemtype' : 'text',
                                         'coords' : (-285, 155),
                                         'params' : {'font' : font_9b,
                                                     'text' : "Mouse button 1 drag objects,\nEscape key reset transfos.",
                                                     'color' : '#2222cc',
                                                     },
                                         },
                           'pl1' : {'itemtype' : 'pathline',
                                    'metacoords' : {'type' : 'polygone',
                                                     'coords' : (0, 0),
                                                     'numsides' : 12,
                                                     'radius' : 200,
                                                     'inner_radius' : 100,
                                                     'startangle' : -8,
                                                     },
                                    'linewidth' : 20,
                                    'closed' : 1,
                                    'graduate' : {'type' : 'linear',
                                                  'colors' : ('#ff0000', '#ff00ff', '#0000ff', '#00ffff',
                                                              '#00ff00', '#ffff00', '#ff0000'),
                                                  },
                                    'params' : {'priority' : 100,
                                                'tags' : ('move'),
                                                },
                                    },
                           
                           'pl2' : {'itemtype' : 'group',
                                    'coords' : (0, 0),
                                    'params' : {'priority' : 200,
                                                'atomic' : 1,
                                                'tags' : ('move'),
                                                },
                                    'items' : {'in' : {'itemtype' : 'pathline',
                                                       'coords' : ((30, -60), (-30, -60), (-30, -30),
                                                                   (-60, -30), (-60, 30), (-30, 30),
                                                                   (-30, 60), (30, 60), (30, 30),
                                                                   (60, 30), (60, -30), (30, -30)),
                                                       'linewidth' : 16,
                                                       'closed' : 1,
                                                       'shifting' : 'left',
                                                       'graduate' : {'type' : 'transversal',
                                                                     'colors' : ('#00aa77;100', '#00aa77;0'),
                                                                     },
                                                       'params' : {'priority' : 10,
                                                                   },
                                                       },
                                               
                                               'out' : {'itemtype' : 'pathline',
                                                        'coords' : ((30, -60), (-30, -60), (-30, -30),
                                                                    (-60, -30), (-60, 30), (-30, 30),
                                                                    (-30, 60), (30, 60), (30, 30),
                                                                    (60, 30), (60, -30), (30, -30)),
                                                        'linewidth' : 10,
                                                        'closed' : 1,
                                                        'shifting' : 'in',
                                                        'graduate' : {'type' : 'transversal',
                                                                      'colors' : ('#00aa77;100', '#00aa77;0'),
                                                                      },
                                                        'params' : {'priority' : 10,
                                                                    },
                                                        },
                                               },
                                    },
                           
                           'pl3' : {'itemtype' : 'group',
                                    'coords' : (0, 0),
                                    'params' : {'priority' : 100,
                                                'atomic' : 1,
                                                'tags' : ('move'),
                                                },
                                    'items' : {'back' : {'itemtype' : 'arc',
                                                         'coords' : ((-150, -150), (150,150)),
                                                         'params' : {'priority' : 10,
                                                                     'closed' : 1,
                                                                     'filled' : 1,
                                                                     'fillcolor' : '=radial 15 15|#ffffff;40|#aaaaff;10',
                                                                     'linewidth' : 0,
                                                                     },
                                                         },
                                               'light' : {'itemtype' : 'pathline',
                                                          'metacoords' : {'type' : 'polygone',
                                                                           'coords' : (0, 0),
                                                                           'numsides' : 30,
                                                                           'radius' : 150,
                                                                           'startangle' : 240,
                                                                           },
                                                          'linewidth' : 20,
                                                          'shifting' : 'in',
                                                          'closed' : 1,
                                                          'graduate' : {'type' : 'double',
                                                                        'colors' : (('#ffffff;0', '#222299;0', '#ffffff;0'),
                                                                                    ('#ffffff;100', '#222299;70', '#ffffff;100')),
                                                                        },
                                                          'params' : {'priority' : 50,
                                                                      },
                                                          },
                                               'bord' : {'itemtype' : 'arc',
                                                         'coords' : ((-150, -150), (150,150)),
                                                         'params' : {'priority' : 100,
                                                                     'closed' : 1,
                                                                     'filled' : 0,
                                                                     'linewidth' : 2,
                                                                     'linecolor' : '#000033;80'
                                                                     },
                                                         },
                                               
                                               },
                                    },
                           }
             }


tabtables = { 'n' : {'numpages' : 8,
                    'titles' : ('A','B','C','D','E','F','G','H'),
                    'names' : ('ATOMIC GROUP :', 'BIND COMMAND :', 'CURVE ITEMS :', 'DISPLAY LIST :',
                               'EVENTS SENSITIVITY :', 'FIT COMMAND :', 'GROUP ITEMS', 'HASTAG COMMAND'),
                    'texts' : ("It may seem at first that there is a contradiction in this title, but there is not. (...) So groups have a feature, the atomic  attribute, that is used to seal a group so that events cannot propagate past it downward. If an item part of an atomic group is under the pointer, TkZinc will try to trigger bindings associated with the atomic group not with the item under the pointer. This improves greatly the metaphor of an indivisible item.",
                               "This widget command is similar to the Tk bind command except that it operates on TkZinc items instead of widgets. Another difference with the bind command is that only mouse and keyboard related events can be specified (such as Enter, Leave, ButtonPress, ButtonRelease, Motion, KeyPress, KeyRelease). The bind manual page is the most accurate place to look for a definition of sequence and command and for a general understanding of how the binding mecanism works.",
                               "Items of type curve display pathes of line segments and/or cubic bezier connected by their end points. A cubic Bezier is defined by four points. The first and last ones are the extremities of the cubic Bezier. The second and the third ones are control point (i.e. they must have a third ``coordinate'' with the value 'c'). If both control points are identical, one may be omitted. As a consequence, it is an error to have more than two succcessive control points or to start or finish a curve with a control point.",
                               "The items are arranged in a display list for each group. The display list imposes a total ordering among its items. The group display lists are connected in a tree identical to the group tree and form a hierarchical display list. The items are drawn by traversing the display list from the least visible item to the most visible one.The search to find the item that should receive an event is done in the opposite direction. In this way, items are drawn according to their relative stacking order and events are dispatched to the top-most item at a given location.",
                               "An item will catch an event if all the following conditions are satisfied: * the item -sensitive must be set to true (this is the default). * the item must be under the pointer location. * the item must be on top of the display list (at the pointer location). Beware that an other item with its -visible set to false DOES catch event before any underneath items. * the item must not be clipped (at the pointer location) * the item must not belong to an atomic group, since an atomic group catchs the event instead of the item.",
                               "This command fits a sequence of Bezier segments on the curve described by the vertices in coordList and returns a list of lists describing the points and control points for the generated segments. All the points on the fitted segments will be within error  distance from the given curve. coordList should be either a flat list of an even number of coordinates in x, y order or a list of lists of point coordinates X, Y. The returned list can be directly used to create or change a curve item contour.",
                               "Groups are very powerful items. They have no graphics of their own but are used to bundle items together so that they can be manipulated easily as a whole. Groups can modify in several way how items are displayed and how they react to events. They have many uses in TkZinc. The main usages are to bundle items, to interpose a new coordinate system in a hierarchy of items, to compose some specific attributes, to apply a clipping to their children items, to manage display",
                               "This command returns a boolean telling if the item specified by tagOrId has the specified tag. If more than one item is named by tagOrId, then the topmost in display list order is used to return the result. If no items are named by tagOrId, an error is raised.",
				  ),
                    },
             'e' : {'numpages' : 5,
                    'titles' : ('I', 'J', 'K', 'L', 'M'),
                    'names' : ('ITEM IDS', 'JOINSTYLE ATTRIBUTE', 'K :', 'LOWER COMMAND', 'MAP ITEM :'),
                    'texts' : ("Each item is associated with a unique numerical id which is returned by the add  or clone  commands. All commands on items accept those ids as (often first) parameter in order to uniquely identify on which item they should operate. When an id has been allocated to an item, it is never collected even after the item has been destroyed, in a TkZinc session two items cannot have the same id. This property can be quite useful when used in conjonction with tags, which are described below.",
                               "Specifies the form of the joint between the curve segments. This attribute is only applicable if the curve outline relief is flat. The default value is round.",
                               "No TkZinc KeyWord with K initial letter...",
                               "Reorder all the items given by tagOrId so that they will be under the item given by belowThis. If tagOrId name more than one item, their relative order will be preserved. If tagOrId doesn't name an item, an error is raised. If  belowThis name more than one item, the bottom most them is used. If belowThis  doesn't name an item, an error is raised. If belowThis is omitted the items are put at the bottom most position of their respective groups.",
                               "Map items are typically used for displaying maps on a radar display view. Maps are not be sensitive to mouse or keyboard events, but have been designed to efficiently display large set of points, segments, arcs, and simple texts. A map item is associated to a mapinfo. This mapinfo entity can be either initialized with the videomap  command or more generally created and edited with a set of commands described in the The mapinfo related commands  section.",
                               ),
                    },
             's' : {'numpages' : 8,
                    'titles' : ('N', 'O', 'P' ,'Q' ,'R' ,'S' ,'T' ,'U'),
                    'names' : ('NUMPARTS COMMAND :', 'OVERLAP MANAGER :', 'PICKAPERTURE WIDGET OPTION :', 'Q :',
                               'RENDER WIDGET OPTION :', 'SMOOTH COMMAND', 'TAGS :', 'UNDERLINED ATTRIBUTE :'),
                    'texts' : ("This command tells how many fieldId are available for event bindings or for field configuration commands in the item specified by tagOrId. If more than one item is named by tagOrId, the topmost in display list order is used to return the result. If no items are named by tagOrId, an error is raised. This command returns always 0 for items which do not support fields. The command hasfields  may be used to decide whether an item has fields.",
                               "his option accepts an item id. It specifies if the label overlapping avoidance algorithm should be allowed to do its work on the track labels and which group should be considered to look for tracks. The default is to enable the avoidance algorithm in the root group (id 1). To disable the algorithm this option should be set to 0.",
                               "Specifies the size of an area around the pointer that is used to tell if the pointer is inside an item. This is useful to lessen the precision required when picking graphical elements. This value must be a positive integer. It defaults to 1.",
                               "No TkZinc KeyWord with Q initial letter...",
                               "Specifies whether to use or not the openGL rendering. When True, requires the GLX extension to the X server. Must be defined at widget creation time. This option is readonly and can be used to ask if the widget is drawing with the GLX extension or in plain X (to adapt the application code for example). The default value is false.",
                               "This command computes a sequence of Bezier segments that will smooth the polygon described by the vertices in coordList and returns a list of lists describing thr points and control points for the generated segments. coordList should be either a flat list of an even number of coordinates in x, y order, or a list of lists of point coordinates X, Y. The returned list can be used to create or change the contour of a curve item.",
                               "Apart from an id, an item can be associated with as many symbolic names as it may be needed by an application. Those names are called tags and can be any string which does not form a valid id (an integer). However the following characters may not be used to form a tag: . * ! ( ) & | :. Tags exists, and may be used in commands, even if no item are associated with them. In contrast an item id doesn't exist if its item is no longer around and thus it is illegal to use it.",
                               "Item Text attribute. If true, a thin line will be drawn under the text characters. The default value is false.",
                               ),
                    },
             'w' : {'numpages' : 5,
                    'titles' : ('V', 'W', 'X', 'Y', 'Z'),
                    'names' : ('VERTEXAT COMMAND :', 'WAYPOINT ITEM :', 'X11, OpenGL and Windows :', 'Y...', 'ZINC an advanced scriptable Canvas :'),
                    'texts' : ("Return a list of values describing the vertex and edge closest to the window coordinates x and y in the item described by tagOrId. If  tagOrId describes more than one item, the first item in display list order that supports vertex picking is used. The list consists of the index of the contour containing the returned vertices, the index of the closest vertex and the index of a vertex next to the closest vertex that identify the closest edge (located between the two returned vertices).",
                               "Waypoints items have been initially designed for figuring out typical fixed position objects (i.e. beacons or fixes in the ATC vocabulary) with associated block of texts on a radar display for Air Traffic Control. They supports mouse event handling and interactions. However they may certainly be used by other kinds of radar view or even by other kind of plan view with many geographical objects and associated textual information.",
                               "TkZinc was firstly designed for X11 server. Since the 3.2.2 version, TkZinc also offers as a runtime option, the support for openGL rendering, giving access to features such as antialiasing, transparency, color gradients and even a new, openGL oriented, item type : triangles  . In order to use the openGL features, you need the support of the GLX extension on your X11 server. We also succeeded in using TkZinc with openGL on the Exceed X11 server (running on windows and developped by Hummingbird) with the 3D extension. ",
                               "No TkZinc KeyWord with Y initial letter...",
                               "TkZinc widgets are very similar to Tk Canvases in that they support structured graphics. But unlike the Canvas, TkZinc can structure the items in a hierarchy, has support for affine 2D transforms, clipping can be set for sub-trees of the item hierarchy, the item set is quite more powerful including field specific items for Air Traffic systems and new rendering techniques such as transparency and gradients. If needed, it is also possible to extend the item set in an additionnal dynamic library through the use of a C api.",
                               ),
		       },
             }

#----------------------------------------------------------------------- fin de MAIN

def resetTransfo():
    zinc.raiseitem('move')
    zinc.treset('move')
    zinc.treset(curview)
    
    
#-----------------------------------------------------------------------------------
# Callback sur evt CLICK des items tagés 'divider'
#-----------------------------------------------------------------------------------
def selectDivider (divname = None , numpage = None):
    global curview
    if (divname is None) :
        tags = zinc.itemcget('current', 'tags')
        divname = tags[0]
        numpage = int(tags[2])

    zinc.itemconfigure("(%s && titre)"%(divname), color = '#000099')
    zinc.itemconfigure("(%s && intercalaire)"%(divname), linewidth = 1.4)
    zinc.itemconfigure("(%s && page)"%(divname), visible = 0)

    divgroup = zinc.group("(%s && %s)"%(divname, numpage))
    zinc.raiseitem(divgroup)
    curview = "(%s && %s && content)"%(divname, numpage)
    zinc.itemconfigure("(%s && %s && titre)"%(divname, numpage), color = '#000000')
    zinc.itemconfigure("(%s && %s && intercalaire)"%(divname, numpage), linewidth = 2);
    zinc.itemconfigure("(%s && %s && page)"%(divname, numpage), visible = 1)

    if (divname == 'div2') :
        fontname = tabtables[tabanchor]['names'][numpage]
        explain = tabtables[tabanchor]['texts'][numpage]
        text = "%s\n\n%s"%(fontname, explain)
        zinc.itemconfigure("(%s && fontname)"%(divname),
                           text = text)
        zinc.raiseitem("(%s && fontname)"%(divname))


#-----------------------------------------------------------------------------------
# Callback sur evt CLICK des items tagés 'selector'
#-----------------------------------------------------------------------------------
def clickSelector(btngroup = None , value = None):
    global tabalign
    global tabanchor
    if (btngroup is None and value is None):
        tags = zinc.itemcget('current', 'tags')
        btngroup = tags[0]
        value = tags[1]

    zinc.treset(btngroup)
    zinc.itemconfigure("(%s && btntext)"%(btngroup), color = '#444444')
    zinc.itemconfigure("(%s && %s && btntext)"%(btngroup, value) , color = '#2222bb')
    zinc.translate("(%s && %s)"%(btngroup, value), 0, 1)

    if (value in ('n', 'e', 's', 'w')) :
        tabanchor = value

    elif (value == 'left' or value == 'center' or value == 'right') :
        tabalign = value

    tabtable = tabtables[tabanchor]
    numpages = tabtable['numpages']
    tabparams = { 'radius' : 8,
                  'tabwidth' : 72,
                  'tabheight' : 28,
                  'numpages' : numpages,
                  'anchor' : tabanchor,
                  'alignment' : tabalign,
                  'overlap' : 3,
                  }

    (shapes, tcoords, inverse) = tabbox_coords(((-240, -160), (240, 100)), **tabparams)

    for index in xrange(7, -1, -1):
        divgroup = zinc.group("(div2 && %s && intercalaire)"%(index))
        zinc.itemconfigure(divgroup,
                           visible = (index < numpages))

        if (index >= numpages) :
            zinc.loweritem(divgroup)
        else :
            zinc.raiseitem(divgroup)
            zinc.itemconfigure("(div2 && %s)"%(index),
                               visible = 1)
            zinc.coords("(div2 && %s && intercalaire)"%(index),
                        tuple(shapes[index]))
            if (zinc.type("(div2 && %s && titre)"%(index))) :
                zinc.coords("(div2 && %s && titre)"%(index), tcoords[index])
                zinc.itemconfigure("(div2 && %s && titre)"%(index),
                                   text = tabtable['titles'][index])
    selectDivider('div2', 0)

def setBindings():
    # grab keyboard
    mw.focus()

    # plus,moins : Zoom++, Zoom--
    mw.bind('<plus>', lambda ev: viewZoom('up'))
    mw.bind('<minus>', lambda ev: viewZoom('down'))
    
    # Up, Down, Right, Left : Translate
    mw.bind('<KeyPress-Up>', lambda ev: viewTranslate('up'))
    mw.bind('<KeyPress-Down>', lambda ev: viewTranslate('down'))
    mw.bind('<KeyPress-Left>', lambda ev: viewTranslate('left'))
    mw.bind('<KeyPress-Right>', lambda ev: viewTranslate('right'))

    
    # >, < : Rotate counterclockwise et clockwise
    mw.bind('<greater>', lambda ev: viewRotate('cw'))
    mw.bind('<less>', lambda ev: viewRotate('ccw'))
    
    def printMsg(*arg, **kw):
        for i in arg :
            print "--> %s : %s"%(i, zinc)
        for i,j in kw.items():
            print "%s --> %s"%(i, j)
            
    # Escape : reset transfos
    mw.bind('<Escape>', lambda ev, : resetTransfo())
    
    zinc.bind_tag('divider', '<1>', lambda ev : selectDivider())

    zinc.bind_tag('selector', '<1>', lambda ev : clickSelector())

    zinc.bind_tag('move', '<1>', lambda ev : mobileStart(ev))
    zinc.bind_tag('move', '<B1-Motion>', lambda ev : mobileMove(ev))
    zinc.bind_tag('move', '<ButtonRelease>', lambda ev : mobileStop(ev))
    
    zinc.bind_tag('pushbtn', '<1>', lambda ev : pushButton())
    zinc.bind_tag('pushbtn', '<ButtonRelease>', lambda ev : pullButton())
    
    zinc.bind_tag('poly', '<1>', lambda ev : startRotatePolygone(ev))
    zinc.bind_tag('poly', '<B1-Motion>', lambda ev : rotatePolygone(ev))


#-----------------------------------------------------------------------------------
# Callback sur evt CLICK des items tagés 'pushbtn'
#-----------------------------------------------------------------------------------
def pushButton ():
  tag = zinc.itemcget('current', 'tags')[0]
  if (len(zinc.find('withtag', tag)) > 1
      and not zinc.find('withtag', "(%s && ico)"%(tag))):
      tag = 'current'
  zinc.scale(tag, .975, .975)
  zinc.translate(tag, 1, 1)

  if (zinc.find('withtag', "(%s && ico)"%(tag))) :
      oldcolor = zinc.itemcget("(%s && ico)"%(tag),
                               'fillcolor')
      zinc.itemconfigure('ico',
                         fillcolor = '#000000')

      if (oldcolor == '#000000') :
          newcolor = '#ffff00'
      else :
          newcolor = '#000000'
      zinc.itemconfigure("(%s && ico)"%(tag),
                         fillcolor = newcolor)
  
#-----------------------------------------------------------------------------------
# Callback sur evt RELEASE des items tagés 'pushbtn'
#-----------------------------------------------------------------------------------
def pullButton ():
    tag = zinc.itemcget('current', 'tags')[0]
    zinc.treset(tag)


#-----------------------------------------------------------------------------------
# Callback sur evt CATCH des items tagés 'poly'
# armement de rotation des polygones
#-----------------------------------------------------------------------------------
def startRotatePolygone (ev):
    global previousangle
    (xref, yref) = zinc.transform(zinc.group('current'), 1, (0, 0))
    previousangle = line_angle((ev.x, ev.y), (xref, yref))

#-----------------------------------------------------------------------------------
# Callback sur evt MOTION des items tagés 'poly'
# rotation des polygones
#-----------------------------------------------------------------------------------
def rotatePolygone (ev):
    global previousangle
    tag = zinc.itemcget('current', 'tags')[0]
    (xref, yref) = zinc.transform(zinc.group('current'),
                                  1,
                                  (0, 0))
    newangle = line_angle((ev.x, ev.y),
                          (xref, yref))

    zinc.rotate(tag,
                math.radians(newangle - previousangle))
    previousangle = newangle

#-----------------------------------------------------------------------------------
# Callback CATCH de sélection (début de déplacement) des items tagés 'move'
#-----------------------------------------------------------------------------------
def mobileStart (ev):
    global dx, dy
    (dx, dy) = (0 - ev.x, 0 - ev.y)
    zinc.raiseitem('current')



#-----------------------------------------------------------------------------------
# Callback MOVE de déplacement des items tagés 'move'
#-----------------------------------------------------------------------------------
def mobileMove (ev):
    global dx, dy
    zinc.translate('current',
                   ev.x + dx,
                   ev.y +dy)
    (dx, dy) = (0 - ev.x, 0 - ev.y)


#-----------------------------------------------------------------------------------
# Callback RELEASE de relaché (fin de déplacement) des items tagés 'move'
#-----------------------------------------------------------------------------------
def mobileStop (ev):
    mobileMove(ev)


#-----------------------------------------------------------------------------------
# Callback sur evénément Tk <KeyPress> flèche gauche, haut, droite, bas
# pan (translation) du contenu de la page active (TabBox)
#-----------------------------------------------------------------------------------
def viewTranslate (way):
    if (way == 'left') :
        dx = -10
    elif (way == 'right') :
        dx = 10
    else :
        dx = 0
    if (way == 'up') :
        dy = -10
    elif (way == 'down') :
        dy = 10
    else:
        dy = 0
    
    zinc.translate(curview, dx, dy);

#-----------------------------------------------------------------------------------
# Callback sur evénément Tk <KeyPress> "+" ou "-"
# zoom du contenu de la page active (TabBox)
#-----------------------------------------------------------------------------------
def viewZoom (key) :
    global curview
    if (key == 'up') :
        scaleratio =  1 + zoomfactor
    else :
        scaleratio = 1 - zoomfactor
    
    zinc.scale(curview, scaleratio, scaleratio);



#-----------------------------------------------------------------------------------
# Callback sur evénément Tk <KeyPress> ">" ou "<"
# rotation du contenu de la page active (TabBox)
#-----------------------------------------------------------------------------------
def viewRotate (way) :
    delta_angle = rotate_angle
    if (way == 'cw') :
        delta_angle *= -1 

    zinc.rotate(curview, delta_angle)


# creation de la fenetre principale
mw = Tkinter.Tk()
mw.geometry("700x560+0+0")
mw.title('Test Graphics Module')


# creation du widget Zinc
zinc = Zinc.Zinc(render = 1,
                 width = 700,
                 height = 560,
                 borderwidth = 0,
                 lightangle = 140,
                 backcolor = '#cccccc',)
zinc.pack(fill = 'both', expand = 1)


# initialise les gradients nommés
pictorial.set_gradients(zinc, **gradset)

# création de la vue principale
tgroup = zinc.add('group', 1)
zinc.coords(tgroup, (350, 240))

# consigne globale
zinc.add('text', 1,
         position = (50, 470),
         text = "Global interations :\n<Up>, <Down>, <Left> and <Right> keys move content of TabBox pages\n<Plus> and <Minus> keys zoom out and zoom in this page\n<Greater> and <Less> keys rotate this page\n<Escape> key reset transfos",
         font = font_9b,
         color = '#555555',
         spacing = 2,
        )

# Création des pages d'exemples
(shapes, tcoords, inverse) = tabbox_coords(((-315, -210), (315, 210)),
                                          numpages = 7,
                                          overlap = 2,
                                          radius = 8,
                                          tabheight = 26,
                                          tabwidth = [92, 100 ,82 ,82 ,82 ,120 , 80],
                                          )

# to find some images (used as textures) needed by this demo
texture = pictorial.get_image(zinc, 'paper.gif')
# création des items zinc correspondants
i = len(shapes) - 1
pagenames = ['Rectangle', 'Hippodrome', 'Polygone', 'Polyline', 'PathLine', 'MultiContours', 'TabBox']
pagegroups=[]

lshapes=list(shapes)
lshapes.reverse()
currentcoords=coords2lpts(tcoords)
for shape in  lshapes:
    divgroup = zinc.add('group', tgroup)

    # création de l'intercalaire
    divider = zinc.add('curve',
                       divgroup,
                       lpts2coords(shape),
                       closed = 1,
                       priority = 10,
                       linewidth = 1,
                       linecolor = '#000000',
                       filled = 1,
                       tile = texture,
                       tags = ('div1', 'divider', i, 'intercalaire'),
                     )

    # groupe page clippé
    page = zinc.add('group',
                    divgroup,
                    priority = 100,
                    tags = ('div1', i, 'page'),
                    )
    clip = zinc.add('rectangle',
                    page,
                    ((-300, -170), (300, 195)),
                    linewidth = 1,
                    linecolor = '#000099',
                    filled = 1,
                    fillcolor = '#000000;4',
                    )
    zinc.itemconfigure(page, clip = clip)
    
    pgroup = zinc.add('group', page,
                      tags = ('div1', i, 'content'),
                      )

    pagegroups.append(pgroup)

    currentcoords[i][1] -= 6
    
    
    # titre de l'intercalaire
    zinc.add('text',
             divgroup,
             position = tuple(currentcoords[i]),
             text = pagenames[i],
	     font = font_9b,
	     alignment = 'center',
	     anchor = 'n',
	     color = '#000099',
	     priority = 200,
	     tags = ('div1', 'divider', i, 'titre'),
             )
    i-= 1


# création du contenu des pages
i = 0
pagenames.reverse()
for pagename  in pagenames:
    if ( pagesconf.has_key(pagename)) :
        pagestyle = pagesconf[pagename]
        pgroup = pagegroups[i]
        for ( itemname, itemstyle) in  pagestyle.items() :
            if (itemname == 'consigne') :
                group = zinc.group(pgroup)
            else:
                group = pgroup
            itemstyle['name'] = itemname
            build_zinc_item(zinc, group, **itemstyle)

    i+=1



# initialisation de la TabBox
clickSelector('sel1', 'n')
clickSelector('sel2', 'left')
selectDivider('div1', 0)

# initialisation des bindings
setBindings()


mw.mainloop()


#Local Variables:
#mode : python
#tab'width' : 4
#end:

Added jni/tkzinc/Python/library/Zinc.py.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
#
# Zinc.py -- Python interface to the tkzinc widget.
#
# Authors         : Frederic Lepied, Patrick Lecoanet
# Created Date    : Thu Jul 22 09:36:04 1999
#
# $Id$
#
#
# Copyright (c) 1999 CENA --
#
# See the file "Copyright" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#

__version__  = "$Revision$"
__revision__ = "$Revision$"

from Tkinter import *
import new
import os
import locale, types
import traceback

ZINC_CURRENT_POSITION = -2
ZINC_SPEED_VECTOR     = -3
ZINC_LEADER           = -4
ZINC_CONNECTION       = -5
_LIBLOADED            = 0
_VERSION              = ""
ZINC_NO_PART          = ""

# current part dictionnary
ZINC_DPART = { 'position'      : ZINC_CURRENT_POSITION, 
         'speedvector'   : ZINC_SPEED_VECTOR , 
         'leader'        : ZINC_LEADER, 
         'connection'    : ZINC_CONNECTION}
# notes : 'field' will be return when currentpart is a field 

def havetkzinc( window ):
  '''load Zinc dynamic sharable object library , test if everything is ok
if  ok :return zinc version
if nok : return 0 '''
  global _LIBLOADED
  global _VERSION
  if ( _LIBLOADED == 1 ) : 
    return _VERSION
  try:
    if os.environ.has_key( 'auto_path' ):
      ldir = os.environ['auto_path'].split( ':' )
      ldir.reverse()
      for adir in ldir :
        window.tk.call( 'eval', 
                  "set auto_path "
                  + "[linsert $auto_path 0 %s]" % ( adir ) )
    window.tk.call( 'eval', 'package require Tkzinc' )
    # Call a function from the package to autoload it
    # and verify that all is OK.
    sversion = window.tk.call( 'zinc' ) + " Zinc.py %s" % __version__
  except TclError:
    traceback.print_exc()
    return 0
  _LIBLOADED = 1
  _VERSION = sversion
  return sversion

class ZincException:
  def __call__( self ):
    raise self

  def __init__( self, message ):
    self.message = message
    
  def __str__( self ):
    return self.message

class Zinc( Widget ):
  def __str__( self ):
    return( "Zinc instance" )
  def __init__( self, master = None, cnf = None, **kw ):
    if kw.has_key( 'backward_compatibility' ):
      self.currentpart = self.__oldcurrentpart
      self.configure   = self.__oldconfigure
      self.scale       = self.__oldscale
      self.translate   = self.__oldtranslate
      del kw['backward_compatibility']
      #Pour éviter des effets de bord 
      #si on met comme valeur par défaut de cnf
      #à {} 
    if cnf is None :
      cnf = {}
    if master :
      self.version = havetkzinc( master )
    else:
      master = Frame()
      master.pack()
      self.version = havetkzinc( master )
    Widget.__init__( self, master, 'zinc', cnf, kw )
    self.items = {}
    #BootStrap Root
    classe = eval( 'Group' )
    obj = None
    kw['id'] = 1
    obj = new.instance( classe, kw )
    self.items[1] = obj

  def mainloop( self ):
    """
    Run the events mainloop 
    """
    self.tk.mainloop()
    
  def add( self, itemType, *args, **kw ):
    """
    listTypes = zinc.add()
    id        = zinc.add(type, group)
    id        = zinc.add(type, group, initargs, **options)
    type=[arc|curve|rectangle|triangles|tabular|track|waypoint|group|icon|map|reticle|text|window]
    """
    args = list( args )
    args = args+list( self._options( kw ) )
    try:
      return self.tk.getint( 
        self.tk.call( self._w, 'add', itemType, *args ) )
    except TclError, excpt :
      ZincException( "%s\nType %s\nArgs : %s"%( excpt, itemType, args ) )()
  
  def addtag( self, *args ):
    """
    zinc.addtag(tag, searchSpec)
    This command add the given tag to all items matching
    the search specification.
    If the tag is already present on some item,
    nothing is done for that item.
    The command has no effect if no item satisfy
    the given criteria. The command returns an empty string.
    """
    self.tk.call( self._w, 'addtag', *args )

  def addtag_above( self, newtag, tagOrId ):
    """
    zinc.addtag_above(tag, tagOrId)
    """
    self.addtag( newtag, 'above', tagOrId )

  def addtag_all( self, newtag ):
    """
    A ne plus utiliser
    Utiliser addtag_withtag
    """
    self.addtag( newtag, 'all' )

  def addtag_ancestors( self, newtag, tagOrId, *ltagOrId ):
    """
    zinc.addtag_ancestors(tag, tagOrId, *listTagOrId)
    """
    self.addtag( newtag, 'ancestors', tagOrId, *ltagOrId )

  def addtag_atpriority( self, newtag, pri, tagOrId = 1 ):
    """
    zinc.addtag_atpriority(tag, priority, tagOrId = 1)
    """
    
    self.addtag( newtag, 'atpriority', pri, tagOrId )

  def addtag_below( self, newtag, tagOrId ):
    """
    zinc.addtag_below(tag, tagOrId)
    """
    self.addtag( newtag, 'below', tagOrId )

  def addtag_closest( self, newtag, x, y, halo = None, startItem = 1, recursive = 0 ):
    """
    zinc.addtag_closest(tag, x, y, halo = None, startItem = 1, recursive = 0)
    """
    self.addtag( newtag, 'closest', x, y, halo, startItem, recursive )    

  def addtag_enclosed( self, newtag, x1, y1, x2, y2, inGroup = 1, recursive = 0 ):
    """
    zinc.addtag_enclosed(tag, x1, y1, x2, y2, inGroup = 1, recursive = 0)
    """
    self.addtag( newtag, 'enclosed', x1, y1, x2, y2, inGroup, recursive )   

  def addtag_overlapping( self, newtag, x1, y1, x2, y2, inGroup = 1, recursive = 0 ):
    """
    zinc.addtag_overlapping(tag, x1, y1, x2, y2, inGroup = 1, recursive = 0)
    """
    self.addtag( newtag, 'overlapping', x1, y1, x2, y2, inGroup, recursive )

  def addtag_withtag( self, newtag, tagOrId ):
    """
    zinc.addtag_withtag(tag, tagOrId)
    """
    self.addtag( newtag, 'withtag', tagOrId )

  def addtag_withtype( self, newtag, type, tagOrId = 1 ):
    """
    zinc.addtag_withtype(tag, type, tagOrId = 1)
    """
    self.addtag( newtag, 'withtype', type, tagOrId )

  def anchorxy( self, *args ):
    """
    (x, y) = zinc.anchorxy(tagOrId, anchor)
    """
    return self.tk.call( self._w, 'anchorxy', *args )

  def bbox( self, *args ):
    """
    (xo, yo, xc, yc) = zinc.bbox(tagOrId, ?fieldIndex?)
    """
    return self.tk.call( self._w, 'bbox', *args )

  def becomes( self ):
    """
    zinc.becomes()
    """
    self.tk.call( self._w, 'becomes' )

  def bind_tag( self, tagOrId, sequence = None, func = None, add = None ):
    '''
    return a funcid which can be usefull for unbinding
    listBindings = zinc.bind_tag(tagOrId)
    listbindings = zinc.bind_tag(tagOrId, sequence)
    zinc.bind_tag(tagOrId, sequence, '')
    zinc.bind_tag(tagOrId, sequence, command)
    '''
    return self._bind( ( self._w, 'bind', tagOrId ), 
          sequence, func, add )

  def cget( self, option ):
    """
    val = zinc.cget(option)
    """
    return self.tk.call( self._w, 'cget', '-' + option )

  def chggroup( self, *args ):
    """
    zinc.chggroup(tagOrId, group, ?adjustTransform?)
    """
    self.tk.call( self._w, 'chggroup', *args )

  def clone( self, *args, **kw):
    """
    id = zinc.clone(tagOrId, **attributs)
    """
    args = list( args ) + list( self._options( kw ) )
    return self.tk.call( self._w, 'clone', *args)

  def __oldconfigure( self, **kw ):
    return Widget.configure( self, **kw )
    
  def configure( self, **kw ):
    """
    listOptions = zinc.configurez()
    listOptions = zinc.configurez(option)
    zinc.configurez(**options)
    """
    res  = Widget.configure( self, **kw )
    dico = {}
    if res:
      for i, j in res.items():
        dico[i] = j[3:]
      return dico

  def contour( self, *args ):
    """
    contourNum = zinc.contour(tagOrId)
    contourNum = zinc.contour(tagOrId, operatorAndFlag, coordListOrTagOrId)
    """
    return self.tk.call( self._w, 'contour', *args )

  def coords( self, *args ):
    """
    zinc.coords(tagOrId, contourIndex)
    zinc.coords(tagOrId, contourIndex, coordList)
    zinc.coords(tagOrId, contourIndex, coordIndex)
    zinc.coords(tagOrId, contourIndex, coordIndex, coordList)
    zinc.coords(tagOrId, 'remove', contourIndex, coordIndex)
    zinc.coords(tagOrId, 'add', contourIndex, coordList)
    zinc.coords(tagOrId, 'add', contourIndex, coordIndex, coordList)
    zinc.coords(tagOrId)
    zinc.coords(tagOrId, coordList)
    zinc.coords(tagOrId, 'remove', coordIndex)
    zinc.coords(tagOrId, 'add', coordList)
    """   
    return self.tk.call( self._w, 'coords', *args )

  def __buggyoldcurrentpart( self ):
    '''
    return a string (result from zinc current part function) and an
    integer representing either the number of the field either
    the number of the item part either ZINC_NO_PART   
    '''
    scurrentp = self.tk.call( self._w, 'currentpart' )
    if scurrentp == "":
      rvalue = ZINC_NO_PART
    else:
      try:
        rvalue = locale.atoi( scurrentp )
      except:
        try:
          rvalue = ZINC_DPART[scurrentp]
        except:
          rvalue = ZINC_NO_PART
      else:
        # string to integer succeeded
        scurrentp = "field"
    return( scurrentp, rvalue )
  
  def __oldcurrentpart( self ):
    '''return a string and an integer ;
the string is among "field", "position", "speedvector", "leader", "connection", "",
the number is the number of the part , or the field number in case of "field";
ex: 
no part return '', ZINC_NO_PART
'''
    scurrentp = self.tk.call( self._w, 'currentpart' )
    print "Zinc::__oldcurrentpart scurrentp = [%s]" % scurrentp
    # warning : read this first :
    # return a string among 'position', 'speedvector', 'leader', 'connection' ,''
    #        or an int representing the number of a field label
    # 
    # print "Zinc::currentpart cp=%s  ,type(cp)=%s" % (scurrentp,type(scurrentp))
    if scurrentp == "":
      rvalue = ZINC_NO_PART
    elif type( scurrentp ) == type( 1 ):
      # meaning a field
      # the subtil thing is here ! warning !
      rvalue    = scurrentp
      scurrentp = "field"
    else:
      # scurrentp is a string different from ""
      try:
        rvalue = ZINC_DPART[scurrentp]
      except:
        print "Zinc::currentpart unknown item part" 
        rvalue = ZINC_NO_PART

    return scurrentp, rvalue

  def currentpart( self ):
    '''
    num = zinc.currentpart()
    '''
    return  str( self.tk.call( self._w, 'currentpart' ) )
    

  def cursor( self, *args ):
    """
    zinc.cursor(tagOrId, index)
    """
    self.tk.call( self._w, 'cursor', *args )
    
  def dchars( self, *args ):
    """
    zinc.dchars( tagOrId, first )
    zinc.dchars( tagOrId, first,last )
    """
    self.tk.call( self._w, 'dchars', *args )
    
  def dtag( self, *args ):
    """
    zinc.dtag(tagOrId)
    zinc.dtag(tagOrId, tagToDelete)
    """
    self.tk.call( self._w, 'dtag', *args )

  def find( self, *args ):
    return self._getints( 
      self.tk.call( self._w, 'find', *args ) ) or ()

  def find_above( self, tagOrId ):
    """
    listItems=zinc.find_above(tagOrId)}
    """
    return self.find( 'above', tagOrId )

  def find_all( self ):
    return self.find( 'all' )
  
  def find_ancestors( self, newtag, tagOrId, *tagOrId2 ):
    """
    listItems=zinc.find_ancestor(tag, tagOrId, ?tagOrId2?)
    """
    return self.find( newtag, 'ancestors', tagOrId, *tagOrId2 )

  def find_atpriority( self, pri, *tagOrId ):
    """
    listItems=zinc.find_atpriority(pri, ?tagOrId?)
    """
    return self.find( 'atpriority', pri, *tagOrId )

  def find_below( self, tagOrId ):
    """
    listItems=zinc.find_below(tagOrId)
    """
    return self.find( 'below', tagOrId )

  def find_closest( self, x, y, *options ):
    """
    listItems=zinc.find_closest(x, y, ?halo?, ?startItem?, ?recursive?)
    """
    return self.find( 'closest', x, y, *options )

  def find_enclosed( self, x1, y1, x2, y2 ):
    """
    listItems=zinc.find_enclosed(x1, y1, x2, y2, inGroup=1, recursive=0)
    """
    return self.find( 'enclosed', x1, y1, x2, y2 )

  def find_overlapping( self, x1, y1, x2, y2, *options ):
    """
    listItems=zinc.find_overlapping( x1, y1, x2, y2, ?inGroup?, ?recursive?)
    """
    return self.find( 'overlapping', x1, y1, x2, y2, *options )

  def find_withtag( self, tagOrId ):
    """
    listItems=zinc.find_withtag( tagOrId)
    """
    return self.find( 'withtag', tagOrId )

  def find_withtype( self, type, *tagOrId ):
    """
    listItems=zinc.find_withtype( type, ?tagOrId?)
    """
    return self.find( 'withtype', type, *tagOrId )


  def fit( self, *args ):
    """
    listControls=zinc.fit(coordList,error)
    """
    return self.tk.call( self._w, 'fit', *args )
    
  def focus( self, *args ):
    """
    zinc.focus(tagOrId, ?itemPart?)
    """
    self.tk.call( self._w, 'focus', *args )

  def gdelete( self, *args ):
    """
    zinc.gdelete(gradientName)
    """
    self.tk.call( self._w, 'gdelete', *args )

  def gettags( self, *args ):
    """
    listTags=zinc.gettags(tagorid)
    """
    return self.tk.splitlist( self.tk.call( self._w, 'gettags', *args ) )

  def gname( self, *args ):
    """
    zinc.gname(gradientDesc, gradientName)
    bExist=zinc.gname(gradientName)
    """
    return self.tk.call( self._w, 'gname', *args )
  
  def group( self, *args ):
    """
    group=zinc.group(tagOrId)
    """
    return self.tk.call( self._w, 'group', *args )

  def hasanchors( self, *args ):
    """
    bool=zinc.hasanchors(tagOrId)
    """
    return self.tk.call( self._w, 'hasanchors', *args )

  def hasfields( self, *args ):
    """
    bool=zinc.hasfields(tagOrId)
    """
    return self.tk.call( self._w, 'hasfield', *args )

  def hastag( self, *args ):
    """
    bool=zinc.hastag(tagOrId, tag)
    """
    return self.tk.call( self._w, 'hastag', *args )

  def index( self, *args ):
    """
    num = zinc.index(tagOrId, index)
    """
    return self.tk.call( self._w, 'tagOrId', *args )

  def insert( self, *args ):
    """
    zinc.insert(tagOrId, before, string)
    """
    self.tk.call( self._w, 'insert', *args )

  def itemcget( self, tagOrId, option ):
    """
    val=zinc.itemcget(tagOrId, attr)
    """
    return self.tk.call( self._w, 'itemcget', tagOrId, '-'+option )

  def itemfieldget( self, tagOrId, field, option ):
    """
    val=zinc.itemcget(tagOrId, field, attr)
    """
    return self.tk.call( self._w, 'itemcget', tagOrId, field, '-'+option )

  def itemconfigure( self, tagOrId, field=None, **kw ):
    '''
    either get the dictionnary of possible attributes (if kw is None)
    either allow to set Items attributes or Field attributes
    
    listAttribs=zinc.itemconfigure(tagOrId)
    listAttribs=zinc.itemconfigure(tagOrId, attrib)
    zinc.itemconfigure(tagOrId, **attributs)
    listAttribs=zinc.itemconfigure(tagOrId, fieldIs, attrib)
    zinc.itemconfigure(TagOrId,fieldId,**attributs)
    '''
    if not kw:
      cnf = {}
      for var_x in self.tk.split( 
        field != None and self.tk.call( self._w, 'itemconfigure', 
                          ( tagOrId, field ) ) or
        self.tk.call( self._w, 'itemconfigure', ( tagOrId, ) ) ):
        cnf[var_x[0][1:]] = ( var_x[0][1:], ) + var_x[1:]
      return cnf
    if field != None:
      args = ( tagOrId, str( field ), )+ self._options( {}, kw )
      self.tk.call( self._w, 'itemconfigure', *args )
    else:
      args = ( tagOrId, ) + self._options( {}, kw )
      self.tk.call( self._w, 'itemconfigure', *args )

  # _dp voir si cette instruction est a execute ici
  # permet de creer un synonyme de itemconfigure
  itemconfig = itemconfigure

  def loweritem( self, *args ):
    """
    zinc.loweritem(tagOrId)
    zinc.loweritem(tagOrId, belowThis)
    Reorder all the items given by tagOrId so that
    they will be under the item given by belowThis.
    If tagOrId name more than one item,
    their relative order will be preserved.
    If tagOrId doesn't name an item, an error is raised.
    If  belowThis name more than one item, the bottom most them is used.
    If belowThis  doesn't name an item, an error is raised.
    If belowThis is omitted the items are put
    at the bottom most position of their respective groups.
    The command ignore all items named by tagOrId
    that are not in the same group than belowThis or,
    if not specified, in the same group than the first item
    named by tagOrId. The command returns an empty string.
    As a side affect of this command, the -priority  attribute
    of all the reordered items is ajusted to match the priority
    of the  belowThis item (or the priority of the bottom most item)
    """
    self.tk.call( self._w, 'lower', *args )

  def monitor( self, *args ):
    """
    bool = zinc.monitor()
    zinc.monitor(bool)
    """
    return self.tk.call( self._w, 'monitor', *args )

  def numparts( self, *args ):
    """
    num = zinc.numparts(tagOrId)
    """
    return self.tk.call( self._w, 'numparts', *args )

  def postcript( self, *args ):
    """
    Not Yet Implemented
    zinc.postscript()
    """
    return self.tk.call( self._w, 'postscript', *args )

  def raiseitem( self, *args ):
    """
    Correspond à l'appel raise de la documentation
    le mot raise est reservé en python
    zinc.raiseitem(tagOrId)
    zinc.raiseitem(tagOrId, aboveThis)
    """
    self.tk.call( self._w, 'raise', *args )

  def remove( self, *args ):
    """
    zinc.remove(tagOrId, ?tagOrId,...?)
    """
    self.tk.call( self._w, 'remove', *args )
  
  def rotate( self, *args ):
    """
    zinc.rotate(tagOrId, angle)
    zinc.rotate(tagOrId, angle, centerX, centerY)
    """
    self.tk.call( self._w, 'rotate', *args )

  def __oldscale( self, xFactor=None, yFactor=None, tagOrId=None ):
    if yFactor == None:
      return self.tk.getdouble( self.tk.call( 'scale' ) )
    else:
      if tagOrId == None:
        self.tk.call( self._w, 'scale', xFactor, yFactor )
      else:
        self.tk.call( self._w, 'scale', tagOrId, xFactor, yFactor )

  def scale( self, *args ):
    """
    zinc.scale(tagOrIdOrTName, xFactor, yFactor)
    zinc.scale(tagOrIdOrTName, xFactor, yFactor, centerX, centerY)
    Add a scale factor to the items or the transform described
    by tagOrId.
    If  tagOrId describes a named transform then this transform
    is used to do the operation. If tagOrId describes more than
    one item then all the items are affected by the operation.
    If tagOrId describes neither a named transform nor an item,
    an error is raised.
    A separate factor is specified for X and Y.
    The optional parameters describe the center of scaling,
    which defaults to the origin.
    """
    if not len( args ):
      return self.tk.getdouble( self.tk.call( self._w, 'scale' ) )
    else:
      self.tk.call( self._w, 'scale', *args )
        
  def select( self, *args ):
    """
    zinc.select('adjust', tagOrId, index)
    Adjust the end of the selection in tagOrId
    that is nearest to the character given by index so
    that it is at index.
    The other end of the selection is made the anchor
    for future select to commands.
    If the selection is not currently in tagOrId,
    this command behaves as the select to command.
    The command returns an empty string.
    zinc.select('clear')
    Clear the selection if it is in the widget.
    If the selection is not in the widget,
    the command has no effect. Return an empty string.
    zinc.select('from', tagOrId, index)
    Set the selection anchor point for the widget
    to be just before the character given by index
    in the item described by tagOrId.
    The command has no effect on the selection,
    it sets one end of the selection so that future
    select to can actually set the selection.
    The command returns an empty string.
    (item,part) = zinc.select('item')
    Returns a list of two elements.
    The first is the id of the selected item
    if the selection is in an item on this widget;
    Otherwise the first element is an empty string.
    The second element is the part of the item
    (track, waypoint or tabular item only) or the empty string.
    zinc.select('to', tagOrId, index)
    Set the selection to be the characters that lies
    between the selection anchor and  index in the item described
    by tagOrId. The selection includes the character given
    by index and includes the character given by the anchor point
    if  index is greater or equal to the anchor point.
    The anchor point is set by the most recent select adjust
    or select from command issued for this widget.
    If the selection anchor point for the widget is not currently
    in tagOrId, it is set to the character given by index.
    The command returns an empty string.
    Manipulates the selection as requested by option.
    tagOrId describes the target item.
    This item must support text indexing and selection. I
    f more than one item is referred to by tagOrId,
    the first in display list order that support both text
    indexing and selection will be used.
    Some forms of the command include an index  parameter,
    this parameter describes a textual position within the
    item and should be a valid index as described in
    Text indices.
    """
    return self.tk.call( self._w, 'select', *args )

  def skew( self, *args ):
    """
    zinc.skew(tagOrIdOrTName,xSkewAngle, ySkewAngle)
    Add a skew (or shear) transform to the to the items
    or the transform described by tagOrIdOrTName.
    If tagOrId describes a named transform then this transform
    is used to do the operation.
    If tagOrId describes more than one item then all the
    items are affected by the operation.
    If tagOrId describes neither a named transform nor an item,
    an error is raised. The angles are given in radian.
    """
    return self.tk.call( self._w, 'skew', *args )

  def smooth( self, *args ):
    """
    zinc.smooth(coordList)
    This command computes a sequence of segments
    that will smooth the polygon described by the vertices
    in coordList and returns a list of lists describing points
    of the generated segments. These segments are approximating
    a Bezier curve. coordList should be either a flat list
    of an even number of coordinates in x, y order, or a list
    of lists of point coordinates X, Y.
    The returned list can be used to create or change the contour
    of a curve item.
    """
    return self.tk.call( self._w, 'smooth', *args )

  def tapply( self, *args ):
    """
    Not Yet Implemented
    zinc.tapply()
    """
    return self.tk.call( self._w, 'tapply', *args )

  def tcompose( self, *args ):
    """
    zinc.tcompose(tagOrIdOrTName, tName)
    zinc.tcompose(tagOrIdOrTName, tName, invert)
    """
    return self.tk.call( self._w, 'tapply', *args )

  def tdelete( self, *args ):
    """
    zinc.tdelete(tName)
    Destroy a named transform.
    If the given name is not found among the named transforms,
    an error is raised.
    """
    self.tk.call( self._w, 'tdelete', *args )
  
  def transform( self, *args ):
    """
    listCoords=zinc.transform(tagOrIdTo, coordList)
    listCoords=zinc.transform(tagOrIdFrom, tagOrIdTo, coordList)
    This command returns a list of coordinates obtained by transforming the coordinates given in coordList
    from the coordinate space of the transform or item described by tagOrIdFrom to the coordinate space
    of the transform or item described by  tagOrIdTo.
    If tagOrIdFrom is omitted it defaults to the window coordinate space.
    If either tagOrIdFrom or tagOrIdTo describes more than one item,
    the topmost in display list order is used. If either tagOrIdFrom or tagOrIdTo
    doesn't describe either a transform or an item, an error is raised.
    The coordList should either be a flat list containing an even number of coordinates
    each point having two coordinates, or a list of lists each sublist of the form [ X Y ?pointtype? ].
    The returned coordinates list will be isomorphic to the list given as argument. 

    It is possible to convert from window coordinate space to the coordinate space of any item.
    This is done by omitting ?tagOrIdFrom? and specifying in tagOrIdTo, the id of the item.
    It can also be done by using the predefined tag 'device' as first argument. 

    It is also possible to convert from the coordinate space of an item to the window coordinate
    space by using the predefined tag 'device' as second argument. 

    """
    return self._getdoubles( self.tk.call( self._w, 'transform', *args ) )

#ANCIENNE IMPLEMENTATION
  def __oldtranslate( self, dx=None, dy=None, tagOrId=None ):   
    if dx == None:
      return self._getints( self.tk.call( 'translate' ) )
    else:
      if tagOrId == None:
        self.tk.call( self._w, 'translate', dx, dy )
      else:
        self.tk.call( self._w, 'translate', tagOrId, dx, dy )

  def translate( self, *args ):
    """
    zinc.translate(tagOrIdOrTName, xAmount, yAmount)
    zinc.translate(tagOrIdOrTName, xAmount, yAmount, absolute)
    Add a translation to the items or the transform described by tagOrIdOrTName.
    If  tagOrIdOrTName describes a named transform then this transform is used
    to do the operation.
    If tagOrIdOrTName describes more than one item then all the items are affected
    by the opration.
    If tagOrIdOrTName describes neither a named transform nor an item,
    an error is raised. A separate value is specified for X and Y.
    If the optionnal ?absolute? parameter is true,
    it will set an absolute translation to the tagOrIdOrTName
    """
    if ( len( args ) == 1 ):
      return self._getints( self.tk.call( self._w, 'translate' ) )
    else:
      self.tk.call( self._w, 'translate', *args )

  def treset( self, *args ):
    """
    zinc.treset(tagOrIdOrTName)
    Set the named transform or the transform for the items described by tagOrIdOrTName
    to identity. If tagOrIdOrTName describes neither a named transform nor an item,
    an error is raised.
    """
    self.tk.call( self._w, 'treset', *args )
  
  def trestore( self, *args ):
    """
    zinc.trestore(tagOrId, tName)
    Set the transform for the items described by tagOrId to the transform named by tName.
    If tagOrId doesn't describe any item or if the transform named  tName doesn't exist,
    an error is raised.
    """
    self.tk.call( self._w, 'trestore', *args )
  
  def tsave( self, *args ):
    """
    zinc.tsave(tName)
    zinc.tsave(tagOrIdOrTName, tName)
    zinc.tsave(tagOrIdOrTName, tName, invert)
    Create (or reset) a transform associated with the name tName
    with initial value the transform associated with the item tagOrIdOrTName.
    If tagOrIdOrTName describes more than one item, the topmost in display list order is used.
    If tagOrIdOrTName doesn't describe any item or named transformation, an error is raised.
    If tName already exists, the transform is set to the new value.
    This command is the only way to create a named transform.
    If tagOrIdOrTName is not specified, the command returns a boolean telling
    if the name is already in use.
    The invert boolean, if specified, cause the transform to be inverted prior to be saved. 

    It is possible to create a new named transformation from the identity
    by using the predefined tag 'identity': $zinc->tsave('identity', 'myTransfo'); 
    """
    return self.tk.call( self._w, 'tsave', *args )

  def tget( self, *args ):
    """
    zinc.tget(tagOrId)
    zinc.tget(tagOrIdOrTName, selector)
    selector:={'all'|'translation'|'scale'|'rotation'|'skew'}
    With only one argument, get the six elements of the 3x4 matrix
    used in affine transformation for tagOrIdOrTName.
    The result is compatible with the tset method.
    With optional second parameter 'all' returns the transform
    decomposed in translation, scale, rotation, skew
    and return the list in this order,
    With 'translation', 'scale', 'rotation', 'skew' optional
    second parameter, returns the corresponding values.
    """
    return self.tk.call( self._w, 'tget', *args )
    
  def tset( self, *args ):
    """
    zinc.tset(tagOrIdOrName, m00, m01, m10, m11, m20, m21)
    Set the six elements of the 3x4 matrix used in affine transformation for tagOrIdOrTName.
    BEWARE that depending on mij values,
    it is possible to define a not inversible matrix which will end up in core dump.
    This method must BE USED CAUTIOUSLY.
    """
    return self.tk.call( self._w, 'tset', *args )

  def type( self, tagOrId ):
    """
    name=zinc.type(tagOrId)
    If more than one item is named by tagOrId,
    then the type of the topmost item in display list order is returned.
    If no items are named by tagOrId, an error is raised.
    """
    return self.tk.call( self._w, 'type', tagOrId )

  def vertexat( self, *args ):
    """
    (contour,vertex,edgevertex)=zinc.vertexat(tagOrId,x,y)
    """
    return self.tk.call( self._w, 'vertexat', *args )

  def xview(self, *args):
      """Query and change horizontal position of the view."""
      if not args:
          return self._getdoubles(self.tk.call(self._w, 'xview'))
      self.tk.call((self._w, 'xview') + args)
  def xview_moveto(self, fraction):
      """Adjusts the view in the window so that FRACTION of the
      total width of the canvas is off-screen to the left."""
      self.tk.call(self._w, 'xview', 'moveto', fraction)
  def xview_scroll(self, number, what):
      """Shift the x-view according to NUMBER which is measured in "units" or "pages" (WHAT)."""
      self.tk.call(self._w, 'xview', 'scroll', number, what)
  def yview(self, *args):
      """Query and change vertical position of the view."""
      if not args:
          return self._getdoubles(self.tk.call(self._w, 'yview'))
      self.tk.call((self._w, 'yview') + args)
  def yview_moveto(self, fraction):
      """Adjusts the view in the window so that FRACTION of the
      total height of the canvas is off-screen to the top."""
      self.tk.call(self._w, 'yview', 'moveto', fraction)
  def yview_scroll(self, number, what):
      """Shift the y-view according to NUMBER which is measured in "units" or "pages" (WHAT)."""
      self.tk.call(self._w, 'yview', 'scroll', number, what)

class ZincItem:
  def __init__( self, zinc, itemType, group = 1, *args, **kw ):
    self.zinc  = zinc
    texture    = None
    fillpatern = None
    scale      = None
    translate  = None
    if kw.has_key( 'texture' ):
      texture = kw['texture']
      del kw['texture']

    if kw.has_key( 'fillpatern' ):
      fillpastern = kw['fillpatern']
      del kw['fillpatern']

    if kw.has_key( 'scale' ):
      scale = kw['scale']
      del kw['scale']

    if kw.has_key( 'rotate' ):
      rotate = kw['rotate']
      del kw['rotate']

    if kw.has_key( 'translate' ):
      translate = kw['translate']
      del kw['translate']
      
    if kw.has_key( 'cloneid' ):
      cloneid = kw['cloneid']
      del kw['cloneid']
    else:
      cloneid = 0 
    group = str( group )
    #        sys.stdout.flush()
    if cloneid == 0 :
      self.id = zinc.add( itemType, group, *args, **kw )
    else :
      self.id = self.zinc.clone(cloneid, *args, **kw)

    zinc.items[self.id] = self
    texture = None
    if fillpatern:
      self.itemconfigure( fillpatern )
    if scale:
      self.scale( scale )     
    if translate:
      self.translate( translate )
    
    
  def __str__( self ):
    return str( self.id )

  def __repr__( self ):
    return str( self.id )

  def bbox( self, *args ):
    return self.zinc.bbox( self.id, *args )
  
  def clone( self, *args, **kw):
    '''id = zincitem.clone(*args,**kw) '''
    # print "ZincItem::clone"
        # on cherche tagOrId
    # nidcloned = self.find_above(tagOrId)
    sclonedtype = self.type()
    sclonedgroupid = self.zinc.group(self.id)

    # ajout cle 'cloneid' (voir ZincItem::__init__) 
    kw['cloneid'] = self.id
        # on cree un nouveau ZincItem meme type,
    return(ZincItem(self.zinc, sclonedtype, sclonedgroupid, **kw ))
  
  def delete( self ):
    del self.zinc.items[self.id]
    try:
      self.zinc.remove( self.id )
    except:
      pass
  def __getitem__( self, key ):
    '''allow to get attribute by self["key"] '''
    if ( key == "coords" ):
      return self.zinc.coords( self.id )
    return self.zinc.itemcget( self.id, key )

  def __setitem__( self, key, value ):
    '''allow to set item attrbutes, eg. for a track position attributes
    just writing :
    a = ZincItem(myzinc, ...)
    a["position"]    = (x,y)
    Notes : when setting multiple attributes
    using itemconfigure is more efficient '''
    if ( key is "coords" ):
      self.zinc.coords( self.id, value )
    else:
      self.zinc.itemconfigure( self.id, **{key:value} )
      
  def getGroup( self ):
    groupid = self.zinc.group( self.id )
    return self.zinc.items[groupid]
    
  def keys( self ):
    if not hasattr( self, '_keys' ):
      self._keys = {}
      config = self.zinc.itemconfig( self.id )
      for x in config.keys():
        self._keys[x] = config[x][1]
    return self._keys

  def has_key( self, key ):
    return key in self.keys()

  def bind( self, sequence=None, command=None, add=None ):
    '''return a funcid which can be used to unbind
notes: unbinding can be done by bind("<seq>","") or using native tkinter
unbind method '''
    return( self.zinc.bind_tag( self.id, sequence, command, add ) )
    
  def cget( self, attr ):
    return self.zinc.itemcget( self.id, attr )
       
  def coords( self, *args, **kw ):
    return self.zinc.coords( self.id, *args, **kw )

  def fieldcget( self, field, attr ):
    return self.zinc.itemfieldcget( self.id, field, attr )

  def itemconfigure( self, field=None, **kw ):
    self.zinc.itemconfigure( self.id, field, **kw )

  def rotate( self, *args ):
    return self.zinc.rotate( self.id, *args )
  
  def scale( self, *args ):
    return self.zinc.scale( self.id, *args )

  def transforms( self, *args ):
    """
    zincitem.transform(tozincitem, coordList)
    This command returns a list of coordinates obtained by transforming the coordinates given in coordList
    from the coordinate space of item to the coordinate space
    of the tozincitem item.
    The coordList should either be a flat list containing an even number of coordinates
    each point having two coordinates, or a list of lists each sublist of the form [ X Y ?pointtype? ].
    The returned coordinates list will be isomorphic to the list given as argument. 
    """
    return self.zinc.transforms( self.id, *args )

  def translate( self, *args ):
    """
    zincitem.translate( xAmount, yAmount)
    zincitem.translate( xAmount, yAmount, absolute)
    Add a translation to the item.
    A separate value is specified for X and Y.
    If the optionnal ?absolute? parameter is true,
    it will set an absolute translation to the item   
    """
    self.zinc.translate( self.id, *args )

  def tset( self, *args ):
    """
    zincitemtset(m00, m01, m10, m11, m20, m21)
    Set the six elements of the 3x4 matrix used in affine transformation.
    BEWARE that depending on mij values,
    it is possible to define a not inversible matrix which will end up in core dump.
    This method must BE USED CAUTIOUSLY.     
    """
    self.zinc.tset( self.id, *args )

  def type( self ):
    """
    name=zincitemtype()
    This command returns the type of the item.
    """
    return self.zinc.type( self.id )

  def tsave( self, *args ):
    """
    zincitemtsave( tName)
    zincitemtsave( tName, invert)
    Create a transform associated with the name tName
    with initial value the transform associated with the item.
    If tName already exists, the transform is set to the new value.
    This command is the only way to create a named transform.
    The invert boolean, if specified, cause the transform to be inverted prior to be saved. 
    """
    return self.zinc.tsave( self.id, *args )

  def treset( self, *args ):
    """
    zincitemtreset()
    Set the named transform or the transform for the item
    to identity. If there are no named transform,
    an error is raised.
    """
    self.zinc.treset( self.id, *args )
    
  def trestore( self, *args ):
    """
    zincitemtrestore( tName)
    Set the transform for the item to the transform named by tName.
    If the transform named  tName doesn't exist, an error is raised.
    """
    self.zinc.trestore( self.id, *args )
    
  def tget( self, *args ):
    """
    zincitemtget()
    zincitemtget(selector)
    selector:={'all'|'translation'|'scale'|'rotation'|'skew'}
    With only one argument, get the six elements of the 3x4 matrix
    used in affine transformation.
    The result is compatible with the tset method.
    With optional second parameter 'all' returns the transform
    decomposed in translation, scale, rotation, skew
    and return the list in this order,
    With 'translation', 'scale', 'rotation', 'skew' optional
    second parameter, returns the corresponding values.
    """   
    return self.zinc.tget( self.id, *args )


class Arc( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        The arc type expects a list of four floating point numbers xo yo xc yc,
        giving the coordinates of the origin and the corner of the enclosing rectangle.
        The origin should be the top left vertex of the enclosing rectangle and the corner
        the bottom right vertex of the rectangle.
        """
        ZincItem.__init__( self, zinc, 'arc', *args, **kw )    

class Group( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        These type do not expect type specific arguments.
        """
        ZincItem.__init__( self, zinc, 'group', *args, **kw )    

    def getGroup( self ):
        """Retourne l'objet de type Group
        auquel est attache l'item"""
        ###Gestion du boostrap
        if self.id == 1:
            return self.zinc.items[1]
        else:
            return ZincItem.getGroup( self )

  #TODO: Extension. Renvoie les références aux ZincItems contenus dans le Groupe
    def getNode( self ):
        """
        """
        pass
            
class Icon( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        These type do not expect type specific arguments.
        """
        ZincItem.__init__( self, zinc, 'icon', *args, **kw )    

class Map( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        These type do not expect type specific arguments.
        """
        ZincItem.__init__( self, zinc, 'map', *args, **kw )
  
class Curve( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        The curve type expects either a flat list or a list of lists.
        In the first case, the flat list must be a list of floating point numbers
        x0 y0 x1 y1 ... xn yn, giving the coordinates of the curve vertices.
        The number of values should be even (or the last value will be discarded)
        but the list can be empty to build an empty invisible curve.
        In the second case,thelist must contain lists of 2 or 3 elements:
        xi, yi and and an optionnal point type. Currently,
        the only available point type is 'c' for a cubic bezier control point.
        For example, the following list is an example of 2 beziers segments
        with a straight segment in-between:
        ( [x0, y0], [x1, y1, 'c'], [x2, y2, 'c'], [x3, y3], [x4, y4, 'c'], [x5, y5] )
        
        As there is only on control point, [x4, y4, 'c'] ,
        for the second cubic bezier,
        the omitted second control point will be defaulted to the same point.
        a named tuple contours can give to define new contours in curve.
        contours=(<contour1>,...)
        <contour>=(<point1>,...)
        A curve can be defined later with the contour or coords commands.
        As a side effect of the curve behavior,
        a one vertex curve is essentially the same as an empty curve,
        it only waste some more memory.
        
        """
        contours = []
        if kw.has_key( 'contours' ):
            contours = kw['contours']
            del kw['contours']
        ZincItem.__init__( self, zinc, 'curve', *args, **kw )
        for contour in contours:
            self.zinc.contour( self.id, *contour )
    

class Rectangle( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        The rectangle type expects a list of four floating point numbers xo yo xc yc,
        giving the coordinates of the origin and the corner of the rectangle.
        """
        ZincItem.__init__( self, zinc, 'rectangle', *args, **kw )    

class Reticle( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        These type do not expect type specific arguments.
        """
        ZincItem.__init__( self, zinc, 'reticle', *args, **kw )    

class Tabular( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        ZincItem.__init__( self, zinc, 'tabular', *args, **kw )    

class Text( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        """
        These type do not expect type specific arguments.
        """
        ZincItem.__init__( self, zinc, 'text', *args, **kw )    

class Track( ZincItem ):
    def __init__( self, zinc, *args, **kw ):
        ZincItem.__init__( self, zinc, 'track', *args, **kw )
  
class WayPoint( ZincItem ):
  def __init__( self, zinc, *args, **kw ):
    ZincItem.__init__( self, zinc, 'waypoint', *args, **kw )
  

# Class to hold mapinfos used by the Map Item class 
class Mapinfo:
    def __init__( self, interp, name = None ):
        """
        @type name: string
        @param name: Name of mapinfo. Must be used carrefully !
        Create a new empty map description.
        The new mapinfo object named name or internal id if name is omitted
        """
        if name :
            self.name = name
        else:
            self.name = `id( self )`
            self.interp = interp.tk
            apply( self.interp.call, ( 'mapinfo', self.name, 'create' ) )
    
    def __repr__( self ):
        return self.name

    def __del__( self ):
        self.delete()

    def delete( self ):
        """
        Delete the mapinfo object.
        All maps that refer to the deleted mapinfo are updated to reflect the change.
        """
        self.interp.call( 'mapinfo', self.name, 'delete' )


    def duplicate( self, *args ):
        """
        B{Optional}
        @type name: Name of the new mapinfo
        @param name: Must be use carrefully !!
        Create a new mapinfo that is a exact copy of this mapinfo Object.
        """
        classe = Mapinfo
        obj = new.instance( classe )
        if len( args ):
            new_name = args[0]
        else:
            new_name = str( obj )
        self.interp.call( 'mapinfo', self.name, 'duplicate', new_name )
        return obj
    
    def add_text( self, text_style, line_style, x, y, text ):
        """
        Add a new graphical element to the mapinfo object text. 
        This element describes a line of text.
        @type text_style: {normal|underlined}
        @param text_style: text style 
        @type line_style: string
        @param line_style: a line style (simple, dashed,  dotted, mixed, marked) to be used for the underline
        @type X: int
        @param X: Coord on X axe
        @type Y: int
        @param Y: Coord on Y axe
        @type text: string
        @param : a string describing the text.
    
        """
        self.interp.call( 'mapinfo', self.name, 'add', 'text', text_style, 
                         line_style, x, y, text )

    def add_line( self, line_style, width, x1, y1, x2, y2 ):
        """
        Add a new graphical element to the mapinfo object line.
        This element describes a line segment.
        @type line_style: {simple|dashed|dotted|mixed|marked}
        @param line_style: a line style
        @type width: int
        @param width: the line width in pixels
        @type x1: int
        @param x1: coords on X axe
        @type x2: int
        @param x2: coords on Y axe
        @type x3: int
        @param x3:  end vertices on X axe
        @type x4: int
        @param x4: end vertices on Y axe
        four integer values setting the X and Y coordinates of the two end vertices.
        """
        self.interp.call( 'mapinfo', self.name, 'add', 'line', line_style, 
                         width, x1, y1, x2, y2 )

    def add_arc( self, line_style, width, cx, cy, radius, start, extent ):
        """
        Add a new graphical element to the mapinfo object arc.
        
        @type line_style: {simple|dashed|dotted|mixed|marked}
        @param line_style: a line style
        @type width: int 
        @param width: the line width in pixels
        @type cx: int
        @param cx: X of arc center
        @type cy: int 
        @param cy: Y of arc center
        @type radius: int 
        @param radius: the arc radius
        @type start: int
        @param start: the start angle (in degree)
        @type extent: int
        @param extent: the angular extent of the arc (in degree).
        
        """
        self.interp.call( 'mapinfo', self.name, 'add', 'arc', line_style, 
                         width, cx, cy, radius, start, extent )
        
    def add_symbol( self, x, y, index ):
        """
        Add a new graphical element to the mapinfo object symbol.
        @type x: int
        @param x: position on X
        @type y: int
        @param y: position on Y
        
        @type index: int
        @param : an integer setting the symbol index in the -symbols list of the map item
        
        """
        self.interp.call( 'mapinfo', self.name, 'add', 'symbol', x, y, index )
    
    def count( self, type ):
        """
        @type type: {text|arc|line|symbol}
        @param type:
        Return an integer value that is the number of elements matching type in the mapinfo.
        type may be one the legal element types   
        """
        return self.interp.call( 'mapinfo', self.name, 'count', type )
    
    def get( self, type, index ):
        """
        Return the parameters of the element at index with type type in the mapinfo.
        The returned value is a list.
        The exact number of parameters in the list and their meaning depend on type and is accurately described in mapinfo add.
        type may be one the legal element types as described in the mapinfo add command.
        Indices are zero based and elements are listed by type.
        """
        return self.interp.call( 'mapinfo', self.name, 'remove', type, index )

    def replace( self, type, index, *args ):
        """
        Replace all parameters for the element at index with type type in the mapinfo.
        The exact number and content for args depend on  type and is accurately described in mapinfo add.
        type may be one the legal element types as described in the mapinfo add command.
        Indices are zero based and elements are listed by type.
        """
        return self.interp.call( 'mapinfo', self.name, 'replace', 
                 type, index, args )

    def remove( self, type, index ):
        """
        Remove the element at index with type type in the mapinfo.
        type may be one the legal element types as described in the mapinfo add command. Indices are zero based and elements are listed by type.
        """
        return self.interp.call( 'mapinfo', self.name, 'remove', type, index )
    
    def scale( self, factor ):
        """
        """
        self.interp.call( 'mapinfo', self.name, 'scale', factor )
        
    def translate( self, xAmount, yAmount ):
        """
        """
        self.interp.call( 'mapinfo', self.name, 'translate', xAmount, yAmount )
    
class Videomap ( Mapinfo ):
    """
    create a mapinfo from a proprietary
    file format for simple maps, in use in french Air Traffic Control Centres. The format is the
    binary cautra4 (with x and y in 1/8nm units) 
    """
    def __init__( self, tk, *args ):
        """
        @type  filename: 
        @param filename:
        @type  mapinfoname: 
        @param mapinfoname: 
        Load the videomap sub-map located at position index in the file named  fileName into a mapinfo object named mapInfoName. It is possible, if needed, to use the videomap ids command to help translate a sub-map id into a sub-map file index.
        """
        self.tk = tk.tk
        args    = args + ( self, )
        self.tk.call( 'videomap', 'load', *args )
        

    def ids( self, filename ):
        """
        @type  filename: string
        @param filename: filename where to search syb-map
        B{Class Method}
        Return all sub-map ids that are described in the videomap file described by  fileName.
        The ids are listed in file order. This command makes possible to iterate through a videomap file
        one sub-map at a time, to know how much sub-maps are there and to sort them according to their ids.
        """
        return self.tk.call( 'videomap', 'ids', filename )

class Colors:
  """
  Classe abstraite utilitaire permettant de gérer sous forme d'objet
  les couleurs aux formats Zinc
  """
  def __init__( self ):
    self.lColors = []
  
  #TODO:
  def getColorsIter( self ):
    """
    Renvoie un itérateur sur les couleurs
    """
    return self.lColors.__iter__()
    
    def addColor( self, color, alpha = 100, 
           colorposition = 0, mid_span_position = 50 ):
      self.lColors.append( ( color, alpha, colorposition, mid_span_position ) )

  def __repr__( self ):
    res = ""
    for i in self.lColors:
      res = "%s%s;%s %s %s|" % ( res, i[0], i[1], i[2], i[3] )
    return res[:-1]
    
class AxialGradientColor( Colors ):
    def __init__( self, *params ):
        """
        params : degre or  x1, y1, x2, y2 which define angle and extension of the axe
        =axial degre | gradient_step1 | ... | gradient_stepn or
        =axial x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn
        """
        Colors.__init__( self )
        count = 0
        self.params = ""
        for i in params:
            self.params = "%s %s" % ( self.params, str( i ) )
            count += 1
        if ( count != 1 ) and ( count != 4 ):
            raise Exception( "Bad Format of params %s" % count )
        
    def __repr__( self ):
        res = "=axial %s" % self.params
        if not ( len( self.lColors ) ):
            raise Exception( "Bad Format, must have  one color less" )
        res = "%s | %s" % ( res, Colors.__repr__( self ) )
        return res
                
class RadialGradientColor( Colors ):
    def __init__( self, *params ):
        """
        =radial x y | gradient_step1 | ... | gradient_stepn  or
        =radial x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn
        The x y parameters define the center of the radial.
        The x1 y1 x2 y2 parameters define both the center and the extension of the radial.
        """
        Colors.__init__( self )
        count = 0
        self.params = ""
        for i in params:
            self.params = "%s %s" % ( self.params, str( i ) )
            count += 1
        if ( ( count!= 2 ) and ( count != 4 ) ):
            raise Exception( "Bad Format of params %s"%count )
        
    def __repr__( self ):
        res = "=radial %s " % self.params
        if not ( len( self.lColors ) ):
            raise Exception( "Bad Format, must have  one color less" )
        res = "%s | %s" % ( res, Colors.__repr__( self ) )
        return res

class PathGradientColor( Colors ):
    def __init__( self, *params ):
        """
    =path x y | gradient_step1 | ... | gradient_stepn
    The x y parameters define the center of the gradient. 
        """
        Colors.__init__( self )
        count       = 0
        self.params = ""
        for i in params:
            self.params = "%s %s" % ( self.params, str( i ) )
            count += 1
        if ( count != 2 ):
            raise Exception( "Bad Format of params %s" % count )
        
    def __repr__( self ):
        res = "=path %s " % self.params
        if not ( len( self.lColors ) ):
            raise Exception( "Bad Format, must have  one color less" )
        res = "%s | %s" % ( res, Colors.__repr__( self ) )
        return res

class ConicalGradientColor( Colors ):
    def __init__( self, *params ):
        """
        =conical degre | gradient_step1 | ... | gradient_stepn or
        =conical degre x y | gradient_step1 | ... | gradient_stepn or
        =conical x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn
        
        The degre parameter defines the angle of the cone in the usual trigonometric sense.
        The optional x y parameters define the center of the cone.
        By default, it is the center of the bounding-box.
        The x1 y1 x2 y2 parameters define the center and the angle of the cone.

        All x and y coordinates are expressed in percentage of the bounding box,
        relatively to the center of the bounding box.
        So 0 0 means the center while -50 -50 means the lower left corner of the bounding box. 

        If none of the above gradient type specification is given,
        the gradient will be drawn as an axial gradient with a null angle. 
        """
        Colors.__init__( self )
        count = 0
        self.params = ""
        for i in params:
            self.params = "%s %s" % ( self.params, str( i ) )
            count += 1
        if ( count != 1 ) and ( count != 3 ) and ( count != 4 ):
            raise Exception( "Bad Format of params %s" % count )
        
    def __repr__( self ):
        res = "=conical %s " % self.params
        if not ( len( self.lColors ) ):
            raise Exception( "Bad Format, must have  one color less" )
        res = "%s | %s" % ( res, Colors.__repr__( self ) )
        return res
                
        
# ---- self-test ----------------------------------------------------------
if __name__ == '__main__':
  from Tkinter import *
  import Zinc
  def createItem( zinc, group, ev ):
    print >> sys.stdout, "CreateIHM"
    sys.stdout.flush()
    Zinc.Rectangle( zinc, group, 
             ( 100, 100, 150, 150 ), 
             linewidth = "10", linecolor = '#FFFF00', 
             relief = "roundgroove", filled = 1, 
             fillcolor = "red", tags = ( "hello", "test" ) )
    sys.stdout.write( "hello_clic" + str( ev ) )
    
  z  = Zinc.Zinc( master = None, render = 1, height = 200, width = 400 )
  g1 = Zinc.Group( z, 1 ) 
  r  = Zinc.Rectangle( z, g1, ( 0, 0, 400, 200 ), 
                 linewidth = "10", 
                 linecolor = '#FFFF00', 
                 relief    = "roundgroove", 
                 filled    = 1, 
                 fillcolor = "#FFFFFF", 
                 tags      = ( "hello", "test" ) )
  t = Zinc.Text( z, g1, position = ( 40, 100 ), text = z.version )
# z.bind_tag("hello","<1>",lambda ev,z=z,g=g1 : createItem(z,g,ev)) 
  z.configure( backcolor = 'black' )
  z.pack()
  z.mainloop()

# Zinc.py ends here

Added jni/tkzinc/Python/library/__init__.py.









>
>
>
>
1
2
3
4
from Zinc import *
import graphics
import geometry
import pictorial

Added jni/tkzinc/Python/library/geometry.py.





















































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# -*- coding: iso-8859-1 -*-
"""
#  Geometrical basic Functions :
#  -----------------------------
#      perpendicular_point
#      line_angle
#      linenormal
#      vertex_angle
#      arc_pts
#      rad_point
#      bezier_compute
#      bezier_segment
#      bezier_point
"""

from math import pi, radians, atan2, sin, cos

# limite globale d'approximation courbe bezier
bezierClosenessThreshold = .2
def perpendicular_point (point, line): 
    """
    #---------------------------------------------------------------------------
    # Graphics::perpendicular_point
    # retourne les coordonnées du point perpendiculaire abaissé d'un point
    # sur une ligne
    #---------------------------------------------------------------------------
    # paramètres :
    # point : <coords> coordonnées du point de référence
    #  line : <coordsList> coordonnées des 2 points de la ligne de référence
    #---------------------------------------------------------------------------
    """
    (p1, p2) = line

    # cas partiuculier de lignes ortho.
    min_dist = .01
    if (abs(p2[1] - p1[1]) < min_dist) :
        # la ligne de référence est horizontale
        return (point[0], p1[1])

    elif (abs(p2[0] - p1[0]) < min_dist) :
        # la ligne de référence est verticale
        return (p1[0], point[1])

    a1 = float(p2[1] - p1[1]) / float(p2[0] - p1[0])
    b1 = p1[1] - (a1 * p1[0])

    a2 = -1.0 / a1
    b2 = point[1] - (a2 * point[0])

    x = (b2 - b1) / (a1 - a2)
    y = (a1 * x) + b1

    return (x, y)

def line_angle(startpoint, endpoint):
    """
    #---------------------------------------------------------------------------
    # Graphics::line_angle
    # retourne l'angle d'un point par rapport à un centre de référence
    #---------------------------------------------------------------------------
    # paramètres :
    # startpoint : <coords> coordonnées du point de départ du segment
    #   endpoint : <coords> coordonnées du point d'extremité du segment
    #---------------------------------------------------------------------------
    """
    angle = atan2(endpoint[1] - startpoint[1], endpoint[0] - startpoint[0])

    angle += pi/2
    angle *= float(180)/pi
    if (angle < 0):
        angle += 360  

    return angle

def linenormal(startpoint, endpoint):
    """
    #---------------------------------------------------------------------------
    # Graphics::linenormal
    # retourne la valeur d'angle perpendiculaire à une ligne
    #---------------------------------------------------------------------------
    # paramètres :
    # startpoint : <coords> coordonnées du point de départ du segment
    #   endpoint : <coords> coordonnées du point d'extremité du segment
    #---------------------------------------------------------------------------
    """
    angle = line_angle(startpoint, endpoint) + 90

    if (angle > 360):
        angle -= 360
    return angle

def vertex_angle(pt0, pt1, pt2):
    """
    #---------------------------------------------------------------------------
    # Graphics::vertex_angle
    # retourne la valeur de l'angle formée par 3 points
    # ainsi que l'angle de la bisectrice
    #---------------------------------------------------------------------------
    # paramètres :
    # pt0 : <coords> coordonnées du premier point de définition de l'angle
    # pt1 : <coords> coordonnées du deuxième point de définition de l'angle
    # pt2 : <coords> coordonnées du troisième point de définition de l'angle
    #---------------------------------------------------------------------------
    """
    angle1 = line_angle(pt0, pt1)
    angle2 = line_angle(pt2, pt1)

    if angle2 < angle1 :
        angle2 += 360 
    alpha = angle2 - angle1
    bisectrice = angle1 + (float(alpha)/2)

    return (alpha, bisectrice)


def arc_pts(center, radius, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::arc_pts
    # calcul des points constitutif d'un arc
    #---------------------------------------------------------------------------
    # paramètres :
    #  center : <coordonnées> centre de l'arc,
    #  radius : <dimension> rayon de l'arc,
    # options :
    #  -angle : <angle> angle de départ en degré de l'arc (par défaut 0)
    # -extent : <angle> delta angulaire en degré de l'arc (par défaut 360),
    #   -step : <dimension> pas de progresion en degré (par défaut 10)
    #---------------------------------------------------------------------------
    """
    if center is None :
        center = [0, 0]
    if (options.has_key('angle')) :
        angle = options['angle']
    else:
        angle = 0
    if (options.has_key('extent')) :
        extent = options['extent']
    else:
        extent = 360
    if (options.has_key('step')) :
        step = options['step']
    else:
        step = 10
    pts = []

    if (extent > 0 and step > 0) :
        #A Verifier !
        alpha = angle
        while(alpha <= angle+extent):
            (x_n, y_n) = rad_point(center, radius, alpha)
            pts.append((x_n, y_n))
            angle += step
            
    elif (extent < 0 and step < 0) :
        #Ca me semble buggue !!
        #Si extent négatif, il faut aussi que step le soit
        #Si ca boucle !
        alpha = angle
        while(alpha >= angle+extent):
            pts.append(rad_point(center, radius, alpha))
            alpha += step
    else:
        raise ValueError("Step and Extent havent the same sign")
    return tuple(pts)

def rad_point(center, radius, angle):
    """
    #---------------------------------------------------------------------------
    # Graphics::rad_point
    # retourne le point circulaire défini par centre-rayon-angle
    #---------------------------------------------------------------------------
    # paramètres :
    # center : <coordonnée> coordonnée [x,y] du centre de l'arc,
    # radius : <dimension> rayon de l'arc,
    #  angle : <angle> angle du point de circonférence avec le centre du cercle
    #---------------------------------------------------------------------------
    """
    alpha = radians(angle)

    xpt = center[0] + (radius * cos(alpha))
    ypt = center[1] + (radius * sin(alpha))

    return (xpt, ypt)

def bezier_segment(coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::bezier_segment
    # Calcul d'une approximation de segment (Quadratique ou Cubique) de bezier
    #---------------------------------------------------------------------------
    # paramètres :
    #    points : <[P1, C1, <C1>, P2]> liste des points définissant
    #             le segment de bezier
    #
    # options :
    #  -tunits : <integer> nombre pas de division des segments bezier
    #            (par défaut 20)
    # -skipend : <boolean> : ne pas retourner le dernier point du
    #            segment (chainage)
    #---------------------------------------------------------------------------
    """
    if (options.has_key('tunits')) :
        tunits = options['tunits']
    else:
        tunits = 20

    
    if options.has_key('skipend'):
        skipendpt = options['skipend']
    else:
        skipendpt = None

    pts = []

    if (skipendpt) :
        lastpt = tunits-1
    else:
        lastpt = tunits 
    for i in xrange(0, lastpt+1):
        if (i) :
            t = (i/tunits)
        else:
            t = i
        pts.append(bezier_point(t, coords))

    return pts


def bezier_point(t, coords):
    """
    #---------------------------------------------------------------------------
    # Graphics::bezier_point
    # calcul d'un point du segment (Quadratique ou Cubique) de bezier
    # params :
    # t = <n> (représentation du temps : de 0 à 1)
    # coords = (P1, C1, <C1>, P2) liste des points définissant le segment
    # de bezier P1 et P2 : extémités du segment et pts situés sur la courbe
    # C1 <C2> : point(s) de contrôle du segment
    #---------------------------------------------------------------------------
    # courbe bezier niveau 2 sur (P1, P2, P3)
    # P(t) = (1-t)²P1 + 2t(1-t)P2 + t²P3
    #
    # courbe bezier niveau 3 sur (P1, P2, P3, P4)
    # P(t) = (1-t)³P1 + 3t(1-t)²P2 + 3t²(1-t)P3 + t³P4
    #---------------------------------------------------------------------------
    """
    ncoords = len(coords)
    if  ncoords == 3:
        (p1, c1, p2) = coords
        c2 = None
    elif ncoords == 4:
        (p1, c1, c2, p2) = coords

    # extrémités : points sur la courbe
    #A VERIFIER
    #Pas compris
    if (not t):
        return tuple(p1)
    if (t >= 1.0):
        return p2


    t2 = t * t
    t3 = t2 * t
    pt = []

    # calcul pour x et y
    for i in (0, 1) :

        if (c2) :
            r1 = (1 - (3*t) + (3*t2) -    t3)  * p1[i]
            r2 = ((3*t) - (6*t2) + (3*t3)) * c1[i]
            r3 = ((3*t2) - (3*t3)) * c2[i]
            r4 = (t3)  * p2[i]

            pt[i] = (r1 + r2 + r3 + r4)

        else :
            r1 = (1 - (2*t) +    t2)  * p1[i]
            r2 = ((2*t) - (2*t2)) * c1[i]
            r3 = (t2)  * p2[i]

            pt[i] = (r1 + r2 + r3)

    return tuple(pt)

def bezier_compute(coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::bezier_compute
    # Retourne une liste de coordonnées décrivant un segment de bezier
    #---------------------------------------------------------------------------
    # paramètres :
    #     coords : <coordsList> liste des points définissant le segment
    #              de bezier
    #
    # options :
    # -precision : <dimension> seuil limite du calcul d'approche de la courbe
    #   -skipend : <boolean> : ne pas retourner le dernier point du segment
    #              (chaînage bezier)
    #---------------------------------------------------------------------------
    """
    if (options.has_key('precision')) :
        precision = options['precision']
    else:
        precision = bezierClosenessThreshold
    lastit = []

    subdivide_bezier(coords, lastit, precision)

    if (not options.has_key('skipend') or not options['skipend']):
        lastit.append(coords[3]) 

    return lastit

def smallenough_bezier(bezier, precision):
    """
    #---------------------------------------------------------------------------
    # Graphics::smallEnought
    # intégration code Stéphane Conversy : calcul points bezier
    # (précision auto ajustée)
    #---------------------------------------------------------------------------
    # distance is something like num/den with den=sqrt(something)
    # what we want is to test that distance is smaller than precision,
    # so we have distance < precision ?  eq. to distance^2 < precision^2 ?
    # eq. to (num^2/something) < precision^2 ?
    # eq. to num^2 < precision^2*something
    # be careful with huge values though (hence 'long long')
    # with common values: 9add 9mul
    #---------------------------------------------------------------------------
    """
    (pt_x, pt_y) = (0, 1)
    (a, b) = (bezier[0], bezier[3])

    den = ((a[pt_y]-b[pt_y])*(a[pt_y]-b[pt_y])) + ((b[pt_x]-a[pt_x])*(b[pt_x]-a[pt_x]))
    p = precision*precision

    # compute distance between P1|P2 and P0|P3
    mat = bezier[1]
    num1 = ((mat[pt_x]-a[pt_x])*(a[pt_y]-b[pt_y])) + ((mat[pt_y]-a[pt_y])*(b[pt_x]-a[pt_x]))

    mat = bezier[2]
    num2 = ((mat[pt_x]-a[pt_x])*(a[pt_y]-b[pt_y])) + ((mat[pt_y]-a[pt_y])*(b[pt_x]-a[pt_x]))

    # take the max
    num1 = max(num1, num2)

    if (p*den > (num1*num1)):
        return 1
    else:
        return 0

def subdivide_bezier(bezier, it, precision, integeropt):
    """
    #---------------------------------------------------------------------------
    # Graphics::subdivide_bezier
    # subdivision d'une courbe de bezier
    #---------------------------------------------------------------------------
    """
    (b0, b1, b2, b3) = bezier

    if (smallenough_bezier(bezier, precision)) :
        it.append((b0[0], b0[1]))

    else :
        (left, right) = (None, None)

        for i in (0, 1) :

            if (integeropt) :
                # int optimized (6+3=9)add + (5+3=8)shift

                left[0][i] = b0[i]
                left[1][i] = (b0[i] + b1[i]) >> 1
                # keep precision
                left[2][i] = (b0[i] + b2[i] + (b1[i] << 1)) >> 2
                
                tmp = (b1[i] + b2[i])
                left[3][i] = (b0[i] + b3[i] + (tmp << 1) + tmp) >> 3
                
                right[3][i] = b3[i]
                right[2][i] = (b3[i] + b2[i]) >> 1
                # keep precision
                right[1][i] = (b3[i] + b1[i] + (b2[i] << 1) ) >> 2
                right[0][i] = left[3][i]

            else :
                # float
                
                left[0][i] = b0[i]
                left[1][i] = float(b0[i] + b1[i]) / 2
                left[2][i] = float(b0[i] + (2*b1[i]) + b2[i]) / 4
                left[3][i] = float(b0[i] + (3*b1[i]) + (3*b2[i]) + b3[i]) / 8
                
                right[3][i] = b3[i]
                right[2][i] = float(b3[i] + b2[i]) / 2
                right[1][i] = float(b3[i] + (2*b2[i]) + b1[i]) / 4
                right[0][i] = float(b3[i] + (3*b2[i]) + (3*b1[i]) + b0[i]) / 8

      

        subdivide_bezier(left, it, precision, integeropt)
        subdivide_bezier(right, it, precision, integeropt)


#Local Variables:
#mode : python
#tab-width: 4
#end:

Added jni/tkzinc/Python/library/graphics.py.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
# -*- coding: iso-8859-1 -*-
"""
#-------------------------------------------------------------------------------
#
#      Graphics.py
#      some graphic design functions
#
#-------------------------------------------------------------------------------
#  Functions to create complexe graphic component :
#  ------------------------------------------------
#      build_zinc_item          (realize a zinc item from description hash table
#                              management of enhanced graphics functions)
#
#      repeat_zinc_item         (duplication of given zinc item)
#
#  Function to compute complexe geometrical forms :
#  (text header of functions explain options for each form,
#  function return curve coords using control points of cubic curve)
#  -----------------------------------------------------------------
#     rounded_rectangle_coords (return curve coords of rounded rectangle)
#     hippodrome_coords       (return curve coords of circus form)
#     ellipse_coords          (return curve coords of ellipse form)
#     polygon_coords          (return curve coords of regular polygon)
#     roundedcurve_coords     (return curve coords of rounded curve)
#     polyline_coords         (return curve coords of polyline)
#     shiftpath_coords        (return curve coords of shifting path)
#     tabbox_coords           (return curve coords of tabbox's pages)
#     pathline_coords         (return triangles coords of pathline)
#
#  Function to compute 2D 1/2 relief and shadow :
#  function build zinc items (triangles and curve) to simulate this
#  -----------------------------------------------------------------
#     graphicitem_relief    (return triangle items simulate relief of given item)
#     polyline_relief_params (return triangle coords
#                           and lighting triangles color list)
#     graphicitem_shadow    (return triangles and curve items
#                           simulate shadow of given item))
#     polyline_shadow_params (return triangle and curve coords
#                           and shadow triangles color list))
#
#
#-------------------------------------------------------------------------------
#      Authors: Jean-Luc Vinot <vinot@cena.fr>
#      PM2PY: Guillaume Vidon <vidon@ath.cena.fr> 
#
# $Id$ 
#-------------------------------------------------------------------------------
"""
VERSION = "1.0"
__revision__ = "0.1"

import logging
import types
import re
from geometry import *
from pictorial import *
from math import pi, radians, atan2, sqrt, sin, cos

graphiclogger = logging.getLogger('Graphics')
debug = graphiclogger.debug
error = graphiclogger.error
exception = graphiclogger.exception
log = lambda msg : graphiclogger.log(logging.DEBUG, msg)

# constante facteur point directeur (conique -> quadratique)
const_ptd_factor = .5523

def transdic(**dict):
    newdic={}
    for key, val in dict.items():
        if (type(val) is types.ListType):
            newdic[key] = tuple(val)
        else:
            newdic[key] = val
    return newdic
    
def is_flat_list(apts):
    if reduce(lambda x, y : x and (type(y) in ( types.FloatType, types.IntType)),
              apts):
        if len(apts) % 2:
            raise ValueError("Not a valid Coords list")
        else :
            return True
    else :
        return False

def is_point(apoint):
    if (type(apoint) in ( types.TupleType, types.ListType)):
        if len(apoint) == 2 :
            if reduce(lambda x, y : x and (type(y) in ( types.FloatType, types.IntType)),
                      apts):
                return True
            else :
                return False
        elif reduce(lambda x, y : x and (type(y) in ( types.FloatType, types.IntType)),
                    apts[:-1])\
                    and type(apts[-1]) in ('c', 'n'):
            return True
        else :
            return False
    else :
        return False
                
# def is_tuple_list(apts):
#     if reduce(lambda x, y : x \
#               and is_point(x)),
#               apts):
                  
    
def lpts2coords(lpts):
    coords = []
    if (type(lpts) in ( types.TupleType, types.ListType )):
        for point in lpts :
            coords.append(tuple(point))
    return tuple(coords)
            
def coords2lpts(coords):
    lpts = []
    if (type(coords) in ( types.TupleType, types.ListType )):
        for point in coords :
            lpts.append(list(point))
    else :
        raise ValueError("Invalid Coords %s "%coords)
    return lpts

def build_zinc_item(widget, pgroup = 1, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::build_zinc_item
    # Création d'un objet Zinc de représentation
    #---------------------------------------------------------------------------
    # types d'items valides :
    # les items natifs zinc : group, rectangle, arc, curve, text, icon
    # les items ci-après permettent de spécifier des curves 'particulières' :
    # -roundedrectangle : rectangle à coin arrondi
    #       -hippodrome : hippodrome
    #          -ellipse : ellipse un centre 2 rayons
    #         -polygone : polygone régulier à n cotés (convexe ou en étoile)
    #     -roundedcurve : curve multicontours à coins arrondis (rayon unique)
    #         -polyline : curve multicontours à coins arrondis (le rayon pouvant
    #                     être défini 
    #                     spécifiquement pour chaque sommet)
    #         -pathline : création d'une ligne 'épaisse' avec l'item Zinc 
    #                     triangles décalage par rapport à un chemin donné 
    #                     (largeur et sens de décalage)
    #                     dégradé de couleurs de la ligne (linéaire, transversal
    #                     ou double)
    #---------------------------------------------------------------------------
    # paramètres :
    # widget : <widget> identifiant du widget Zinc
    # parentgroup : <tagOrId> identifiant du group parent
    #
    # options :
    #   -itemtype : type de l'item à construire (type zinc ou metatype)
    #     -coords : <coords|coordsList> coordonnées de l'item
    # -metacoords : <hastable> calcul de coordonnées par type 
    #               d'item différent de itemtype
    #   -contours : <contourList> paramètres multi-contours
    #     -params : <hastable> arguments spécifiques de l'item à passer
    #               au widget
    #    -addtags : [list of specific tags] to add to params -tags
    #    -texture : <imagefile> ajout d'une texture à l'item
    #    -pattern : <imagefile> ajout d'un pattern à l'item
    #     -relief : <hastable> création d'un relief à l'item invoque la fonction
    #               graphicitem_relief()
    #     -shadow : <hastable> création d'une ombre portée à l'item invoque
    #               la fonction graphicitem_shadow()
    #      -scale : <scale_factor|[xscale_factor,yscale_factor]> application
    #               d'une transformation zinc->scale à l'item
    #  -translate : <[delta_x,delta_y]> application d'un transformation zinc->translate
    #               à l'item.
    #     -rotate : <angle> application d'une transformation zinc->rotate
    #               (en degré) à l'item
    #       -name : <str> nom de l'item
    #               spécifiques item group :
    #       -clip : <coordList|hashtable> paramètres de clipping d'un item group
    #               (coords ou item)
    #      -items : <hashtable> appel récursif de la fonction permettant
    #               d'inclure des items au groupe
    #---------------------------------------------------------------------------
    #
    #---------------------------------------------------------------------------
    """

    if options.has_key('parentgroup'):
        parentgroup = options['parentgroup']
    else :
        parentgroup = pgroup
    try:
        itemtype = options['itemtype']
    except KeyError:
        raise ValueError("Must have itemtype option")
    try:
        coords = options['coords']
    except KeyError:
        try:
            coords = options['metacoords']
        except KeyError :
            raise ValueError("Must have coords or metacoords option")
        
    if options.has_key('params'):
        params = options['params']
    else:
        params = {}

    #return unless($widget and $itemtype
    #and ($coords or $options{'-metacoords'}))

    try:
        name = options['name']
    except KeyError:
        name = None

    item = None
    metatype = None
    items = []
    reliefs = []
    shadows = []
    tags = []

    #--------------------
    # GEOMETRIE DES ITEMS

    # gestion des types d'items particuliers et à raccords circulaires
    if (itemtype in ( 'roundedrectangle',
                      'hippodrome',
                      'polygone',
                      'ellipse',
                      'roundedcurve',
                      'polyline',
                      'curveline')):

        # par défaut la curve sera fermée -closed = 1
        if not params.has_key('closed'):
            params['closed'] = 1
        metatype = itemtype
        itemtype = 'curve'

        # possibilité de définir les coordonnées initiales par metatype
        if (options.has_key('metacoords')) :
            options['coords'] = meta_coords( **options['metacoords'])

    # création d'une pathline à partir d'item zinc triangles
    elif (itemtype == 'pathline') :
        itemtype = 'triangles'
        if (options.has_key('metacoords')) :
            coords = meta_coords( **options['metacoords'])
          
        if (options.has_key('graduate')) :
            numcolors = len(coords)
            lcolors = path_graduate(widget,
                                    numcolors,
                                    options['graduate'])
            params['colors'] = tuple(lcolors)

        if options.has_key('coords'):
            coords = pathline_coords(**options)
        else:
            coords = pathline_coords(coords, **options)

        # création d'une boite à onglet
    elif (itemtype == 'tabbox') :
        return build_tabboxitem(widget, parentgroup, **options)

    # calcul des coordonnées finales de la curve
    if (metatype is not None):
        coords = meta_coords(type = metatype, **options)


    # gestion du multi-contours (accessible pour tous les types
    # d'items géometriques)
    if (options.has_key('contours') and (metatype is not None)) :
        lcontours = options['contours']
        contours=[]
        numcontours = len(contours)
        for contour in lcontours:
            # radius et corners peuvent être défini
            # spécifiquement pour chaque contour
            (atype, way, addcoords,) = contour[:3]
            if len(contour) >= 4:
                radius = contour[3]
            else :
                radius = None
            if len(contour) >= 5:
                corners = contour[4]
            else:
                corners = None
            if len(contour) >= 6:
                corners_radius = contour[5]
            else :
                corners_radius = None
            if (radius is None):
                if options.has_key('radius'):
                    radius = options['radius']
                else :
                    raise ValueError("radius option requiered")

            newcoords = meta_coords(type = metatype,
                                    coords = addcoords,
                                    radius = radius,
                                    corners = corners,
                                    corners_radius = corners_radius
                                    )
            contours.append((atype, way, newcoords))

        options['contours'] = contours

    #----------------------
    # REALISATION DES ITEMS

    # ITEM GROUP
    # gestion des coordonnées et du clipping
    if (itemtype == 'group') :
        item = widget.add(itemtype,
                          parentgroup,
                          **params)
        widget.addtag_withtag(name, item)
        if coords:
            widget.coords(item, tuple(coords))

        # clipping du groupe par item ou par géometrie
        if (options.has_key('clip')) :
            clipbuilder = options['clip']
            clip = None

            # création d'un item de clipping
            if (type(clipbuilder) is types.DictType
                and clipbuilder.has_key('itemtype')):
                clip = build_zinc_item(widget, item, **clipbuilder)

            elif (type(clipbuilder) in (types.TupleType, types.ListType)
                  or widget.type(clipbuilder)) :
                clip = clipbuilder

            if (clip):
                widget.itemconfigure(item, clip = clip)

        # créations si besoin des items contenus dans le groupe
        if (options.has_key('items')
            and type(options['items']) is types.DictType) :
            for (itemname, itemstyle) in options['items'].items() :
                if not itemstyle.has_key('name'):
                    itemstyle['name'] = itemname
                build_zinc_item(widget, item, **itemstyle)


    # ITEM TEXT ou ICON
    elif (itemtype in ('text', 'icon')) :
        imagefile = None
        if (itemtype == 'icon') :
            imagefile = params['image']
            image = get_image(widget, imagefile)
            if (image) :
                params['image'] = image
            else:
                params['image'] = ""
    

        item = widget.add(itemtype,
                          parentgroup,
                          position = coords,
                          **params
                          )
        if imagefile:
            params['image'] = imagefile 


    # ITEMS GEOMETRIQUES -> CURVE
    else :
        nparams=params
        item = widget.add(itemtype,
                          parentgroup,
                          lpts2coords(coords),
                          **params
                          )

        if (itemtype == 'curve' and options.has_key('contours')) :
            for contour in options['contours'] :
                contour = list(contour)
                contour[2] = tuple(contour[2])
                widget.contour(item, *contour)
                             
        # gestion du mode norender
        if (options.has_key('texture')) :
            texture = get_texture(widget, options['texture'])
            if texture:
                widget.itemconfigure(item, tile = texture)

        if (options.has_key('pattern')) :
            bitmap = get_pattern(**options['pattern'])
            if bitmap:
                widget.itemconfigure(item, fillpattern = bitmap)

    # gestion des tags spécifiques
    if (options.has_key('addtags')) :
        tags = options['addtags']

        params_tags = params['tags']
        if params_tags:
            tags.extend(params_tags) 

        widget.itemconfigure(item, tags = tags)

    #-------------------------------
    # TRANSFORMATIONS ZINC DE L'ITEM

    # transformation scale de l'item si nécessaire
    if (options.has_key('scale')) :
        scale = options['scale']
        if (type(scale) is not types.TupleType) :
            scale = (scale, scale) 
        widget.scale(item, scale)
  

    # transformation rotate de l'item si nécessaire
    if (options.has_key('rotate')):
        widget.rotate(item, radians(options['rotate'])) 

    # transformation translate de l'item si nécessaire
    if (options.has_key('translate')):
        widget.translate(item, options['translate'])


    # répétition de l'item
    if (options.has_key('repeat')) :
        items.extend((item,
                      repeat_zinc_item(widget, item, **options['repeat'])))

    #-----------------------
    # RELIEF ET OMBRE PORTEE

    # gestion du relief
    if (options.has_key('relief')) :
        if (len(items)) :
            target = items
        else:
            target = item
        reliefs.extend(graphicitem_relief(widget,
                                          target, **options['relief']))

    # gestion de l'ombre portée
    if (options.has_key('shadow')) :
        if (len(items)) :
            target = items
        else:
            target = item
        shadows.extend(graphicitem_shadow(widget,
                                         target, **options['shadow']))
  

    if len(reliefs):
        items.extend(reliefs)
    if len(shadows):
        items.extend(shadows)

    if len(items):
        return items
    else:
        return item

def repeat_zinc_item(widget,
                     item,
                     num = 2,
                     dxy = (0,0),
                     angle = None,
                     params = None,
                     copytag = None) :
    """
    #---------------------------------------------------------------------------
    # Graphics::repeat_zinc_item
    # Duplication (clonage) d'un objet Zinc de représentation
    #---------------------------------------------------------------------------
    # paramètres :
    # widget : <widget> identifiant du widget zinc
    #   item : <tagOrId> identifiant de l'item source
    # options :
    #     -num : <n> nombre d'item total (par defaut 2)
    #     -dxy : <[delta_x, delta_y]> translation entre 2 duplications (par defaut [0,0])
    #   -angle : <angle> rotation entre 2 duplications
    # -copytag : <sting> ajout d'un tag indexé pour chaque copie
    #  -params : <hashtable> {clef => [value list]}> valeur de paramètre
    #            de chaque copie
    #---------------------------------------------------------------------------
    """
    clones = []
    delta_x, delta_y = dxy
    # duplication d'une liste d'items -> appel récursif
    if (type(item) in (types.TupleType, types.ListType)) :
        for part in item :
            clones.append(repeat_zinc_item(widget,
                                           part,
                                           dxy,
                                           angle,
                                           params,
                                           copytag))

        return clones

    tags = []

    if (copytag) :
        tags = widget.itemcget(item, 'tags')
        widget.itemconfigure(item, tags = tags + ("%s0"%copytag,))

    for i in xrange(1, num) :
        clone = None

        if (copytag) :
            clone = widget.clone(item, tags = tags + ("%s%s"%(copytag, i),))
        else :
            clone = widget.clone(item)

        clones.append(clone)
        widget.translate(clone, delta_x*i, delta_y*i)
        if angle :
            widget.rotate(clone, radians(angle*i))

        if (params is not None ) :
            widget.itemconfigure(clone, **params )
    return clones


#MUST BE TESTED
def meta_coords( type,
                 coords,
                 **options ):
    """
    #---------------------------------------------------------------------------
    # FONCTIONS GEOMETRIQUES
    #---------------------------------------------------------------------------
    
    #---------------------------------------------------------------------------
    # Graphics::meta_coords
    # retourne une liste de coordonnées en utilisant la fonction du type
    # d'item spécifié
    #---------------------------------------------------------------------------
    # paramètres : (passés par %options)
    #   -type : <string> type de primitive utilisée
    # -coords : <coordsList> coordonnées nécessitée par la fonction [type]_coords
    #
    # les autres options spécialisées au type seront passés
    # à la fonction [type]coords
    #---------------------------------------------------------------------------
    """
    pts = None

    if (type == 'roundedrectangle'):
        log('Coords for roundedrectangle')
        pts = rounded_rectangle_coords(coords, **options)

    elif (type == 'hippodrome') :
        log('Coords for hippodrome')
        pts = hippodrome_coords(coords, **options)

    elif (type == 'ellipse') :
        log('Coords for ellipse')
        pts = ellipse_coords(coords, **options)

    elif (type == 'roundedcurve') :
        log('Coords for roundedcurve')
        pts = roundedcurve_coords(coords, **options)

    elif (type == 'polygone') :
        log('Coords for polygone')
        pts = polygon_coords(coords, **options)

    elif (type == 'polyline') :
        log('Coords for polyline')
        pts = polyline_coords(coords, **options)
    
    elif (type == 'curveline') :
        log('Coords for curveline')
        pts = curveline_coords(coords, **options)

    return pts


def zincitem_2_curvecoords( widget, item,
                            linear = 0,
                            realcoords = 0,
                            adjust = 1,
                            ):
    """
    #--------------------------------------------------------------------------
    # Graphics::zincitem_2_curvecoords
    # retourne une liste des coordonnées 'Curve' d'un l'item Zinc
    # rectangle, arc ou curve
    #--------------------------------------------------------------------------
    # paramètres :
    # widget : <widget> identifiant du widget zinc
    #   item : <tagOrId> identifiant de l'item source
    # options :
    #     -linear : <boolean> réduction à des segments non curviligne
    #               (par défaut 0)
    # -realcoords : <boolean> coordonnées à transformer dans le groupe père
    #               (par défaut 0)
    #     -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
    #--------------------------------------------------------------------------
    """
    itemtype = widget.type(item)

    if not itemtype :
        raise ValueError("Not a Valid Item %s" % item)

    itemcoords = widget.coords(item)
    coords = None
    multi = []

    if (itemtype == 'rectangle') :
        coords = rounded_rectangle_coords(itemcoords, radius = 0)

    elif (itemtype == 'arc') :
        coords = ellipse_coords(itemcoords)
        if linear :
            coords = curve2polyline_coords(coords, adjust) 

    elif (itemtype == 'curve') :
        numcontours = widget.contour(item)

        if (numcontours < 2) :
            if linear:
                coords = curve2polyline_coords(itemcoords, adjust)
        else :
            if (linear) :
                multi = curveitem2polyline_coords(widget, item)

            else :
                for contour in xrange(0, numcontours):
                    points = widget.coords(item, contour)
                    multi.extend(points)
            coords = multi

    if (realcoords) :
        parentgroup = widget.group(item)
        if (len(multi)) :
            newcoords = []
            for points in multi :
                transcoords = widget.transform(item, parentgroup, points)
                newcoords.extend(transcoords)
            coords = newcoords
        else :
            transcoords =  widget.transform(item, parentgroup, coords)
            coords = transcoords

    return coords

def rounded_rectangle_coords( coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::rounded_rectangle_coords
    # calcul des coords du rectangle à coins arrondis
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> coordonnées bbox (haut-gauche et bas-droite)
    #          du rectangle
    # options :
    #  -radius : <dimension> rayon de raccord d'angle
    # -corners : <booleanList> liste des raccords de sommets
    #            [0 (aucun raccord)|1] par défaut [1,1,1,1]
    #---------------------------------------------------------------------------
    """
    (x_0, y_0, x_n, y_n) = (coords[0][0], coords[0][1],
                        coords[1][0], coords[1][1])

    if (options.has_key('radius')):
        radius = options['radius']
    else:
        radius = None
  
    if (options.has_key('corners')):
        corners = options['corners']
    else:
        corners = [1, 1, 1, 1]

    # attention aux formes 'négatives'
    if (x_n < x_0) :
        (x_0, x_n) = (x_n, x_0)
      
    if (y_n < y_0) :
        (y_0, y_n) = (y_n, y_0)

    height = min(x_n -x_0, y_n - y_0)
    #radius non defini dans les parametres
    if (radius is None) :
        radius = int(height/10)
        radius = max(radius, 3)
      
    #radius defini mais trop petit
    if ( radius < 2) :
        return ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))

    # correction de radius si necessaire
    max_rad = height
    #CODE BIZARRE
    #Comment corners ne peut être non défini
    #a ce niveau ?
    #  max_rad /= 2 if (!defined corners)
    if (corners is None):
        max_rad /= 2
    radius = min(max_rad, radius)

    # points remarquables
    ptd_delta = radius * const_ptd_factor
    (x_2, x_3) = (x_0 + radius, x_n - radius)
    (x_1, x_4) = (x_2 - ptd_delta, x_3 + ptd_delta)
    (y_2, y_3) = (y_0 + radius, y_n - radius)
    (y_1, y_4) = (y_2 - ptd_delta, y_3 + ptd_delta)

    # liste des 4 points sommet du rectangle : angles sans raccord circulaire
    angle_pts = ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))

    # liste des 4 segments quadratique : raccord d'angle = radius
    roundeds = [[(x_2, y_0), (x_1, y_0, 'c'), (x_0, y_1, 'c'), (x_0, y_2),],
                [(x_0, y_3), (x_0, y_4, 'c'), (x_1, y_n, 'c'), (x_2, y_n),],
                [(x_3, y_n), (x_4, y_n, 'c'), (x_n, y_4, 'c'), (x_n, y_3),],
                [(x_n, y_2), (x_n, y_1, 'c'), (x_4, y_0, 'c'), (x_3, y_0),]]

    pts = []
    previous = None
    for i  in xrange(0, 4):
        #BUGS ??
        if (corners[i]):
            if (previous is not None) :
                # on teste si non duplication de point
                (nx, ny) = roundeds[i][0]
                if (previous[0] == nx and previous[1] == ny) :
                    pts.pop()
            pts.extend(roundeds[i])
            previous = roundeds[i][3]
        else :
            pts.append(angle_pts[i])

    return pts

def ellipse_coords(coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::ellipse_coords
    # calcul des coords d'une ellipse
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> coordonnées bbox du rectangle exinscrit
    # options :
    # -corners : <booleanList> liste des raccords de sommets
    # [0 (aucun raccord)|1] par défaut [1,1,1,1]
    #---------------------------------------------------------------------------
    """
    (x_0, y_0, x_n, y_n) = (coords[0][0], coords[0][1],
                        coords[1][0], coords[1][1])

    if options.has_key('corners') :
        corners = options.has_key('corners')
    else:
        corners = [1, 1, 1, 1]

    # attention aux formes 'négatives'
    if (x_n < x_0) :
        xs = x_0
        (x_0, x_n) = (x_n, xs)
    if (y_n < y_0) :
        ys = y_0
        (y_0, y_n) = (y_n, ys)

    # points remarquables
    delta_x = (x_n - x_0)/2 * const_ptd_factor
    delta_y = (y_n - y_0)/2 * const_ptd_factor
    (x_2, y_2) = ((x_0+x_n)/2, (y_0+y_n)/2)
    (x_1, x_3) = (x_2 - delta_x, x_2 + delta_x)
    (y_1, y_3) = (y_2 - delta_y, y_2 + delta_y)

    # liste des 4 points sommet de l'ellipse : angles sans raccord circulaire
    angle_pts = ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))

    # liste des 4 segments quadratique : raccord d'angle = arc d'ellipse
    roundeds = (((x_2, y_0), (x_1, y_0, 'c'), (x_0, y_1, 'c'), (x_0, y_2), ),
                ((x_0, y_2), (x_0, y_3, 'c'), (x_1, y_n, 'c'), (x_2, y_n), ),
                ((x_2, y_n), (x_3, y_n, 'c'), (x_n, y_3, 'c'), (x_n, y_2), ),
                ((x_n, y_2), (x_n, y_1, 'c'), (x_3, y_0, 'c'), (x_2, y_0), ))

    pts = []
    previous = None
    for i in xrange(0, 4):
        if (corners[i]) :
            if (previous) :
                # on teste si non duplication de point
                (nx, ny) = roundeds[i][0]
                if (previous[0] == nx and previous[1] == ny) :
                    pts.pop()
            
            
            pts.extend(roundeds[i])
            previous = roundeds[i][3]

        else :
            pts.append(angle_pts[i])

    return pts


def hippodrome_coords(coords, **options) :
    """
    #---------------------------------------------------------------------------
    # Graphics::hippodrome_coords
    # calcul des coords d'un hippodrome
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> coordonnées bbox du rectangle exinscrit
    # options :
    # -orientation : orientation forcée de l'hippodrome [horizontal|vertical]
    #     -corners : liste des raccords de sommets [0|1] par défaut [1,1,1,1]
    #       -trunc : troncatures [left|right|top|bottom|both]
    #---------------------------------------------------------------------------
    """
    (x_0, y_0, x_n, y_n) = (coords[0][0],
                            coords[0][1],
                            coords[1][0],
                            coords[1][1])

    if (options.has_key('orientation')) :
        orientation = options['orientation']
    else:
        orientation = 'none'

    # orientation forcée de l'hippodrome
    # (sinon hippodrome sur le plus petit coté)
    if (orientation == 'horizontal') :
        height = abs(y_n - y_0)
    elif (orientation == 'vertical') :
        height = abs(x_n - x_0)
    else:
        height = min(abs(x_n - x_0), abs(y_n - y_0))
    radius = height/2
    corners = (1, 1, 1, 1)

    if  (options.has_key('corners')) :
        corners = options['corners']

    elif (options.has_key('trunc')) :
        trunc = options['trunc']
        if (trunc == 'both') :
            return ((x_0, y_0), (x_0, y_n), (x_n, y_n), (x_n, y_0))
        else :
            if (trunc == 'left'):
                corners = (0, 0, 1, 1)
            elif (trunc == 'right'):
                corners = (1, 1, 0, 0)
            elif (trunc == 'top'):
                corners = (0, 1, 1, 0)
            elif (trunc == 'bottom') :
                corners = (1, 0, 0, 1)
            else :
                corners = (1, 1, 1, 1)

    # l'hippodrome est un cas particulier de roundedRectangle
    # on retourne en passant la 'configuration' à la fonction
    # générique rounded_rectangle_coords
    return rounded_rectangle_coords(coords,
                                  radius = radius,
                                  corners = corners)

def polygon_coords(coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::polygon_coords
    # calcul des coords d'un polygone régulier
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coords> point centre du polygone
    # options :
    #      -numsides : <integer> nombre de cotés
    #        -radius : <dimension> rayon de définition du polygone
    #                  (distance centre-sommets)
    #  -inner_radius : <dimension> rayon interne (polygone type étoile)
    #       -corners : <booleanList> liste des raccords de sommets [0|1]
    #                  par défaut [1,1,1,1]
    # -corner_radius : <dimension> rayon de raccord des cotés
    #    -startangle : <angle> angle de départ en degré du polygone
    #---------------------------------------------------------------------------
    """
    if options.has_key('numsides'):
        numsides = options['numsides']
    else :
        numsides = 0
    if options.has_key('radius'):
        radius = options['radius']
    else:
        radius = None
    if (numsides < 3 or not radius) :
        raise ValueError("Vous devez au moins spécifier "
                         +"un nombre de cotés >= 3 et un rayon...\n")

    if (coords is None):
        coords = (0, 0)
    if (options.has_key('startangle')) :
        startangle = options['startangle']
    else:
        startangle = 0
    anglestep = 360/numsides
    if options.has_key('inner_radius'):
        inner_radius = options['inner_radius']
    else:
        inner_radius = None
    pts = []

    # points du polygone
    for i in xrange(0, numsides):
        (xp, yp) = rad_point(coords, radius, startangle + (anglestep*i))
        pts.append((xp, yp))

        # polygones 'étoiles'
        if (inner_radius) :
            (xp, yp) = rad_point(coords, inner_radius,
                                 startangle + (anglestep*(i+ 0.5)))
            pts.append((xp, yp))
    
    pts.reverse()

    if (options.has_key('corner_radius')) :
        if options.has_key('corners'):
            corners = options['corners']
        else:
            corners = None
        return roundedcurve_coords(pts,
                                   radius = options['corner_radius'],
                                   corners = corners)
    else :
        return pts


def rounded_angle(widget, parentgroup, coords, radius) :
    """
    #---------------------------------------------------------------------------
    # Graphics::rounded_angle
    # THIS FUNCTION IS NO MORE USED, NEITHER EXPORTED
    # curve d'angle avec raccord circulaire
    #---------------------------------------------------------------------------
    # paramètres :
    # widget : identifiant du widget Zinc
    # parentgroup : <tagOrId> identifiant de l'item group parent
    # coords : <coordsList> les 3 points de l'angle
    # radius : <dimension> rayon de raccord
    #---------------------------------------------------------------------------
    """
    (pt0, pt1, pt2) = coords

    (corner_pts, center_pts) = rounded_angle_coords(coords, radius)
    (cx_0, cy_0) = center_pts

    if (parentgroup is None) :
        parentgroup = 1 

    pts = [pt0]
    pts.extend(corner_pts)
    pts.append(pt2)
    
    widget.add('curve',
               parentgroup,
               lpts2coords(pts),
               closed = 0,
               linewidth = 1,
               priority = 20,
               )


def rounded_angle_coords (coords, radius) :
    """
    #---------------------------------------------------------------------------
    # Graphics::rounded_angle_coords
    # calcul des coords d'un raccord d'angle circulaire
    #---------------------------------------------------------------------------
    # le raccord circulaire de 2 droites sécantes est traditionnellement
    # réalisé par un
    # arc (conique) du cercle inscrit de rayon radius tangent à ces 2 droites
    #
    # Quadratique :
    # une approche de cette courbe peut être réalisée simplement par le calcul
    # de 4 points
    # spécifiques qui définiront - quelle que soit la valeur de l'angle formé
    # par les 2
    # droites - le segment de raccord :
    # - les 2 points de tangence au cercle inscrit seront les points de début
    #   et de fin
    # du segment de raccord
    # - les 2 points de controle seront situés chacun sur le vecteur
    #   reliant le point de
    # tangence au sommet de l'angle (point secant des 2 droites)
    # leur position sur ce vecteur peut être simplifiée comme suit :
    # - à un facteur de 0.5523 de la distance au sommet pour
    #   un angle >= 90° et <= 270°
    # - à une 'réduction' de ce point vers le point de tangence
    #   pour les angles limites
    # de 90° vers 0° et de 270° vers 360°
    # ce facteur sera légérement modulé pour recouvrir plus précisement
    # l'arc correspondant
    #---------------------------------------------------------------------------
    # coords : <coordsList> les 3 points de l'angle
    # radius : <dimension> rayon de raccord
    #---------------------------------------------------------------------------
    """
    (pt0, pt1, pt2) = coords

    # valeur d'angle et angle formé par la bisectrice
    (angle, bisecangle)  = vertex_angle(pt0, pt1, pt2)

    # distance au centre du cercle inscrit : rayon/sinus demi-angle
    asin = sin(radians(angle/2))
    
    if (asin) :
        delta = abs(radius / asin)
    else:
        delta = radius

    # point centre du cercle inscrit de rayon $radius
    if (angle < 180) :
        refangle = bisecangle + 90
    else :
        refangle = bisecangle - 90
        
    (cx_0, cy_0) = rad_point(pt1, delta, refangle)

    # points de tangeance : pts perpendiculaires du centre aux 2 droites
    (px_1, py_1) = perpendicular_point((cx_0, cy_0), (pt0, pt1))
    (px_2, py_2) = perpendicular_point((cx_0, cy_0), (pt1, pt2))

    # point de controle de la quadratique
    # facteur de positionnement sur le vecteur pt.tangence, sommet
    ptd_factor =  const_ptd_factor
    if (angle < 90 or angle > 270) :
        if (angle < 90) :
            diffangle = angle
        else:
            diffangle =  360 - angle
        if (diffangle > 15) :
            ptd_factor -= (((90 - diffangle)/90) * (ptd_factor/4)) 
        ptd_factor = (diffangle/90) * (ptd_factor
                                       + ((1 - ptd_factor)
                                          * (90 - diffangle)/90))
    else :
        diffangle = abs(180 - angle)
        if (diffangle > 15) :
            ptd_factor += (((90 - diffangle)/90) * (ptd_factor/3))

    # delta xy aux pts de tangence
    (d1x, d1y) = ((pt1[0] - px_1) * ptd_factor, (pt1[1] - py_1) *  ptd_factor)
    (d2x, d2y) = ((pt1[0] - px_2) * ptd_factor, (pt1[1] - py_2) *  ptd_factor)

    # les 4 points de l'arc 'quadratique'
    corner_pts = [(px_1, py_1), (px_1+d1x, py_1+d1y, 'c'),
                  (px_2+d2x, py_2+d2y, 'c'), (px_2, py_2)]

    
    # retourne le segment de quadratique et le centre du cercle inscrit
    return (corner_pts, (cx_0, cy_0))


def roundedcurve_coords(coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::roundedcurve_coords
    # retourne les coordonnées d'une curve à coins arrondis
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> liste de coordonnées des points de la curve
    # options :
    #  -radius : <dimension> rayon de raccord d'angle
    #  -corners : <booleanList> liste des raccords de sommets [0|1]
    # par défaut [1,1,1,1]
    #---------------------------------------------------------------------------
    """
    numfaces = len(coords)
    curve_pts = []

    if (options.has_key('radius')) :
        radius = options['radius']
    else:
        radius = 0
    corners = None
    if options.has_key('corners') :
        corners = options['corners']

    for index in xrange(numfaces):
        if (corners is not None) :
            if (index+1 > len(corners)) or not corners[index] :
                curve_pts.append(coords[index])
                continue

        if (index) :
            prev = index - 1
        else :
            prev = numfaces - 1
        if (index > numfaces - 2) :
            next = 0
        else :
            next = index + 1
        anglecoords = (coords[prev], coords[index], coords[next])
            
        quad_pts = rounded_angle_coords(anglecoords, radius)[0]
        curve_pts.extend(quad_pts)
    return curve_pts


def polyline_coords(coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::polyline_coords
    # retourne les coordonnées d'une polyline
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> liste de coordonnées des sommets de la polyline
    # options :
    #  -radius : <dimension> rayon global de raccord d'angle
    # -corners : <booleanList> liste des raccords de sommets [0|1]
    #            par défaut [1,1,1,1],
    # -corners_radius : <dimensionList> liste des rayons de raccords de sommets
    #---------------------------------------------------------------------------
    """
    numfaces = len(coords)
    curve_pts = []

    if (options.has_key('radius')) :
        radius = options['radius']
    else:
        radius = 0
    if options.has_key('corners_radius'):
        corners_radius = options['corners_radius']
        corners = corners_radius
    else:
        corners_radius = None
        if options.has_key('corners'):
            corners = options['corners']
        else:
            corners = None

    for index in xrange(0, numfaces):
        if (corners is not None
            and (len(corners) - 1 < index
                 or not corners[index])):
            curve_pts.append(coords[index])
        else :
            if (index) :
                prev = index - 1
            else:
                prev = numfaces - 1
            if (index > numfaces - 2) :
                next = 0
            else:
                next = index + 1
            anglecoords = (coords[prev], coords[index], coords[next])

            if (corners_radius) :
                rad = corners_radius[index]
            else:
                rad = radius
            quad_pts = rounded_angle_coords(anglecoords, rad)[0]
            curve_pts.extend(quad_pts)

    return curve_pts

def pathline_coords (coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::pathline_coords
    # retourne les coordonnées d'une pathline
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> liste de coordonnées des points du path
    # options :
    #    -closed : <boolean> ligne fermée
    #  -shifting : <out|center|in> sens de décalage du path (par défaut center)
    # -linewidth : <dimension> epaisseur de la ligne
    #---------------------------------------------------------------------------
    """
    numfaces = len(coords)
    pts = []

    if options.has_key('closed'):
        closed = options['closed']
    else:
        closed = None
    if (options.has_key('linewidth')) :
        linewidth = options['linewidth']
    else:
        linewidth = 2
          
    if (options.has_key('shifting')) :
        shifting = options['shifting']
    else:
        shifting = 'center'

    if ( not numfaces or linewidth < 2):
        raise ValueError("Invalid PathLine_coords")

    if (closed) :
        previous = coords[numfaces - 1]
    else:
        previous = None
      
    next = coords[1]
    if (shifting == 'center'):
        linewidth /= 2

    for i in xrange(0, numfaces):
        pt = coords[i]

        if (previous is None) :
            # extrémité de curve sans raccord -> angle plat
            previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))

        (angle, bisecangle) = vertex_angle(previous, pt, next)

        # distance au centre du cercle inscrit : rayon/sinus demi-angle
        asin = sin(radians(angle/2))
        if (asin) :
            delta = abs(linewidth / asin)
        else:
            delta = linewidth

        if (shifting == 'out' or shifting == 'in') :
            if (shifting == 'out') :
                adding = -90
            else:
                adding = 90
            pts.append(rad_point(pt, delta, bisecangle + adding))
            pts.append(pt)

        else :
            pts.append(rad_point(pt, delta, bisecangle-90))
            pts.append(rad_point(pt, delta, bisecangle+90))

        if (i == numfaces - 2) :
            if (closed) :
                next = coords[0]
            else:
                next = (coords[i+1][0] + (coords[i+1][0] - pt[0]),
                        coords[i+1][1] + (coords[i+1][1] - pt[1]))
        elif (i == numfaces - 1):
            next = None
        else :
            next = coords[i+2]
    
        previous = coords[i]

    if (closed) :
        pts.extend((pts[0], pts[1], pts[2], pts[3]))

    return pts


def curveline_coords(coords, **options) :
    """
    #---------------------------------------------------------------------------
    # Graphics::curveline_coords
    # retourne les coordonnées d'une curveLine
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> liste de coordonnées des points de la ligne
    # options :
    #    -closed : <boolean> ligne fermée
    #  -shifting : <out|center|in> sens de décalage du contour
    #              (par défaut center)
    # -linewidth : <dimension> epaisseur de la ligne
    #---------------------------------------------------------------------------
    """
    numfaces = len(coords)
    gopts = []
    backpts = []
    pts = []

    if options.has_key('closed'):
        closed = options['closed']
    else:
        closed = None
    if (options.has_key('linewidth')) :
        linewidth = options['linewidth']
    else:
        linewidth = 2
    if (options.has_key('shifting')) :
        shifting = options['shifting']
    else:
        shifting = 'center'

    if( not numfaces or linewidth < 2):
        raise ValueError("Bad coords %s or linewidth %s"%(numfaces, linewidth))

    if (closed) :
        previous = coords[numfaces - 1]
    else:
        previous = None
        
    next = coords[1]
    if (shifting == 'center'):
        linewidth /= 2 

    for i in xrange(0, numfaces):
        pt = coords[i]

        if ( previous is None ) :
            # extrémité de curve sans raccord -> angle plat
            previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
            

        (angle, bisecangle) = vertex_angle(previous, pt, next)

        # distance au centre du cercle inscrit : rayon/sinus demi-angle
        asin = sin(radians(angle/2))
        if (asin) :
            delta = abs(linewidth / asin)
        else:
            delta = linewidth

        if (shifting == 'out' or shifting == 'in') :
            if (shifting == 'out') :
                adding = -90
            else:
                adding = 90
            pts.append(rad_point(pt, delta, bisecangle + adding))
            pts.append(pt)

        else :
            pts = rad_point(pt, delta, bisecangle+90)
            gopts.append(pts)
            pts = rad_point(pt, delta, bisecangle-90)
            backpts.insert(0, pts)

        if (i == numfaces - 2) :
            if (closed) :
                next = coords[0]
            else:
                next = (coords[i+1][0] +
                        (coords[i+1][0] - pt[0]), coords[i+1][1]
                        + (coords[i+1][1] - pt[1]))
        else :
            next = coords[i+2]

        previous = coords[i]

    gopts.extend(backpts)

    if (closed) :
        gopts.extend ((gopts[0], gopts[1]))

    return gopts


def shiftpath_coords(coords, **options) :
    """
    #---------------------------------------------------------------------------
    # Graphics::shiftpath_coords
    # retourne les coordonnées d'un décalage de path
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordsList> liste de coordonnées des points du path
    # options :
    #   -closed : <boolean> ligne fermée
    # -shifting : <'out'|'in'> sens de décalage du path (par défaut out)
    #    -width : <dimension> largeur de décalage (par défaut 1)
    #---------------------------------------------------------------------------
    """
    numfaces = len(coords)

    if options.has_key('closed'):
        closed = options['closed']
    else:
        closed = None
    if (options.has_key('width')) :
        width = options['width']
    else:
        width = 1
    if (options.has_key('shifting')) :
        shifting = options['shifting']
    else:
        shifting = 'out'

    if (not numfaces or not width):
        return coords 

    pts = []
    
    if (closed) :
        previous = coords[numfaces - 1]
    else:
        previous = None
    next = coords[1]

    for i in xrange(0, numfaces):
        pt = coords[i]

        if ( previous is None ) :
            # extrémité de curve sans raccord -> angle plat
            previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
            

        (angle, bisecangle) = vertex_angle(previous, pt, next)

        # distance au centre du cercle inscrit : rayon/sinus demi-angle
        asin = sin(radians(angle/2))
        if (asin) :
            delta = abs(width / asin)
        else:
            delta = width

        if (shifting == 'out') :
            adding = -90
        else:
            adding = 90
        (x, y) = rad_point(pt, delta, bisecangle + adding)
        pts.append((x, y))


        if (i > numfaces - 3) :
            if (closed) :
                next = coords[0]
            else:
                next = (pt[0] + (pt[0] - previous[0]),
                        pt[1] + (pt[1] - previous[1]))

        else :
            next = coords[i+2]

        previous = coords[i]

    return pts




def curveitem2polyline_coords(widget, item, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::curveitem2polyline_coords
    # Conversion des coordonnées Znitem curve (multicontours)
    # en coordonnées polyline(s)
    #---------------------------------------------------------------------------
    # paramètres :
    # widget : <widget> identifiant du widget zinc
    #   item : <tagOrId> identifiant de l'item source
    # options :
    # -tunits : <integer> nombre pas de division des segments bezier
    #           (par défaut 20)
    # -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
    #---------------------------------------------------------------------------
    """
    if (not widget.type(item)):
        raise ValueError("Item Not Found")
    coords = []
    numcontours = widget.contour(item)
    #parentgroup = widget.group(item)

    for contour in xrange(0, numcontours):
        points = widget.coords(item, contour)
        contourcoords = curve2polyline_coords(points, **options)

        coords.append(contourcoords)

    return coords

def curve2polyline_coords(points, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::curve2polyline_coords
    # Conversion curve -> polygone
    #---------------------------------------------------------------------------
    # paramètres :
    # points : <coordsList> liste des coordonnées curve à transformer
    # options :
    # -tunits : <integer> nombre pas de division des segments bezier
    #           (par défaut 20)
    # -adjust : <boolean> ajustement de la courbe de bezier (par défaut 1)
    #---------------------------------------------------------------------------
    """
    if (options.has_key('tunits')) :
        tunits = options['tunits']
    else:
        tunits = 20
    if (options.has_key('adjust')) :
        adjust = options['adjust']
    else:
        adjust = 1

    poly = []
    previous = None
    bseg = []
    numseg = 0
    #prevtype = None

    for point in points:
        if len(point) == 3:
            (x, y, c) = point
        elif len(point) == 2:
            (x, y, c) = (point, None)
        else:
            ValueError("Bad point")
        if (c == 'c') :
            if not len(bseg) and previous:
                bseg.append(previous)
            bseg.append(point)
            
        else :
            if (len (bseg)) :
                bseg.append(point)
                if (adjust) :
                    pts = bezier_compute(bseg, skipend = 1)
                    del pts[0]
                    del pts[0]
                    poly.extend(pts)
                     
                else :
                    pts = bezier_segment(bseg, tunits = tunits, skipend = 1)
                    del pts[0]
                    del pts[0]
                    poly.extend(pts)

                bseg = []
                numseg += 1
                #prevtype = 'bseg'

            else :
                poly.append((x, y))
                #prevtype = 'line'

        previous = point


    return poly


def build_tabboxitem(widget, parentgroup, **options):
    """
    #-------------------------------------------------------------------------------
    # Graphics::build_tabboxitem
    # construit les items de représentations Zinc d'une boite à onglets
    #-------------------------------------------------------------------------------
    # paramètres :
    #      widget : <widget> identifiant du widget zinc
    # parentgroup : <tagOrId> identifiant de l'item group parent
    #
    #    options :
    #     -coords : <coordsList> coordonnées haut-gauche et bas-droite
    #               du rectangle
    #               englobant du Tabbox
    #     -params : <hastable> arguments spécifiques des items curve
    #               à passer au widget
    #    -texture : <imagefile> ajout d'une texture aux items curve
    #  -tabtitles : <hashtable> table de hash de définition des titres onglets
    #  -pageitems : <hashtable> table de hash de définition des pages internes
    #     -relief : <hashtable> table de hash de définition du relief de forme
    #
    # (options de construction géometrique passées à tabbox_coords)
    #  -numpages : <integer> nombre de pages (onglets) de la boite
    #    -anchor : <'n'|'e'|'s'|'w'> ancrage (positionnement) de la ligne
    #              d'onglets
    # -alignment : <'left'|'center'|'right'> alignement des onglets sur le coté
    #              d'ancrage
    #  -tabwidth : <'auto'>|<dimension>|<dimensionList> : largeur des onglets
    #              'auto' largeur répartie, les largeurs sont auto-ajustée
    #              si besoin.
    # -tabheight : <'auto'>|<dimension> : hauteur des onglets
    #  -tabshift : <'auto'>|<dimension> offset de 'biseau' entre base et haut de
    #              l'onglet (défaut auto)
    #    -radius : <dimension> rayon des arrondis d'angle
    #   -overlap : <'auto'>|<dimension> offset de recouvrement/séparation entre
    #              onglets
    #   -corners : <booleanList> liste 'spécifique' des raccords de sommets [0|1]
    #---------------------------------------------------------------------------
    """
    if options.has_key('coords') :
        coords = options['coords']
    else:
        raise ValueError("Coords needed")
    if options.has_key('params'):
        params = options['params']
    else:
        params = {}
    if params.has_key('tags'):
        tags = params['tags']
    else :
        tags = []
    texture = None

    if (options.has_key('texture')) :
        texture = get_texture(widget,
                             options['texture'])
        

    if options.has_key('tabtitles'):
        titlestyle = options['tabtitles']
    else :
        titlestyle = None
    if (titlestyle) :
        titles = titlestyle['text']
    else:
        titles = None

    tabs = []
    (shapes, tcoords, invert) = tabbox_coords(**options)
    if (invert) :
        k = len(shapes)
    else:
        k = -1
    shapes.reverse()
    for shape in shapes :
        if (invert) :
            k -= 1
        else :
            k += +1
        group = widget.add('group', parentgroup)
        params['tags'] = tags
        params['tags'] += (k, 'intercalaire')
        form = widget.add('curve',
                          group,
                          lpts2coords(shape),
                          **params)
        if texture :
            widget.itemconfigure(form, tile = texture)

        if (options.has_key('relief')) :
            graphicitem_relief(widget, form, **options['relief'])
            

        if (options.has_key('page')) :
            build_zinc_item(widget, group, **options['page'])
    
        if (titles) :
            if (invert) :
                tindex = k
            else:
                tindex = len(shapes) - k
            titlestyle['itemtype'] = 'text'
            titlestyle['coords'] = tcoords[tindex]
            titlestyle['params']['text'] = titles[tindex]
            ltags = list(tags)
            ltags.append(tindex)
            ltags.append('titre')
            titlestyle['params']['tags'] = tuple(ltags)
            build_zinc_item(widget, group, **titlestyle)

    return tabs


def tabbox_coords(coords, **options):
    """
    #---------------------------------------------------------------------------
    # tabbox_coords
    # Calcul des shapes de boites à onglets
    #---------------------------------------------------------------------------
    # paramètres :
    # coords : <coordList> coordonnées haut-gauche bas-droite du rectangle
    #          englobant de la tabbox
    # options
    #  -numpages : <integer> nombre de pages (onglets) de la boite
    #    -anchor : <'n'|'e'|'s'|'w'> ancrage (positionnement) de la
    #              ligne d'onglets
    # -alignment : <'left'|'center'|'right'> alignement des onglets
    #              sur le coté d'ancrage
    #  -tabwidth : <'auto'>|<dimension>|<dimensionList> : largeur des onglets
    #              'auto' largeur répartie, les largeurs sont auto-ajustée
    #               si besoin.
    # -tabheight : <'auto'>|<dimension> : hauteur des onglets
    #  -tabshift : <'auto'>|<dimension> offset de 'biseau' entre base et haut
    #              de l'onglet (défaut auto)
    #    -radius : <dimension> rayon des arrondis d'angle
    #   -overlap : <'auto'>|<dimension> offset de recouvrement/séparation
    #              entre onglets
    #   -corners : <booleanList> liste 'spécifique' des raccords
    #              de sommets [0|1]
    #---------------------------------------------------------------------------
    """
    (x_0, y_0) = coords[0]
    (x_n, y_n) = coords[1]
    shapes, titles_coords = [], []
    inverse = None

    #loptions = options.keys()
    if options.has_key('numpages'):
        numpages = options['numpages']
    else:
        numpages = 0
    
    if (not x_0 or not y_0 or not x_n or not y_n or not numpages) :
        raise ValueError("Vous devez au minimum spécifier\
        le rectangle englobant et le nombre de pages")

    if (options.has_key('anchor')) :
        anchor = options['anchor']
    else:
        anchor = 'n'
    if (options.has_key('alignment')) :
        alignment = options['alignment']
    else:
        alignment ='left'


    if (options.has_key('tabwidth')) :
        nlen = options['tabwidth']
    else:
        nlen ='auto'
    if (options.has_key('tabheight')) :
        thick = options['tabheight']
    else:
        thick ='auto'
    if (options.has_key('tabshift')) :
        biso = options['tabshift']
    else:
        biso = 'auto'
    if (options.has_key('radius')) :
        radius = options['radius']
    else:
        radius = 0
    if (options.has_key('overlap')) :
        overlap = options['overlap']
    else:
        overlap = 0
    if (options.has_key('corners')):
        corners = options['corners']
    else:
        corners = None
    if (anchor in ( 'n', 's')) :
        orientation = 'horizontal'
    else:
        orientation = 'vertical'
    if (orientation == 'horizontal') :
        maxwidth = (x_n - x_0)
    else:
        maxwidth = (y_n - y_0)
    tabswidth = 0
    align = 1

    if (nlen == 'auto') :
        tabswidth = maxwidth
        nlen = float(tabswidth + (overlap * (numpages - 1)))/numpages
    else :
        if (type(nlen) in (types.TupleType, types.ListType )) :
            for w in nlen :
                tabswidth += (w - overlap)
      
            tabswidth += overlap
        else :
            tabswidth = (nlen * numpages) - (overlap * (numpages - 1))
    

        if (tabswidth > maxwidth) :
            tabswidth = maxwidth
            nlen = float(tabswidth + (overlap * (numpages - 1)))/numpages

        if (alignment == 'center' and ((maxwidth - tabswidth) > radius)):
            align = 0 


    if (thick == 'auto') :
        if (orientation == 'horizontal') :
            thick = int((y_n - y_0)/10)
        else:
            thick = int((x_n - y_0)/10)
        thick = max(10, thick) 
        thick = min(40, thick)

    if (biso == 'auto') :
        biso = int(thick/2)

    if ((alignment == 'right' and anchor != 'w') or
        (anchor == 'w' and alignment != 'right')) :

        if (type(nlen) in (types.TupleType, types.ListType)) :
            for p in xrange(0, numpages):
                nlen[p] *= -1
        else :
            nlen *= -1
        biso *= -1
        overlap *= -1

    if (alignment == 'center') :
        (biso1, biso2) = (biso/2, biso/2)
    else:
        (biso1, biso2) = (0, biso)

    cadre, tabdxy = [], []
    xref, yref = 0, 0
    if (orientation == 'vertical') :
        if (anchor == 'w'):
            thick *= -1 
        if (anchor == 'w') :
            (startx, endx) = (x_0, x_n)
        else:
            (startx, endx) = (x_n, x_0)
        if ((anchor == 'w' and alignment != 'right') or 
            (anchor == 'e' and alignment == 'right')) :
            (starty, endy) = (y_n, y_0)
        else:
            (starty, endy) = (y_0, y_n)

        xref = startx - thick
        yref = starty
        if  (alignment == 'center') :
            if (anchor == 'w') :
                ratio = -2
            else:
                ratio = 2
            yref += (float(maxwidth - tabswidth)/ratio)

        cadre = ((xref, endy), (endx, endy), (endx, starty), (xref, starty))

        # flag de retournement de la liste des pts de curve si nécessaire
        # -> sens anti-horaire
        inverse = (alignment == 'right')

    else :
        if (anchor == 's'):
            thick *= -1
            (starty, endy) = (y_n, y_0)
        else :
            (starty, endy) = (y_0, y_n)
            
        if (alignment == 'right') :
            (startx, endx) = (x_n, x_0)
        else:
            (startx, endx) = (x_0, x_n)


        yref = starty + thick
        if (alignment == 'center') :
            xref = x_0 + (float(maxwidth - tabswidth)/2)
        else :
            xref = startx

        cadre = ((endx, yref), (endx, endy), (startx, endy), (startx, yref))

        # flag de retournement de la liste des pts de curve si nécessaire
        # -> sens anti-horaire
        inverse = ((anchor == 'n' and alignment != 'right')
                   or (anchor == 's' and alignment == 'right'))
         
        
    for i in xrange(0, numpages):
        pts = []

        # décrochage onglet
        #push (pts, ([xref, yref])) if i > 0

        # cadre
        pts.extend(cadre)

        # points onglets
        if (i > 0 or not align) :
            pts.append((xref, yref)) 

        if (type(nlen) in (types.TupleType, types.ListType)) :
            tw = nlen[i]
        else:
            tw = nlen

        if (type(nlen) in (types.TupleType, types.ListType)) :
            slen = len(nlen)
        else:
            slen = nlen
        
        if (orientation == 'vertical') :
            tabdxy = ((thick, biso1), (thick, tw - biso2), (0, tw))
        else:
            tabdxy = ((biso1, -thick), (tw - biso2, -thick), (tw, 0))
        for delta_xy in tabdxy :
            pts.append((xref + delta_xy[0], yref + delta_xy[1]))
    

        if (radius) :
            if (not options.has_key('corners')) :
                if (i > 0 or not align) :
                    corners =  (0, 1, 1, 0, 0, 1, 1, 0)
                else :
                    corners = (0, 1, 1, 0, 1, 1, 0, 0, 0)
      
            curvepts = roundedcurve_coords(pts,
                                          radius = radius,
                                          corners = corners)
            lcurvepts = list(curvepts)
            if (inverse):
                lcurvepts.reverse()
            shapes.append(lcurvepts)
        else :
            if (inverse):
                pts.reverse()
            shapes.append(pts)

        if (orientation == 'horizontal') :
            titles_coords.append((float(xref) + (tw - (biso2 - biso1))/2,
                                  float(yref) - (thick/2)))
            xref += (tw - overlap)

        else :
            titles_coords.append( (float(xref) + (thick/2),
                                   yref + (slen - ((biso2 - biso1)/2))/2))
            yref += (slen - overlap)
            
    return (shapes, titles_coords, inverse)


def graphicitem_relief(widget, item, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::graphicitem_relief
    # construit un relief à l'item Zinc en utilisant des items Triangles
    #---------------------------------------------------------------------------
    # paramètres :
    #  widget : <widget> identifiant du widget zinc
    #    item : <tagOrId> identifiant de l'item zinc
    # options : <hash> table d'options
    #     -closed : <boolean> le relief assure la fermeture de forme (défaut 1)
    #     -profil : <'rounded'|'flat'> type de profil (defaut 'rounded')
    #     -relief : <'raised'|'sunken'> (défaut 'raised')
    #       -side : <'inside'|'outside'> relief interne ou externe à la forme
    #               (défaut 'inside')
    #      -color : <color> couleur du relief (défaut couleur de la forme)
    #   -smoothed : <boolean> facettes relief lissées ou non (défaut 1)
    # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
    #      -width : <dimension> 'épaisseur' du relief en pixel
    #       -fine : <boolean> mode précision courbe de bezier
    #               (défaut 0 : auto-ajustée)
    #-------------------------------------------------------------------------------
    """
    items = []

    # relief d'une liste d'items -> appel récursif
    if (type(item) in (types.TupleType, types.ListType)) :
        for part in item :
            items.extend(graphicitem_relief(widget, part, **options))
    else :
        itemtype = widget.type(item)
        if not itemtype:
            raise ValueError("Bad Item")

        parentgroup = widget.group(item)
        if (options.has_key('priority')) :
            priority = options['priority']
        else :
            priority = widget.itemcget(item, 'priority')+1

        # coords transformés (polyline) de l'item
        adjust = not options['fine']
        for coords in zincitem_2_curvecoords(widget,
                                           item, linear = 1,
                                           realcoords = 1,
                                           adjust = adjust) :
            (pts, colors) = polyline_relief_params(widget,
                                                 item,
                                                 coords,
                                                 **options)

            items.append(widget.add('triangles',
                                    parentgroup,
                                    pts,
                                    priority = priority,
                                    colors = colors))


        # renforcement du contour
        if (widget.itemcget(item, 'linewidth')) :
            items.append(widget.clone(item,
                                      filled = 0,
                                      priority = priority+1))

    return items


def polyline_relief_params(widget, item, coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::polyline_relief_params
    # retourne la liste des points et des couleurs nécessaires à la construction
    # de l'item Triangles du relief
    #---------------------------------------------------------------------------
    # paramètres :
    #  widget : <widget> identifiant widget Zinc
    #    item : <tagOrId> identifiant item Zinc
    # options : <hash> table d'options
    #     -closed : <boolean> le relief assure la fermeture de forme (défaut 1)
    #     -profil : <'rounded'|'flat'> type de profil (defaut 'rounded')
    #     -relief : <'raised'|'sunken'> (défaut 'raised')
    #       -side : <'inside'|'outside'> relief interne ou externe à la forme
    #               (défaut 'inside')
    #      -color : <color> couleur du relief (défaut couleur de la forme)
    #   -smoothed : <boolean> facettes relief lissées ou non (défaut 1)
    # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
    #      -width : <dimension> 'épaisseur' du relief en pixel
    #---------------------------------------------------------------------------
    """

    if (options.has_key('closed')) :
        closed = options['closed']
    else:
        closed = 1
    if (options.has_key('profil')) :
        profil = options['profil']
    else:
        profil = 'rounded'
    if (options.has_key('relief')) :
        relief = options['relief']
    else :
        relief = 'raised'
    if (options.has_key('side')) :
        side = options['side']
    else:
        side = 'inside'
    if (options.has_key('color')) :
        basiccolor = options['color']
    else:
        basiccolor = zincitem_predominantcolor(widget, item)
    if (options.has_key('smooth')) :
        smoothed = options['smooth']
    else:
        smoothed = 1
    if (options.has_key('lightangle')) :
        lightangle = options['lightangle']
    else:
        lightangle = widget.cget('lightangle')

    if options.has_key('width'):
        width = options['width']
    else:
        raise ValueError('Options must have width field')
    if ( width < 1) :
        (x_0, y_0, x_1, y_1) = widget.bbox(item)
        width = min(x_1 -x_0, y_1 - y_0)/10
        if (width < 2) :
            width = 2

    numfaces = len(coords)
    if (closed):
        previous = coords[numfaces - 1]
    else:
        previous = None
    next = coords[1]

    pts = []
    colors = []
    alpha = 100
    m = re.compile("^(?P<color>#[0-9a-fA-F]{6});(?P<alpha>\d{1,2})$")
    res = m.match(basiccolor)
    if (res is not None) :
        (basiccolor, alpha) = res.group('color'), res.group('alpha')

    if ( options.has_key('color')):
        color = options['color']
        res = m.match(color)
        if ((res is None) and (profil == 'flat')):
            alpha /= 2

    if (profil == 'rounded') :
        reliefalphas = [0, alpha]
    else:
        reliefalphas = [alpha, alpha]

    for i in xrange(0, numfaces):
        pt = coords[i]

        if (previous) :
            # extrémité de curve sans raccord -> angle plat
            previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))
    

        (angle, bisecangle) = vertex_angle(previous, pt, next)

        # distance au centre du cercle inscrit : rayon/sinus demi-angle
        asin = sin(radians(angle/2))
        if (asin) :
            delta = abs(width / asin)
        else:
            delta = width
        if (side == 'outside') :
            decal = -90
        else:
            decal = 90

        shift_pt = rad_point(pt, delta, bisecangle+decal)
        pts.append(shift_pt)
        pts.append(pt)

        if (smoothed and i) :
            pts.append(shift_pt)
            pts.append(pt)
    

        faceangle = 360 -(linenormal(previous, next)+90)

        light = abs(lightangle - faceangle)
        if (light > 180):
            light = 360 - light
        if light < 1:
            light = 1 

        if (relief == 'sunken') :
            lumratio = (180-light)/180
        else:
            lumratio = light/180

        if ( not smoothed and i) :
            #A VOIR
            #OBSCURE
            colors.extend((colors[-2], colors[-1]))

        if (basiccolor) :
            # création des couleurs dérivées
            shade = lightingcolor(basiccolor, lumratio)
            color0 = "%s;%s"% (shade, reliefalphas[0])
            color1 = "%s;%s"% (shade, reliefalphas[1])
            colors.extend((color0, color1))

        else :
            c = (255*lumratio)
            color0 = hexargbcolor(c, c, c, reliefalphas[0])
            color1 = hexargbcolor(c, c, c, reliefalphas[1])
            colors.extend((color0, color1))
    

        if (i == (numfaces - 2)) :
            if (closed) :
                next = coords[0]
            else:
                next = (coords[i+1][0] + (coords[i+1][0] - pt[0]),
                        coords[i+1][1] + (coords[i+1][1] - pt[1]))
        else :
            next = coords[i+2]

        previous = coords[i]

    if (closed) :
        pts.extend((pts[0], pts[1], pts[2], pts[3]))
        colors.extend((colors[0], colors[1]))

        if (not smoothed) :
            pts.extend((pts[0], pts[1], pts[2], pts[3]))
            colors.extend((colors[0], colors[1]))
    
    return (pts, colors)


def graphicitem_shadow(widget, item, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::graphicitem_shadow
    # Création d'une ombre portée à l'item
    #---------------------------------------------------------------------------
    # paramètres :
    #  widget : <widget> identifiant widget Zinc
    #    item : <tagOrId> identifiant item Zinc
    # options : <hash> table d'options
    #    -opacity : <percent> opacité de l'ombre (défaut 50)
    #     -filled : <boolean> remplissage totale de l'ombre (hors bordure) (defaut 1)
    # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
    #   -distance : <dimension> distance de projection de l'ombre en pixel
    #  -enlarging : <dimension> grossi de l'ombre portée en pixels (defaut 0)
    #      -width : <dimension> taille de diffusion/diffraction (défaut 4)
    #      -color : <color> couleur de l'ombre portée (défaut black)
    #---------------------------------------------------------------------------
    """
    items = []

    # relief d'une liste d'items -> appel récursif
    if (type(item) in (types.TupleType, types.ListType)) :
        for part in item :
            items.append(graphicitem_shadow(widget, part, **options))
        return items

    else :

        itemtype = widget.type(item)

        if not itemtype :
            raise ValueError("Not a valid Item Id %s"%item)

        # création d'un groupe à l'ombre portée
        if (options.has_key('parentgroup')) :
            parentgroup = options['parentgroup']
        else:
            parentgroup = widget.group(item)
        if (options.has_key('priority')) :
            priority = options['priority']
        else:
            priority = widget.itemcget(item, 'priority')-1
        priority = max(0, priority) 

        shadow = widget.add('group', parentgroup, priority = priority)
            
        if (itemtype == 'text') :
            if (options.has_key('opacity')) :
                opacity = options['opacity']
            else:
                opacity = 50
            if (options['color']) :
                color = options['color']
            else:
                color = '#000000'
            
            clone = widget.clone(item, color = "%s;%s"% (color, opacity))
            widget.chggroup(clone, shadow)

        else :

            # création des items (de dessin) de l'ombre
            if ( options.has_key('filled')) :
                filled = options['filled']
            else:
                filled = 1
      
            # coords transformés (polyline) de l'item
            for coords in zincitem_2_curvecoords(widget,
                                               item,
                                               linear = 1,
                                               realcoords = 1) :
                (t_pts, i_pts, colors) = polyline_shadow_params( coords,
                                                               **options)
                
                # option filled : remplissage hors bordure
                # de l'ombre portée (item curve)
                if (filled) :
                    if (len(items)) :
                        widget.contour(items[0], 'add', 0, i_pts)
	
                    else :
                        items.append( widget.add('curve', shadow, i_pts,
                                                  linewidth = 0,
                                                  filled = 1,
                                                  fillcolor = colors[0],
                                                  ))
                        
                # bordure de diffusion de l'ombre (item triangles)
                items.append( widget.add('triangles', shadow, t_pts,
                                          colors = colors))
      

        # positionnement de l'ombre portée
        if (options.has_key('distance')) :
            distance = options['distance']
        else:
            distance = 10
        if (options.has_key('lightangle')) :
            lightangle = options['lightangle']
        else:
            lightangle = widget.cget('lightangle')

        (delta_x, delta_y) = rad_point((0, 0),
                             distance,
                             lightangle+180)
        widget.translate(shadow, delta_x, -delta_y)

    return shadow


def polyline_shadow_params(coords, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::polyline_shadow_params
    # retourne les listes des points et de couleurs nécessaires à la 
    # construction des items triangles (bordure externe) et curve
    # (remplissage interne) de l'ombre portée
    #---------------------------------------------------------------------------
    # paramètres :
    #    coords : coordonnées
    # options : <hash> table d'options
    #    -opacity : <percent> opacité de l'ombre (défaut 50)
    # -lightangle : <angle> angle d'éclairage (défaut valeur générale widget)
    #   -distance : <dimension> distance de projection de l'ombre en pixel
    #               (défaut 10)
    #  -enlarging : <dimension> grossi de l'ombre portée en pixels (defaut 2)
    #      -width : <dimension> taille de diffusion/diffraction
    #               (défaut distance -2)
    #      -color : <color> couleur de l'ombre portée (défaut black)
    #---------------------------------------------------------------------------
    """
    if (options.has_key('distance')) :
        distance = options['distance']
    else:
        distance = 10
    if (options.has_key('width')) :
        width = options['width']
    else:
        width = distance-2
    if (options.has_key('opacity')) :
        opacity = options['opacity']
    else:
        opacity = 50
    if (options.has_key('color')) :
        color = options['color']
    else:
        color ='#000000'
    if (options.has_key('enlarging')) :
        enlarging = options['enlarging']
    else :
        enlarging = 2

    if (enlarging) :
        coords = shiftpath_coords(coords,
                                 width = enlarging,
                                 closed = 1,
                                 shifting = 'out')

    numfaces = len(coords)
    previous = coords[numfaces - 1]
    next = coords[1]

    t_pts = []
    i_pts = []
    colors = []
    (color0, color1) = ("%s;%s"% (color, opacity), "%s;0"% color)

    for i in xrange(0, numfaces):
        pt = coords[i]

        #A VOIR
        #Je ne vois pas quand cela peut arriver
        if (not previous) :
            # extrémité de curve sans raccord -> angle plat
            previous = (pt[0] + (pt[0] - next[0]), pt[1] + (pt[1] - next[1]))

        (angle, bisecangle) = vertex_angle(previous, pt, next)

        # distance au centre du cercle inscrit : rayon/sinus demi-angle
        asin = sin(radians(angle/2))
        if (asin) :
            delta = abs(width / asin)
        else :
            delta =  width
        decal = 90

        shift_pt = rad_point(pt, delta, bisecangle+decal)
        i_pts.append(shift_pt)
        t_pts.append(shift_pt)
        t_pts.append(pt)
        
        colors.append(color0)
        colors.append(color1)
        if (i == numfaces - 2) :
            next = coords[0]
        else :
            next = coords[i+2]

        previous = coords[i]

    # fermeture
    t_pts.extend((t_pts[0], t_pts[1], t_pts[2], t_pts[3]))
    i_pts.extend((t_pts[0], t_pts[1]))
    colors.extend((color0, color1, color0, color1))

    return (t_pts, i_pts, colors)





#Local Variables:
#mode : python
#tab-width: 4
#end:

Added jni/tkzinc/Python/library/pictorial.py.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
# -*- coding: iso-8859-1 -*-
#  Pictorial Functions  :
#  ----------------------
#      set_gradients
#      get_pattern
#      get_texture
#      get_image
#      init_pixmaps
#      zincitem_predominantcolor
#      zncolor_to_rgb
#      hexargbcolor
#      create_graduate
#      path_graduate
#      mediancolor
#      lightingcolor
#      rgb_to_lch
#      lch_to_rgb
#      rgb_to_hls
#      hls_to_rgb

import PIL.Image, PIL.ImageTk
import re
from math import pi, radians, atan2, sqrt, sin, cos

# initialisation et partage de ressources couleurs et images
textures = {}
IMAGES = {}
bitmaps = {}
AVERAGE_COLOR = '#777777'


_GRADIENTS = []

# constante white point (conversion couleur espace CIE XYZ)
(Xw, Yw, Zw) = (95.047, 100.0, 108.883)

def set_gradients(zinc, **grads):
    """
    #---------------------------------------------------------------------------
    # Graphics::set_gradients
    # création de gradient nommés Zinc
    #---------------------------------------------------------------------------
    # paramètres :
    #   widget : <widget> identifiant du widget zinc
    #    **grads : <dictionnaire> de définition de couleurs zinc
    #---------------------------------------------------------------------------
    """
    global _GRADIENTS
    if (not _GRADIENTS):
        _GRADIENTS = []
        for (name, gradient) in grads.items():
            zinc.gname(gradient, name)
            _GRADIENTS.append(name)

def rgb_dec2hex(rgb):
    """
    #---------------------------------------------------------------------------
    # Graphics::rgb_dec2hex
    # conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
    #---------------------------------------------------------------------------
    # paramètres :
    #  rgb : <rgbColorList> liste de couleurs au format RGB
    #---------------------------------------------------------------------------
    """
    return "#%04x%04x%04x"% rgb

def path_graduate(zinc, numcolors, style):
    """
    #---------------------------------------------------------------------------
    # Graphics::path_graduate
    # création d'un jeu de couleurs dégradées pour item pathline
    #---------------------------------------------------------------------------
    """
    typ = style['type']
    if (typ == 'linear'):
        return create_graduate(numcolors, style['colors'], 2)
    elif (typ == 'double'):
        colors1 = create_graduate(numcolors/2+1,
                                 style['colors'][0])
        colors2 = create_graduate(numcolors/2+1,
                                 style['colors'][1])
        colors = []
        for i in xrange(numcolors+1):
            colors.extend([colors1[i], colors2[i]])
        return colors
    elif (typ == 'transversal'):
        (c1, c2) = style['colors']
        colors = [c1, c2]
        for i in xrange(numcolors):
            colors.extend([c1, c2])

    return colors

def create_graduate(totalsteps, refcolors, repeat = 1):
    """
    #---------------------------------------------------------------------------
    # Graphics::create_graduate
    # création d'un jeu de couleurs intermédiaires (dégradé) entre n couleurs
    #---------------------------------------------------------------------------
    """
    colors = []

    numgraduates = len(refcolors) - 1
    if (numgraduates < 1):
        raise ValueError("Le degradé necessite\
        au moins 2 couleurs de référence...")
    steps = None
    if (numgraduates > 1):
        steps = totalsteps/(numgraduates - 1)
    else:
        steps = totalsteps

    for c in xrange(numgraduates):
        (c1, c2) = (refcolors[c], refcolors[c + 1])

        for i in xrange(steps):
            color = mediancolor(c1, c2, i / (steps - 1))
            for it in xrange(repeat):
                colors.append(color)

        if (c < numgraduates - 1):
            for k in xrange(repeat):
                colors.pop()

    return colors

def lightingcolor (color, new_l) :
    """
    #---------------------------------------------------------------------------
    # Graphics::lightingcolor
    # modification d'une couleur par sa composante luminosité
    #---------------------------------------------------------------------------
    # paramètres :
    #  color : <color> couleur au format zinc
    #   new_l : <pourcent> (de 0 à 1) nouvelle valeur de luminosité
    #---------------------------------------------------------------------------
    """
    (h, l, s) = 0, 0, 0
    rgb = hexa2rgb(color)
    h, l, s = rgb_to_hls(rgb)
    new_l = min(new_l, 1) 
    (n_r, n_g, n_b) = hls_to_rgb(h, new_l, s)
    return hexargbcolor(n_r*255, n_g*255, n_b*255)


def get_predominantcolor(colors):
    """
    #---------------------------------------------------------------------------
    # Graphics::get_predominantcolor
    # donne la couleur dominante
    #---------------------------------------------------------------------------
    # paramètres :
    #  colors : <color>* liste de couleurs au format zinc
    #---------------------------------------------------------------------------
    """
    (rs, gs, bs, as, numcolors) = (0, 0, 0, 0, 0)
    for color in colors :
        (r, g, b, a) = zncolor_to_rgb(color)
        rs += r
        gs += g
        bs += b
        as += a
        numcolors += 1

    new_r = int(rs/numcolors)
    new_g = int(gs/numcolors)
    new_b = int(bs/numcolors)
    new_a = int(as/numcolors)

    newcolor = hexargbcolor(new_r, new_g, new_b, new_a)
    return newcolor

def zincitem_predominantcolor(widget, item):
    """
    #---------------------------------------------------------------------------
    # Graphics::zincitem_predominantcolor
    # retourne la couleur dominante d'un item ('barycentre' gradiant fillcolor)
    #---------------------------------------------------------------------------
    # paramètres :
    #  widget : <widget> identifiant du widget zinc
    #    item : <tagOrId> identifiant de l'item zinc
    #---------------------------------------------------------------------------
    """
    typ = widget.type(item)
    if not typ :
        raise ValueError("Not a Valid Item %s" % item)
    if (typ == 'text' or typ == 'icon') :
        return widget.itemcget(item, 'color')

    elif (typ == 'triangles' or
          typ == 'rectangle' or
          typ == 'arc' or
          typ == 'curve') :

        colors = []

        if (typ == 'triangles') :
            colors =  widget.itemcget(item, 'colors')
        else :
            grad =  widget.itemcget(item, 'fillcolor')
            regexp = re.compile(
                "^=(?P<class>\w+)(?P<params>[^|]+)\|(?P<colorparts>.*)$")
            res = regexp.match(grad)
            if (res is None):
                #couleur simple
                return grad
            else:
                #Gradient
                colorspart = res.group('colorparts').split("|")
                regexp_color = re.compile("^(?P<color>^\S+).*") 
                for colorpart in colorspart:                  
                    res = regexp_color.match(colorpart)
                    if res:
                        colors.append(res.group('color'))
                    else :
                        raise ValueError("Impossible case!!")
        return get_predominantcolor(colors)
    else :
        return AVERAGE_COLOR

def mediancolor (color1, color2, rate) :
    """
    #---------------------------------------------------------------------------
    # Graphics::mediancolor
    # calcul d'une couleur intermédiaire défini par un ratio ($rate)
    # entre 2 couleurs
    #---------------------------------------------------------------------------
    # paramètres :
    #  color1 : <color> première couleur zinc
    #  color2 : <color> seconde couleur zinc
    #    rate : <pourcent> (de 0  à 1) position de la couleur intermédiaire
    #---------------------------------------------------------------------------
    """
    if (rate > 1):
        rate = 1
    if (rate < 0):
        rate = 0

    (r0, g0, b0, a0) = zncolor_to_rgb(color1)
    (r1, g1, b1, a1) = zncolor_to_rgb(color2)

    r = r0 + int((r1 - r0) * rate)
    g = g0 + int((g1 - g0) * rate)
    b = b0 + int((b1 - b0) * rate)
    a = a0 + int((a1 - a0) * rate)

    return hexargbcolor(r, g, b, a)


def zncolor_to_rgb (zncolor):
    """
    #---------------------------------------------------------------------------
    # Graphics::zncolor_to_rgb
    # conversion d'une couleur Zinc au format RGBA (255,255,255,100)
    #---------------------------------------------------------------------------
    # paramètres :
    #  zncolor : <color> couleur au format hexa zinc (#ffffff ou #ffffffffffff)
    #---------------------------------------------------------------------------
    """
    #Recherche du format d'entrée
    # ffffff ou ffffffffffff avec ou sans alpha
    #test présence alpha
    res = []
    res.append(
        re.match(
        "^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2});(?P<alpha>\d{1,3})$"
        ,zncolor))
    res.append(
        re.match(
        "^#([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4});(?P<alpha>\d{1,3})$"
        ,zncolor))
    #Pas de alpha
    res.append(re.match("^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$"
                        ,zncolor))
    res.append(re.match("^#([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})$"
                        ,zncolor))
    res.sort()
    resultat = res.pop()
    if res is None:
        raise ValueError("Not a valid zinc color")
    alpha = 100
    res = resultat.groupdict()
    if res.has_key('alpha'):
        alpha = int(res['alpha'])
    else:
        alpha = 100

    R = int(resultat.group(1), 16)
    G = int(resultat.group(2), 16)
    B = int(resultat.group(3), 16)

    return (R, G, B, alpha)

def rgb_to_lch(r, g, b) :
    """
    #---------------------------------------------------------------------------
    # ALGORYTHMES DE CONVERSION ENTRE ESPACES DE COULEURS
    #---------------------------------------------------------------------------
    #---------------------------------------------------------------------------
    # Graphics::rgb_to_lch
    # Algorythme de conversion RGB -> CIE LCH°
    #---------------------------------------------------------------------------
    # paramètres :
    #  r : <pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB
    #  g : <pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB
    #  b : <pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB
    #---------------------------------------------------------------------------
    """
    # Conversion RGBtoXYZ
    gamma = 2.4
    rgblimit = 0.03928

    if (r > rgblimit):
        r = ((r + 0.055)/1.055)**gamma
    else :
        r = r / 12.92

    if (g > rgblimit) :
        g = ((g + 0.055)/1.055)**gamma
    else:
        g = g / 12.92
      
    if (b > rgblimit) :
        b = ((b + 0.055)/1.055)**gamma
    else:
        b = b / 12.92

    r *= 100
    g *= 100
    b *= 100

    X = (0.4124 * r) + (0.3576 * g) + (0.1805 * b)
    Y = (0.2126 * r) + (0.7152 * g) + (0.0722 * b)
    Z = (0.0193 * r) + (0.1192 * g) + (0.9505 * b)

    # Conversion XYZtoLab
    gamma = 1/3
    (L, A, B) = 0, 0, 0

    if (Y == 0) :
        (L, A, B) = (0, 0, 0)
    else :
        #Utilisation des constantes white point (variables globale)
        (Xs, Ys, Zs) = (X/Xw, Y/Yw, Z/Zw)

    
        if (Xs > 0.008856) :
            Xs = Xs**gamma
        else :
            Xs = (7.787 * Xs) + (16/116)
            
        if (Ys > 0.008856) :
            Ys = Ys**gamma
        else :
            Ys = (7.787 * Ys) + (16/116)
            
        if (Zs > 0.008856) :
            Zs = Zs**gamma
        else :
            Zs = (7.787 * Zs) + (16/116)

        L = (116.0 * Ys) - 16.0

        A = 500 * (Xs - Ys)
        B = 200 * (Ys - Zs)

    # conversion LabtoLCH 
    (C, H) = 0, 0


    if (A == 0) :
        H = 0
    else :
        H = atan2(B, A)
    
        if (H > 0) :
            H = (H / pi) * 180

        else :
            H = 360 - ( abs(H) / pi) * 180



    C = sqrt(A**2 + B**2)
    
    return (L, C, H)

def lch_to_rgb (L, C, H) :
    """
    #---------------------------------------------------------------------------
    # Graphics::lch_to_rgb
    # Algorythme de conversion CIE L*CH -> RGB
    #---------------------------------------------------------------------------
    # paramètres :
    #  L : <pourcent> (de 0 à 1) valeur de la composante luminosité
    #  de la couleur CIE LCH
    #  C : <pourcent> (de 0 à 1) valeur de la composante saturation
    #  de la couleur CIE LCH
    #  H : <pourcent> (de 0 à 1) valeur de la composante teinte
    #  de la couleur CIE LCH
    #---------------------------------------------------------------------------
    """
    (a, b) = 0, 0
    
    # Conversion LCHtoLab
    a = cos( radians(H)) * C
    b = sin( radians(H)) * C
    
    # Conversion LabtoXYZ
    gamma = 3
    (X, Y, Z) = 0, 0, 0
    
    Ys = (L + 16.0) / 116.0
    Xs = (a / 500) + Ys
    Zs = Ys - (b / 200)
    
    if ((Ys**gamma) > 0.008856) :
        Ys = Ys**gamma
    else :
        Ys = (Ys - 16 / 116) / 7.787

    if ((Xs**gamma) > 0.008856) :
        Xs = Xs**gamma
    else :
        Xs = (Xs - 16 / 116) / 7.787
        
    if ((Zs**gamma) > 0.008856) :
        Zs = Zs**gamma
    else :
        Zs = (Zs - 16 / 116) / 7.787


    X = Xw * Xs
    Y = Yw * Ys
    Z = Zw * Zs

    # Conversion XYZtoRGB
    gamma = 1/2.4
    rgblimit = 0.00304
    (R, G, B) = (0, 0, 0)
    
    X /= 100
    Y /= 100
    Z /= 100

    R = (3.2410 * X) + (-1.5374 * Y) + (-0.4986 * Z)
    G = (-0.9692 * X) + (1.8760 * Y) + (0.0416 * Z)
    B = (0.0556 * X) + (-0.2040 * Y) + (1.0570 * Z)

    if (R > rgblimit) :
        R = (1.055 * (R**gamma)) - 0.055
    else :
        R = (12.92 * R)
        
    if (G > rgblimit) :
        G = (1.055 * (G**gamma)) - 0.055
    else :
        G = (12.92 * G)
        
    if (B > rgblimit) :
        B = (1.055 * (B**gamma)) - 0.055
    else :
        B = (12.92 * B)

    if (R < 0) :
        R = 0
    elif (R > 1.0) :
        R = 1.0
    else :
        R = _trunc(R, 5)
      
    if (G < 0) :
        G = 0
    elif (G > 1.0) :
        G = 1.0
    else :
        G = _trunc(G, 5)
      
    if (B < 0) :
        B = 0
    elif (B > 1.0) :
        B = 1.0
    else :
        B = _trunc(B, 5)

    return (R, G, B)

def rgb_to_hls(r, g, b):
    """
    #---------------------------------------------------------------------------
    # Graphics::rgb_to_hls
    # Algorythme de conversion RGB -> HLS
    #---------------------------------------------------------------------------
    #  r : <pourcent> (de 0 à 1) valeur de la composante rouge de la couleur RGB
    #  g : <pourcent> (de 0 à 1) valeur de la composante verte de la couleur RGB
    #  b : <pourcent> (de 0 à 1) valeur de la composante bleue de la couleur RGB
    #---------------------------------------------------------------------------
    """
    H, L, S = 0, 0, 0
    minv, maxv, diffv = 0, 0, 0 
    maxv = max(r, g, b)
    minv = min(r, g, b)

    # calcul de la luminosité
    L = (maxv + minv) / 2

    # calcul de la saturation
    if (maxv == minv) :
        # couleur a-chromatique (gris) r = g = b
        S = 0
        H = None
        return [H, L, S]

    # couleurs "Chromatiques" --------------------

    # calcul de la saturation
    if (L <= 0.5) :
        S = (maxv - minv) / (maxv + minv)

    else :
        S = (maxv - minv) / (2 - maxv - minv)

    # calcul de la teinte
    diffv = maxv - minv

    if (r == maxv) :
        # couleur entre jaune et magenta
        H = (g - b) / diffv

    elif (g == maxv) :
        # couleur entre cyan et jaune
        H = 2 + (b - r) / diffv

    elif (b == maxv) :
        # couleur entre magenta et cyan
        H = 4 + (r - g) / diffv

    # Conversion en degrés
    H *= 60

    # pour éviter une valeur négative
    if (H < 0) :
        H += 360

    return [H, L, S]

def hls_to_rgb (H, L, S):
    """
    #---------------------------------------------------------------------------
    # Graphics::hls_to_rgb
    # Algorythme de conversion HLS -> RGB
    #---------------------------------------------------------------------------
    # paramètres :
    #  H : <pourcent>(de 0 à 1) valeur de la composante teinte de la couleur HLS
    #  L : <pourcent>(de 0 à 1) valeur de la composante luminosité de la
    #      couleur HLS
    #  S : <pourcent>(de 0 à 1) valeur de la composante saturation
    #      de la couleur HLS
    #---------------------------------------------------------------------------
    """
    (R, G, B) = 0, 0, 0
    (p1, p2) = 0, 0


    if (L <= 0.5) : 
        p2 = L + (L * S)
    
    else :
        p2 = L + S - (L * S)

    p1 = 2.0 * L - p2

    if (S == 0) :
        # couleur a-chromatique (gris)
        # R = G = B = L
        R = L
        G = L
        B = L

    else :
        # couleurs "Chromatiques"
        R = hls_value(p1, p2, H + 120)
        G = hls_value(p1, p2, H)
        B = hls_value(p1, p2, H - 120)
    
    return [R, G, B]

def hls_value(q1, q2, hue):
    """
    #---------------------------------------------------------------------------
    # Graphics::hls_value (sous fonction interne hls_to_rgb)
    #---------------------------------------------------------------------------
    """
    value = None

    hue = hue % 360

    if (hue < 60) : 
        value = q1 + (q2 - q1) * hue / 60

    elif (hue < 180) : 
        value = q2

    elif (hue < 240) :
        value = q1 + (q2 - q1) * (240 - hue) / 60

    else :
        value = q1

    return value

def hexargbcolor(r, g, b, a = None):
    """
    #---------------------------------------------------------------------------
    # Graphics::hexargbcolor
    # conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
    #---------------------------------------------------------------------------
    """
    hexacolor = "#%02x%02x%02x"% (r, g, b)
    if ( a is not None ):
        hexacolor = "%s;%d"% (hexacolor, a)
    return hexacolor



def hexa2rgb(hexastr):
    """
    #---------------------------------------------------------------------------
    # Graphics::hexa2rgb
    # conversion d'une couleur au format Zinc '#ffffff' en RGB (255,255,255) 
    #---------------------------------------------------------------------------    
    """
    r, g, b = 0, 0, 0
    regex = re.compile("^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$")
    res = regex.match(hexastr)
    if res is not None :
        r = int(res.group(1), 16)
        g = int(res.group(2), 16)
        b = int(res.group(3), 16)
        return (r/255, g/255, b/255)
    else :
        raise ValueError("Not a hexa color")

def get_pattern (filename, **options):
    """
    #---------------------------------------------------------------------------
    # RESOURCES GRAPHIQUES PATTERNS, TEXTURES, IMAGES, GRADIENTS, COULEURS...
    #---------------------------------------------------------------------------
    #---------------------------------------------------------------------------
    # Graphics::get_pattern
    # retourne la ressource bitmap en l'initialisant si première utilisation
    #---------------------------------------------------------------------------
    # paramètres :
    # filename : nom du fichier bitmap pattern
    # options
    # -storage : <hastable> référence de la table de stockage de patterns
    #---------------------------------------------------------------------------
    """
    if (options.has_key('storage')):
        table = options['storage']
    else :
        table = bitmaps
    if (not table.has_key(filename)) :
        bitmap = "@%s"% (find_inc(filename))
        table[filename] = bitmap
    return table[filename]

def get_texture(widget, filename, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::get_texture
    # retourne l'image de texture en l'initialisant si première utilisation
    #---------------------------------------------------------------------------
    # paramètres :
    #   widget : <widget> identifiant du widget zinc
    # filename : nom du fichier texture
    # options
    # -storage : <hastable> référence de la table de stockage de textures
    #---------------------------------------------------------------------------
    """
    if (options.has_key('storage')):
        table = options['storage']
    else :
        table = textures
    return get_image(widget, filename, storage = table)

class FileNotFound (Exception):
    """
    #---------------------------------------------------------------------------
    # Graphics::FileNotFound
    # Classe d'exception levée lorsqu'un fichier n'est pas trouvé
    # paramètres :
    #   filename : nom du fichier
    #---------------------------------------------------------------------------    
    """
    def __init__(self, filename):
        Exception.__init__(self, "File %s not Found"%(filename))

def find_inc(name):
    """
    #---------------------------------------------------------------------------
    # Graphics::find_inc
    # recherche le fichier dans les répertoires de PYTHONPATH
    #---------------------------------------------------------------------------
    """
    import sys
    import os.path
    for path in sys.path:
        tfile = os.path.join(path, name)
        if (os.path.isfile(tfile)):
            return tfile
    raise FileNotFound(name)
            
    
def get_image(zinc, filename, storage = {}):
    """
    #---------------------------------------------------------------------------
    # Graphics::get_image
    # retourne la ressource image en l'initialisant si première utilisation
    #---------------------------------------------------------------------------
    # paramètres :
    #   widget : <widget> identifiant du widget zinc
    # filename : nom du fichier image
    # options
    # storage : <hastable> référence de la table de stockage d'images
    #---------------------------------------------------------------------------
    """
    if (not storage.has_key(filename)):
        im = PIL.Image.open(find_inc(filename))
        #Cela marche uniquement si Tkinter.Tk a une instance
        image = PIL.ImageTk.PhotoImage(im)
        storage[filename] = image
    return storage[filename]

def init_pixmaps(widget, *pixfiles, **options):
    """
    #---------------------------------------------------------------------------
    # Graphics::init_pixmaps
    # initialise une liste de fichier image
    #---------------------------------------------------------------------------
    # paramètres :
    #    widget : <widget> identifiant du widget zinc
    # filenames : <filenameList> list des noms des fichier image
    # options
    #  storage : <hastable> référence de la table de stockage d'images
    #---------------------------------------------------------------------------
    """
    imgs = []
    for pixfile in pixfiles:
        imgs.append(get_image(widget, pixfile, **options))
    return imgs

def _trunc(f, n):
    """
    #---------------------------------------------------------------------------
    # Graphics::_trunc
    # fonction interne de troncature des nombres: n = position décimale 
    #---------------------------------------------------------------------------
    """
    import fpformat
    return fpformat.fix(f, n)

#Local Variables:
#mode : python
#tab-width: 4
#end:

Added jni/tkzinc/Python/setup.py.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
from distutils.core import setup
setup(name="python-zinc",
      version="1.0",
      description="Zinc for Python",
      author="Guillaume Vidon",
      author_email="vidon at ath.cena.fr",
      license="GPL",
      url="http://www.tkzinc.org",
      py_modules=[],
      package_dir = {"Zinc" : "library"},
      packages = ["Zinc",],
      data_files=[('share/doc/zinc-python/demos/Graphics',
                   ['demos/testGraphics.py','demos/paper.gif'])])
                  

#Local Variables:
#mode: python
#End:

Added jni/tkzinc/README.







































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275

	*===========================================*
		The Tkzinc widget version 3.6
	*===========================================*


WHAT IS THIS?

  Tkzinc is a canvas like widget extension to Tcl/Tk. It adds
support for ATC displays, provides structured assembly of
items, transformations, clipping, and openGL based rendering
features such as gradients and alpha blending.

  It is currently available on Unices (tested on Linux),
Windows and Mac OSX (with X11 and fink).


WHERE DOES IT COME FROM?

  The newest version is found at: https://bitbucket.org/plecoanet/tkzinc
  It should be at least available in source form in a file
  named Tkzinc<version>.tgz.
  Distribution specific packages may also be available for
  Debian/Mandrake/Red Hat distributions, most likely for stable
  versions.

  For Tcl/Tk users, Tkzinc is also available as a multi-plateforme
  (linux/windows) starkit on https://bitbucket.org/plecoanet/tkzinc
  For Perl/Tk users, Tkzinc is available on the CPAN, see for example
  on http://search.cpan.org/search?query=TkZinc&mode=all

  As a convenience the documentation (pdf+html) is made available
  on the web site as a separate package.


BUILDING AND INSTALLATION FOR TCL/TK


0. You need a working Tcl/Tk distribution (version >= 8.4). You can either grab
   it using your regular package manager, or build it and install it from scratch.

   On a Linux system, you need tcl tcl-dev tk tk-dev packages.

   On MacOSX you need:
	- fink with tcltk and tcltk-dev package (http://fink.sf.net)
	- tcl/tk sources, though you are _not_ required to compile and install them.
	tcl/tk sources are needed  because some required files are missing in the packages (tclInt.h and tkInt.h,
	if you know how to get those files with fink, submit a suggestion to the maintainers).
	I couldn't install them using fink, d/l them instead:
		http://prdownloads.sourceforge.net/fink/direct_download/source
	- X11 et X11 sdk from Apple (http://www.apple.com/macosx/x11/)

   From sources or on Windows, get, build and _install_ the Tcl/Tk distribution.
   On Windows there is currently an incompatibility when using a Tkzinc compiled under mingw32 with
   a core Tcl/Tk compiled with visual C++. You need to grab a Tcl/Tk
   compiled with the same environment as Tkzinc.


1. Unpack the distribution

   On Unix/Linux/MacOSX:

	tar zxf Tkzinc<version>.tgz

   On Windows:

	Use WinZip or something similar to unpack

   This creates a directory Tkzinc<version> with all the
   needed files. This directory should be in the same
   directory as the Tcl/Tk sources.


2. Configure

   On Unix/Linux:

	cd Tkzinc<version>
	./configure  <option>*

   This will configure the package for your platform. It
   will install it in /usr/local. If you want it elsewhere
   you can use the --prefix and --exec-prefix options of
   configure to assign another location.

   On MacOSX:

   say we have unpacked tlc/tk sources in $HOME/src. The configure
   line is as follows: 
             env "CPPFLAGS=-I/sw/include -I$HOME/src/tcl8.4.1/generic -I$HOME/src/tk8.4.1/generic" ./configure --with-tcl=/sw/lib --with-tk=/sw/lib --enable-gl

   On Windows:

   Tkzinc has been built using the msys/mingw32 environment.
   It is known to work with Tcl/Tk 8.4.2 compiled using the
   same environment. CAUTION: It doesn't work with Tcl/Tk 8.4.1
   using mingw32.
   The steps for building under mingw32 are the same as on Unices.
   Currently there is no support for building with visual C++.

   On all platforms:

   It is possible to customize Tkzinc through configure options:

	--enable-gl=[yes|no|damage]
	--disable-gl

	This is turned off by default. Building with --enable-gl
	is the recommanded way for openGL support.

	--enable-om=[yes|no]
	--disable-om

	This is turned on by default. It controls the inclusion of
	code for avoid overlap between track labels in radar images.

	--enable-shape=[yes|no]
	--disable-shape

	This is turned on by default except on Windows where support
	code is not currently available (it may become available).
	It allows for non rectangular Tkzinc windows optionally including 
	the top level window.

   And the Tcl standards:

	--enable-threads=[yes|no]
	--disable-threads

	Compile a thread aware/thread safe version (not tested in multi
	threaded environment). Needed if Tcl/Tk has been compiled with
	the same configure option.

	--enable-symbols=[yes|no|mem|all]
	--disable-symbols

	Turn on debugging symbols. If the form --enable-symbols=mem is 
	used, turn on memory debugging as well.


3. Make and Install

   For use with Tcl on Unix/Linux and Windows using mingw32:

	make
	make install-tcl

   It is recommended to do a make distclean before actual building if you
   have done a previous build.

   The warnings while compiling libtess are harmless (or so I believe ;-).
   libtess is a tesselation library extracted from GLU/Mesa. I trust it as
   robust unless proven wrong. I do not want to modify the code just to
   shut up some warnings.


   For use with Tcl on Windows using Visual C++:

	nmake /F win/makefile.vc

   There is no install target. You are left with the dlls and the start of
   pkgIndex.tcl (it lacks the entries for the Tcl modules in library).
   It is needed to compile with Visual C++ if Tkzinc is to be used with a
   Tcl/Tk compiled with Visual C++.

   P.S: If a pkgIndex.tcl for Tkzinc exists in the autoload path before
   installing, it will interfere with the generation of the new pkgIndex.tcl.
   It should be removed or renamed. echo 'puts $auto_path' | tclsh will
   tell the current load path.
   
   WATCH OUT! On Linux it is quite frequent to have both Mesa and proprietary
              openGL libraries installed. This may lead to big problems at
	      runtime if the linker picks the wrong library. It is often the
	      case between the static (libGL.a) Mesa library and the dynamic
	      (libGL.so) NVidia library. It is very important to assert that
	      the link is done with the library matching the openGL driver
	      loaded in the X server.

4. Run the demos

   In the Tkzinc<version> directory run:

	wish8.4 demos/zinc-widget

   Under windows do:

	wish84 demos/zinc-widget

   It should start a Tk like 'widget' demo showing Tkzinc
   features. You can also run the demo with: demos/zinc-widget
   if you have in the PATH a wish that is greater or equal to
   8.4.2.


BUILDING AND INSTALLATION FOR PERL/TK

TkZinc for Perl/Tk is available for Linux, Windows (Perl/Tk 804)
and MacOSX. Also remember that the easiest way could be to use
the CPAN. However new releases are usually first available on
https://bitbucket.org/plecoanet/tkzinc


0. You need a working Perl (>= 5.6) and Perl/Tk distribution (800 or 804). You can either grab
   it using your regular package manager, or build it and install it from scratch. To build it
   from scratch you need:

   On a Linux system, you need perl, perl-tk and perl-tk-devel packages 

   On MacOSX you need:
      - fink with tk-pm package and its dependencies (http://fink.sf.net)
        tk-pm is available in unstable. You can add this binary unstable tree to you /sw/etc/apt/sources.list:
        deb http://fink.opendarwin.org/bbraun 10.3/unstable main crypto
        deb http://fink.opendarwin.org/bbraun 10.3/stable main crypto
     - X11 et X11 sdk from Apple (http://www.apple.com/macosx/x11/)

   On WinXP you need:
      - perl and perl-tk 804, 
      - Visual C++ or the Free Visual C++ Command Line Tools

1. Unpack the distribution

        tar zxf Tkzinc<version>.tgz
        cd Tkzinc<version>/Perl
        ./export2cpan
        cd ../export2cpan/tk-zinc<version>

2. Make and install

    This done is the usual way

        perl Makefile.PL
        make
        make test

        # to run the demo without/before installing:
        perl -Mblib demos/zinc-demos

        make install

   WATCH OUT! On Linux it is quite frequent to have both Mesa and proprietary
              openGL libraries installed. This may lead to big problems at
	      runtime if the linker picks the wrong library. It is often the
	      case between the static (libGL.a) Mesa library and the dynamic
	      (libGL.so) NVidia library. It is very important to assert that
	      the link is done with the library matching the openGL driver
	      loaded in the X server.

3. Run the demo

    You can choose in the 35 available demos with the
    following perl script:

        zinc-demos


MAKE AND READ THE DOCUMENTATION


   It is available in pdf and html forms.
   To make the pdf doc you need pdflatex installed. Then do:

	cd Tkzinc<version>
        ./configure
	make pdf

   This should create a refman.pdf in the doc directory.

	cd Tkzinc<version>
        ./configure
	make html

   This should create the html documentation in the doc directory
   with all the html pages and images. The entry point is index.html.
   You need tex4ht for doing this. It may be packaged separately from
   tetex on Linux, it is so on Debian distributions.

Added jni/tkzinc/aclocal.m4.

























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#
# Include the TEA standard macro set
#

builtin(include,tclconfig/tcl.m4)

#
# Zinc specific macros below.
#
#
# ALL the new macros here need to be modified to
# detect the various packages needed and to get their paths.
# Right now all this is statically defined in the macros.
#
#------------------------------------------------------------------------
# ZINC_ENABLE_GL --
#
#	Specify if openGL support should be used.
#	Code for managing a damage area can also be enabled.
#
# Arguments:
#	none
#	
# Results:
#
#	Adds the following arguments to configure:
#		--enable-gl=[yes,no,damage]
#
#	Defines the following vars:
#		GL_INCLUDES	OpenGL include files path
#		GL_LIBS		additional libraries needed for GL
#		LIBS		Modified to reflect the need of new
#				libraries
#		GL		Defined if GL support is enabled
#		GL_DAMAGE	Defined if damage support has been
#				requested
#
#------------------------------------------------------------------------

AC_DEFUN(ZINC_ENABLE_GL, [
     AC_MSG_CHECKING([for build with GL])
     AC_ARG_ENABLE(gl,
 		  [  --enable-gl             build with openGL support (yes,no,damage) [[no]]],
 		  [tcl_ok=$enableval], [tcl_ok=no])

     if test "$tcl_ok" = "no"; then
 	GL_LIBS=
 	GL_INCLUDES=
 	AC_MSG_RESULT([no])
     else
	if test "${TEA_PLATFORM}" = "windows" ; then
	    GL_LIBS="-lglu32 -lopengl32"
	elif test "${TEA_WINDOWINGSYSTEM}" = "aqua" ; then
	    GL_LIBS="-framework AGL -framework OpenGL"
 	    GL_INCLUDES="${GL_INCLUDES}"
	elif test `uname -s` = "Darwin" ; then
	    GL_LIBS="-framework OpenGL"
 	    GL_INCLUDES="${GL_INCLUDES}"
        else
 	    GL_LIBS="-lGL"
 	    GL_INCLUDES="${GL_INCLUDES} -I/usr/include"
        fi

 	AC_DEFINE(GL)
 	if test "$tcl_ok" = "damage"; then
 	    AC_DEFINE(GL_DAMAGE)
        fi

 	LIBS="$LIBS $GL_LIBS"

 	if test "$tcl_ok" = "yes"; then
 	    AC_MSG_RESULT([yes (standard)])
 	else
 	    AC_MSG_RESULT([yes (with damage support)])
 	fi
     fi

     AC_SUBST(GL_LIBS)
     AC_SUBST(GL_INCLUDES)
])

#------------------------------------------------------------------------
# ZINC_ENABLE_ATC --
#
#	Specify if the Atc code should be included.
#
# Arguments:
#	none
#	
# Results:
#
#	Adds the following arguments to configure:
#		--enable-atc=[yes,no]
#
#	Defines the following vars:
#		ATC		Defined if ATC support is enabled
#
#------------------------------------------------------------------------

 AC_DEFUN(ZINC_ENABLE_ATC, [
     AC_MSG_CHECKING([for build with the ATC extensions])
     AC_ARG_ENABLE(atc,
 		  [  --enable-atc            build with ATC extensions [[yes]]],
 		  [tcl_ok=$enableval], [tcl_ok=yes])
     if test "$tcl_ok" = "no"; then
 	AC_MSG_RESULT([no])
     else
 	AC_DEFINE(ATC)
        TEA_ADD_SOURCES([OverlapMan.c])
        TEA_ADD_SOURCES([Track.c])
        TEA_ADD_SOURCES([Reticle.c])
        TEA_ADD_SOURCES([Map.c])
        TEA_ADD_SOURCES([MapInfo.c])
 	AC_MSG_RESULT([yes])
     fi
])

#------------------------------------------------------------------------
# ZINC_ENABLE_SHAPE --
#
#	Specify if the X shape extension support should be included.
#
# Arguments:
#	none
#	
# Results:
#
#	Adds the following arguments to configure:
#		--enable-shape=[yes,no]
#
#	Defines the following vars:
#		SHAPE		Defined if shape support is enabled
#
#	Adjust LIBS to include the X extension library
#
#------------------------------------------------------------------------

AC_DEFUN(ZINC_ENABLE_SHAPE, [
     AC_MSG_CHECKING([for build with X shape support])
     AC_ARG_ENABLE(shape,
 		  [  --enable-shape          build with X shape support (if applicable) [[yes]]],
 		  [tcl_ok=$enableval], [tcl_ok=yes])
     if test "$tcl_ok" = "no"; then
 	AC_MSG_RESULT([no])
     else
         if test "${TEA_PLATFORM}" = "windows" ; then
 	    AC_MSG_RESULT([no (not available on windows)])
	elif test "${TEA_WINDOWINGSYSTEM}" = "aqua" ; then
 	    AC_MSG_RESULT([no (not available on windows)])
        else
 	    AC_DEFINE(SHAPE)
 	    AC_MSG_RESULT([yes])
	    LIBS="${LIBS} -lXext"
 	fi
     fi
])

Added jni/tkzinc/bootstrap.







>
>
>
1
2
3
aclocal -I .
libtoolize --force
autoconf

Added jni/tkzinc/configure.

more than 10,000 changes

Added jni/tkzinc/configure.in.









































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
dnl 
dnl Process this file with autoconf to produce a configure script.
dnl autoconf 2.13 should work fine. However autoconf >= 2.53 and
dnl perhaps versions in between (2.50 and 2.52) are not directly usuable.
dnl 
dnl
dnl This configure.in is derived from the Sample TEA template which is:
dnl
dnl Copyright (c) 1999 Scriptics Corporation.
dnl Copyright (c) 2002 ActiveState SRL.
dnl
dnl
dnl $Id$

#-----------------------------------------------------------------------
# Define MAJOR_VERSION, MINOR_VERSION and PATCHLEVEL, they are
# useful to built version strings without dots (windows).
#
# !!!MUST ALSO BE SUBSTITUTED in AC_INIT !!!
#-----------------------------------------------------------------------
MAJOR_VERSION=3
MINOR_VERSION=3
PATCHLEVEL=6

#-----------------------------------------------------------------------
# Check the source path of the package
#-----------------------------------------------------------------------
AC_INIT([Tkzinc], [3.3.6])

#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows".
#
# Keep it here we will need ${TEA_PLATFORM} soon.
#--------------------------------------------------------------------
TEA_INIT([3.5])

#-----------------------------------------------------------------------
# Setup the CONFIGDIR to the path of the directory containing the
# configuration files
#-----------------------------------------------------------------------
AC_CONFIG_AUX_DIR(tclconfig)
CONFIGDIR=${srcdir}/tclconfig
AC_SUBST(CONFIGDIR)

AC_SUBST(MAJOR_VERSION)
AC_SUBST(MINOR_VERSION)
AC_SUBST(PATCHLEVEL)

#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------
TEA_PATH_TCLCONFIG
TEA_LOAD_TCLCONFIG

#--------------------------------------------------------------------
# Load the tkConfig.sh file
#--------------------------------------------------------------------
TEA_PATH_TKCONFIG
TEA_LOAD_TKCONFIG

#-----------------------------------------------------------------------
# Handle the --prefix=... option by defaulting to what Tcl gave.
# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
#-----------------------------------------------------------------------
TEA_PREFIX

#-----------------------------------------------------------------------
# Standard compiler checks.
# This sets up CC by using the CC env var, or looks for gcc otherwise.
# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create
# the basic setup necessary to compile executables.
#-----------------------------------------------------------------------
TEA_SETUP_COMPILER
#AC_MINGW32


#--------------------------------------------------------------------
# C source files
#--------------------------------------------------------------------
TEA_ADD_SOURCES([Tabular.c])
TEA_ADD_SOURCES([Rectangle.c])
TEA_ADD_SOURCES([Arc.c])
TEA_ADD_SOURCES([Curve.c])
TEA_ADD_SOURCES([Item.c])
TEA_ADD_SOURCES([PostScript.c])
TEA_ADD_SOURCES([Attrs.c])
TEA_ADD_SOURCES([Draw.c])
TEA_ADD_SOURCES([Geo.c])
TEA_ADD_SOURCES([List.c])
TEA_ADD_SOURCES([perfos.c])
TEA_ADD_SOURCES([Transfo.c])
TEA_ADD_SOURCES([Group.c])
TEA_ADD_SOURCES([Icon.c])
TEA_ADD_SOURCES([Text.c])
TEA_ADD_SOURCES([Image.c])
TEA_ADD_SOURCES([Color.c])
TEA_ADD_SOURCES([Field.c])
TEA_ADD_SOURCES([Triangles.c])
TEA_ADD_SOURCES([Viewport.c])
TEA_ADD_SOURCES([WindowUtils.c])
TEA_ADD_SOURCES([Window.c])
TEA_ADD_SOURCES([tkZinc.c])

#--------------------------------------------------------------------
# Choose which headers you need.  Extension authors should try very
# hard to only rely on the Tcl public header files.  Internal headers
# contain private data structures and are subject to change without
# notice.
# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
#
# Sorry but zinc needs the internal functionality provided by Tk
# even if this is less convenient and secure.
#--------------------------------------------------------------------
TEA_PRIVATE_TCL_HEADERS
TEA_PRIVATE_TK_HEADERS

#--------------------------------------------------------------------
# A few miscellaneous platform-specific items:
#
# Windows creates a few extra files that need to be cleaned up.
#
# Define any extra compiler flags in the PACKAGE_CFLAGS variable.
# These will be appended to the current set of compiler flags for
# your system.
#--------------------------------------------------------------------
if test "${TEA_PLATFORM}" = "windows" ; then
    CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch"
    case ${TK_DEFS} in
        *PLATFORM_SDL*)
            ;;
        *)
            TEA_ADD_SOURCES([WinPort.c])
            ;;
    esac
elif test "${TEA_WINDOWINGSYSTEM}" = "aqua" ; then
    CLEANFILES="pkgIndex.tcl"
    TEA_ADD_SOURCES([macosx/OSXPort.c])
else
    CLEANFILES="pkgIndex.tcl"
fi
CLEANFILES="${CLEANFILES} doc/*.dvi doc/*.aux doc/*.idx doc/*.ilg doc/*.ind"
CLEANFILES="${CLEANFILES} doc/*.lof doc/*.log doc/*.out doc/*.toc doc/*.tpt"
CLEANFILES="${CLEANFILES} doc/refman doc/refman.pdf"
CLEANFILES="${CLEANFILES} starkit.tcl"

AC_SUBST(CLEANFILES)

#--------------------------------------------------------------------
# Check whether --enable-threads or --disable-threads was given.
# This auto-enables if Tcl was compiled threaded.
#--------------------------------------------------------------------
TEA_ENABLE_THREADS

#--------------------------------------------------------------------
# The statement below defines a collection of symbols related to
# building as a shared library instead of a static library.
#--------------------------------------------------------------------
TEA_ENABLE_SHARED

#--------------------------------------------------------------------
# This macro figures out what flags to use with the compiler/linker
# when building shared/static debug/optimized objects.  This information
# can be taken from the tclConfig.sh file, but this figures it all out.
#--------------------------------------------------------------------
TEA_CONFIG_CFLAGS

case ${TK_DEFS} in
    *PLATFORM_SDL*)
        TEA_ADD_CFLAGS([-DPLATFORM_SDL=1])
        ;;
esac

#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols option.
#--------------------------------------------------------------------
TEA_ENABLE_SYMBOLS

#--------------------------------------------------------------------
# For Unix/Tk builds, make sure that the X libraries/headers are found.
# This must be called after TEA_CONFIG_CFLAGS as it adjusts LIBS.
#--------------------------------------------------------------------
TEA_PATH_X

#--------------------------------------------------------------------
# Tkzinc is always linked against the tcl and tk stubs libraries
#--------------------------------------------------------------------
AC_DEFINE(USE_TCL_STUBS)
AC_DEFINE(USE_TK_STUBS)

#--------------------------------------------------------------------
# Add platform libs to LIBS or SHLIB_LD_LIBS as necessary.
#--------------------------------------------------------------------
if test "${TEA_PLATFORM}" = "windows" ; then
    LIBS="${LIBS} -lglu32 -lgdi32 -luser32 -lwsock32"
elif test "${TEA_WINDOWINGSYSTEM}" = "aqua" ; then
    LIBS="${LIBS} -framework Carbon"
elif test `uname -s` = "Darwin" ; then
    LIBS="${LIBS} -framework OpenGL"
else
    LIBS="${LIBS} -lGLU"
fi
AC_SUBST(GL_INCLUDES)

#--------------------------------------------------------------------
# This macro generates a line to use when building a library.  It
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
# and TEA_LOAD_TCLCONFIG macros above.
#--------------------------------------------------------------------
TEA_MAKE_LIB

#--------------------------------------------------------------------
# Find tclsh so that we can run pkg_mkIndex to generate the pkgIndex.tcl
# file during the install process.  Don't run the TCLSH_PROG through
# ${CYGPATH} because it's being used directly by make.
# Require that we use a tclsh shell version 8.2 or later since earlier
# versions have bugs in the pkg_mkIndex routine.
# Add WISH as well since Tkzinc  is a Tk extension.
#--------------------------------------------------------------------
TEA_PROG_TCLSH
TEA_PROG_WISH

#--------------------------------------------------------------------
# Define the SHAPE symbol to control the X shape extension support.
# This must be called after TEA_CONFIG_CFLAGS as it adjusts LIBS.
#--------------------------------------------------------------------
ZINC_ENABLE_SHAPE

#--------------------------------------------------------------------
# Adjust the library set based on --enable-gl option. Define also
# the GL and GL_DAMAGE symbols to configure the code.
# This must be called after TEA_CONFIG_CFLAGS as it adjusts LIBS.
#--------------------------------------------------------------------
ZINC_ENABLE_GL

#--------------------------------------------------------------------
# Define the ATC symbol to control inclusion of the ATC specific code.
#--------------------------------------------------------------------
ZINC_ENABLE_ATC

AC_SUBST(TCL_INCLUDE_SPEC)
AC_SUBST(TK_INCLUDE_SPEC)

AC_OUTPUT([Makefile starkit.tcl])

Added jni/tkzinc/debian/README.debian.













>
>
>
>
>
>
1
2
3
4
5
6
zinc for DEBIAN
----------------------

No comments ;-)

Patrick Lecoanet <lecoanet@ath.cena.fr>, Wed, 25 Feb 1998 14:11:43 +0100

Added jni/tkzinc/debian/changelog.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
zinc-tk (3.3.6) unstable; urgency=low

  * Items of type window have a new attribute -windowtitle to retrieve and
    display any top-level window (ie any application) whose title matches
    the value of -windowtitle
  * Damage support (ie OpenGL optimizations) can now be controlled by a
    new TkZinc attribute (-usedamage)

 -- Alexandre Lemort <lemort@intuilab.com>  Wed, 23 Jan 2008 17:00:07 +0200

zinc-tk (3.3.5) unstable; urgency=low

  * Fixed a core dump that occured following an error while configuring
    a connected item (occuring only via tksubject).
  * Fixed the slow loading bug #71 and incorrect rendering of the text bug #67
    in Windows/GL (reverted to the previous code).
  * Fixed the blur of the text in GL (Linux). Revert to nearest filtering
    meaning no anti-aliasing.
  * MouseWheel support under Windows bug #70. Thanks A. Lemort.
  * Map items honor the filled attribute in GL bug #69. Thanks A. Lemort.
  * Fixed an incorrect rendering of the selection (off by one) for text items.
  * Introduced GL extension handling with GLEW.
  * Capability to rotate the canvas via a texture.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue, 6 Mar 2007 15:35:07 +0200

zinc-tk (3.3.4) unstable; urgency=low

  * Ported to Mac Os X native. But, the quartz version does not support
    stippling, clipping and as a side effect can't draw bitmap symbols.
    This is probably only a minor annoyance since the GL version should
    be fully functional and can be run without starting the X server.
  * Started updating the small demos partly to simply and Tclisize the
    code and partly to 'enhance' some rather old and ugly displays.
  * Fixed a weird bug under windows/GL causing the application to be
    throwed out after a short while because it was out of contexts.
  * Close several bugzilla submitted bugs: #58, #63, #64, #60, #50.
  * Added a collapsemotions command to control the Tk event queue
    behavior with motion events.
  * Added a -catchevent attribute to all items in order to control their
    "transparency" to events.
  * Update to the documentation.
  * Better looking html documentation with a navigation sidebar.
  * Merged requests and patches to enhance communication with the overlap
    manager.
  * Removal of the explicit dependency on xlibmesa3 - dh_shlibdeps should be able to
    identify and list the shared library dependencies anyway IMHO.
  * Add explicit path for tcl8.4 and tk8.4.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 18 Oct 2005 15:35:07 +0200

zinc-tk (3.3.3) unstable; urgency=low

  * Added fixes to compile the Linux debian packages (Thanks Till Varoquaux)
  * Integrated a patch from D Pavet. This patch keep the angular position
    of the leader in sync when changing the leader position with -labeldx
    and -labeldy.
  * Angles are seen as floating point numbers (they are still integers inside).
  * Changed the text texture filtering to linear. This should provide better
    looking text when scaled/rotated.
  * Fix Bug 41 related to a badly updated connection between
    tracks or waypoints. The update was dependant on the connection
    ordrer between items. This bug induced a bad bounding box
    and thus a failure to correctly detect enter/leaves on the
    connection.
  * Fix a text field drawing problem when alignment is center.
  * Fix an annoying core dump with the gradients (bug 51).
  * Labelformats field widths can be negative. This makes possible
	  kerning adjustments.
  * The transformation methods test if the tagOrId is not an empty string,
	  if it is, it reports an error.
  * Added three unicode points for the tendancy arrows in the GL renderer.
  * Fixed (for good this time ?) the swap buffer problem. It showed up on
    Intel i865 which really swap buffers instead of copying them. In fact
		this is not really fixed, it can't work properly on all cards, the only
		secure option is build without the damage option. It is safe on NVIDIA
		though.
  * The GL_Damage option default has been set to NO for perl-tk
  * Rearranged the Window destroy handling to make it more robust.
  * Other minors fixes.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 18 Jan 2006 15:35:07 +0200

zinc-tk (3.3.2) unstable; urgency=low

  * Updated Python binding and new demos added (Guillaume Vidon).
    * python :Updated Python binding and new demos added (Guillaume Vidon).
    * python :No more need to call explicitely the function havetkzinc to load
      the library ELF tkzinc. On peut créer un objet Zinc avec ou sans conteneur. 
    * python :A Zinc object can be created with or without container object.
      If master arg is 0, a new object Tkinter.Frame is created and the object Zinc is inserted on.
    * python :Add Zinc.Zinc.addtag_ancestors
    * python :Del Zinc.Zinc.addtag_atpoint ( not anymore in specifications of Zinc API )
    * python :Zinc.Zinc.addtag_closest can take a new arg : recursive
    * python :Zinc.Zinc.addtag_atpriority can take a arg tagOrId which begin root of tree
      where function act.
    * python :Zinc.Zinc.addtag_overlapping and addtag_enclosed can take 2 new optional
      params : inGroup et recursive
    * python :addtag_withtype can take one new optional param tagOrId
    * python :some docstrings for public methods of Zinc.Zinc
    * python :Zinc.Zinc.find_atpoint becomes Zinc.Zinc.find_closest
    * python :Fix Zinc.Zinc.hasfields
    * python :Del Zinc.Zinc.hasparts ( not supported )
    * python :Add Zinc.ZincItem.bbox Zinc.Zinc.find_ancestors Zinc.Zinc.contours
      Zinc.Zinc.dchars Zinc.index Zinc.hastag Zinc.insert Zinc.numparts Zinc.postscript
      vertexat Zinc.tset Zinc.tapply Zinc.tcompose Zinc.skew Zinc.smooth Zinc.select
    * python :Fix find_overlapping : options ingroup et recursive
    * python :Fix Zinc.scale Zinc.cget Zinc.configure Zinc.translate like in specs
    * python :New attribut Zinc.Zinc.version return version of Zinc
    * python :New __main__ : display a window wich show  version number
    * python :ZincException Class added for generate Zinc exception (Not more TclError Later)
    * python :ZincItem.getGroup return Group Item which is the parent of the ZincItem's instance
    * python :Fix ZincItem.scale ZincItem.rotate and ZincItem.translate to run with
      Zinc.Zinc Objects
    * python :Add ZincItem.coords method because attribut accessor dont permit all possible
      invocations (for exemple Cure Item we can manipulate multi contours)
    * python :In Group getGroup method has been overwrited to treat the root group case
    * python :In Curve constructor accepts a option contours which is a list of lists of coords
      defining extended contours
    * python :self._do deprecated. Use now self.tk.call (Thx JC Daudin)
    * python :Add Mapinfo.duplicate which return a clone of the  Mapinfo instance
    * python :Add Mapinfo.add_symbol Mapinfo.count Mapinfo.get Mapinfo.replace Mapinfo.remove
    * python :Add de Videomap.ids, class method which return maps from the file
    * python :add param backward_compatibility to Zinc.Zinc constructor. If it is set, the widget
      use old format of currentpart and configure  
    * python :havetkzinc doesnt return version number in some cases (M. Cousy)
    * python :Add classes Colors AxialGradientColor RadialGradientColor ConicalGradientColor,
      color's handler classes
    * python :bbox doesnt return values (J. Tseng)
    * python :Zinc.Zinc.itemconfigure doesnt work. the syntax of tk.call is different of _do
      then we must deference list
    * python :Zinc.Zinc.tget not implemented -> Added Thx M. Cousy
    * python :Add Zinc.ZINC_NO_PART
    * python :Add Zinc.ZincItem.transform Zinc.ZincItem.tget Zinc.ZincItem.tsave
      Zinc.ZincItem.trestore Zinc.ZincItem.tset Zinc.ZincItem.treset 
    * python :library Tkzinc load use now tcl require system.
    * python :auto_path environment variable allows to change auto_set value
    * python :return miss in some Zinc.methods
    * python :type of return of currentpart must be string (M. Cousy)
    * python :ZINC_NO_PART bad value (M. Cousy)

  * In Perl, when doing an itemcget or itemconfigure on an image, the returned
    value is now the image object not its name. This should be far more useful.
  * Fixed a bug causing a segv when a gradient is specified outside an
    item bbox.
  * Added the new C++ binding contributed by Intuilab.
  * Exported ZincObjCmd to support the new C++ wrapper
  * Switched to the native GLU tesselator instead of the builtin.
    Removed the builtin code.
  * Merged new Postscript emitting code (still under developpement).
  * Added a new track attribute -historywidth to separate the width of
    the history points from the width of the main symbol.
  * Extensive reformatting to suppress tabs which results in inaccurate
    indenting depending on the editor used.
  * Suppressed the use of the __unused attribute to suppress warnings
    on unused attributes. It has raised several incompatibilities and
    should be dealed with on the command line (gcc).
  * Corrected a trace left by thick label borders under GL.
  * Added a tcl script to automate the production of the code under
    Windows/VC.
  * A new packager build using Wix is available to install for Active
    Tcl/Perl/Python.
    

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 22 Jun 2005 10:10:07 +0200

zinc-tk (3.3.01) unstable; urgency=low

  * All the ATC specific code in now optional. To remove it add
    --enable-atc=no to the configure invocation. In Perl you have
    to say perl Makefile.PL with-atc=no.
  * Changed the method used to position the label wrt the track
  	position. Now regarless of its shape and its angular position,
    the label is maintained at the requested distance.
  * Corrected a nasty memory leak in the Curve geometry management.
    It affected only the simple curves, convex with only one contour.
    This bug might be the source of some performance problems observed
    lately.
  * Debug.pm (D.Etienne)
    - built code correctly manages transformations.
    - the transformation matrix can be displayed.
    - transformation primitives parameters can be displayed and changed.
    - added a new entry in the control bar to display the X cursor device
      coordinates.
    - added the -expandTagsField option to configure the tags display in
      the attributes window.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 11 Nov 2004 17:10:07 +0200

zinc-tk (3.3.0) unstable; urgency=low

  * Reworked the X11 arc handling code in order to fix bugs
    and improve coherence between X11 and openGL.
  * Reworked once more the GL init code to cope with Windows.
  * Many various bug fixes.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 5 Oct 2004 17:10:07 +0200

zinc-tk (3.2.100) unstable; urgency=low

  * Fixed a problem in GL init code which prevented zinc from
    working with Mesa.
  * A (hopefully) more useful warning is emitted when openGL
    rendering is not good enough (most often 24 bits buffer
    or stencil not available).
  * Tweaking and bending the openGL init code to make it
    work better.
  * Changed the group picking code to enable correct picking with a
    complex clipping shape.
  * Fixed the font loading code when compiling for perl 800.
    The error prevented the correct encoding of codes > 127.
  * Fixed processing of extended gradient syntax (vector based
    specification) which was completly wrong for axial gradients.
  * Fixed some other minor bugs in gradient structure initialisation
    which led to gradient fill extending outside the item boundary.
  * Improved the two README to clarify how to compile
    the two possible distributions (cpan or full distrib).
  * Fixed the Perl compilation for MacOS.
  * Fixed the crash when closing a TkZinc on MacOS OpenGL.
  * Fixed the coredump due to a bug in the field text handling.
  * Updated the doc.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 25 May 2004 17:10:07 +0200

zinc-tk (3.2.98) unstable; urgency=low

  * Suppressed the fieldbbox command. It is available when calling
    the bbox command with the -field and -label options.
  * Fixed a nasty openGL/Windows redraw bug when opening a window.
  * GL contexts are destoyed when no longer needed.
  * Fixed Enter/leave emission to match the Canvas (and better).
  * Slightly rearranged the init sequence for openGL. This will
    ensure that render will be reset has soon has possible if
    GL is not there. It will _stay_ set if we discover later that
    GL is not available. This will fix a rather bewildering situation
    when using images: The image is created for GL, then all of a sudden
    accessed in an X11 context.
  * Bug fixes. These should have boosted the stability a lot.
  * A new Tcl_Obj type "attribute" is used to cache the attribute
    lookup from one command invocation to the other. This can
    speed up the code slightly (or more). Available only for
    Tcl.
  * Text rendering in text items should be better quality.
  * Fixed the scrollbar protocol to work with all versions
    of Perl/Tk and Tcl.
  * The "new" tk option configuration mecanism is used where
    possible (not with Perl/TK 800).
  * Only one tesselator is allocated regardless of how many
    TkZinc widgets an application use. This potentially can
    bring resource savings for applications using many
    TkZincs with OpenGL.
  * TkZinc perl works under Windows (Perl/Tk 804 only).
  * Font loading under GL has been rewritten it is now as fast
    as before and still utf8 based.
  * coords has (yet) been modified (fixed) so that items which
    exhibit only one meaningful coordinate will return this
    coordinate as a flat list instead of as a list of lists.
  * Redisplaying after a move or a resize even when clipped
    by the display border is now rock stable. This has been
    achieved by a full redisplay when moving/resizing.
  * An msi package Tcl/Tk and Perl/Tk on Windows.
  * makefile for building for Tcl with vc++ has been updated.
  * Several fixes in Makefile.PL (pthreads, INC augmented,
    Windows port)

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 3 May 2004 17:10:07 +0200

zinc-tk (3.2.97) unstable; urgency=low

  * Added a tget command. If called with a transform or an
    item as parameter, it returns the transform factors as
    a list (compatible with tset). An optional second parameter
    can be given, either 'all' meaning decompose the transform
    in translation, scale, rotation, skew and return the list
    in this order, or 'translation', 'scale', 'rotation', 'skew'
    which means return the corresponding value.
  * Added an optional boolean parameter abs to the translate
    command. If true it means that the translation should be
    interpreted as absolute. If absent or false the usual
    behavior is preserved.
  * Under OpenGL, a single graphic context is used for all
    zincs on a single display. Textures are put in common
    for the display. This should greatly reduce the resource
    consumption with GL.
  * Potential memory bugs have been fixed thanks to valgrind.
  * The code can be compiled either for perl/Tk 800 (define
    PTK and PTK_800) or perl/Tk 804 (define PTK alone).
  * The coords command returns a flat point instead of a list
    of one point for all items with a -position attribute.
  * The transformation of items with a -position has been slightly
    modified. The point described by -position is no longer considered
    in the coordinate space of the item but in the coordinate space
    of its parent group. The item is always located in 0,0 of its
    own coordinate space. This is so to make use of -composescale and
    -composerotation a lot more useful (and compatible).
  * The default value of -composescale and -composerotation on texts
    and icons is now false. This is coherent with the default behavior
    of these items (being rigids). The impact of this change is
    greatly minored by the new processing of the -position attribute.
  * Modified the command bindings for the transform
    testbed demo. Added a new delete item command.
  * Added two new Tcl demos ported from perl, testGraphics
    and magicLens.
  * Ported the Graphics package by JL Vinot to Tcl as
    zincGraphics.
  * Modified the behavior of options and arguments controlling
    the display of track history. The -trackmanagehistory is
    gone, a -trackvisiblehistorysize option has appeared, it
    describe the length of the history for ALL tracks in a zinc
    instance. In the Track class -visiblehistorysize has been
    removed and replaced by a boolean attribute -historyvisible
    that can be used to switch off the history for the concerned
    track instance. !!! INCOMPATIBLE CHANGE !!!
  * Fixed several problems with respect to UTF8 strings
    rendering. It should be possible for the text item
    to render OpenGL strings in all configurations.
  * Fixed a bug in indexing a Text item with utf8 characters
    (above 127).
  * Re-ported the pathtag demo from Perl to Tcl.
  * Fixed some bugs in the transform code (core dumps)
  * The scale method takes an optional center
  * The angle in the rotate method can be specified in
    degrees, a flag has been added to tell if the angle
    is given in degrees or radians.
  * The find and addtag method can do spacial searches
    (overlapping, enclosed, closest) in atomic
    groups overriding the atomic specification. The
    recursive flag takes the new value 'override' to do
    so.
  * a new command fieldbbox has been added. It returns the bounding
    box of the given field for the specified item or the item's label
    bounding box.
  * The bounding box reported for groups with clip areas
    takes into account the clipping. This was a long
    standing bug.
  * The enter leave processing as been sped somewhat by
    correcting an omission in the detection code.
  * The bind method now handles virtual events (an omission).
  * The bind method accept an alternative syntax for specifying
    bindings on fields instead of saying:
        .z bind $id:3 <1> "script"
    it is possible to say: 
        .z bind $id 3 <1> "script"
    This is coherent with the syntax used by the other methods.
  * Icons are fully transformable in X. The same behavior is
    achieved in both graphical environments.
  * The anchors positions have been fixed for rotated icons.
  * The text items are fully transformable in both environments.
  * The insertion cursor wasn't displayed on the last text line
    if empty. Fixed.
  * The last character of a text selection was never displayed
    as part of the selection (but correctly reported). Fixed.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon,  26 Jan 2004 13:37:48 +0200
	
zinc-tk (3.2.96) unstable; urgency=low

  * Fixed a bad redraw of maps (traces) and adapted for floating
    point MapInfos.
  * MapInfo coordinates converted to floating point. This should
    greatly improve map usefullness in Zinc.
  * Fixed an erroneous clipping shape when specified with
    an unaligned rectangle or an icon.
  * Fixed a core dump in curve when -closed 1 under X.
  * Added tcompose, tset, skew transformation commands.
  * The transform command now accept the reserved tag 'device' as
    source and destination. This specifies the device coordinate
    space. A named transform can be given as source and destination.
  * The tsave command accept the reserved tag 'identity' as source.
    It can also take a named transform as source.
  * Zinc is now able to use all font glyphs above 0x20 in a
    256 glyph font.
  * The smooth method reports a list of line segment vertices
    instead of the incorrect list of bezier segment vertices.
  * Added a -followpointer widget option to optimize pointer
    motion processing (suppress enter/leave processing).
  * The coords method correctly updates the control flags when
    replacing the whole vertex list.
  * Fixed a problem a the invalidation code which prevented
    item with a transform update pending from being correctly
    processed. All item specific invalidation flags were
    ignored after a transform operation on the item.
  * The -lastasfirst attribute of tracks failed to work causing
    a mis-coloring of the history when -lastasfirst was turned on.
  * Corrected a potential problem in the processing of end of lines
    in multi-lines texts.
  * Update of the refman, tanks C. Mertz.
  * Fixed the Makefile.in to build a correct pkgIndex.tcl when
    installing, it lacked an entry for loading the Tkzinc
    library itself.
  * Debug.pm :  A control bar and zoom/translate new functionalities
    have been added. finditems(), tree(), snapshot() functions become
    deprecated. Initialisation is done using the new init() function.
    (D. Etienne).
  * zinc-demo (perl variant) : the pathtag demo has been corrected.
    Should be more explict now (C. Mertz)
  * A first contribution by zentara : TripleRotatingWheel.
  * New tests (perl variant) : find method with 'overlaped', 'enclosing',
    'withtype', pathtags. More images tests. Tests for text items.
    Tests for openGL fonts with multiple sizes (C. Mertz).
	
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  28 Nov 2003 13:37:48 +0200
	
zinc-tk (3.2.95) unstable; urgency=low

  * Configuration of image and bitmap valued attibutes is now
    optimized against reconfiguration with the same value (image).
    This has the side benefit of fixing a core dump ;-).
  * Fixed the return type of the ZnPointInRegion prototype to return
    a ZnBool (A. Lemort).
  * Stephane Conversy has contributed diffs to compile the tcl
    version on MacOs X Fink.
  * ZincDebug: Contours of curves can be displayed and explored
    (D. Etienne).
  * ZincDebug: Fixed a bug in device coordinates when a non group
    item has a transformation (D. Etienne).
  * a new debian package has been created to install the doc
    files (pdf and html) separately.
  * Integrated the export script and Makefile contributed for
    Perl by Somanos Sar. Merged the CPAN features written by
    C. Mertz.
  * The scrollbar protocol should now work with perl as well as
    with tcl.
  * libom is no more. It will be made into a loadable module
    as soon as Tkzinc will have stubs and a tcl binding will be
    written for the overlap manager api.
  * No more perl building/configure code in the main trunk. All
    perl related build and configuring tools are in Perl.
  * Fixed a font texture allocation problem with large fonts.
    The texture sizing has been changed with better results.
  * Added a -tracksymbol option to act as the default value
    for the -symbol attributes of tracks.
  * The track default symbol for current positon is now correctly
    read from the -tracksymbol option and not statically fixed.
  * Changed the parameters of the new conical gradient.
    If only one value is given, it is taken to be the gradient
    starting angle, the center being 0,0. If two values are given,
    they are taken as the gradient center, the starting angle being 0.
    If three values are given, it's the gradient center followed by
    the gradient starting angle. If four values are given, they are
    two points defining the center and the angle/extent of the gradient
    (vector based definition).
  * Corrected a bug when tiling aligned rectangles under GL.
    The rectangular form was not correctly clipped so that
    it showed outside its area.
  * Shaped icons should be rendered correctly under all environments
    and for all image formats.
    In fact the image/bitmap code has been reworked and integrated.
    For the internals there is no difference now between images,
    image supported bitmaps and old style bitmaps obtained by
    Tk_DefineBitmap.
  * The image update mecanism is now fully functional. It will
    work for tiles, icon, symbols and even patterns if they are
    made with image bitmaps.
  * Icon item picking should be ok in all cases and all environments.
    It used to be limited for rotated shaped images.
  * Change in the font texture allocation to guarantee that it
    will not fail. This is now postponed until first use for
    drawing.
  * Videomap loading is done through the Tcl_Channel api enabling
    the use of Tkzinc and all of its datas in a starkit.
  * no more dependencies between zinc-perl and zinc-tk
  * a new perl module for building complex graphic objects:
    Tk::Zinc::Graphics.pm
  * Perl module Text is renamed Tk::Zinc::Text (beware: slight incompatible change!)
  * Perl module Logo is renamed Tk::Zinc::Logo
  * PerlModules ZincTrace, ZincTraceErrors and ZincDebug are renamed
    Tk::Zinc::[Trace|TraceErrors|Debug]
  * new demos :
    - color-path-and-conic.pl to demonstrate conical and path gradient
    - testGraphics.pl to demonstrate the power of Graphics.pm
    - Magiclens.pl 

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  5 Sep 2003 13:37:48 +0200

zinc-tk (3.2.94) unstable; urgency=low

  * Added an optimization for aligned/textured rectangles in openGL.
    This can really boost the performances of some apps.
  * Fixed a core dump when destroying zinc after an error occured
    during the first Configure.
  * Fixed the picking of multi-contours curves. They should be
    correctly detected now.
  * Fixed a bug in the compilation of libtess around the inclusion
    of glu.h
  * Added a new vector based method to describe gradient geometry.
    The vector is specified by two points (4 floats).
    It is available for axial, radial and the new conical gradients.
  * Added a new gradient type: conical, defined by an angle,
    a center and an angle or a vector.
  * (ZincDebug) A partir de l'arbre des items, possibilité de générer
    du code perl correspondant à une branche (Daniel Etienne).
  * Ajout d'un module ZincTraceError (perl) qui trappe les erreurs
    Zinc et affiche pour chaque erreur l'instruction et le message
    d'erreur (Daniel Etienne).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 21 May 2003 09:22:18 +0200

zinc-tk (3.2.93) unstable; urgency=low

  * Fixed a bug preventing the loading and display of accented letters
    in openGL.
  * In zincText.tcl fixed a problem preventing insertion of accented
    letters
  * Added the documentation in the tk debian package
  * Shaped images can be used both in perl/tk and in Tcl/Tk under
    GL. Alpha channel is also supported in perl/tk (for image formats
    that support the feature).
  * Fixed a gradient filling bug on some (many usual) multi-contours
    curves.
  * Fixed a X Pixmap error problem (in GL) with some fonts reporting
    a zero width on critical characters.
  * Text item: Modified the processing of the white space/tab causing
    a line break when a -width limiting atribute is in effect. The extra
    space used to be located at the beginning of the new line. Now it is
    suppressed. Other white spaces are still displayed at the begining
    of the line. The new behavior seems more natural.
  * Fixed a typo in zincText.tcl preventing the insertion of a new line.
  * Fixed a core dump when destroying a map item due to
    the freeing of an unallocated pattern in the symbols
    list

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 12 May 2003 13:51:10 +0200

zinc-tk (3.2.92) unstable; urgency=low

  * Perl compilation ok even if no package installed
  * Perl demo runable without installation. Idem for
    tests (but there is no tests yet ;-).
  * Fixed Enter/Leave bugs during grabs and in fields.
  * Fixed stipple filling in openGL.
  * Fixed several core dumps.
  * Fixed several bugs in relation with contour manipulation
    (adding, orientation evaluation, memory allocation, gradients).
  * Fixed text cursor visibility if no text to display (text
    item & fields).
  * Fixed problems with some demos in Tcl.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  9 May 2003 17:12:14 +0200

zinc-tk (3.2.91) unstable; urgency=low

  * Corrected the scollbar/view bug under Windows.
  * Polished quite a bit the install process.
  * Added a makefile.vc to be used with Visual C++ on Windows.
  * Small fixes on several demo scripts.
  * Corrected a very touchy bug related to font texture
    loading on Windows. The symptom is a blank window,
    if it contains text and the mouse is in the window
    when it is mapped.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 25 Apr 2003 11:50:38 +0200

zinc-tk (3.2.90) unstable; urgency=low

  * Portage Windows
  * Changement du symbole de compilation openGL de GLX en GL.
  * Tentative de préfixage exhaustif de tous les symboles externes
    (fonctions, macros, variables, types) par Zn.
  * Modification du code de traitement des images pour 1/ assurer
    le portage sous Windows, 2/ Obtenir le rendu transparent pour
    les images le supportant (PNG), 3/ Rétablir dans un deuxième
    temps le mécanisme de mise à jour de Tk lors de la modif de
    l'objet image. Le prix à payer est l'impossibilité temporaire
    d'avoir des images détourées en perl/Tk **PROBLEME POTENTIEL**.
  * Compilation avec tous les warnings réalistes et correction des
    types de variables + casts explicites pour faire disparaitre
    les warnings.
  * Suppression de l'utilisation de strcasecmp pour la conversion
    des valeurs certains attributs. Il faudra désormais les spécifier
    obligatoirement en minuscules. **PROBLEME POTENTIEL**.
  * Utilisation du code de gestion des couleurs de Tk plutôt que
    celui qui avait été importé depuis Tk dans zinc.
  * Gros remaniement du code de chargement des glyphes de fontes
    sous forme de textures en openGL afin d'assurer le portage
    Windows.
  * Dans l'item Text -spacing et -width sont des entiers au lieu de
    floats.
  * Les priorités par défaut ont été modifiées et valent 0 pour Map
    et Reticle et 1 pour tous les autres items. **PROBLEME POTENTIEL**.
  * Grosse réorganisation des headers afin de regrouper par module
    logique. Cela a permit de dégonfler Types.h.
  * Déplacement des fonctions de parsing d'attributs de Item.c vers
    Attrs.c comme de logique.
  * Nouvelle chaine de configuration/Makefile basée sur TEA.
  * Restructuration des fichiers afin d'être plus proche de l'architecture
    TEA.
  * Portage des démos en Tcl (J.P Imbert).
  * Début de squelette pour des tests en Tcl.
  * Le Makefile.PL est généré par configure. C'est également le cas
    de Zinc.py. Cela permet une meileure configuration selon les
    plateformes et les versions.
  * Changement de module dans le repository CVS. Le module s'appelle
    désormais Tkzinc. L'ancien module reste actif au cas où.
  * Des corrections de bugs nécessités/découverts par le portage
    Windows.v
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 24 Apr 2003 11:59:09 +0200

zinc-tk (3.2.6i) unstable; urgency=low

  * Les couleurs du relief de la fenêtre ne sont allouées que si
    et lorsque le relief est différent de flat. Cela permet de
    ménager les colormaps.
  * zinc verifie que l'on ne demande pas à chggroup de placer un
    ancestre dans un de ses descendants.
  * Les infos GL au démarrage sont conditionnées à la présence de
    la variable d'environnement ZINC_GLX_INFO.
  * Les flags -composerotation et -composescale de Icon sont
    positionnés à vrai par défaut. C'est un pis-aller, il faudra
    repenser le traitement des icones et du texte dans un contexte
    de transformation totale (rotation, echelle).
  * Correction d'un bug de précision conduisant à la fameuse bande
    non rafaichie à droite en 1600x1200 sous GL.
  * Le paquet zinc debian devrait mieux se comporter quand aux
    dépendances sur les autres paquets tant à la compil qu'au
    runtime. La dépendance à openGL est supportée au travers
    de mesa.
  * Le répertoire test est renommé sandbox. IL FAUT RE-EXTRAIRE
    une copie fraiche des sources depuis la base CVS ou tripoter
    les fichiers dans les répertoires CVS de zinc et de sandbox
    pour refléter la modif.
  * Changement du format des gradients pour être compatible avec
    les formats de nom de couleur normalisés. MODIF INCOMPATIBLE.
  * Début d'architecure TEA pour la version Tcl. Le module Zinc
    utilise désormais les stubs de tcl/tk plutot que le linker
    dynamique pour résoudre les références sur tcl/tk. Il en
    résulte une meilleure indépendance par rapport aux versions
    de tcl/tk.
  * Incorporation de libtess, ce qui permet de se passer de GLU/GL
    dans des versions sans openGL.
  * Améliorations et corrections de bugs dans ZincDebug (Daniel Etienne):
  	Gestion de plusieurs instances de Zinc.
        Paramétrage de ZincDebug sur la ligne de commande:
          perl -MZincDebug monappli.pl <-options_monappli> <-options_zincdebug>
        Ajout d'un bouton treset permettant de savoir si un item a subi des
        transformations.
        Correction de bug d'affichage :
          des coordonnées d'un item curve.
          de la bounding box de groupes vides.
  * Incorporation d'un module python mis à jour (uillaume Vidon)
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 10 Mar 2003 17:42:53 +0100

zinc-tk (3.2.6h) unstable; urgency=low

  * Correction d'un bug provoquant la suppression d'un blanc
    en début de lignes sur l'item text
  * Correction d'un problème de spécialisation des images sous
    X. Il fallait spécialiser par Screen et non par Display.
  * Correction d'une erreur lors de la requête de bindings
    sur un item/séquence.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 20 Jan 2003 13:53:19 +0100

zinc-tk (3.2.6g) unstable; urgency=low

  * Edition des attributs dans ZincDebug: la plupart des champs attributs
    sont maintenant éditables (un <Control-z> dans un champ permet de
    restaurer la valeur initiale)
  * Possibilite de visualiser la bounding box d'un item dans ZincDebug.
  * Ajout d'un module permettant de tracer les appels de commande 
    zinc pour faciliter sensiblement le debugging d'une appli. Faire
    perl -MZincTrace myscript.pl (Christophe/Daniel).
  * Correction d'un bug d'analyse des listes de points d'ancienne forme.
  * Correction d'un core dump lors d'une tentative de clonage du top
    group.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 20 Jan 2003 10:53:40 +0100

zinc-tk (3.2.6f) unstable; urgency=low

  * Adaptation des méthodes fit, smooth, transform, coords, contour
    pour obtenir un tout cohérent dans la nouvelle logique de gestion
    des points et des contours.
  * Correction d'un bug de gradient introduit par le debug.
  * Ajout d'un attribut -fillrule à l'item curve (en liaison avec le
    premier point.
  * L'item curve ne détruit plus un contour vidé par la méthode coords.
    Il n'en ajoute pas non plus (cas d'un item vide).
  * Correction d'un bug d'affichage de texte en GL avec plusieurs
    fenêtres (cycle de création/destruction).
  * Corrections de bugs en relation avec le premier point.
  * La limitation qui obligeait à déclarer comme globale l'instance de zinc
    lorsque ZincDebug était chargé au runtime (perl -MZincDebug script.pl)
    n'est plus.
  * Correction de bug (ZincDebug): la selection du groupe 1 dans l'arbre des
    items provoquait un segmentation fault.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue, 14 Jan 2003 12:14:38 +0100

zinc-tk (3.2.6e) unstable; urgency=low

  * Corrections de bugs
  * Ajout du support UTF8 pour Tcl/Tk
  * Possibilité d'invoquer ZincDebug sans modifier le code,
    de la maniere suivante: perl -MZincDebug script.pl
    (cf man ZincDebug). Ajout de D.Etienne.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 20 Dec 2002 14:56:42 +0100

zinc-tk (3.2.6d) unstable; urgency=low

  * Adaptations (mineures) pour TCL/TK 8.4.
  * Corrections de bugs dans les méthodes Coords et Contour.
  * Changement incompatible du code des gradients.
  * Fin de réalisation des nouveaux contours utilisant le tesselateur GLU.
  * Le tesselateur est disponible même si on utilise une version compilée sans GL.
  * Fin de réalisation des paths dans Curve.
  * Utilisation des display lists GL pour Arc, Curve, Rectangle, Text.
    L'optimisation n'est effective que si l'item n'est pas modifié (ce qui est
    souvent le cas quand même).
  * Encore des corrections de bugs.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue, 10 Dec 2002 11:09:08 +0100

zinc-tk (3.2.6c) unstable; urgency=low

  * Correction d'un bug empéchant Zinc de s'initialiser (ZnBezier a disparu).
  * Mise à jour de ZincDebug par Daniel Etienne:
     Modification concernant la fonction tree() :
     Possibilité d'afficher, pour chaque item de l'arbre, la valeur d'un ou
     de plusieurs de ses attributs; utiliser les options -optionsToDisplay et
     -optionsFormat.
     Mécanisme de recherche de chaine de caractères.
     Feedback pour signaler qu'un item sélectionné dans l'arbre n'est pas
     visible car en dehors de la fenêtre.
  * Suppression de la fabrication du paquet zinc python qui de toute manière
    n'était plus maintenu et ne fonctionnait pas sous Woody.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed,  6 Nov 2002 09:59:13 +0100

zinc-tk (3.2.6b) unstable; urgency=low

  * Correction d'un bug empechant la mise à jour des bitmaps/images modifiées.
  * Suppression du clippeur GPC et remplacement par le tesselateur de GLU.
    Zinc est maintenant entièrement Open Source ;-).
  * Les commandes contour ont entièrement changé: exit les union, xor, inter, diff
    maintenant on peut faire des add, addhole et remove. Les contours ainsi manipulés
    gardent leur position relative les uns par rapport aux autres.
  * L'item Bezier n'existe plus, il est remplacé par un traitement plus général dans
    Curve qui accepte maintenant la specification de controles sur les points. Il est
    ainsi possible de décrire des chemins mélangeant segments de droites et de cubiques
    de Bezier.
  * Correction d'un oubli dans Zinc.pm qui empêchait l'usage de vertexat.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue,  5 Nov 2002 11:13:12 +0100

zinc-tk (3.2.6a) unstable; urgency=low

  * Correction du bug de rendu des lignes (hachures) sur GeForce 3/4
  * Correction d'un bug de rendu de lignes avec alpha dans certaines
    circonstances (modulation de la couluer).
  * Adaptation du Makefile pour compil avec les derniers drivers NVidia.
  * Correction du bug de mise à jour de la bbox d'un gruope suite à
  l'ajout/suppression d'un item (Daniel Etiienne, Nathalie Banoun).
  * Correction d'un bug sur l'épaisseur des lignes de 0.5 pixels en GL.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 26 Sep 2002 12:10:58 +0200

zinc-tk (3.2.6) unstable; urgency=low

  * Correction d'un bug lors de l'utilisation simultanée par
    une appli d'un environnement X et GL (Bug détecté par A. Marion).
  
  * Corrections dans le Makefile.in.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 18 Sep 2002 15:07:37 +0200

zinc-tk (3.2.5i) unstable; urgency=low

  * Encore des corrections de bugs

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon,  9 Sep 2002 14:48:46 +0200

zinc-tk (3.2.5h) unstable; urgency=low

  * Corrections de bugs.
  * la commande contour retourne le nombre de contours d'un item.
  * Changements dans ZincDebug (Daniel Etienne), la liste suit :
  * meilleure gestion des groupes atomiques : ils sont maintenant scannés
    comme les autres.
  * la mise en evidence des items selectionnés est modulable. Par defaut,
    l'item est mis en avant-plan et encadré (click gauche), mais pour
    faciliter sa distinction on peut egalement cacher les autres items de
    son groupe (click milieu), voire ceux du groupe parent (click droit).
  * il est possible de rechercher des items en specifiant un tagOrId dans
    un champs de saisie (ouvert sur un Control-f)
  * séparation des traitements : 2 fonctions sont maintenant exportées,
    finditems() qui cree les bindings necessaires a la recherche d'items
    et snapshot() qui cree ceux necessaires a la capture d'image. (action
    sur Control-s)
  * mise a jour du man ZincDebug
  * Possibilite d'afficher l'arbre des items d'une application
    (Control-t)

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon,  2 Sep 2002 14:36:04 +0200

zinc-tk (3.2.5g) unstable; urgency=low

  * Ajout de la commande find ancestors qui permet de retrouver, avec
    un éventuel filtrage sur tag, l'ensemble des ancêtres d'un item.
  * Corrections de bugs sur le curseur d'insertion : text et fields.
  * Correction d'un bug dans find overlapping/enclosed qui retournait
    des résultats aléatoires selon le groupe de départ.
  * Correction du calcul des ancres pour les items icons.
  * Nouveaux programmes de démos et amélioration de la doc (C. Mertz)
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  5 Jul 2002 17:08:12 +0200

zinc-tk (3.2.5f) unstable; urgency=low

  * Correction d'un bug génant (les items se déplacent suite à un
    problème dans la méthode ToArea de group) introduit en 3.2.5d
    et révélé en 3.2.5e.
  * Ajustement de la doc pour find/addtag.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue, 25 Jun 2002 11:38:36 +0200

zinc-tk (3.2.5e) unstable; urgency=low

  * Corrections de qq bugs.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 24 Jun 2002 11:19:02 +0200

zinc-tk (3.2.5d) unstable; urgency=low

  * la commande de création de zinc rapporte le numéro de version
    et énumère mes différentes têtes graphiques possibles (X11, GL).
  * Les fonctions tsave et gsave permettent de savoir si un nom est déjà
    utilisé.
  * L'item Icon peut tourner et être redimensionné.
  * QQ bug squashes.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 10 Jun 2002 15:33:46 +0200

zinc-tk (3.2.5c) unstable; urgency=low

  * Correction du calcul de l'angle du guideur (passage entre
    antirec et Zinc + une erreur dans la fonction PointPolarToCartesian.
  * Le rho n'était plus passé à l'antirec second problème expliquant
    les perfos pitoyables de l'antirec.
  * Correction d'un bug de specification d'angle créant un problème dans
    les items arcs si on specifiait un extent de 360.
  * Correction d'un core dump lors de la deallocation des fontes (cas
    où plusieurs Zincs sont créés).
  * Correction d'une boucle infinie lors de l'allocation d'une fonte
    (cas où plusieurs Zincs sont créés).
  * Correction d'un core dump se produisant dans certains cas lors de
    l'utilisation d'un Curve en clipping.
  * Correction d'un core dump lorsque l'on tentait d'éditer un texte
    dans un champ.
  * Les ressources Zinc de type images/bitmaps (-tile, -mapdistancesymbol,
    etc), ne pouvaient pas être remises à "". Une consultation de la valeur
    de ces ressources provoquait un core dump si la ressource valait "".
  * L'item Icon ne possède plus qu'un attribut -image/-mask. Cependant il
    est toujours possible de positionner cet attribut soit par -image soit
    par -mask. La reconnaissance bitmap/image est automatique.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 27 May 2002 17:07:19 +0200

zinc-tk (3.2.5b) unstable; urgency=low

  * Les tags peuvent désormais comporter un chemin permettant de
    préciser dans quelle partie de l'arborescence les items doivent
    être recherchés. Le chemin consiste en une suite de tags séparés
    par des . ou des *. Chaque tag désigne le groupe possédant ce tag
    à un niveau donné de la hierarchie. Le caractère * premet de demander
    la recherche en profondeur en sautant éventuellement des degrés dans
    la hierarchie. LES CARACTERES . et * sont donc INTERDITS dans les tags.
    Cette fonctionalité est particulièrement importante lors de l'utilisation
    de la commande clone (création et paramétrage d'après un modèle,
    programmation par prototype). Elle est sensée être à peu près transparente
    pour ceux que cela n'interesse pas.
  * Les sous commandes de find/addtag ont été remaniées pour tenir compte
    du point précédent. En particulier 'find all' a disparu. Les
    paramètres optionnels 'inGroup' et 'recursive' ont disparu des commandes
    above, below, withtag. Ils sont remplacé par un simple tag optionnel
    pour les commandes withtype et atpriority. Par contre les commandes
    overlapping et enclosed gagnent ces mêmes paramètres optionnels 
    'inGroup' et 'recursive'. La commande closest gagne le paramètre optionnel
    'recursive' et le paramètre start voie son sens modifié : si 'start' est
    un groupe non ATOMIC, la recherche démarre au premier item de ce groupe
    sinon le sens précédent est conservé, la recherche démarre à l'item suivant
    'start'
  * Un tag chaine vide (ou un chemin sans tag final) est équivalent au
    tag 'all'.
  * Meilleure prise en compte de la présence de l'extension GLX. Son
    absence ne devrait plus générer de core dump.
  * La commande clone ne clone plus tous les items désignés par le tagOrId
    mais seulement le premier dans l'ordre de la display list et elle
    retourne l'id de ce nouvel item.
  * Correction d'une erreur dans itemconfigure qui retournait une info
    incorrecte quand on lui demandait la liste des attributs d'un field.
  * Redesign complet de la gestion des images/bitmaps et fontes afin 1/
    de gérer correctement les ressources sous GL avec plusieurs fenêtres
    et 2/ de LIBERER les ressources automatiquement lorsqu'elles ne sont plus
    utilisées (textures et mémoire process X et GL). Une conséquence est
    que le nouveau code ne peut plus gérer le changement du contenu d'une
    image Tk, il faut détruire l'image et la recréer.
  * Correction d'un bug provoquant un core dump en 3.2.5a suite à la modification
    du code de réparation de l'image. Un redisplay était planifié lors de la
    destruction d'un widget et lorsqu'il était effectivement déclenché le
    widget n'existait plus, bien sûr.... No comments
  * Les bordures de champs n'étaient pas dessinées en GL, l'alpha n'étant
    pas composé correctement et l'épaisseur de trait à été portée à 1.5.
  * Correction du code de dessin des images dans les fields sous X. Elles ne
    pouvaient pas être clippée correctement si elles avaient un masque.
  * Correction d'un bug de clonage des fields, on tentait de dupliquer
    un label format sur un groupe de champs vide.
  * Mise en cohérence des types d'attributs entre le code et la doc, certains
    type ont été modifiés dans le code : tags/taglist, justify/alignment,
    autojustify/autoalignment, border/edgelist, gradients/gradientlist,
    text/string, patterns/bitmaplist, pattern/bitmap.
  * Retablissement du controle de la validité des attributs dans
    itemconfigure même lorsqu'un tag est utilisé.
  * Correction dans les lineshapes des types lineleftcorner et
    linedoubleleftcorner qui étaient confondus avec leur analogues
    droits.
  * Sortie d'un message d'erreur lorsqu'un item n'est pas trouvé comme
    valeur d'attribut.
  * Correction du traitement des angles startangle et extent dans Arc, les
    extents négatifs étaient erronés et si startangle était nul on obtenait
    systématiquement un arc de 360 degrés.
  * Ajout d'un attribut -composealpha à tous les items. Il agit de la même
    manière que -composescale et -composerotate mais pour l'alpha des
    couleurs de l'item.
  * Correction d'un bug rendant inctif le paramètre de tension dans les gradients.
  * Incorporation des corrections de Christophe dans la doc.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  3 May 2002 13:44:17 +0200

zinc-tk (3.2.5a) unstable; urgency=low

  * Correction d'un core dump lors de la destruction d'un
    item text cloné dont on a modifié le texte.
  * Le changement de fonte d'un texte (Text et Field) n'était
    pas suivi d'effet en openGL, maintenant ça devrait aller
    mieux.
  * Tous les items peuvent avoir le focus, donc on peut utiliser
    des bindings sur des evènements clavier sur tout item. C'est
    également vrai pour les fields (extension de la commande focus).
  * La selection et le curseur sont affiché en GL pour l'item Text
  * La selection et le curseur sont affiché pour le texte dans les
    fields (X et GL).
  * L'édition de texte, la selection, et le curseur sont supportés
    pour les fields.
  * Restructuration du module Item, création du module Field et
    suppression de l'ingérance de Item dans Group. Le code devrait
    être plus clair et plus facile à maintenir (il reste à préfixer
    toutes les fonctions externes par Zn).
  * L'option -render n'est plus un booléen, elle peut prendre les
    valeurs 0: rendu X, 1: rendu GL direct, 2: rendu GL indirect.
  * Amélioration de ZincText.pm: correction de bugs, évolution des
    bindings pour mieux gérer la sélection, intégration de l'édition
    des textes dans les fields, possibilité d'aller en fin/début de
    ligne, de monter/descendre d'une ligne (item text).
  * Des nouveaux indices sont disponibles dans les items indexables:
    bol, eol, bow, eow, up, down.
  * Correction d'un core dans DeleteChars de Text (pointeur non
    déréférencé).
  * La commande currentpart prend un paramètre booléen optionnel
    qui spécifie si elle doit reporter les parties privées de l'item
    ou seulement les fields (elle retourne "" si le pointeur est
    sur une partie privée).
  * Toutes les commandes acceptant un paramètre field optionnel
    comprennent un field index "" comme étant une absence de paramètre:
    aucune erreur n'est générée et tout se passe comme si le paramètre
    n'avait pas été spécifié.
  * Les commandes 'focus' et 'select item' retournent une liste
    (item, field) ou "" si pas d'item. La présence de field est
    garantie (liste de longueur 2) mais peut être "", se qui veut
    dire pas de field. On peut directement utiliser le résultat
    de ces commandes comme paramètres pour les commandes prennant
    un couple item, field.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 12 Apr 2002 13:02:05 +0200

zinc-tk (3.2.4) unstable; urgency=low

  * Correction de -lastasfirst, le bug était dû à un
    débordement du champs de bits traitant les flags.
    Il a été porté à 16 bits pour tous les flags d'item
    (header et privé).
  * Correction d'un core dump lors de clonage de rectangle,
    arc, curve, bezier. La réallocation des structures
    géométrique doit se faire tout de suite dans clone.
  * Correction du bug faisant apparaitre un petit carré en
    fin de ligne dans Text.
  * Les coins supérieurs des bordures des rectangles n'étaient
    pas fermés (visible sur les bordures épaisses).
  * Zinc openGL marche un peu mieux sous Mesa (attention aux
    -linewidth supérieurs à 3 et inférieurs à 11).
  * Module perl ZincText.pm qui permet d'éditer les items textes
    pour peu que ceux ci possèdent le tag 'text'. Il faut faire:
    use ZincText; new ZincText($zinc);
  * L'option -tile de Zinc n'avait pas subit le traitement destiné
    à l'immuniser contre les images sans contenu. Il en resultait
    l'infame XCreatePixmap error. C'est corrigé.
  * itemconfigure a été (encore) modifié pour accepter les attributs
    inconnus. Il est préferrable de na pas reporter d'erreur que
    de bloquer un itemconfigure sur tag.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 29 Mar 2002 16:19:40 +0100

zinc-tk (3.2.3g) unstable; urgency=low

  * Correction d'un core d'un lors de la creation répétée
    d'un label format erroné. L'entrée de cache n'était pas
    détruite bien qu'invalide.
  * Correction d'un bug très génant de redessin en openGL du
    à un problème de calcul de la damaged area et révélé par
    la modification du traitement de la zone de dessin du
    widget (inset). Un contournement en 3.2.3f et de mettre
    -borderwidth et highlightthickness à 0.
  * Dans le code de reparation le scissor n'était pas réactivé
    aprés le dessin de la bordure.
  * Correction de la commande itemconfigure qui reportait à tort
    une erreur attribut invalide sur un tag. L'erreur doit être
    reportée que pour un id.
  * Rectangle correction d'un core dump dû à une variable couleur
    non initialisée (si -linewith != 0).
  * Le code de redessin sur changement de focus nécessaire pour
    corriger certains problèmes liés au redessin avec scissor n'était
    pas compilé conditionnellement.
  * Un pas de plus vers une doc potable.
  * Ajout d'une démo sur les transformations.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue, 26 Mar 2002 10:42:27 +0100

zinc-tk (3.2.3f) unstable; urgency=low

  * Remplacement de la doc PostScript par une doc pdf.
    Celle ci exploite les références hyper texte et la table
    des matières latérale.
  * Un grand pas en avant sur le contenu de la doc. Pas mal
    d'explications supplémentaires et des chapitres vides qui
    commencent doucement à se remplir. Mise à jour pour les
    nouvelles fonctionalités (pas toutes encore). Index,
    figures, etc Contribution de Christophe Mertz.
  * Une suite de démos qui fonctionne et qui commence à être
    sympa est apparue. Merci là aussi  Christophe Mertz, et qq
    autres. Qui?
  * Réalisation de reliefs pour les courbes exploitant
    les possibilités de dégradés de GL. L'item curve
    possède un attribut -smoothrelief qui permet de décider
    si on veut traiter le relief comme pour un arc (en douceur)
    ou par facettes.
  * Les reliefs peuvent être bombés au lieu d'être simplement
    biseautés (plusieurs variations).
  * La couleur des reliefs est calculée sur le -linecolor et
    non plus sur le -fillcolor. INCOMPATIBILITE.
  * Portage de l'item Bezier en GL. Il peut se dessiner et servir
    de clipping.
  * Correction d'un bug dans LeaderAnchor qui empéchait le
    paramétrage. Il n'y a pas beaucoup de monde qui a essayé
    de s'en servir, apparement.
  * Suppression du inset autour de la fenetre. L'origine des
    coordonnées device est partout et pour toutes les commandes
    le 0,0 de la fenetre.
  * Amélioration de la détection des images bugées. Désormais
    si une image est malencontreusement créée vide (nom de fichier
    ""), zinc détecte l'anomalie et sort une erreur.
  * Correction d'un bug qui affectait chggroup lorsqu'elle était
    utilisée sur un groupe et sans ajustement : les fils du groupe
    n'étaient pas replacés correctement.
  * Rétablissement de l'option -lastasfirst de l'item track qui
    était en panne du à un débordement de capacité des flags
    privés.
  * Correction de deux bugs dans le tracé des cercles. Un empéchait
    le tracé correct d'un cercle complet dans arc (sous certaines
    conditions). L'autre créait une petite facette sous certains
    angles pour un arc non complet.
  * Toutes les options couleurs de zinc sont exprimables sous forme
    de gradient et donc possèdent un alpha. C'est appréciable sachant
    par example que -forecolor sert de valeur par défaut à la plupart
    des couleurs d'item.
  * L'option de relief bénéficie également d'un traitement spécial
    permettant toutes les valeurs de relief (pas seulement celles
    acceptées par Tk).
  * Makefile.in tricky enhancement for installing zinc-demos and its
    components (H. Damiano)

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 15 Mar 2002 16:15:06 +0100
  
zinc-tk (3.2.3e) unstable; urgency=low

  * Intégration des modifs des Didier Pavet concernant l'antirec.
  * Petite mise à jour de l'interface Python (D.Pavet).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 20 Feb 2002 14:02:59 +0100

zinc-tk (3.2.3d) unstable; urgency=low

  * Suppression des attributs alpha. Toutes les couleurs
    sont des gradients et comportent un alpha. Les gradients
    ont été totalement purgés du code développé pour le
    rendu sous X (shades).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 18 Feb 2002 17:03:05 +0100

zinc-tk (3.2.3c) unstable; urgency=low

  * Correction d'un bug de recalcul de la géométrie des
    labels lors d'une modif d'un champ.
  * Correction du dessin des arcs lorsqu'ils ne sont pas
    complets (arc partiel). Meilleure prise en compte
    des angles en utilisant le modulo plutôt que le bornage.
  * Les attributs de type dimension comme les linewidth et autres
    tailles, n'acceptent plus une spécification à la Tk avec
    possibilité de décrire en point en millimètres etc. En
    revanche ils sont promus valeur flottante et donc peuvent
    être utilisé en GL pour spécifier des tailles fractionnaires.
  * Correction d'un bug de clipping qui empéchait la remise à
    jour de la scène après la suppression du clipping dans un
    groupe.
  * Correction du clonage et de la destruction d'un item Triangles.
    Les couleurs n'étaient pas correctement dupliquées/libérées.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 15 Feb 2002 10:29:55 +0100

zinc-tk (3.2.3b) unstable; urgency=low

  * Ajout de démos de Christophe dans le répertoire
    examples.
  * Correction des bugs de dessin des polylines qui affectaient
    gravement twinkle (entre autre).
  * Correction de code de Daniel.
  * Correction de tsave et trestore, les noms ne fonctionnaient
    pas.
  * Ajout du module PerlDebug et de quelques examples
    contribués par Daniel Etienne.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 28 Jan 2002 14:57:57 +0100

zinc-tk (3.2.3a) unstable; urgency=low

  * Ajout d'attributs dans Track sur vecteur vitesse.
  * Ajout de RenderPolyline qui débarasse de libgle et qui fournit
    les flêches.
  * Ajout de l'item Triangles.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon,  3 Dec 2001 15:29:13 +0100

zinc-tk (3.2.2) unstable; urgency=low

  * Ajout du clipping non rectangulaire.
  * Gradient PATH
  * Correction d'un bug de binding Enter/Leave dans item.
  * Intégration de la gestion sélective du redessin.
  * Réalisation de la bordure relief et du highlight de focus
    directement en X ou en GL pour éviter les clignotements
    (en GL).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 26 Nov 2001 11:29:08 +0100

zinc-tk (3.2.1) unstable; urgency=low

  * Correction d'un core dump dans clonage de curve.
  * Correction d'un break oublié dans mapinfo add symbol.
  * Travail sur les gradients et les reliefs.
  * Corrections de bugs dans la version OpenGL.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed,  7 Nov 2001 10:31:22 +0100

zinc-tk (3.2.0) unstable; urgency=low

  * Version avec OpenGL actif.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 24 Oct 2001 15:25:10 +0200

zinc-tk (3.1.28) unstable; urgency=low

  * Correction du core dump dans la fonction currentpart si
    pas de current item.

  * Recompilation avec la dernière version de perl woody.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 12 Oct 2001 09:50:39 +0200

zinc-tk (3.1.27) unstable; urgency=low

  * Correction d'un bug de sensibilité sur tabular et track

  * Modification de la syntaxe des gradients (-fillcolor) et
    réécriture des gradients.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 25 Jun 2001 13:27:40 +0200

zinc-tk (3.1.26) unstable; urgency=low

  * Correction de itemcget et itemconfigure afin qu'ils retournent
    des tableaux perl et non des refs sur des tableaux.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 30 Mar 2001 14:19:54 +0200

zinc-tk (3.1.25) unstable; urgency=low

  * Retour arrière sur le traitement du grab lors d'un buttonpress.

  * Correction du bug bloquant l'appel des callbacks d'enter lors du
    dans l'item de grab (buttonpress actif).

  * Correction de doc.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue, 20 Mar 2001 10:49:46 +0100

zinc-tk (3.1.24) unstable; urgency=low

  * Un début de scripts de démo en Perl.

  * Des adaptations pour Redhat/Mandrake et Solaris au niveau
    de la compilation (configure, Makefiles).

  * Debut d'intégration d'un rendu à base de GLX.

  * Corrections de bugs de rendu (rectangle, track), et de
    clipping (champs). Le relief des curves est géré dans
    le bon sens (il était inversé).

  * Correction du bug des curves -closed (corre dump).

  * Correction du core dump lors de la destruction d'un dépendant,
    par example waypoint attachées.
    
  * Correction de la fonction contour, il est désormais possible
    de fournir un contour sous forme de point. Correction d'un
    core dump lié à la libération intempestive de mémoire.

  * Correction de coords, il est possible d'ajouter/modifier des
    points à un curve sans contours (curve vide à la construction).
    
  * Modification du traitment des évènements/bindings pour
    les champs/parties. Maintenant les enter/leaves d'items
    sont controlés exclusivement par la sensibilité de l'item
    et les enter/leaves de champs par la sensibilité du champ
    et celle de l'item.

  * Suppression du grab sur bouton gauche appuyé, les enter/leave
    sont toujours générés.

  * Tentative d'homogénéiser la valeur de retour des fonctions
    retournant une liste. Désormais ce sera un tableau en Perl.
    Les fonctions touchées : bbox, monitor, find, mapinfo get.
    
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  9 Feb 2001 11:22:22 +0100

zinc-tk (3.1.23) unstable; urgency=low

  * -curve est à false par défaut (conforme à l'ancien
    usage).
  * Une curve ouverte garde ses deux points extrèmes même
    s'ils sont identiques.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 12 Jan 2001 17:39:42 +0100

zinc-tk (3.1.22) unstable; urgency=low

  * Ajout de sections de compilation conditionnelle pour libart.
    Renommage de l'option -localrender en -render pour préparer
    l'avenir (openGL ou extension Render de Xfree86).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu,  4 Jan 2001 11:41:11 +0100

zinc-tk (3.1.21) unstable; urgency=low

  * Ajouté une dep sur libart. Corrige des bugs sur l'appel de l'antirec.
    Corrge un bug de spec sur l'affichage de la derniere pos d'une piste
    en surbrillance.
    Implementation de la méthode Render sur plus d'items.
    Le vecteur vitesse est codé en flottant et il est possible de modifier
    sa largeur.
    Blocage de la version Tk à 8.0 pour etre compatible perltk et tk :
    Tk 8.2 implémente UTF8 et unicode.
    Correction de plusieurs bugs sur l'appel de l'antirec (essentiellement
    situés dans Track.c).
    
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 16 Nov 2000 16:27:20 +0100

zinc-tk (3.1.20) unstable; urgency=low

  * Début d'ajout du rendu local. Modif de l'appel
    de l'antirec (il était appelé trop fréquement).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 13 Nov 2000 11:23:18 +0100

zinc-tk (3.1.19) unstable; urgency=low

  * Plus de doc.

  * Ajout de deux attributs à l'item Track afin de permettre une colorisation
    différenciée des positions passée et de la position courante.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 27 Sep 2000 10:58:01 +0200

zinc-tk (3.1.18) unstable; urgency=low

  * Correction de bugs: fuite de mémoire, segmentation au démarrage
    alors que le pointeur est dans la fenêtre.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 29 Jun 2000 14:55:44 +0200

zinc-tk (3.1.17) unstable; urgency=low

  * MODIFICATIONS INCOMPATIBLES: find atpoint est remplacée par
    find closest qui a la même sémantique que le find closest du
    canvas. LEs parties privées (connexions, vecteurs vitesse, etc)
    ne sont plus spécifiée par des nombres négatifs mais par des
    symboles (connection, position, speedvector, leader).

  * Tous les bindings associés à un item sont libérés lors de la
    destruction de l'item y compris ceux associés aux champs et
    aux parties privées.

  * La nouvelle commande verticeat retourne le sommet d'un curve ou
    bezier le plus près d'un point donné.

  * Le système de tags à été entièrement revu et s'appuie maintenant
    sur un seul jeuy de fonctions (plus de table de tag). Les items sont
    désormais toujours énumérés par ordre de priorité d'affichage.
    Il est désormais possible d'utiliser des connecteurs booléens là
    où un tag est attendu (&& || () ! ^ sont reconnus).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 21 Jun 2000 13:07:11 +0200

zinc-tk (3.1.16) unstable; urgency=low

  * Passage en Tcl_Objs.

  * La compilation de GPC est optionnelle et la
    commande contour n'est oérationnelle que si
    GPC est inclu.

  * Ajout du copyright de GPC dans le fichier copyright.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon,  5 Jun 2000 13:56:59 +0200

zinc-tk (3.1.15) unstable; urgency=low

  * Ajout de l'item Window

  * Ajout du focus, de la selection et des commandes et
    méthodes nécessaires à la saisie de texte.

  * Ajout d'une spec de dimensionnement de field permettant
    de specifier toute la hauteur et/ou toute la largeur
    du label.
    
  * Corrections de bugs sur Curve, Coords, Recherche de
    tags, etc.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 26 May 2000 10:41:38 +0200

zinc-tk (3.1.14) unstable; urgency=low

  * Ajout des polygones multi-contours (fonction contour),
    de l'item Bezier, des fonctions fit et smooth (Bezier).
  * Correction d'un bug sur l'antirec interdisant l'antirec
    ailleurs que dans le top group.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 11 May 2000 16:09:30 +0200

zinc-tk (3.1.13) unstable; urgency=low

  * Fix de bugs. Réalisation des dégradés. Clipping par un arc.
    find withtag ne sort plus en erreur si le tag/id n'est pas
    trouvé

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 23 Mar 2000 15:27:32 +0100

zinc-tk (3.1.12) unstable; urgency=low

  * Fix de bugs et du paquetage. Amélioration des reliefs.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue,  7 Mar 2000 16:00:09 +0100

zinc-tk (3.1.11) unstable; urgency=low

  * 

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 25 Feb 2000 11:19:53 +0100

zinc-tk (3.1.10) unstable; urgency=low

  * Modifications pour une meilleure configuration de la compil
    et du test en Perl.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  4 Feb 2000 15:42:11 +0100

zinc-tk (3.1.9) unstable; urgency=low

  * Passage du nom radar au nom zinc.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 31 Jan 2000 14:27:56 +0100

xradar3-tk (3.1.8) unstable; urgency=low

  * Fin de réalisation de ToArea pour Curve.
  * Mise à dispo de l'item Arc complet (sauf relief).

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 26 Jan 2000 14:39:05 +0100

xradar3-tk (3.1.7) unstable; urgency=low

  * Ajout des commandes clone, group, monitor,
  * extension de fonctionalité de coords,
  * changement de nom de multipoint en curve,
  * amélioration des commandes find et addtag,
  * gestion des dégradés/couleurs en interne,
  * Gestion des flêches dans track et curve.
  * Gestion des bouts de lignes et des joints dans
  curve.
  * curve permet d'interpreter ses points comme des
  controles de Bezier (en plus de la méthode smooth).
  * Correction de bugs nombreuses.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 13 Jan 2000 11:12:35 +0100

xradar3-tk (3.1.6) unstable; urgency=low

  * Correction dans debian pour assurer la mise en paquet suite à
  l'ajout de la bib dynamique ptkradar et om.
  * Correction de bugs, ajout de la commande chggroup.
  * Les reliefs ne sont plus fonctionnels.
  
 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu, 16 Dec 1999 11:30:43 +0100

xradar3-tk (3.1.5) unstable; urgency=low

  * Ajout du clip, du tuilage. Séparation de l'antirec dans une lib.
  Mise à jour Perl, génération possible d'une bib debug pour perl.
  Génération d'une bib dynamique pour perl. Correction de bug.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu,  9 Dec 1999 14:28:44 +0100

xradar3-tk (3.1.4) unstable; urgency=low

  * Remplacement de l'algo d'antirec par l'ancienne version de LAOM
    qui peut être distribuée sous LGPL. Corrections de bugs en particulier
    autour des transformations et du label format. Mise à jour partielle
    de la doc, etc. Suppression des phidiasseries.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu,  2 Dec 1999 15:47:18 +0100

xradar3-tk (3.1.3) unstable; urgency=low

  * Grosses modifs autour des étiquettes, labelformats, guideurs
    et ancres/attachements.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 29 Nov 1999 11:36:23 +0100

xradar3-tk (3.1.2) unstable; urgency=low

  * Ajout de l'item Rectangle. Correction de problèmes de binding.
    et plein d'autres choses.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu,  4 Nov 1999 16:51:06 +0100

xradar3-tk (3.1.1) unstable; urgency=low

  * Première version de la branche instable 3.1. Comporte l'ajout des
    transformations et des groupes et les items Icon et Text.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 29 Oct 1999 17:14:20 +0200

xradar3-tk (3.0.12) unstable; urgency=low

  * Quatrième version distribuée. Correction d'un bug bloquant sur itemcget
    dans l'incarnation perl. Début de passage en RadarBBox.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  4 Jun 1999 13:30:02 +0200

xradar3-tk (3.0.11) unstable; urgency=low

  * Troisieme version distribuée. La XToolkit n'existe plus. Le paquetage
    de base est désormais xradar3-tk. Corrections de bugs dans le widget.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri,  4 Jun 1999 13:30:02 +0200

xradar (3.0.10) unstable; urgency=low

  * Seconde version distribuée. Le schema de nommage debian incorpore
    desormais le patch level en troisieme partie. De plus la numérotation
    est celle d'un paquetage debian natif.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 21 May 1999 13:20:02 +0200

xradar (3.0-2) unstable; urgency=low

  * Premiere version distribuée. Elle correspond à la ALPHA_10.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 21 May 1999 11:20:02 +0200

xradar (3.0-1) unstable; urgency=low

  * Suppression de la dependance  xbase. Cration des paquetages xradar-tk et
    xradar-perl.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Fri, 28 May 1999 14:26:02 +0200

xradar (2.5-3) unstable; urgency=low

  * Ajout des dépendances et du soname sur la bibliothèque dynamique.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed,  9 Dec 1998 11:05:27 +0100

xradar (2.5-2) unstable; urgency=low

  * Eclatement en trois paquetages. Un pour le runtime, un pour
    le développement et un pour les fontes.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon, 24 Aug 1998 13:40:50 +0200

xradar (2.5-1) unstable; urgency=low

  * Passage en xradar 2.5.0 (beta de la 3.0)
  * Installation sous /usr/X11R6

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Mon,  4 May 1998 15:29:50 +0200

xradar (2.4-3) unstable; urgency=low

  * Separation de la fonte curseur des autres fontes. Elle n'est plus
    fabriquée automatiquement et elle n'est plus installée.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Thu,  2 Apr 1998 10:13:50 +0200

xradar (2.4-2) unstable; urgency=low

  * Ajout des fontes phidias.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Tue, 10 Mar 1998 11:04:38 +0100

xradar (2.4-1) unstable; urgency=low

  * Initial Release.

 -- Patrick Lecoanet <lecoanet@ath.cena.fr>  Wed, 25 Feb 1998 14:11:43 +0100


Added jni/tkzinc/debian/control.













































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Source: zinc-tk
Section: devel
Priority: extra
Maintainer: Patrick Lecoanet <lecoanet@ath.cena.fr>
Build-Depends: xlibs-dev, libgl1-mesa-dev | xlibmesa-dev, tk8.4-dev, tcl8.4-dev, perl-base, python (>= 2.1), python-dev, debhelper (>> 3.0.0), tetex-extra (>= 1.0.2+20011202-2), gcc(>= 2.95.4-14), perl (>= 5.6.1-8.2), tex4ht, perl-tk (>= 800.024)
Standards-Version: 2.3.0.0

Package: zinc-tk
Architecture: i386
Depends: tk8.4 (>= 8.4.3)
Conflicts: xradar3-tk
Description: The Tk zinc widget.
 Tkzinc is a canvas like widget for the Tk toolkit. Its has been
 designed to provide a structured organization of its graphical
 components. It provides also advanced geometrical and graphical
 capabilities such as geometric construction (boolean ops),
 transformations, non rectangular clipping gradient fills, smart
 reliefs, etc.
 For more information, http://www.tkzinc.org

Package: zinc-perl
Architecture: i386
Depends: perl-tk (>= 800.024)
Conflicts: xradar3-perl
Description: perl-tk variant of the Tk zinc widget.
 perl-tk variant of the Tk zinc widget.

Package: zinc-python
Architecture: all
Depends: python, python-imaging, python-imaging-tk, python-tk, zinc-tk (= ${Source-Version})
Conflicts: python-xradar3
Description:  python interface to the Tk zinc widget.
 python interface to the Tk zinc widget.

Package: zinc-doc
Architecture: all
Description: Documentation files for the Tk zinc widget
 Documentation files for the Tk zinc widget in html and pdf formats

Added jni/tkzinc/debian/copyright.









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
This package was debianized by Patrick Lecoanet lecoanet@ath.cena.fr on
Wed, 25 Feb 1998 14:11:43 +0100.

Copyright:

  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

Added jni/tkzinc/debian/rules.































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/make -f
# Sample debian/rules that uses debhelper. 
# This file is public domain software, originally written by Joey Hess.
#
# This version is for a hypothetical package that builds an
# architecture-dependant package, as well as an architecture-independent
# package.

# Uncomment this to turn on verbose mode. 
#export DH_VERBOSE=1

TMP=`pwd`/debian/tmp
TMP_DOC=`pwd`/debian/zinc-doc
TMP_PERL=`pwd`/debian/zinc-perl
TMP_PYTHON=$(shell echo `pwd`/debian/zinc-python)


DEFAULT_VERSION_PYTHON=$(shell echo `dpkg -p python| grep -e "^Version:" |cut -d" " -f2|cut -d"." -f1-2`)

build: build-stamp

build-stamp:
	dh_testdir

	touch build-stamp

clean:
	dh_testdir
	dh_testroot
	-rm -f build-stamp 
	-rm -f config.cache
	-$(MAKE) clean

	-cd Python && python setup.py clean
	dh_clean

install: build
	dh_testdir
	dh_testroot
	dh_clean -k
	dh_installdirs

#
# Configuring/compiling/installing for Tcl.
	./configure --prefix=/usr --exec_prefix=/usr --enable-gl --with-tcl=/usr/lib/tcl8.4 --with-tk=/usr/lib/tk8.4 --x-libraries=/usr/X11R6/lib
	make
#	make install prefix=$(TMP)/usr
	make install DESTDIR=$(TMP)
#
# Making/installing the documentation
	make pdf html
	-mkdir -p $(TMP_DOC)/usr/share/doc/zinc-doc/refman
	-install -m644 doc/refman.pdf $(TMP_DOC)/usr/share/doc/zinc-doc
	-install -m644 doc/*.html doc/*.css doc/*.png $(TMP_DOC)/usr/share/doc/zinc-doc/refman

#
# Configuring/compiling/installing for Python.
	-cd Python && python setup.py install --prefix=$(TMP_PYTHON)/usr

#
# Configuring/compiling/installing for perl/Tk.
	-mkdir -p $(TMP_PERL)
	(cd Perl; ./export2cpan)
	(cd export2cpan/tk-zinc; perl Makefile.PL; make; make pure_install prefix=`pwd`/../../debian/zinc-perl/usr INSTALLDIRS=vendor PREFIX=`pwd`/../../debian/zinc-perl/usr)

	find $(TMP_PERL)/usr/lib/perl5  -type f -name .packlist | xargs rm -f

# Build architecture-independent files here.
binary-indep: build install
	dh_testdir -i
	dh_testroot -i
	dh_installchangelogs -i
	dh_installdocs -i BUGS
	dh_installexamples -i
#	dh_install --sourcedir=debian/tmp
#	dh_installmenu -i
#	dh_installdebconf -i
#	dh_installlogrotate -i
#	dh_installemacsen -i
#	dh_installpam -i
#	dh_installmime -i
#	dh_installinit -i
#	dh_installcron -i
#	dh_installinfo -i
#	dh_undocumented -i
	dh_installman -i
	dh_link -i
	dh_compress -i --exclude=.pdf --exclude=.py
	dh_fixperms -i
	dh_installdeb -i
#	dh_perl -i
	dh_gencontrol -i
	dh_md5sums -i
	dh_builddeb -i

# Build architecture-dependent files here.
binary-arch: build install
	dh_testdir -a
	dh_testroot -a
	dh_installchangelogs -a
	dh_installdocs -a
	dh_installexamples -a
	dh_installmenu -a
#	dh_installdebconf -a
#	dh_installlogrotate -a
#	dh_installemacsen -a
#	dh_installpam -a
#	dh_installmime -a
#	dh_installinit -a
#	dh_installcron -a
#	dh_installinfo -a
#	dh_undocumented -a
	dh_installman -a
	dh_strip -a
	dh_link -a
	dh_compress -a --exclude=.pdf
	dh_fixperms -a
#	dh_makeshlibs -a
	dh_installdeb -a
#	dh_perl -a
	dh_shlibdeps -a
	dh_gencontrol -a
	dh_md5sums -a
	dh_builddeb -a

binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install

Added jni/tkzinc/debian/zinc-python.postinst.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#! /bin/bash -e
#
# Debian postinst script for Python hierarchical modules
# Written by Gregor Hoffleit <flight@debian.org>
#

NAME=zinc-python
DEFAULT_VERSION_PYTHON=`dpkg -p python| grep -e "^Version:" |cut -d" " -f2|cut -d"." -f1-2`
DIRLIST="/usr/lib/python${DEFAULT_VERSION_PYTHON}/site-packages"

case "$1" in
    configure|abort-upgrade|abort-remove|abort-deconfigure)
        for i in $DIRLIST ; do
             python -O /usr/lib/python${DEFAULT_VERSION_PYTHON}/compileall.py -q $i
             python /usr/lib/python${DEFAULT_VERSION_PYTHON}/compileall.py -q $i
        done
    ;;

    *)
        echo "postinst called with unknown argument \`$1'" >&2
        exit 1
    ;;
esac

Added jni/tkzinc/debian/zinc-python.prerm.























>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
#! /bin/bash -e
#
# Debian prerm script for Python hierarchical modules
# Written by Gregor Hoffleit <flight@debian.org>
#

NAME=zinc-python

dpkg --listfiles $NAME |
	awk '$0~/\.py$/ {print $0"c\n" $0"o"}' |
	xargs rm -f >&2

Added jni/tkzinc/demos/allOptions.tcl.

















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval allOptions {
    variable w .allOptions
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc All Option Demonstration"
    wm iconname $w "All options"

    frame $w.buttons
    pack $w.buttons -side bottom -fill x -pady 2m
    ttk::button $w.buttons.dismiss -text Dismiss -command "destroy $w"
    ttk::button $w.buttons.code -text "See Code" -command "showCode $w"
    pack $w.buttons.dismiss $w.buttons.code -side left -expand 1

    # The explanation displayed when running this demo
    label $w.label -justify left -text {Click on one of the following
	buttons to get a list of Item
	attributes (or zinc options)
	with their types.}

    pack $w.label -padx 10 -pady 10

    # Creating the zinc widget
    zinc $w.zinc -width 1 -height 1 -borderwidth 0 -relief sunken
    pack $w.zinc

    # Creating an instance of every item type

    variable itemTypes
    # These Items have fields! So the number of fields must be given at creation time
    foreach type {tabular track waypoint} {
	set itemTypes($type)  [$w.zinc add $type 1 0]
    }

    # These items needs no specific initial values
    foreach type {group icon map reticle text window} {
	set itemTypes($type) [$w.zinc add $type 1]
    }

    # These items needs some coordinates at creation time
    # However curves usually needs more than 2 points.
    foreach type {arc curve rectangle} {
	set itemTypes($type) [$w.zinc add $type 1 {0 0 1 1}]
    }

    # Triangles item needs at least 3 points for the coordinates 
    foreach type {triangles} {
	set itemTypes($type) [$w.zinc add $type 1 {0 0 1 1 2 2}]
    }

    proc showAllOptions { w type} {
	variable itemTypes

	if [winfo exists .tl] {destroy .tl}
	toplevel .tl
	if {[string compare $type zinc]==0} {
	    set options  [$w.zinc configure]
	    set typeopt optionClass
	    set readopt defaultValue
	    set readoff 3
	    set  title  {All options of zinc widget}
	} else {
	    set options  [$w.zinc itemconfigure $itemTypes($type)];
	    set title  "All attributes of an $type item"
	    set typeopt Type
	    set readopt ReadOnly
	    set readoff 2
	}

	wm title .tl $title

	frame .tl.f1
	set bgcolor ivory

	label .tl.f1.opt -text Option -background $bgcolor -relief ridge -width 20
	label .tl.f1.typ -text $typeopt -background $bgcolor -relief ridge -width 20
	label .tl.f1.rd -text $readopt  -background $bgcolor -relief ridge -width 21

	pack .tl.f1.opt .tl.f1.typ  .tl.f1.rd -side left
	set nbelem [llength $options]
	frame .tl.f2
	listbox .tl.f2.l1 -width 20 -height $nbelem
	listbox .tl.f2.l2 -width 20 -height $nbelem
	listbox .tl.f2.l3 -width 20 -height $nbelem
	pack .tl.f2.l1 .tl.f2.l2 .tl.f2.l3 -side left
	pack .tl.f1 .tl.f2 -side top -anchor nw

	# Remplissage des list box
	foreach elem $options {
	    .tl.f2.l1 insert end [lindex $elem 0]
	    .tl.f2.l2 insert end [lindex $elem 1]
	    .tl.f2.l3 insert end [lindex $elem $readoff]
	}
    }

    pack [frame $w.col]

    variable width 0
    foreach type [lsort [array names itemTypes]] {
	if {[string length $type] > $width} {
	    set width  [string length $type]
	}
    }

    foreach type [lsort [array names itemTypes]] {
	ttk::button $w.col.$type -text "$type" -width $width -command "::allOptions::showAllOptions $w $type"
	pack $w.col.$type -pady 4

    }

    ttk::button $w.col.b -text "zinc widget options" -command "::allOptions::showAllOptions $w zinc"
    pack $w.col.b -pady 4
}

Added jni/tkzinc/demos/atomicGroups.tcl.









































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval atomicGroups {
    variable w .atomicGroups
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Atomicity Demonstration"
    wm iconname $w "Atomic"

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 6 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 6 -column 1 -pady 10

    grid [zinc $w.zinc -width 500 -height 350 -font $defaultfont -borderwidth 0] \
	-row 0 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 0 -weight 2

    variable groupsGroupAtomicity  0
    variable redGroupAtomicity  0
    variable greenGroupAtomicity  0

    $w.zinc add "text"  1 -font $defaultfont -text  "- There are 3 groups: a red group containing 2 redish objects\na green group containing 2 greenish objects,\nand groupsGroup containing both previous groups.\n- You can make some groups atomic or not by depressing \nthe toggle buttons at the bottom of the window\n- Try and then click on some items to observe that callbacks\n are then different: they modify either the item, or 2 items of\n a group or all items" -anchor  "nw" -position  "10 10"

    ############### creating the top group with its bindings ###############################
    variable groupsGroup [$w.zinc add group 1 -visible 1 -atomic $groupsGroupAtomicity -tags groupsGroup]

    # the following callbacks will be called only if "groupsGroup" IS atomic
    $w.zinc bind $groupsGroup <1> ::atomicGroups::modifyBitmapBg
    $w.zinc bind $groupsGroup <ButtonRelease-1> ::atomicGroups::modifyBitmapBg

    ############### creating the redGroup, with its binding and its content ################
    # the redGroup may be atomic, that is is makes all children as a single object
    # and sensitive to redGroup callbacks
    variable redGroup [$w.zinc add group $groupsGroup -visible 1 -atomic $redGroupAtomicity -sensitive 1 -tags redGroup]

    # the following callbacks will be called only if "groupsGroup" IS NOT-atomic
    # and if "redGroup" IS atomic
    $w.zinc bind $redGroup <1> "::atomicGroups::modifyItemLines $redGroup"
    $w.zinc bind $redGroup <ButtonRelease-1> "::atomicGroups::modifyItemLines $redGroup" 


    variable rc [$w.zinc add arc $redGroup {100 200 140 240} -filled 1 -fillcolor red2 -linewidth 3 -linecolor white -tags redCircle]
    variable rr [$w.zinc add rectangle $redGroup {300 200 400 250} -filled 1 -fillcolor red2 -linewidth 3 -linecolor white -tags redRectangle]

    # the following callbacks will be called only if "groupsGroup" IS NOT atomic
    # and if "redGroup" IS NOT atomic
    $w.zinc bind $rc  <1> ::atomicGroups::toggleColor
    $w.zinc bind $rc  <ButtonRelease-1> ::atomicGroups::toggleColor
    $w.zinc bind $rr  <1> ::atomicGroups::toggleColor
    $w.zinc bind $rr  <ButtonRelease-1> ::atomicGroups::toggleColor

    ############### creating the greenGroup, with its binding and its content ################
    # the greenGroup may be atomic, that is is makes all children as a single object
    # and sensitive to greenGroup callbacks
    variable greenGroup  [$w.zinc add group $groupsGroup -visible 1 -atomic $greenGroupAtomicity -sensitive 1 -tags greenGroup]

    # the following callbacks will be called only if "groupsGroup" IS NOT atomic
    # and if "greenGroup" IS atomic
    $w.zinc bind $greenGroup <1> "::atomicGroups::modifyItemLines $greenGroup"
    $w.zinc bind $greenGroup <ButtonRelease-1> "::atomicGroups::modifyItemLines $greenGroup"

    variable gc [$w.zinc add arc $greenGroup {100 270  140 310} -filled 1 -fillcolor green2 -linewidth 3 -linecolor white -tags greenCircle]

    variable gr [$w.zinc add rectangle $greenGroup {300 270   400 320} -filled 1 -fillcolor green2 -linewidth 3 -linecolor white -tags greenRectangle]
    # the following callbacks will be called only if "groupsGroup" IS NOT atomic
    # and if "greenGroup" IS NOT atomic
    $w.zinc bind $gc  <1>  ::atomicGroups::toggleColor
    $w.zinc bind $gc  <ButtonRelease-1>  ::atomicGroups::toggleColor
    $w.zinc bind $gr  <1>  ::atomicGroups::toggleColor
    $w.zinc bind $gr  <ButtonRelease-1>  ::atomicGroups::toggleColor

    variable currentBg  ""
    ###################### groupsGroup callback ##############

    proc modifyBitmapBg {} {
	variable currentBg		      
	variable rc
	variable rr
	variable gc
	variable gr
	variable w
	if {$currentBg=="AlphaStipple2"} {
	    set currentBg {}
	} else {
	    set currentBg AlphaStipple2
	}
	foreach item "$rc  $rr  $gc  $gr" {
	    $w.zinc itemconfigure $item -fillpattern $currentBg
	}
    }

    #################### red/greenGroup callback ##############
    proc modifyItemLines {gr} {
	variable w
	
	set children [$w.zinc find withtag ".$gr*"] 
	# we are using a pathtag (still undocumented feature of 3.2.6) to get items of an atomic group!
	# we could also temporary modify the groups (make it un-atomic) to get its child

	set currentLineWidth [$w.zinc itemcget [lindex $children 0] -linewidth]

	if {$currentLineWidth == 3} {
	    set currentLineWidth 0
	} else {
	    set currentLineWidth 3
	}
	foreach item $children {
	    $w.zinc itemconfigure $item  -linewidth  $currentLineWidth
	}
	
    }

    ##################### items callback ######################
    proc toggleColor {} {
	variable w
	set item  [$w.zinc find withtag current]
	set fillcolor  [$w.zinc itemcget $item  -fillcolor]
	regexp {([a-z]+)(\d)} $fillcolor "" color num

	#my ($color $num) = $fillcolor =~ /("a-z"+)(\d)/ 
	if {$num == 2} {    
	    set val 1
	    set num 4
	} else {
	    set num 2
	}
	$w.zinc itemconfigure $item -fillcolor "$color$num"
    }

    proc  atomicOrNot {gr} {
	variable w
	set val [lindex [$w.zinc itemconfigure $gr  -atomic] 4]
	if {$val==1} {
	    $w.zinc itemconfigure $gr  -atomic 0
	} else {
	    $w.zinc itemconfigure $gr  -atomic 1
	}
	updateFoundItems
    }

    ###################### toggle buttons at the bottom ####

    grid [ttk::checkbutton $w.cb -text "groupsGroup is atomic" \
	-variable ::atomicGroups::groupsGroupAtomicity \
	-command "::atomicGroups::atomicOrNot  $groupsGroup"] -row 1 -column 0 -sticky w
    grid [ttk::checkbutton $w.cb2 -text "red group is atomic" \
	-variable ::atomicGroups::redGroupAtomicity \
	-command "::atomicGroups::atomicOrNot $redGroup"] -row 2 -column 0 -sticky w
    grid [ttk::checkbutton $w.cb3 -text "green group is atomic" \
	-variable  ::atomicGroups::greenGroupAtomicity \
	-command  "::atomicGroups::atomicOrNot $greenGroup"] -row 3 -column 0 -sticky w

    grid [label $w.lb2 -text "Following command '$w.zinc find overlapping 0 200 500 400', returns:"] \
	-row 4 -column 0 -columnspan 2 -pady 10
    grid [label $w.label -text ""] \
	-row 5 -column 0 -columnspan 2

    ##### to update the list of enclosed items
    proc updateFoundItems {} {
	variable w
	set found  [$w.zinc find overlapping 0 200 500 400]
	set str  ""
	foreach item $found {
	    set tags [$w.zinc itemcget $item  -tags]
	    set str  "$str $tags"
	}
	$w.label configure -text  $str 
    }

    # to init the list of enclosed items
    updateFoundItems
}

Added jni/tkzinc/demos/clipping.tcl.





































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval clippingDemo {
    variable w .clipping
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Clipping Demonstration"
    wm iconname $w "Clipping"

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    grid [zinc $w.zinc -width 700 -height 600 -font $defaultfont \
              -borderwidth 3 \
	      -relief sunken] -row 0 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 0 -weight 2

    variable displayClippingItemBackground   0
    variable clip   1

    $w.zinc add text 1 -font $defaultfont -text "You can drag and drop the objects.\nThere are two groups of objects a tan group and a blue group\nTry to move them and discover the clipping area which is a curve.\nwith two contours" -anchor nw -position {10 10}

    variable clippedGroup [$w.zinc add group 1 -visible 1]

    variable clippingItem  [$w.zinc add curve $clippedGroup {10 100 690 100 690 590 520 350 350 590 180 350 10 590} -closed 1 -priority 1 -fillcolor tan2 -linewidth 0 -filled $displayClippingItemBackground]
    $w.zinc contour $clippingItem add +1 {200 200 500 200 500 250 200 250}

    ############### creating the tanGroup objects ################
    # the tanGroup is atomic  that is is makes all children as a single object
    # and sensitive to tanGroup callbacks
    variable tanGroup [$w.zinc add group $clippedGroup -visible 1 -atomic 1 -sensitive 1]

    $w.zinc add arc $tanGroup {200 220 280 300} -filled 1 -linewidth 1 -startangle 45 -extent 270 -pieslice 1 -closed 1 -fillcolor tan
    
    $w.zinc add curve $tanGroup {400 400 440 450 400 500 500 500 460 450 500 400} -filled 1 -fillcolor tan -linecolor tan

    ############### creating the blueGroup objects ################
    # the blueGroup is atomic too  that is is makes all children as a single object
    # and sensitive to blueGroup callbacks
    variable blueGroup   [$w.zinc add group $clippedGroup -visible 1 -atomic 1 -sensitive 1]

    $w.zinc add rectangle $blueGroup {570 180   470 280} -filled 1 -linewidth 1 -fillcolor blue2

    $w.zinc add curve $blueGroup {200 400 200 500 300 500 300 400 300 300} -filled 1 -fillcolor blue -linewidth 0

    $w.zinc itemconfigure $clippedGroup -clip  $clippingItem

    ###################### drag and drop callbacks ############
    # for both tanGroup and blueGroup

    $w.zinc bind $tanGroup <1> "::clippingDemo::itemStartDrag $tanGroup %x %y" 
    $w.zinc bind $tanGroup <B1-Motion> "::clippingDemo::itemDrag $tanGroup %x %y"
    $w.zinc bind $blueGroup <1> "::clippingDemo::itemStartDrag $blueGroup %x %y" 
    $w.zinc bind $blueGroup <B1-Motion> "::clippingDemo::itemDrag $blueGroup %x %y"

    # callback for starting a drag
    variable xOrig ""
    variable yOrig ""

    proc itemStartDrag {item x y} {
	variable xOrig
	variable yOrig
	set xOrig $x
	set yOrig $y
    }

    # Callback for moving an item
    proc itemDrag {item x y} {
	variable xOrig
	variable yOrig
	variable w
	$w.zinc translate $item  [expr $x-$xOrig] [expr $y-$yOrig];
	set xOrig  $x;
	set yOrig  $y;
    }

    ###################### toggle buttons at the bottom #######
    grid [frame $w.row] -row 1 -column 0 -columnspan 2
    ttk::checkbutton $w.row.show -text "Show clipping item" \
	-variable ::clippingDemo::displayClippingItemBackground \
	-command "::clippingDemo::displayClippingArea"
    ttk::checkbutton $w.row.clip -text Clip -variable ::clippingDemo::clip \
	-command "::clippingDemo::clipCommand"
    pack $w.row.show $w.row.clip -side left

    proc displayClippingArea {} {
	variable clippingItem
	variable w
	variable displayClippingItemBackground
	$w.zinc itemconfigure $clippingItem -filled  $displayClippingItemBackground
    }

    proc clipCommand {} {
	variable clip
	variable clippedGroup
	variable clippingItem
	variable w

	if {$clip} {
	    $w.zinc itemconfigure $clippedGroup -clip  $clippingItem
	} else {
	    $w.zinc itemconfigure $clippedGroup -clip ""
	}
    }
}

Added jni/tkzinc/demos/colorCircular.tcl.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval colorCircular {
    variable w .colorCircular
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Color Circular Demonstration"
    wm iconname $w "Color Circular"

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    variable defaultfont {Helvetica -11}

    grid [zinc $w.zinc -width 700 -height 600 -borderwidth 3 \
              -relief sunken -render 1 -font $defaultfont] \
	-row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2
 
    $w.zinc add rectangle 1 {10 10 80 80} -fillcolor {=radial 50 50|red|blue} -filled 1
    $w.zinc add text 1 -font $defaultfont -text {Radial variation from non-transparent red to non-transparent blue in a square.
The gradient starts in the lower right corner.} -anchor nw -position {120 20}

    $w.zinc add arc 1 {10 110 90 190} -fillcolor {=radial 0 25|red;40|blue;40} -filled 1

    $w.zinc add text 1 -font $defaultfont -text {Radial variation from 40% transparent red to 40% transparent blue in a disc.
The gradient starts mid way between the center and the bottom.} \
	-anchor nw -position {120 120}

    $w.zinc add arc 1 {10 210 90 290} -fillcolor {=radial 0 0|red;40|green;40 50|blue;40} -filled 1

    $w.zinc add text 1 -font $defaultfont -text {A variation from 40% transparent red to 40% transparent blue
through 40% green in the middle of the disc. The gradient is centered.} \
	-anchor nw -position {120 220}

    $w.zinc add text 1 -font $defaultfont -anchor w -position {20 320} \
	-text {Two overlapping items filled by a transparent radial gradient on a white background.
On the right three gradient filled ovals, note the warped gradients following the ovals.}

    $w.zinc add rectangle 1 {10 340 690 590} -fillcolor white -filled  1 

    $w.zinc add rectangle 1 {20 365 220 565} -fillcolor {=radial 0 0|red;40|green;40 50|blue;40} -filled 1

    $w.zinc add arc 1 {150 365 350 565} -fillcolor {=radial 0 0|yellow;40|black;40 50|cyan;40} -filled 1

    $w.zinc add arc 1 {280 365 480 565} -fillcolor {=radial 0 0|black;100|black;100 20|mistyrose;40} -filled 1 -linewidth 0

    variable warc [$w.zinc add arc 1 {-50 -50 50 50} \
		       -fillcolor {=radial -10 16|black;80|blue;20 90 100} -filled 1]
    $w.zinc scale $warc 1.5 1
    $w.zinc translate $warc 500 432

    variable warc [$w.zinc add arc 1 {-50 -50 50 50} \
		       -fillcolor {=radial 0 20|black;70|green;20} -filled 1]
    $w.zinc scale $warc 1 1.5
    $w.zinc translate $warc 630 432
}

Added jni/tkzinc/demos/colorX.tcl.



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval colorX {
    variable w .colorX 
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Color-x Demonstration"
    wm iconname $w "Color X"

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    variable defaultfont {Helvetica -11}

    grid [zinc  $w.zinc -width 700 -height 600 -borderwidth 3 \
              -relief sunken -render 1 -font $defaultfont] \
	-row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2
 
    $w.zinc add rectangle 1 {10 10 690 100} -fillcolor {red|blue} -filled 1

    $w.zinc add text 1 -font $defaultfont  -anchor nw -position {20 20} \
	-text "A variation from non transparent red to non transparent blue.\n"

    $w.zinc add rectangle 1 {10 110 690 200} -fillcolor {red;40|blue;40} -filled 1

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 120} \
	-text "A variation from 40%transparent red to 40% transparent blue."

    $w.zinc add rectangle 1 {10 210 690 300} -fillcolor {red;40|green;40 50|blue;40} -filled 1

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 220} \
	-text "A variation from 40%transparent red to 40% transparent blue.\nthrough a 40%green on the middle"

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 320} \
	-text "Two overlaping transparently colored rectangles on a white background"

    $w.zinc add rectangle 1 {10 340 690 590} -fillcolor white -filled 1
    $w.zinc add rectangle 1 {200 350 500 580} -fillcolor {red;40|green;40 50|blue;40} -filled 1

    $w.zinc add rectangle 1 {10 400 690 500} -fillcolor {yellow;40|black;40 50|cyan;40} -filled 1
}

Added jni/tkzinc/demos/colorY.tcl.



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval colorY {
    variable w .colorY
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Color-y Demonstration"
    wm iconname $w "Color y"

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    variable defaultfont {Helvetica -11}

    grid [zinc $w.zinc -width 700 -height 600 -borderwidth 3 \
        -relief sunken -render 1 -font $defaultfont] \
	-row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    $w.zinc add rectangle 1 {10 10 690 100} -fillcolor {=axial 90|red|blue} -filled 1

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 20} \
	-text "A variation from non transparent red to non transparent blue.\n"

    $w.zinc add rectangle 1 {10 110 690 200} -fillcolor {=axial 90|red;40|blue;40} -filled 1

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 120} \
	-text "A variation from 40%transparent red to 40% transparent blue."

    $w.zinc add rectangle 1 {10 210 690 300} -fillcolor {=axial 90|red;40|green;40 50|blue;40} -filled 1

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 220} \
	-text "A variation from 40%transparent red to 40% transparent blue.\nthrough a 40%green on the middle"

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 320} \
	-text "Two overlaping transparently colored rectangles on a white background"

    $w.zinc add rectangle 1 {10 340 690 590} -fillcolor white -filled  1
    $w.zinc add rectangle 1 {200 350 500 580} -fillcolor {=axial 90|red;40|green;40 50|blue;40} -filled 1

    $w.zinc add rectangle 1 {10 400 690 500} -fillcolor {=axial 90|yellow;40|black;40 50|cyan;40} -filled 1
}

Added jni/tkzinc/demos/contours.tcl.









































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval contoursDemo {
    variable w .contours
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Curve contours Demonstration"
    wm iconname $w Curve

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    # The explanation displayed when running this demo
    grid [text  $w.text -relief sunken -borderwidth 2 -setgrid true \
              -height 9 -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {All visibles items are made by combining 2 items using contours:
 - the firebrick curve1 has been holed using a addhole with a circle,
 - the lightblue curve2 has been mickey-moused by adding two circles,
 - the yellow curve3 is the union with a disjoint circle,
 - the grey curve4 is combined with 7 circles, with positive -fillrule.
The following operations are possible:
 - Mouse Button 1 for dragging objects.
 - Mouse Button 1 for dragging the black handle and
   modifying the grey curve contour.}
    $w.text configure -state disabled

    # Creating the zinc widget
    grid [zinc $w.zinc -width 600 -height 500 -borderwidth 3 \
	      -relief sunken] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    variable top 1

    # Creation of 2 items NOT visible, but used for creating visible
    # curves[1-5] with more than one contours.
    # The center of these 2 items is 200,100

    variable curve0 [$w.zinc add curve $top {
	{300 0} {400 100 c} {300 200} {200 300 c} {100 200} {0 100 c} {100 0}
    } -closed 1 -visible 0 -filled 1]
    variable cercle100  [$w.zinc add arc 1 {130 30 280 180} -visible 0]

    # cloning curve0 as curve1 and moving it
    variable  curve1 [$w.zinc clone $curve0 -visible 1 -fillcolor firebrick1]
    # adding a 'difference' contour to the curve1
    $w.zinc contour $curve1 add 1 $cercle100

    # cloning curve0 as curve2 and moving it
    # creating a curve without contour to control contour clockwise/counterclockwise
    variable curve2 [$w.zinc add curve $top {} -closed 1 -filled 1 \
		    -fillcolor lightblue2 -fillrule positive]
    $w.zinc contour $curve2 add +1 $curve0
    $w.zinc translate $curve2 100 90

    # adding the left ear of mickey mouse!
    $w.zinc contour $curve2 add +1 $cercle100
    $w.zinc translate $curve2 -200 0

    # adding the right ear of mickey mouse!
    $w.zinc contour $curve2 add +1 $cercle100

    # ... translate to make it more visible
    $w.zinc translate $curve2 320 20

    # cloning curve0 as curve3 and moving it
    variable curve3  [$w.zinc clone $curve0 -visible 1 -fillcolor yellow3]
    $w.zinc translate $curve3 0 290

    # adding an  nion' contour to the curve3
    $w.zinc contour $curve3 add +1 $cercle100
    # ... translate to make it more visible
    $w.zinc translate $curve3 -130 0

    # cloning curve0 as curve4 and moving it slightly
    variable curve4 [$w.zinc clone $curve0 -visible 1 -fillcolor grey50 \
		    -tags grouped -fillrule positive]
    # the tag "grouped" is used for both curve4 and
    # a handle (see just below)
    # It is used for translating both easily

    variable index  2; ## index of the vertex associated to the handle
    variable coord  [$w.zinc coords $curve4 0 $index]
    variable x [lindex $coord 0]
    variable y [lindex $coord 1]
    variable handle [$w.zinc add rectangle $top "[expr $x-5] [expr $y-5] [expr $x+5] [expr $y+5]" \
		    -fillcolor black -filled 1 -tags {grouped}]

    # adding a 'difference' contour to the curve4
    $w.zinc contour $curve4 add +1 $cercle100
    $w.zinc translate grouped 110 0
    $w.zinc contour $curve4 add +1 $cercle100
    $w.zinc translate grouped -220 0
    $w.zinc contour $curve4 add +1 $cercle100
    $w.zinc translate grouped 10 80
    $w.zinc contour $curve4 add -1 $cercle100
    $w.zinc translate grouped 0 -10
    $w.zinc contour $curve4 add +1 $cercle100

    $w.zinc translate grouped 200 80
    $w.zinc contour $curve4  add +1 $cercle100
    $w.zinc translate grouped -350 0
    $w.zinc contour $curve4 add +1 $cercle100

    $w.zinc translate grouped 350 250
    #$zinc->lower(grouped);

    # Deleting no more usefull items: curve0 and cercle10:
    $w.zinc remove $curve0 $cercle100

    $w.zinc raise $curve1

    # adding drag and drop callback to each visible curve!
    foreach item "$curve1 $curve2 $curve3 $curve4" {
	# Some bindings for dragging the items
	$w.zinc bind $item <ButtonPress-1> "::contoursDemo::press $item motion %x %y"
	$w.zinc bind $item <ButtonRelease-1> ::contoursDemo::release
    }

    # adding drag and drop on curve4 which also moves handle
    $w.zinc bind $curve4  <ButtonPress-1> "::contoursDemo::press $curve4 motionWithHandle %x %y"
    $w.zinc bind $curve4, <ButtonRelease-1> ::contoursDemo::release

    # adding drag and drop on handle which also modify curve4
    $w.zinc bind $handle  <ButtonPress-1> "::contoursDemo::press $handle moveHandle %x %y"
    $w.zinc bind $handle  <ButtonRelease-1> ::contoursDemo::release

    # callback for starting a drag
    variable xOrig 0
    variable yOrig 0

    proc press {item action x y} {
	variable w
	variable xOrig
	variable yOrig

	set xOrig $x
	set yOrig $y
	bind $w.zinc <Motion> "::contoursDemo::$action $item %x %y"
    }

    # Callback for moving an item
    proc motion {item x y} {
	variable w
	variable xOrig
	variable yOrig

	$w.zinc translate $item [expr $x - $xOrig] [expr $y - $yOrig]
	set xOrig $x
	set yOrig $y
    }

    # Callback for moving an item and its handle
    proc motionWithHandle {item x y} {
	variable w
	variable xOrig
	variable yOrig

	set tag [lindex [$w.zinc itemcget $item -tags] 0]
	$w.zinc translate $tag  [expr $x-$xOrig] [expr $y-$yOrig]
	set xOrig $x;
	set yOrig $y;
    }

    # Callback for moving the handle and modifying curve4
    # this code is far from being generic. Only for demonstrating how we can
    # modify a contour with a unique handle!
    proc moveHandle {handle x y} {
	variable w
	variable xOrig
	variable yOrig
	variable curve4
	variable index

	$w.zinc translate $handle  [expr $x - $xOrig] [expr $y - $yOrig];

	foreach {vertxX vertxY} [$w.zinc coords $curve4 0 $index] break
	$w.zinc coords $curve4 0 $index "[expr $vertxX+($x-$xOrig)] [expr $vertxY+($y-$yOrig)]"
	set xOrig $x
	set yOrig $y
    }

    proc release {} {
	variable w

	bind $w.zinc <Motion> {}
    }
}

Added jni/tkzinc/demos/curveBezier.tcl.









































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval curveBezier {
    variable w .curveBezier
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Curve Bezier Demonstration"
    wm iconname $w Curve

    variable defaultfont {Helvetica -11}
    #variable imagePath [file join $zinc_library demos images]
    #variable texture [image create photo -file [file join $imagePath paper-grey1.gif]]
    variable splineColor \#AA0000
    variable handleColor grey70
    variable barColor grey30
    variable textColor grey20

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    grid [text $w.text -relief sunken -borderwidth 2 -setgrid true \
              -height 3 -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert 0.0 {
	6 examples of curves containing control points are displayed
	with the list of control points written just below.
	You can move the handles to modify the bezier curves
    }
    $w.text configure -state disabled

    grid [zinc $w.zinc -width 700 -height 650 -font $defaultfont -borderwidth 0 \
	      -backcolor \#898A8F] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    variable group [$w.zinc add group 1]

    $w.zinc add text $group -position {50 20} -anchor w -color $textColor \
	-text {Examples of curve items using cubic bezier control points}

    ## Please note: much of the items below could be computed
    $w.zinc add text $group -anchor w -position {25 270} -tags bezier1 -color $textColor -width 270
    $w.zinc add curve $group {100 200 100 100} -tags {line1 l1-2} \
	-linecolor $barColor -filled 0 -linewidth 2
    $w.zinc add curve $group {400 100 400 200} -tags {line1 l3-4} \
	-linecolor $barColor -filled 0 -linewidth 2
    $w.zinc add curve $group {{100 200} {100 100 c} {400 100 c} {400 200}} \
	-tags bezier1 -closed 0 -linecolor $splineColor -linewidth 5
    $w.zinc add arc $group {90 190 110 210} -tags {handle1 p1} -filled 1 \
	-fillcolor \#BBBBBB
    $w.zinc add arc $group {90 90 110 110} -tags {handle1 p2} -filled 1 \
	-linewidth 0 -fillcolor $handleColor -filled 1
    $w.zinc add arc $group {390 90 410 110} -tags {handle1 p3} -filled 1 \
	-linewidth 0 -fillcolor $handleColor -filled 1
    $w.zinc add arc $group {390 190 410 210} -tags {handle1 p4} -filled 1 \
	-fillcolor \#BBBBBB

    $w.zinc add text $group -anchor w -position {570 270} -tags bezier2 -color $textColor -width 270
    $w.zinc add curve $group {600 200 675 100} -tags {line2 l1-2} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {975 100 900 200} -tags {line2 l3-4} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {{600 200} {675 100 c} {975 100 c} {900 200}} \
	-tags bezier2 -closed 0 -linecolor $splineColor -linewidth 5
    $w.zinc add arc $group {590 190 610 210} -tags {handle2 p1} -filled 1 \
	-fillcolor $handleColor
    $w.zinc add arc $group {665 90 685 110} -tags {handle2 p2} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {965 90 985 110} -tags {handle2 p3} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {890 190 910 210} -tags {handle2 p4} -filled 1 \
	-fillcolor $handleColor

    $w.zinc add text $group -anchor w -position {25 570} -tags bezier3 -color $textColor -width 270
    $w.zinc add curve $group {100 500 25 400} -tags {line3 l1-2} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {475 400 400 500} -tags {line3 l3-4} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {{100 500} {25 400 c} {475 400 c} {400 500}} \
	-tags {bezier3} -closed 0 -linecolor $splineColor -linewidth 5
    $w.zinc add arc $group {90 490 110 510} -tags {handle3 p1} -filled 1 \
	-fillcolor $handleColor
    $w.zinc add arc $group {15 390 35 410} -tags {handle3 p2} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {465 390 485 410} -tags {handle3 p3} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {390 490 410 510} -tags {handle3 p4} -filled 1 \
	-fillcolor $handleColor

    $w.zinc add text $group -anchor w -position {570 570} -tags bezier4 -color $textColor -width 270
    $w.zinc add curve $group {600 500 600 350} -tags {line4 l1-2} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {900 650 900 500} -tags {line4 l3-4} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {{600 500} {600 350 c} {900 650 c} {900 500}} \
	-tags {bezier4} -closed 0 -linecolor $splineColor -linewidth 5
    $w.zinc add arc $group {590 490 610 510} -tags {handle4 p1} -filled 1 \
	-fillcolor $handleColor
    $w.zinc add arc $group {590 340 610 360} -tags {handle4 p2} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {890 640 910 660} -tags {handle4 p3} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {890 490 910 510} -tags {handle4 p4} -filled 1 \
	-fillcolor $handleColor

    $w.zinc add text $group -anchor w -position {25 870} -tags bezier5 -color $textColor -width 270
    $w.zinc add curve $group {100 800 175 700} -tags {line5 l1-2} \
	-linecolor $barColor -filled 0 -linewidth 2
    $w.zinc add curve $group {325 700 400 800} -tags {line5 l3-4} \
	-linecolor $barColor -filled 0 -linewidth 2
    $w.zinc add curve $group {{100 800} {175 700 c} {325 700 c} {400 800}} \
	-tags {bezier5} -closed 0 -linecolor $splineColor -linewidth 5
    $w.zinc add arc $group {90 790 110 810} -tags {handle5 p1} -filled 1 \
	-fillcolor $handleColor
    $w.zinc add arc $group {165 690 185 710} -tags {handle5 p2} -filled 1 \
	-linewidth 0 -fillcolor $handleColor -filled 1
    $w.zinc add arc $group {315 690 335 710} -tags {handle5 p3} -filled 1 \
	-linewidth 0 -fillcolor $handleColor -filled 1
    $w.zinc add arc $group {390 790 410 810} -tags {handle5 p4} -filled 1 \
	-fillcolor $handleColor

    $w.zinc add text $group -anchor w -position {570 970} -tags bezier6 -color $textColor -width 280
    $w.zinc add curve $group {600 800 625 700} -tags {line6 l1-2} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {725 700 750 800} -tags {line6 l3-4} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {750 800 775 900} -tags {line6 l4-5} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {875 900 900 800} -tags {line6 l6-7} \
	-linecolor $barColor -linewidth 2
    $w.zinc add curve $group {
	{600 800} {625 700 c} {725 700 c} {750 800}
	{775 900 c} {875 900 c} {900 800}
    } -tags {bezier6} -filled 0 -closed 0 -linecolor $splineColor -linewidth 5
    $w.zinc add arc $group {590 790 610 810} -tags {handle6 p1} -filled 1 \
	-fillcolor $handleColor
    $w.zinc add arc $group {615 690 635 710} -tags {handle6 p2} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {715 690 735 710} -tags {handle6 p3} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {740 790 760 810} -tags {handle6 p4} -filled 1 \
	-linecolor blue -fillcolor blue -linewidth 2
    $w.zinc add arc $group {766 891 784 909} -tags {handle6 p5} -filled 1 \
	-fillcolor $handleColor
    $w.zinc add arc $group {865 890 885 910} -tags {handle6 p6} -filled 1 \
	-linewidth 0 -fillcolor $handleColor
    $w.zinc add arc $group {890 790 910 810} -tags {handle6 p7} -filled 1 \
	-fillcolor $handleColor

    $w.zinc scale $group 0.6 0.6

    ## Set the text of the text item with a tag "tag"
    ## to a human-readable form of the coords of the
    ## corresponding curve with the same tag "tag"
    proc setText {tag} {
	variable w
	set textItem  [$w.zinc find withtype text $tag]
	set curveItem [$w.zinc find withtype curve $tag]
	set coords [$w.zinc coords $curveItem]
	set count 0
	$w.zinc itemconfigure $textItem -text $coords
    }

    foreach bezierCount {1 2 3 4 5 6} {
	setText "bezier$bezierCount"
	set curveItem [$w.zinc find withtype curve "bezier$bezierCount"]
	set coords [$w.zinc coords $curveItem]
	#puts "$bezierCount : $curveItem : $coords"
	$w.zinc bind "handle$bezierCount" <1> {::curveBezier::itemStartDrag %x %y}
	$w.zinc bind "handle$bezierCount" <B1-Motion> {::curveBezier::itemDrag %x %y}
	#$w.zinc bind "handle$bezierCount" "<ButtonPress-1>" {\&press \&motion}
	#$w.zinc bind "handle$bezierCount" "<ButtonRelease-1>" {\&release}
    }

    ##### bindings for moving the handles
    variable item ""
    variable bezierNum ""
    variable ptNum ""

    variable xOrig 0
    variable yOrig 0

    proc itemStartDrag {x y} {
	variable w
	variable xOrig
	variable yOrig
	variable bezierNum
	variable ptNum
	variable item

	set xOrig $x
	set yOrig $y
	set item [$w.zinc find withtag current]

	foreach val [$w.zinc gettags $item] {
	    regexp {([a-z]+)(\d)} $val "" name num
	    if {$name=="handle"} {set bezierNum $num}
	    if {$name=="p"} {set ptNum $num}
	}
	#puts "bezierNum=$bezierNum ptNum=$ptNum"
    }

    # Callback for moving an item
    proc itemDrag {x y} {
	variable xOrig
	variable yOrig
	variable w
	variable item

	$w.zinc transform $item "[expr $x - $xOrig] [expr $y - $yOrig]"
	moveHandle [expr $x - $xOrig] [expr $y - $yOrig]
	set xOrig $x
	set yOrig $y
    }

    proc moveHandle {dx dy} {
	variable w
	variable bezierNum
	variable ptNum
	variable item

	set pt1 [lindex [$w.zinc coords $item] 0]
	set pt2 [lindex [$w.zinc coords $item] 1]

	## modifying the handle coords
	$w.zinc coords $item "[expr [lindex $pt1 0]+$dx] [expr [lindex $pt1 1]+$dy] [expr [lindex $pt2 0]+$dx] [expr [lindex $pt2 1]+$dy]"
	set prevPtNum [expr $ptNum-1]

	# there should only be one such item!
	set lineA [$w.zinc find withtag "line$bezierNum && l$prevPtNum-$ptNum"]
	if {$lineA!=""} {
	    set x [lindex [$w.zinc coords $lineA 0 1] 0]
	    set y [lindex [$w.zinc coords $lineA 0 1] 1]
	    $w.zinc coords $lineA 0 1 "[expr $x+$dx] [expr $y+$dy]"
	}

	set nextPtNum [expr $ptNum+1]
	# there should only be one such item:
	set lineB [$w.zinc find withtag "line$bezierNum && l$ptNum-$nextPtNum"]
	if {$lineB!=""} {
	    set x [lindex [$w.zinc coords $lineB 0 0] 0]
	    set y [lindex [$w.zinc coords $lineB 0 0] 1]
	    $w.zinc coords $lineB 0 0 "[expr $x+$dx] [expr $y+$dy]"
	}
	set tab [$w.zinc coords "bezier$bezierNum" 0 [expr $ptNum-1]]
	set x [lindex $tab 0]
	set y [lindex $tab 1]
	set control [lindex $tab 2]
	$w.zinc coords "bezier$bezierNum" 0 [expr $ptNum-1] "[expr $x+$dx] [expr $y+$dy] $control"
	setText "bezier$bezierNum"
    }
}

Added jni/tkzinc/demos/data/hegias_parouest_TE.vid.

cannot compute difference between binary files

Added jni/tkzinc/demos/data/videomap_orly.

cannot compute difference between binary files

Added jni/tkzinc/demos/data/videomap_paris-w_90_2.

cannot compute difference between binary files

Added jni/tkzinc/demos/fillRule.tcl.













































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval fillRule {
    variable w .fillRule
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Fillrule Demonstration"
    wm iconname $w "Fillrule"

    variable defaultfont {Helvetica -11}

    grid [button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ####### This file has been largely inspired from figure 11-3
    ####### of "The OpenGL Programming Guide 3rd Edition The
    ####### Official Guide to Learning OpenGL Version 1.2" ISBN 0201604582

    ####### it illustrates the use of :
    #######  -fillrule attribute of curves
    #######  contour coords and clone method

    #variable imagePath [file join $zinc_library demos images]
    #variable texture [image create photo -file [file join $imagePath paper-grey1.gif]]

    grid [zinc $w.zinc -width 550 -height 680 -font $defaultfont -borderwidth 0 \
	      -backcolor \#898A8F] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2


    $w.zinc add text 1 -position {20 8} -alignment center -text {This static example reproduces figure 11-3
of "The OpenGL Programming Guide 3rd Edition" V 1.2}

    variable group [$w.zinc add group 1]

    variable g1 [$w.zinc add group $group]
    variable curve1 [$w.zinc add curve $g1 {}]
    $w.zinc contour $curve1 add +1 { 0 0 0 120 120 120 120 0 0 0}
    $w.zinc contour $curve1 add +1 { 20 20 20 100 100 100 100 20 20 20}
    $w.zinc contour $curve1 add +1 { 40 40 40 80 80 80 80 40 40 40}
    $w.zinc translate $g1 100 100

    variable g2 [$w.zinc add group $group]
    variable curve2 [$w.zinc add curve $g2 {}]
    $w.zinc contour $curve2 add +1 { 0 0 0 120 120 120 120 0 0 0}
    $w.zinc contour $curve2 add -1 { 20 20 20 100 100 100 100 20 20 20}
    $w.zinc contour $curve2 add -1 { 40 40 40 80 80 80 80 40 40 40}
    $w.zinc translate $g2 260 100

    variable g3 [$w.zinc add group $group]
    variable curve3 [$w.zinc add curve $g3 {}]
    $w.zinc contour $curve3 add +1 { 20 0 20 120 100 120 100 0 20 0}
    $w.zinc contour $curve3 add +1 { 40 20 60 140 80 20 40 20}
    $w.zinc contour $curve3 add +1 { 0 60 0 80 120 80 120 60 0 60}
    $w.zinc translate $g3 420 100

    variable g4 [$w.zinc add group $group]
    variable curve4 [$w.zinc add curve $g4 {}]
    $w.zinc contour $curve4 add +1 { 0 0 0 140 140 140 140 60 60 60 60 80 80 80 80 40 40 40 40 100 100 100 100 20 20 20 20 120 120 120 120 0 0 0}
    $w.zinc translate $g4 580 100

    $w.zinc scale $group 0.6 0.6
    $w.zinc translate $group 80 40

    variable t [$w.zinc add text $group -underlined yes -text "Contours"]
    $w.zinc translate $t 280 30
    set t [$w.zinc add text $group -underlined yes -text "-fillrule"]
    $w.zinc translate $t -110 30
    variable dy 0
    foreach fillrule {odd nonzero positive negative abs_geq_2} {
	set dy [expr $dy + 160]
	set t [$w.zinc add text $group -text $fillrule]
	$w.zinc translate $t -110 [expr 100+$dy]
	foreach item "$curve1 $curve2 $curve3 $curve4" {
	    set clone [$w.zinc clone $item -fillrule $fillrule -filled 1 -linewidth 0]
	    $w.zinc translate $clone 0 $dy
	}
    }

    # creating simple lines with arrows under each curves
    foreach item "$curve1 $curve2 $curve3 $curve4" {
	set contour_number [$w.zinc contour $item]
	#puts "$item contour_number=$contour_number\n"
	for {set n 0} {$n <=[expr $contour_number-1]} {incr n} {
	    set points [$w.zinc coords $item $n]
	    set nbpoints [llength $points]
	    for {set i 0} {$i <=[expr $nbpoints-2]} {incr i} {
		set firstpoint [lindex $points $i]
		set lastpoint [lindex $points [expr $i+1]]
		set middlepoint "[expr [lindex $firstpoint 0]+([lindex $lastpoint 0]- [lindex $firstpoint 0])/1.5] [expr [lindex $firstpoint 1]+([lindex $lastpoint 1]-[lindex $firstpoint 1])/1.5]"
		$w.zinc add curve [$w.zinc group $item] "$firstpoint $middlepoint" -lastend "7 10 4"
	    }
	}
    }
}

Added jni/tkzinc/demos/groupsInAtcStrips.tcl.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
#-----------------------------------------------------------------------------------
#
#      Copyright (C) 2002
#      Centre d'Études de la Navigation Aérienne
#
#      Authors: Jean-Luc Vinot <vinot@cena.fr> for the graphic design
#               Patrick Lecoanet for the tcl code.
#-----------------------------------------------------------------------------------
#      This small application illustrates both the use of groups in combination
#         of -composescale attributes and an implementation of kind of air traffic
#         control electronic strips.
#      However it is only a simplified example given as is, without any immediate usage!
#
#      3 strips formats are accessible through "+" / "-" buttons on the right side
#
#      1.   small-format: with 2 lines of info, and reduced length
#
#      2.   normal-format: with 3 lines of info, full length
#
#      3.  extended-format: with 3 lines of infos, full length
#                           the 3 lines are zoomed
#                           an additionnel 4th lone is displayed
#
#      An additionnal 4th format (micro-format) is available when double-clicking somewhere...
#
#      Strips can be moved around by drag&drop from the callsign
#
#      When changing size, strips are animated. The animation is a very simple one,
#        which should be enhanced.... You can change the animation parameters, by modifyng
#        $delay and $steps.
#
#-----------------------------------------------------------------------------------

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval groupsInAtcStrips {
  variable w .groupsInAtcStrips

  catch {destroy $w}
  toplevel $w
  wm title $w "Atc electronic strips using groups"
  wm iconname $w groupsInAtcStrips

  grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
  grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

  ###########################################
  # Text zone
  ###########################################

  grid [text $w.text -relief sunken -borderwidth 2 -height 5 \
            -font TkDefaultFont] \
    -row 0 -column 0 -columnspan 2 -sticky ew

  $w.text insert end {These fake air Traffic Control electronic strips illustrates
the use of groups for an advanced graphic design.
The following interactions are possible:
  "drag&drop button1" on the callsign.
  "button 1" triangle buttons on the right side of the strips
  to modify strips size
  "double click 1" on the blueish zone to fully reduce size}
  $w.text configure -state disabled

  catch {font create dfont -family Helvetica -size -10 -weight bold}
  catch {font create radar-b15 -family Helvetica -size -16 -slant roman -weight bold}
  catch {font create radar-b12 -family Helvetica -size -12 -slant roman -weight bold}
  catch {font create radar-b10 -family Helvetica -size -10 -slant roman -weight bold}
  catch {font create radar-m18 -family Helvetica -size -18 -slant roman -weight normal}
  catch {font create radar-m20 -family Helvetica -size -20 -slant roman -weight normal}

  set fontsets(scales) {1.2 normal 10 large}
  set fontsets(normal,callsign) radar-b15
  set fontsets(normal,type1) radar-b12
  set fontsets(normal,type2) radar-b10
  set fontsets(normal,type3) radar-b10
  set fontsets(large,callsign) radar-m20
  set fontsets(large,type1) radar-m18
  set fontsets(large,type2) radar-b15
  set fontsets(large,type3) radar-b12

  image create photo backtex -data {
    R0lGODlhIAAgAPcAALi4uLe3t7a2trS0tLOzs7KysrGxsbCwsK+vr66urq2traysrKurq6qq
    qqmpqaioqKenp6ampqWlpaSkpKOjo6KioqGhoaCgoJ+fn56enp2dnZycnJubm5qampmZmZiY
    mJeXl5aWlpWVlZSUlJOTk5KSkpGRkZCQkI+Pj46Ojo2NjYyMjIuLi4qKiomJiYiIiIeHh4aG
    hoWFhYSEhIODg4KCgoGBgYCAgH9/f35+fn19fXx8fHt7e3p6enl5eXh4eHR0dAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAgACAABwj/ADto4ABCAwgS
    Ijps4NAhA4cJE0SIcJjhggUKDxxcGBEixAiGAz04oEDwQ4cQJjiU+MBhxAcNIzZMkGDBQgQI
    FDyEwGCBw4YNHShQMFhQQwcLIj5sAMEhAwkOEiSczFABQ0uaHjowLLhBxM4IEi54wFCBZQUO
    HixgGCECw9oPKSRw+OChroYJFECY+JAhQwkTGjCUGHEBgwi0JTo8qHCCA4oHHT6w1GBwRIcJ
    DyxIrvAgwswKGz5SnLD2RImHHRRqWNjUQoULGfZ2ABGi6VIMeCVAEEwhAwYKEkMUvPD652+X
    IVCkCBGYpwXfFTKEgKCho3AQIDAU3lB3A2wLGkSQ/zhawUJX00o1ZBCRIsXF1+A/gMjqwaTb
    urgnfCCB4sQIEArNRsIIE0RQgXonhZDVByKogFx2Qik3wm8ZyKdgZEKpBOBCHmDnAQl0SbRB
    TSKYIMIFE2hAFwoeZOBBZx2ckBIFmrmEgQQPUHASB27lZSIIInhQAQp3XbDdWB+gwIKD3vGF
    F3caULBAByqY4AGPETAwAVomWQABCHT5NJtlGag1l0AcmLCcehdI4IAFIJRwAgkXMJBUYBl0
    MMIJUeGlVl8ooECCdxlocEEEPYVQAgkeXAAUCCMM5oEGDDwwQQXlZbBBCSF4Z5VWq6n30wcj
    DBSnCSFckKNVdXUYZGCrbf/gG1sbVDBTeEwV6hNnhUbmoUKazmeBBBNEpgFNE4BXwlisanCW
    enONRdMFHYBoa19eWbUBT/95IEKgIPgF4EGl6rYlpxdoYCIMMgSqkAgSJLDABTx6oAIEB26b
    7pUkgBCVVhC0KFAGGVFgAoACVUABBpbCtlpkHiw6V5UYrHCCg3xVyGC4GPxkJGwdiFDCoubJ
    GoIKJICWZgiupesABhl49kEImvrWkgkuUVBBVBuAOEEDEoAZ3U9yQRWBehB4VxVDVDF1UXiH
    HehfV0HS25BDI2bFAUMcGApimfQCaWAIH4QlJXEZAClZTBB3HapvxIEWQgQRbE1qBxF8ABsJ
    JFRaBAIDiFYQwQPIWl1mzymUkMKgW28QQa1vahduX5T3hUEDcFIWQgeAURAa2R8kXSZ2HNBp
    kWuYnnX0eBzUNkIGQ3WgHQaPu3XYUOq5BXOhG0iwaUO1pvBfCAEBADs=
  }

  image create photo striptex -data {
    R0lGODlhCgBQAID/ALbd9tnn6ywAAAAACgBQAAACNYyPmcDtCqN0FMiL68Nc6daFx8eIImmZ
    HaquZMux8CXPUW17bw7h/Lj7IXxC4s/IQ+aUNmYBADuioNSSFFMFXrHZ7mMr8YpZ4LE5AX6d
    m+X1Oe1+t+NiOJ1UAAA7
  }

  ##########################################
  # Zinc
  ##########################################
  grid [zinc $w.zinc -render 1 -width 700 -height 500 -borderwidth 0 \
      -lightangle 130 -tile backtex] -row 1 -column 0 -columnspan 2 -sticky news
  grid columnconfigure $w 0 -weight 1
  grid columnconfigure $w 1 -weight 1
  grid rowconfigure $w 1 -weight 2

  catch "$w.zinc gname {=axial 90|#ffffff 0|#ffeedd 30|#e9d1ca 90|#e9a89a} idnt"
  catch "$w.zinc gname {#c1daff|#8aaaff} back"
  catch "$w.zinc gname {=path -40 -40|#000000;50 0|#000000;50 92|#000000;0 100} shad"
  catch "$w.zinc gname {#ffeedd|#8a9acc} btnOutside"
  catch "$w.zinc gname {=axial 180|#ffeedd|#8a9acc} btnInside"
  catch "$w.zinc gname {#8aaaff|#5b76ed} ch1"

  set anim(delay) 50;	# ms between each animation steps
  set anim(steps) 6;	# number of steps for the animation

  #
  # The strip building routine
  proc Strip { } {
    variable scale
    variable w
    #
    # Creating the object group
    set stripG [$w.zinc add group 1]
    #
    # Add a group for all items that will need scaling
    set scaleG [$w.zinc add group $stripG -tags scaling]
    #
    # Add add background shadow
    $w.zinc add rectangle $scaleG {8 8 374 94} -filled 1 -linewidth 0 \
        -fillcolor shad -tags shadow
    #
    # This is the strip background
    $w.zinc add rectangle $scaleG {0 0 340 86} -filled 1 \
        -linewidth 3 -linecolor {#aaccff} -fillcolor back -relief roundraised
    #
    # Add a group for the two size change buttons.
    set btnGroup [$w.zinc add group $scaleG]
    $w.zinc translate $btnGroup 340 0 true
    #
    # Clip the button group to a rectangular shape that will
    # be scaled with the rest of the strip.
    $w.zinc itemconfigure $btnGroup -clip [$w.zinc add rectangle $btnGroup {0 0 90 83} -visible no]
    #
    # Here the cylindrical background of the button area.
    # The scale is not inherited to preserve the cylindrical
    # relief of the area, this is explain the need for a
    # clipping on btnGroup.
    $w.zinc add rectangle $btnGroup {0 0 26 85} -filled 1 -linewidth 0 \
        -fillcolor btnOutside -composescale 0 -tags content

    ArrowButton $btnGroup + {0 0 26 43} {14 2 24 40 1 40 14 2} {13 27} [list $stripG more content]
    ArrowButton $btnGroup - {0 43 26 86} {14 83 24 43 1 43 14 83} {13 56} [list $stripG less content]

    #
    # This group will get the strip useful content. Its area is clipped.
    set clippedContent [$w.zinc add group $scaleG]
    $w.zinc itemconfigure $clippedContent \
        -clip [$w.zinc add rectangle $clippedContent {3 3 332 80} -visible 0]
    #
    # One more group to control whether the scale is inherited or not.
    set content [$w.zinc add group $clippedContent -composescale 0 -tags content]
    #
    # The strip is divided into functional textual zones.
    # They are created here.
    set input [Zone $content {3 3 334 82} 0 white back {} flat [list $stripG scale input]]
    TextField $input TYPA type1 {100 18} {#444444} w
    TextField $input 08:26 type1 {200 18} {#444444} e
    TextField $input NIPOR type2 {100 40} {#444444} w
    TextField $input 8G type2 {158 40} {#444444} center
    TextField $input G23 type2 {200 40} {#444444} e
    TextField $input DEST type2 {10 66} {#555555} w
    TextField $input Bret. type2 {200 66} {#444444} e
    RectField $input {45 56 135 76} ch1

    Zone $content {210 3 346 82} 2 {#deecff} {#d3e5ff} striptex sunken {zreco edit}

    set ident [Zone $content {3 3 90 50} 1 {#ffeedd}  idnt {} sunken [list $stripG move]]
    $w.zinc raise $ident
    TextField $ident EWG361 callsign {10 18} {#000000} w
    TextField $ident Eurowing type2 {10 34} {#444444} w
    #
    # Add and extension area beneath the main strip
    # This extension is shown when the strip is shown in its
    # extended form.
    set extent [$w.zinc add group $scaleG -atomic yes -tags {zinfo edit2}]
    $w.zinc translate $extent 0 86 true
    #
    # Add a background shadow.
    $w.zinc add rectangle $extent {8 8 348 28} \
        -filled 1 -linewidth 0 -tags shadow -fillcolor shad
    #
    # This is the extention background
    $w.zinc add rectangle $extent {0 0 340 20} -filled 1 \
        -linewidth 2 -linecolor {#aaccff} -fillcolor back -relief roundraised
    TextField $extent 7656 type3 {4 10} {#444444} w
    TextField $extent G23 type3 {47 10} {#444444} center
    TextField $extent 09R type3 {73 10} {#444444} center
    TextField $extent vit: type3 {105 10} {#444444} e
    TextField $extent 260 type3 {106 10} {#444444} w
    TextField $extent EPL type3 {142 10} {#444444} center
    TextField $extent 210 type3 {166 10} {#444444} center
    TextField $extent 8350 type3 {183 10} {#444444} w
    TextField $extent MOD type3 {219 10} {#444444} w
    TextField $extent 21/05/02 type3 {297 10} {#444444} e
    TextField $extent 13:50 type3 {332 10} {#444444} e
    DisplayExtentZone $stripG no

    #
    # Preset the scale and font size of the layout
    set scale($stripG,x) 1.0
    set scale($stripG,y) 1.0
    set scale($stripG,fontset) normal

    return $stripG
  }

  proc ArrowButton {top text coords arrow labelpos tags} {
    variable w
    set sGroup [$w.zinc add group $top -atomic 1 -composescale 0 -tags $tags]
    $w.zinc add rectangle $sGroup $coords -filled 1 -visible 0
    $w.zinc add curve $sGroup $arrow -closed 1 -filled 1 \
        -linewidth 1  -linecolor {#aabadd} -fillcolor btnInside
    $w.zinc add text $sGroup -position $labelpos -text $text \
        -font radar-m20 -color {#ffffff} -anchor center
  }

  proc RectField {top coords fillcolor} {
    variable w
    $w.zinc add rectangle $top $coords -linewidth 0 -filled yes \
        -fillcolor $fillcolor
  }

  proc TextField {top text fonttype coords color anchor} {
    variable w
    variable fontsets
    $w.zinc add text $top -position $coords -text $text -font $fontsets(normal,$fonttype) \
        -color $color -anchor $anchor -tags $fonttype
  }

  proc Zone {top coords linewidth linecolor fillcolor texture relief tags} {
    variable w
    #
    # Zone group
    set gz [$w.zinc add group $top -atomic 1 -tags $tags]
    #
    # Zone background
    set rectZone [$w.zinc add rectangle $gz $coords \
                      -filled yes -linewidth $linewidth -linecolor $linecolor \
                      -fillcolor $fillcolor -relief $relief]
    if { $texture ne "" } {
      $w.zinc itemconfigure $rectZone -tile $texture
    }

    return $gz
  }

  #
  # Called when the user click on the strip's identification area.
  proc CatchStrip {x y} {
    variable w
    variable dx
    variable dy

    set strip [lindex [$w.zinc itemcget current -tags] 0]
    foreach {lx ly} [$w.zinc coords $strip] break
    set dx [expr {$lx - $x}]
    set dy [expr {$ly - $y}]
    $w.zinc raise $strip
  }

  #
  # Called when the mouse drag the strip
  proc MotionStrip {x y} {
    variable w
    variable dx
    variable dy

    set strip [lindex [$w.zinc itemcget current -tags] 0]
    $w.zinc translate $strip [expr $x + $dx] [expr $y + $dy] true
  }

  #
  # ExtendedStrip, NormalStrip, SmallStrip, MicroStrip
  # Those functions controls the transition from the current
  # strip layout to the named layout.
  # They are bonud to the resize buttons to the right of
  # the strip.
  proc NormalStrip {} {
    variable w
    set strip [lindex [$w.zinc itemcget current -tags] 0]
    $w.zinc itemconfigure $strip*input -sensitive 1

    DisplayRecoZone $strip yes
    DisplayExtentZone $strip no
    ConfigButtons $strip ExtendedStrip SmallStrip
    ChangeStripFormat $strip 1 1 no
  }

  proc SmallStrip {} {
    variable w
    set strip [lindex [$w.zinc itemcget current -tags] 0]
    DisplayRecoZone $strip no
    ConfigButtons $strip NormalStrip {}
    ChangeStripFormat $strip 1 0.63 no
  }

  proc MicroStrip {} {
    variable w
    set strip [lindex [$w.zinc itemcget current -tags] 0]
    ConfigButtons $strip NormalStrip {}
    ChangeStripFormat $strip 0.28 0.63 no
  }

  proc ExtendedStrip {} {
    variable w
    set strip [lindex [$w.zinc itemcget current -tags] 0]
    $w.zinc itemconfigure $strip*input -sensitive 0
    $w.zinc raise $strip
    DisplayRecoZone $strip no
    DisplayExtentZone $strip yes
    ConfigButtons $strip {} NormalStrip
    ChangeStripFormat $strip 1.3 1.3 yes
  }

  #
  # Controls the display of the gesture recognition area.
  proc DisplayRecoZone {strip bool} {
    variable w
    $w.zinc itemconfigure $strip*zreco -visible $bool
  }

  #
  # Controls the display of the extended information area.
  proc DisplayExtentZone {strip bool} {
    variable w
    $w.zinc itemconfigure $strip*zinfo -visible $bool -sensitive $bool
  }

  #
  # Update the scaling buttons to reflect the current
  # layout of the strip.
  proc ConfigButtons {strip funcUp funcDown} {
    variable w
    if { $funcUp ne "" } {
      $w.zinc itemconfigure $strip*more -visible 1
      $w.zinc bind more <1> ::groupsInAtcStrips::$funcUp
    } {
      $w.zinc itemconfigure $strip*more -visible 0
    }
    if { $funcDown ne "" } {
      $w.zinc itemconfigure $strip*less -visible 1
      $w.zinc bind less <1> ::groupsInAtcStrips::$funcDown
    } {
      $w.zinc itemconfigure $strip*less -visible 0
    }
  }

  #
  # Change the strip size hiding information has needed.
  # Uses an animation to highlight the state change to te user.
  proc ChangeStripFormat {strip xscale yscale composeflag} {
    variable w
    variable scale
    variable anim
    #
    # Adjust the scale inheritance of the content area
    $w.zinc itemconfigure $strip*content -composescale $composeflag
    #
    # Compute the scaling animation and start it.
    # At the same time if needed switch to bigger/smaller fonts.
    set dx [expr {($xscale - $scale($strip,x)) / $anim(steps)}]
    set dy [expr {($yscale - $scale($strip,y)) / $anim(steps)}]
    set newXScale [expr {$scale($strip,x) + $dx}]
    set newYScale [expr {$scale($strip,y) + $dy}]
    set scale($strip,x) $xscale
    set scale($strip,y) $yscale
    SetFontes $strip
    ::groupsInAtcStrips::ResizeAnim $strip $newXScale $newYScale $dx $dy $anim(steps)
  }

  #
  # This is the animation stepping function
  proc ResizeAnim {strip xscale yscale dx dy steps} {
    variable w
    variable anim
    $w.zinc treset $strip*scaling
    $w.zinc scale $strip*scaling $xscale $yscale
    incr steps -1
    if { $steps > 0 } {
      after $anim(delay) [list ::groupsInAtcStrips::ResizeAnim $strip [expr {$xscale+$dx}] \
                        [expr {$yscale+$dy}] $dx $dy $steps]
    }
  }

  proc SetFontes {strip} {
    variable w
    variable scale
    variable fontsets
    #
    # Find a fontset matching the current y scale
    foreach {maxScale fs} $fontsets(scales) {
      if { $scale($strip,y) < $maxScale } break
    }
    if { $scale($strip,fontset) ne $fs } {
      foreach type {callsign type1 type2 type3} {
        $w.zinc itemconfigure $strip*$type -font $fontsets($fs,$type)
      }
    }
    set scale($strip,fontset) $fs
  }
  #
  # Initialization of user input bindings..
  $w.zinc bind more <1> ::groupsInAtcStrips::ExtendedStrip
  $w.zinc bind less <1> ::groupsInAtcStrips::SmallStrip
  $w.zinc bind move <1> {::groupsInAtcStrips::CatchStrip %x %y}
  $w.zinc bind move <B1-Motion> {::groupsInAtcStrips::MotionStrip %x %y}
  $w.zinc bind scale <Double-Button-1> ::groupsInAtcStrips::MicroStrip

  #
  # Generate a handful of strips
  for {set xn 10; set yn 30; set i 0} {$i < 4} {incr i; incr xn 50; incr yn 120} {
    $w.zinc translate [Strip] $xn $yn true
  }
}

Added jni/tkzinc/demos/groupsPriority.tcl.





































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval groupsPriority {
    variable w .groupsPriority
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Groups priority Demonstration"
    wm iconname $w Groups

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 12 \
              -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end "There are two groups (a red one and a green one) each containing\n4 rectangles. Those rectangles display their current priority.\nThe following operations are possible:\n Mouse Button 1 for dragging objects.\n Mouse Button 2 for dragging a colored group.\n Key + on a rectangle to raise it inside its group.\n Key - on a rectangle to lower it inside its group.\n Key l on a rectangle to lower its colored group.\n Key r on a rectangle to raise its colored group.\n Key t on a rectangle to change its group (but not its color!).\n Key 0-9 on a rectangle to set the priority to 0-9\nRaising or lowering an item inside a group modify its priority if necessary"
    §w.text configure -state disabled

    ###########################################
    # Zinc
    ###########################################
    variable zinc_width 600
    variable zinc_height 500
    grid [zinc $w.zinc -width $zinc_width -height $zinc_height -font $defaultfont \
	      -borderwidth 3 -relief sunken] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    #########################################################################"
    # Creating the redish group
    variable group1 [$w.zinc add group 1 -visible 1]

    variable counter 0
    # Adding 4 rectangles with text to redish group
    foreach data { {200 100 red} {210 210 red1} {390 110 red2} {395 215 red3} } {
	set counter [expr $counter+ 2]
	set centerx [lindex $data 0]
	set centery [lindex $data 1]
	set color [lindex $data 2]

	# this small group is for merging together :
	# the rectangle and the text showing its name
	set g [$w.zinc add group $group1 -visible 1 -atomic 1 -sensitive 1 -priority $counter]
	set rec [$w.zinc add rectangle $g \
		     [list [expr $centerx-100] [expr $centery-60] [expr $centerx+100] [expr $centery+60]] \
		     -fillcolor $color -filled 1]

	set txt [$w.zinc add "text" $g -position "$centerx $centery" -text "pri=$counter" -anchor center]

	# Some bindings for dragging the rectangle or the full group
	$w.zinc bind $g <1> "::groupsPriority::itemStartDrag $g %x %y"
	$w.zinc bind $g <B1-Motion> "::groupsPriority::itemDrag $g %x %y"
	$w.zinc bind $g <2> "::groupsPriority::itemStartDrag $g %x %y"
	$w.zinc bind $g <B2-Motion> "::groupsPriority::groupDrag $g %x %y"
    }

    #########################################################################"
    # Creating the greenish group
    variable group2 [$w.zinc add group 1 -visible 1]
    variable counter 0

    # Adding 4 rectangles with text to greenish group
    foreach data {{200 300 green1} {210 410 green2} {390 310 green3} {395 415 green4}} {
	incr counter
	set centerx [lindex $data 0]
	set centery [lindex $data 1]
	set color [lindex $data 2]

	# this small group is for merging together a rectangle
	# and the text showing its priority
	set g [$w.zinc add group $group2 -atomic 1 -sensitive 1 -priority $counter]

	set rec [$w.zinc add rectangle $g "[expr $centerx-100] [expr $centery-60] [expr $centerx+100] [expr $centery+60]" -fillcolor $color -filled 1]

	set txt [$w.zinc add text $g -position "$centerx $centery" -text "pri=$counter" -anchor center]

	# Some bindings for dragging the rectangle or the full group
	$w.zinc bind $g <1> "::groupsPriority::itemStartDrag $g %x %y"
	$w.zinc bind $g <B1-Motion> "::groupsPriority::itemDrag $g %x %y"
	$w.zinc bind $g <2> "::groupsPriority::itemStartDrag $g %x %y"
	$w.zinc bind $g <B2-Motion> "::groupsPriority::groupDrag $g %x %y"
    }

    #########################################################################"
    # adding the key bindings

    # the focus on the widget is ABSOLUTELY necessary for key bindings!
    focus $w.zinc

    bind $w.zinc <KeyPress-r> ::groupsPriority::raiseGroup
    bind $w.zinc <KeyPress-l> ::groupsPriority::lowerGroup
    bind $w.zinc <KeyPress-plus> ::groupsPriority::raise

    bind $w.zinc <KP_Add> ::groupsPriority::raise
    bind $w.zinc <KeyPress-minus> ::groupsPriority::lower
    bind $w.zinc <KP_Subtract> ::groupsPriority::lower
    bind $w.zinc <KeyPress-t> ::groupsPriority::toggleItemGroup

    for {set i 0} {$i<=9} {incr i} {
	bind $w.zinc <KeyPress-$i> "::groupsPriority::setPriority $i"
	bind $w.zinc <KeyPress-KP_$i> "::groupsPriority::setPriority $i"
    }

    # The following binding is currently not possible only text items
    # with focus can get a KeyPress or KeyRelease event
    # $zinc->bind($g '<KeyPress>' [\&raise $g]

    ####################################withtype#####################################"
    # Definition of all callbacks

    proc updateLabel {group} {
	variable w

	set priority [$w.zinc itemcget $group -priority]
	# we get the text item from this group:
	set textitem [$w.zinc find withtype text ".$group."]
	$w.zinc itemconfigure $textitem -text "pri=$priority"
    }

    proc setPriority {priority} {
	variable w

	set item [$w.zinc find withtag current]
	#return unless $item
	$w.zinc itemconfigure $item -priority $priority
	updateLabel $item
    }

    # Callback to lower a small group of a rectangle and a text
    proc lower {} {
	variable w

	# to get the item under the cursor!
	set item [$w.zinc find withtag current]
	#return unless $item
	$w.zinc lower $item
	updateLabel $item
    }

    # Callback to raise a small group of a rectangle and a text
    proc raise {} {
	variable w

	# to get the item under the cursor!
	set item [$w.zinc find withtag current]
	#return unless $item
	$w.zinc raise $item
	updateLabel $item
    }

    # Callback to raise the group of groups of a rectangle and a text
    proc lowerGroup {} {
	variable w

	# to get the item under the cursor!
	set item [$w.zinc find withtag current]
	#return unless $item
	set coloredGroup [$w.zinc group $item]
	$w.zinc lower $coloredGroup
    }

    # Callback to raise the group of groups of a rectangle and a text
    proc raiseGroup {} {
	variable w

	# to get the item under the cursor!
	set item [$w.zinc find withtag current]
	#return unless $item
	set coloredGroup [$w.zinc group $item]
	$w.zinc raise $coloredGroup
	updateLabel $item
    }

    # Callback to change  puts raise
    #the group of groups of a rectangle and a text
    proc toggleItemGroup {} {
	variable group1
	variable group2
	variable w

	# to get the item under the cursor!
	set item [$w.zinc find withtag current]

	# return unless $item
	set newgroup ""
	if {$group1 == [$w.zinc group $item]} {
	    set newgroup $group2
	} else {
	    set newgroup $group1
	}
	$w.zinc chggroup $item $newgroup 1
	updateLabel $item
    }

    # callback for starting a drag
    set xOrig ""
    set yOrig ""

    proc itemStartDrag {item x y} {
	variable xOrig
	variable yOrig

	set xOrig $x
	set yOrig $y
    }

    # Callback for moving an item
    proc itemDrag {item x y} {
	variable xOrig
	variable yOrig
	variable w

	$w.zinc translate $item [expr $x-$xOrig] [expr $y-$yOrig];
	set xOrig $x;
	set yOrig $y;
    }

    # Callback for moving an item
    proc groupDrag {item x y} {
	variable xOrig
	variable yOrig
	variable w

	set coloredGroup [$w.zinc group $item]
	$w.zinc translate $coloredGroup [expr $x-$xOrig] [expr $y-$yOrig];
	set xOrig $x;
	set yOrig $y;
    }
}

Added jni/tkzinc/demos/iconTransform.tcl.





















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# $Id$
# this simple demo has been developped by C. Mertz <mertz@cena.fr>
# Ported to Tcl by P.Lecoanet

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval iconTransform {
    variable w .iconTransform
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc icon scale/rotate Demonstration"
    wm iconname $w iconTransform

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 6 \
              -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {You can transform this image with your mouse:
Drag-Button 1 for moving,
Drag-Button 2 for zooming,
Drag-Button 3 for rotating,
Shift-Drag-Button 1 for modifying the transparency (OpenGL only).}
    $w.text configure -state disabled

    ###########################################
    # Zinc
    ###########################################
    grid [zinc $w.zinc -width 350 -height 250 -render 1 -font $defaultfont \
	-borderwidth 3 -relief sunken] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    variable topGroup [$w.zinc add group 1]

    image create photo zincAA -file [file join $::zinc_demos images zinc.gif]

    variable zincAA [$w.zinc add icon $topGroup -image zincAA \
			 -position {10 10} -composescale 1 -composerotation 1]

    $w.zinc add text $topGroup \
	-text "try to zoom/resize the banner!\nNow works also without openGL ;-)" \
        -color white -composescale 1 -composerotation 1 -position {15 100}

    #
    # Controls for the window transform.
    #
    bind $w.zinc <ButtonPress-1>  "::iconTransform::press motion %x %y"
    bind $w.zinc <ButtonRelease-1>  ::iconTransform::release
    bind $w.zinc <ButtonPress-2>  "::iconTransform::press zoom %x %y"
    bind $w.zinc <ButtonRelease-2>  ::iconTransform::release
    bind $w.zinc <ButtonPress-3>  "::iconTransform::press mouseRotate %x %y"
    bind $w.zinc <ButtonRelease-3>  ::iconTransform::release

    #
    # Controls for alpha and gradient
    #
    bind $w.zinc <Shift-ButtonPress-1> "::iconTransform::press modifyAlpha %x %y"
    bind $w.zinc <Shift-ButtonRelease-1> ::iconTransform::release

    variable curX 0
    variable curY 0
    variable curAngle 0

    proc press {action x y} {
	variable w
	variable curAngle
	variable curX
	variable curY

	set curX $x
	set curY $y
	set curAngle [expr atan2($y, $x)]
	bind $w.zinc <Motion> "::iconTransform::$action %x %y"
    }

    proc motion {x y} {
	variable w
	variable topGroup
	variable curX
	variable curY

	foreach {x1 y1 x2 y2} [$w.zinc transform $topGroup \
				   [list $x $y $curX $curY]] break
	$w.zinc translate $topGroup [expr $x1 - $x2] [expr $y1 - $y2]
	set curX $x
	set curY $y
    }

    proc zoom {x y} {
	variable w
	variable topGroup
	variable curX
	variable curY

	if {$x > $curX} {
	    set maxX $x
	} else {
	    set maxX $curX
	}
	if {$y > $curY} {
	    set maxY $y
	} else {
	    set maxY $curY
	}
	if {($maxX == 0) || ($maxY == 0)} {
	    return;
	}
	set sx [expr 1.0 + (double($x - $curX) / $maxX)]
	set sy [expr 1.0 + (double($y - $curY) / $maxY)]
	$w.zinc scale $topGroup $sx $sx

	set curX $x
	set curY $y
    }

    proc mouseRotate {x y} {
	variable w
	variable curAngle
	variable topGroup

	set lAngle [expr atan2($y, $x)]
	$w.zinc rotate $topGroup [expr -($lAngle - $curAngle)]
	set curAngle  $lAngle
    }

    proc release {} {
	variable w

	bind $w.zinc <Motion> {}
    }

    proc modifyAlpha {x y} {
	variable w
	variable topGroup

	set xRate [expr double($x) / [$w.zinc cget -width]]
	set xRate [expr ($xRate < 0) ? 0 : ($xRate > 1) ? 1 : $xRate]
	set alpha [expr int($xRate * 100)]

	$w.zinc itemconfigure $topGroup -alpha $alpha
    }
}

Added jni/tkzinc/demos/images/background_texture.gif.

cannot compute difference between binary files

Added jni/tkzinc/demos/images/paper-grey.gif.

cannot compute difference between binary files

Added jni/tkzinc/demos/images/paper-grey1.gif.

cannot compute difference between binary files

Added jni/tkzinc/demos/images/paper.gif.

cannot compute difference between binary files

Added jni/tkzinc/demos/images/photoAlpha.png.

cannot compute difference between binary files

Added jni/tkzinc/demos/images/stripped_texture.gif.

cannot compute difference between binary files

Added jni/tkzinc/demos/images/zinc.gif.

cannot compute difference between binary files

Added jni/tkzinc/demos/items.tcl.

























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# $Id$
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval allItems {
    variable w .items
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Item Demonstration"
    wm iconname $w Items

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ttk::scrollbar $w.vscroll -command "$w.zinc yview"
    grid $w.vscroll -row 0 -column 2 -sticky ns
    ttk::scrollbar $w.hscroll -orient horiz -command "$w.zinc xview"
    grid $w.hscroll -row 1 -column 0 -columnspan 2 -sticky we

    zinc $w.zinc -width 700 -height 600 -scrollregion {-100 0 1000 1000} \
	-xscrollcommand "$w.hscroll set" \
	-yscrollcommand "$w.vscroll set" \
	-font $defaultfont -borderwidth 3 -relief sunken
    grid $w.zinc -row 0 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 0 -weight 2

    $w.zinc add rectangle 1 {10 10 100 50} -fillcolor green -filled 1 -linewidth 10 \
	-relief roundridge -linecolor darkgreen

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {120 20} \
	-text {A filled rectangle with a "roundridge" relief border of 10 pixels.}

    variable labelformat {x82x60+0+0 x60a0^0^0 x32a0^0>1 a0a0>2>1 x32a0>3>1 a0a0^0>2};

    variable x 20;
    variable y 120;
    variable track [$w.zinc add track 1 6 -labelformat $labelformat -position "$x $y" \
		   -speedvector {40 -10} -speedvectormark 1 -speedvectorticks 1]

    # moving the track, to display past positions
    for {set i 0} {$i<=5} {incr i} {
	set x1 [expr $x+$i*10]
	set y1 [expr $y-$i*2]
	$w.zinc coords "$track" "$x1 $y1"
    }

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {200 80} \
	-text "A flight track for a radar display. A waypoint looks similar,
but has no speed vector and no past positions."

    $w.zinc itemconfigure $track 0 -filled 0 -bordercolor DarkGreen -border contour

    $w.zinc itemconfigure $track 1 -filled 1 -backcolor gray60 -text AFR001
    $w.zinc itemconfigure $track 2 -filled 0 -backcolor gray65 -text 360
    $w.zinc itemconfigure $track 3 -filled 0 -backcolor gray65 -text /
    $w.zinc itemconfigure $track 4 -filled 0 -backcolor gray65 -text 410
    $w.zinc itemconfigure $track 5 -filled 0 -backcolor gray65 -text Beacon

    $w.zinc add arc 1 {150 140 450 240} -fillcolor gray20 -filled 0 -linewidth 1 \
	-startangle 45 -extent 270
    $w.zinc add arc 1 {260 150 340 230} -fillcolor gray20 -filled 0 -linewidth 1 \
	-startangle 45 -extent 270 -pieslice 1 -closed 1 -linestyle mixed -linewidth 3

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {320 180} \
	-text {Two arcs, starting at 45° with an extent of 270°}


    $w.zinc add curve 1 {10 324 24 300 45 432 247 356 128 401} -filled 0 -relief roundgroove
    # -linewidth 10, ## BUG with zinc 3.2.3g

    $w.zinc add text 1 -font $defaultfont -text {An open curve} -anchor nw -position {50 350}

    $w.zinc add text 1 -font $defaultfont -text {A waypoint} -anchor nw -position {10 480}

    variable waypoint [$w.zinc add waypoint 1 6 -position {100 520} -labelformat $labelformat \
		      -symbol AtcSymbol2 -labeldistance 30]

    for {set fieldId 1} {$fieldId<=5} {incr fieldId} {
	$w.zinc itemconfigure $waypoint $fieldId -filled 0 -bordercolor DarkGreen \
	    -border contour -text "field$fieldId"
    }

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {510 380} \
	-text "3 tabulars of 2 fields,\nattached together."

    variable labelformat2 {x72x40 x72a0^0^0 x34a0^0>1}

    variable tabular1 [$w.zinc add tabular 1 6 -position {570 250} -labelformat $labelformat2]
    variable tabular2 [$w.zinc add tabular 1 6 -connecteditem $tabular1 -labelformat $labelformat2]
    variable tabular3 [$w.zinc add tabular 1 6 -connecteditem $tabular2 -labelformat $labelformat2]

    variable count 1

    foreach tab "$tabular1 $tabular2 $tabular3" {
	$w.zinc itemconfigure $tab 1 -filled 0 -bordercolor DarkGreen -border contour -text tabular
	$w.zinc itemconfigure $tab 2 -filled 0 -bordercolor DarkGreen -border contour -text "n°$count"
	incr count
    }

    $w.zinc add reticle 1 -position {530 550} -firstradius 20 -numcircles 6 \
	-period 2 -stepsize 20 -brightlinestyle dashed -brightlinecolor darkred

    $w.zinc add text 1 -font $defaultfont -text {a reticle with 6 circles} \
	-anchor nw -position {530 540}

    bind $w.zinc <ButtonPress-1> "::allItems::press $w.zinc motion %x %y"
    bind $w.zinc <ButtonRelease-1> "::allItems::release $w.zinc"

    variable curX 0
    variable curY 0

    proc press {z action x y} {
	variable curX
	variable curY

	set curX $x
	set curY $y
	bind $z <Motion> "::allItems::$action $z %x %y"
    }

    proc motion {z x y} {
	variable curX
	variable curY

	$z translate current [expr $x - $curX] [expr $y - $curY]
	set curX $x
	set curY $y
    }

    proc release {z} {
	bind $z <Motion> {}
    }
}

Added jni/tkzinc/demos/labelformat.tcl.











































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval labelFormat {
    variable w .labelformat
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Label Format Demonstration"
    wm iconname $w Label

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 4 \
              -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {This scipt demonstrates the use of labelformat for tabular items.
The fieldPos (please, refer to the labelformat type description
in the Zinc reference manual) of each field as described in
the labelformat is displayed inside the field.}
    $w.text configure -state disabled

    ###########################################
    # Zinc
    ###########################################
    grid [zinc $w.zinc -width 600 -height 500 -font $defaultfont -borderwidth 3 \
	      -relief sunken] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    ### this function displays in each field, the corresponding <fieldPos>
    ### part of the labelformat
    proc setLabelContent {item labelformat} {
	variable w
	set i 0
	foreach fieldSpec $labelformat {
	    set posSpec $i
	    regexp {^.\d+.\d+(.*)} $fieldSpec "" posSpec
	    $w.zinc itemconfigure $item $i -text "$i: $posSpec" -border "contour"
	    incr i
	}
    }

    ###########################################
    # Tabulars
    ###########################################

    ### first labelformat and tabular
    variable labelformat1 {x100x20+0+0 x100x20+100+0 x100x20+0+20 x100x20+100+20 x100x20+50+55}

    variable tabular1 [$w.zinc add tabular 1 5 -position {10 10} -labelformat $labelformat1]

    setLabelContent $tabular1 $labelformat1

    $w.zinc add text 1 -position {10 100} -text "All fields positions\nare given in pixels"

    ### second labelformat and tabular
    variable labelformat2 {x110x20+100+30 x80x20<0<0 x80x20<0>0 x80x20>0>0 x80x20>0<0}

    variable tabular2 [$w.zinc add tabular 1 5 -position {270 10} -labelformat $labelformat2]
    setLabelContent $tabular2 $labelformat2

    $w.zinc add text 1 -position {260 100} -text "All fields positions are given\nrelatively to field 0.\nThey are either on the left/right\nand up/down the field 0."

    ### third labelformat and tabular
    variable labelformat3 {x200x70+100+70 x80x26^0<0 x80x26^0>0 x80x29$0$0 x80x32$0^0 x90x20<1^1 x90x20<2$2 x90x20^4<4 x90x20^3>3}

    variable tabular3 [$w.zinc add tabular 1 9 -position {150 180} -labelformat $labelformat3]

    setLabelContent $tabular3 $labelformat3

    $w.zinc add text 1 -position {40 360} -text "Fields 1-4 are positionned relatively to field 0.\nField 5 is positionned relatively to field 1\nField 6 is positionned relatively to field 2..."
}

Added jni/tkzinc/demos/lines.tcl.















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval linesDemo {
    variable w .lines
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Lines Demonstration"
    wm iconname $w Lines

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    variable defaultfont {Helvetica -11}

    grid [zinc $w.zinc -width 700 -height 600 -font $defaultfont -borderwidth 3 \
	      -relief sunken] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    $w.zinc add text 1 -font $defaultfont -anchor nw -position {20 20} \
-text "A set of lines with different styles of lines and termination\nNB: some attributes such as line styles are not necessarily\navailable with an openGL rendering system"

    $w.zinc add curve 1 {20 100 320 100}
    $w.zinc add curve 1 {20 120 320 120} -linewidth 20

    $w.zinc add curve 1 {20 160 320 160} -linewidth 20 -capstyle butt

    $w.zinc add curve 1 {20 200 320 200} -linewidth 20 -capstyle projecting

    $w.zinc add curve 1 {20 240 320 240} -linewidth 20 -linepattern AlphaStipple7 -linecolor red

    # right column
    $w.zinc add curve 1 {340 100 680 100} -firstend {10 10 10} -lastend {10 25 45}

    $w.zinc add curve 1 {340 140 680 140} -linewidth 2 -linestyle dashed

    $w.zinc add curve 1 {340 180 680 180} -linewidth 4 -linestyle mixed

    $w.zinc add curve 1 {340 220 680 220} -linewidth 2 -linestyle dotted

    $w.zinc add curve 1 {20 300 140 360 320 300 180 260} -closed 1 -filled 1 -fillpattern "" \
	-fillcolor grey60 -linecolor red -marker AtcSymbol7 -markercolor blue

    $w.zinc add curve 1 {340 300 440 360 620 300 480 260} -closed 1 -linewidth 10 -joinstyle miter \
	-linecolor red

    $w.zinc add curve 1 {400 300 440 330 560 300 480 280} -closed 1 -linewidth 10 -joinstyle round \
	-tile "" -fillcolor grey60 -filled 1 -linecolor red
}

Added jni/tkzinc/demos/magicLens.tcl.























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#-----------------------------------------------------------------------------------
# MagicLens.tcl
#
#  This small demo shows the use of groups, transformations, clipping
#  gradients and multi-contour curves to produce a structured and non
#  trivial small application
#
#      Authors: Jean-Luc Vinot <vinot@cena.fr>
#		            Patrick Lecoanet (Translation to Tcl).
#
#-----------------------------------------------------------------------------------

if {![info exists zincDemo]} {
  error "This script should be run from the zinc-widget demo."
}

namespace eval magicLens {

  image create photo paper -data {
    R0lGODlhIAAgALMAAAAAAP///6ysrKKiogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAACH5BAAAAAAALAAAAAAgACAAAwSzUIgxpKzzTmqprximgRxpdaQ3ot0YZm8Gfyp8
    fhuYc9stXzxVqCTT2Wy6F1HZGyaPJRGwuIvOejfpMrgSxbBHDTXFihp/LW2V7EUxrVLkzLyU
    s4CpWJKHNffbaXI4LU1VhUJoRV5vTVtXOWVQgSaIXHF1hJWQlHF3aXo+NV1zLos/W08moaWP
    lp6Eo0Z8kGKpdrNZSLaruHV8e4e/RIYuV2eGT4Ktbr9/kpc7p6Wud4iNAhEAOw==
  }

  catch {font create magfont -family Helvetica -size -13 -weight bold}
  catch {font create nfont -family Helvetica -size -11 -weight normal}

  #
  # The basics colors, one per column.
  set basicColors {
    {Yellow {#fff52A} {#f1f1f1} {#6a6611}}
    {"Yellow\nOrange" {#ffc017} {#cfcfcf} {#6b510a}}
    {Orange {#ff7500} {#a5a5a5} {#622d00}}
    {Red {#ff2501} {#8b8b8b} {#620e00}}
    {Magenta {#ec145d} {#828282} {#600826}}
    {"Red\nViolet" {#a41496} {#636363} {#020940}}
    {"Violet\nBlue" {#6a25b6} {#555555} {#2a0f48}}
    {Blue {#324bde} {#646464} {#101846}}
    {Cyan {#0a74f0} {#818181} {#064a9a}}
    {"Green\nBlue" {#009bb4} {#969696} {#006474}}
    {Green {#0fa706} {#979797} {#096604}}
    {"Yellow\nGreen" {#9dd625} {#c9c9c9} {#496311}}
  }

  #
  # Compute a set of interpolated colors
  #
  proc CreateGraduate {steps color1 color2} {
    scan $color1 {#%2x%2x%2x} r1 g1 b1
    scan $color2 {#%2x%2x%2x} r2 g2 b2
    set colors [list]
    for {set i 0} {$i < $steps} {incr i} {
      set ratio [expr {$i/($steps-1.0)}]
      lappend colors [format {#%02x%02x%02x} \
                          [expr {$r1 + int(($r2 - $r1) * $ratio)}] \
                          [expr {$g1 + int(($g2 - $g1) * $ratio)}] \
                          [expr {$b1 + int(($b2 - $b1) * $ratio)}]]
    }
    return $colors
  }

  set dx 0
  set dy 0
  set zoom 1.20
  set width 1000
  set height 900
  set simpleLens 1

  variable w .magicLens
  catch {destroy $w}
  toplevel $w
  wm title $w "Color Magic Lens Demonstration"
  wm iconname $w magicLens

  grid [button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
  grid [button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10
  #
  # Create a Zinc instance
  grid [zinc $w.zinc -render 1 -width $width -height $height -borderwidth 0 \
         -tile paper -backcolor {#cccccc}] -row 0 -column 0 -columnspan 2 -sticky ew
  #
  # The main view. The unzoomed world is here.
  $w.zinc add group 1 -tags normview
  #
  # The hidden view. It holds the hidden world.
  # It is clipped by the lens shape.
  $w.zinc add group 1 -tags hiddenview
  #
  # Create the lens itself. It is made of an atomic
  # group, a back to catch the mouse events and a
  # border. The back is not visible but remain sensitive.
  if { $simpleLens } {
    $w.zinc add arc 1 {{-100 -100} {100 100}} -tags {lens lensback} \
          -linewidth 2 -linecolor {#222266;80} -filled 1 -fillcolor {#ffffff;0}
  } {
    $w.zinc add group 1 -atomic yes -tags lens
    $w.zinc add arc lens {{-100 -100} {100 100}} -tags lensborder -linewidth 2 \
        -linecolor {#222266;80}
    $w.zinc clone lensborder -filled yes -visible no -tags lensback
  }
  #
  # Add the clipping shape to the hidden view so that we can view
  # the magnified view only within the lens.
  $w.zinc clone lensback -visible yes -filled yes -tile paper \
       -fillcolor {#ffffff;100} -tags {lens lenszone}
  $w.zinc chggroup lenszone hiddenview true
  $w.zinc itemconfigure hiddenview -clip lenszone
  #
  # The zoomed view is inside the hidden view.
  $w.zinc add group hiddenview -tags magview
  $w.zinc scale magview $zoom $zoom
  #
  # Create the vertical color stripes in both normal and magnified views.
  # In the normal view multi-contours curves are used, they are filled
  # with vertical axial gradients. In the magnified view arc items are
  # used filled with solid colors.
  set x 60
  foreach colorDesc $basicColors {
    #
    # Color Description : name, Saturated, Unsaturated, Shadow
    foreach {colorName satColor greyColor shadColor} $colorDesc break
    #
    # Add a group in each view
    set normGroup [$w.zinc add group normview]
    $w.zinc translate $normGroup $x 60 yes
    set magGroup [$w.zinc add group magview]
    $w.zinc translate $magGroup $x 60 yes
    #
    # Reference color on a ball shaped item.
    set refBall [$w.zinc add arc $normGroup {{-30 -30} {30 30}} \
          -fillcolor "=radial -12 -20|white 0|$satColor 40|$shadColor 100" \
          -linewidth 2 -filled 1]
    #
    # Clone the reference ball and move it into the magview group
    $w.zinc chggroup [$w.zinc clone $refBall] $magGroup
    #
    # Add the color name in magview
    $w.zinc add text $magGroup -text $colorName -anchor center \
         -alignment center -font magfont -spacing 2
    #
    # Create the color samples (Multi contours curve)
    set gradientBar [$w.zinc add curve $normGroup {} -linewidth 2 \
         -filled 1 -fillcolor "=axial 270|$satColor|$greyColor"]
    #
    # Create intermediate steps between colors (saturated -> unsaturated)
    set c 0
    foreach color [CreateGraduate 11 $satColor $greyColor] {
      # Create a zinc item for the color
      set sample [$w.zinc clone $refBall -fillcolor $color]
      $w.zinc translate $sample 0 [expr {65*($c+1)}]
      #
      # Add its shape to the multi-contours gradient bar
      $w.zinc contour $gradientBar add 1 $sample
      #
      # Move the item to the maggroup
      $w.zinc chggroup $sample $magGroup
      #
      # Text of label Saturation % + Color.
      set sampleText [$w.zinc add text $magGroup -text "[expr {((10 - $c)*10)}]%\n$color" \
          -anchor center -alignment center -font nfont -composescale no]
      $w.zinc translate $sampleText 0 [expr {65*($c+1)}]
      incr c
    }
    incr x 80
  }
  #
  # Add the caption text.
  $w.zinc add text normview -position {30 840} -font nfont -tags blurb -color white \
      -text "Move the Magic Lens on a color to see the color value and saturation"
  $w.zinc chggroup [$w.zinc clone blurb -font magfont] magview
  #
  # Lens motion callback proc.
  proc LensMove {x y} {
    variable w
    variable zoom
    $w.zinc translate lens $x $y yes
    $w.zinc translate magview [expr {$x * (1-$zoom)}]  [expr {$y * (1-$zoom)}] yes
  }
  #
  # The bindings needed to drag the lens.
  $w.zinc bind lens <B1-Motion> {::magicLens::LensMove %x %y}
  #
  # Lets put the lens somewhere within the window area.
  LensMove 300 110
}

Added jni/tkzinc/demos/pathTags.tcl.































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#!/usr/bin/perl -w
# $Id$
# this pathtatg demo have been developped by C. Mertz mertz@cena.fr
# with the help of Daniel Etienne etienne@cena.fr.
# tcl version by Patrick Lecoanet lecoanet@cena.fr


if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval pathTags {
    variable w .pathTags
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Path tags Demonstration"
    wm iconname $w "Path tags"

    variable defaultFont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 3 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 3 -column 1 -pady 10

    ## this demo demonstrates the use of path tags to address one or more items
    ## belonging to a hierarchy of groups.
    ## This hierarchy is described just below gr_xxx designates a group
    ## (with a tag xxx and i_yyy designates an non-group item (with a tag yyy .

    #  gr_top --- gr_a --- gr_aa --- gr_aaa --- gr_aaaa --- i_aaaaa
    #          |       |         |          |-- i_aaab  |-- i_aaaab
    #          |       |         -- i_aab
    #          |       |-- i_ab
    #          |       |
    #          |       ---gr_ac --- i_aca
    #          |                |
    #          |-- i_b          --- i_acb
    #          |
    #          --- gr_c --- gr_ca --- i_caa
    #                   |         |
    #                   |         --- i_cab
    #                   |-- i_cb
    #                   |
    #                   ---gr_cc --- i_cca
    #                            |
    #                            --- i_ccb
    #the same objects are cloned and put in an other hierarchy where
    #grTop is replaced by grOtherTop

    variable defaultForeColor grey80
    variable selectedColor yellow

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 5 -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {This represents a group hierarchy:
    - groups are represented by a rectangle and an underlined title.
    - non-group items are represented by a text.
Select a pathTag or a tag with one of the radio-button
or experiment your own tags in the input field}
    $w.text configure -state disabled

    ###########################################
    # Zinc creation
    ###########################################

    grid [zinc $w.zinc -width 850 -height 360 -font $defaultFont -borderwidth 0 \
	-backcolor black -forecolor $defaultForeColor] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    ###########################################
    # Creation of a bunch of radiobutton and a text input
    ###########################################

    variable pathtag {}
    variable explanation {...}

    grid [frame $w.toggles] -row 2 -column 0 -columnspan 2 -sticky w

    variable tagsExpl {
	top {a simple tag matching the top group}
	.top {all items with tag 'top' in the root group }
	.top. {direct children of a group with tag 'top' in the root group}
	.top* {descendents of a group with tag 'top' in the root group }
	.top*cca {items with a tag 'cca' in a direct group of root group with tag 'top'}
	.5. {direct content of the group with id 5}
	.top*aa {items with a tag 'aa' in a direct group of root group with tag 'top'}
	.top*aa. {direct children of a group with a tag 'aa', descending from a direct group of root group with tag 'top'}
	.top*aa* {descendance of a group with a tag 'aa', descending from a direct group of root group with tag 'top'}
	.top.a {items with a tag 'a' in a direct group of root group with tag 'top'}
	.top.a. {direct children of a group with tag 'a' in a direct group of root group with tag 'top'}
	.5* {descendents of the group of id 5}
	.top*aa*aaa {all items with tag 'aaa' descending from a group with tag 'aa' descending from a group with tag 'top', child of the root group}
	.top*aa*aaa. {children of a group with a tag 'aaa' descending from ONE group with a tag 'aa' descending from a group with a tag 'top' child of the root group}
	.top*aa*aaa* {descendance of ONE group with a tag 'aaa' descending from ONE group with a tag 'aa' descending from ONE group with a tag 'top' child of the root group}
	.other_top*aa* {descendance of ONE group with a tag 'aa' descending from ONE group with a tag 'other_top' child of the root group}
	.5*ca* {descendance of ONE group with a tag 'ca' descending from THE group with id 5}
	*aa*aaaa {all items with a tag 'aaaa' descending from a group with a tag 'aa'}
	*aaa {all items with a tag 'aaa'}
	aa||ca {items with tag 'aa' or tag 'ca'}
	none {no items, as none has the tag 'none'}
	all {all items}
    }

    variable row 1
    variable col 2
    foreach {key val} $tagsExpl {
	grid [ttk::radiobutton $w.toggles.r$row+$col -text $key \
		  -command ::pathTags::displayPathtag -variable ::pathTags::pathtag \
		  -value $key] -column $col -row $row -sticky w -pady 0 -ipady 0
	incr row
	if {$row > 6} {
	    set row 1
	    incr col
	}
    }

    grid [label $w.toggles.lyt -relief flat \
	      -text {your own tag:}] -column 2 -row 7 -sticky e -ipady 5
    grid [entry $w.toggles.eyt -width 15 \
	      -textvariable ::pathTags::pathtag] -column 3 -row 7 -sticky w
    bind $w.toggles.eyt <Return> ::pathTags::displayPathtag
    grid [label $w.toggles.elabel -text "explanation:"] \
	-row 8 -column 2 -sticky e
    grid [label $w.toggles.explan -width 70 -height 3 \
	      -justify left -anchor w -wraplength 16c -textvariable explanation] \
	-row 8 -column 3 -columnspan 4 -sticky w
    grid columnconfigure $w.toggles 5 -weight 10


    ### Here we create the genuine hierarchy of groups and items
    ### Later we will create graphical objects to display groups
    proc createSubHierarchy {gr} {
	variable w

	$w.zinc add group $gr -tags a
	$w.zinc add text $gr -tags {b text} -text b -position {270 150}
	$w.zinc add group $gr -tags c

	$w.zinc add group a -tags aa
	$w.zinc add text a -tags {ab text} -text ab -position {60 220}
	$w.zinc add group a -tags ac

	$w.zinc add group aa -tags aaa
	$w.zinc add text aa -tags {aab text} -text aab -position {90 190}
	$w.zinc add group aaa -tags aaaa
	$w.zinc add text aaaa -tags {aaaaa text} -text aaaaa -position {150 110}
	$w.zinc add text aaaa -tags {aaaab text} -text aaaab -position {150 130}
	$w.zinc add text aaa -tags {aaab text} -text aaab -position {120 160}

	$w.zinc add text ac -tags aca -text aca -position {90 260}
	$w.zinc add text ac -tags {acb text} -text acb -position {90 290}

	$w.zinc add group c -tags ca
	$w.zinc add text c -tags {cb text} -text cb -position {330 160}
	$w.zinc add group c -tags cc

	$w.zinc add text ca -tags {caa text} -text caa -position {360 110}
	$w.zinc add text ca -tags {cab text} -text cab -position {360 130}

	$w.zinc add text cc -tags {cca text} -text cca -position {360 200}
	$w.zinc add text cc -tags {ccb text} -text ccb -position {360 220}
    }

    # creating the item hierarchy
    $w.zinc add group 1 -tags top
    createSubHierarchy top

    # creating a parallel hierarchy
    $w.zinc add group 1 -tags other_top
    createSubHierarchy other_top

    ## modifying the priority so that all rectangles and text will be visible
    foreach item [$w.zinc find withtype text ".top*"] {
	$w.zinc itemconfigure $item -priority 20
    }
    foreach item [$w.zinc find withtype text ".other_top*"] {
	$w.zinc itemconfigure $item -priority 20
    }
    foreach item [$w.zinc find withtype group ".top*"] {
	$w.zinc itemconfigure $item -priority 20
    }
    foreach item [$w.zinc find withtype group ".other_top*"] {
	$w.zinc itemconfigure $item -priority 20
    }

    # converts a list of items ids in a list of sorted tags (the first tag of each item)
    proc items2tags {items} {
	variable w

	set selectedTags {}
	foreach item $items {
	    set tags [$w.zinc itemcget $item -tags]
	    if {[regexp {frame|title} [lindex $tags 0]]} {
		# to remove group titles frame
		continue
	    }
	    lappend selectedTags [lindex tags 0]
	}
	return [lsort $selectedTags]
    }

    ### drawing :
    ####   a rectangle item for showing the bounding box of each group
    ###    a text item for the group name (i.e. its first tag)

    ## backgrounds used to fill rectangles representing groups
    variable backgrounds {grey25 grey35 grey43 grey50 grey55}

    proc drawHierarchy {group level} {
	variable w
	variable backgrounds

	set tags [$w.zinc gettags $group]
	#    print "level=$level (" $tags[0],")\n";
	foreach g [$w.zinc find withtype group .$group.] {
	    drawHierarchy $g [expr $level + 1]
	}
	foreach {x y x2 y2} [$w.zinc bbox $group] break
	$w.zinc add text $group -position [list [expr $x-5] [expr $y-4]] \
	    -text [lindex $tags 0] -anchor w -alignment left -underlined 1 \
	    -priority 20 -tags [list title_[lindex $tags 0] group_title]
	foreach {x y x2 y2} [$w.zinc bbox $group] break
	if {$x ne "" } {
	    $w.zinc add rectangle $group [list [expr $x+0] [expr $y+5] \
					      [expr $x2+5] [expr $y2+2]] \
		-filled 1 -fillcolor [lindex $backgrounds $level] -priority $level \
		-tags [list frame_[lindex $tags 0] group_frame]
	} else {
	    puts "undefined bbox for $group : $tags"
	}
    }

    ### this sub extracts out of groups both text and frame representing
    ### each group. This is necessary to avoid unexpected selection of
    ### rectangles and titles inside groups
    proc extractTextAndFrames { } {
	variable w

	foreach group_title [$w.zinc find withtag group_title||group_frame] {
	    set ancestors [$w.zinc find ancestor $group_title]
	    #	puts "$group_title $ancestors"
	    set grandFather [lindex $ancestors 1]
	    $w.zinc chggroup $group_title $grandFather 1
	}
    }

    proc TLGet {list tag {default ""}} {
	foreach {key val} $list {
	    if { [string compare $key $tag] == 0 } {
		return $val
	    }
	}
	return $default
    }

    ## this sub modifies the color/line color of texts and rectangles
    ## representing selected items.
    proc displayPathtag { } {
	variable w
	variable explanation
	variable pathtag
	variable defaultForeColor
	variable selectedColor
	variable tagsExpl

	if {[catch {set explanation [TLGet $tagsExpl $pathtag]}]} {
	    set explanation {sorry, I am not smart enough to explain your pathTag ;-\)}
	}
	set selected [$w.zinc find withtag $pathtag]
	set tags [items2tags $selected]
	#    puts "selected: $tags"

	## unselecting all items
	foreach item [$w.zinc find withtype text] {
	    $w.zinc itemconfigure $item -color $defaultForeColor
	}
	foreach item [$w.zinc find withtype rectangle] {
	    $w.zinc itemconfigure $item -linecolor $defaultForeColor
	}

	## highlighting selected items
	foreach item $selected {
	    set type [$w.zinc type $item]
	    #puts "$item $type [$w.zinc gettags $item]"
	    if {$type eq "text"} {
		$w.zinc itemconfigure $item -color $selectedColor
	    } elseif {$type eq "rectangle"} {
		$w.zinc itemconfigure $item -linecolor $selectedColor
	    } elseif {$type eq "group"} {
		set tag [lindex [$w.zinc gettags $item] 0]
		## as there is 2 // hierachy we must refine the tag used
		## to restrict to the proper hierarchy
		## NB: this is due to differences between the group hierarchy
		##     and the graphical object hierarchy used for this demo
		if {[llength [$w.zinc find ancestors $item top]]} {
		    $w.zinc itemconfigure ".top*frame_$tag" -linecolor $selectedColor
		    $w.zinc itemconfigure ".top*title_$tag" -color $selectedColor
		} elseif {[llength [$w.zinc find ancestors $item other_top]]} {
		    $w.zinc itemconfigure ".other_top*frame_$tag" -linecolor $selectedColor
		    $w.zinc itemconfigure ".other_top*title_$tag" -color $selectedColor
		} else {
		    $w.zinc itemconfigure "frame_$tag" -linecolor $selectedColor
		    $w.zinc itemconfigure "title_$tag" -color $selectedColor
		}
	    }
	}
    }

    drawHierarchy top 0
    drawHierarchy other_top 0
    $w.zinc translate other_top 400 0
    extractTextAndFrames
}

Added jni/tkzinc/demos/photoAlpha.tcl.























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# $Id$
# this simple demo has been developped by P.Lecoanet <lecoanet@cena.fr>

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval photoAlpha {
    package require Img

    variable girl [image create photo -file [file join $::zinc_demos images photoAlpha.png]]
    variable texture [image create photo -file [file join $::zinc_demos images stripped_texture.gif]]

    variable w .photoAlpha
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc photo transparency Demonstration"
    wm iconname $w photoAlpha

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 7 \
              -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {This demo needs openGL for displaying the photo
with transparent pixels and for rescaling/rotating.
You can transform this png photo with your mouse:
Drag-Button 1 for moving the photo,
Drag-Button 2 for zooming the photo,
Drag-Button 3 for rotating the photo,
Shift-Drag-Button 1 for modifying the global photo transparency.}
    $w.text configure -state disabled

    ###########################################
    # Zinc
    ###########################################
    zinc $w.zinc -width 350 -height 250 -render 1 -font $defaultfont \
	    -borderwidth 3 -relief sunken -tile $texture
    grid $w.zinc -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    variable topGroup [$w.zinc add group 1]

    variable girlItem [$w.zinc add icon $topGroup -image $girl \
			   -composescale 1 -composerotation 1]

    #
    # Controls for the window transform.
    #
    bind $w.zinc <ButtonPress-1>  "::photoAlpha::press motion %x %y"
    bind $w.zinc <ButtonRelease-1>  ::photoAlpha::release
    bind $w.zinc <ButtonPress-2>  "::photoAlpha::press zoom %x %y"
    bind $w.zinc <ButtonRelease-2>  ::photoAlpha::release
    bind $w.zinc <ButtonPress-3>  "::photoAlpha::press mouseRotate %x %y"
    bind $w.zinc <ButtonRelease-3>  ::photoAlpha::release

    #
    # Controls for alpha and gradient
    #
    bind $w.zinc <Shift-ButtonPress-1> "::photoAlpha::press modifyAlpha %x %y"
    bind $w.zinc <Shift-ButtonRelease-1> ::photoAlpha::release

    variable curX 0
    variable curY 0
    variable curAngle 0

    proc press {action x y} {
	variable w
	variable curAngle
	variable curX
	variable curY

	set curX $x
	set curY $y
	set curAngle [expr atan2($y, $x)]
	bind $w.zinc <Motion> "::photoAlpha::$action %x %y"
    }

    proc motion {x y} {
	variable w
	variable topGroup
	variable curX
	variable curY

	foreach {x1 y1 x2 y2} [$w.zinc transform $topGroup \
				   [list $x $y $curX $curY]] break
	$w.zinc translate $topGroup [expr $x1 - $x2] [expr $y1 - $y2]
	set curX $x
	set curY $y
    }

    proc zoom {x y} {
	variable w
	variable topGroup
	variable curX
	variable curY

	if {$x > $curX} {
	    set maxX $x
	} else {
	    set maxX $curX
	}
	if {$y > $curY} {
	    set maxY $y
	} else {
	    set maxY $curY
	}
	if {($maxX == 0) || ($maxY == 0)} {
	    return;
	}
	set sx [expr 1.0 + (double($x - $curX) / $maxX)]
	set sy [expr 1.0 + (double($y - $curY) / $maxY)]
	$w.zinc scale $topGroup $sx $sx

	set curX $x
	set curY $y
    }

    proc mouseRotate {x y} {
	variable w
	variable curAngle
	variable topGroup

	set lAngle [expr atan2($y, $x)]
	$w.zinc rotate $topGroup [expr $lAngle - $curAngle]
	set curAngle  $lAngle
    }

    proc release {} {
	variable w

	bind $w.zinc <Motion> {}
    }

    proc modifyAlpha {x y} {
	variable w
	variable topGroup

	set xRate [expr double($x) / [$w.zinc cget -width]]
	set xRate [expr ($xRate < 0) ? 0 : ($xRate > 1) ? 1 : $xRate]
	set alpha [expr int($xRate * 100)]

	$w.zinc itemconfigure $topGroup -alpha $alpha
    }
}

Added jni/tkzinc/demos/reliefs.tcl.













































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# $Id$
# this simple demo has been developped by P.Lecoanet <lecoanet@cena.fr>

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval reliefDemo {
    variable w .reliefs
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Relief Testbed"
    wm iconname $w reliefs

    variable allReliefs {flat raised sunken groove ridge \
			roundraised roundsunken roundgroove roundridge \
			sunkenrule raisedrule}

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 8 -width 50 \
              -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {This demo lets you play with the various relief parameters
on rectangles polygons and arcs. Some reliefs and The smooth relief
capability is only available with openGL.
You can modify the items with your mouse:

  Drag-Button 1 for moving    Ctrl/Shft-Button 1 for Incr/Decr sides
  Drag-Button 2 for zooming   Ctrl/Shft-Button 2 for cycling reliefs
  Drag-Button 3 for rotating  Ctrl/Shft-Button 3 for Incr/Decr border}
    $w.text configure -state disabled

    ###########################################
    # Zinc
    ###########################################
    proc deg2Rad {deg} {
	return [expr 3.14159 * $deg / 180.0]
    }

    proc rad2Deg {rad} {
	return [expr int(fmod(($rad * 180.0 / 3.14159)+360.0, 360.0))]
    }

    variable bw 4
    variable width 60
    variable lightAngle 120
    variable lightAngleRad [deg2Rad $lightAngle]
    variable zincSize 500

    grid [zinc $w.zinc -width $zincSize -height $zincSize -render 1 \
        -font $defaultfont \
	-highlightthickness 0 -borderwidth 0 -relief sunken -backcolor lightgray \
	-lightangle $lightAngle] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    variable topGroup [$w.zinc add group 1]

    proc polyPoints { ox oy rad n } {
	set step [expr 2 * 3.14159 / $n]
	for {set i 0} {$i < $n} {incr i} {
	    set x [expr $ox + ($rad * cos($i * $step))];
	    set y [expr $oy + ($rad * sin($i * $step))];
	    lappend coords $x $y;
	}
	lappend coords [lindex $coords 0] [lindex $coords 1]
	return $coords
    }

    proc makePoly {x y bw sides color group} {
	variable w
	variable state
	variable allReliefs
	variable width

	set relief 2

	set g [$w.zinc add group $group]
	$w.zinc translate $g $x $y
	$w.zinc add curve $g [polyPoints 0 0 $width $sides] \
	    -relief [lindex $allReliefs $relief] -linewidth $bw \
	    -smoothrelief 1 -fillcolor $color -linecolor $color \
	    -filled t -tags {subject polygon}
	$w.zinc add text $g -anchor center \
	    -text [lindex $allReliefs $relief] -tags {subject relief}
	$w.zinc add text $g -anchor center -position {0 16} \
	    -text $bw -tags {subject bw}
	set state($g,sides) $sides
	set state($g,relief) $relief
	set state($g,bw) $bw
	return $g
    }

    variable poly [makePoly 100 100 $bw 8 lightblue $topGroup]
    variable poly [makePoly [expr 100 + 2*($width + 10)] 100 $bw 8 tan $topGroup]
    variable poly [makePoly [expr 100 + 4*($width + 10) ] 100 $bw 8 slateblue $topGroup]

    proc lightCenter {radius angle} {
	return [list [expr $radius * (1 + 0.95*cos($angle))] \
		    [expr $radius * (1 - 0.95*sin($angle))]]
    }

    #
    # Place the light at lightAngle on the circle
    $w.zinc add arc 1 {-5 -5 5 5} -filled 1 -fillcolor yellow \
	-tags light -priority 10
    eval "$w.zinc translate light [lightCenter [expr $zincSize/2] $lightAngleRad]"

    #
    # Controls.
    #
    $w.zinc bind subject <ButtonPress-1>  "::reliefDemo::press motion %x %y"
    $w.zinc bind subject <ButtonRelease-1>  ::reliefDemo::release
    $w.zinc bind subject <ButtonPress-2>  "::reliefDemo::press zoom %x %y"
    $w.zinc bind subject <ButtonRelease-2>  ::reliefDemo::release
    $w.zinc bind subject <ButtonPress-3>  "::reliefDemo::press mouseRotate %x %y"
    $w.zinc bind subject <ButtonRelease-3>  ::reliefDemo::release

    $w.zinc bind polygon <Shift-ButtonPress-1>  "::reliefDemo::incrPolySides 1"
    $w.zinc bind polygon <Control-ButtonPress-1>  "::reliefDemo::incrPolySides -1"

    $w.zinc bind subject <Shift-ButtonPress-2>  "::reliefDemo::cycleRelief 1"
    $w.zinc bind subject <Control-ButtonPress-2>  "::reliefDemo::cycleRelief -1"

    $w.zinc bind subject <Shift-ButtonPress-3>  "::reliefDemo::incrBW 1"
    $w.zinc bind subject <Control-ButtonPress-3>  "::reliefDemo::incrBW -1"

    $w.zinc bind light <ButtonPress-1>  "::reliefDemo::press lightMotion %x %y"
    $w.zinc bind light <ButtonRelease-1>  ::reliefDemo::release

    variable curX 0
    variable curY 0
    variable curAngle 0

    proc press {action x y} {
	variable w
	variable curAngle
	variable curX
	variable curY

	$w.zinc raise [$w.zinc group current]

	set curX $x
	set curY $y
	set curAngle [expr atan2($y, $x)]
	bind $w.zinc <Motion> "::reliefDemo::$action %x %y"
    }

    proc motion {x y} {
	variable w
	variable curX
	variable curY
	variable topGroup

	foreach {x1 y1 x2 y2} [$w.zinc transform $topGroup \
				   [list $x $y $curX $curY]] break
	$w.zinc translate [$w.zinc group current] [expr $x1 - $x2] [expr $y1 - $y2]
	set curX $x
	set curY $y
    }

    proc lightMotion {x y} {
	variable w
	variable zincSize
	variable topGroup

	set radius [expr $zincSize/2]
	if { $x < 0 } {
	    set x 0
	} elseif { $x > $zincSize } {
	    set x $zincSize
	}

	set angle [expr acos(double($x-$radius)/$radius)]
	if { $y > $radius } {
	    set angle [expr - $angle]
	}
	$w.zinc treset light
	eval "$w.zinc translate light [lightCenter [expr $zincSize/2] $angle]"
	$w.zinc configure -lightangle [rad2Deg $angle]
    }

    proc zoom {x y} {
	variable w
	variable curX
	variable curY

	if {$x > $curX} {
	    set maxX $x
	} else {
	    set maxX $curX
	}
	if {$y > $curY} {
	    set maxY $y
	} else {
	    set maxY $curY
	}
	if {($maxX == 0) || ($maxY == 0)} {
	    return;
	}
	set sx [expr 1.0 + (double($x - $curX) / $maxX)]
	set sy [expr 1.0 + (double($y - $curY) / $maxY)]
	$w.zinc scale current $sx $sx

	set curX $x
	set curY $y
    }

    proc mouseRotate {x y} {
	variable w
	variable curAngle

	set lAngle [expr atan2($y, $x)]
	$w.zinc rotate current [expr $lAngle - $curAngle]
	set curAngle  $lAngle
    }

    proc release {} {
	variable w

	bind $w.zinc <Motion> {}
    }

    proc incrPolySides {incr} {
	variable w
	variable state
	variable width

	set g [$w.zinc group current]
	incr state($g,sides) $incr
	if { $state($g,sides) < 3 } {
	    set state($g,sides) 3
	}

	set points [polyPoints 0 0 $width $state($g,sides)]
	$w.zinc coords $g.polygon $points
    }

    proc cycleRelief {incr} {
	variable w
	variable state
	variable allReliefs

	set g [$w.zinc group current]
	incr state($g,relief) $incr
	if { $state($g,relief) < 0 } {
	    set state($g,relief) [expr [llength $allReliefs] - 1]
	} elseif { $state($g,relief) >= [llength $allReliefs] } {
	    set state($g,relief) 0
	}
	set rlf [lindex $allReliefs $state($g,relief)]
	$w.zinc itemconfigure $g.polygon -relief $rlf
	$w.zinc itemconfigure $g.relief -text $rlf
    }

    proc incrBW {incr} {
	variable w
	variable state

	set g [$w.zinc group current]
	incr state($g,bw) $incr
	if { $state($g,bw) < 0 } {
	    set state($g,bw) 0
	}
	$w.zinc itemconfigure $g.polygon -linewidth $state($g,bw)
	$w.zinc itemconfigure $g.bw -text $state($g,bw)
    }
}

Added jni/tkzinc/demos/simpleInteractionTrack.tcl.



















































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval simpleInteractionTrack {
    variable w .simpleInteractionTrack
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Track Interaction Demonstration"
    wm iconname $w TrackInteraction

    set defaultfont {Helvetica -11}
    set labelfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Zinc
    ###########################################
    grid [zinc $w.zinc -width 600 -height 500 -font $labelfont -borderwidth 0] \
	-row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2


    # The explanation displayed when running this demo
    $w.zinc add text 1 -position {10 10} -text {This toy application shows some interactions on
differnet parts of a flight track item.
The following operations are possible:
    - Drag Button 1 on the track to move it.
      Please Note the position history past positions
    - Enter/Leave flight label fields
    - Enter/Leave the speedvector symbol i.e. current
      position label leader} -font $defaultfont

    ###########################################
    # Track
    ###########################################

    #the label format 6 formats for 6 fields#
    variable labelformat {x90x55+0+0 a0a0^0^0 a0a0^0>1 a0a0>2>1 a0a0>3>1 a0a0^0>2}

    #the track#
    variable x 250
    variable y 200
    variable xi 0
    variable yi 0
    variable track [$w.zinc add track 1 6 -labelformat $labelformat -position "$x $y" \
			-speedvector {30 -15} -markersize 10]

    # moving the track to display past positions
    for {set i 0} {$i<=5} {incr i} {
	$w.zinc coords $track [list [expr $x+$i*10] [expr $y-$i*5]]
    }

    #fields of the label#
    $w.zinc itemconfigure $track 0 -filled 0 -bordercolor DarkGreen -border contour
    $w.zinc itemconfigure $track 1 -filled 1 -backcolor gray60 -text AFR6128

    $w.zinc itemconfigure $track 2 -filled 0 -backcolor gray65 -text 390

    $w.zinc itemconfigure $track 3 -filled 0 -backcolor gray65 -text /

    $w.zinc itemconfigure $track 4 -filled 0 -backcolor gray65 -text 350

    $w.zinc itemconfigure $track 5 -filled 0 -backcolor gray65 -text TUR

    ###########################################
    # Events on the track
    ###########################################
    #---------------------------------------------
    # Enter/Leave a field of the label of the track
    #---------------------------------------------

    for {set field 0} {$field<=5} {incr field} {
	#Entering the field $field higlights it#
	$w.zinc bind $track:$field <Enter> "::simpleInteractionTrack::highlightEnter $field"
	#Leaving the field cancels the highlight of $field#
	$w.zinc bind $track:$field <Leave> "::simpleInteractionTrack::highlightLeave $field"
    }

    proc highlightEnter {field} {
	if {$field == 0} {
	    highlightLabelOn
	} else {
	    highlightFieldsOn $field
	}
    }

    proc highlightLeave {field} {
	if {$field == 0} {
	    highlightLabelOff
	} else {
	    if {$field == 1} {
		highlightField1Off
	    } else {
		highlightOtherFieldsOff $field
	    }
	}
    }

    #fonction#
    proc highlightLabelOn {} {
	variable w
	$w.zinc itemconfigure current 0 -filled 0 -bordercolor red -border contour
    }

    proc highlightLabelOff {} {
	variable w
	$w.zinc itemconfigure current 0 -filled 0 -bordercolor DarkGreen -border contour
    }

    proc highlightFieldsOn {field} {
	variable w
	$w.zinc itemconfigure current $field -border contour -filled 1 -color white
    }

    proc highlightField1Off {} {
	variable w
	$w.zinc itemconfigure current 1 -border "" -filled 1 -color black -backcolor gray60
    }

    proc highlightOtherFieldsOff {field} {
	variable w
	$w.zinc itemconfigure current $field -border "" -filled 0 -color black -backcolor gray65
    }

    #---------------------------------------------
    # Enter/Leave other parts of the track
    #---------------------------------------------
    $w.zinc bind $track:position <Enter> "$w.zinc itemconfigure $track -symbolcolor red"
    $w.zinc bind $track:position <Leave> "$w.zinc itemconfigure $track -symbolcolor black"
    $w.zinc bind $track:speedvector <Enter> "$w.zinc itemconfigure $track -speedvectorcolor red"
    $w.zinc bind $track:speedvector <Leave> "$w.zinc itemconfigure $track -speedvectorcolor black"
    $w.zinc bind $track:leader <Enter> "$w.zinc itemconfigure $track -leadercolor red"
    $w.zinc bind $track:leader <Leave> "$w.zinc itemconfigure $track -leadercolor black"

    #---------------------------------------------
    # Drag and drop the track
    #---------------------------------------------
    #Binding to ButtonPress event -> "moveOn" state#
    $w.zinc bind $track <1> {
	::simpleInteractionTrack::selectColorOn
	::simpleInteractionTrack::moveOn %x %y
    }

    bind $w.zinc <greater> {
      %W itemconfigure $::simpleInteractionTrack::track -labelangle \
          [expr 10 + [%W itemcget $::simpleInteractionTrack::track -labelangle]]
    }
    bind $w.zinc <less> {
      %W itemconfigure $::simpleInteractionTrack::track -labelangle \
          [expr 10 - [%W itemcget $::simpleInteractionTrack::track -labelangle]]
    }
    focus $w.zinc

    #"moveOn" state#
    proc moveOn {x y} {
	variable track
	variable w
	variable xi
	variable yi

	set xi $x
	set yi $y

	#ButtonPress event not allowed on track
	$w.zinc bind $track <ButtonPress-1> ""
	#Binding to Motion event -> move the track#
	$w.zinc bind $track <Motion> "::simpleInteractionTrack::bindMotion %x %y"

	#Binding to ButtonRelease event -> "moveOff" state#
	$w.zinc bind $track <ButtonRelease-1> {
	    ::simpleInteractionTrack::selectColorOff
	    ::simpleInteractionTrack::moveOff
	}
    }

    proc bindMotion { x y} {
	variable xi
	variable yi

	move $xi $yi $x $y

	set xi $x
	set yi $y
    }

    #"moveOff" state#
    proc moveOff {} {
	variable track
	variable w
	#Binding to ButtonPress event -> "moveOn" state#
	$w.zinc bind $track <ButtonPress-1> {
	    ::simpleInteractionTrack::selectColorOn
	    ::simpleInteractionTrack::moveOn %x %y
	}

	#Motion event not allowed on track
	$w.zinc bind $track <Motion> ""
	#ButtonRelease event not allowed on track
	$w.zinc bind $track <ButtonRelease-1> ""
    }

    #move the track#
    proc move {xi yi x y} {
	variable w
	variable track

	selectColorOn
	foreach {X1 Y1} [$w.zinc coords $track] break
	$w.zinc coords $track [list [expr $X1+$x-$xi] [expr $Y1+$y-$yi]]
    }

    proc selectColorOn {} {
	variable track
	variable w

	$w.zinc itemconfigure $track -speedvectorcolor white -markercolor white -leadercolor white
    }

    proc selectColorOff {} {
	variable track
	variable w

	$w.zinc itemconfigure $track -speedvectorcolor black -markercolor black -leadercolor black
    }
}

Added jni/tkzinc/demos/simpleRadar.tcl.









































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# $Id$
# This simple radar has been initially developped by P. Lecoanet <lecoanet@cena.fr>
# It has been adapted by C. Mertz <mertz@cena.fr> for demo purpose.

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval simpleRadar {
    variable rotation 0
    variable w .simpleRadar
    catch {destroy $w}
    toplevel $w
    wm title $w "Simple radar display"
    wm iconname $w SimpleRadar

    text $w.text -relief sunken -borderwidth 2 -height 3 -font TkDefaultFont
    pack $w.text -expand yes -fill both

    $w.text insert end {This a very simple radar display, where you can see flight tracks,
a so-called ministrip (green) and and extend flight label (tan background).}
    $w.text configure -state disabled

    #-------------------------------------------------
    # Create zinc
    #-------------------------------------------------
    variable top 1
    variable scale 1.0
    variable centerX 0.0
    variable centerY 0.0
    variable zincWidth 800
    variable zincHeight 500
    variable delay 2000
    variable rate 0.3
    array unset tracks
    # if true the flights are no more moving
    variable pause 0

    zinc $w.zinc -render 1 -backcolor gray65 -relief sunken \
      -font {Helvetica -11} \
      -width $zincWidth -height $zincHeight
    pack $w.zinc -expand 1 -fill both

    $w.zinc add group $top -tags {controls radar}
    $w.zinc configure -overlapmanager [$w.zinc find withtag radar]

#    bind $w.zinc <Alt-1> {
#      incr ::simpleRadar::rotation 10
#      %W configure -screenrotation $::simpleRadar::rotation
#    }
#    bind $w.zinc <Alt-3> {
#      incr ::simpleRadar::rotation -10
#      %W configure -screenrotation $::simpleRadar::rotation
#    }

    #-------------------------------------------------
    # Create control panel
    #-------------------------------------------------
    frame $w.f
    pack $w.f
    ttk::button $w.f.up -text Up -command "::simpleRadar::Up $w.zinc"
    grid $w.f.up -row 0 -column 2 -sticky ew
    ttk::button $w.f.down -text Down -command "::simpleRadar::Down $w.zinc"
    grid $w.f.down -row 2 -column 2 -sticky ew
    ttk::button $w.f.left -text Left -command "::simpleRadar::Left $w.zinc"
    grid $w.f.left -row 1 -column 1
    ttk::button $w.f.right -text Right -command "::simpleRadar::Right $w.zinc"
    grid $w.f.right -row 1 -column 3
    ttk::button $w.f.expand -text Expand -command "::simpleRadar::Expand $w.zinc"
    grid $w.f.expand -row 1 -column 4
    ttk::button $w.f.shrink -text Shrink -command "::simpleRadar::Shrink $w.zinc"
    grid $w.f.shrink -row 1 -column 0
    ttk::button $w.f.reset -text Reset -command "::simpleRadar::Reset $w.zinc"
    grid $w.f.reset -row 1 -column 2 -sticky ew
    ttk::button $w.f.pause -text Pause -command "::simpleRadar::Pause $w.zinc"
    grid $w.f.pause -row 0 -column 6

    #--------------------------------------------------
    # Resize handling code
    #--------------------------------------------------
    bind $w.zinc <Configure> "::simpleRadar::resize $w.zinc %w %h"

    proc Up {z} {
	variable centerY
	set centerY [expr $centerY - 30.0]
	updateTransform $z
    }

    proc Down {z} {
	variable centerY
	set centerY [expr $centerY + 30.0]
	updateTransform $z
    }

    proc Left {z} {
	variable centerX
	set centerX [expr $centerX + 30.0]
	updateTransform $z
    }

    proc Right {z} {
	variable centerX
	set centerX [expr $centerX - 30.0]
	updateTransform $z
    }

    proc Expand {z} {
	variable scale
	set scale [expr $scale * 1.1]
	updateTransform $z
    }

    proc Shrink {z} {
	variable scale
	set scale [expr $scale * 0.9]
	updateTransform $z
    }

    proc Reset {z} {
	variable centerX
	variable centerY
	variable scale
	set scale 1.0
	set centerX 0.0
	set centerY 0.0
	updateTransform $z
    }

    proc Pause {z} {
	variable pause
	set pause [expr ! $pause]
    }

    proc resize {z w h} {
	variable zincWidth
	variable zincHeight

	set bw [$z cget -borderwidth]
	set zincWidth [expr $w - 2 * $bw]
	set zincHeight [expr $h - 2 * $bw]
	updateTransform $z
    }

    proc updateTransform {z} {
	variable centerX
	variable centerY
	variable zincWidth
	variable zincHeight
	variable scale

	$z treset 1
	$z translate 1 [expr -$centerX] [expr -$centerY]
	$z scale 1 $scale $scale
	$z scale 1 1 -1
#  set hVirtualSize [expr hypot($zincWidth, $zincHeight)/2]
#	$z translate 1 $hVirtualSize $hVirtualSize
	$z translate 1 [expr $zincWidth/2] [expr $zincHeight/2]
    }

    #------------------------------------------------
    # Create the tracks
    #------------------------------------------------
    proc createTracks {z} {
	variable oneTrack
	variable zincWidth
	variable zincHeight
	variable scale
	variable centerX
	variable centerY
	variable tracks

	set w [expr $zincWidth / $scale]
	set h [expr $zincHeight / $scale]

	set allTracks {}

	set bOn "$z itemconfigure current \[$z currentpart\] -border contour"
	set bOff "$z itemconfigure current \[$z currentpart\] -border noborder"

	for {set i 20} {$i > 0} {incr i -1} {
	    set item [$z add track radar 6 -lastasfirst 1]
	    lappend allTracks $item
	    set oneTrack $item

	    set tracks($item,x) [expr rand()*$w - $w/2 + $centerX]
	    set tracks($item,y) [expr rand()*$h - $h/2 + $centerY]
	    set d [expr (rand() > 0.5) ? 1 : -1]
	    set tracks($item,vx) [expr (8.0 + rand()*10.0) * $d]
	    set d [expr (rand() > 0.5) ? 1 : -1]
	    set tracks($item,vy) [expr (8.0 + rand()*10.0) * $d]
	    $z itemconfigure $item -position "$tracks($item,x) $tracks($item,y)" -circlehistory 1 \
		-speedvector "$tracks($item,vx) $tracks($item,vy)" -speedvectorsensitive 1 \
		-labeldistance 30 -markersize 20 -historycolor white -filledhistory 0 \
		-labelformat {x80x60+0+0 x63a0^0^0 x33a0^0>1 a0a0>2>1 x33a0>3>1 a0a0^0>2}
	    $z itemconfigure $item 0 -filled 0 -backcolor gray60 -sensitive 1
	    $z itemconfigure $item 1 -filled 1 -backcolor gray55 -text [format {AFR%03i} $i]
	    $z itemconfigure $item 2 -filled 0 -backcolor gray65 -text 360
	    $z itemconfigure $item 3 -filled 0 -backcolor gray65 -text /
	    $z itemconfigure $item 4 -filled 0 -backcolor gray65 -text 410
	    $z itemconfigure $item 5 -filled 0 -backcolor gray65 -text Balise

	    for {set j 0} {$j < 6} {incr j} {
		$z bind $item:$j <Enter> $bOn
		$z bind $item:$j <Leave> $bOff
		$z bind $item <1> "::simpleRadar::fieldSensitivity $z"
		$z bind $item <Shift-1> {}
	    }
	    $z bind $item <Enter> [list $z itemconfigure current -historycolor red3 \
				       -symbolcolor red3 -markercolor red3 -leaderwidth 2 \
				       -leadercolor red3 -speedvectorwidth 2 -speedvectorcolor red3]
	    $z bind $item <Leave> [list $z itemconfigure current -historycolor white \
				       -symbolcolor black -markercolor black -leaderwidth 1 \
				       -leadercolor black -speedvectorwidth 1 -speedvectorcolor black]
	    $z bind $item:position <1> "::simpleRadar::createRoute $z"
	    $z bind $item:position <Shift-1> {}
	    set tracks($item,route) 0
	}

	set tracks(all) $allTracks
    }

    createTracks $w.zinc

    #---------------------------------------------------
    # Create route way points
    #---------------------------------------------------
    proc createRoute {z} {
	variable tracks

	set track [$z find withtag current]

	if { $tracks($track,route) == 0 } {
	    set x [expr $tracks($track,x) + 8.0 * $tracks($track,vx)]
	    set y [expr $tracks($track,y) + 8.0 * $tracks($track,vy)]
	    set connected $track
	    for {set i 4} {$i > 0} {incr i -1} {
		set wp [$z add waypoint radar 2 -position "$x $y" -labelformat x20x18+0+0 \
			    -connecteditem $connected -connectioncolor green -symbolcolor green]
		$z lower $wp $connected
		$z bind $wp:0 <Enter> "$z itemconfigure current 0 -border contour"
		$z bind $wp:position <Enter> "$z itemconfigure current -symbolcolor red"
		$z bind $wp:leader <Enter> "$z itemconfigure current -leadercolor red"
		$z bind $wp:connection <Enter> "$z itemconfigure current -connectioncolor red"
		$z bind $wp:0 <Leave> "$z itemconfigure current 0 -border noborder"
		$z bind $wp:position <Leave> "$z itemconfigure current -symbolcolor green"
		$z bind $wp:leader <Leave> "$z itemconfigure current -leadercolor black"
		$z bind $wp:connection <Leave> "$z itemconfigure current -connectioncolor green"
		$z itemconfigure $wp 0 -text $i -filled 1 -backcolor gray55
		$z bind $wp:position <1> "::simpleRadar::delWaypoint $z"
		set x [expr $x + (2.0 + rand()*8.0) * $tracks($track,vx)]
		set y [expr $y + (2.0 + rand()*8.0) * $tracks($track,vy)]
		set connected $wp
	    }
	    set tracks($track,route) $wp
	} else {
	    set wp $tracks($track,route)
	    while { $wp != $track } {
		set tracks($track,route) [$z itemcget $wp -connecteditem]
		$z bind $wp:position <1> {}
		$z bind $wp:position <Enter> {}
		$z bind $wp:position <Leave> {}
		$z bind $wp:leader <Enter> {}
		$z bind $wp:leader <Leave> {}
		$z bind $wp:connection <Enter> {}
		$z bind $wp:connection <Leave> {}
		$z bind $wp:0 <Enter> {}
		$z bind $wp:0 <Leave> {}
		$z remove $wp
		set wp $tracks($track,route)
	    }
	    set tracks($track,route) 0
	}
    }

    #-----------------------------------------------------
    # Toggle current field sensitivity
    #-----------------------------------------------------
    proc fieldSensitivity {z} {
	set curPart [$z currentpart]
	if { [regexp {[0-9]+} $curPart] } {
	    set onOff [$z itemcget current $curPart -sensitive]
	    $z itemconfigure current $curPart -sensitive [expr !$onOff]
	}
    }

    #-----------------------------------------------------
    # Removal of a route Waypoint
    #-----------------------------------------------------
    proc findTrack {z wp} {
	set connected $wp

	while { [$z type $connected] != "track" } {
	    set connected [$z itemcget $connected -connecteditem]
	}
	return $connected
    }

    proc delWaypoint {z} {
	variable tracks

	set wp [$z find withtag current]
	set track [findTrack $z $wp]
	set next [$z itemcget $wp -connecteditem]

	set prev $tracks($track,route)
	if { $prev != $wp } {
	    set prevnext [$z itemcget $prev -connecteditem]
	    while { $prevnext != $wp } {
		set prev $prevnext
		set prevnext [$z itemcget $prev -connecteditem]
	    }
	}
	$z itemconfigure $prev -connecteditem $next
	$z bind $wp:position <1> {}
	$z remove $wp
	if { $wp == $tracks($track,route) } {
	    if { $next == $track } {
		set tracks($track,route) 0
	    } else {
		set tracks($track,route) $next
	    }
	}
    }

    #---------------------------------------------
    # Create a macro
    #---------------------------------------------
    set macro [$w.zinc add tabular radar 10 -labelformat {x73x20+0+0 x20x20+0+0 x53x20+20+0}]
    $w.zinc itemconfigure $macro 0 -backcolor tan1 -filled 1 -fillpattern AlphaStipple7 \
	-bordercolor red3
    $w.zinc itemconfigure $macro 1 -text a
    $w.zinc itemconfigure $macro 2 -text macro
    $w.zinc itemconfigure $macro -connecteditem $oneTrack
    foreach part {0 1 2} {
	$w.zinc bind $macro:$part <Enter> "::simpleRadar::borders $w.zinc 1"
	$w.zinc bind $macro:$part <Leave> "::simpleRadar::borders $w.zinc 0"
    }

    proc borders {z on} {
	if { $on } {
	    set contour contour
	} else {
	    set contour noborder
	}
	$z itemconfigure current 0 -border $contour
    }

    #---------------------------------------------
    # Create a ministrip
    #---------------------------------------------
    set ministrip [$w.zinc add tabular 1 10 -position {100 10} \
		       -labelformat {x153x80^0^0 x93x20^0^0 x63a0^0>1 a0a0>2>1 x33a0>3>1 a0a0^0>2}]
    $w.zinc itemconfigure $ministrip 0 -filled 1 -backcolor grey70 -border contour -bordercolor green
    $w.zinc itemconfigure $ministrip 1 -text ministrip -color darkgreen -backcolor grey40
    $w.zinc itemconfigure $ministrip 2 -text field1 -color darkgreen -backcolor grey40
    $w.zinc itemconfigure $ministrip 3 -text field2 -color darkgreen -backcolor grey40
    $w.zinc itemconfigure $ministrip 4 -text f3 -color darkgreen -backcolor grey40
    $w.zinc itemconfigure $ministrip 5 -text field4 -color darkgreen -backcolor grey40

    foreach field {1 2 3 4 5} {
	$w.zinc bind $ministrip:$field <Enter> \
	    "$w.zinc itemconfigure current $field -border contour -filled 1 -color white"
	$w.zinc bind $ministrip:$field <Leave> \
	    "$w.zinc itemconfigure current $field -border noborder -filled 0 -color darkgreen"
    }

    #-------------------------------------------
    # Create some maps
    #-------------------------------------------
    set dataDir [file join [file dirname [info script]] data]
    videomap load [file join $dataDir videomap_paris-w_90_2] 0 paris-w
    videomap load [file join $dataDir videomap_orly] 17 orly
    videomap load [file join $dataDir hegias_parouest_TE.vid] 0 paris-ouest

    $w.zinc add map radar -color gray80 -mapinfo orly
    $w.zinc add map radar -color gray60 -filled 1 -priority 0 \
	-fillpattern AlphaStipple6 -mapinfo paris-ouest
    $w.zinc add map radar -color gray50 -mapinfo paris-w


    #--------------------------------------------
    # Animate tracks along their trajectories
    #--------------------------------------------
    variable timer [after $delay "::simpleRadar::refresh $w.zinc"]
    bind $w.zinc <Destroy> {puts {canceling timer}; after cancel $::simpleRadar::timer}

    proc refresh {z} {
	variable pause
	variable timer
	variable delay
	variable tracks
	variable rate

	set timer [after $delay "::simpleRadar::refresh $z"]

	if { ! $pause } {
	    foreach t $tracks(all) {
		set tracks($t,x) [expr $tracks($t,x) + $tracks($t,vx) * $rate]
		set tracks($t,y) [expr $tracks($t,y) + $tracks($t,vy) * $rate]
		$z itemconfigure $t -position [list $tracks($t,x) $tracks($t,y)]
	    }
	}
    }
}

Added jni/tkzinc/demos/testGraphics.tcl.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
#!/usr/bin/tclsh
#-----------------------------------------------------------------------------------
#
#      testGraphics.pl
#      Fichier test du module Graphics
#
#      Authors: Jean-Luc Vinot <vinot@cena.fr>
#      		Patrick Lecoanet <lecoanet@cena.fr> (Straightt translation
#		to Tcl, based on testGraphics.pl revision 1.9)
#
# $Id:
#-----------------------------------------------------------------------------------

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

package require zincGraphics

namespace eval testGraphics {
    set w .testGraphics
    catch {destroy $w}
    toplevel $w
    wm title $w "zincGraphics Demonstration"
    wm iconname $w testGraphics
    frame $w.buttons
    pack $w.buttons -side bottom -fill x -pady 2m
    ttk::button $w.buttons.dismiss -text Dismiss -command "destroy $w"
    ttk::button $w.buttons.code -text "See Code" -command "showCode $w"
    pack $w.buttons.dismiss $w.buttons.code -side left -expand 1

    # creation du widget Zinc
    set zinc [zinc $w.z -render 1 -width 700 -height 560 -borderwidth 0 \
		  -lightangle 140 -backcolor \#cccccc]
    pack $w.z -fill both -expand yes


    set previousAngle 0
    set rotateAngle .1
    set zoomFactor .1
    set curView 0
    set dx 0
    set dy 0
    set tabAnchor n
    set tabAlign left

    set font9b {Helvetica -11}

    set gradSet {
	boitOnglet {=axial 0|#ff7777|#ffff99}
	roundRect1 {=axial 270|#a7ffa7;70 0|#ffffff;90 5|#00bd00;80 8|#b7ffb7;50 80|#ffffff;70 91|#00ac00;70 95|#006700;60 100}
	roundRect2 {=axial 270|#00bd00;80 |#d7ffd7;60}
	roundRect3 {=axial 270|#00bd00;100 0|#ffffff;100 14|#ffffff;100 16|#00bd00;90 25|#b7ffb7;60 100}
	roundRect4 {=axial 0|#00bd00;100 0|#ffffff;100 20|#00bd00;50 30|#00bd00;90 80|#b7ffb7;60 100}
	roundRect4Ed {=path 48 48|#e7ffe7;20 0 70|#007900;20}
	roundCurve2 {=axial 270|#d7ffd7;60|#7777ff;80}
	roundCurve1 {=axial 270|#2222ff;80 |#d7ffd7;60}
	roundCurve {=axial 270|#7777ff;80 |#d7ffd7;60}
	roundPolyg {=radial -15 -20|#ffb7b7;50|#bd6622;90}
	rPolyline {=axial 90|#ffff77;80 |#ff7700;60}
	pushBtn1 {=axial 0|#cccccc;100 0|#ffffff;100 10|#5a5a6a;100 80|#aaaadd;100 100}
	pushBtn2 {=axial 270|#ccccff;100 0|#ffffff;100 10|#5a5a7a;100 80|#bbbbee;100 100}
	pushBtn3 {=radial -15 -15|#ffffff;100 0|#333344;100 100}
	pushBtn4 {=axial 270|#ccccff;100 0|#ffffff;100 10|#7a7a9a;100 80|#bbbbee;100 100}
	conicalEdge {=conical 0 0 -45|#ffffff;100 0|#888899;100 30|#555566;100 50|#888899;100 70|#ffffff;100 100}
	conicalExt {=conical 0 0 135|#ffffff;100 0|#777788;100 30|#444455;100 50|#777788;100 70|#ffffff;100 100}
	pushBtnEdge {=axial 140|#ffffff;100 0|#555566;100 100}
	pushBtnEdge2 {=axial 92|#ffffff;100 0|#555566;100 100}
	logoShape {=axial 270|#ffffff|#7192aa}
	logoPoint {=radial -20 -20|#ffffff 0|#f70000 48|#900000 80|#ab0000 100}
	logoPtShad {=path 0 0|#770000;64 0|#770000;70 78|#770000;0 100}
    }

# contenu des pages exemples
    variable pagesConf {
	Rectangle {
	    consigne {
		-itemtype text
		-coords {-285 155}
		-params {
		    -text "Mouse button 1 drag objects,\nEscape key reset transfos."
		    -color \#2222cc
		}
	    }
	    rr1 {
		-itemtype roundedrectangle
		-coords {{-200 30} {50 130}}
		-radius 20
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundRect2
		    -linewidth 2
		    -linecolor \#000000
		    -priority 20
		    -tags move
		}
	    }
	    rr2 {
		-itemtype roundedrectangle
		-coords {{-250 -100} {-90 60}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundRect1
		    -linewidth 3
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
	    }
	    rr3 {
		-itemtype roundedrectangle
		-coords {{-30 80} {130 160}}
		-radius 40
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundRect3
		    -linewidth 4
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
	    }
	    rr4a {
		-itemtype roundedrectangle
		-coords {{-30 -60} {110 10}}
		-radius 40
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundRect3
		    -linewidth 3
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
		-corners {1 0 1 0}
	    }

	    rr4b {
		-itemtype roundedrectangle
		-coords {{118 -68} {220 -132}}
		-radius 40
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundRect3
		    -linewidth 3
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
		-corners {1 0 1 0}
	    }

	    rr4c {
		-itemtype roundedrectangle
		-coords {{118 -60} {190 30}}
		-radius 40
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundRect3
		    -linewidth 3
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
		-corners {0 1 0 1}
	    }

	    rr4d {
		-itemtype roundedrectangle
		-coords {{40 -152} {110 -68}}
		-radius 40
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundRect3
		    -linewidth 3
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
		-corners {0 1 0 1}
	    }
	    gr8 {
		-itemtype group
		-coords {0 0}
		-params {
		    -priority 10
		    -tags move
		    -atomic 1
		}
		-items {
		    edge {
			-itemtype roundedrectangle
			-coords {{174 -36} {266 146}}
			-radius 26
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundRect4Ed
			    -linewidth 1
			    -linecolor \#ffffff
			    -priority 20
			}
		    }
		    top {
			-itemtype roundedrectangle
			-coords {{180 -30} {260 53}}
			-parentgroup gr8
			-radius 20
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundRect4
			    -linewidth 2.5
			    -linecolor \#000000
			    -priority 30
			}
			-corners {1 0 0 1}
		    }
		    topico {
			-itemtype curve
			-parentgroup gr8
			-coords {{220 -10} {200 30} {240 30}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor {#ffff00;80}
			    -linewidth 1
			    -linecolor {#007900;80}
			    -priority 50
			}
		    }
		    bottom {
			-itemtype roundedrectangle
			-parentgroup gr8
			-coords {{180 57} {260 140}}
			-radius 20
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundRect4
			    -linewidth 2.5
			    -linecolor \#000000
			    -priority 30
			}
			-corners {0 1 1 0}
		    }
		    bottomico {
			-itemtype curve
			-parentgroup gr8
			-coords {{220 120} {240 80} {200 80}}
			-params {
			    -closed 1
			    -filled 1
	    -fillcolor {#ffff00;80}
	    -linewidth 1
	    -linecolor {#007900;80}
			    -priority 50
			}
		    }
		}
	    }
	}

	Hippodrome {
	    consigne {
		-itemtype text
		-coords {-285 165}
		-params {
		    -text "Click hippo Buttons with mouse button 1.\n"
		    -color \#2222cc
		}
	    }

	    hp1 {
		-itemtype group
		-coords {-163 -40}
		-params {
		    -priority 40
		}
		-items {
		    edge {
			-itemtype hippodrome
			-coords {{-46 -86} {46 86}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtnEdge
			    -linewidth 1
			    -linecolor \#ffffff
			    -priority 10
			}
		    }
		    form {
			-itemtype hippodrome
			-coords {{-40 -80} {40 80}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn1
			    -linewidth 3
			    -linecolor \#000000
			    -priority 20
			    -tags {b1 pushBtn}
			}
		    }
		}
	    }

	    hp2 {
		-itemtype group
		-coords {-50 -40}
		-params {
		    -priority 40
		}
		-items {
		    edge {
			-itemtype hippodrome
			-coords {{-46 -86} {46 86}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtnEdge
			    -linewidth 1
			    -linecolor \#ffffff
			    -priority 10
			}
		    }
		    formT {
			-itemtype hippodrome
			-coords {{-40 -80} {40 -28}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn1
			    -linewidth 3
			    -linecolor \#000000
			    -priority 20
			    -tags {b2t pushBtn}
			}
			-orientation vertical
			-trunc bottom
		    }
		    formC {
			-itemtype hippodrome
			-coords {{-40 -26.5} {40 26.5}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn1
			    -linewidth 3
			    -linecolor \#000000
			    -priority 20
			    -tags {b2c pushBtn}
			}
			-trunc both
		    }
		    formB {
			-itemtype hippodrome
			-coords {{-40 28} {40 80}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn1
			    -linewidth 3
			    -linecolor \#000000
			    -priority 20
			    -tags {b2b pushBtn}
			}
			-orientation vertical
			-trunc top
		    }
		}
	    }
	    hp3edge {
		-itemtype hippodrome
		-coords {{-204 96} {204 144}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtnEdge2
		    -linewidth 1
		    -linecolor \#ffffff
		    -priority 10
		}
	    }
	    hp3g {
		-itemtype group
		-coords {-160 120}
		-params {
		    -priority 40
		}
		-items {
		    form {
			-itemtype hippodrome
			-coords {{-40 -20} {40 20}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn2
			    -linewidth 2
			    -linecolor \#000000
			    -priority 20
			    -tags {b3g pushBtn}
			}
			-trunc right
		    }
		    ico {
			-itemtype curve
			-coords {{-20 0} {-4 8} {-4 -8}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor \#000000
			    -linewidth 1
			    -linecolor \#aaaaaa
			    -relief raised
			    -priority 30
			    -tags {b3g pushBtn}
			}
			-contours  {
			    {add -1 {{0 0} {16 8} {16 -8}}}
			}
		    }
		}
	    }
	    hp3c1 {
		-itemtype group
		-coords {-80 120}
		-params {
		    -priority 40
		}
		-items {
		    form {
			-itemtype hippodrome
			-coords {{-38 -20} {39 20}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn2
			    -linewidth 2
			    -linecolor \#000000
			    -priority 20
			    -tags {b3c1 pushBtn}
			}
			-trunc both
		    }
		    ico {
			-itemtype curve
			-coords {{-8 0} {8 8} {8 -8}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor \#000000
			    -linewidth 1
			    -linecolor \#aaaaaa
			    -priority 30
			    -relief raised
			    -tags {b3c1 pushBtn}
			}
		    }
		}
	    }
	    hp3c2 {
		-itemtype group
		-coords {0 120}
		-params {
		    -priority 40
		}
		-items {
		    form {
			-itemtype hippodrome
			-coords {{-39 -20} {39 20}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn2
			    -linewidth 2
			    -linecolor \#000000
			    -priority 20
			    -tags {b3c2 pushBtn}
			}
			-trunc both
		    }
		    ico {
			-itemtype rectangle
			-coords {{-6 -6} {6 6}}
			-params {
			    -filled 1
			    -fillcolor \#000000
			    -linewidth 1
			    -linecolor \#aaaaaa
			    -priority 30
			    -tags {b3c2 pushBtn}
			}
		    }
		}
	    }
	    hp3c3 {
		-itemtype group
		-coords {80 120}
		-params {
		    -priority 40
		}
		-items {
		    form {
			-itemtype hippodrome
			-coords {{-39 -20} {38 20}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn2
			    -linewidth 2
			    -linecolor \#000000
			    -priority 20
			    -tags {b3c3 pushBtn}
			}
			-trunc both
		    }
		    ico {
			-itemtype curve
			-coords {{8 0} {-8 8} {-8 -8}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor \#000000
			    -linewidth 1
			    -linecolor \#aaaaaa
			    -priority 30
			    -relief raised
			    -tags {b3c3 pushBtn}
			}
		    }
		}
	    }

	    hp3d {
		-itemtype group
		-coords {160 120}
		-params {
		    -priority 40
		}
		-items {
		    form {
			-itemtype hippodrome
			-coords {{-40 -20} {40 20}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn2
			    -linewidth 2
			    -linecolor \#000000
			    -priority 20
			    -tags {b3d pushBtn}
			}
			-trunc left
		    }
		    ico {
			-itemtype curve
			-coords {{20 0} {4 -8} {4 8}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor \#000000
			    -linewidth 1
			    -linecolor \#aaaaaa
			    -relief raised
			    -priority 30
			    -tags {b3d pushBtn}
			}
			-contours  {
			    {add -1 {{0 0} {-16 -8} {-16 8}}}
			}
		    }
		}
	    }

	    hp4a {
		-itemtype group
		-coords {48 -97}
		-params {
		    -priority 40
		}
		-repeat {
		    -num 2
		    -dxy {0 64}
		}
		-items {
		    edge {
			-itemtype hippodrome
			-coords {{-29 -29} {29 29}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtnEdge
			    -linewidth 1
			    -linecolor \#ffffff
			    -priority 0
			}
		    }
		    form {
			-itemtype hippodrome
			-coords {{-24 -24} {24 24}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn3
			    -linewidth 3
			    -linecolor \#000000
			    -priority 30
			    -tags {b4a pushBtn}
			}
		    }
		}
	    }

	    hp4b {
		-itemtype group
		-coords {145 -65}
		-params {
		    -priority 40
		}
		-items {
		    edge {
			-itemtype hippodrome
			-coords {{-60 -60} {60 60}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor conicalEdge
			    -linewidth 1
			    -linecolor \#ffffff
			    -priority 0
			}
		    }
		    ext {
			-itemtype hippodrome
			-coords {{-53 -53} {53 53}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor conicalExt
			    -linewidth 3
			    -linecolor \#000000
			    -priority 10
			    -tags {b4b pushBtn}
			}
		    }
		    int {
			-itemtype hippodrome
			-coords {{-41 -41} {40 40}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor {=path 10 10|#ffffff 0|#ccccd0 50|#99999f 80|#99999f;0 100}
			    -linewidth 0
			    -linecolor {#cccccc;80}
			    -priority 30
			    -tags {b4b pushBtn}
			}
		    }
		}
	    }

	    hp5 {
		-itemtype group
		-coords {60 25}
		-params {
		    -priority 40
		}
		-rotate 30
		-repeat {
		    -num 4
		    -dxy {45 0}
		}
		-items {
		    edge {
			-itemtype hippodrome
			-coords {{-19 -34} {19 34}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtnEdge
			    -linewidth 1
			    -linecolor \#ffffff
			    -priority 10
			}
		    }
		    form {
			-itemtype hippodrome
			-coords {{-15 -30} {15 30}}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor pushBtn1
			    -linewidth 2
			    -linecolor \#000000
			    -priority 20
			    -tags {b5 pushBtn}
			}
		    }
		}
	    }
	}

	Polygone {
	    consigne {
		-itemtype text
		-coords {-285 160}
		-params {
		    -text "Click and Drag inside Polygons for rotate them\nEscape key reset transfos."
		    -color \#2222cc
		}
	    }
	    triangle {
		-itemtype group
		-coords {-215 -95}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 3
			-radius 78
			-cornerradius 10
			-startangle 90
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p1 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text "Triangle"
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	    carre {
		-itemtype group
		-coords {-80 -75}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 4
			-radius 70
			-cornerradius 10
			-startangle 90
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p2 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text "Carré"
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	    pentagone {
		-itemtype group
		-coords {65 -75}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 5
			-radius 70
			-cornerradius 10
			-startangle 270
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p3 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text "Pentagone"
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	    hexagone {
		-itemtype group
		-coords {210 -75}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 6
			-radius 68
			-cornerradius 10
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p4 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text "Hexagone"
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	    heptagone {
		-itemtype group
		-coords {-215 85}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 7
			-radius 64
			-cornerradius 10
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p5 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text "Heptagone"
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	    octogone {
		-itemtype group
		-coords {-76 85}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 8
			-radius 64
			-cornerradius 10
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p6 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text Octogone
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	    petagone {
		-itemtype group
		-coords {66 85}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 32
			-radius 64
			-cornerradius 10
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p7 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text "32 cotés..."
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	    etoile {
		-itemtype group
		-coords {210 85}
		-items {
		    form {
			-itemtype polygone
			-coords {0 0}
			-numsides 5
			-radius 92
			-innerradius 36
			-cornerradius 10
			-startangle 270
			-corners {1 0 1 0 1 0 1 0 1 0}
			-params {
			    -closed 1
			    -filled 1
			    -fillcolor roundPolyg
			    -linewidth 2
			    -linecolor \#330000
			    -priority 20
			    -tags {p8 poly}
			}
		    }
		    text {
			-itemtype text
			-coords {0 0}
			-params {
			    -text "Etoile"
			    -anchor center
			    -alignment center
			    -color \#660000
			    -priority 50
			}
		    }
		}
	    }
	}

	Polyline {
	    consigne {
		-itemtype text
		-coords {-285 155}
		-params {
		    -text "Mouse button 1 drag objects\nEscape key reset transfos."
		    -color \#2222cc
		}
	    }
	    a {
		-itemtype polyline
		-coords {
		    {-200 -115} {-200 -100} {-218 -115} {-280 -115} {-280 -16}
		    {-218 -16} {-200 -31} {-200 -17.5} {-150 -17.5} {-150 -115}
		}
		-cornersradius {0 0 42 47 47 42 0 0 0 0 0 0}
		-params {
		    -closed 1
		    -filled 1
		    -visible 1
		    -fillcolor rPolyline
		    -linewidth 2
		    -linecolor \#000000
		    -priority 50
		    -tags move
		}
		-contours {{add -1 {{-230 -80} {-230 -50} {-200 -50} {-200 -80}} 15}}
	    }
	    b {
		-itemtype polyline
		-coords {
		    {-138 -150} {-138 -17.5} {-88 -17.5} {-88 -31} {-70 -16}
		    {-8 -16} {-8 -115} {-70 -115} {-88 -100} {-88 -150}
		}
		-cornersradius {0 0 0 0 42 47 47 42 0 0 0 0 0 0}
		-params {
		    -closed 1
		    -filled 1
		    -visible 1
		    -fillcolor rPolyline
		    -linewidth 2
		    -linecolor \#000000
		    -priority 50
		    -tags move
		}
		-contours {{add -1 {{-88 -80} {-88 -50} {-58 -50} {-58 -80}} 15}}
	    }
	    c {
		-itemtype polyline
		-coords {
		    {80 -76} {80 -110} {60 -115} {0 -115} {0 -16}
		    {60 -16} {80 -21} {80 -57} {50 -47} {50 -86}
		}
		-cornersradius {0 0 70 47 47 70 0 0 14 14 0 0 00 }
		-params {
		    -closed 1
		    -filled 1
		    -visible 1
		    -fillcolor rPolyline
		    -linewidth 2
		    -linecolor \#000000
		    -priority 50
		    -tags move
		}
	    }
	    spirale {
		-itemtype polyline
		-coords {
		    {215 -144} {139 -144} {139 0} {268 0} {268 -116}
		    {162.5 -116} {162.5 -21} {248 -21} {248 -96} {183 -96}
		    {183 -40} {231 -40} {231 -80} {199 -80} {199 -55} {215 -55}
		}
		-cornersradius {0 76 68 61 55 50 45 40 35 30 26 22 18 14 11}
		-params {
		    -closed 1
		    -filled 1
		    -visible 1
		    -fillcolor rPolyline
		    -linewidth 2
		    -linecolor \#000000
		    -priority 50
		    -tags move
		}
	    }
	    logo {
		-itemtype group
		-coords {0 0}
		-params {
		    -priority 30
		    -atomic 1
		    -tags move
		}
		-items {
		    tkzinc {
			-itemtype polyline
			-coords {
			    {-150 10} {-44 10} {-44 68} {-28 51} {6 51}
			    {-19 79} {3 109} {53 51} {5 51} {5 10} {140 10}
			    {52 115} {96 115} {96 47} {196 47} {196 158}
			    {155 158} {155 89} {139 89} {139 160} {101 160}
			    {101 132} {85 132} {85 160} {-42 160} {-2 115}
			    {-30 115} {-46 91} {-46 115} {-76 115} {-76 51}
			    {-98 51} {-98 115} {-130 115} {-130 51} {-150 51}
			}
			-cornersradius {
			    0 0 0 0 0 0 0 0 0 0 30 0 0 50 50
			    0 0 8 8 0 0 8 8 0 27}
			-params {
			    -closed 1
			    -filled 1
			    -visible 1
			    -fillcolor logoShape
			    -linewidth 2.5
			    -linecolor \#000000
			    -priority 10
			    -fillrule nonzero
			}
			-contours {
			    {add 1 {{245 88} {245 47} {190 47} {190 158}
				{259 158} {259 117} {230 117} {230 88}}
				0 {} {0 0 55 55 0 0 15 15}}
			}
		    }
		    shad {
			-itemtype arc
			-coords {{75 91} {115 131}}
			-params {
			    -priority 20
			    -filled 1
			    -linewidth 0
			    -fillcolor logoPtShad
			    -closed 1
			}
		    }
		    point {
			-itemtype arc
			-coords {{70 86} {110 126}}
			-params {
			    -priority 50
			    -filled 1
			    -linewidth 1
			    -linecolor \#a10000
			    -fillcolor logoPoint
			    -closed 1
			}
		    }
		}
	    }
	}

	MultiContours {
	    consigne {
		-itemtype text
		-coords {-285 155}
		-params {
		    -text "Mouse button 1 drag objects\nEscape key reset transfos."
		    -color \#2222cc
		}
	    }
	    mc1 {
		-itemtype roundedcurve
		-coords {{-30 -170} {-130 0} {70 0}}
		-radius 14
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundCurve2
		    -linewidth 1
		    -linecolor \#000000
		    -priority 20
		    -tags move
		    -fillrule odd
		}
		-contours {
		    {add 1 {{-30 -138} {-100 -18} {40 -18}} 8}
		    {add 1 {{-30 -130} { -92 -22} {32 -22}} 5}
		    {add 1 {{-30 -100} { -68 -36} {8 -36}} 5}
		    {add 1 {{-30 -92} { -60 -40} {0 -40}} 3}
		}
	    }
	    mc2 {
		-itemtype polyline
		-coords {
		    {-250 -80} {-240 -10} {-285 -10} {-285 80}
		    {-250 80} {-250 40} {-170 40} {-170 80}
		    {-100 80} {-100 40} {-20 40} {-20 80} {30 80}
		    {-10 0} {-74 -10} {-110 -80}
		}
		-cornersradius {24 4 40 20 0 40 40 0 0 40 40 0 30 75 0 104}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundCurve1
		    -linewidth 2
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
		-contours {
		    {add -1 {{-240 -72} {-230 0} {-169 0} {-185 -72}} 0 {} {16 16 0 0}}
		    {add -1 {{-175 -72} {-159 0} {-78 0} {-116 -72}} 0 {} {0 0 8 88}}
		    {add 1 {{-245 45} {-245 115} {-175 115} {-175 45}} 35}
		    {add -1 {{-225 65} {-225 95} {-195 95} {-195 65}} 15}
		    {add 1 {{-95 45} {-95 115} {-25 115} {-25 45}} 35}
		    {add -1 {{-75 65} {-75 95} {-45 95} {-45 65}} 15}
		}
	    }
	    mc3 {
		-itemtype roundedcurve
		-coords {{-10 170} {256 170} {312 60} {48 60}}
		-radius 34
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundCurve2
		    -linewidth 2.5
		    -linecolor \#000000
		    -priority 40
		    -tags move
		}
		-contours {
		    {add -1 {{58 62} {12 144} {60 172} {104 88}} 27}
		    {add 1 {{48 77} {48 119} {90 119} {90 77}} 21}
		    {add -1 {{244 58} {198 140} {246 168} {290 84}} 27}
		    {add 1 {{213 110} {213 152} {255 152} {255 110}} 21}
		    {add -1 {{150 60} {150 170} {160 170} {160 60}} 0}
		}
	    }
	    mc4 {
		-itemtype roundedcurve
		-coords {
		    {222 -150} {138 -150} {180 -50} {138 -150}
		    {80 -92} {180 -50} {80 -92} {80 -8}
		    {180 -50} {80 -8} {138 50} {180 -50}
		    {138 50} {222 50} {179.8 -50} {222 50}
		    {280 -8} {180 -50} {280 -8} {280 -92}
		    {180 -50} {280 -92} {222 -150} {180 -50}
		}
		-radius 28
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor roundCurve
		    -linewidth 2
		    -linecolor \#000000
		    -priority 30
		    -tags move
		}
		-contours {{add -1 {{160 -70} {160 -30} {200 -30} {200 -70}} 20}}
	    }
	}

	TabBox {
	    consigne {
		-itemtype text
		-coords {-285 160}
		-params {
		    -text "Click on thumbnail to select page\nChange anchor or alignment tabs options with radio buttons.\n"
		    -color \#2222cc
		}
	    }
	    bo1 {
		-itemtype tabbox
		-coords {{-240 -160} {240 100}}
		-radius 8
		-tabwidth 72
		-tabheight 28
		-numpages 8
		-anchor n
		-alignment left
		-overlap 3
		-tabtitles {A B C D E F G H}
		-params {
		    -closed 1
		    -priority 100
		    -filled 1
		    -fillcolor \#ffffff
		    -linewidth 1.2
		    -linecolor \#000000
		    -tags {div2 divider intercalaire}
		}
	    }

	    back {
		-itemtype roundedrectangle
		-coords {{-242 -162} {242 102}}
		-radius 10
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor {#777777;80}
		    -linewidth 1
		    -linecolor {#777777;80}
		}
	    }

	    anchor {
		-itemtype text
		-coords {-120 115}
		-params {
		    -text {tabs anchor}
		    -color \#2222cc
		    -anchor center
		    -alignment center
		    -priority 40
		}
	    }

	    anchorN {
		-itemtype hippodrome
		-coords {{-210 125} {-165 151}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtn4
		    -linewidth 1.5
		    -linecolor \#000000
		    -priority 20
		    -tags {sel1 n btn selector}
		}
		-trunc right
	    }
	    txtanN {
		-itemtype text
		-coords {-187 138}
		-params {
		    -text N
		    -color \#000000
		    -anchor center
		    -alignment center
		    -priority 40
		    -tags {sel1 n btntext selector}
		}
	    }

	    anchorE {
		-itemtype hippodrome
		-coords {{-163 125} {-120 151}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtn4
		    -linewidth 1.5
		    -linecolor \#000000
		    -priority 20
		    -tags {sel1 e btn selector}
		}
		-trunc both
	    }
	    txtanE {
		-itemtype text
		-coords {-141.5 138}
		-params {
		    -text E
		    -color \#000000
		    -anchor center
		    -alignment center
		    -priority 40
		    -tags {sel1 e btntext selector}
		}
	    }

	    anchorS {
		-itemtype hippodrome
		-coords {{-118 125} {-75 151}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtn4
		    -linewidth 1.5
		    -linecolor \#000000
		    -priority 20
		    -tags {sel1 s btn selector}
		}
		-trunc both
	    }
	    txtanS {
		-itemtype text
		-coords {-96.5 138}
		-params {
		    -text S
		    -color \#000000
		    -anchor center
		    -alignment center
		    -priority 40
		    -tags {sel1 s btntext selector}
		}
	    }
	    anchorW {
		-itemtype hippodrome
		-coords {{-73 125} {-28 151}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtn4
		    -linewidth 1.5
		    -linecolor \#000000
		    -priority 20
		    -tags {sel1 w btn selector}
		}
		-trunc left
	    }
	    txtanW {
		-itemtype text
		-coords {-52 138}
		-params {
		    -text W
		    -color \#000000
		    -anchor center
		    -alignment center
		    -priority 40
		    -tags {sel1 w btntext selector}
		}
	    }
	    alignment {
		-itemtype text
		-coords {120 115}
		-params {
		    -text {tabs alignment}
		    -color \#2222cc
		    -anchor center
		    -alignment center
		    -priority 40
		}
	    }
	    alignG {
		-itemtype hippodrome
		-coords {{30 125} {90 151}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtn4
		    -linewidth 1.5
		    -linecolor \#000000
		    -priority 20
		    -tags {sel2 left btn selector}
		}
		-trunc right
	    }
	    txtalG {
		-itemtype text
		-coords {60 138}
		-params {
		    -text left
		    -color \#000000
		    -anchor center
		    -alignment center
		    -priority 40
		    -tags {sel2 left btntext selector}
		}
	    }
	    alignC {
		-itemtype hippodrome
		-coords {{92 125} {148 151}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtn4
		    -linewidth 1.5
		    -linecolor \#000000
		    -priority 20
		    -tags {sel2 center btn selector}
		}
		-trunc both
	    }
	    txtalC {
		-itemtype text
		-coords {120 138}
		-params {
		    -text center
		    -color \#000000
		    -anchor center
		    -alignment center
		    -priority 40
		    -tags {sel2 center btntext selector}
		}
	    }
	    alignD {
		-itemtype hippodrome
		-coords {{150 125} {210 151}}
		-params {
		    -closed 1
		    -filled 1
		    -fillcolor pushBtn4
		    -linewidth 1.5
		    -linecolor \#000000
		    -priority 20
		    -tags {sel2 right btn selector}
		}
		-trunc left
	    }
	    txtalD {
		-itemtype text
		-coords {180 138}
		-params {
		    -text right
		    -color \#000000
		    -anchor center
		    -alignment center
		    -priority 40
		    -tags {sel2 right btntext selector}
		}
	    }
	}

	PathLine {
	    consigne {
		-itemtype text
		-coords {-285 155}
		-params {
		    -text "Mouse button 1 drag objects\nEscape key reset transfos."
		    -color \#2222cc
		}
	    }
	    pl1 {
		-itemtype pathline
		-metacoords {
		    -type polygone
		    -coords {0 0}
		    -numsides 12
		    -radius 200
		    -innerradius 100
		    -startangle -8
		}
		-linewidth 20
		-closed 1
		-graduate {
		    -type linear
		    -colors {
			#ff0000 #ff00ff #0000ff #00ffff
			#00ff00 #ffff00 #ff0000
		    }
		}
		-params {
		    -priority 100
		    -tags move
		}
	    }

	    pl2 {
		-itemtype group
		-coords {0 0}
		-params {
		    -priority 200
		    -atomic 1
		    -tags move
		}
		-items {
		    in {
			-itemtype pathline
			-coords {
			    {30 -60} {-30 -60} {-30 -30}
			    {-60 -30} {-60 30} {-30 30}
			    {-30 60} {30 60} {30 30}
			    {60 30} {60 -30} {30 -30}
			}
			-linewidth 16
			-closed 1
			-shifting left
			-graduate {
			    -type transversal
			    -colors {{#00aa77;100} {#00aa77;0}}
			}
			-params {
			    -priority 10
			}
		    }

		    out {
			-itemtype pathline
			-coords {
			    {30 -60} {-30 -60} {-30 -30}
			    {-60 -30} {-60 30} {-30 30}
			    {-30 60} {30 60} {30 30}
			    {60 30} {60 -30} {30 -30}
			}
			-linewidth 10
			-closed 1
			-shifting right
			-graduate {
			    -type transversal
			    -colors {{#00aa77;100} {#00aa77;0}}
			}
			-params {
			    -priority 10
			}
		    }
		}
	    }

	    pl3 {
		-itemtype group
		-coords {0 0}
		-params {
		    -priority 100
		    -atomic 1
		    -tags move
		}
		-items {
		    back {
			-itemtype arc
			-coords {{-150 -150} {150 150}}
			-params {
			    -priority 10
			    -closed 1
			    -filled 1
			    -fillcolor {=radial 15 15|#ffffff;40|#aaaaff;10}
			    -linewidth 0
			}
		    }
		    light {
			-itemtype pathline
			-metacoords {
			    -type polygone
			    -coords {0 0}
			    -numsides 30
			    -radius 150
			    -startangle 240
			}
			-linewidth 20
			-shifting right
			-closed 1
			-graduate {
			    -type double
			    -colors {
				{{#ffffff;0} {#222299;0} {#ffffff;0}}
				{{#ffffff;100} {#222299;70} {#ffffff;100}}
			    }
			}
			-params {
			    -priority 50
			}
		    }
		    bord {
			-itemtype arc
			-coords {{-150 -150} {150 150}}
			-params {
			    -priority 100
			    -closed 1
			    -filled 0
			    -linewidth 2
			    -linecolor {#000033;80}
			}
		    }

		}
	    }
	}
    }

    variable tabTable {
	n {
	    -numpages 8
	    -titles {A B C D E F G H}
	    -names {
		{ATOMIC GROUP} {BIND COMMAND} {CURVE ITEMS} {DISPLAY LIST}
		{EVENTS SENSITIVITY} {FIT COMMAND} {GROUP ITEMS} {HASTAG COMMAND}
	    }
	    -texts {
		"It may seem at first that there is a contradiction in this title but there is none. [...] So groups have a feature: the atomic  attribute that is used to seal a group so that events cannot propagate past it downward. If an item part of an atomic group is under the pointer TkZinc will try to trigger bindings associated with the atomic group not with the item under the pointer. This improves greatly the metaphor of an indivisible item."
		"This widget command is similar to the Tk bind command except that it operates on TkZinc items instead of widgets. Another difference with the bind command is that only mouse and keyboard related events can be specified (such as Enter Leave ButtonPress ButtonRelease Motion KeyPress KeyRelease). The bind manual page is the most accurate place to look for a definition of sequence and command and for a general understanding of how the binding mecanism works."
		"Items of type curve display pathes of line segments and/or cubic bezier connected by their end points. A cubic Bezier is defined by four points. The first and last ones are the extremities of the cubic Bezier. The second and the third ones are control point (i.e. they must have a third ``coordinate with the value c). If both control points are identical one may be omitted. As a consequence it is an error to have more than two succcessive control points or to start or finish a curve with a control point."
		"The items are arranged in a display list for each group. The display list imposes a total ordering among its items. The group display lists are connected in a tree identical to the group tree and form a hierarchical display list. The items are drawn by traversing the display list from the least visible item to the most visible one.The search to find the item that should receive an event is done in the opposite direction. In this way items are drawn according to their relative stacking order and events are dispatched to the top-most item at a given location."
		"An item will catch an event if all the following conditions are satisfied: * the item -sensitive must be set to true (this is the default). * the item must be under the pointer location. * the item must be on top of the display list (at the pointer location). Beware that an other item with its -visible set to false DOES catch event before any underneath items. * the item must not be clipped (at the pointer location) * the item must not belong to an atomic group since an atomic group catchs the event instead of the item."
		"This command fits a sequence of Bezier segments on the curve described by the vertices in coordList and returns a list of lists describing the points and control points for the generated segments. All the points on the fitted segments will be within error  distance from the given curve. coordList should be either a flat list of an even number of coordinates in x y order or a list of lists of point coordinates X Y. The returned list can be directly used to create or change a curve item contour."
		"Groups are very powerful items. They have no graphics of their own but are used to bundle items together so that they can be manipulated easily as a whole. Groups can modify in several way how items are displayed and how they react to events. They have many uses in TkZinc. The main usages are to bundle items to interpose a new coordinate system in a hierarchy of items to compose some specific attributes to apply a clipping to their children items to manage display"
		"This command returns a boolean telling if the item specified by tagOrId has the specified tag. If more than one item is named by tagOrId then the topmost in display list order is used to return the result. If no items are named by tagOrId an error is raised."
	    }
	}
	e {
	    -numpages 5
	    -titles {I J K L M}
	    -names {
		{ITEM IDS} JOINSTYLE {ATTRIBUTE K} {LOWER COMMAND} {MAP ITEM}
	    }
	    -texts {
		"Each item is associated with a unique numerical id which is returned by the add  or clone  commands. All commands on items accept those ids as (often first) parameter in order to uniquely identify on which item they should operate. When an id has been allocated to an item it is never collected even after the item has been destroyed in a TkZinc session two items cannot have the same id. This property can be quite useful when used in conjonction with tags which are described below."
		"Specifies the form of the joint between the curve segments. This attribute is only applicable if the curve outline relief is flat. The default value is round."
		"No TkZinc KeyWord with K initial letter..."
		"Reorder all the items given by tagOrId so that they will be under the item given by belowThis. If tagOrId name more than one item their relative order will be preserved. If tagOrId doesnt name an item an error is raised. If  belowThis name more than one item the bottom most them is used. If belowThis  doesnt name an item an error is raised. If belowThis is omitted the items are put at the bottom most position of their respective groups."
		"Map items are typically used for displaying maps on a radar display view. Maps are not be sensitive to mouse or keyboard events but have been designed to efficiently display large set of points segments arcs and simple texts. A map item is associated to a mapinfo. This mapinfo entity can be either initialized with the videomap  command or more generally created and edited with a set of commands described in the The mapinfo related commands  section."
	    }
	}
	s {
	    -numpages 8
	    -titles {N O P Q R S T U}
	    -names {
		{NUMPARTS COMMAND} {OVERLAP MANAGER} {PICKAPERTURE WIDGET OPTION}
		Q {RENDER WIDGET OPTION} {SMOOTH COMMAND} TAGS {UNDERLINED ATTRIBUTE}
	    }
	    -texts {
		"This command tells how many fieldId are available for event bindings or for field configuration commands in the item specified by tagOrId. If more than one item is named by tagOrId the topmost in display list order is used to return the result. If no items are named by tagOrId an error is raised. This command returns always 0 for items which do not support fields. The command hasfields  may be used to decide whether an item has fields."
		"his option accepts an item id. It specifies if the label overlapping avoidance algorithm should be allowed to do its work on the track labels and which group should be considered to look for tracks. The default is to enable the avoidance algorithm in the root group (id 1). To disable the algorithm this option should be set to 0."
		"Specifies the size of an area around the pointer that is used to tell if the pointer is inside an item. This is useful to lessen the precision required when picking graphical elements. This value must be a positive integer. It defaults to 1."
		"No TkZinc KeyWord with Q initial letter..."
		"Specifies whether to use or not the openGL rendering. When True requires the GLX extension to the X server. Must be defined at widget creation time. This option is readonly and can be used to ask if the widget is drawing with the GLX extension or in plain X (to adapt the application code for example). The default value is false."
		"This command computes a sequence of Bezier segments that will smooth the polygon described by the vertices in coordList and returns a list of lists describing thr points and control points for the generated segments. coordList should be either a flat list of an even number of coordinates in x y order or a list of lists of point coordinates X Y. The returned list can be used to create or change the contour of a curve item."
		"Apart from an id an item can be associated with as many symbolic names as it may be needed by an application. Those names are called tags and can be any string which does not form a valid id (an integer). However the following characters may not be used to form a tag: . * ! ( ) & | :. Tags exists and may be used in commands even if no item are associated with them. In contrast an item id doesnt exist if its item is no longer around and thus it is illegal to use it."
		"Item Text attribute. If true a thin line will be drawn under the text characters. The default value is false."
	    }
	}
	w {
	    -numpages 5
	    -titles {V W X Y Z}
	    -names {
		{VERTEXAT COMMAND} {WAYPOINT ITEM} {X11 OpenGL and Windows}
		{Y...} {ZINC an advanced scriptable Canvas}
	    }
	    -texts {
		"Return a list of values describing the vertex and edge closest to the window coordinates x and y in the item described by tagOrId. If  tagOrId describes more than one item the first item in display list order that supports vertex picking is used. The list consists of the index of the contour containing the returned vertices the index of the closest vertex and the index of a vertex next to the closest vertex that identify the closest edge (located between the two returned vertices)."
		"Waypoints items have been initially designed for figuring out typical fixed position objects (i.e. beacons or fixes in the ATC vocabulary) with associated block of texts on a radar display for Air Traffic Control. They supports mouse event handling and interactions. However they may certainly be used by other kinds of radar view or even by other kind of plan view with many geographical objects and associated textual information."
		"TkZinc was firstly designed for X11 server. Since the 3.2.2 version TkZinc also offers as a runtime option the support for openGL rendering giving access to features such as antialiasing transparency color gradients and even a new openGL oriented item type : triangles  . In order to use the openGL features you need the support of the GLX extension on your X11 server. We also succeeded in using TkZinc with openGL on the Exceed X11 server (running on windows and developped by Hummingbird) with the 3D extension. "
		"No TkZinc KeyWord with Y initial letter..."
		"TkZinc widgets are very similar to Tk Canvases in that they support structured graphics. But unlike the Canvas TkZinc can structure the items in a hierarchy has support for affine 2D transforms clipping can be set for sub-trees of the item hierarchy the item set is quite more powerful including field specific items for Air Traffic systems and new rendering techniques such as transparency and gradients. If needed it is also possible to extend the item set in an additionnal dynamic library through the use of a C api."
	    }
	}
    }

    proc TLGet {list tag {default ""}} {
	foreach {key val} $list {
	    if { [string compare $key $tag] == 0 } {
		return $val
	    }
	}
	return $default
    }

    proc SetBindings {} {
	variable zinc
	variable curView

	# focus the keyboard
	focus $zinc

	# plusmoins : Zoom++ Zoom--
	bind $zinc <plus> "::testGraphics::ViewZoom $zinc up"
	bind $zinc <minus> "::testGraphics::ViewZoom $zinc down"

	# Up Down Right Left : Translate
	bind $zinc <KeyPress-Up> "::testGraphics::ViewTranslate $zinc up"
	bind $zinc <KeyPress-Down> "::testGraphics::ViewTranslate $zinc down"
	bind $zinc <KeyPress-Left> "::testGraphics::ViewTranslate $zinc left"
	bind $zinc <KeyPress-Right> "::testGraphics::ViewTranslate $zinc right"


	# > < : Rotate counterclockwise et clockwise
	bind $zinc <greater> "::testGraphics::ViewRotate $zinc cw"
	bind $zinc <less> "::testGraphics::ViewRotate $zinc ccw"

	# Escape : reset transfos
	bind $zinc <Escape> "$zinc treset poly; $zinc treset move; \
     $zinc raise move; $zinc treset $curView"

	$zinc bind divider <1> "::testGraphics::SelectDivider $zinc"
	$zinc bind selector <1> "::testGraphics::ClickSelector $zinc"
	$zinc bind move <1> "::testGraphics::MobileStart $zinc %x %y"
	$zinc bind move <B1-Motion> "::testGraphics::MobileMove $zinc %x %y"
	$zinc bind move <ButtonRelease> "::testGraphics::MobileStop $zinc %x %y"
	$zinc bind pushBtn <1> "::testGraphics::PushButton $zinc"
	$zinc bind pushBtn <ButtonRelease> "::testGraphics::PullButton $zinc"
	$zinc bind poly <1> "::testGraphics::StartRotatePolygone $zinc %x %y"
	$zinc bind poly <B1-Motion> "::testGraphics::RotatePolygone $zinc %x %y"
    }


    proc SelectDivider {zinc {divName ""} {numPage ""}} {
	variable curView
	variable tabTable
	variable tabAnchor

	if { $divName eq "" } {
	    foreach {divName numPage} [$zinc itemcget current -tags] break
	}

	$zinc itemconfigure $divName&&titre -color \#000099
	$zinc itemconfigure $divName&&intercalaire -linewidth 1.4
	$zinc itemconfigure $divName&&page -visible 0

	set divGroup [$zinc group $divName&&$numPage]
	$zinc raise $divGroup
	set curView $divName&&$numPage&&content
	$zinc itemconfigure $divName&&$numPage&&titre -color \#000000
	$zinc itemconfigure $divName&&$numPage&&intercalaire -linewidth 2
	$zinc itemconfigure $divName&&$numPage&&page -visible 1

	if { $divName eq "div2" } {
	    set anchors [TLGet $tabTable $tabAnchor]
	    set names [lindex [TLGet $anchors -names] $numPage]
	    set explain [lindex [TLGet $anchors -texts] $numPage]
	    $zinc itemconfigure $divName&&fontname -text "$names\n\n$explain"
	    $zinc raise $divName&&fontname
	}
    }

    proc ClickSelector {zinc {btnGroup ""} {value ""}} {
	variable tabTable
	variable tabAnchor
	variable tabAlign

	if { $btnGroup eq "" && $value eq "" } {
	    set tags [$zinc itemcget current -tags]
	    foreach {btnGroup value} $tags break
	}

	$zinc treset $btnGroup
	$zinc itemconfigure $btnGroup&&btntext -color \#444444
	$zinc itemconfigure $btnGroup&&$value&&btntext -color \#2222bb
	$zinc translate $btnGroup&&$value 0 1

	switch -- $value {
	    n -
	    e -
	    s -
	    w { set tabAnchor $value }
	    left -
	    center -
	    right { set tabAlign $value }
	}

	set table [TLGet $tabTable $tabAnchor]
	set numPages [TLGet $table -numpages]
	foreach {shapes tCoords} [zincGraphics::TabBoxCoords {{-240 -160} {240 100}} \
				      -radius 8 -tabwidth 72 -tabheight 28 \
				      -numpages $numPages -anchor $tabAnchor \
				      -alignment $tabAlign -overlap 3] break

	for {set index 7} {$index >= 0} {incr index -1} {
	    set divGroup [$zinc group div2&&$index&&intercalaire]
	    $zinc itemconfigure $divGroup -visible [expr $index < $numPages]

	    if { $index >= $numPages } {
		$zinc lower $divGroup
	    } else {
		$zinc raise $divGroup
		$zinc itemconfigure div2&&$index -visible 1
		$zinc coords div2&&$index&&intercalaire [lindex $shapes $index]
		$zinc coords div2&&$index&&titre [lindex $tCoords $index]
		$zinc itemconfigure div2&&$index&&titre \
		    -text [lindex [TLGet $table -titles] $index]
	    }
	}

	SelectDivider $zinc div2 0
    }

    #-----------------------------------------------------------------------------------
    # Callback sur evt CLICK des items tagés pushBtn
    #-----------------------------------------------------------------------------------
    proc PushButton {zinc} {
	set tag [lindex [$zinc itemcget current -tags] 0]
	$zinc scale $tag .975 .975
	$zinc translate $tag 1 1
    }

    #-----------------------------------------------------------------------------------
    # Callback sur evt RELEASE des items tagés pushBtn
    #-----------------------------------------------------------------------------------
    proc PullButton {zinc} {
	set tag [lindex [$zinc itemcget current -tags] 0]
	$zinc treset $tag
    }

    #-----------------------------------------------------------------------------------
    # Callback sur evt CATCH des items tagés poly
    # armement de rotation des polygones
    #-----------------------------------------------------------------------------------
    proc StartRotatePolygone {zinc x y} {
	variable previousAngle

	foreach {xRef yRef} [$zinc transform [$zinc group current] 1 {0 0}] break
	set previousAngle [zincGraphics::LineAngle [list $x $y] [list $xRef $yRef]]
    }

    #-----------------------------------------------------------------------------------
    # Callback sur evt MOTION des items tagés poly
    # rotation des polygones
    #-----------------------------------------------------------------------------------
    proc RotatePolygone {zinc x y} {
	variable previousAngle

	set tag [lindex [$zinc itemcget current -tags] 0]
	foreach {xRef yRef} [$zinc transform [$zinc group current] 1 {0 0}] break
	set newAngle [zincGraphics::LineAngle [list $x $y] [list $xRef $yRef]]

	$zinc rotate $tag [zincGraphics::deg2rad [expr $newAngle - $previousAngle]]
	set previousAngle $newAngle
    }

    #-----------------------------------------------------------------------------------
    # Callback CATCH de sélection (début de déplacement) des items tagés move
    #-----------------------------------------------------------------------------------
    proc MobileStart {zinc x y} {
	variable dx
	variable dy

	set dx [expr 0 - $x]
	set dy [expr 0 - $y]
	$zinc raise current
    }

    #-----------------------------------------------------------------------------------
    # Callback MOVE de déplacement des items tagés move
    #-----------------------------------------------------------------------------------
    proc MobileMove {zinc x y} {
	variable dx
	variable dy

	$zinc translate current [expr $x + $dx] [expr $y + $dy]
	set dx [expr 0 - $x]
	set dy [expr 0 - $y]
    }

    #-----------------------------------------------------------------------------------
    # Callback RELEASE de relaché (fin de déplacement) des items tagés move
    #-----------------------------------------------------------------------------------
    proc MobileStop {zinc x y} {
	MobileMove $zinc $x $y
    }

    proc ViewTranslate {zinc way} {
	variable curView

	set dx 0
	set dy 0
	switch -- $way {
	    left {set dx -10}
	    up {set dy -10}
	    right {set dx 10}
	    down {set dy 10}
	}
	$zinc translate $curView $dx $dy
    }

    proc ViewZoom {zinc key} {
	variable curView
	variable zoomFactor

	set scaleRatio [expr {($key == "up") ? (1 + $zoomFactor) : (1 - $zoomFactor)}]
	$zinc scale $curView $scaleRatio $scaleRatio
    }

    proc ViewRotate {zinc way} {
	variable curView
	variable rotateAngle

	set deltaAngle $rotateAngle

	if { $way eq "cw" } {
	    set deltaAngle [expr $deltaAngle * -1]
	}

	$zinc rotate $curView $deltaAngle
    }

    proc lreverse {l} {
	set res {}
	set i [llength $l]
	while {$i} {
	    lappend res [lindex $l [incr i -1]]
	}
	return $res
    }

    proc BuildTabBox {zinc parentGroup style name} {
	variable tabTable
	variable font9b

	set params [TLGet $style -params]
	set tags [TLGet $params -tags]
	set coords [TLGet $style -coords]
	set table [TLGet $tabTable [TLGet $style -anchor]]
	set titles [TLGet $style -tabtitles]
	set cmd [linsert $style 0 zincGraphics::TabBoxCoords $coords]
	foreach {shapes tCoords invert} [eval $cmd] break

	set k -1
	if { $invert } {
	    set k [llength $shapes]
	}
	foreach shape [lreverse $shapes] {
	    incr k [expr $invert ? -1 : 1]
	    set group [$zinc add group $parentGroup]
	    set cmd [linsert $params 0 $zinc add curve $group $shape]
	    lappend cmd -tags [list [lindex $tags 0] $k [lindex $tags 1] intercalaire]
	    eval $cmd
	    set page [TLGet $style -page {}]
	    if { $page ne "" } {
		zincGraphics::BuildZincItem $zinc $group $page
	    }

	    set tIndex [expr $invert ? $k : ([llength $shapes] - $k - 1)]
	    if { [llength $titles] } {
		set titlTags [list [lindex $tags 0] $k [lindex $tags 1] titre]
		$zinc add text $group -position [lindex $tCoords $tIndex] \
		    -text [lindex $titles $tIndex] -font $font9b -alignment center \
		    -anchor center -color \#000099 -priority 200 -tags $titlTags
	    }

	    # exemple fonte
	    if { $tIndex == 0 } {
		$zinc add text $parentGroup -position {-165 -105} \
		    -text [lindex [TLGet $table -names] 0] -font $font9b \
		    -alignment left -anchor nw -color \#000000 -priority 500 \
		    -width 350 -tags [list [lindex $tags 0] fontname]
	    }
	}

	SelectDivider $zinc [lindex $tags 0] $k
    }

    # initialise les gradients nommés
    zincGraphics::SetGradients $zinc $gradSet

    # création de la vue principale
    variable tgroup [$zinc add group 1]
    $zinc coords $tgroup {350 240}

    # consigne globale
    $zinc add text 1 -position {50 470} -font $font9b -color \#555555 -spacing 2 \
	-text "Global interations :\n<Up> <Down> <Left> and <Right> keys move content of TabBox pages\n<Plus> and <Minus> keys zoom out and zoom in this page\n<Greater> and <Less> keys rotate this page\n<Escape> key reset transfos"

    # Création des pages d'exemples
    foreach {shapes tCoords} [zincGraphics::TabBoxCoords {{-315 -210} {315 210}} \
				  -numpages 7 -overlap 2 -radius 8 \
				  -tabheight 26 -tabwidth {92 100 82 82 82 120 80}] break
    # to find some images (used as textures) needed by this demo
    variable imagePath [file join $::zinc_demos images]
    variable texture [image create photo -file [file join $imagePath paper.gif]]
    # création des items zinc correspondants
    variable i 0
    variable pageNames {Rectangle Hippodrome Polygone Polyline PathLine MultiContours TabBox}
    variable pageGroups {}
    foreach shape $shapes {
	set divGroup [$zinc add group $tgroup]

	# création de l'intercalaire
	set divider [$zinc add curve $divGroup $shape -closed 1 \
			 -priority 10 -linewidth 1 -linecolor \#000000 \
			 -filled 1 -tile $texture -tags [list div1 $i divider intercalaire]]

	# groupe page clippé
	set page [$zinc add group $divGroup -priority 100 -tags [list div1 $i page]]
	set clip [$zinc add rectangle $page {{-300 -170} {300 195}} -linewidth 1 \
		      -linecolor \#000099 -filled 1 -fillcolor {#000000;4}]
	$zinc itemconfigure $page -clip $clip

	set pGroup [$zinc add group $page -tags [list div1 $i content]]
	lappend pageGroups $pGroup

	# titre de l'intercalaire
	$zinc add text $divGroup -position [lindex $tCoords $i] \
	    -text [lindex $pageNames $i] \
	    -font $font9b -alignment center \
	    -anchor center -color \#000099 \
	    -priority 200 -tags [list div1 $i divider titre]

	incr i
    }

    # # création du contenu des pages
    foreach pageName $pageNames pGroup $pageGroups {
	set pageStyle [TLGet $pagesConf $pageName]
	if { $pageStyle ne "" } {
	    foreach {itemName itemStyle} $pageStyle {
		if { [TLGet $itemStyle -itemtype] eq "tabbox" } {
		    BuildTabBox $zinc $pGroup $itemStyle $itemName
		} else {
		    if { [TLGet $itemStyle -itemtype] eq "group" } {
			set subGroup [zincGraphics::BuildZincItem $zinc $pGroup $itemStyle {} $itemName]
			foreach {name style} [TLGet $itemStyle -items] {
			    zincGraphics::BuildZincItem $zinc $subGroup $style {} $name
			}

			if { [llength [TLGet $itemStyle -repeat]] != 0 } {
			    set num [TLGet [TLGet $itemStyle -repeat] -num]
			    foreach {dx dy} [TLGet [TLGet $itemStyle -repeat] -dxy] break
			    for {set j 1} {$j < $num} {incr j} {
				set clone [$zinc clone $subGroup]
				$zinc translate $clone [expr $dx*$j] [expr $dy*$j]
				set items [$zinc find withtag ".$clone*"]
				foreach item $items {
				    set tags [$zinc itemcget $item -tags]
				    if { [llength $tags] } {
					foreach {name type} $tags break
					$zinc itemconfigure $item -tags [list $name$j $type]
				    }
				}
			    }
			}
		    } else {
			if { $itemName eq "consigne" } {
			    set group [$zinc group $pGroup]
			} else {
			    set group $pGroup
			}
			zincGraphics::BuildZincItem $zinc $group $itemStyle {} $itemName
		    }
		}
	    }
	}
    }

    ClickSelector $zinc sel1 n
    ClickSelector $zinc sel2 left
    SelectDivider $zinc div1 0
    SetBindings
}

Added jni/tkzinc/demos/textInput.tcl.





























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr


if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval textInputDemo {
    #
    # We need the text input support
    package require zincText

    variable w .textInput
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc textInput Demonstration"
    wm iconname $w textInput

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 5 \
              -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {This demo demonstrates the use of the zincText package.
This module is designed for facilitating text input.
It works on text items or on fields of items such as
tracks, waypoints or tabulars.}
    $w.text configure -state disabled

    ###########################################
    # Zinc
    ###########################################
    grid [zinc $w.zinc -width 500 -height 300 -render 1 -font $defaultfont -borderwidth 0] \
	-row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    #
    # Activate text input support from zincText
    zn_TextBindings $w.zinc

    ### creating a tabular with 3 fields 2 of them being editable
    variable labelformat1 {130x100 x130x20+0+0 x130x20+0+20 x130x20+0+40}

    variable x 120
    variable y 6
    variable track [$w.zinc add track 1 3 -position "$x $y" -speedvector {40 10} -labeldistance 30 -labelformat $labelformat1 -tags text]

    # moving the track to display past positions
    for {set i 0} {$i<=5} {incr i} {
	$w.zinc coords "$track" "[expr $x+$i*10] [expr $y+$i*2]"
    }

    $w.zinc itemconfigure $track 0 -border contour -text {  editable} -sensitive 0

    $w.zinc itemconfigure $track 1 -border contour -text editable -sensitive 1

    $w.zinc itemconfigure $track 2 -border contour -text {editable too} -alignment center -sensitive 1


    # creating a text item tagged with "text" but not editable because
    # it is not sensitive
    $w.zinc add text 1 -position {220 160} -text "this text is not editable \nbecause it is not sensitive" -sensitive 0 -tags text


    # creating an editable text item
    $w.zinc add text 1 -position {50 230} -text {this text IS editable} -sensitive 1 -tags text
}

Added jni/tkzinc/demos/tiger.tcl.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
###
####### This file has been initially generated from tiger.svg by SVG2zinc.pm
### Version: Revision: 1.10
### the idea of using the shape extension (as possible with zinc) was
### done by Daniel Etienne! Thx!
###
### It has been subsequently ported to Tcl by P.Lecoanet for testing
### purposes.
###

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval tigerDemo {
    variable w .tiger
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc tiger (Generated from SVG) Demonstration"
    wm iconname $w tiger

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10


    ###########################################
    # Zinc
    ##########################################
    grid [zinc $w.zinc -width 600 -height 600 -font $defaultfont -borderwidth 0 -backcolor grey90 \
	      -render 1] -row 0 -column 0 -columnspan 2 -sticky news
    # -reshape 1 -fullreshape 1
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 0 -weight 2

    variable topGroup [$w.zinc add group 1]

    variable text {
	Drag-Button 1 for moving the tiger,
	Drag-Button 2 for zooming the tiger,
    }

    #variable clip [$w.zinc add curve 1 { {0 150} {150 0} {470 20} {580 200}
    #    {600 300} {500 560} {50 550} {10 450} {100 480}} -closed 1 -visible 0]
    #$w.zinc itemconfigure 1 -clip $clip

    $w.zinc add text 1 -position {51 521} -anchor w \
	-priority 20 -text $text -color white

    $w.zinc add text 1 -position {50 520} -anchor w \
	-priority 20 -text $text -color black

    $w.zinc add group $topGroup -tags __svg__1 -priority 10
    $w.zinc add group __svg__1 -tags __g__2 -priority 10
    $w.zinc add curve __g__2 {{-122.304 84.285} {-122.304 84.285 c} {-122.203 86.179 c} {-123.027 86.16} {-123.851 86.141 c} {-140.305 38.066 c} {-160.833 40.309} {-160.833 40.309 c} {-143.05 32.956 c} {-122.304 84.285}} -tags __path__3 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__4 -priority 10
    $w.zinc add curve __g__4 {{-118.774 81.262} {-118.774 81.262 c} {-119.323 83.078 c} {-120.092 82.779} {-120.86 82.481 c} {-119.977 31.675 c} {-140.043 26.801} {-140.043 26.801 c} {-120.82 25.937 c} {-118.774 81.262}} -tags __path__5 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__6 -priority 10
    $w.zinc add curve __g__6 {{-91.284 123.59} {-91.284 123.59 c} {-89.648 124.55 c} {-90.118 125.227} {-90.589 125.904 c} {-139.763 113.102 c} {-149.218 131.459} {-149.218 131.459 c} {-145.539 112.572 c} {-91.284 123.59}} -tags __path__7 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__8 -priority 10
    $w.zinc add curve __g__8 {{-94.093 133.801} {-94.093 133.801 c} {-92.237 134.197 c} {-92.471 134.988} {-92.704 135.779 c} {-143.407 139.121 c} {-146.597 159.522} {-146.597 159.522 c} {-149.055 140.437 c} {-94.093 133.801}} -tags __path__9 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__10 -priority 10
    $w.zinc add curve __g__10 {{-98.304 128.276} {-98.304 128.276 c} {-96.526 128.939 c} {-96.872 129.687} {-97.218 130.435 c} {-147.866 126.346 c} {-153.998 146.064} {-153.998 146.064 c} {-153.646 126.825 c} {-98.304 128.276}} -tags __path__11 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__12 -priority 10
    $w.zinc add curve __g__12 {{-109.009 110.072} {-109.009 110.072 c} {-107.701 111.446 c} {-108.34 111.967} {-108.979 112.488 c} {-152.722 86.634 c} {-166.869 101.676} {-166.869 101.676 c} {-158.128 84.533 c} {-109.009 110.072}} -tags __path__13 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__14 -priority 10
    $w.zinc add curve __g__14 {{-116.554 114.263} {-116.554 114.263 c} {-115.098 115.48 c} {-115.674 116.071} {-116.25 116.661 c} {-162.638 95.922 c} {-174.992 112.469} {-174.992 112.469 c} {-168.247 94.447 c} {-116.554 114.263}} -tags __path__15 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__16 -priority 10
    $w.zinc add curve __g__16 {{-119.154 118.335} {-119.154 118.335 c} {-117.546 119.343 c} {-118.036 120.006} {-118.526 120.669 c} {-167.308 106.446 c} {-177.291 124.522} {-177.291 124.522 c} {-173.066 105.749 c} {-119.154 118.335}} -tags __path__17 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__18 -priority 10
    $w.zinc add curve __g__18 {{-108.42 118.949} {-108.42 118.949 c} {-107.298 120.48 c} {-107.999 120.915} {-108.7 121.35 c} {-148.769 90.102 c} {-164.727 103.207} {-164.727 103.207 c} {-153.862 87.326 c} {-108.42 118.949}} -tags __path__19 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__20 -priority 10
    $w.zinc add curve __g__20 {{-128.2 90} {-128.2 90 c} {-127.6 91.8 c} {-128.4 92} {-129.2 92.2 c} {-157.8 50.2 c} {-177.001 57.8} {-177.001 57.8 c} {-161.8 46 c} {-128.2 90}} -tags __path__21 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__22 -priority 10
    $w.zinc add curve __g__22 {{-127.505 96.979} {-127.505 96.979 c} {-126.53 98.608 c} {-127.269 98.975} {-128.007 99.343 c} {-164.992 64.499 c} {-182.101 76.061} {-182.101 76.061 c} {-169.804 61.261 c} {-127.505 96.979}} -tags __path__23 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__24 -priority 10
    $w.zinc add curve __g__24 {{-127.62 101.349} {-127.62 101.349 c} {-126.498 102.88 c} {-127.199 103.315} {-127.9 103.749 c} {-167.969 72.502 c} {-183.927 85.607} {-183.927 85.607 c} {-173.062 69.726 c} {-127.62 101.349}} -tags __path__25 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.172
    $w.zinc add group __svg__1  -tags __g__26 -priority 10
    $w.zinc add curve __g__26 {{-129.83 103.065} {-129.327 109.113 c} {-128.339 115.682 c} {-126.6 118.801} {-126.6 118.801 c} {-130.2 131.201 c} {-121.4 144.401} {-121.4 144.401 c} {-121.8 151.601 c} {-120.2 154.801} {-120.2 154.801 c} {-116.2 163.201 c} {-111.4 164.001} {-107.516 164.648 c} {-98.793 167.717 c} {-88.932 169.121} {-88.932 169.121 c} {-71.8 183.201 c} {-75 196.001} {-75 196.001 c} {-75.4 212.401 c} {-79 214.001} {-79 214.001 c} {-67.4 202.801 c} {-77 219.601} {-81.4 238.401} {-81.4 238.401 c} {-55.8 216.801 c} {-71.4 235.201} {-81.4 261.201} {-81.4 261.201 c} {-61.8 242.801 c} {-69 251.201} {-72.2 260.001} {-72.2 260.001 c} {-29 232.801 c} {-59.8 262.401} {-59.8 262.401 c} {-51.8 258.801 c} {-47.4 261.601} {-47.4 261.601 c} {-40.6 260.401 c} {-41.4 262.001} {-41.4 262.001 c} {-62.2 272.401 c} {-65.8 290.801} {-65.8 290.801 c} {-57.4 280.801 c} {-60.6 291.601} {-60.2 303.201} {-60.2 303.201 c} {-56.2 281.601 c} {-56.6 319.201} {-56.6 319.201 c} {-37.4 301.201 c} {-49 322.001} {-49 338.801} {-49 338.801 c} {-33.8 322.401 c} {-40.2 335.201} {-40.2 335.201 c} {-30.2 326.401 c} {-34.2 341.601} {-34.2 341.601 c} {-35 352.001 c} {-30.6 340.801} {-30.6 340.801 c} {-14.6 310.201 c} {-20.6 336.401} {-20.6 336.401 c} {-21.4 355.601 c} {-16.6 340.801} {-16.6 340.801 c} {-16.2 351.201 c} {-7 358.401} {-7 358.401 c} {-8.2 307.601 c} {4.6 343.601} {8.6 360.001} {8.6 360.001 c} {11.4 350.801 c} {11 345.601} {11 345.601 c} {25.8 329.201 c} {19 353.601} {19 353.601 c} {34.2 330.801 c} {31 344.001} {31 344.001 c} {23.4 360.001 c} {25 364.801} {25 364.801 c} {41.8 330.001 c} {43 328.401} {43 328.401 c} {41 370.802 c} {51.8 334.801} {51.8 334.801 c} {57.4 346.801 c} {54.6 351.201} {54.6 351.201 c} {62.6 343.201 c} {61.8 340.001} {61.8 340.001 c} {66.4 331.801 c} {69.2 345.401} {69.2 345.401 c} {71 354.801 c} {72.6 351.601} {72.6 351.601 c} {76.6 375.602 c} {77.8 352.801} {77.8 352.801 c} {79.4 339.201 c} {72.2 327.601} {72.2 327.601 c} {73 324.401 c} {70.2 320.401} {70.2 320.401 c} {83.8 342.001 c} {76.6 313.201} {76.6 313.201 c} {87.801 321.201 c} {89.001 321.201} {89.001 321.201 c} {75.4 298.001 c} {84.2 302.801} {84.2 302.801 c} {79 292.401 c} {97.001 304.401} {97.001 304.401 c} {81 288.401 c} {98.601 298.001} {98.601 298.001 c} {106.601 304.401 c} {99.001 294.401} {99.001 294.401 c} {84.6 278.401 c} {106.601 296.401} {106.601 296.401 c} {118.201 312.801 c} {119.001 315.601} {119.001 315.601 c} {109.001 286.401 c} {104.601 283.601} {104.601 283.601 c} {113.001 247.201 c} {154.201 262.801} {154.201 262.801 c} {161.001 280.001 c} {165.401 261.601} {165.401 261.601 c} {178.201 255.201 c} {189.401 282.801} {189.401 282.801 c} {193.401 269.201 c} {192.601 266.401} {192.601 266.401 c} {199.401 267.601 c} {198.601 266.401} {198.601 266.401 c} {211.801 270.801 c} {213.001 270.001} {213.001 270.001 c} {219.801 276.801 c} {220.201 273.201} {220.201 273.201 c} {229.401 276.001 c} {227.401 272.401} {227.401 272.401 c} {236.201 288.001 c} {236.601 291.601} {239.001 277.601} {241.001 280.401} {241.001 280.401 c} {242.601 272.801 c} {241.801 271.601} {241.001 270.401 c} {261.801 278.401 c} {266.601 299.201} {268.601 307.601} {268.601 307.601 c} {274.601 292.801 c} {273.001 288.801} {273.001 288.801 c} {278.201 289.601 c} {278.601 294.001} {278.601 294.001 c} {282.601 270.801 c} {277.801 264.801} {277.801 264.801 c} {282.201 264.001 c} {283.401 267.601} {283.401 260.401} {283.401 260.401 c} {290.601 261.201 c} {290.601 258.801} {290.601 258.801 c} {295.001 254.801 c} {297.001 259.601} {297.001 259.601 c} {284.601 224.401 c} {303.001 243.601} {303.001 243.601 c} {310.201 254.401 c} {306.601 235.601} {303.001 216.801 c} {299.001 215.201 c} {303.801 214.801} {303.801 214.801 c} {304.601 211.201 c} {302.601 209.601} {300.601 208.001 c} {303.801 209.601 c} {303.801 209.601} {303.801 209.601 c} {308.601 213.601 c} {303.401 191.601} {303.401 191.601 c} {309.801 193.201 c} {297.801 164.001} {297.801 164.001 c} {300.601 161.601 c} {296.601 153.201} {296.601 153.201 c} {304.601 157.601 c} {307.401 156.001} {307.401 156.001 c} {307.001 154.401 c} {303.801 150.401} {303.801 150.401 c} {282.201 95.6 c} {302.601 117.601} {302.601 117.601 c} {314.451 131.151 c} {308.051 108.351} {308.051 108.351 c} {298.94 84.341 c} {299.717 80.045} {-129.83 103.065}} -tags __path__27 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1
    $w.zinc add group __svg__1  -tags __g__28 -priority 10
    $w.zinc add curve __g__28 {{299.717 80.245} {300.345 80.426 c} {302.551 81.55 c} {303.801 83.2} {303.801 83.2 c} {310.601 94 c} {305.401 75.6} {305.401 75.6 c} {296.201 46.8 c} {305.001 58} {305.001 58 c} {311.001 65.2 c} {307.801 51.6} {303.936 35.173 c} {301.401 28.8 c} {301.401 28.8} {301.401 28.8 c} {313.001 33.6 c} {286.201 -6} {295.001 -2.4} {295.001 -2.4 c} {275.401 -42 c} {253.801 -47.2} {245.801 -53.2} {245.801 -53.2 c} {284.201 -91.2 c} {271.401 -128} {271.401 -128 c} {264.601 -133.2 c} {255.001 -124} {255.001 -124 c} {248.601 -119.2 c} {242.601 -120.8} {242.601 -120.8 c} {211.801 -119.6 c} {209.801 -119.6} {207.801 -119.6 c} {173.001 -156.8 c} {107.401 -139.2} {107.401 -139.2 c} {102.201 -137.2 c} {97.801 -138.4} {97.801 -138.4 c} {79.4 -154.4 c} {30.6 -131.6} {30.6 -131.6 c} {20.6 -129.6 c} {19 -129.6} {17.4 -129.6 c} {14.6 -129.6 c} {6.6 -123.2} {-1.4 -116.8 c} {-1.8 -116 c} {-3.8 -114.4} {-3.8 -114.4 c} {-20.2 -103.2 c} {-25 -102.4} {-25 -102.4 c} {-36.6 -96 c} {-41 -86} {-44.6 -84.8} {-44.6 -84.8 c} {-46.2 -77.6 c} {-46.6 -76.4} {-46.6 -76.4 c} {-51.4 -72.8 c} {-52.2 -67.2} {-52.2 -67.2 c} {-61 -61.2 c} {-60.6 -56.8} {-60.6 -56.8 c} {-62.2 -51.6 c} {-63 -46.8} {-63 -46.8 c} {-70.2 -42 c} {-69.4 -39.2} {-69.4 -39.2 c} {-77 -25.2 c} {-75.8 -18.4} {-75.8 -18.4 c} {-82.2 -18.8 c} {-85 -16.4} {-85 -16.4 c} {-85.8 -11.6 c} {-87.4 -11.2} {-87.4 -11.2 c} {-90.2 -10 c} {-87.8 -6} {-87.8 -6 c} {-89.4 -3.2 c} {-89.8 -1.6} {-89.8 -1.6 c} {-89 1.2 c} {-93.4 6.8} {-93.4 6.8 c} {-99.8 25.6 c} {-97.8 30.8} {-97.8 30.8 c} {-97.4 35.6 c} {-100.2 37.2} {-100.2 37.2 c} {-103.8 36.8 c} {-95.4 48.8} {-95.4 48.8 c} {-94.6 50 c} {-97.8 52.4} {-97.8 52.4 c} {-115 56 c} {-117.4 72.4} {-117.4 72.4 c} {-131 87.2 c} {-131 92.4} {-131 94.705 c} {-130.729 97.852 c} {-130.03 102.465} {-130.03 102.465 c} {-130.6 110.801 c} {-103 111.601} {-75.4 112.401 c} {299.717 80.245 c} {299.717 80.245}} -tags __path__29 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#cc7226 -filled 1
    $w.zinc add group __svg__1  -tags __g__30 -priority 10
    $w.zinc add curve __g__30 {{-115.6 102.6} {-140.6 63.2 c} {-126.2 119.601 c} {-126.2 119.601} {-117.4 154.001 c} {12.2 116.401 c} {12.2 116.401} {12.2 116.401 c} {181.001 86 c} {192.201 82} {203.401 78 c} {298.601 84.4 c} {298.601 84.4} {293.001 67.6} {228.201 21.2 c} {209.001 44.4 c} {195.401 40.4} {181.801 36.4 c} {184.201 46 c} {181.001 46.8} {177.801 47.6 c} {138.601 22.8 c} {132.201 23.6} {125.801 24.4 c} {100.459 0.649 c} {115.401 32.4} {131.401 66.4 c} {57 71.6 c} {40.2 60.4} {23.4 49.2 c} {47.4 78.8 c} {47.4 78.8} {65.8 98.8 c} {31.4 82 c} {31.4 82} {-3 69.2 c} {-27 94.8 c} {-30.2 95.6} {-33.4 96.4 c} {-38.2 99.6 c} {-39 93.2} {-39.8 86.8 c} {-47.31 70.099 c} {-79 96.4} {-99 113.001 c} {-112.8 91 c} {-112.8 91} {-115.6 102.6}} -tags __path__31 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__32 -priority 10
    $w.zinc add curve __g__32 {{133.51 25.346} {127.11 26.146 c} {101.743 2.407 c} {116.71 34.146} {133.31 69.346 c} {58.31 73.346 c} {41.51 62.146} {24.709 50.946 c} {48.71 80.546 c} {48.71 80.546} {67.11 100.546 c} {32.709 83.746 c} {32.709 83.746} {-1.691 70.946 c} {-25.691 96.546 c} {-28.891 97.346} {-32.091 98.146 c} {-36.891 101.346 c} {-37.691 94.946} {-38.491 88.546 c} {-45.87 72.012 c} {-77.691 98.146} {-98.927 115.492 c} {-112.418 94.037 c} {-112.418 94.037} {-115.618 104.146} {-140.618 64.346 c} {-125.546 122.655 c} {-125.546 122.655} {-116.745 157.056 c} {13.509 118.146 c} {13.509 118.146} {13.509 118.146 c} {182.31 87.746 c} {193.51 83.746} {204.71 79.746 c} {299.038 86.073 c} {299.038 86.073} {293.51 68.764} {228.71 22.364 c} {210.31 46.146 c} {196.71 42.146} {183.11 38.146 c} {185.51 47.746 c} {182.31 48.546} {179.11 49.346 c} {139.91 24.546 c} {133.51 25.346}} -tags __path__33 -priority 10 -filled 1 -closed 1 -fillcolor \#e87f3a -filled 1 -linecolor \#e87f3a
    $w.zinc add group __svg__1  -tags __g__34 -priority 10
    $w.zinc add curve __g__34 {{134.819 27.091} {128.419 27.891 c} {103.685 3.862 c} {118.019 35.891} {134.219 72.092 c} {59.619 75.092 c} {42.819 63.892} {26.019 52.692 c} {50.019 82.292 c} {50.019 82.292} {68.419 102.292 c} {34.019 85.492 c} {34.019 85.492} {-0.381 72.692 c} {-24.382 98.292 c} {-27.582 99.092} {-30.782 99.892 c} {-35.582 103.092 c} {-36.382 96.692} {-37.182 90.292 c} {-44.43 73.925 c} {-76.382 99.892} {-98.855 117.983 c} {-112.036 97.074 c} {-112.036 97.074} {-115.636 105.692} {-139.436 66.692 c} {-124.891 125.71 c} {-124.891 125.71} {-116.091 160.11 c} {14.819 119.892 c} {14.819 119.892} {14.819 119.892 c} {183.619 89.492 c} {194.819 85.492} {206.019 81.492 c} {299.474 87.746 c} {299.474 87.746} {294.02 69.928} {229.219 23.528 c} {211.619 47.891 c} {198.019 43.891} {184.419 39.891 c} {186.819 49.491 c} {183.619 50.292} {180.419 51.092 c} {141.219 26.291 c} {134.819 27.091}} -tags __path__35 -priority 10 -filled 1 -closed 1 -fillcolor \#ea8c4d -filled 1 -linecolor \#ea8c4d
    $w.zinc add group __svg__1  -tags __g__36 -priority 10
    $w.zinc add curve __g__36 {{136.128 28.837} {129.728 29.637 c} {104.999 5.605 c} {119.328 37.637} {136.128 75.193 c} {60.394 76.482 c} {44.128 65.637} {27.328 54.437 c} {51.328 84.037 c} {51.328 84.037} {69.728 104.037 c} {35.328 87.237 c} {35.328 87.237} {0.928 74.437 c} {-23.072 100.037 c} {-26.272 100.837} {-29.472 101.637 c} {-34.272 104.837 c} {-35.072 98.437} {-35.872 92.037 c} {-42.989 75.839 c} {-75.073 101.637} {-98.782 120.474 c} {-111.655 100.11 c} {-111.655 100.11} {-115.655 107.237} {-137.455 70.437 c} {-124.236 128.765 c} {-124.236 128.765} {-115.436 163.165 c} {16.128 121.637 c} {16.128 121.637} {16.128 121.637 c} {184.928 91.237 c} {196.129 87.237} {207.329 83.237 c} {299.911 89.419 c} {299.911 89.419} {294.529 71.092} {229.729 24.691 c} {212.929 49.637 c} {199.329 45.637} {185.728 41.637 c} {188.128 51.237 c} {184.928 52.037} {181.728 52.837 c} {142.528 28.037 c} {136.128 28.837}} -tags __path__37 -priority 10 -filled 1 -closed 1 -fillcolor \#ec9961 -filled 1 -linecolor \#ec9961
    $w.zinc add group __svg__1  -tags __g__38 -priority 10
    $w.zinc add curve __g__38 {{137.438 30.583} {131.037 31.383 c} {106.814 7.129 c} {120.637 39.383} {137.438 78.583 c} {62.237 78.583 c} {45.437 67.383} {28.637 56.183 c} {52.637 85.783 c} {52.637 85.783} {71.037 105.783 c} {36.637 88.983 c} {36.637 88.983} {2.237 76.183 c} {-21.763 101.783 c} {-24.963 102.583} {-28.163 103.383 c} {-32.963 106.583 c} {-33.763 100.183} {-34.563 93.783 c} {-41.548 77.752 c} {-73.763 103.383} {-98.709 122.965 c} {-111.273 103.146 c} {-111.273 103.146} {-115.673 108.783} {-135.473 73.982 c} {-123.582 131.819 c} {-123.582 131.819} {-114.782 166.22 c} {17.437 123.383 c} {17.437 123.383} {17.437 123.383 c} {186.238 92.983 c} {197.438 88.983} {208.638 84.983 c} {300.347 91.092 c} {300.347 91.092} {295.038 72.255} {230.238 25.855 c} {214.238 51.383 c} {200.638 47.383} {187.038 43.383 c} {189.438 52.983 c} {186.238 53.783} {183.038 54.583 c} {143.838 29.783 c} {137.438 30.583}} -tags __path__39 -priority 10 -filled 1 -closed 1 -fillcolor \#eea575 -filled 1 -linecolor \#eea575
    $w.zinc add group __svg__1  -tags __g__40 -priority 10
    $w.zinc add curve __g__40 {{138.747 32.328} {132.347 33.128 c} {106.383 9.677 c} {121.947 41.128} {141.147 79.928 c} {63.546 80.328 c} {46.746 69.128} {29.946 57.928 c} {53.946 87.528 c} {53.946 87.528} {72.346 107.528 c} {37.946 90.728 c} {37.946 90.728} {3.546 77.928 c} {-20.454 103.528 c} {-23.654 104.328} {-26.854 105.128 c} {-31.654 108.328 c} {-32.454 101.928} {-33.254 95.528 c} {-40.108 79.665 c} {-72.454 105.128} {-98.636 125.456 c} {-110.891 106.183 c} {-110.891 106.183} {-115.691 110.328} {-133.691 77.128 c} {-122.927 134.874 c} {-122.927 134.874} {-114.127 169.274 c} {18.746 125.128 c} {18.746 125.128} {18.746 125.128 c} {187.547 94.728 c} {198.747 90.728} {209.947 86.728 c} {300.783 92.764 c} {300.783 92.764} {295.547 73.419} {230.747 27.019 c} {215.547 53.128 c} {201.947 49.128} {188.347 45.128 c} {190.747 54.728 c} {187.547 55.528} {184.347 56.328 c} {145.147 31.528 c} {138.747 32.328}} -tags __path__41 -priority 10 -filled 1 -closed 1 -fillcolor \#f1b288 -filled 1 -linecolor \#f1b288
    $w.zinc add group __svg__1  -tags __g__42 -priority 10
    $w.zinc add curve __g__42 {{140.056 34.073} {133.655 34.873 c} {107.313 11.613 c} {123.255 42.873} {143.656 82.874 c} {64.855 82.074 c} {48.055 70.874} {31.255 59.674 c} {55.255 89.274 c} {55.255 89.274} {73.655 109.274 c} {39.255 92.474 c} {39.255 92.474} {4.855 79.674 c} {-19.145 105.274 c} {-22.345 106.074} {-25.545 106.874 c} {-30.345 110.074 c} {-31.145 103.674} {-31.945 97.274 c} {-38.668 81.578 c} {-71.145 106.874} {-98.564 127.947 c} {-110.509 109.219 c} {-110.509 109.219} {-115.709 111.874} {-131.709 81.674 c} {-122.273 137.929 c} {-122.273 137.929} {-113.473 172.329 c} {20.055 126.874 c} {20.055 126.874} {20.055 126.874 c} {188.856 96.474 c} {200.056 92.474} {211.256 88.474 c} {301.22 94.437 c} {301.22 94.437} {296.056 74.583} {231.256 28.183 c} {216.856 54.874 c} {203.256 50.874} {189.656 46.873 c} {192.056 56.474 c} {188.856 57.274} {185.656 58.074 c} {146.456 33.273 c} {140.056 34.073}} -tags __path__43 -priority 10 -filled 1 -closed 1 -fillcolor \#f3bf9c -filled 1 -linecolor \#f3bf9c
    $w.zinc add group __svg__1  -tags __g__44 -priority 10
    $w.zinc add curve __g__44 {{141.365 35.819} {134.965 36.619 c} {107.523 13.944 c} {124.565 44.619} {146.565 84.219 c} {66.164 83.819 c} {49.364 72.619} {32.564 61.419 c} {56.564 91.019 c} {56.564 91.019} {74.964 111.019 c} {40.564 94.219 c} {40.564 94.219} {6.164 81.419 c} {-17.836 107.019 c} {-21.036 107.819} {-24.236 108.619 c} {-29.036 111.819 c} {-29.836 105.419} {-30.636 99.019 c} {-37.227 83.492 c} {-69.836 108.619} {-98.491 130.438 c} {-110.127 112.256 c} {-110.127 112.256} {-115.727 113.419} {-130.128 85.019 c} {-121.618 140.983 c} {-121.618 140.983} {-112.818 175.384 c} {21.364 128.619 c} {21.364 128.619} {21.364 128.619 c} {190.165 98.219 c} {201.365 94.219} {212.565 90.219 c} {301.656 96.11 c} {301.656 96.11} {296.565 75.746} {231.765 29.346 c} {218.165 56.619 c} {204.565 52.619} {190.965 48.619 c} {193.365 58.219 c} {190.165 59.019} {186.965 59.819 c} {147.765 35.019 c} {141.365 35.819}} -tags __path__45 -priority 10 -filled 1 -closed 1 -fillcolor \#f5ccb0 -filled 1 -linecolor \#f5ccb0
    $w.zinc add group __svg__1  -tags __g__46 -priority 10
    $w.zinc add curve __g__46 {{142.674 37.565} {136.274 38.365 c} {108.832 15.689 c} {125.874 46.365} {147.874 85.965 c} {67.474 85.565 c} {50.674 74.365} {33.874 63.165 c} {57.874 92.765 c} {57.874 92.765} {76.274 112.765 c} {41.874 95.965 c} {41.874 95.965} {7.473 83.165 c} {-16.527 108.765 c} {-19.727 109.565} {-22.927 110.365 c} {-27.727 113.565 c} {-28.527 107.165} {-29.327 100.765 c} {-35.786 85.405 c} {-68.527 110.365} {-98.418 132.929 c} {-109.745 115.293 c} {-109.745 115.293} {-115.745 114.965} {-129.346 88.564 c} {-120.963 144.038 c} {-120.963 144.038} {-112.163 178.438 c} {22.673 130.365 c} {22.673 130.365} {22.673 130.365 c} {191.474 99.965 c} {202.674 95.965} {213.874 91.965 c} {302.093 97.783 c} {302.093 97.783} {297.075 76.91} {232.274 30.51 c} {219.474 58.365 c} {205.874 54.365} {192.274 50.365 c} {194.674 59.965 c} {191.474 60.765} {188.274 61.565 c} {149.074 36.765 c} {142.674 37.565}} -tags __path__47 -priority 10 -filled 1 -closed 1 -fillcolor \#f8d8c4 -filled 1 -linecolor \#f8d8c4
    $w.zinc add group __svg__1  -tags __g__48 -priority 10
    $w.zinc add curve __g__48 {{143.983 39.31} {137.583 40.11 c} {110.529 17.223 c} {127.183 48.11} {149.183 88.91 c} {68.783 87.31 c} {51.983 76.11} {35.183 64.91 c} {59.183 94.51 c} {59.183 94.51} {77.583 114.51 c} {43.183 97.71 c} {43.183 97.71} {8.783 84.91 c} {-15.217 110.51 c} {-18.417 111.31} {-21.618 112.11 c} {-26.418 115.31 c} {-27.218 108.91} {-28.018 102.51 c} {-34.346 87.318 c} {-67.218 112.11} {-98.345 135.42 c} {-109.363 118.329 c} {-109.363 118.329} {-115.764 116.51} {-128.764 92.51 c} {-120.309 147.093 c} {-120.309 147.093} {-111.509 181.493 c} {23.983 132.11 c} {23.983 132.11} {23.983 132.11 c} {192.783 101.71 c} {203.983 97.71} {215.183 93.71 c} {302.529 99.456 c} {302.529 99.456} {297.583 78.074} {232.783 31.673 c} {220.783 60.11 c} {207.183 56.11} {193.583 52.11 c} {195.983 61.71 c} {192.783 62.51} {189.583 63.31 c} {150.383 38.51 c} {143.983 39.31}} -tags __path__49 -priority 10 -filled 1 -closed 1 -fillcolor \#fae5d7 -filled 1 -linecolor \#fae5d7
    $w.zinc add group __svg__1  -tags __g__50 -priority 10
    $w.zinc add curve __g__50 {{145.292 41.055} {138.892 41.855 c} {112.917 18.411 c} {128.492 49.855} {149.692 92.656 c} {70.092 89.056 c} {53.292 77.856} {36.492 66.656 c} {60.492 96.256 c} {60.492 96.256} {78.892 116.256 c} {44.492 99.456 c} {44.492 99.456} {10.092 86.656 c} {-13.908 112.256 c} {-17.108 113.056} {-20.308 113.856 c} {-25.108 117.056 c} {-25.908 110.656} {-26.708 104.256 c} {-32.905 89.232 c} {-65.908 113.856} {-98.273 137.911 c} {-108.982 121.365 c} {-108.982 121.365} {-115.782 118.056} {-128.582 94.856 c} {-119.654 150.147 c} {-119.654 150.147} {-110.854 184.547 c} {25.292 133.856 c} {25.292 133.856} {25.292 133.856 c} {194.093 103.456 c} {205.293 99.456} {216.493 95.456 c} {302.965 101.128 c} {302.965 101.128} {298.093 79.237} {233.292 32.837 c} {222.093 61.856 c} {208.493 57.856} {194.893 53.855 c} {197.293 63.456 c} {194.093 64.256} {190.892 65.056 c} {151.692 40.255 c} {145.292 41.055}} -tags __path__51 -priority 10 -filled 1 -closed 1 -fillcolor \#fcf2eb -filled 1 -linecolor \#fcf2eb
    $w.zinc add group __svg__1  -tags __g__52 -priority 10
    $w.zinc add curve __g__52 {{-115.8 119.601} {-128.6 97.6 c} {-119 153.201 c} {-119 153.201} {-110.2 187.601 c} {26.6 135.601 c} {26.6 135.601} {26.6 135.601 c} {195.401 105.2 c} {206.601 101.2} {217.801 97.2 c} {303.401 102.8 c} {303.401 102.8} {298.601 80.4} {233.801 34 c} {223.401 63.6 c} {209.801 59.6} {196.201 55.6 c} {198.601 65.2 c} {195.401 66} {192.201 66.8 c} {153.001 42 c} {146.601 42.8} {140.201 43.6 c} {114.981 19.793 c} {129.801 51.6} {152.028 99.307 c} {69.041 89.227 c} {54.6 79.6} {37.8 68.4 c} {61.8 98 c} {61.8 98} {80.2 118.001 c} {45.8 101.2 c} {45.8 101.2} {11.4 88.4 c} {-12.6 114.001 c} {-15.8 114.801} {-19 115.601 c} {-23.8 118.801 c} {-24.6 112.401} {-25.4 106 c} {-31.465 91.144 c} {-64.6 115.601} {-98.2 140.401 c} {-108.6 124.401 c} {-108.6 124.401} {-115.8 119.601}} -tags __path__53 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__54 -priority 10
    $w.zinc add curve __g__54 {{-74.2 149.601} {-74.2 149.601 c} {-81.4 161.201 c} {-60.6 174.401} {-60.6 174.401 c} {-59.2 175.801 c} {-77.2 171.601} {-77.2 171.601 c} {-83.4 169.601 c} {-85 159.201} {-85 159.201 c} {-89.8 154.801 c} {-94.6 149.201} {-99.4 143.601 c} {-74.2 149.601 c} {-74.2 149.601}} -tags __path__55 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__56 -priority 10
    $w.zinc add curve __g__56 {{65.8 102} {65.8 102 c} {83.498 128.821 c} {82.9 133.601} {81.6 144.001 c} {81.4 153.601 c} {84.6 157.601} {87.801 161.601 c} {96.601 194.801 c} {96.601 194.801} {96.601 194.801 c} {96.201 196.001 c} {108.601 158.001} {108.601 158.001 c} {120.201 142.001 c} {100.201 123.601} {100.201 123.601 c} {65 94.8 c} {65.8 102}} -tags __path__57 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__58 -priority 10
    $w.zinc add curve __g__58 {{-54.2 176.401} {-54.2 176.401 c} {-43 183.601 c} {-57.4 214.801} {-51 212.401} {-51 212.401 c} {-51.8 223.601 c} {-55 226.001} {-47.8 222.801} {-47.8 222.801 c} {-43 230.801 c} {-47 235.601} {-47 235.601 c} {-30.2 243.601 c} {-31 250.001} {-31 250.001 c} {-24.6 242.001 c} {-28.6 235.601} {-32.6 229.201 c} {-39.8 233.201 c} {-39 214.801} {-47.8 218.001} {-47.8 218.001 c} {-42.2 209.201 c} {-42.2 202.801} {-50.2 205.201} {-50.2 205.201 c} {-34.731 178.623 c} {-45.4 177.201} {-51.4 176.401 c} {-54.2 176.401 c} {-54.2 176.401}} -tags __path__59 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__60 -priority 10
    $w.zinc add curve __g__60 {{-21.8 193.201} {-21.8 193.201 c} {-19 188.801 c} {-21.8 189.601} {-24.6 190.401 c} {-55.8 205.201 c} {-61.8 214.801} {-61.8 214.801 c} {-27.4 190.401 c} {-21.8 193.201}} -tags __path__61 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__62 -priority 10
    $w.zinc add curve __g__62 {{-11.4 201.201} {-11.4 201.201 c} {-8.6 196.801 c} {-11.4 197.601} {-14.2 198.401 c} {-45.4 213.201 c} {-51.4 222.801} {-51.4 222.801 c} {-17 198.401 c} {-11.4 201.201}} -tags __path__63 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__64 -priority 10
    $w.zinc add curve __g__64 {{1.8 186.001} {1.8 186.001 c} {4.6 181.601 c} {1.8 182.401} {-1 183.201 c} {-32.2 198.001 c} {-38.2 207.601} {-38.2 207.601 c} {-3.8 183.201 c} {1.8 186.001}} -tags __path__65 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__66 -priority 10
    $w.zinc add curve __g__66 {{-21.4 229.601} {-21.4 229.601 c} {-21.4 223.601 c} {-24.2 224.401} {-27 225.201 c} {-63 242.801 c} {-69 252.401} {-69 252.401 c} {-27 226.801 c} {-21.4 229.601}} -tags __path__67 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__68 -priority 10
    $w.zinc add curve __g__68 {{-20.2 218.801} {-20.2 218.801 c} {-19 214.001 c} {-21.8 214.801} {-23.8 214.801 c} {-50.2 226.401 c} {-56.2 236.001} {-56.2 236.001 c} {-26.6 214.401 c} {-20.2 218.801}} -tags __path__69 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__70 -priority 10
    $w.zinc add curve __g__70 {{-34.6 266.401} {-44.6 274.001} {-44.6 274.001 c} {-34.2 266.401 c} {-30.6 267.601} {-30.6 267.601 c} {-37.4 278.801 c} {-38.2 284.001} {-38.2 284.001 c} {-27.8 271.201 c} {-22.2 271.601} {-22.2 271.601 c} {-14.6 272.001 c} {-14.6 282.801} {-14.6 282.801 c} {-9 272.401 c} {-5.8 272.801} {-5.8 272.801 c} {-4.6 279.201 c} {-5.8 286.001} {-5.8 286.001 c} {-1.8 278.401 c} {2.2 280.001} {2.2 280.001 c} {8.6 278.001 c} {7.8 289.601} {7.8 289.601 c} {7.8 300.001 c} {7 302.801} {7 302.801 c} {12.6 276.401 c} {15 276.001} {15 276.001 c} {23 274.801 c} {27.8 283.601} {27.8 283.601 c} {23.8 276.001 c} {28.6 278.001} {28.6 278.001 c} {39.4 279.601 c} {42.6 286.401} {42.6 286.401 c} {35.8 274.401 c} {41.4 277.601} {41.4 277.601 c} {48.2 277.601 c} {49.4 284.001} {49.4 284.001 c} {57.8 305.201 c} {59.8 306.801} {59.8 306.801 c} {52.2 285.201 c} {53.8 285.201} {53.8 285.201 c} {51.8 273.201 c} {57 288.001} {57 288.001 c} {53.8 274.001 c} {59.4 274.801} {65 275.601 c} {69.4 285.601 c} {77.8 283.201} {77.8 283.201 c} {87.401 288.801 c} {89.401 219.601} {-34.6 266.401}} -tags __path__71 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__72 -priority 10
    $w.zinc add curve __g__72 {{-29.8 173.601} {-29.8 173.601 c} {-15 167.601 c} {25 173.601} {25 173.601 c} {32.2 174.001 c} {39 165.201} {45.8 156.401 c} {72.6 149.201 c} {79 151.201} {88.601 157.601} {89.401 158.801} {89.401 158.801 c} {101.801 169.201 c} {102.201 176.801} {102.601 184.401 c} {87.801 232.401 c} {78.2 248.401} {68.6 264.401 c} {59 276.801 c} {39.8 274.401} {39.8 274.401 c} {19 270.401 c} {-6.6 274.401} {-6.6 274.401 c} {-35.8 272.801 c} {-38.6 264.801} {-41.4 256.801 c} {-27.4 241.601 c} {-27.4 241.601} {-27.4 241.601 c} {-23 233.201 c} {-24.2 218.801} {-25.4 204.401 c} {-25 176.401 c} {-29.8 173.601}} -tags __path__73 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__74 -priority 10
    $w.zinc add curve __g__74 {{-7.8 175.601} {0.6 194.001 c} {-29 259.201 c} {-29 259.201} {-31 260.801 c} {-16.34 266.846 c} {-6.2 264.401} {4.746 261.763 c} {45 266.001 c} {45 266.001} {68.6 250.401 c} {81.4 206.001 c} {81.4 206.001} {81.4 206.001 c} {91.801 182.001 c} {74.2 178.801} {56.6 175.601 c} {-7.8 175.601 c} {-7.8 175.601}} -tags __path__75 -priority 10 -filled 1 -closed 1 -fillcolor \#e5668c -filled 1 -linecolor \#e5668c
    $w.zinc add group __svg__1  -tags __g__76 -priority 10
    $w.zinc add curve __g__76 {{-9.831 206.497} {-6.505 193.707 c} {-4.921 181.906 c} {-7.8 175.601} {-7.8 175.601 c} {54.6 182.001 c} {65.8 161.201} {70.041 153.326 c} {84.801 184.001 c} {84.4 193.601} {84.4 193.601 c} {21.4 208.001 c} {6.6 196.801} {-9.831 206.497}} -tags __path__77 -priority 10 -filled 1 -closed 1 -fillcolor \#b23259 -filled 1 -linecolor \#b23259
    $w.zinc add group __svg__1  -tags __g__78 -priority 10
    $w.zinc add curve __g__78 {{-5.4 222.801} {-5.4 222.801 c} {-3.4 230.001 c} {-5.8 234.001} {-5.8 234.001 c} {-7.4 234.801 c} {-8.6 235.201} {-8.6 235.201 c} {-7.4 238.801 c} {-1.4 240.401} {-1.4 240.401 c} {0.6 244.801 c} {3 245.201} {5.4 245.601 c} {10.2 251.201 c} {14.2 250.001} {18.2 248.801 c} {29.4 244.801 c} {29.4 244.801} {29.4 244.801 c} {35 241.601 c} {43.8 245.201} {43.8 245.201 c} {46.175 244.399 c} {46.6 240.401} {47.1 235.701 c} {50.2 232.001 c} {52.2 230.001} {54.2 228.001 c} {63.8 215.201 c} {62.6 214.801} {61.4 214.401 c} {-5.4 222.801 c} {-5.4 222.801}} -tags __path__79 -priority 10 -filled 1 -closed 1 -fillcolor \#a5264c -filled 1 -linecolor \#a5264c
    $w.zinc add group __svg__1  -tags __g__80 -priority 10
    $w.zinc add curve __g__80 {{-9.8 174.401} {-9.8 174.401 c} {-12.6 196.801 c} {-9.4 205.201} {-6.2 213.601 c} {-7 215.601 c} {-7.8 219.601} {-8.6 223.601 c} {-4.2 233.601 c} {1.4 239.601} {13.4 241.201} {13.4 241.201 c} {28.6 237.601 c} {37.8 240.401} {37.8 240.401 c} {46.794 241.744 c} {50.2 226.801} {50.2 226.801 c} {55 220.401 c} {62.2 217.601} {69.4 214.801 c} {76.6 173.201 c} {72.6 165.201} {68.6 157.201 c} {54.2 152.801 c} {38.2 168.401} {22.2 184.001 c} {20.2 167.201 c} {-9.8 174.401}} -tags __path__81 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ff727f -filled 1
    $w.zinc add group __svg__1  -tags __g__82 -priority 10
    $w.zinc add curve __g__82 {{-8.2 249.201} {-8.2 249.201 c} {-9 247.201 c} {-13.4 246.801} {-13.4 246.801 c} {-35.8 243.201 c} {-44.2 230.801} {-44.2 230.801 c} {-51 225.201 c} {-46.6 236.801} {-46.6 236.801 c} {-36.2 257.201 c} {-29.4 260.001} {-29.4 260.001 c} {-13 264.001 c} {-8.2 249.201}} -tags __path__83 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__84 -priority 10
    $w.zinc add curve __g__84 {{71.742 185.229} {72.401 177.323 c} {74.354 168.709 c} {72.6 165.201} {66.154 152.307 c} {49.181 157.695 c} {38.2 168.401} {22.2 184.001 c} {20.2 167.201 c} {-9.8 174.401} {-9.8 174.401 c} {-11.545 188.364 c} {-10.705 198.376} {-10.705 198.376 c} {26.6 186.801 c} {27.4 192.401} {27.4 192.401 c} {29 189.201 c} {38.2 189.201} {47.4 189.201 c} {70.142 188.029 c} {71.742 185.229}} -tags __path__85 -priority 10 -filled 1 -closed 1 -fillcolor \#cc3f4c -filled 1 -linecolor \#cc3f4c
    $w.zinc add group __svg__1  -tags __g__86 -priority 10
    $w.zinc add curve __g__86 {{28.6 175.201} {28.6 175.201 c} {33.4 180.001 c} {29.8 189.601} {29.8 189.601 c} {15.4 205.601 c} {17.4 219.601}} -tags __path__87 -priority 10 -filled 1 -closed 0 -linecolor \#a51926 -linewidth 2
    $w.zinc add group __svg__1  -tags __g__88 -priority 10
    $w.zinc add curve __g__88 {{-19.4 260.001} {-19.4 260.001 c} {-23.8 247.201 c} {-15 254.001} {-15 254.001 c} {-10.2 256.001 c} {-11.4 257.601} {-12.6 259.201 c} {-18.2 263.201 c} {-19.4 260.001}} -tags __path__89 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__90 -priority 10
    $w.zinc add curve __g__90 {{-14.36 261.201} {-14.36 261.201 c} {-17.88 250.961 c} {-10.84 256.401} {-10.84 256.401 c} {-6.419 258.849 c} {-7.96 259.281} {-12.52 260.561 c} {-7.96 263.121 c} {-14.36 261.201}} -tags __path__91 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__92 -priority 10
    $w.zinc add curve __g__92 {{-9.56 261.201} {-9.56 261.201 c} {-13.08 250.961 c} {-6.04 256.401} {-6.04 256.401 c} {-1.665 258.711 c} {-3.16 259.281} {-6.52 260.561 c} {-3.16 263.121 c} {-9.56 261.201}} -tags __path__93 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__94 -priority 10
    $w.zinc add curve __g__94 {{-2.96 261.401} {-2.96 261.401 c} {-6.48 251.161 c} {0.56 256.601} {0.56 256.601 c} {4.943 258.933 c} {3.441 259.481} {0.48 260.561 c} {3.441 263.321 c} {-2.96 261.401}} -tags __path__95 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__96 -priority 10
    $w.zinc add curve __g__96 {{3.52 261.321} {3.52 261.321 c} {0 251.081 c} {7.041 256.521} {7.041 256.521 c} {10.881 258.121 c} {9.921 259.401} {8.961 260.681 c} {9.921 263.241 c} {3.52 261.321}} -tags __path__97 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__98 -priority 10
    $w.zinc add curve __g__98 {{10.2 262.001} {10.2 262.001 c} {5.4 249.601 c} {14.6 256.001} {14.6 256.001 c} {19.4 258.001 c} {18.2 259.601} {17 261.201 c} {18.2 264.401 c} {10.2 262.001}} -tags __path__99 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__100 -priority 10
    $w.zinc add curve __g__100 {{-18.2 244.801} {-18.2 244.801 c} {-5 242.001 c} {1 245.201} {1 245.201 c} {7 246.401 c} {8.2 246.001} {9.4 245.601 c} {12.6 245.201 c} {12.6 245.201}} -tags __path__101 -priority 10 -filled 1 -closed 0 -linecolor \#a5264c -linewidth 2
    $w.zinc add group __svg__1  -tags __g__102 -priority 10
    $w.zinc add curve __g__102 {{15.8 253.601} {15.8 253.601 c} {27.8 240.001 c} {39.8 244.401} {46.816 246.974 c} {45.8 243.601 c} {46.6 240.801} {47.4 238.001 c} {47.6 233.801 c} {52.6 230.801}} -tags __path__103 -priority 10 -filled 1 -closed 0 -linecolor \#a5264c -linewidth 2
    $w.zinc add group __svg__1  -tags __g__104 -priority 10
    $w.zinc add curve __g__104 {{33 237.601} {33 237.601 c} {29 226.801 c} {26.2 239.601} {23.4 252.401 c} {20.2 256.001 c} {18.6 258.801} {18.6 258.801 c} {18.6 264.001 c} {27 263.601} {27 263.601 c} {37.8 263.201 c} {38.2 260.401} {38.6 257.601 c} {37 246.001 c} {33 237.601}} -tags __path__105 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__106 -priority 10
    $w.zinc add curve __g__106 {{47 244.801} {47 244.801 c} {50.6 242.401 c} {53 243.601}} -tags __path__107 -priority 10 -filled 1 -closed 0 -linecolor \#a5264c -linewidth 2
    $w.zinc add group __svg__1  -tags __g__108 -priority 10
    $w.zinc add curve __g__108 {{53.5 228.401} {53.5 228.401 c} {56.4 223.501 c} {61.2 222.701}} -tags __path__109 -priority 10 -filled 1 -closed 0 -linecolor \#a5264c -linewidth 2
    $w.zinc add group __svg__1  -tags __g__110 -priority 10
    $w.zinc add curve __g__110 {{-25.8 265.201} {-25.8 265.201 c} {-7.8 268.401 c} {-3.4 266.801} {-3.4 266.801 c} {5.4 266.801 c} {-3 268.801} {-3 268.801 c} {-15.8 268.801 c} {-23.8 267.601} {-23.8 267.601 c} {-35.4 262.001 c} {-25.8 265.201}} -tags __path__111 -priority 10 -filled 1 -closed 1 -fillcolor \#b2b2b2 -filled 1 -linecolor \#b2b2b2
    $w.zinc add group __svg__1  -tags __g__112 -priority 10
    $w.zinc add curve __g__112 {{-11.8 172.001} {-11.8 172.001 c} {5.8 172.001 c} {7.8 172.801} {7.8 172.801 c} {15 203.601 c} {11.4 211.201} {11.4 211.201 c} {10.2 214.001 c} {7.4 208.401} {7.4 208.401 c} {-11 175.601 c} {-14.2 173.601} {-17.4 171.601 c} {-13 172.001 c} {-11.8 172.001}} -tags __path__113 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__114 -priority 10
    $w.zinc add curve __g__114 {{-88.9 169.301} {-88.9 169.301 c} {-80 171.001 c} {-67.4 173.601} {-67.4 173.601 c} {-62.6 196.001 c} {-59.4 200.801} {-56.2 205.601 c} {-59.8 205.601 c} {-63.4 202.801} {-67 200.001 c} {-81.8 186.001 c} {-83.8 181.601} {-85.8 177.201 c} {-88.9 169.301 c} {-88.9 169.301}} -tags __path__115 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__116 -priority 10
    $w.zinc add curve __g__116 {{-67.039 173.818} {-67.039 173.818 c} {-61.239 175.366 c} {-60.23 177.581} {-59.222 179.795 c} {-61.432 183.092 c} {-61.432 183.092} {-61.432 183.092 c} {-62.432 186.397 c} {-63.634 184.235} {-64.836 182.072 c} {-67.708 174.412 c} {-67.039 173.818}} -tags __path__117 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__118 -priority 10
    $w.zinc add curve __g__118 {{-67 173.601} {-67 173.601 c} {-63.4 178.801 c} {-59.8 178.801} {-56.2 178.801 c} {-55.818 178.388 c} {-53 179.001} {-48.4 180.001 c} {-48.8 178.001 c} {-42.2 179.201} {-39.56 179.681 c} {-37 178.801 c} {-34.2 180.001} {-31.4 181.201 c} {-28.2 180.401 c} {-27 178.401} {-25.8 176.401 c} {-21 172.201 c} {-21 172.201} {-21 172.201 c} {-33.8 174.001 c} {-36.6 174.801} {-36.6 174.801 c} {-59 176.001 c} {-67 173.601}} -tags __path__119 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__120 -priority 10
    $w.zinc add curve __g__120 {{-22.4 173.801} {-22.4 173.801 c} {-28.85 177.301 c} {-29.25 179.701} {-29.65 182.101 c} {-24 185.801 c} {-24 185.801} {-24 185.801 c} {-21.25 190.401 c} {-20.65 188.001} {-20.05 185.601 c} {-21.6 174.201 c} {-22.4 173.801}} -tags __path__121 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__122 -priority 10
    $w.zinc add curve __g__122 {{-59.885 179.265} {-59.885 179.265 c} {-52.878 190.453 c} {-52.661 179.242} {-52.661 179.242 c} {-52.104 177.984 c} {-53.864 177.962} {-59.939 177.886 c} {-58.418 173.784 c} {-59.885 179.265}} -tags __path__123 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__124 -priority 10
    $w.zinc add curve __g__124 {{-52.707 179.514} {-52.707 179.514 c} {-44.786 190.701 c} {-45.422 179.421} {-45.422 179.421 c} {-45.415 179.089 c} {-47.168 178.936} {-51.915 178.522 c} {-51.57 174.004 c} {-52.707 179.514}} -tags __path__125 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__126 -priority 10
    $w.zinc add curve __g__126 {{-45.494 179.522} {-45.494 179.522 c} {-37.534 190.15 c} {-38.203 180.484} {-38.203 180.484 c} {-38.084 179.251 c} {-39.738 178.95} {-43.63 178.244 c} {-43.841 174.995 c} {-45.494 179.522}} -tags __path__127 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__128 -priority 10
    $w.zinc add curve __g__128 {{-38.618 179.602} {-38.618 179.602 c} {-30.718 191.163 c} {-30.37 181.382} {-30.37 181.382 c} {-28.726 180.004 c} {-30.472 179.782} {-36.29 179.042 c} {-35.492 174.588 c} {-38.618 179.602}} -tags __path__129 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffcc -filled 1 -linewidth 0.5
    $w.zinc add group __svg__1  -tags __g__130 -priority 10
    $w.zinc add curve __g__130 {{-74.792 183.132} {-82.45 181.601} {-85.05 176.601 c} {-87.15 170.451 c} {-87.15 170.451} {-87.15 170.451 c} {-80.8 171.451 c} {-68.3 174.251} {-68.3 174.251 c} {-67.424 177.569 c} {-65.952 183.364} {-74.792 183.132}} -tags __path__131 -priority 10 -filled 1 -closed 1 -fillcolor \#e5e5b2 -filled 1 -linecolor \#e5e5b2
    $w.zinc add group __svg__1  -tags __g__132 -priority 10
    $w.zinc add curve __g__132 {{-9.724 178.47} {-11.39 175.964 c} {-12.707 174.206 c} {-13.357 173.8} {-16.37 171.917 c} {-12.227 172.294 c} {-11.098 172.294} {-11.098 172.294 c} {5.473 172.294 c} {7.356 173.047} {7.356 173.047 c} {7.88 175.289 c} {8.564 178.68} {8.564 178.68 c} {-1.524 176.67 c} {-9.724 178.47}} -tags __path__133 -priority 10 -filled 1 -closed 1 -fillcolor \#e5e5b2 -filled 1 -linecolor \#e5e5b2
    $w.zinc add group __svg__1  -tags __g__134 -priority 10
    $w.zinc add curve __g__134 {{43.88 40.321} {71.601 44.281 c} {97.121 8.641 c} {98.881 -1.04} {100.641 -10.72 c} {90.521 -22.6 c} {90.521 -22.6} {91.841 -25.68 c} {87.001 -39.76 c} {81.721 -49} {76.441 -58.24 c} {60.54 -57.266 c} {43 -58.24} {27.16 -59.12 c} {8.68 -35.8 c} {7.36 -34.04} {6.04 -32.28 c} {12.2 6.001 c} {13.52 11.721} {14.84 17.441 c} {12.2 43.841 c} {12.2 43.841} {46.44 34.741 c} {16.16 36.361 c} {43.88 40.321}} -tags __path__135 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__136 -priority 10
    $w.zinc add curve __g__136 {{8.088 -33.392} {6.792 -31.664 c} {12.84 5.921 c} {14.136 11.537} {15.432 17.153 c} {12.84 43.073 c} {12.84 43.073} {45.512 34.193 c} {16.728 35.729 c} {43.944 39.617} {71.161 43.505 c} {96.217 8.513 c} {97.945 -0.992} {99.673 -10.496 c} {89.737 -22.16 c} {89.737 -22.16} {91.033 -25.184 c} {86.281 -39.008 c} {81.097 -48.08} {75.913 -57.152 c} {60.302 -56.195 c} {43.08 -57.152} {27.528 -58.016 c} {9.384 -35.12 c} {8.088 -33.392}} -tags __path__137 -priority 10 -filled 1 -closed 1 -fillcolor \#ea8e51 -filled 1 -linecolor \#ea8e51
    $w.zinc add group __svg__1  -tags __g__138 -priority 10
    $w.zinc add curve __g__138 {{8.816 -32.744} {7.544 -31.048 c} {13.48 5.841 c} {14.752 11.353} {16.024 16.865 c} {13.48 42.305 c} {13.48 42.305} {44.884 33.145 c} {17.296 35.097 c} {44.008 38.913} {70.721 42.729 c} {95.313 8.385 c} {97.009 -0.944} {98.705 -10.272 c} {88.953 -21.72 c} {88.953 -21.72} {90.225 -24.688 c} {85.561 -38.256 c} {80.473 -47.16} {75.385 -56.064 c} {60.063 -55.125 c} {43.16 -56.064} {27.896 -56.912 c} {10.088 -34.44 c} {8.816 -32.744}} -tags __path__139 -priority 10 -filled 1 -closed 1 -fillcolor \#efaa7c -filled 1 -linecolor \#efaa7c
    $w.zinc add group __svg__1  -tags __g__140 -priority 10
    $w.zinc add curve __g__140 {{9.544 -32.096} {8.296 -30.432 c} {14.12 5.761 c} {15.368 11.169} {16.616 16.577 c} {14.12 41.537 c} {14.12 41.537} {43.556 32.497 c} {17.864 34.465 c} {44.072 38.209} {70.281 41.953 c} {94.409 8.257 c} {96.073 -0.895} {97.737 -10.048 c} {88.169 -21.28 c} {88.169 -21.28} {89.417 -24.192 c} {84.841 -37.504 c} {79.849 -46.24} {74.857 -54.976 c} {59.824 -54.055 c} {43.24 -54.976} {28.264 -55.808 c} {10.792 -33.76 c} {9.544 -32.096}} -tags __path__141 -priority 10 -filled 1 -closed 1 -fillcolor \#f4c6a8 -filled 1 -linecolor \#f4c6a8
    $w.zinc add group __svg__1  -tags __g__142 -priority 10
    $w.zinc add curve __g__142 {{10.272 -31.448} {9.048 -29.816 c} {14.76 5.681 c} {15.984 10.985} {17.208 16.289 c} {14.76 40.769 c} {14.76 40.769} {42.628 31.849 c} {18.432 33.833 c} {44.136 37.505} {69.841 41.177 c} {93.505 8.129 c} {95.137 -0.848} {96.769 -9.824 c} {87.385 -20.84 c} {87.385 -20.84} {88.609 -23.696 c} {84.121 -36.752 c} {79.225 -45.32} {74.329 -53.888 c} {59.585 -52.985 c} {43.32 -53.888} {28.632 -54.704 c} {11.496 -33.08 c} {10.272 -31.448}} -tags __path__143 -priority 10 -filled 1 -closed 1 -fillcolor \#f9e2d3 -filled 1 -linecolor \#f9e2d3
    $w.zinc add group __svg__1  -tags __g__144 -priority 10
    $w.zinc add curve __g__144 {{44.2 36.8} {69.4 40.4 c} {92.601 8 c} {94.201 -0.8} {95.801 -9.6 c} {86.601 -20.4 c} {86.601 -20.4} {87.801 -23.2 c} {83.4 -36 c} {78.6 -44.4} {73.8 -52.8 c} {59.346 -51.914 c} {43.4 -52.8} {29 -53.6 c} {12.2 -32.4 c} {11 -30.8} {9.8 -29.2 c} {15.4 5.6 c} {16.6 10.8} {17.8 16 c} {15.4 40 c} {15.4 40} {40.9 31.4 c} {19 33.2 c} {44.2 36.8}} -tags __path__145 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__146 -priority 10
    $w.zinc add curve __g__146 {{90.601 2.8} {90.601 2.8 c} {62.8 10.4 c} {51.2 8.8} {51.2 8.8 c} {35.4 2.2 c} {26.6 24} {26.6 24 c} {23 31.2 c} {21 33.2} {19 35.2 c} {90.601 2.8 c} {90.601 2.8}} -tags __path__147 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__148 -priority 10
    $w.zinc add curve __g__148 {{94.401 0.6} {94.401 0.6 c} {65.4 12.8 c} {55.4 12.4} {55.4 12.4 c} {39 7.8 c} {30.6 22.4} {30.6 22.4 c} {22.2 31.6 c} {19 33.2} {19 33.2 c} {18.6 34.8 c} {25 30.8} {35.4 36} {35.4 36 c} {50.2 45.6 c} {59.8 29.6} {59.8 29.6 c} {63.8 18.4 c} {63.8 16.4} {63.8 14.4 c} {85 8.8 c} {86.601 8.4} {88.201 8 c} {94.801 3.8 c} {94.401 0.6}} -tags __path__149 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__150 -priority 10
    $w.zinc add curve __g__150 {{47 36.514} {40.128 36.514 c} {31.755 32.649 c} {31.755 26.4} {31.755 20.152 c} {40.128 13.887 c} {47 13.887} {53.874 13.887 c} {59.446 18.952 c} {59.446 25.2} {59.446 31.449 c} {53.874 36.514 c} {47 36.514}} -tags __path__151 -priority 10 -filled 1 -closed 1 -fillcolor \#99cc32 -filled 1 -linecolor \#99cc32
    $w.zinc add group __svg__1  -tags __g__152 -priority 10
    $w.zinc add curve __g__152 {{43.377 19.83} {38.531 20.552 c} {33.442 22.055 c} {33.514 21.839} {35.054 17.22 c} {41.415 13.887 c} {47 13.887} {51.296 13.887 c} {55.084 15.865 c} {57.32 18.875} {57.32 18.875 c} {52.004 18.545 c} {43.377 19.83}} -tags __path__153 -priority 10 -filled 1 -closed 1 -fillcolor \#659900 -filled 1 -linecolor \#659900
    $w.zinc add group __svg__1  -tags __g__154 -priority 10
    $w.zinc add curve __g__154 {{55.4 19.6} {55.4 19.6 c} {51 16.4 c} {51 18.6} {51 18.6 c} {54.6 23 c} {55.4 19.6}} -tags __path__155 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__156 -priority 10
    $w.zinc add curve __g__156 {{45.4 27.726} {42.901 27.726 c} {40.875 25.7 c} {40.875 23.2} {40.875 20.701 c} {42.901 18.675 c} {45.4 18.675} {47.9 18.675 c} {49.926 20.701 c} {49.926 23.2} {49.926 25.7 c} {47.9 27.726 c} {45.4 27.726}} -tags __path__157 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__158 -priority 10
    $w.zinc add curve __g__158 {{-58.6 14.4} {-58.6 14.4 c} {-61.8 -6.8 c} {-59.4 -11.2} {-59.4 -11.2 c} {-48.6 -21.2 c} {-49 -24.8} {-49 -24.8 c} {-49.4 -42.8 c} {-50.6 -43.6} {-51.8 -44.4 c} {-59.4 -50.4 c} {-65.4 -44} {-65.4 -44 c} {-75.8 -26 c} {-75 -19.6} {-75 -17.6} {-75 -17.6 c} {-82.6 -18 c} {-84.2 -16} {-84.2 -16 c} {-85.4 -10.8 c} {-86.6 -10.4} {-86.6 -10.4 c} {-89.4 -8 c} {-87.4 -5.2} {-87.4 -5.2 c} {-89.4 -2.8 c} {-89 1.2} {-81.4 5.2} {-81.4 5.2 c} {-79.4 19.6 c} {-68.6 24.8} {-63.764 27.129 c} {-60.6 20.4 c} {-58.6 14.4}} -tags __path__159 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__160 -priority 10
    $w.zinc add curve __g__160 {{-59.6 12.56} {-59.6 12.56 c} {-62.48 -6.52 c} {-60.32 -10.48} {-60.32 -10.48 c} {-50.6 -19.48 c} {-50.96 -22.72} {-50.96 -22.72 c} {-51.32 -38.92 c} {-52.4 -39.64} {-53.48 -40.36 c} {-60.32 -45.76 c} {-65.72 -40} {-65.72 -40 c} {-75.08 -23.8 c} {-74.36 -18.04} {-74.36 -16.24} {-74.36 -16.24 c} {-81.2 -16.6 c} {-82.64 -14.8} {-82.64 -14.8 c} {-83.72 -10.12 c} {-84.8 -9.76} {-84.8 -9.76 c} {-87.32 -7.6 c} {-85.52 -5.08} {-85.52 -5.08 c} {-87.32 -2.92 c} {-86.96 0.68} {-80.12 4.28} {-80.12 4.28 c} {-78.32 17.24 c} {-68.6 21.92} {-64.248 24.015 c} {-61.4 17.96 c} {-59.6 12.56}} -tags __path__161 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__162 -priority 10
    $w.zinc add curve __g__162 {{-51.05 -42.61} {-52.14 -43.47 c} {-59.63 -49.24 c} {-65.48 -43} {-65.48 -43 c} {-75.62 -25.45 c} {-74.84 -19.21} {-74.84 -17.26} {-74.84 -17.26 c} {-82.25 -17.65 c} {-83.81 -15.7} {-83.81 -15.7 c} {-84.98 -10.63 c} {-86.15 -10.24} {-86.15 -10.24 c} {-88.88 -7.9 c} {-86.93 -5.17} {-86.93 -5.17 c} {-88.88 -2.83 c} {-88.49 1.07} {-81.08 4.97} {-81.08 4.97 c} {-79.13 19.01 c} {-68.6 24.08} {-63.886 26.35 c} {-60.8 19.79 c} {-58.85 13.94} {-58.85 13.94 c} {-61.97 -6.73 c} {-59.63 -11.02} {-59.63 -11.02 c} {-49.1 -20.77 c} {-49.49 -24.28} {-49.49 -24.28 c} {-49.88 -41.83 c} {-51.05 -42.61}} -tags __path__163 -priority 10 -filled 1 -closed 1 -fillcolor \#eb955c -filled 1 -linecolor \#eb955c
    $w.zinc add group __svg__1  -tags __g__164 -priority 10
    $w.zinc add curve __g__164 {{-51.5 -41.62} {-52.48 -42.54 c} {-59.86 -48.08 c} {-65.56 -42} {-65.56 -42 c} {-75.44 -24.9 c} {-74.68 -18.82} {-74.68 -16.92} {-74.68 -16.92 c} {-81.9 -17.3 c} {-83.42 -15.4} {-83.42 -15.4 c} {-84.56 -10.46 c} {-85.7 -10.08} {-85.7 -10.08 c} {-88.36 -7.8 c} {-86.46 -5.14} {-86.46 -5.14 c} {-88.36 -2.86 c} {-87.98 0.94} {-80.76 4.74} {-80.76 4.74 c} {-78.86 18.42 c} {-68.6 23.36} {-64.006 25.572 c} {-61 19.18 c} {-59.1 13.48} {-59.1 13.48 c} {-62.14 -6.66 c} {-59.86 -10.84} {-59.86 -10.84 c} {-49.6 -20.34 c} {-49.98 -23.76} {-49.98 -23.76 c} {-50.36 -40.86 c} {-51.5 -41.62}} -tags __path__165 -priority 10 -filled 1 -closed 1 -fillcolor \#f2b892 -filled 1 -linecolor \#f2b892
    $w.zinc add group __svg__1  -tags __g__166 -priority 10
    $w.zinc add curve __g__166 {{-51.95 -40.63} {-52.82 -41.61 c} {-60.09 -46.92 c} {-65.64 -41} {-65.64 -41 c} {-75.26 -24.35 c} {-74.52 -18.43} {-74.52 -16.58} {-74.52 -16.58 c} {-81.55 -16.95 c} {-83.03 -15.1} {-83.03 -15.1 c} {-84.14 -10.29 c} {-85.25 -9.92} {-85.25 -9.92 c} {-87.84 -7.7 c} {-85.99 -5.11} {-85.99 -5.11 c} {-87.84 -2.89 c} {-87.47 0.81} {-80.44 4.51} {-80.44 4.51 c} {-78.59 17.83 c} {-68.6 22.64} {-64.127 24.794 c} {-61.2 18.57 c} {-59.35 13.02} {-59.35 13.02 c} {-62.31 -6.59 c} {-60.09 -10.66} {-60.09 -10.66 c} {-50.1 -19.91 c} {-50.47 -23.24} {-50.47 -23.24 c} {-50.84 -39.89 c} {-51.95 -40.63}} -tags __path__167 -priority 10 -filled 1 -closed 1 -fillcolor \#f8dcc8 -filled 1 -linecolor \#f8dcc8
    $w.zinc add group __svg__1  -tags __g__168 -priority 10
    $w.zinc add curve __g__168 {{-59.6 12.46} {-59.6 12.46 c} {-62.48 -6.52 c} {-60.32 -10.48} {-60.32 -10.48 c} {-50.6 -19.48 c} {-50.96 -22.72} {-50.96 -22.72 c} {-51.32 -38.92 c} {-52.4 -39.64} {-53.16 -40.68 c} {-60.32 -45.76 c} {-65.72 -40} {-65.72 -40 c} {-75.08 -23.8 c} {-74.36 -18.04} {-74.36 -16.24} {-74.36 -16.24 c} {-81.2 -16.6 c} {-82.64 -14.8} {-82.64 -14.8 c} {-83.72 -10.12 c} {-84.8 -9.76} {-84.8 -9.76 c} {-87.32 -7.6 c} {-85.52 -5.08} {-85.52 -5.08 c} {-87.32 -2.92 c} {-86.96 0.68} {-80.12 4.28} {-80.12 4.28 c} {-78.32 17.24 c} {-68.6 21.92} {-64.248 24.015 c} {-61.4 17.86 c} {-59.6 12.46}} -tags __path__169 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__170 -priority 10
    $w.zinc add curve __g__170 {{-62.7 6.2} {-62.7 6.2 c} {-84.3 -4 c} {-85.2 -4.8} {-85.2 -4.8 c} {-76.1 3.4 c} {-75.3 3.4} {-74.5 3.4 c} {-62.7 6.2 c} {-62.7 6.2}} -tags __path__171 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__172 -priority 10
    $w.zinc add curve __g__172 {{-79.8 0} {-79.8 0 c} {-61.4 3.6 c} {-61.4 8} {-61.4 10.912 c} {-61.643 24.331 c} {-67 22.8} {-75.4 20.4 c} {-71.8 6 c} {-79.8 0}} -tags __path__173 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__174 -priority 10
    $w.zinc add curve __g__174 {{-71.4 3.8} {-71.4 3.8 c} {-62.422 5.274 c} {-61.4 8} {-60.8 9.6 c} {-60.137 17.908 c} {-65.6 19} {-70.152 19.911 c} {-72.382 9.69 c} {-71.4 3.8}} -tags __path__175 -priority 10 -filled 1 -closed 1 -fillcolor \#99cc32 -filled 1 -linecolor \#99cc32
    $w.zinc add group __svg__1  -tags __g__176 -priority 10
    $w.zinc add curve __g__176 {{14.595 46.349} {14.098 44.607 c} {15.409 44.738 c} {17.2 44.2} {19.2 43.6 c} {31.4 39.8 c} {32.2 37.2} {33 34.6 c} {46.2 39 c} {46.2 39} {48 39.8 c} {52.4 42.4 c} {52.4 42.4} {57.2 43.6 c} {63.8 44 c} {63.8 44} {66.2 45 c} {69.6 47.8 c} {69.6 47.8} {84.2 58 c} {96.601 50.8 c} {96.601 50.8} {116.601 44.2 c} {110.601 27 c} {110.601 27} {107.601 18 c} {110.801 14.6 c} {110.801 14.6} {111.001 10.8 c} {118.201 17.2 c} {118.201 17.2} {120.801 21.4 c} {121.601 26.4 c} {121.601 26.4} {129.601 37.6 c} {126.201 19.8 c} {126.201 19.8} {126.401 18.8 c} {123.601 15.2 c} {123.601 14} {123.601 12.8 c} {121.801 9.4 c} {121.801 9.4} {118.801 6 c} {121.201 -1 c} {121.201 -1} {123.001 -14.8 c} {120.801 -13 c} {120.801 -13} {119.601 -14.8 c} {110.401 -4.8 c} {110.401 -4.8} {108.201 -1.4 c} {102.201 0.2 c} {102.201 0.2} {99.401 2 c} {96.001 0.6 c} {96.001 0.6} {93.401 0.2 c} {87.801 7.2 c} {87.801 7.2} {90.601 7 c} {93.001 11.4 c} {95.401 11.6} {97.801 11.8 c} {99.601 9.2 c} {101.201 8.6} {102.801 8 c} {105.601 13.8 c} {105.601 13.8} {106.001 16.4 c} {100.401 21.2 c} {100.401 21.2} {100.001 25.8 c} {98.401 24.2 c} {98.401 24.2} {95.401 23.6 c} {94.201 27.4 c} {93.201 32} {92.201 36.6 c} {88.001 37 c} {88.001 37} {86.401 44.4 c} {85.2 41.4 c} {85.2 41.4} {85 35.8 c} {79 41.6 c} {79 41.6} {77.8 43.6 c} {73.2 41.4 c} {73.2 41.4} {66.4 39.4 c} {68.8 37.4 c} {68.8 37.4} {70.6 35.2 c} {81.8 37.4 c} {81.8 37.4} {84 35.8 c} {76 31.8 c} {76 31.8} {75.4 30 c} {76.4 25.6 c} {76.4 25.6} {77.6 22.4 c} {84.4 16.8 c} {84.4 16.8} {93.801 15.6 c} {91.001 14 c} {91.001 14} {84.801 8.8 c} {79 16.4 c} {79 16.4} {76.8 22.6 c} {59.4 37.6 c} {59.4 37.6} {54.6 41 c} {57.2 34.2 c} {53.2 37.6} {49.2 41 c} {28.6 32 c} {28.6 32} {17.038 30.807 c} {14.306 46.549 c} {10.777 43.429} {10.777 43.429 c} {16.195 51.949 c} {14.595 46.349}} -tags __path__177 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__178 -priority 10
    $w.zinc add curve __g__178 {{209.401 -120} {209.401 -120 c} {183.801 -112 c} {181.001 -93.2} {181.001 -93.2 c} {178.601 -70.4 c} {199.001 -52.8} {199.001 -52.8 c} {199.401 -46.4 c} {201.401 -43.2} {201.401 -43.2 c} {199.801 -38.4 c} {218.601 -46} {245.801 -54.4} {245.801 -54.4 c} {252.201 -56.8 c} {257.401 -65.6} {262.601 -74.4 c} {277.801 -93.2 c} {274.201 -118.4} {274.201 -118.4 c} {275.401 -129.6 c} {269.401 -130} {269.401 -130 c} {261.001 -131.6 c} {253.801 -124} {253.801 -124 c} {247.001 -120.8 c} {244.601 -121.2} {209.401 -120}} -tags __path__179 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__180 -priority 10
    $w.zinc add curve __g__180 {{264.022 -120.99} {264.022 -120.99 c} {266.122 -129.92 c} {261.282 -125.08} {261.282 -125.08 c} {254.242 -119.36 c} {246.761 -119.36} {246.761 -119.36 c} {232.241 -117.16 c} {227.841 -103.96} {227.841 -103.96 c} {223.881 -77.12 c} {231.801 -71.4} {231.801 -71.4 c} {236.641 -63.92 c} {243.681 -70.52} {250.722 -77.12 c} {266.222 -107.35 c} {264.022 -120.99}} -tags __path__181 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__182 -priority 10
    $w.zinc add curve __g__182 {{263.648 -120.632} {263.648 -120.632 c} {265.738 -129.376 c} {260.986 -124.624} {260.986 -124.624 c} {254.074 -119.008 c} {246.729 -119.008} {246.729 -119.008 c} {232.473 -116.848 c} {228.153 -103.888} {228.153 -103.888 c} {224.265 -77.536 c} {232.041 -71.92} {232.041 -71.92 c} {236.793 -64.576 c} {243.705 -71.056} {250.618 -77.536 c} {265.808 -107.24 c} {263.648 -120.632}} -tags __path__183 -priority 10 -filled 1 -closed 1 -fillcolor \#323232 -filled 1 -linecolor \#323232
    $w.zinc add group __svg__1  -tags __g__184 -priority 10
    $w.zinc add curve __g__184 {{263.274 -120.274} {263.274 -120.274 c} {265.354 -128.832 c} {260.69 -124.168} {260.69 -124.168 c} {253.906 -118.656 c} {246.697 -118.656} {246.697 -118.656 c} {232.705 -116.536 c} {228.465 -103.816} {228.465 -103.816 c} {224.649 -77.952 c} {232.281 -72.44} {232.281 -72.44 c} {236.945 -65.232 c} {243.729 -71.592} {250.514 -77.952 c} {265.394 -107.13 c} {263.274 -120.274}} -tags __path__185 -priority 10 -filled 1 -closed 1 -fillcolor \#666666 -filled 1 -linecolor \#666666
    $w.zinc add group __svg__1  -tags __g__186 -priority 10
    $w.zinc add curve __g__186 {{262.9 -119.916} {262.9 -119.916 c} {264.97 -128.288 c} {260.394 -123.712} {260.394 -123.712 c} {253.738 -118.304 c} {246.665 -118.304} {246.665 -118.304 c} {232.937 -116.224 c} {228.777 -103.744} {228.777 -103.744 c} {225.033 -78.368 c} {232.521 -72.96} {232.521 -72.96 c} {237.097 -65.888 c} {243.753 -72.128} {250.41 -78.368 c} {264.98 -107.02 c} {262.9 -119.916}} -tags __path__187 -priority 10 -filled 1 -closed 1 -fillcolor \#999999 -filled 1 -linecolor \#999999
    $w.zinc add group __svg__1  -tags __g__188 -priority 10
    $w.zinc add curve __g__188 {{262.526 -119.558} {262.526 -119.558 c} {264.586 -127.744 c} {260.098 -123.256} {260.098 -123.256 c} {253.569 -117.952 c} {246.633 -117.952} {246.633 -117.952 c} {233.169 -115.912 c} {229.089 -103.672} {229.089 -103.672 c} {225.417 -78.784 c} {232.761 -73.48} {232.761 -73.48 c} {237.249 -66.544 c} {243.777 -72.664} {250.305 -78.784 c} {264.566 -106.91 c} {262.526 -119.558}} -tags __path__189 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__190 -priority 10
    $w.zinc add curve __g__190 {{262.151 -119.2} {262.151 -119.2 c} {264.201 -127.2 c} {259.801 -122.8} {259.801 -122.8 c} {253.401 -117.6 c} {246.601 -117.6} {246.601 -117.6 c} {233.401 -115.6 c} {229.401 -103.6} {229.401 -103.6 c} {225.801 -79.2 c} {233.001 -74} {233.001 -74 c} {237.401 -67.2 c} {243.801 -73.2} {250.201 -79.2 c} {264.151 -106.8 c} {262.151 -119.2}} -tags __path__191 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__192 -priority 10
    $w.zinc add curve __g__192 {{50.6 84} {50.6 84 c} {30.2 64.8 c} {22.2 64} {22.2 64 c} {-12.2 60 c} {-27 78} {-27 78 c} {-9.4 57.6 c} {18.2 63.2} {18.2 63.2 c} {-3.4 58.8 c} {-15.8 62} {-15.8 62 c} {-32.6 62 c} {-42.2 76} {-45 80.8} {-45 80.8 c} {-41 66 c} {-22.6 60} {-22.6 60 c} {0.2 55.2 c} {11 60} {11 60 c} {-10.6 53.2 c} {-20.6 55.2} {-20.6 55.2 c} {-51 52.8 c} {-63.8 79.2} {-63.8 79.2 c} {-59.8 64.8 c} {-45 57.6} {-45 57.6 c} {-31.4 48.8 c} {-11 51.6} {-11 51.6 c} {3.4 54.8 c} {8.6 57.2} {13.8 59.6 c} {12.6 56.8 c} {4.2 52} {4.2 52 c} {-1.4 42 c} {-15.4 42.4} {-15.4 42.4 c} {-58.2 46 c} {-68.6 58} {-68.6 58 c} {-55 46.8 c} {-44.6 44} {-44.6 44 c} {-22.2 36 c} {-13.8 36.8} {-13.8 36.8 c} {11 37.8 c} {18.6 33.8} {18.6 33.8 c} {7.4 38.8 c} {10.6 42} {13.8 45.2 c} {20.6 52.8 c} {20.6 54} {20.6 55.2 c} {44.8 77.3 c} {48.4 81.7} {50.6 84}} -tags __path__193 -priority 10 -filled 1 -closed 1 -fillcolor \#992600 -filled 1 -linecolor \#992600
    $w.zinc add group __svg__1  -tags __g__194 -priority 10
    $w.zinc add curve __g__194 {{189 278} {189 278 c} {173.5 241.5 c} {161 232} {161 232 c} {187 248 c} {190.5 266} {190.5 266 c} {190.5 276 c} {189 278}} -tags __path__195 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__196 -priority 10
    $w.zinc add curve __g__196 {{236 285.5} {236 285.5 c} {209.5 230.5 c} {191 206.5} {191 206.5 c} {234.5 244 c} {239.5 270.5} {240 276} {237 273.5} {237 273.5 c} {236.5 282.5 c} {236 285.5}} -tags __path__197 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__198 -priority 10
    $w.zinc add curve __g__198 {{292.5 237} {292.5 237 c} {230 177.5 c} {228.5 175} {228.5 175 c} {289 241 c} {292 248.5} {292 248.5 c} {290 239.5 c} {292.5 237}} -tags __path__199 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__200 -priority 10
    $w.zinc add curve __g__200 {{104 280.5} {104 280.5 c} {123.5 228.5 c} {142.5 251} {142.5 251 c} {157.5 261 c} {157 264} {157 264 c} {153 257.5 c} {135 258} {135 258 c} {116 255 c} {104 280.5}} -tags __path__201 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__202 -priority 10
    $w.zinc add curve __g__202 {{294.5 153} {294.5 153 c} {249.5 124.5 c} {242 123} {230.193 120.639 c} {291.5 152 c} {296.5 162.5} {296.5 162.5 c} {298.5 160 c} {294.5 153}} -tags __path__203 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__204 -priority 10
    $w.zinc add curve __g__204 {{143.801 259.601} {143.801 259.601 c} {164.201 257.601 c} {171.001 250.801} {175.401 254.401} {193.001 216.001} {196.601 221.201} {196.601 221.201 c} {211.001 206.401 c} {210.201 198.401} {209.401 190.401 c} {223.001 204.401 c} {223.001 204.401} {223.001 204.401 c} {222.201 192.801 c} {229.401 199.601} {229.401 199.601 c} {227.001 184.001 c} {235.401 192.001} {235.401 192.001 c} {224.864 161.844 c} {247.401 187.601} {253.001 194.001 c} {248.601 187.201 c} {248.601 187.201} {248.601 187.201 c} {222.601 139.201 c} {244.201 153.601} {244.201 153.601 c} {246.201 130.801 c} {245.001 126.401} {243.801 122.001 c} {241.801 99.6 c} {237.001 94.4} {232.201 89.2 c} {237.401 87.6 c} {243.001 92.8} {243.001 92.8 c} {231.801 68.8 c} {245.001 80.8} {245.001 80.8 c} {241.401 65.6 c} {237.001 62.8} {237.001 62.8 c} {231.401 45.6 c} {246.601 56.4} {246.601 56.4 c} {242.201 44 c} {239.001 40.8} {239.001 40.8 c} {227.401 13.2 c} {234.601 18} {239.001 21.6} {239.001 21.6 c} {232.201 7.6 c} {238.601 12} {245.001 16.4 c} {245.001 16 c} {245.001 16} {245.001 16 c} {223.801 -17.2 c} {244.201 0.4} {244.201 0.4 c} {236.042 -13.518 c} {232.601 -20.4} {232.601 -20.4 c} {213.801 -40.8 c} {228.201 -34.4} {233.001 -32.8} {233.001 -32.8 c} {224.201 -42.8 c} {216.201 -44.4} {208.201 -46 c} {218.601 -52.4 c} {225.001 -50.4} {231.401 -48.4 c} {247.001 -40.8 c} {247.001 -40.8} {247.001 -40.8 c} {259.801 -22 c} {263.801 -21.6} {263.801 -21.6 c} {243.801 -29.2 c} {249.801 -21.2} {249.801 -21.2 c} {264.201 -7.2 c} {257.001 -7.6} {257.001 -7.6 c} {251.001 -0.4 c} {255.801 8.4} {255.801 8.4 c} {237.342 -9.991 c} {252.201 15.6} {259.001 32} {259.001 32 c} {234.601 7.2 c} {245.801 29.2} {245.801 29.2 c} {263.001 52.8 c} {265.001 53.2} {267.001 53.6 c} {271.401 62.4 c} {271.401 62.4} {267.001 60.4} {272.201 69.2} {272.201 69.2 c} {261.001 57.2 c} {267.001 70.4} {272.601 84.8} {272.601 84.8 c} {252.201 62.8 c} {265.801 92.4} {265.801 92.4 c} {249.401 87.2 c} {258.201 104.4} {258.201 104.4 c} {256.601 120.401 c} {257.001 125.601} {257.401 130.801 c} {258.601 159.201 c} {254.201 167.201} {249.801 175.201 c} {260.201 194.401 c} {262.201 198.401} {264.201 202.401 c} {267.801 213.201 c} {259.001 204.001} {250.201 194.801 c} {254.601 200.401 c} {256.601 209.201} {258.601 218.001 c} {264.601 233.601 c} {263.801 239.201} {263.801 239.201 c} {262.601 240.401 c} {259.401 236.801} {259.401 236.801 c} {244.601 214.001 c} {246.201 228.401} {246.201 228.401 c} {245.001 236.401 c} {241.801 245.201} {241.801 245.201 c} {238.601 256.001 c} {238.601 247.201} {238.601 247.201 c} {235.401 230.401 c} {232.601 238.001} {229.801 245.601 c} {226.201 251.601 c} {223.401 254.001} {220.601 256.401 c} {215.401 233.601 c} {214.201 244.001} {214.201 244.001 c} {202.201 231.601 c} {197.401 248.001} {185.801 264.401} {185.801 264.401 c} {185.401 252.001 c} {184.201 258.001} {184.201 258.001 c} {154.201 264.001 c} {143.801 259.601}} -tags __path__205 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__206 -priority 10
    $w.zinc add curve __g__206 {{109.401 -97.2} {109.401 -97.2 c} {97.801 -105.2 c} {93.801 -104.8} {89.801 -104.4 c} {121.401 -113.6 c} {162.601 -86} {162.601 -86 c} {167.401 -83.2 c} {171.001 -83.6} {171.001 -83.6 c} {174.201 -81.2 c} {171.401 -77.6} {171.401 -77.6 c} {162.601 -68 c} {173.801 -56.8} {173.801 -56.8 c} {192.201 -50 c} {186.601 -58.8} {186.601 -58.8 c} {197.401 -54.8 c} {199.801 -50.8} {202.201 -46.8 c} {201.001 -50.8 c} {201.001 -50.8} {201.001 -50.8 c} {194.601 -58 c} {188.601 -63.2} {188.601 -63.2 c} {183.401 -65.2 c} {180.601 -73.6} {177.801 -82 c} {175.401 -92 c} {179.801 -95.2} {179.801 -95.2 c} {175.801 -90.8 c} {176.601 -94.8} {177.401 -98.8 c} {181.001 -102.4 c} {182.601 -102.8} {184.201 -103.2 c} {200.601 -119 c} {207.401 -119.4} {207.401 -119.4 c} {198.201 -118 c} {195.201 -119} {192.201 -120 c} {165.601 -131.4 c} {159.601 -132.6} {159.601 -132.6 c} {142.801 -139.2 c} {154.801 -137.2} {154.801 -137.2 c} {190.601 -133.4 c} {208.801 -120.2} {208.801 -120.2 c} {201.601 -128.6 c} {183.201 -135.6} {183.201 -135.6 c} {161.001 -148.2 c} {125.801 -143.2} {125.801 -143.2 c} {108.001 -140 c} {100.201 -138.2} {100.201 -138.2 c} {97.601 -138.8 c} {97.001 -139.2} {96.401 -139.6 c} {84.6 -148.6 c} {57 -141.6} {57 -141.6 c} {40 -137 c} {31.4 -132.2} {31.4 -132.2 c} {16.2 -131 c} {12.6 -127.8} {12.6 -127.8 c} {-6 -113.2 c} {-8 -112.4} {-10 -111.6 c} {-21.4 -104 c} {-22.2 -103.6} {-22.2 -103.6 c} {2.4 -110.2 c} {4.8 -112.6} {7.2 -115 c} {24.6 -117.6 c} {27 -116.2} {29.4 -114.8 c} {37.8 -115.4 c} {28.2 -114.8} {28.2 -114.8 c} {103.801 -100 c} {104.601 -98} {105.401 -96 c} {109.401 -97.2 c} {109.401 -97.2}} -tags __path__207 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__208 -priority 10
    $w.zinc add curve __g__208 {{180.801 -106.4} {180.801 -106.4 c} {170.601 -113.8 c} {168.601 -113.8} {166.601 -113.8 c} {154.201 -124 c} {150.001 -123.6} {145.801 -123.2 c} {133.601 -133.2 c} {106.201 -125} {106.201 -125 c} {105.601 -127 c} {109.201 -127.8} {109.201 -127.8 c} {115.601 -130 c} {116.001 -130.6} {116.001 -130.6 c} {136.201 -134.8 c} {143.401 -131.2} {143.401 -131.2 c} {152.601 -128.6 c} {158.801 -122.4} {158.801 -122.4 c} {170.001 -119.2 c} {173.201 -120.2} {173.201 -120.2 c} {182.001 -118 c} {182.401 -116.2} {182.401 -116.2 c} {188.201 -113.2 c} {186.401 -110.6} {186.401 -110.6 c} {186.801 -109 c} {180.801 -106.4}} -tags __path__209 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__210 -priority 10
    $w.zinc add curve __g__210 {{168.33 -108.509} {169.137 -107.877 c} {170.156 -107.779 c} {170.761 -106.97} {170.995 -106.656 c} {170.706 -106.33 c} {170.391 -106.233} {169.348 -105.916 c} {168.292 -106.486 c} {167.15 -105.898} {166.748 -105.691 c} {166.106 -105.873 c} {165.553 -106.022} {163.921 -106.463 c} {162.092 -106.488 c} {160.401 -105.8} {158.416 -106.929 c} {156.056 -106.345 c} {153.975 -107.346} {153.917 -107.373 c} {153.695 -107.027 c} {153.621 -107.054} {150.575 -108.199 c} {146.832 -107.916 c} {144.401 -110.2} {141.973 -110.612 c} {139.616 -111.074 c} {137.188 -111.754} {135.37 -112.263 c} {133.961 -113.252 c} {132.341 -114.084} {130.964 -114.792 c} {129.507 -115.314 c} {127.973 -115.686} {126.11 -116.138 c} {124.279 -116.026 c} {122.386 -116.546} {122.293 -116.571 c} {122.101 -116.227 c} {122.019 -116.254} {121.695 -116.362 c} {121.405 -116.945 c} {121.234 -116.892} {119.553 -116.37 c} {118.065 -117.342 c} {116.401 -117} {115.223 -118.224 c} {113.495 -117.979 c} {111.949 -118.421} {108.985 -119.269 c} {105.831 -117.999 c} {102.801 -119} {106.914 -120.842 c} {111.601 -119.61 c} {115.663 -121.679} {117.991 -122.865 c} {120.653 -121.763 c} {123.223 -122.523} {123.71 -122.667 c} {124.401 -122.869 c} {124.801 -122.2} {124.935 -122.335 c} {125.117 -122.574 c} {125.175 -122.546} {127.625 -121.389 c} {129.94 -120.115 c} {132.422 -119.049} {132.763 -118.903 c} {133.295 -119.135 c} {133.547 -118.933} {135.067 -117.717 c} {137.01 -117.82 c} {138.401 -116.6} {140.099 -117.102 c} {141.892 -116.722 c} {143.621 -117.346} {143.698 -117.373 c} {143.932 -117.032 c} {143.965 -117.054} {145.095 -117.802 c} {146.25 -117.531 c} {147.142 -117.227} {147.48 -117.112 c} {148.143 -116.865 c} {148.448 -116.791} {149.574 -116.515 c} {150.43 -116.035 c} {151.609 -115.852} {151.723 -115.834 c} {151.908 -116.174 c} {151.98 -116.146} {153.103 -115.708 c} {154.145 -115.764 c} {154.801 -114.6} {154.936 -114.735 c} {155.101 -114.973 c} {155.183 -114.946} {156.21 -114.608 c} {156.859 -113.853 c} {157.96 -113.612} {158.445 -113.506 c} {159.057 -112.88 c} {159.633 -112.704} {162.025 -111.973 c} {163.868 -110.444 c} {166.062 -109.549} {166.821 -109.239 c} {167.697 -109.005 c} {168.33 -108.509}} -tags __path__211 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__212 -priority 10
    $w.zinc add curve __g__212 {{91.696 -122.739} {89.178 -124.464 c} {86.81 -125.57 c} {84.368 -127.356} {84.187 -127.489 c} {83.827 -127.319 c} {83.625 -127.441} {82.618 -128.05 c} {81.73 -128.631 c} {80.748 -129.327} {80.209 -129.709 c} {79.388 -129.698 c} {78.88 -129.956} {76.336 -131.248 c} {73.707 -131.806 c} {71.2 -133} {71.882 -133.638 c} {73.004 -133.394 c} {73.6 -134.2} {73.795 -133.92 c} {74.033 -133.636 c} {74.386 -133.827} {76.064 -134.731 c} {77.914 -134.884 c} {79.59 -134.794} {81.294 -134.702 c} {83.014 -134.397 c} {84.789 -134.125} {85.096 -134.078 c} {85.295 -133.555 c} {85.618 -133.458} {87.846 -132.795 c} {90.235 -133.32 c} {92.354 -132.482} {93.945 -131.853 c} {95.515 -131.03 c} {96.754 -129.755} {97.006 -129.495 c} {96.681 -129.194 c} {96.401 -129} {96.789 -129.109 c} {97.062 -128.903 c} {97.173 -128.59} {97.257 -128.351 c} {97.257 -128.049 c} {97.173 -127.81} {97.061 -127.498 c} {96.782 -127.397 c} {96.408 -127.346} {95.001 -127.156 c} {96.773 -128.536 c} {96.073 -128.088} {94.8 -127.274 c} {95.546 -125.868 c} {94.801 -124.6} {94.521 -124.794 c} {94.291 -125.012 c} {94.401 -125.4} {94.635 -124.878 c} {94.033 -124.588 c} {93.865 -124.272} {93.48 -123.547 c} {92.581 -122.132 c} {91.696 -122.739}} -tags __path__213 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__214 -priority 10
    $w.zinc add curve __g__214 {{59.198 -115.391} {56.044 -116.185 c} {52.994 -116.07 c} {49.978 -117.346} {49.911 -117.374 c} {49.688 -117.027 c} {49.624 -117.054} {48.258 -117.648 c} {47.34 -118.614 c} {46.264 -119.66} {45.351 -120.548 c} {43.693 -120.161 c} {42.419 -120.648} {42.095 -120.772 c} {41.892 -121.284 c} {41.591 -121.323} {40.372 -121.48 c} {39.445 -122.429 c} {38.4 -123} {40.736 -123.795 c} {43.147 -123.764 c} {45.609 -124.148} {45.722 -124.166 c} {45.867 -123.845 c} {46 -123.845} {46.136 -123.845 c} {46.266 -124.066 c} {46.4 -124.2} {46.595 -123.92 c} {46.897 -123.594 c} {47.154 -123.848} {47.702 -124.388 c} {48.258 -124.198 c} {48.798 -124.158} {48.942 -124.148 c} {49.067 -123.845 c} {49.2 -123.845} {49.336 -123.845 c} {49.467 -124.156 c} {49.6 -124.156} {49.736 -124.155 c} {49.867 -123.845 c} {50 -123.845} {50.136 -123.845 c} {50.266 -124.066 c} {50.4 -124.2} {51.092 -123.418 c} {51.977 -123.972 c} {52.799 -123.793} {53.837 -123.566 c} {54.104 -122.418 c} {55.178 -122.12} {59.893 -120.816 c} {64.03 -118.671 c} {68.393 -116.584} {68.7 -116.437 c} {68.91 -116.189 c} {68.8 -115.8} {69.067 -115.8 c} {69.38 -115.888 c} {69.57 -115.756} {70.628 -115.024 c} {71.669 -114.476 c} {72.366 -113.378} {72.582 -113.039 c} {72.253 -112.632 c} {72.02 -112.684} {67.591 -113.679 c} {63.585 -114.287 c} {59.198 -115.391}} -tags __path__215 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__216 -priority 10
    $w.zinc add curve __g__216 {{45.338 -71.179} {43.746 -72.398 c} {43.162 -74.429 c} {42.034 -76.221} {41.82 -76.561 c} {42.094 -76.875 c} {42.411 -76.964} {42.971 -77.123 c} {43.514 -76.645 c} {43.923 -76.443} {45.668 -75.581 c} {47.203 -74.339 c} {49.2 -74.2} {51.19 -71.966 c} {55.45 -71.581 c} {55.457 -68.2} {55.458 -67.341 c} {54.03 -68.259 c} {53.6 -67.4} {51.149 -68.403 c} {48.76 -68.3 c} {46.38 -69.767} {45.763 -70.148 c} {46.093 -70.601 c} {45.338 -71.179}} -tags __path__217 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__218 -priority 10
    $w.zinc add curve __g__218 {{17.8 -123.756} {17.935 -123.755 c} {24.966 -123.522 c} {24.949 -123.408} {24.904 -123.099 c} {17.174 -122.05 c} {16.81 -122.22} {16.646 -122.296 c} {9.134 -119.866 c} {9 -120} {9.268 -120.135 c} {17.534 -123.756 c} {17.8 -123.756}} -tags __path__219 -priority 10 -filled 1 -closed 1 -fillcolor \#cc7226 -filled 1 -linecolor \#cc7226
    $w.zinc add group __svg__1  -tags __g__220 -priority 10
    $w.zinc add curve __g__220 {{33.2 -114} {33.2 -114 c} {18.4 -112.2 c} {14 -111} {9.6 -109.8 c} {-9 -102.2 c} {-12 -100.2} {-12 -100.2 c} {-25.4 -94.8 c} {-42.4 -74.8} {-42.4 -74.8 c} {-34.8 -78.2 c} {-32.6 -81} {-32.6 -81 c} {-19 -93.6 c} {-19.2 -91} {-19.2 -91 c} {-7 -99.6 c} {-7.6 -97.4} {-7.6 -97.4 c} {16.8 -108.6 c} {14.8 -105.4} {14.8 -105.4 c} {36.4 -110 c} {35.4 -108} {35.4 -108 c} {54.2 -103.6 c} {51.4 -103.4} {51.4 -103.4 c} {45.6 -102.2 c} {52 -98.6} {52 -98.6 c} {48.6 -94.2 c} {43.2 -98.2} {37.8 -102.2 c} {40.8 -100 c} {35.8 -99} {35.8 -99 c} {33.2 -98.2 c} {28.6 -102.2} {28.6 -102.2 c} {23 -106.8 c} {14.2 -103.2} {14.2 -103.2 c} {-16.4 -90.6 c} {-18.4 -90} {-18.4 -90 c} {-22 -87.2 c} {-24.4 -83.6} {-24.4 -83.6 c} {-30.2 -79.2 c} {-33.2 -77.8} {-33.2 -77.8 c} {-46 -66.2 c} {-47.2 -64.8} {-47.2 -64.8 c} {-50.6 -59.6 c} {-51.4 -59.2} {-51.4 -59.2 c} {-45 -63 c} {-43 -65} {-43 -65 c} {-29 -75 c} {-23.6 -75.8} {-23.6 -75.8 c} {-19.2 -78.8 c} {-18.4 -80.2} {-18.4 -80.2 c} {-4 -89.4 c} {0.2 -89.4} {0.2 -89.4 c} {9.4 -84.2 c} {11.8 -91.2} {11.8 -91.2 c} {17.6 -93 c} {23.2 -91.8} {23.2 -91.8 c} {26.4 -94.4 c} {25.6 -96.6} {25.6 -96.6 c} {27.2 -98.4 c} {28.2 -94.6} {28.2 -94.6 c} {31.6 -91 c} {36.4 -93} {36.4 -93 c} {40.4 -93.2 c} {38.4 -90.8} {38.4 -90.8 c} {34 -87 c} {22.2 -86.8} {22.2 -86.8 c} {9.8 -86.2 c} {-6.6 -78.6} {-6.6 -78.6 c} {-36.4 -68.2 c} {-45.6 -57.8} {-45.6 -57.8 c} {-52 -49 c} {-57.4 -47.8} {-57.4 -47.8 c} {-63.2 -47 c} {-69.2 -39.6} {-69.2 -39.6 c} {-59.4 -45.4 c} {-50.4 -45.4} {-50.4 -45.4 c} {-46.4 -47.8 c} {-50.2 -44.2} {-50.2 -44.2 c} {-53.8 -36.6 c} {-52.2 -31.2} {-52.2 -31.2 c} {-52.8 -26 c} {-53.6 -24.4} {-53.6 -24.4 c} {-61.4 -11.6 c} {-61.4 -9.2} {-61.4 -6.8 c} {-60.2 3 c} {-59.8 3.6} {-59.4 4.2 c} {-60.8 2 c} {-57 4.4} {-53.2 6.8 c} {-50.4 8.4 c} {-49.6 11.2} {-48.8 14 c} {-51.6 5.8 c} {-51.8 4} {-52 2.2 c} {-56.2 -5 c} {-55.4 -7.4} {-55.4 -7.4 c} {-54.4 -6.4 c} {-53.6 -5} {-53.6 -5 c} {-54.2 -5.6 c} {-53.6 -9.2} {-53.6 -9.2 c} {-52.8 -14.4 c} {-51.4 -17.6} {-50 -20.8 c} {-48 -24.6 c} {-47.6 -25.4} {-47.2 -26.2 c} {-47.2 -32 c} {-45.8 -29.4} {-42.4 -26.8} {-42.4 -26.8 c} {-45.2 -29.4 c} {-43 -31.6} {-43 -31.6 c} {-44 -37.2 c} {-42.2 -39.8} {-42.2 -39.8 c} {-35.2 -48.2 c} {-33.6 -49.2} {-32 -50.2 c} {-33.4 -49.8 c} {-33.4 -49.8} {-33.4 -49.8 c} {-27.4 -54 c} {-33.2 -52.4} {-33.2 -52.4 c} {-37.2 -50.8 c} {-40.2 -50.8} {-40.2 -50.8 c} {-47.8 -48.8 c} {-43.8 -53} {-39.8 -57.2 c} {-29.8 -62.6 c} {-26 -62.4} {-25.2 -60.8} {-14 -63.2} {-15.2 -62.4} {-15.2 -62.4 c} {-15.4 -62.6 c} {-11.2 -63} {-7 -63.4 c} {-1.2 -62 c} {0.2 -63.8} {1.6 -65.6 c} {5 -66.6 c} {4.6 -65.2} {4.2 -63.8 c} {4 -61.8 c} {4 -61.8} {4 -61.8 c} {9 -67.6 c} {8.4 -65.4} {7.8 -63.2 c} {-0.4 -58 c} {-1.8 -51.8} {8.6 -60} {12.2 -63} {12.2 -63 c} {15.8 -60.8 c} {16 -62.4} {16.2 -64 c} {20.8 -69.8 c} {22 -69.6} {23.2 -69.4 c} {25.2 -72.2 c} {25 -69.6} {24.8 -67 c} {32.4 -61.6 c} {32.4 -61.6} {32.4 -61.6 c} {35.6 -63.4 c} {37 -62} {38.4 -60.6 c} {42.6 -81.8 c} {42.6 -81.8} {67.6 -92.4} {111.201 -95.8} {94.201 -102.6} {33.2 -114}} -tags __path__221 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__230 -priority 10
    $w.zinc add curve __g__230 {{20.895 54.407} {22.437 55.87 c} {49.4 84.8 c} {49.4 84.8} {84.6 121.401 c} {56.6 87.2 c} {56.6 87.2} {49 82.4 c} {39.8 63.6 c} {39.8 63.6} {38.6 60.8 c} {53.8 70.8 c} {53.8 70.8} {57.8 71.6 c} {71.4 90.8 c} {71.4 90.8} {64.6 88.4 c} {69.4 95.6 c} {69.4 95.6} {72.2 97.6 c} {92.601 113.201 c} {92.601 113.201} {96.201 117.201 c} {100.201 118.801 c} {100.201 118.801} {114.201 113.601 c} {107.801 126.801 c} {107.801 126.801} {110.201 133.601 c} {115.801 122.001 c} {115.801 122.001} {127.001 105.2 c} {110.601 107.601 c} {110.601 107.601} {80.6 110.401 c} {73.8 94.4 c} {73.8 94.4} {71.4 92 c} {80.2 94.4 c} {80.2 94.4} {88.601 96.4 c} {73 82 c} {73 82} {75.4 82 c} {84.6 88.8 c} {84.6 88.8} {95.001 98 c} {97.001 96 c} {97.001 96} {115.001 87.2 c} {125.401 94.8 c} {125.401 94.8} {127.401 96.4 c} {121.801 103.2 c} {123.401 108.401} {125.001 113.601 c} {129.801 126.001 c} {129.801 126.001} {127.401 127.601 c} {127.801 138.401 c} {127.801 138.401} {144.601 161.601 c} {135.001 159.601 c} {135.001 159.601} {119.401 159.201 c} {134.201 166.801 c} {134.201 166.801} {137.401 168.801 c} {146.201 176.001 c} {146.201 176.001} {143.401 174.801 c} {141.801 180.001 c} {141.801 180.001} {146.601 184.001 c} {143.801 188.801 c} {143.801 188.801} {137.801 190.001 c} {136.601 194.001 c} {136.601 194.001} {143.401 202.001 c} {133.401 202.401 c} {133.401 202.401} {137.001 206.801 c} {132.201 218.801 c} {132.201 218.801} {127.401 218.801 c} {121.001 224.401 c} {121.001 224.401} {123.401 229.201 c} {113.001 234.801 c} {113.001 234.801} {104.601 236.401 c} {107.401 243.201 c} {107.401 243.201} {99.401 249.201 c} {97.001 265.201 c} {97.001 265.201} {96.201 275.601 c} {93.801 278.801 c} {99.001 276.801} {104.201 274.801 c} {103.401 262.401 c} {103.401 262.401} {98.601 246.801 c} {141.401 230.801 c} {141.401 230.801} {145.401 229.201 c} {146.201 224.001 c} {146.201 224.001} {148.201 224.401 c} {157.001 232.001 c} {157.001 232.001} {164.601 243.201 c} {165.001 234.001 c} {165.001 234.001} {166.201 230.401 c} {164.601 224.401 c} {164.601 224.401} {170.601 202.801 c} {156.601 196.401 c} {156.601 196.401} {146.601 162.801 c} {160.601 171.201 c} {160.601 171.201} {163.401 176.801 c} {174.201 182.001 c} {174.201 182.001} {177.801 179.601} {176.201 174.801 c} {184.601 168.801 c} {184.601 168.801} {187.401 175.201 c} {193.401 167.201 c} {193.401 167.201} {197.001 142.801 c} {209.401 157.201 c} {209.401 157.201} {213.401 158.401 c} {214.601 151.601 c} {214.601 151.601} {218.201 141.201 c} {214.601 127.601 c} {214.601 127.601} {218.201 127.201 c} {227.801 133.201 c} {227.801 133.201} {230.601 129.601 c} {221.401 112.801 c} {225.401 115.201} {229.401 117.601 c} {233.801 119.201 c} {233.801 119.201} {234.601 117.201 c} {224.601 104.801 c} {224.601 104.801} {220.201 102 c} {215.001 81.6 c} {215.001 81.6} {222.201 85.2 c} {212.201 70 c} {212.201 70} {212.201 66.8 c} {218.201 55.6 c} {218.201 55.6} {217.401 48.8 c} {218.201 49.2 c} {218.201 49.2} {221.001 50.4 c} {229.001 52 c} {222.201 45.6} {215.401 39.2 c} {223.001 34.4 c} {223.001 34.4} {227.401 31.6 c} {213.801 32 c} {213.801 32} {208.601 27.6 c} {209.001 23.6 c} {209.001 23.6} {217.001 25.6 c} {202.601 11.2 c} {200.201 7.6} {197.801 4 c} {207.401 -1.2 c} {207.401 -1.2} {220.601 -4.8 c} {209.001 -8 c} {209.001 -8} {189.401 -7.6 c} {200.201 -18.4 c} {200.201 -18.4} {206.201 -18 c} {204.601 -20.4 c} {204.601 -20.4} {199.401 -21.6 c} {189.801 -28 c} {189.801 -28} {185.801 -31.6 c} {189.401 -30.8 c} {189.401 -30.8} {206.201 -29.6 c} {177.401 -40.8 c} {177.401 -40.8} {185.401 -40.8 c} {167.401 -51.2 c} {167.401 -51.2} {165.401 -52.8 c} {162.201 -60.4 c} {162.201 -60.4} {156.201 -65.6 c} {151.401 -72.4 c} {151.401 -72.4} {151.001 -76.8 c} {146.201 -81.6 c} {146.201 -81.6} {134.601 -95.2 c} {129.001 -94.8 c} {129.001 -94.8} {114.201 -98.4 c} {109.001 -97.6 c} {109.001 -97.6} {56.2 -93.2} {29.8 -80.4 c} {37.6 -59.4 c} {37.6 -59.4} {44 -51 c} {53.2 -54.8 c} {53.2 -54.8} {57.8 -61 c} {69.4 -58.8 c} {69.4 -58.8} {89.801 -55.6 c} {87.201 -59.2 c} {87.201 -59.2} {84.801 -63.8 c} {68.6 -70 c} {68.4 -70.6} {68.2 -71.2 c} {59.4 -74.6 c} {59.4 -74.6} {56.4 -75.8 c} {52 -85 c} {52 -85} {48.8 -88.4 c} {64.6 -82.6 c} {64.6 -82.6} {63.4 -81.6 c} {70.8 -77.6 c} {70.8 -77.6} {88.201 -78.6 c} {98.801 -67.8 c} {98.801 -67.8} {109.601 -51.2 c} {109.801 -59.4 c} {109.801 -59.4} {112.601 -68.8 c} {100.801 -90 c} {100.801 -90} {101.201 -92 c} {109.401 -85.4 c} {109.401 -85.4} {110.801 -87.4 c} {111.601 -81.6 c} {111.601 -81.6} {111.801 -79.2 c} {115.601 -71.2 c} {115.601 -71.2} {118.401 -58.2 c} {122.001 -65.6 c} {122.001 -65.6} {126.601 -56.2} {128.001 -53.6 c} {122.001 -46 c} {122.001 -46} {121.801 -43.2 c} {122.601 -43.4 c} {117.001 -35.8} {111.401 -28.2 c} {114.801 -23.8 c} {114.801 -23.8} {113.401 -17.2 c} {122.201 -17.6 c} {122.201 -17.6} {124.801 -15.4 c} {128.201 -15.4 c} {128.201 -15.4} {130.001 -13.4 c} {132.401 -14 c} {132.401 -14} {134.001 -17.8 c} {140.201 -15.8 c} {140.201 -15.8} {141.601 -18.2 c} {149.801 -18.6 c} {149.801 -18.6} {150.801 -21.2 c} {151.201 -22.8 c} {154.601 -23.4} {158.001 -24 c} {133.401 -67 c} {133.401 -67} {139.801 -67.8 c} {131.601 -80.2 c} {131.601 -80.2} {129.401 -86.8 c} {140.801 -72.2 c} {143.001 -70.8} {145.201 -69.4 c} {146.201 -67.2 c} {144.601 -67.4} {143.001 -67.6 c} {141.201 -65.4 c} {142.601 -65.2} {144.001 -65 c} {157.001 -50 c} {160.401 -39.8} {163.801 -29.6 c} {169.801 -25.6 c} {176.001 -19.6} {182.201 -13.6 c} {181.401 10.6 c} {181.401 10.6} {181.001 19.4 c} {187.001 30 c} {187.001 30} {189.001 33.8 c} {184.801 52 c} {184.801 52} {182.801 54.2 c} {184.201 55 c} {184.201 55} {185.201 56.2 c} {192.001 69.4 c} {192.001 69.4} {190.201 69.2 c} {193.801 72.8 c} {193.801 72.8} {199.001 78.8 c} {192.601 75.8 c} {192.601 75.8} {186.601 74.2 c} {193.601 84 c} {193.601 84} {194.801 85.8 c} {185.801 81.2 c} {185.801 81.2} {176.601 80.6 c} {188.201 87.8 c} {188.201 87.8} {196.801 95 c} {185.401 90.6 c} {185.401 90.6} {180.801 88.8 c} {184.001 95.6 c} {184.001 95.6} {187.201 97.2 c} {204.401 104.2 c} {204.401 104.2} {204.801 108.001 c} {201.801 113.001 c} {201.801 113.001} {202.201 117.001 c} {200.001 120.401 c} {200.001 120.401} {198.801 128.601 c} {198.201 129.401 c} {198.201 129.401} {194.001 129.601 c} {186.601 143.401 c} {186.601 143.401} {184.801 146.001 c} {174.601 158.001 c} {174.601 158.001} {172.601 165.001 c} {154.601 157.801 c} {154.601 157.801} {148.001 161.201 c} {150.001 157.801 c} {150.001 157.801} {149.601 155.601 c} {154.401 149.601 c} {154.401 149.601} {161.401 147.001 c} {158.801 136.201 c} {158.801 136.201} {162.801 134.801 c} {151.601 132.001 c} {151.801 130.801} {152.001 129.601 c} {157.801 128.201 c} {157.801 128.201} {165.801 126.201 c} {161.401 123.801 c} {161.401 123.801} {160.801 119.801 c} {163.801 114.201 c} {163.801 114.201} {175.401 113.401 c} {163.801 97.2 c} {163.801 97.2} {153.001 89.6 c} {152.001 83.8 c} {152.001 83.8} {164.601 75.6 c} {156.401 63.2 c} {156.601 59.6} {156.801 56 c} {158.001 34.4 c} {158.001 34.4} {156.001 28.2 c} {153.001 14.6 c} {153.001 14.6} {155.201 9.4 c} {162.601 -3.2 c} {162.601 -3.2} {165.401 -7.4 c} {174.201 -12.2 c} {172.001 -15.2} {169.801 -18.2 c} {162.001 -16.4 c} {162.001 -16.4} {154.201 -17.8 c} {154.801 -12.6 c} {154.801 -12.6} {153.201 -11.6 c} {152.401 -6.6 c} {152.401 -6.6} {151.68 1.333 c} {142.801 7.6 c} {142.801 7.6} {131.601 13.8 c} {140.801 17.8 c} {140.801 17.8} {146.801 24.4 c} {137.001 24.6 c} {137.001 24.6} {126.001 22.8 c} {134.201 33 c} {134.201 33} {145.001 45.8 c} {142.001 48.6 c} {142.001 48.6} {131.801 49.6 c} {144.401 58.8 c} {144.401 58.8} {144.401 58.8 c} {143.601 56.8 c} {143.801 58.6} {144.001 60.4 c} {147.001 64.6 c} {147.801 66.6} {148.601 68.6 c} {144.601 68.8 c} {144.601 68.8} {145.201 78.4 c} {129.801 74.2 c} {129.801 74.2} {129.801 74.2 c} {129.801 74.2 c} {128.201 74.4} {126.601 74.6 c} {115.401 73.8 c} {109.601 71.6} {103.801 69.4 c} {97.001 69.4 c} {97.001 69.4} {97.001 69.4 c} {93.001 71.2 c} {85.4 71} {77.8 70.8 c} {69.8 73.6 c} {69.8 73.6} {65.4 73.2 c} {74 68.8 c} {74.2 69} {74.4 69.2 c} {80 63.6 c} {72 64.2} {50.203 65.835 c} {39.4 55.6 c} {39.4 55.6} {37.4 54.2 c} {34.8 51.4 c} {34.8 51.4} {24.8 49.4 c} {36.2 63.8 c} {36.2 63.8} {37.4 65.2 c} {36 66.2 c} {36 66.2} {35.2 64.6 c} {27.4 59.2 c} {27.4 59.2} {24.589 58.227 c} {23.226 56.893 c} {20.895 54.407}} -tags __path__231 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__232 -priority 10
    $w.zinc add curve __g__232 {{-3 42.8} {-3 42.8 c} {8.6 48.4 c} {11.2 51.2} {13.8 54 c} {27.8 65.4 c} {27.8 65.4} {27.8 65.4 c} {22.4 63.4 c} {19.8 61.6} {17.2 59.8 c} {6.4 51.6 c} {6.4 51.6} {6.4 51.6 c} {2.6 45.6 c} {-3 42.8}} -tags __path__233 -priority 10 -filled 1 -closed 1 -fillcolor \#4c0000 -filled 1 -linecolor \#4c0000
    $w.zinc add group __svg__1  -tags __g__234 -priority 10
    $w.zinc add curve __g__234 {{-61.009 11.603} {-60.672 11.455 c} {-61.196 8.743 c} {-61.4 8.2} {-62.422 5.474 c} {-71.4 4 c} {-71.4 4} {-71.627 5.365 c} {-71.682 6.961 c} {-71.576 8.599} {-71.576 8.599 c} {-66.708 14.118 c} {-61.009 11.603}} -tags __path__235 -priority 10 -filled 1 -closed 1 -fillcolor \#99cc32 -filled 1 -linecolor \#99cc32
    $w.zinc add group __svg__1  -tags __g__236 -priority 10
    $w.zinc add curve __g__236 {{-61.009 11.403} {-61.458 11.561 c} {-61.024 8.669 c} {-61.2 8.2} {-62.222 5.474 c} {-71.4 3.9 c} {-71.4 3.9} {-71.627 5.265 c} {-71.682 6.861 c} {-71.576 8.499} {-71.576 8.499 c} {-67.308 13.618 c} {-61.009 11.403}} -tags __path__237 -priority 10 -filled 1 -closed 1 -fillcolor \#659900 -filled 1 -linecolor \#659900
    $w.zinc add group __svg__1  -tags __g__238 -priority 10
    $w.zinc add curve __g__238 {{-65.4 11.546} {-66.025 11.546 c} {-66.531 10.406 c} {-66.531 9} {-66.531 7.595 c} {-66.025 6.455 c} {-65.4 6.455} {-64.775 6.455 c} {-64.268 7.595 c} {-64.268 9} {-64.268 10.406 c} {-64.775 11.546 c} {-65.4 11.546}} -tags __path__239 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__240 -priority 10
    $w.zinc add curve __g__240 {{-65.4 9}} -tags __path__241 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__242 -priority 10
    $w.zinc add curve __g__242 {{-111 109.601} {-111 109.601 c} {-116.6 119.601 c} {-91.8 113.601} {-91.8 113.601 c} {-77.8 112.401 c} {-75.4 110.001} {-74.2 110.801 c} {-65.834 113.734 c} {-63 114.401} {-56.2 116.001 c} {-47.8 106 c} {-47.8 106} {-47.8 106 c} {-43.2 95.5 c} {-40.4 95.5} {-37.6 95.5 c} {-40.8 97.1 c} {-40.8 97.1} {-40.8 97.1 c} {-47.4 107.201 c} {-47 108.801} {-47 108.801 c} {-52.2 128.801 c} {-68.2 129.601} {-68.2 129.601 c} {-84.35 130.551 c} {-83 136.401} {-83 136.401 c} {-74.2 134.001 c} {-71.8 136.401} {-71.8 136.401 c} {-61 136.001 c} {-69 142.401} {-75.8 154.001} {-75.8 154.001 c} {-75.66 157.919 c} {-85.8 154.401} {-95.6 151.001 c} {-105.9 138.101 c} {-105.9 138.101} {-105.9 138.101 c} {-121.85 123.551 c} {-111 109.601}} -tags __path__243 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__244 -priority 10
    $w.zinc add curve __g__244 {{-112.2 113.601} {-112.2 113.601 c} {-114.2 123.201 c} {-77.4 112.801} {-77.4 112.801 c} {-73 112.801 c} {-70.6 113.601} {-68.2 114.401 c} {-56.2 117.201 c} {-54.2 116.001} {-54.2 116.001 c} {-61.4 129.601 c} {-73 128.001} {-73 128.001 c} {-86.2 129.601 c} {-85.8 134.401} {-85.8 134.401 c} {-81.8 141.601 c} {-77 144.001} {-77 144.001 c} {-74.2 146.401 c} {-74.6 149.601} {-75 152.801 c} {-77.8 154.401 c} {-79.8 155.201} {-81.8 156.001 c} {-85 152.801 c} {-86.6 152.801} {-88.2 152.801 c} {-96.6 146.401 c} {-101 141.601} {-105.4 136.801 c} {-113.8 124.801 c} {-113.4 122.001} {-113 119.201 c} {-112.2 113.601 c} {-112.2 113.601}} -tags __path__245 -priority 10 -filled 1 -closed 1 -fillcolor \#e59999 -filled 1 -linecolor \#e59999
    $w.zinc add group __svg__1  -tags __g__246 -priority 10
    $w.zinc add curve __g__246 {{-109 131.051} {-106.4 135.001 c} {-103.2 139.201 c} {-101 141.601} {-96.6 146.401 c} {-88.2 152.801 c} {-86.6 152.801} {-85 152.801 c} {-81.8 156.001 c} {-79.8 155.201} {-77.8 154.401 c} {-75 152.801 c} {-74.6 149.601} {-74.2 146.401 c} {-77 144.001 c} {-77 144.001} {-80.066 142.468 c} {-82.806 138.976 c} {-84.385 136.653} {-84.385 136.653 c} {-84.2 139.201 c} {-89.4 138.401} {-94.6 137.601 c} {-99.8 134.801 c} {-101.4 131.601} {-103 128.401 c} {-105.4 126.001 c} {-103.8 129.601} {-102.2 133.201 c} {-99.8 136.801 c} {-98.2 137.201} {-96.6 137.601 c} {-97 138.801 c} {-99.4 138.401} {-101.8 138.001 c} {-104.6 137.601 c} {-109 132.401}} -tags __path__247 -priority 10 -filled 1 -closed 1 -fillcolor \#b26565 -filled 1 -linecolor \#b26565
    $w.zinc add group __svg__1  -tags __g__248 -priority 10
    $w.zinc add curve __g__248 {{-111.6 110.001} {-111.6 110.001 c} {-109.8 96.4 c} {-108.6 92.4} {-108.6 92.4 c} {-109.4 85.6 c} {-107 81.4} {-104.6 77.2 c} {-102.6 71 c} {-99.6 65.6} {-96.6 60.2 c} {-96.4 56.2 c} {-92.4 54.6} {-88.4 53 c} {-82.4 44.4 c} {-79.6 43.4} {-76.8 42.4 c} {-77 43.2 c} {-77 43.2} {-77 43.2 c} {-70.2 28.4 c} {-56.6 32.4} {-56.6 32.4 c} {-72.8 29.6 c} {-57 20.2} {-57 20.2 c} {-61.8 21.3 c} {-58.5 14.3} {-56.299 9.632 c} {-56.8 16.4 c} {-67.8 28.2} {-67.8 28.2 c} {-72.8 36.8 c} {-78 39.8} {-83.2 42.8 c} {-95.2 49.8 c} {-96.4 53.6} {-97.6 57.4 c} {-100.8 63.2 c} {-102.8 64.8} {-104.8 66.4 c} {-107.6 70.6 c} {-108 74} {-108 74 c} {-109.2 78 c} {-110.6 79.2} {-112 80.4 c} {-112.2 83.6 c} {-112.2 85.6} {-112.2 87.6 c} {-114.2 90.4 c} {-114 92.8} {-114 92.8 c} {-113.2 111.801 c} {-113.6 113.801} {-111.6 110.001}} -tags __path__249 -priority 10 -filled 1 -closed 1 -fillcolor \#992600 -filled 1 -linecolor \#992600
    $w.zinc add group __svg__1  -tags __g__250 -priority 10
    $w.zinc add curve __g__250 {{-120.2 114.601} {-120.2 114.601 c} {-122.2 113.201 c} {-126.6 119.201} {-126.6 119.201 c} {-119.3 152.201 c} {-119.3 153.601} {-119.3 153.601 c} {-118.2 151.501 c} {-119.5 144.301} {-120.8 137.101 c} {-121.7 124.401 c} {-121.7 124.401} {-120.2 114.601}} -tags __path__251 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__252 -priority 10
    $w.zinc add curve __g__252 {{-98.6 54} {-98.6 54 c} {-116.2 57.2 c} {-115.8 86.4} {-116.6 111.201} {-116.6 111.201 c} {-117.8 85.6 c} {-119 84} {-120.2 82.4 c} {-116.2 71.2 c} {-119.4 77.2} {-119.4 77.2 c} {-133.4 91.2 c} {-125.4 112.401} {-125.4 112.401 c} {-123.9 115.701 c} {-126.9 111.101} {-126.9 111.101 c} {-131.5 98.5 c} {-130.4 92.1} {-130.4 92.1 c} {-130.2 89.9 c} {-128.3 87.1} {-128.3 87.1 c} {-119.7 75.4 c} {-117 73.1} {-117 73.1 c} {-115.2 58.7 c} {-99.8 53.5} {-99.8 53.5 c} {-94.1 51.2 c} {-98.6 54}} -tags __path__253 -priority 10 -filled 1 -closed 1 -fillcolor \#992600 -filled 1 -linecolor \#992600
    $w.zinc add group __svg__1  -tags __g__254 -priority 10
    $w.zinc add curve __g__254 {{40.8 -12.2} {41.46 -12.554 c} {41.451 -13.524 c} {42.031 -13.697} {43.18 -14.041 c} {43.344 -15.108 c} {43.862 -15.892} {44.735 -17.211 c} {44.928 -18.744 c} {45.51 -20.235} {45.782 -20.935 c} {45.809 -21.89 c} {45.496 -22.55} {44.322 -25.031 c} {43.62 -27.48 c} {42.178 -29.906} {41.91 -30.356 c} {41.648 -31.15 c} {41.447 -31.748} {40.984 -33.132 c} {39.727 -34.123 c} {38.867 -35.443} {38.579 -35.884 c} {39.104 -36.809 c} {38.388 -36.893} {37.491 -36.998 c} {36.042 -37.578 c} {35.809 -36.552} {35.221 -33.965 c} {36.232 -31.442 c} {37.2 -29} {36.418 -28.308 c} {36.752 -27.387 c} {36.904 -26.62} {37.614 -23.014 c} {36.416 -19.662 c} {35.655 -16.188} {35.632 -16.084 c} {35.974 -15.886 c} {35.946 -15.824} {34.724 -13.138 c} {33.272 -10.693 c} {31.453 -8.312} {30.695 -7.32 c} {29.823 -6.404 c} {29.326 -5.341} {28.958 -4.554 c} {28.55 -3.588 c} {28.8 -2.6} {25.365 0.18 c} {23.115 4.025 c} {20.504 7.871} {20.042 8.551 c} {20.333 9.76 c} {20.884 10.029} {21.697 10.427 c} {22.653 9.403 c} {23.123 8.557} {23.512 7.859 c} {23.865 7.209 c} {24.356 6.566} {24.489 6.391 c} {24.31 5.972 c} {24.445 5.851} {27.078 3.504 c} {28.747 0.568 c} {31.2 -1.8} {33.15 -2.129 c} {34.687 -3.127 c} {36.435 -4.14} {36.743 -4.319 c} {37.267 -4.07 c} {37.557 -4.265} {39.31 -5.442 c} {39.308 -7.478 c} {39.414 -9.388} {39.464 -10.272 c} {39.66 -11.589 c} {40.8 -12.2}} -tags __path__255 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__256 -priority 10
    $w.zinc add curve __g__256 {{31.959 -16.666} {32.083 -16.743 c} {31.928 -17.166 c} {32.037 -17.382} {32.199 -17.706 c} {32.602 -17.894 c} {32.764 -18.218} {32.873 -18.434 c} {32.71 -18.814 c} {32.846 -18.956} {35.179 -21.403 c} {35.436 -24.427 c} {34.4 -27.4} {35.424 -28.02 c} {35.485 -29.282 c} {35.06 -30.129} {34.207 -31.829 c} {34.014 -33.755 c} {33.039 -35.298} {32.237 -36.567 c} {30.659 -37.811 c} {29.288 -36.508} {28.867 -36.108 c} {28.546 -35.321 c} {28.824 -34.609} {28.888 -34.446 c} {29.173 -34.3 c} {29.146 -34.218} {29.039 -33.894 c} {28.493 -33.67 c} {28.487 -33.398} {28.457 -31.902 c} {27.503 -30.391 c} {28.133 -29.062} {28.905 -27.433 c} {29.724 -25.576 c} {30.4 -23.8} {29.166 -21.684 c} {30.199 -19.235 c} {28.446 -17.358} {28.31 -17.212 c} {28.319 -16.826 c} {28.441 -16.624} {28.733 -16.138 c} {29.139 -15.732 c} {29.625 -15.44} {29.827 -15.319 c} {30.175 -15.317 c} {30.375 -15.441} {30.953 -15.803 c} {31.351 -16.29 c} {31.959 -16.666}} -tags __path__257 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__258 -priority 10
    $w.zinc add curve __g__258 {{94.771 -26.977} {96.16 -25.185 c} {96.45 -22.39 c} {94.401 -21} {94.951 -17.691 c} {98.302 -19.67 c} {100.401 -20.2} {100.292 -20.588 c} {100.519 -20.932 c} {100.802 -20.937} {101.859 -20.952 c} {102.539 -21.984 c} {103.601 -21.8} {104.035 -23.357 c} {105.673 -24.059 c} {106.317 -25.439} {108.043 -29.134 c} {107.452 -33.407 c} {104.868 -36.653} {104.666 -36.907 c} {104.883 -37.424 c} {104.759 -37.786} {104.003 -39.997 c} {101.935 -40.312 c} {100.001 -41} {98.824 -44.875 c} {98.163 -48.906 c} {96.401 -52.6} {94.787 -52.85 c} {94.089 -54.589 c} {92.752 -55.309} {91.419 -56.028 c} {90.851 -54.449 c} {90.892 -53.403} {90.899 -53.198 c} {91.351 -52.974 c} {91.181 -52.609} {91.105 -52.445 c} {90.845 -52.334 c} {90.845 -52.2} {90.846 -52.065 c} {91.067 -51.934 c} {91.201 -51.8} {90.283 -50.98 c} {88.86 -50.503 c} {88.565 -49.358} {87.611 -45.648 c} {90.184 -42.523 c} {91.852 -39.322} {92.443 -38.187 c} {91.707 -36.916 c} {90.947 -35.708} {90.509 -35.013 c} {90.617 -33.886 c} {90.893 -33.03} {91.645 -30.699 c} {93.236 -28.96 c} {94.771 -26.977}} -tags __path__259 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__260 -priority 10
    $w.zinc add curve __g__260 {{57.611 -8.591} {56.124 -6.74 c} {52.712 -4.171 c} {55.629 -2.243} {55.823 -2.114 c} {56.193 -2.11 c} {56.366 -2.244} {58.387 -3.809 c} {60.39 -4.712 c} {62.826 -5.294} {62.95 -5.323 c} {63.224 -4.856 c} {63.593 -5.017} {65.206 -5.72 c} {67.216 -5.662 c} {68.4 -7} {72.167 -6.776 c} {75.732 -7.892 c} {79.123 -9.2} {80.284 -9.648 c} {81.554 -10.207 c} {82.755 -10.709} {84.131 -11.285 c} {85.335 -12.213 c} {86.447 -13.354} {86.58 -13.49 c} {86.934 -13.4 c} {87.201 -13.4} {87.161 -14.263 c} {88.123 -14.39 c} {88.37 -15.012} {88.462 -15.244 c} {88.312 -15.64 c} {88.445 -15.742} {90.583 -17.372 c} {91.503 -19.39 c} {90.334 -21.767} {90.049 -22.345 c} {89.8 -22.963 c} {89.234 -23.439} {88.149 -24.35 c} {87.047 -23.496 c} {86 -23.8} {85.841 -23.172 c} {85.112 -23.344 c} {84.726 -23.146} {83.867 -22.707 c} {82.534 -23.292 c} {81.675 -22.854} {80.313 -22.159 c} {79.072 -21.99 c} {77.65 -21.613} {77.338 -21.531 c} {76.56 -21.627 c} {76.4 -21} {76.266 -21.134 c} {76.118 -21.368 c} {76.012 -21.346} {74.104 -20.95 c} {72.844 -20.736 c} {71.543 -19.044} {71.44 -18.911 c} {70.998 -19.09 c} {70.839 -18.955} {69.882 -18.147 c} {69.477 -16.913 c} {68.376 -16.241} {68.175 -16.118 c} {67.823 -16.286 c} {67.629 -16.157} {66.983 -15.726 c} {66.616 -15.085 c} {65.974 -14.638} {65.645 -14.409 c} {65.245 -14.734 c} {65.277 -14.99} {65.522 -16.937 c} {66.175 -18.724 c} {65.6 -20.6} {67.677 -23.12 c} {70.194 -25.069 c} {72 -27.8} {72.015 -29.966 c} {72.707 -32.112 c} {72.594 -34.189} {72.584 -34.382 c} {72.296 -35.115 c} {72.17 -35.462} {71.858 -36.316 c} {72.764 -37.382 c} {71.92 -38.106} {70.516 -39.309 c} {69.224 -38.433 c} {68.4 -37} {66.562 -36.61 c} {64.496 -35.917 c} {62.918 -37.151} {61.911 -37.938 c} {61.333 -38.844 c} {60.534 -39.9} {59.549 -41.202 c} {59.884 -42.638 c} {59.954 -44.202} {59.96 -44.33 c} {59.645 -44.466 c} {59.645 -44.6} {59.646 -44.735 c} {59.866 -44.866 c} {60 -45} {59.294 -45.626 c} {59.019 -46.684 c} {58 -47} {58.305 -48.092 c} {57.629 -48.976 c} {56.758 -49.278} {54.763 -49.969 c} {53.086 -48.057 c} {51.194 -47.984} {50.68 -47.965 c} {50.213 -49.003 c} {49.564 -49.328} {49.132 -49.544 c} {48.428 -49.577 c} {48.066 -49.311} {47.378 -48.807 c} {46.789 -48.693 c} {46.031 -48.488} {44.414 -48.052 c} {43.136 -46.958 c} {41.656 -46.103} {40.171 -45.246 c} {39.216 -43.809 c} {38.136 -42.489} {37.195 -41.337 c} {37.059 -38.923 c} {38.479 -38.423} {40.322 -37.773 c} {41.626 -40.476 c} {43.592 -40.15} {43.904 -40.099 c} {44.11 -39.788 c} {44 -39.4} {44.389 -39.291 c} {44.607 -39.52 c} {44.8 -39.8} {45.658 -38.781 c} {46.822 -38.444 c} {47.76 -37.571} {48.73 -36.667 c} {50.476 -37.085 c} {51.491 -36.088} {53.02 -34.586 c} {52.461 -31.905 c} {54.4 -30.6} {53.814 -29.287 c} {53.207 -28.01 c} {52.872 -26.583} {52.59 -25.377 c} {53.584 -24.18 c} {54.795 -24.271} {56.053 -24.365 c} {56.315 -25.124 c} {56.8 -26.2} {57.067 -25.933 c} {57.536 -25.636 c} {57.495 -25.42} {57.038 -23.033 c} {56.011 -21.04 c} {55.553 -18.609} {55.494 -18.292 c} {55.189 -18.09 c} {54.8 -18.2} {54.332 -14.051 c} {50.28 -11.657 c} {47.735 -8.492} {47.332 -7.99 c} {47.328 -6.741 c} {47.737 -6.338} {49.14 -4.951 c} {51.1 -6.497 c} {52.8 -7} {53.013 -8.206 c} {53.872 -9.148 c} {55.204 -9.092} {55.46 -9.082 c} {55.695 -9.624 c} {56.019 -9.754} {56.367 -9.892 c} {56.869 -9.668 c} {57.155 -9.866} {58.884 -11.061 c} {60.292 -12.167 c} {62.03 -13.356} {62.222 -13.487 c} {62.566 -13.328 c} {62.782 -13.436} {63.107 -13.598 c} {63.294 -13.985 c} {63.617 -14.17} {63.965 -14.37 c} {64.207 -14.08 c} {64.4 -13.8} {63.754 -13.451 c} {63.75 -12.494 c} {63.168 -12.292} {62.393 -12.024 c} {61.832 -11.511 c} {61.158 -11.064} {60.866 -10.871 c} {60.207 -11.119 c} {60.103 -10.94} {59.505 -9.912 c} {58.321 -9.474 c} {57.611 -8.591}} -tags __path__261 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__262 -priority 10
    $w.zinc add curve __g__262 {{2.2 -58} {2.2 -58 c} {-7.038 -60.872 c} {-18.2 -35.2} {-18.2 -35.2 c} {-20.6 -30 c} {-23 -28} {-25.4 -26 c} {-36.6 -22.4 c} {-38.6 -18.4} {-49 -2.4} {-49 -2.4 c} {-34.2 -18.4 c} {-31 -20.8} {-31 -20.8 c} {-23 -29.2 c} {-26.2 -22.4} {-26.2 -22.4 c} {-40.2 -11.6 c} {-39 -2.4} {-39 -2.4 c} {-44.6 12 c} {-45.4 14} {-45.4 14 c} {-29.4 -18 c} {-27 -19.2} {-24.6 -20.4 c} {-23.4 -20.4 c} {-24.6 -16.8} {-25.8 -13.2 c} {-26.2 3.2 c} {-29 5.2} {-29 5.2 c} {-21 -15.2 c} {-21.8 -18.4} {-21.8 -18.4 c} {-18.6 -22 c} {-16.2 -16.8} {-17.4 -0.8} {-13 11.2} {-13 11.2 c} {-15.4 0 c} {-13.8 -15.6} {-13.8 -15.6 c} {-15.8 -26 c} {-11.8 -20.4} {-7.8 -14.8 c} {1.8 -8.8 c} {1.8 -4} {1.8 -4 c} {-3.4 -21.6 c} {-12.6 -26.4} {-16.6 -20.4} {-17.8 -22.4} {-17.8 -22.4 c} {-21.4 -23.2 c} {-17 -30} {-12.6 -36.8 c} {-13 -37.6 c} {-13 -37.6} {-13 -37.6 c} {-6.6 -30.4 c} {-5 -30.4} {-5 -30.4 c} {8.2 -38 c} {9.4 -13.6} {9.4 -13.6 c} {16.2 -28 c} {7 -34.8} {7 -34.8 c} {-7.8 -36.8 c} {-6.6 -42} {0.6 -54.4} {4.2 -59.6 c} {2.6 -56.8 c} {2.6 -56.8}} -tags __path__263 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__264 -priority 10
    $w.zinc add curve __g__264 {{-17.8 -41.6} {-17.8 -41.6 c} {-30.6 -41.6 c} {-33.8 -36.4} {-41 -26.8} {-41 -26.8 c} {-23.8 -36.8 c} {-19.8 -38} {-15.8 -39.2 c} {-17.8 -41.6 c} {-17.8 -41.6}} -tags __path__265 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__266 -priority 10
    $w.zinc add curve __g__266 {{-57.8 -35.2} {-57.8 -35.2 c} {-59.8 -34 c} {-60.2 -31.2} {-60.6 -28.4 c} {-63 -28 c} {-62.2 -25.2} {-61.4 -22.4 c} {-59.4 -20 c} {-59.4 -24} {-59.4 -28 c} {-57.8 -30 c} {-57 -31.2} {-56.2 -32.4 c} {-54.6 -36.8 c} {-57.8 -35.2}} -tags __path__267 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__268 -priority 10
    $w.zinc add curve __g__268 {{-66.6 26} {-66.6 26 c} {-75 22 c} {-78.2 18.4} {-81.4 14.8 c} {-80.948 19.966 c} {-85.8 19.6} {-91.647 19.159 c} {-90.6 3.2 c} {-90.6 3.2} {-94.6 10.8} {-94.6 10.8 c} {-95.8 25.2 c} {-87.8 22.8} {-83.893 21.628 c} {-82.6 23.2 c} {-84.2 24} {-85.8 24.8 c} {-78.6 25.2 c} {-81.4 26.8} {-84.2 28.4 c} {-69.8 23.2 c} {-72.2 33.6} {-66.6 26}} -tags __path__269 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__270 -priority 10
    $w.zinc add curve __g__270 {{-79.2 40.4} {-79.2 40.4 c} {-94.6 44.8 c} {-98.2 35.2} {-98.2 35.2 c} {-103 37.6 c} {-100.8 40.6} {-98.6 43.6 c} {-97.4 44 c} {-97.4 44} {-97.4 44 c} {-92 45.2 c} {-92.6 46} {-93.2 46.8 c} {-95.6 50.2 c} {-95.6 50.2} {-95.6 50.2 c} {-85.4 44.2 c} {-79.2 40.4}} -tags __path__271 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__272 -priority 10
    $w.zinc add curve __g__272 {{149.201 118.601} {148.774 120.735 c} {147.103 121.536 c} {145.201 122.201} {143.284 121.243 c} {140.686 118.137 c} {138.801 120.201} {138.327 119.721 c} {137.548 119.661 c} {137.204 118.999} {136.739 118.101 c} {137.011 117.055 c} {136.669 116.257} {136.124 114.985 c} {135.415 113.619 c} {135.601 112.201} {137.407 111.489 c} {138.002 109.583 c} {137.528 107.82} {137.459 107.563 c} {137.03 107.366 c} {137.23 107.017} {137.416 106.694 c} {137.734 106.467 c} {138.001 106.2} {137.866 106.335 c} {137.721 106.568 c} {137.61 106.548} {137 106.442 c} {137.124 105.805 c} {137.254 105.418} {137.839 103.672 c} {139.853 103.408 c} {141.201 104.6} {141.457 104.035 c} {141.966 104.229 c} {142.401 104.2} {142.351 103.621 c} {142.759 103.094 c} {142.957 102.674} {143.475 101.576 c} {145.104 102.682 c} {145.901 102.07} {146.977 101.245 c} {148.04 100.546 c} {149.118 101.149} {150.927 102.162 c} {152.636 103.374 c} {153.835 105.115} {154.41 105.949 c} {154.65 107.23 c} {154.592 108.188} {154.554 108.835 c} {153.173 108.483 c} {152.83 109.412} {152.185 111.16 c} {154.016 111.679 c} {154.772 113.017} {154.97 113.366 c} {154.706 113.67 c} {154.391 113.768} {153.98 113.896 c} {153.196 113.707 c} {153.334 114.16} {154.306 117.353 c} {151.55 118.031 c} {149.201 118.601}} -tags __path__273 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__274 -priority 10
    $w.zinc add curve __g__274 {{139.6 138.201} {139.593 136.463 c} {137.992 134.707 c} {139.201 133.001} {139.336 133.135 c} {139.467 133.356 c} {139.601 133.356} {139.736 133.356 c} {139.867 133.135 c} {140.001 133.001} {141.496 135.217 c} {145.148 136.145 c} {145.006 138.991} {144.984 139.438 c} {143.897 140.356 c} {144.801 141.001} {142.988 142.349 c} {142.933 144.719 c} {142.001 146.601} {140.763 146.315 c} {139.551 145.952 c} {138.401 145.401} {138.753 143.915 c} {138.636 142.231 c} {139.456 140.911} {139.89 140.213 c} {139.603 139.134 c} {139.6 138.201}} -tags __path__275 -priority 10 -filled 1 -closed 1 -fillcolor \#ffffff -filled 1 -linecolor \#ffffff
    $w.zinc add group __svg__1  -tags __g__276 -priority 10
    $w.zinc add curve __g__276 {{-26.6 129.201} {-26.6 129.201 c} {-43.458 139.337 c} {-29.4 124.001} {-20.6 114.401 c} {-10.6 108.801 c} {-10.6 108.801} {-10.6 108.801 c} {-0.2 104.4 c} {3.4 103.2} {7 102 c} {22.2 96.8 c} {25.4 96.4} {28.6 96 c} {38.2 92 c} {45 96} {51.8 100 c} {59.8 104.4 c} {59.8 104.4} {59.8 104.4 c} {43.4 96 c} {39.8 98.4} {36.2 100.8 c} {29 100.4 c} {23 103.6} {23 103.6 c} {8.2 108.001 c} {5 110.001} {1.8 112.001 c} {-8.6 123.601 c} {-10.2 122.801} {-11.8 122.001 c} {-9.8 121.601 c} {-8.6 118.801} {-7.4 116.001 c} {-9.4 114.401 c} {-17.4 120.801} {-25.4 127.201 c} {-26.6 129.201 c} {-26.6 129.201}} -tags __path__277 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__278 -priority 10
    $w.zinc add curve __g__278 {{-19.195 123.234} {-19.195 123.234 c} {-17.785 110.194 c} {-9.307 111.859} {-9.307 111.859 c} {-1.081 107.689 c} {1.641 105.721} {1.641 105.721 c} {9.78 104.019 c} {11.09 103.402} {29.569 94.702 c} {44.288 99.221 c} {44.835 98.101} {45.381 96.982 c} {65.006 104.099 c} {68.615 108.185} {69.006 108.628 c} {58.384 102.588 c} {48.686 100.697} {40.413 99.083 c} {18.811 100.944 c} {7.905 106.48} {4.932 107.989 c} {-4.013 113.773 c} {-6.544 113.662} {-9.075 113.55 c} {-19.195 123.234 c} {-19.195 123.234}} -tags __path__279 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__280 -priority 10
    $w.zinc add curve __g__280 {{-23 148.801} {-23 148.801 c} {-38.2 146.401 c} {-21.4 144.801} {-21.4 144.801 c} {-3.4 142.801 c} {0.6 137.601} {0.6 137.601 c} {14.2 128.401 c} {17 128.001} {19.8 127.601 c} {49.8 120.401 c} {50.2 118.001} {50.6 115.601 c} {56.2 115.601 c} {57.8 116.401} {59.4 117.201 c} {58.6 118.401 c} {55.8 119.201} {53 120.001 c} {21.8 136.401 c} {15.4 137.601} {9 138.801 c} {-2.6 146.401 c} {-7.4 147.601} {-12.2 148.801 c} {-23 148.801 c} {-23 148.801}} -tags __path__281 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__282 -priority 10
    $w.zinc add curve __g__282 {{-3.48 141.403} {-3.48 141.403 c} {-12.062 140.574 c} {-3.461 139.755} {-3.461 139.755 c} {5.355 136.331 c} {7.403 133.668} {7.403 133.668 c} {14.367 128.957 c} {15.8 128.753} {17.234 128.548 c} {31.194 124.861 c} {31.399 123.633} {31.604 122.404 c} {65.67 109.823 c} {70.09 113.013} {73.001 115.114 c} {63.1 113.437 c} {53.466 117.847} {52.111 118.467 c} {18.258 133.054 c} {14.981 133.668} {11.704 134.283 c} {5.765 138.174 c} {3.307 138.788} {0.85 139.403 c} {-3.48 141.403 c} {-3.48 141.403}} -tags __path__283 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__284 -priority 10
    $w.zinc add curve __g__284 {{-11.4 143.601} {-11.4 143.601 c} {-6.2 143.201 c} {-7.4 144.801} {-8.6 146.401 c} {-11 145.601 c} {-11 145.601} {-11.4 143.601}} -tags __path__285 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__286 -priority 10
    $w.zinc add curve __g__286 {{-18.6 145.201} {-18.6 145.201 c} {-13.4 144.801 c} {-14.6 146.401} {-15.8 148.001 c} {-18.2 147.201 c} {-18.2 147.201} {-18.6 145.201}} -tags __path__287 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__288 -priority 10
    $w.zinc add curve __g__288 {{-29 146.801} {-29 146.801 c} {-23.8 146.401 c} {-25 148.001} {-26.2 149.601 c} {-28.6 148.801 c} {-28.6 148.801} {-29 146.801}} -tags __path__289 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__290 -priority 10
    $w.zinc add curve __g__290 {{-36.6 147.601} {-36.6 147.601 c} {-31.4 147.201 c} {-32.6 148.801} {-33.8 150.401 c} {-36.2 149.601 c} {-36.2 149.601} {-36.6 147.601}} -tags __path__291 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__292 -priority 10
    $w.zinc add curve __g__292 {{1.8 108.001} {1.8 108.001 c} {6.2 108.001 c} {5 109.601} {3.8 111.201 c} {0.6 110.801 c} {0.6 110.801} {1.8 108.001}} -tags __path__293 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__294 -priority 10
    $w.zinc add curve __g__294 {{-8.2 113.601} {-8.2 113.601 c} {-1.694 111.46 c} {-4.2 114.801} {-5.4 116.401 c} {-7.8 115.601 c} {-7.8 115.601} {-8.2 113.601}} -tags __path__295 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__296 -priority 10
    $w.zinc add curve __g__296 {{-19.4 118.401} {-19.4 118.401 c} {-14.2 118.001 c} {-15.4 119.601} {-16.6 121.201 c} {-19 120.401 c} {-19 120.401} {-19.4 118.401}} -tags __path__297 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__298 -priority 10
    $w.zinc add curve __g__298 {{-27 124.401} {-27 124.401 c} {-21.8 124.001 c} {-23 125.601} {-24.2 127.201 c} {-26.6 126.401 c} {-26.6 126.401} {-27 124.401}} -tags __path__299 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__300 -priority 10
    $w.zinc add curve __g__300 {{-33.8 129.201} {-33.8 129.201 c} {-28.6 128.801 c} {-29.8 130.401} {-31 132.001 c} {-33.4 131.201 c} {-33.4 131.201} {-33.8 129.201}} -tags __path__301 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__302 -priority 10
    $w.zinc add curve __g__302 {{5.282 135.598} {5.282 135.598 c} {12.203 135.066 c} {10.606 137.195} {9.009 139.325 c} {5.814 138.26 c} {5.814 138.26} {5.282 135.598}} -tags __path__303 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__304 -priority 10
    $w.zinc add curve __g__304 {{15.682 130.798} {15.682 130.798 c} {22.603 130.266 c} {21.006 132.395} {19.409 134.525 c} {16.214 133.46 c} {16.214 133.46} {15.682 130.798}} -tags __path__305 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__306 -priority 10
    $w.zinc add curve __g__306 {{26.482 126.398} {26.482 126.398 c} {33.403 125.866 c} {31.806 127.995} {30.209 130.125 c} {27.014 129.06 c} {27.014 129.06} {26.482 126.398}} -tags __path__307 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__308 -priority 10
    $w.zinc add curve __g__308 {{36.882 121.598} {36.882 121.598 c} {43.803 121.066 c} {42.206 123.195} {40.609 125.325 c} {37.414 124.26 c} {37.414 124.26} {36.882 121.598}} -tags __path__309 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__310 -priority 10
    $w.zinc add curve __g__310 {{9.282 103.598} {9.282 103.598 c} {16.203 103.066 c} {14.606 105.195} {13.009 107.325 c} {9.014 107.06 c} {9.014 107.06} {9.282 103.598}} -tags __path__311 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__312 -priority 10
    $w.zinc add curve __g__312 {{19.282 100.398} {19.282 100.398 c} {26.203 99.866 c} {24.606 101.995} {23.009 104.125 c} {18.614 103.86 c} {18.614 103.86} {19.282 100.398}} -tags __path__313 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__314 -priority 10
    $w.zinc add curve __g__314 {{-3.4 140.401} {-3.4 140.401 c} {1.8 140.001 c} {0.6 141.601} {-0.6 143.201 c} {-3 142.401 c} {-3 142.401} {-3.4 140.401}} -tags __path__315 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__316 -priority 10
    $w.zinc add curve __g__316 {{-76.6 41.2} {-76.6 41.2 c} {-81 50 c} {-81.4 53.2} {-81.4 53.2 c} {-80.6 44.4 c} {-79.4 42.4} {-78.2 40.4 c} {-76.6 41.2 c} {-76.6 41.2}} -tags __path__317 -priority 10 -filled 1 -closed 1 -fillcolor \#992600 -filled 1 -linecolor \#992600
    $w.zinc add group __svg__1  -tags __g__318 -priority 10
    $w.zinc add curve __g__318 {{-95 55.2} {-95 55.2 c} {-98.2 69.6 c} {-97.8 72.4} {-97.8 72.4 c} {-99 60.8 c} {-98.6 59.6} {-98.2 58.4 c} {-95 55.2 c} {-95 55.2}} -tags __path__319 -priority 10 -filled 1 -closed 1 -fillcolor \#992600 -filled 1 -linecolor \#992600
    $w.zinc add group __svg__1  -tags __g__320 -priority 10
    $w.zinc add curve __g__320 {{-74.2 -19.4} {-74.4 -16.2} {-76.6 -16} {-76.6 -16 c} {-62.4 -3.4 c} {-61.8 4.2} {-61.8 4.2 c} {-61 -4 c} {-74.2 -19.4}} -tags __path__321 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__322 -priority 10
    $w.zinc add curve __g__322 {{-70.216 -18.135} {-70.647 -18.551 c} {-70.428 -19.296 c} {-70.836 -19.556} {-71.645 -20.072 c} {-69.538 -20.129 c} {-69.766 -20.845} {-70.149 -22.051 c} {-69.962 -22.072 c} {-70.084 -23.348} {-70.141 -23.946 c} {-69.553 -25.486 c} {-69.168 -25.926} {-67.722 -27.578 c} {-69.046 -30.51 c} {-67.406 -32.061} {-67.102 -32.35 c} {-66.726 -32.902 c} {-66.441 -33.32} {-65.782 -34.283 c} {-64.598 -34.771 c} {-63.648 -35.599} {-63.33 -35.875 c} {-63.531 -36.702 c} {-62.962 -36.61} {-62.248 -36.495 c} {-61.007 -36.625 c} {-61.052 -35.784} {-61.165 -33.664 c} {-62.494 -31.944 c} {-63.774 -30.276} {-63.323 -29.572 c} {-63.781 -28.937 c} {-64.065 -28.38} {-65.4 -25.76 c} {-65.211 -22.919 c} {-65.385 -20.079} {-65.39 -19.994 c} {-65.697 -19.916 c} {-65.689 -19.863} {-65.336 -17.528 c} {-64.752 -15.329 c} {-63.873 -13.1} {-63.507 -12.17 c} {-63.036 -11.275 c} {-62.886 -10.348} {-62.775 -9.662 c} {-62.672 -8.829 c} {-63.08 -8.124} {-61.045 -5.234 c} {-62.354 -2.583 c} {-61.185 0.948} {-60.978 1.573 c} {-59.286 3.487 c} {-59.749 3.326} {-62.262 2.455 c} {-62.374 2.057 c} {-62.551 1.304} {-62.697 0.681 c} {-63.027 -0.696 c} {-63.264 -1.298} {-63.328 -1.462 c} {-63.499 -3.346 c} {-63.577 -3.468} {-65.09 -5.85 c} {-63.732 -5.674 c} {-65.102 -8.032} {-66.53 -8.712 c} {-67.496 -9.816 c} {-68.619 -10.978} {-68.817 -11.182 c} {-67.674 -11.906 c} {-67.855 -12.119} {-68.947 -13.408 c} {-70.1 -14.175 c} {-69.764 -15.668} {-69.609 -16.358 c} {-69.472 -17.415 c} {-70.216 -18.135}} -tags __path__323 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__324 -priority 10
    $w.zinc add curve __g__324 {{-73.8 -16.4} {-73.8 -16.4 c} {-73.4 -9.6 c} {-71 -8} {-68.6 -6.4 c} {-69.8 -7.2 c} {-73 -8.4} {-76.2 -9.6 c} {-75 -10.4 c} {-75 -10.4} {-75 -10.4 c} {-77.8 -10 c} {-75.4 -8} {-73 -6 c} {-69.4 -3.6 c} {-71 -3.6} {-72.6 -3.6 c} {-80.2 -7.6 c} {-80.2 -10.4} {-80.2 -13.2 c} {-81.2 -17.3 c} {-81.2 -17.3} {-81.2 -17.3 c} {-80.1 -18.1 c} {-75.3 -18} {-75.3 -18 c} {-73.9 -17.3 c} {-73.8 -16.4}} -tags __path__325 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__326 -priority 10
    $w.zinc add curve __g__326 {{-74.6 2.2} {-74.6 2.2 c} {-83.12 -0.591 c} {-101.6 2.8} {-101.6 2.8 c} {-92.569 0.722 c} {-73.8 3} {-63.5 4.25 c} {-74.6 2.2 c} {-74.6 2.2}} -tags __path__327 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__328 -priority 10
    $w.zinc add curve __g__328 {{-72.502 2.129} {-72.502 2.129 c} {-80.748 -1.389 c} {-99.453 0.392} {-99.453 0.392 c} {-90.275 -0.897 c} {-71.774 2.995} {-61.62 5.131 c} {-72.502 2.129 c} {-72.502 2.129}} -tags __path__329 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__330 -priority 10
    $w.zinc add curve __g__330 {{-70.714 2.222} {-70.714 2.222 c} {-78.676 -1.899 c} {-97.461 -1.514} {-97.461 -1.514 c} {-88.213 -2.118 c} {-70.052 3.14} {-60.086 6.025 c} {-70.714 2.222 c} {-70.714 2.222}} -tags __path__331 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__332 -priority 10
    $w.zinc add curve __g__332 {{-69.444 2.445} {-69.444 2.445 c} {-76.268 -1.862 c} {-93.142 -2.96} {-93.142 -2.96 c} {-84.803 -2.79 c} {-68.922 3.319} {-60.206 6.672 c} {-69.444 2.445 c} {-69.444 2.445}} -tags __path__333 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__334 -priority 10
    $w.zinc add curve __g__334 {{45.84 12.961} {45.84 12.961 c} {44.91 13.605 c} {45.124 12.424} {45.339 11.243 c} {73.547 -1.927 c} {77.161 -1.677} {77.161 -1.677 c} {46.913 11.529 c} {45.84 12.961}} -tags __path__335 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__336 -priority 10
    $w.zinc add curve __g__336 {{42.446 13.6} {42.446 13.6 c} {41.57 14.315 c} {41.691 13.121} {41.812 11.927 c} {68.899 -3.418 c} {72.521 -3.452} {72.521 -3.452 c} {43.404 12.089 c} {42.446 13.6}} -tags __path__337 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__338 -priority 10
    $w.zinc add curve __g__338 {{39.16 14.975} {39.16 14.975 c} {38.332 15.747 c} {38.374 14.547} {38.416 13.348 c} {58.233 -2.149 c} {68.045 -4.023} {68.045 -4.023 c} {50.015 4.104 c} {39.16 14.975}} -tags __path__339 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__340 -priority 10
    $w.zinc add curve __g__340 {{36.284 16.838} {36.284 16.838 c} {35.539 17.532 c} {35.577 16.453} {35.615 15.373 c} {53.449 1.426 c} {62.28 -0.26} {62.28 -0.26 c} {46.054 7.054 c} {36.284 16.838}} -tags __path__341 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__342 -priority 10
    $w.zinc add curve __g__342 {{4.6 164.801} {4.6 164.801 c} {-10.6 162.401 c} {6.2 160.801} {6.2 160.801 c} {24.2 158.801 c} {28.2 153.601} {28.2 153.601 c} {41.8 144.401 c} {44.6 144.001} {47.4 143.601 c} {63.8 140.001 c} {64.2 137.601} {64.6 135.201 c} {70.6 132.801 c} {72.2 133.601} {73.8 134.401 c} {73.8 143.601 c} {71 144.401} {68.2 145.201 c} {49.4 152.401 c} {43 153.601} {36.6 154.801 c} {25 162.401 c} {20.2 163.601} {15.4 164.801 c} {4.6 164.801 c} {4.6 164.801}} -tags __path__343 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__344 -priority 10
    $w.zinc add curve __g__344 {{77.6 127.401} {77.6 127.401 c} {74.6 129.001 c} {73.4 131.601} {73.4 131.601 c} {67 142.201 c} {52.8 145.401} {52.8 145.401 c} {29.8 154.401 c} {22 156.401} {22 156.401 c} {8.6 161.401 c} {1.2 160.601} {1.2 160.601 c} {-5.8 160.801 c} {0.4 162.401} {0.4 162.401 c} {20.6 160.401 c} {24 158.601} {24 158.601 c} {39.6 153.401 c} {42.6 150.801} {45.6 148.201 c} {63.8 143.201 c} {66 141.201} {68.2 139.201 c} {78 130.801 c} {77.6 127.401}} -tags __path__345 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__346 -priority 10
    $w.zinc add curve __g__346 {{18.882 158.911} {18.882 158.911 c} {24.111 158.685 c} {22.958 160.234} {21.805 161.784 c} {19.357 160.91 c} {19.357 160.91} {18.882 158.911}} -tags __path__347 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__348 -priority 10
    $w.zinc add curve __g__348 {{11.68 160.263} {11.68 160.263 c} {16.908 160.037 c} {15.756 161.586} {14.603 163.136 c} {12.155 162.263 c} {12.155 162.263} {11.68 160.263}} -tags __path__349 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__350 -priority 10
    $w.zinc add curve __g__350 {{1.251 161.511} {1.251 161.511 c} {6.48 161.284 c} {5.327 162.834} {4.174 164.383 c} {1.726 163.51 c} {1.726 163.51} {1.251 161.511}} -tags __path__351 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__352 -priority 10
    $w.zinc add curve __g__352 {{-6.383 162.055} {-6.383 162.055 c} {-1.154 161.829 c} {-2.307 163.378} {-3.46 164.928 c} {-5.908 164.054 c} {-5.908 164.054} {-6.383 162.055}} -tags __path__353 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__354 -priority 10
    $w.zinc add curve __g__354 {{35.415 151.513} {35.415 151.513 c} {42.375 151.212 c} {40.84 153.274} {39.306 155.336 c} {36.047 154.174 c} {36.047 154.174} {35.415 151.513}} -tags __path__355 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__356 -priority 10
    $w.zinc add curve __g__356 {{45.73 147.088} {45.73 147.088 c} {51.689 143.787 c} {51.155 148.849} {50.885 151.405 c} {46.362 149.749 c} {46.362 149.749} {45.73 147.088}} -tags __path__357 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__358 -priority 10
    $w.zinc add curve __g__358 {{54.862 144.274} {54.862 144.274 c} {62.021 140.573 c} {60.287 146.035} {59.509 148.485 c} {55.493 146.935 c} {55.493 146.935} {54.862 144.274}} -tags __path__359 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__360 -priority 10
    $w.zinc add curve __g__360 {{64.376 139.449} {64.376 139.449 c} {68.735 134.548 c} {69.801 141.21} {70.207 143.748 c} {65.008 142.11 c} {65.008 142.11} {64.376 139.449}} -tags __path__361 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__362 -priority 10
    $w.zinc add curve __g__362 {{26.834 155.997} {26.834 155.997 c} {32.062 155.77 c} {30.91 157.32} {29.757 158.869 c} {27.308 157.996 c} {27.308 157.996} {26.834 155.997}} -tags __path__363 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__364 -priority 10
    $w.zinc add curve __g__364 {{62.434 34.603} {62.434 34.603 c} {61.708 35.268 c} {61.707 34.197} {61.707 33.127 c} {79.191 19.863 c} {88.034 18.479} {88.034 18.479 c} {71.935 25.208 c} {62.434 34.603}} -tags __path__365 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__366 -priority 10
    $w.zinc add curve __g__366 {{65.4 98.4} {65.4 98.4 c} {87.401 120.801 c} {96.601 124.401} {96.601 124.401 c} {105.801 135.601 c} {101.801 161.601} {101.801 161.601 c} {98.601 169.201 c} {95.401 148.401} {95.401 148.401 c} {98.601 123.201 c} {87.401 139.201} {87.401 139.201 c} {79 129.301 c} {85.4 129.601} {85.4 129.601 c} {88.601 131.601 c} {89.001 130.001} {89.401 128.401 c} {81.4 114.801 c} {64.2 100.4} {47 86 c} {65.4 98.4 c} {65.4 98.4}} -tags __path__367 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__368 -priority 10
    $w.zinc add curve __g__368 {{7 137.201} {7 137.201 c} {6.8 135.401 c} {8.6 136.201} {10.4 137.001 c} {104.601 143.201 c} {136.201 167.201} {136.201 167.201 c} {91.001 144.001 c} {7 137.201}} -tags __path__369 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__370 -priority 10
    $w.zinc add curve __g__370 {{17.4 132.801} {17.4 132.801 c} {17.2 131.001 c} {19 131.801} {20.8 132.601 c} {157.401 131.601 c} {181.001 164.001} {181.001 164.001 c} {159.001 138.801 c} {17.4 132.801}} -tags __path__371 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__372 -priority 10
    $w.zinc add curve __g__372 {{29 128.801} {29 128.801 c} {28.8 127.001 c} {30.6 127.801} {32.4 128.601 c} {205.801 115.601 c} {229.401 148.001} {229.401 148.001 c} {219.801 122.401 c} {29 128.801}} -tags __path__373 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__374 -priority 10
    $w.zinc add curve __g__374 {{39 124.001} {39 124.001 c} {38.8 122.201 c} {40.6 123.001} {42.4 123.801 c} {164.601 85.2 c} {188.201 117.601} {188.201 117.601 c} {174.801 93 c} {39 124.001}} -tags __path__375 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__376 -priority 10
    $w.zinc add curve __g__376 {{-19 146.801} {-19 146.801 c} {-19.2 145.001 c} {-17.4 145.801} {-15.6 146.601 c} {2.2 148.801 c} {4.2 187.601} {4.2 187.601 c} {-3 145.601 c} {-19 146.801}} -tags __path__377 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__378 -priority 10
    $w.zinc add curve __g__378 {{-27.8 148.401} {-27.8 148.401 c} {-28 146.601 c} {-26.2 147.401} {-24.4 148.201 c} {-10.2 143.601 c} {-13 182.401} {-13 182.401 c} {-11.8 147.201 c} {-27.8 148.401}} -tags __path__379 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__380 -priority 10
    $w.zinc add curve __g__380 {{-35.8 148.801} {-35.8 148.801 c} {-36 147.001 c} {-34.2 147.801} {-32.4 148.601 c} {-17 149.201 c} {-29.4 171.601} {-29.4 171.601 c} {-19.8 147.601 c} {-35.8 148.801}} -tags __path__381 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__382 -priority 10
    $w.zinc add curve __g__382 {{11.526 104.465} {11.526 104.465 c} {11.082 106.464 c} {12.631 105.247} {28.699 92.622 c} {61.141 33.72 c} {116.826 28.086} {116.826 28.086 c} {78.518 15.976 c} {11.526 104.465}} -tags __path__383 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__384 -priority 10
    $w.zinc add curve __g__384 {{22.726 102.665} {22.726 102.665 c} {21.363 101.472 c} {23.231 100.847} {25.099 100.222 c} {137.541 27.72 c} {176.826 35.686} {176.826 35.686 c} {149.719 28.176 c} {22.726 102.665}} -tags __path__385 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__386 -priority 10
    $w.zinc add curve __g__386 {{1.885 108.767} {1.885 108.767 c} {1.376 110.366 c} {3.087 109.39} {12.062 104.27 c} {15.677 47.059 c} {59.254 45.804} {59.254 45.804 c} {26.843 31.09 c} {1.885 108.767}} -tags __path__387 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__388 -priority 10
    $w.zinc add curve __g__388 {{-18.038 119.793} {-18.038 119.793 c} {-19.115 121.079 c} {-17.162 120.825} {-6.916 119.493 c} {14.489 78.222 c} {58.928 83.301} {58.928 83.301 c} {26.962 68.955 c} {-18.038 119.793}} -tags __path__389 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__390 -priority 10
    $w.zinc add curve __g__390 {{-6.8 113.667} {-6.8 113.667 c} {-7.611 115.136 c} {-5.742 114.511} {4.057 111.237 c} {17.141 66.625 c} {61.729 63.078} {61.729 63.078 c} {27.603 55.135 c} {-6.8 113.667}} -tags __path__391 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__392 -priority 10
    $w.zinc add curve __g__392 {{-25.078 124.912} {-25.078 124.912 c} {-25.951 125.954 c} {-24.369 125.748} {-16.07 124.669 c} {1.268 91.24 c} {37.264 95.354} {37.264 95.354 c} {11.371 83.734 c} {-25.078 124.912}} -tags __path__393 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__394 -priority 10
    $w.zinc add curve __g__394 {{-32.677 130.821} {-32.677 130.821 c} {-33.682 131.866 c} {-32.091 131.748} {-27.923 131.439 c} {2.715 98.36 c} {21.183 113.862} {21.183 113.862 c} {9.168 95.139 c} {-32.677 130.821}} -tags __path__395 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__396 -priority 10
    $w.zinc add curve __g__396 {{36.855 98.898} {36.855 98.898 c} {35.654 97.543 c} {37.586 97.158} {39.518 96.774 c} {160.221 39.061 c} {198.184 51.927} {198.184 51.927 c} {172.243 41.053 c} {36.855 98.898}} -tags __path__397 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__398 -priority 10
    $w.zinc add curve __g__398 {{3.4 163.201} {3.4 163.201 c} {3.2 161.401 c} {5 162.201} {6.8 163.001 c} {22.2 163.601 c} {9.8 186.001} {9.8 186.001 c} {19.4 162.001 c} {3.4 163.201}} -tags __path__399 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__400 -priority 10
    $w.zinc add curve __g__400 {{13.8 161.601} {13.8 161.601 c} {13.6 159.801 c} {15.4 160.601} {17.2 161.401 c} {35 163.601 c} {37 202.401} {37 202.401 c} {29.8 160.401 c} {13.8 161.601}} -tags __path__401 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__402 -priority 10
    $w.zinc add curve __g__402 {{20.6 160.001} {20.6 160.001 c} {20.4 158.201 c} {22.2 159.001} {24 159.801 c} {48.6 163.201 c} {72.2 195.601} {72.2 195.601 c} {36.6 158.801 c} {20.6 160.001}} -tags __path__403 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__404 -priority 10
    $w.zinc add curve __g__404 {{28.225 157.972} {28.225 157.972 c} {27.788 156.214 c} {29.678 156.768} {31.568 157.322 c} {52.002 155.423 c} {90.099 189.599} {90.099 189.599 c} {43.924 154.656 c} {28.225 157.972}} -tags __path__405 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__406 -priority 10
    $w.zinc add curve __g__406 {{38.625 153.572} {38.625 153.572 c} {38.188 151.814 c} {40.078 152.368} {41.968 152.922 c} {76.802 157.423 c} {128.499 192.399} {128.499 192.399 c} {54.324 150.256 c} {38.625 153.572}} -tags __path__407 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__408 -priority 10
    $w.zinc add curve __g__408 {{-1.8 142.001} {-1.8 142.001 c} {-2 140.201 c} {-0.2 141.001} {1.6 141.801 c} {55 144.401 c} {85.4 171.201} {85.4 171.201 c} {50.499 146.426 c} {-1.8 142.001}} -tags __path__409 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__410 -priority 10
    $w.zinc add curve __g__410 {{-11.8 146.001} {-11.8 146.001 c} {-12 144.201 c} {-10.2 145.001} {-8.4 145.801 c} {16.2 149.201 c} {39.8 181.601} {39.8 181.601 c} {4.2 144.801 c} {-11.8 146.001}} -tags __path__411 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__412 -priority 10
    $w.zinc add curve __g__412 {{49.503 148.962} {49.503 148.962 c} {48.938 147.241 c} {50.864 147.655} {52.79 148.068 c} {87.86 150.004 c} {141.981 181.098} {141.981 181.098 c} {64.317 146.704 c} {49.503 148.962}} -tags __path__413 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__414 -priority 10
    $w.zinc add curve __g__414 {{57.903 146.562} {57.903 146.562 c} {57.338 144.841 c} {59.264 145.255} {61.19 145.668 c} {96.26 147.604 c} {150.381 178.698} {150.381 178.698 c} {73.317 143.904 c} {57.903 146.562}} -tags __path__415 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__416 -priority 10
    $w.zinc add curve __g__416 {{67.503 141.562} {67.503 141.562 c} {66.938 139.841 c} {68.864 140.255} {70.79 140.668 c} {113.86 145.004 c} {203.582 179.298} {203.582 179.298 c} {82.917 138.904 c} {67.503 141.562}} -tags __path__417 -priority 10 -filled 1 -closed 1 -linecolor \#000000 -fillcolor \#ffffff -filled 1 -linewidth 0.1
    $w.zinc add group __svg__1  -tags __g__418 -priority 10
    $w.zinc add curve __g__418 {{-43.8 148.401} {-43.8 148.401 c} {-38.6 148.001 c} {-39.8 149.601} {-41 151.201 c} {-43.4 150.401 c} {-43.4 150.401} {-43.8 148.401}} -tags __path__419 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__420 -priority 10
    $w.zinc add curve __g__420 {{-13 162.401} {-13 162.401 c} {-7.8 162.001 c} {-9 163.601} {-10.2 165.201 c} {-12.6 164.401 c} {-12.6 164.401} {-13 162.401}} -tags __path__421 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__422 -priority 10
    $w.zinc add curve __g__422 {{-21.8 162.001} {-21.8 162.001 c} {-16.6 161.601 c} {-17.8 163.201} {-19 164.801 c} {-21.4 164.001 c} {-21.4 164.001} {-21.8 162.001}} -tags __path__423 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__424 -priority 10
    $w.zinc add curve __g__424 {{-117.169 150.182} {-117.169 150.182 c} {-112.124 151.505 c} {-113.782 152.624} {-115.439 153.744 c} {-117.446 152.202 c} {-117.446 152.202} {-117.169 150.182}} -tags __path__425 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__426 -priority 10
    $w.zinc add curve __g__426 {{-115.169 140.582} {-115.169 140.582 c} {-110.124 141.905 c} {-111.782 143.024} {-113.439 144.144 c} {-115.446 142.602 c} {-115.446 142.602} {-115.169 140.582}} -tags __path__427 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__428 -priority 10
    $w.zinc add curve __g__428 {{-122.369 136.182} {-122.369 136.182 c} {-117.324 137.505 c} {-118.982 138.624} {-120.639 139.744 c} {-122.646 138.202 c} {-122.646 138.202} {-122.369 136.182}} -tags __path__429 -priority 10 -filled 1 -closed 1 -fillcolor \#000000 -filled 1 -linecolor \#000000
    $w.zinc add group __svg__1  -tags __g__430 -priority 10
    $w.zinc add curve __g__430 {{-42.6 211.201} {-42.6 211.201 c} {-44.2 211.201 c} {-48.2 213.201} {-50.2 213.201 c} {-61.4 216.801 c} {-67 226.801} {-67 226.801 c} {-54.6 217.201 c} {-42.6 211.201}} -tags __path__431 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__432 -priority 10
    $w.zinc add curve __g__432 {{45.116 303.847} {45.257 304.105 c} {45.312 304.525 c} {45.604 304.542} {46.262 304.582 c} {47.495 304.883 c} {47.37 304.247} {46.522 299.941 c} {45.648 295.004 c} {41.515 293.197} {40.876 292.918 c} {39.434 293.331 c} {39.36 294.215} {39.233 295.739 c} {39.116 297.088 c} {39.425 298.554} {39.725 299.975 c} {41.883 299.985 c} {42.8 298.601} {43.736 300.273 c} {44.168 302.116 c} {45.116 303.847}} -tags __path__433 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__434 -priority 10
    $w.zinc add curve __g__434 {{34.038 308.581} {34.786 309.994 c} {34.659 311.853 c} {36.074 312.416} {36.814 312.71 c} {38.664 311.735 c} {38.246 310.661} {37.444 308.6 c} {37.056 306.361 c} {35.667 304.55} {35.467 304.288 c} {35.707 303.755 c} {35.547 303.427} {34.953 302.207 c} {33.808 301.472 c} {32.4 301.801} {31.285 304.004 c} {32.433 306.133 c} {33.955 307.842} {34.091 307.994 c} {33.925 308.37 c} {34.038 308.581}} -tags __path__435 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__436 -priority 10
    $w.zinc add curve __g__436 {{-5.564 303.391} {-5.672 303.014 c} {-5.71 302.551 c} {-5.545 302.23} {-5.014 301.197 c} {-4.221 300.075 c} {-4.558 299.053} {-4.906 297.997 c} {-6.022 298.179 c} {-6.672 298.748} {-7.807 299.742 c} {-7.856 301.568 c} {-8.547 302.927} {-8.743 303.313 c} {-8.692 303.886 c} {-9.133 304.277} {-9.607 304.698 c} {-10.047 306.222 c} {-9.951 306.793} {-9.898 307.106 c} {-10.081 317.014 c} {-9.859 316.751} {-9.24 316.018 c} {-6.19 306.284 c} {-6.121 305.392} {-6.064 304.661 c} {-5.332 304.196 c} {-5.564 303.391}} -tags __path__437 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__438 -priority 10
    $w.zinc add curve __g__438 {{-31.202 296.599} {-28.568 294.1 c} {-25.778 291.139 c} {-26.22 287.427} {-26.336 286.451 c} {-28.111 286.978 c} {-28.298 287.824} {-29.1 291.449 c} {-31.139 294.11 c} {-33.707 296.502} {-35.903 298.549 c} {-37.765 304.893 c} {-38 305.401} {-34.303 300.145 c} {-32.046 297.399 c} {-31.202 296.599}} -tags __path__439 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__440 -priority 10
    $w.zinc add curve __g__440 {{-44.776 290.635} {-44.253 290.265 c} {-44.555 289.774 c} {-44.338 289.442} {-43.385 287.984 c} {-42.084 286.738 c} {-42.066 285} {-42.063 284.723 c} {-42.441 284.414 c} {-42.776 284.638} {-43.053 284.822 c} {-43.395 284.952 c} {-43.503 285.082} {-45.533 287.531 c} {-46.933 290.202 c} {-48.376 293.014} {-48.559 293.371 c} {-49.703 297.862 c} {-49.39 297.973} {-49.151 298.058 c} {-47.431 293.877 c} {-47.221 293.763} {-45.958 293.077 c} {-45.946 291.462 c} {-44.776 290.635}} -tags __path__441 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__442 -priority 10
    $w.zinc add curve __g__442 {{-28.043 310.179} {-27.599 309.31 c} {-26.023 308.108 c} {-26.136 307.219} {-26.254 306.291 c} {-25.786 304.848 c} {-26.698 305.536} {-27.955 306.484 c} {-31.404 307.833 c} {-31.674 313.641} {-31.7 314.212 c} {-28.726 311.519 c} {-28.043 310.179}} -tags __path__443 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__444 -priority 10
    $w.zinc add curve __g__444 {{-13.6 293.001} {-13.2 292.333 c} {-12.492 292.806 c} {-12.033 292.543} {-11.385 292.171 c} {-10.774 291.613 c} {-10.482 290.964} {-9.512 288.815 c} {-7.743 286.995 c} {-7.6 284.601} {-9.091 283.196 c} {-9.77 285.236 c} {-10.4 286.201} {-11.723 284.554 c} {-12.722 286.428 c} {-14.022 286.947} {-14.092 286.975 c} {-14.305 286.628 c} {-14.38 286.655} {-15.557 287.095 c} {-16.237 288.176 c} {-17.235 288.957} {-17.406 289.091 c} {-17.811 288.911 c} {-17.958 289.047} {-18.61 289.65 c} {-19.583 289.975 c} {-19.863 290.657} {-20.973 293.364 c} {-24.113 295.459 c} {-26 303.001} {-25.619 303.91 c} {-21.488 296.359 c} {-21.001 295.661} {-20.165 294.465 c} {-20.047 297.322 c} {-18.771 296.656} {-18.72 296.629 c} {-18.534 296.867 c} {-18.4 297.001} {-18.206 296.721 c} {-17.988 296.492 c} {-17.6 296.601} {-17.6 296.201 c} {-17.734 295.645 c} {-17.533 295.486} {-16.296 294.509 c} {-16.38 293.441 c} {-15.6 292.201} {-15.142 292.99 c} {-14.081 292.271 c} {-13.6 293.001}} -tags __path__445 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__446 -priority 10
    $w.zinc add curve __g__446 {{46.2 347.401} {46.2 347.401 c} {53.6 327.001 c} {49.2 315.801} {49.2 315.801 c} {60.6 337.401 c} {56 348.601} {56 348.601 c} {55.6 338.201 c} {51.6 333.201} {51.6 333.201 c} {47.6 346.001 c} {46.2 347.401}} -tags __path__447 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__448 -priority 10
    $w.zinc add curve __g__448 {{31.4 344.801} {31.4 344.801 c} {36.8 336.001 c} {28.8 317.601} {28.8 317.601 c} {28 338.001 c} {21.2 349.001} {21.2 349.001 c} {35.4 328.801 c} {31.4 344.801}} -tags __path__449 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__450 -priority 10
    $w.zinc add curve __g__450 {{21.4 342.801} {21.4 342.801 c} {21.2 322.801 c} {21.6 319.801} {21.6 319.801 c} {17.8 336.401 c} {7.6 346.001} {7.6 346.001 c} {22 334.001 c} {21.4 342.801}} -tags __path__451 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__452 -priority 10
    $w.zinc add curve __g__452 {{11.8 310.801} {11.8 310.801 c} {17.8 324.401 c} {7.8 342.801} {7.8 342.801 c} {14.2 330.601 c} {9.4 323.601} {9.4 323.601 c} {12 320.201 c} {11.8 310.801}} -tags __path__453 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__454 -priority 10
    $w.zinc add curve __g__454 {{-7.4 342.401} {-7.4 342.401 c} {-8.4 326.801 c} {-6.6 324.601} {-6.6 324.601 c} {-6.4 318.201 c} {-6.8 317.201} {-6.8 317.201 c} {-2.8 311.001 c} {-2.6 318.401} {-2.6 318.401 c} {-1.2 326.201 c} {1.6 330.801} {1.6 330.801 c} {5.2 336.201 c} {5 342.601} {5 342.601 c} {-5 312.401 c} {-7.4 342.401}} -tags __path__455 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__456 -priority 10
    $w.zinc add curve __g__456 {{-11 314.801} {-11 314.801 c} {-17.6 325.601 c} {-19.4 344.601} {-19.4 344.601 c} {-20.8 338.401 c} {-17 324.001} {-17 324.001 c} {-12.8 308.601 c} {-11 314.801}} -tags __path__457 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__458 -priority 10
    $w.zinc add curve __g__458 {{-32.8 334.601} {-32.8 334.601 c} {-27.8 329.201 c} {-26.4 324.201} {-26.4 324.201 c} {-22.8 308.401 c} {-29.2 317.001} {-29.2 317.001 c} {-29 325.001 c} {-37.2 332.401} {-37.2 332.401 c} {-32.4 330.001 c} {-32.8 334.601}} -tags __path__459 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__460 -priority 10
    $w.zinc add curve __g__460 {{-38.6 329.601} {-38.6 329.601 c} {-35.2 312.201 c} {-34.4 311.401} {-34.4 311.401 c} {-32.6 308.001 c} {-35.4 311.201} {-35.4 311.201 c} {-44.2 330.401 c} {-48.2 337.001} {-48.2 337.001 c} {-40.2 327.801 c} {-38.6 329.601}} -tags __path__461 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__462 -priority 10
    $w.zinc add curve __g__462 {{-44.4 313.001} {-44.4 313.001 c} {-32.8 290.601 c} {-54.6 316.401} {-54.6 316.401 c} {-43.6 306.601 c} {-44.4 313.001}} -tags __path__463 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__464 -priority 10
    $w.zinc add curve __g__464 {{-59.8 298.401} {-59.8 298.401 c} {-55 279.601 c} {-52.4 279.801} {-52.4 279.801 c} {-44.2 270.801 c} {-50.8 281.401} {-50.8 281.401 c} {-56.8 291.001 c} {-56.2 300.801} {-56.2 300.801 c} {-56.8 291.201 c} {-59.8 298.401}} -tags __path__465 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__466 -priority 10
    $w.zinc add curve __g__466 {{270.5 287} {270.5 287 c} {258.5 277 c} {256 273.5} {256 273.5 c} {269.5 292 c} {269.5 299} {269.5 299 c} {272 291.5 c} {270.5 287}} -tags __path__467 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__468 -priority 10
    $w.zinc add curve __g__468 {{276 265} {276 265 c} {255 250 c} {251.5 242.5} {251.5 242.5 c} {278 272 c} {278 276.5} {278 276.5 c} {278.5 267.5 c} {276 265}} -tags __path__469 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__470 -priority 10
    $w.zinc add curve __g__470 {{293 111} {293 111 c} {281 103 c} {279.5 105} {279.5 105 c} {290 111.5 c} {292.5 120} {292.5 120 c} {291 111 c} {293 111}} -tags __path__471 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc
    $w.zinc add group __svg__1  -tags __g__472 -priority 10
    $w.zinc add curve __g__472 {{301.5 191.5} {284 179.5} {284 179.5 c} {303 196.5 c} {303.5 200.5} {301.5 191.5}} -tags __path__473 -priority 10 -filled 1 -closed 1 -fillcolor \#cccccc -filled 1 -linecolor \#cccccc

    ### translating ojects for making them all visibles

    $w.zinc translate $topGroup 200 150

    ##### bindings for moving rotating scaling the items

    bind $w.zinc <ButtonPress-1>  "::tigerDemo::press motion %x %y"
    bind $w.zinc <ButtonRelease-1>  ::tigerDemo::release
    bind $w.zinc <ButtonPress-2>  "::tigerDemo::press zoom %x %y"
    bind $w.zinc <ButtonRelease-2>  ::tigerDemo::release
    bind $w.zinc <ButtonPress-3>  "::tigerDemo::press mouseRotate %x %y"
    bind $w.zinc <ButtonRelease-3>  ::tigerDemo::release


    variable curX 0
    variable curY 0
    variable curAngle 0

    proc press {action x y} {
	variable w
	variable curAngle
	variable curX
	variable curY

	set curX $x
	set curY $y
	set curAngle [expr atan2($y, $x)]
	bind $w.zinc <Motion> "::tigerDemo::$action %x %y"
    }

    proc motion {x y} {
	variable w
	variable topGroup
	variable curX
	variable curY

	foreach {x1 y1 x2 y2} [$w.zinc transform $topGroup \
				   [list $x $y $curX $curY]] break
	$w.zinc translate $topGroup [expr $x1 - $x2] [expr $y1 - $y2]
	set curX $x
	set curY $y
    }

    proc zoom {x y} {
	variable w
	variable curX
	variable curY

	if {$x > $curX} {
	    set maxX $x
	} else {
	    set maxX $curX
	}
	if {$y > $curY} {
	    set maxY $y
	} else {
	    set maxY $curY
	}
	if {($maxX == 0) || ($maxY == 0)} {
	    return;
	}
	set sx [expr 1.0 + (double($x - $curX) / $maxX)]
	set sy [expr 1.0 + (double($y - $curY) / $maxY)]
	$w.zinc scale __svg__1 $sx $sx
	set curX $x
	set curY $y
    }

    proc mouseRotate {x y} {
	variable w
	variable curAngle

	set lAngle [expr atan2($y, $x)]
	$w.zinc rotate __svg__1 [expr $lAngle - $curAngle]
	set curAngle  $lAngle
    }

    proc release {} {
	variable w

	bind $w.zinc <Motion> {}
    }
}

Added jni/tkzinc/demos/tkZincLogo.tcl.











































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#
# $Id$
# this simple demo has been adapted by C. Mertz <mertz@cena.fr> from the original
# work of JL. Vinot <vinot@cena.fr>
# Ported to Tcl by P.Lecoanet

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval tkZincLogo {
    #
    # We need the zincLogo support
    package require zincLogo

    variable w .tkZincLogo
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc logo Demonstration"
    wm iconname $w tkZincLogo

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################

    grid [text $w.text -relief sunken -borderwidth 2 -height 7 \
              -font TkDefaultFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert end {This tkZinc logo should used openGL for a correct rendering!
You can transform this logo with your mouse:
Drag-Button 1 for moving the logo,
Drag-Button 2 for zooming the logo,
Drag-Button 3 for rotating the logo,
Shift-Drag-Button 1 for modifying the logo transparency,
Shift-Drag-Button 2 for modifying the logo gradient.}
    $w.text configure -state disabled

    ###########################################
    # Zinc
    ##########################################
    grid [ zinc $w.zinc -width 350 -height 250 -render 1 \
	-borderwidth 3 -relief sunken] -row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    variable topGroup [$w.zinc add group 1]

    variable logo [zincLogo::create $w.zinc $topGroup 800 40 70 0.6 0.6]

    #
    # Controls for the window transform.
    #
    bind $w.zinc <ButtonPress-1>  "::tkZincLogo::press motion %x %y"
    bind $w.zinc <ButtonRelease-1>  ::tkZincLogo::release
    bind $w.zinc <ButtonPress-2>  "::tkZincLogo::press zoom %x %y"
    bind $w.zinc <ButtonRelease-2>  ::tkZincLogo::release
    bind $w.zinc <ButtonPress-3> "::tkZincLogo::press mouseRotate %x %y"
    bind $w.zinc <ButtonRelease-3> ::tkZincLogo::release

    #
    # Controls for alpha and gradient
    #
    bind $w.zinc <Shift-ButtonPress-1> "::tkZincLogo::press modifyAlpha %x %y"
    bind $w.zinc <Shift-ButtonRelease-1> ::tkZincLogo::release
    bind $w.zinc <Shift-ButtonPress-2> "::tkZincLogo::press modifyGradient %x %y"
    bind $w.zinc <Shift-ButtonRelease-2> ::tkZincLogo::release

    variable curX 0
    variable curY 0
    variable curAngle 0

    proc press {action x y} {
	variable w
	variable curAngle
	variable curX
	variable curY

	set curX $x
	set curY $y
	set curAngle [expr atan2($y, $x)]
	bind $w.zinc <Motion> "::tkZincLogo::$action %x %y"
    }

    proc motion {x y} {
	variable w
	variable topGroup
	variable curX
	variable curY

	foreach {x1 y1 x2 y2} [$w.zinc transform $topGroup \
				   [list $x $y $curX $curY]] break
	$w.zinc translate $topGroup [expr $x1 - $x2] [expr $y1 - $y2]
	set curX $x
	set curY $y
    }

    proc zoom {x y} {
	variable w
	variable topGroup
	variable curX
	variable curY

	if {$x > $curX} {
	    set maxX $x
	} else {
	    set maxX $curX
	}
	if {$y > $curY} {
	    set maxY $y
	} else {
	    set maxY $curY
	}
	if {($maxX == 0) || ($maxY == 0)} {
	    return;
	}
	set sx [expr 1.0 + (double($x - $curX) / $maxX)]
	set sy [expr 1.0 + (double($y - $curY) / $maxY)]
	$w.zinc scale $topGroup $sx $sx

	set curX $x
	set curY $y
    }

    proc mouseRotate {x y} {
	variable w
	variable curAngle
	variable logo

	set lAngle [expr atan2($y, $x)]
	$w.zinc rotate $logo [expr $lAngle - $curAngle]
	set curAngle  $lAngle
    }

    proc release {} {
	variable w

	bind $w.zinc <Motion> {}
    }

    proc modifyAlpha {x y} {
	variable w
	variable topGroup

	set xRate [expr double($x) / [$w.zinc cget -width]]
	set xRate [expr ($xRate < 0) ? 0 : ($xRate > 1) ? 1 : $xRate]
	set alpha [expr int($xRate * 100)]

	$w.zinc itemconfigure $topGroup -alpha $alpha
    }

    proc modifyGradient {x y} {
	variable w

	set yRate [expr double($y) / [$w.zinc cget -height]]
	set yRate [expr ($yRate < 0) ? 0 : ($yRate > 1) ? 1 : $yRate]
	set gradPercent [expr int($yRate * 100)]

	$w.zinc itemconfigure letters -fillcolor "=axial 270|#ffffff;100 0 28|#66848c;100 $gradPercent|#7192aa;100 100"
    }
}

Added jni/tkzinc/demos/transforms.tcl.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
# $Id$
# This simple demo has been developped by P. Lecoanet <lecoanet@cena.fr>

#
# TODO:
#
# Add the building of missing items
#

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval transforms {
    variable w .transforms
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Transformation Demonstration"
    wm iconname $w Transformation

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 3 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 3 -column 1 -pady 10

    ###########################################
    # Text zone
    ###########################################
    grid [text $w.text -relief sunken -borderwidth 2 -setgrid true \
              -height 12 -font TkSmallCaptionFont] \
	-row 0 -column 0 -columnspan 2 -sticky ew

    $w.text insert 0.0 {Items are always added to the current group.
The available commands are:
    Button 1         on the background, add an item with initial translation
    Button 2         on the background, add a group with initial translation
    Button 1         on item/group axes, select/deselect that item coordinates
    Drag Button 1    on item/group axes, translate that item coordinates
    Home             reset the transformation
    Shift-Home       reset a group direct children transformations
    +/-              scale the selected item up/down
    Ctrl-Left/Right  rotate the selected item right/left
    Shift-Up/Down    swap the selected item Y axis
    Shift-Left/Right swap the selected item X axis
    4 arrows         translate in the 4 directions
    Delete           destroy the selected item}
    $w.text configure -state disabled

    ###########################################
    # Zinc
    ###########################################
    variable zincWidth 600
    variable zincHeight 500

    grid [zinc $w.zinc -width $zincWidth -height $zincHeight \
	-font $defaultfont -borderwidth 3 -relief sunken -takefocus 1 -render 0] \
	-row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    variable top 1

    variable inactiveAxisColor blue
    variable activeAxisColor red
    variable worldAxisColor \#a5a5a5

    variable composeRot 1
    variable composeScale 1
    variable drag 0
    variable itemType Rectangle
    variable currentItem 0

    image create photo logo -file [file join $::zinc_demos images zinc.gif]

    grid [frame $w.f] -row 2 -column 0 -columnspan 2 -sticky w

    tk_optionMenu $w.f.types itemType Rectangle Arc Curve Icon Tabular \
	Text Track Triangles WayPoint
    grid $w.f.types -row 0 -column 1 -sticky w

    ttk::button $w.f.add -text {Add item} -command "::transforms::addItem $w.zinc"
    grid $w.f.add -row 0 -column 2 -padx 10 -sticky ew

    ttk::button $w.f.addg -text {Add group} -command "::transforms::addGroup $w.zinc"
    grid $w.f.addg -row 0 -column 3 -padx 10 -sticky ew

    ttk::button $w.f.remove -text Remove -command "::transforms::removeItem $w.zinc"
    grid $w.f.remove -row 0 -column 4 -padx 10 -sticky ew

    ttk::checkbutton $w.f.cscale -text -composescale -command "::transforms::toggleComposeScale $w.zinc" \
	-variable ::transforms::composeScale
    grid $w.f.cscale -row 0 -column 6 -sticky w

    ttk::checkbutton $w.f.crot -text -composesrotation -command "::transforms::toggleComposeRot $w.zinc" \
	-variable ::transforms::composeRot
    grid $w.f.crot -row 1 -column 6 -sticky w

    variable world [$w.zinc add group $top]
    variable currentGroup $world
    $w.zinc add curve $top {0 0 80 0} -linewidth 3 \
	-linecolor $worldAxisColor -lastend {6 8 3} -tags axis:$world
    $w.zinc add curve $top {0 0 0 80} -linewidth 3 \
	-linecolor $worldAxisColor -lastend {6 8 3} -tags axis:$world
    $w.zinc add rectangle $top {-2 -2 2 2} -filled 1 \
	-fillcolor $worldAxisColor -linecolor $worldAxisColor \
	-linewidth 3 -tags axis:$world
    $w.zinc add text $top -text "This is the origin\nof the world" \
	-anchor s -color $worldAxisColor -alignment center \
	-tags [list "axis:$world" text]
    $w.zinc lower axis:$world

    bind $w.zinc <1> {::transforms::mouseAdd %W Item %x %y}
    bind $w.zinc <2> {::transforms::mouseAdd %W Group %x %y}
    bind $w.zinc <Up> {::transforms::moveUp %W}
    bind $w.zinc <Left> {::transforms::moveLeft %W}
    bind $w.zinc <Right> {::transforms::moveRight %W}
    bind $w.zinc <Down> {::transforms::moveDown %W}
    bind $w.zinc <minus> {::transforms::scaleDown %W}
    bind $w.zinc <KP_Subtract> {::transforms::scaleDown %W}
    bind $w.zinc <plus> {::transforms::scaleUp %W}
    bind $w.zinc <KP_Add> {::transforms::scaleUp %W}
    bind $w.zinc <Home> {::transforms::reset %W}
    bind $w.zinc <Shift-Home> {::transforms::resetChildren %W}
    bind $w.zinc <Control-Left> {::transforms::rotateLeft %W}
    bind $w.zinc <Control-Right> {::transforms::rotateRight %W}
    bind $w.zinc <Shift-Up> {::transforms::swapAxis %W y}
    bind $w.zinc <Shift-Down> {::transforms::swapAxis %W y}
    bind $w.zinc <Shift-Left> {::transforms::swapAxis %W x}
    bind $w.zinc <Shift-Right> {::transforms::swapAxis %W x}
    bind $w.zinc <Delete> {::transforms::removeItem %W}

    bind $w.zinc <Configure> {::transforms::resize %W %w %h}

    focus $w.zinc
    tk_focusFollowsMouse

    proc resize {z width height} {
	variable world

	set x [expr $width/2]
	set y [expr $height/2]

	$z treset $world
	$z treset axis:$world
	$z translate $world $x $y
	$z translate axis:$world $x $y
    }

    proc swapAxis {z axis} {
	variable currentItem

	set sx 1
	set sy 1
	if { $axis eq "x" } {
	    set sx -1
	} elseif { $axis eq "y" } {
	    set sy -1
	}
	if {$currentItem != 0} {
	    $z scale $currentItem $sx $sy
	    $z scale axisgrp:$currentItem $sx $sy
	}
    }

    proc toggleComposeRot {z} {
	variable currentItem
	variable composeRot

	if {$currentItem != 0} {
	    $z itemconfigure $currentItem -composerotation $composeRot
	    $z itemconfigure axisgrp:$currentItem -composerotation $composeRot
	}
    }

    proc toggleComposeScale {z} {
	variable currentItem
	variable composeScale

	if {$currentItem != 0} {
	    $z itemconfigure $currentItem -composescale $composeScale
	    $z itemconfigure axisgrp:$currentItem -composescale $composeScale
	}
    }

    proc removeItem {z} {
	variable currentGroup
	variable currentItem
	variable world

	if {$currentItem != 0} {
	    $z remove $currentItem axisgrp:$currentItem
	    if {$currentItem == $currentGroup} {
		set currentGroup $world
	    }
	    set currentItem 0
	    set composeScale 1
	    set composeRot 1
	}
    }

    proc dragItem {z x y} {
	variable drag
	variable currentItem

	set drag 1
	if {$currentItem == 0} {
	    return
	}

	set group [$z group $currentItem]
	foreach {x y} [$z transform $group [list $x $y]] break

	$z treset $currentItem
	$z treset axisgrp:$currentItem
	$z translate $currentItem $x $y
	$z translate axisgrp:$currentItem $x $y
    }

    proc select {z} {
	foreach t [$z gettags current] {
	    if {[regexp {^axis:(\d+)} $t m item]} {
		changeItem $z $item
	    }
	}
    }

    proc changeItem {z item} {
	variable currentItem
	variable currentGroup
	variable composeRot
	variable composeScale
	variable drag
	variable activeAxisColor
	variable inactiveAxisColor

	if {($currentItem != 0) && !$drag} {
	    $z itemconfigure axis:$currentItem&&!text \
		-linecolor $inactiveAxisColor -fillcolor $inactiveAxisColor
	}
	if {($currentItem == 0) || ($item != $currentItem)} {
	    $z itemconfigure axis:$item&&!text \
		-linecolor $activeAxisColor -fillcolor $activeAxisColor -linewidth 3
	    set currentItem $item
	    set composeRot [$z itemcget $currentItem -composerotation]
	    $z itemconfigure axisgrp:$currentItem -composerotation $composeRot
	    set composeScale [$z itemcget $currentItem -composescale]
	    $z itemconfigure axisgrp:$currentItem -composescale $composeScale
	} elseif {!$drag} {
	    set currentItem 0
	    set composeRot 1
	    set composeScale 1
	}
    }

    proc selectGroup {z} {
	foreach t [$z gettags current] {
	    if {[regexp {^axis:(\d+)} $t m item]} {
		changeGroup $z $item
		return
	    }
	}
    }

    proc changeGroup {z grp} {
	variable currentItem
	variable currentGroup
	variable world

	changeItem $z $grp
	if {$currentItem != 0} {
	    set currentGroup $currentItem
	} else {
	    set currentGroup $world
	}
    }

    proc reset {z } {
	variable currentItem

	if {$currentItem != 0} {
	    $z treset $currentItem
	    $z treset axisgrp:$currentItem
	}
    }

    proc resetChildren {z} {
	variable currentItem

	if {($currentItem != 0) && ([$z type $currentItem] == "group")} {
	    $z addtag rt withtag .$currentItem.
	    $z treset rt
	    $z dtag rt rt
	}
    }

    proc moveUp {z} {
	move $z 0 20
    }

    proc moveDown {z} {
	move $z 0 -20
    }

    proc moveRight {z} {
	move $z 20 0
    }

    proc moveLeft {z} {
	move $z -20 0
    }

    proc move {z dx dy} {
	variable currentItem

	if {$currentItem != 0} {
	    $z translate $currentItem $dx $dy
	    $z translate axisgrp:$currentItem $dx $dy
	}
    }

    proc scaleUp {z} {
	scale $z 1.1 1.1
    }

    proc scaleDown {z} {
	scale $z 0.9 0.9
    }

    proc scale {z dx dy} {
	variable currentItem

	if {$currentItem != 0} {
	    $z scale $currentItem $dx $dy
	    $z scale axisgrp:$currentItem $dx $dy
	}
    }

    proc rotateLeft {z} {
	rotate $z [expr -3.14159/18]
    }

    proc rotateRight {z} {
	rotate $z [expr 3.14159/18]
    }

    proc rotate {z angle} {
	variable currentItem

	if {$currentItem != 0} {
	    $z rotate $currentItem $angle
	    $z rotate axisgrp:$currentItem $angle
	}
    }

    proc newRectangle {z} {
	variable currentGroup

	return [$z add rectangle $currentGroup {-15 -15 15 15} \
		    -filled 1 -linewidth 0 -fillcolor tan]
    }

    proc newArc {z} {
	variable currentGroup

	return [$z add arc $currentGroup {-25 -15 25 15} \
		    -filled 1 -linewidth 0 -fillcolor tan]
    }

    proc newCurve {z} {
	variable currentGroup

	return [$z add curve $currentGroup {-15 -15 -15 15 15 15 15 -15} \
		    -filled 1 -linewidth 0 -fillcolor tan]
    }

    proc newText {z} {
	variable currentGroup

	set item [$z add text $currentGroup -anchor s]
	$z itemconfigure $item -text "Item id: $item"
	return $item;
    }

    proc newIcon {z} {
	variable currentGroup

	return [$z add icon $currentGroup -image logo -anchor center]
    }

    proc newTriangles {z} {
	variable currentGroup

	return [$z add triangles $currentGroup \
		    {-25 15 -10 -15 5 15 20 -15 35 15 50 -30} \
		    -colors {tan wheat tan wheat}]
    }

    proc newTrack {z} {
	variable currentGroup

	set labelformat {x80x50+0+0 a0a0^0^0 a0a0^0>1 a0a0>2>1 x30a0>3>1 a0a0^0>2}

	set item [$z add track $currentGroup 6 -labelformat $labelformat \
		      -speedvector {30 -15} -markersize 20]
	$z itemconfigure $item 0 -filled 0 -bordercolor DarkGreen -border contour
	$z itemconfigure $item 1 -filled 1 -backcolor gray60 -text AFR6128
	$z itemconfigure $item 2 -filled 0 -backcolor gray65 -text 390
	$z itemconfigure $item 3 -filled 0 -backcolor gray65 -text /
	$z itemconfigure $item 4 -filled 0 -backcolor gray65 -text 350
	$z itemconfigure $item 5 -filled 0 -backcolor gray65 -text TUR

	return $item;
    }

    proc newWayPoint {z} {
	variable currentGroup

	set labelformat {a0a0+0+0 a0a0>0^1}

	set item [$z add waypoint $currentGroup 2 -labelformat $labelformat]
	$z itemconfigure $item 0 -filled 1 -backcolor DarkGreen -text TUR
	$z itemconfigure $item 1 -text >>>

	return $item;
    }

    proc newTabular {z} {
	variable currentGroup

	set labelformat {f700f600+0+0 f700a0^0^0 f700a0^0>1 \
			     f700a0^0>2 f700a0^0>3 f700a0^0>4 f700a0^0>5}

	set item [$z add tabular $currentGroup 7 -labelformat $labelformat]
	$z itemconfigure $item 0 -filled 1 -border contour \
	    -bordercolor black -backcolor gray60
	$z itemconfigure $item 1 -alignment center -text AFR6128
	$z itemconfigure $item 2 -alignment center -text 390
	$z itemconfigure $item 3 -alignment center -text 370
	$z itemconfigure $item 4 -alignment center -text 350
	$z itemconfigure $item 5 -alignment center -text 330
	$z itemconfigure $item 6 -alignment center -text TUR

	return $item;
    }

    proc addAxes {z item length command inFront} {
	variable currentGroup

	set axesGroup [$z add group $currentGroup -tags axisgrp:$item]
	$z add curve $axesGroup [list 0 0 $length 0] -linewidth 3 \
	    -lastend {6 8 3} -tags axis:$item
	$z add curve $axesGroup [list 0 0 0 $length] -linewidth 3 \
	    -lastend {6 8 3} -tags axis:$item
	$z add rectangle $axesGroup {-3 -3 3 3} -filled 1 \
	    -linewidth 0 -composescale 0 -tags axis:$item
	if {$inFront} {
	    $z raise $item $axesGroup
	}
	$z bind axis:$item <B1-Motion> {::transforms::dragItem %W %x %y}
	$z bind axis:$item <ButtonRelease-1> "::transforms::$command %W; set drag 0"
    }

    proc addItem {z} {
	variable itemType

	set length 25
	set itemOnTop 0

	set item [eval "new$itemType $z"]
	if {($itemType == "Track") || ($itemType == "WayPoint")} {
	    set itemOnTop 1
	}

	addAxes $z $item 25 select $itemOnTop
	changeItem $z $item
    }

    proc addGroup {z} {
	variable currentGroup

	set item [$z add group $currentGroup]

	addAxes $z $item 80 selectGroup 1
	changeGroup $z $item
    }

    proc mouseAdd {z itemOrGroup x y} {
	variable currentGroup
	variable currentItem

	if {[llength [$z find withtag current]] != 0} {
	    return
	}

	foreach {x y} [$z transform $currentGroup [list $x $y]] break

	eval "add$itemOrGroup $z"

	$z translate $currentItem $x $y
	$z translate axisgrp:$currentItem $x $y
    }
}

Added jni/tkzinc/demos/triangles.tcl.





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# these simple samples have been developped by C. Mertz mertz@cena.fr and N. Banoun banoun@cena.fr
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval trianglesDemo {
    variable w .triangles
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Triangles Demonstration"
    wm iconname $w Triangles

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    variable defaultfont {Helvetica -11}

    grid [zinc $w.zinc -width 700 -height 300 -font $defaultfont -render 1 -borderwidth 3 -relief sunken] \
	-row 1 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 1 -weight 2

    # 6 equilateral triangles around a point
    $w.zinc add text 1 -position {40 10} -text "Triangles item without transparency"

    variable x0 200
    variable y0 150
    variable coords [list "$x0 $y0"]
    for {set i 0} {$i<=6} {incr i} {
	set angle [expr $i * 6.28/6]
	lappend coords "[expr $x0 + 100 * cos($angle)] [expr $y0 - 100 * sin ($angle)]"
    }

    set tr1 [$w.zinc add triangles 1 $coords -fan 1 -colors {white yellow red magenta blue cyan green yellow} -visible 1]


    $w.zinc add text 1 -position {370 10} -text "Triangles item with transparency"

    # using the clone method to make a copy and then modify the clone"colors
    set tr2 [$w.zinc clone $tr1]
    $w.zinc translate $tr2 300 0
    $w.zinc itemconfigure $tr2 -colors {white;50 yellow;50 red;50 magenta;50 blue;50 cyan;50 green;50 yellow;50}
}

Added jni/tkzinc/demos/windowContours.tcl.





















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# these simple samples have been developped by C. Mertz mertz@cena.fr in perl
# tcl version by Jean-Paul Imbert imbert@cena.fr

if {![info exists zincDemo]} {
    error "This script should be run from the zinc-widget demo."
}

namespace eval windowContours {
    variable w .windowContours
    catch {destroy $w}
    toplevel $w
    wm title $w "Zinc Contours Demonstration"
    wm iconname $w Contours

    variable defaultfont {Helvetica -11}

    grid [ttk::button $w.dismiss -text Dismiss -command "destroy $w"] -row 2 -column 0 -pady 10
    grid [ttk::button $w.code -text "See Code" -command "showCode $w"] -row 2 -column 1 -pady 10

    # Creating the zinc widget
    grid [zinc $w.zinc -font $defaultfont -width 600 -height 500 \
               -borderwidth 3 -relief sunken] \
        -row 0 -column 0 -columnspan 2 -sticky news
    grid columnconfigure $w 0 -weight 1
    grid columnconfigure $w 1 -weight 1
    grid rowconfigure $w 0 -weight 2

    # The explanation displayed when running this demo
    $w.zinc add text 1 -position {10 10} -text "These windows are simply rectangles holed by 4 smaller\nrectangles. The text appears behind the window glasses.\nYou can drag text or windows"

    # Text in background
    variable backtext [$w.zinc add text 1 -position {50 200} \
			   -text "This text appears\nthrough holes of curves"]

    variable window [$w.zinc add curve 1 {100 100 300 100 300 400 100 400} -closed 1 \
			 -visible 1 -filled 1 -fillcolor grey66]


    variable aGlass [$w.zinc add rectangle 1 {120 120 190 240}]
    $w.zinc contour $window add +1 $aGlass

    $w.zinc translate $aGlass 90 0
    $w.zinc contour $window add +1 $aGlass

    $w.zinc translate $aGlass 0 140
    $w.zinc contour $window add +1 $aGlass

    $w.zinc translate $aGlass -90 0
    $w.zinc contour $window add +1 $aGlass


    # deleting $aGlass which is no more usefull
    $w.zinc remove $aGlass

    # cloning $window
    variable window2 [$w.zinc clone $window]

    # changing its background moving it and scaling it!
    $w.zinc itemconfigure $window2 -fillcolor grey50
    $w.zinc translate $window2 30 50
    $w.zinc scale $window 0.8 0.8

    # adding drag and drop callback to the two windows and backtext
    foreach item "$window $window2 $backtext" {
	# Some bindings for dragging the items
	$w.zinc bind $item <1> "::windowContours::itemStartDrag $item %x %y"
	$w.zinc bind $item <B1-Motion> "::windowContours::itemDrag $item %x %y"
    }

    # callback for starting a drag
    variable xOrig ""
    variable yOrig ""

    proc itemStartDrag {item x y} {
	variable xOrig
	variable yOrig
	set xOrig $x
	set yOrig $y
    }

    # Callback for moving an item
    proc itemDrag {item x y} {
	variable xOrig
	variable yOrig
	variable w
	$w.zinc translate $item [expr $x-$xOrig] [expr $y-$yOrig];
	set xOrig $x;
	set yOrig $y;
    }
}

Added jni/tkzinc/demos/zinc-widget.





































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
#!/bin/sh
# the next line restarts using wish \
    exec wish "$0" "$@"

#
# Locate the zinc top level directory.
#
set ::zinc_demos [file dirname [info script]]
if { [file exist [file join $::zinc_demos .. .. lib Tkzinc pkgIndex.tcl]] } {
  set ::zinc_library [file join $::zinc_demos .. .. lib Tkzinc]
} {
  if { [lindex $::tcl_platform(os) 0] eq "Windows" } {
    #
    # For test purposes on the build site on windows.
    set ::zinc_library [file join $::zinc_demos .. win buildtcl]
  } {
    set ::zinc_library [file join $::zinc_demos ..]
  }
}

#
# And adjust the paths accordingly.
#
lappend auto_path $::zinc_library

package require Tkzinc 3.3
set zincVersion [lindex [zinc] 0]

eval destroy [winfo child .]
wm title . "Zinc Widget Demonstration"
set ::zincDemo	1

menu .menuBar -tearoff 0
.menuBar add cascade -menu .menuBar.file -label File -underline 0
menu .menuBar.file -tearoff 0

.menuBar.file add command -label "About..." -command "aboutBox" \
    -underline 0 -accelerator "<F1>"
.menuBar.file add sep
.menuBar.file add command -label Quit -command exit -underline 0 \
    -accelerator Meta-Q
. configure -menu .menuBar
bind . <F1> aboutBox

frame .statusBar
label .statusBar.lab -text " " -relief sunken -bd 1 -anchor w
label .statusBar.foo -width 8 -relief sunken -bd 1 -anchor w
pack .statusBar.lab -side left -padx 2 -expand yes -fill both
pack .statusBar.foo -side left -padx 2
pack .statusBar -side bottom -fill x -pady 2

frame .textFrame
ttk::scrollbar .s -orient vertical -command {.t yview}
pack .s -in .textFrame -side right -fill y
text .t -yscrollcommand {.s set} -wrap word -width 60 -height 30 \
    -setgrid 1 -highlightthickness 0 -padx 4 -pady 2 -takefocus 0 \
    -font TkDefaultFont
pack .t -in .textFrame -expand y -fill both -padx 1
pack .textFrame -expand yes -fill both

# Create a bunch of tags to use in the text widget, such as those for
# section titles and demo descriptions. Also define the bindings for
# tags.

eval font create titleFont [font configure TkDefaultFont] -weight bold
.t tag configure title -font titleFont

# We put some "space" characters to the left and right of each demo description
# so that the descriptions are highlighted only when the mouse cursor
# is right over them (but not when the cursor is to their left or right)
#
.t tag configure demospace -lmargin1 1c -lmargin2 1c


if {[winfo depth .] == 1} {
    .t tag configure demo -lmargin1 1c -lmargin2 1c -underline 1
    .t tag configure visited -lmargin1 1c -lmargin2 1c \
	-underline 1
    .t tag configure hot -background black -foreground white
} else {
    .t tag configure demo -lmargin1 1c -lmargin2 1c \
	-foreground blue -underline 1
    .t tag configure visited -lmargin1 1c -lmargin2 1c \
	-foreground #303080 -underline 1
    .t tag configure hot -foreground red -underline 1
}
.t tag bind demo <ButtonRelease-1> {
    invoke [.t index {@%x,%y}]
}
set lastLine ""
.t tag bind demo <Enter> {
    set lastLine [.t index {@%x,%y linestart}]
    .t tag add hot "$lastLine +1 chars" "$lastLine lineend -1 chars"
    .t config -cursor hand2
    showStatus [.t index {@%x,%y}]
}
.t tag bind demo <Leave> {
    .t tag remove hot 1.0 end
    .t config -cursor xterm
    .statusBar.lab config -text ""
}
.t tag bind demo <Motion> {
    set newLine [.t index {@%x,%y linestart}]
    if {[string compare $newLine $lastLine] != 0} {
	.t tag remove hot 1.0 end
	set lastLine $newLine

	set tags [.t tag names {@%x,%y}]
	set i [lsearch -glob $tags demo-*]
	if {$i >= 0} {
	    .t tag add hot "$lastLine +1 chars" "$lastLine lineend -1 chars"
	}
    }
    showStatus [.t index {@%x,%y}]
}

# Create the text for the text widget.

.t insert end "Tkzinc Widget Demonstrations $zincVersion\n" title
.t insert end {
This application provides a front end for several short scripts in Tcl/Tk that demonstrate what you can do with the Tkzinc widget. Each of the numbered lines below describes a demonstration; you can click on it to invoke the demonstration. Once the demonstration window appears, you can click the "See Code" button to see the Tcl/Tk code that created the demonstration.
}
.t insert end "\n" {} "Small applications\n" title
.t insert end "1. The famous tiger (better with openGL).\n" {demo demo-tiger}
.t insert end "2. A toy radar display.\n" {demo demo-simpleRadar}
.t insert end "3. ATC electronic strips demo (better with openGL).\n" {demo demo-groupsInAtcStrips}
.t insert end "3. A magic lens simulation (need openGL).\n" {demo demo-magicLens}
.t insert end "4. A demo of the Graphics tcl module (based on curves).\n" {demo demo-testGraphics}

.t insert end "\n" {} "All Items\n" title
.t insert end "1. Examples of all items.\n" {demo demo-items}
.t insert end "2. All items options (and their types).\n" {demo demo-allOptions}
.t insert end "3. Examples of line style and line termination.\n" {demo demo-lines}
.t insert end "4. Curves with multiple contours.\n" {demo demo-contours}
.t insert end "7. Curves with cubic bezier control points.\n" {demo demo-curveBezier}
.t insert end "8. Curves with multiple contours and various fillrule.\n" {demo demo-fillRule}

.t insert end "\n" {} "Groups, Priority, Clipping and PathTags\n" title
.t insert end "1. Groups and Priorities.\n" {demo demo-groupsPriority}
.t insert end "2. Clipping examples (with simple or multiple contours).\n" {demo demo-clipping}
.t insert end "3. Group atomicity.\n" {demo demo-atomicGroups}
.t insert end "4. \"Windows\" with four glasses using curve with multiple contours.\n" {demo demo-windowContours}
.t insert end "5. Pathtags demonstration.\n" {demo demo-pathTags}

.t insert end "\n" {} "Transformation\n" title
.t insert end "1. Transformation testbed.\n" {demo demo-transforms}

.t insert end "\n" {} "Use of open GL\n" title
.t insert end "1. The Tkzinc Logo.\n" {demo demo-tkZincLogo}
.t insert end "2. Applying transformations to an icon.\n" {demo demo-iconTransform}
.t insert end "3. Using the alpha information from an image (Need Img ext.).\n" {demo demo-photoAlpha}
.t insert end "4. Axial color variation on the X axis.\n" {demo demo-colorX}
.t insert end "5. Axial color variation on the Y axis.\n" {demo demo-colorY}
.t insert end "6. Circular color variation.\n" {demo demo-colorCircular}
.t insert end "7. The triangles item.\n" {demo demo-triangles}
.t insert end "8. Relief testbed.\n" {demo demo-reliefs}

.t insert end "\n" {} "ATC oriented features and items\n" title
.t insert end "1. Examples of labelformat.\n" {demo demo-labelformat}
.t insert end "2. Simple interaction on a track.\n" {demo demo-simpleInteractionTrack}
.t insert end "3. Text input in a text item and a track item.\n" {demo demo-textInput}

.t configure -state disabled
focus .s

# positionWindow --
# This procedure is invoked by most of the demos to position a
# new demo window.
#
# Arguments:
# w -		The name of the window to position.

proc positionWindow w {
    wm geometry $w +300+300
}

# showVars --
# Displays the values of one or more variables in a window, and
# updates the display whenever any of the variables changes.
#
# Arguments:
# w -		Name of new window to create for display.
# args -	Any number of names of variables.

proc showVars {w args} {
    catch {destroy $w}
    toplevel $w
    wm title $w "Variable values"
    label $w.title -text "Variable values:" -width 20 -anchor center \
	-font titleFont
    pack $w.title -side top -fill x
    set len 1
    foreach i $args {
	if {[string length $i] > $len} {
	    set len [string length $i]
	}
    }
    foreach i $args {
	frame $w.$i
	label $w.$i.name -text "$i: " -width [expr $len + 2] -anchor w
	label $w.$i.value -textvar $i -anchor w
	pack $w.$i.name -side left
	pack $w.$i.value -side left -expand 1 -fill x
	pack $w.$i -side top -anchor w -fill x
    }
    ttk::button $w.ok -text OK -command "destroy $w" -default active
    bind $w <Return> "tkButtonInvoke $w.ok"
    pack $w.ok -side bottom -pady 2
}


# invoke --
# This procedure is called when the user clicks on a demo description.
# It is responsible for invoking the demonstration.
#
# Arguments:
# index -	The index of the character that the user clicked on.

proc invoke index {
    set tags [.t tag names $index]
    set i [lsearch -glob $tags demo-*]
    if {$i < 0} {
	return
    }
    set cursor [.t cget -cursor]
    .t configure -cursor watch
    update
    set demo [string range [lindex $tags $i] 5 end]
    uplevel [list source [file join $::zinc_demos $demo.tcl]]
    update
    .t configure -cursor $cursor

    .t tag add visited "$index linestart +1 chars" "$index lineend -1 chars"
}

# showStatus --
#
#	Show the name of the demo program in the status bar. This procedure
#	is called when the user moves the cursor over a demo description.
#
proc showStatus index {
    set tags [.t tag names $index]
    set i [lsearch -glob $tags demo-*]
    set cursor [.t cget -cursor]
    if {$i < 0} {
	.statusBar.lab config -text " "
	set newcursor xterm
    } else {
	set demo [string range [lindex $tags $i] 5 end]
	.statusBar.lab config -text "Run the \"$demo\" sample program"
	set newcursor hand2
    }
    if [string compare $cursor $newcursor] {
	.t config -cursor $newcursor
    }
}


# showCode --
# This procedure creates a toplevel window that displays the code for
# a demonstration and allows it to be edited and reinvoked.
#
# Arguments:
# w -		The name of the demonstration's window, which can be
#		used to derive the name of the file containing its code.

proc showCode w {
    set file [string range $w 1 end].tcl
    if ![winfo exists .code] {
	toplevel .code
	frame .code.buttons
	pack .code.buttons -side bottom -fill x
	ttk::button .code.buttons.dismiss -text Dismiss \
	    -default active -command "destroy .code"
	ttk::button .code.buttons.rerun -text "Rerun Demo" -command {
	    eval [.code.text get 1.0 end]
	}
	pack .code.buttons.dismiss .code.buttons.rerun -side left \
	    -expand 1 -pady 2
	frame .code.frame
	pack .code.frame -expand yes -fill both -padx 1 -pady 1
	text .code.text -height 40 -wrap word \
	    -xscrollcommand ".code.xscroll set" \
	    -yscrollcommand ".code.yscroll set" \
	    -setgrid 1 -highlightthickness 0 -pady 2 -padx 3
	ttk::scrollbar .code.xscroll -command ".code.text xview" \
	    -orient horizontal
	ttk::scrollbar .code.yscroll -command ".code.text yview" \
	    -orient vertical

	grid .code.text -in .code.frame -padx 1 -pady 1 \
	    -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
	grid .code.yscroll -in .code.frame -padx 1 -pady 1 \
	    -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
	#	grid .code.xscroll -in .code.frame -padx 1 -pady 1 \
	    #	 -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
	grid rowconfig .code.frame 0 -weight 1 -minsize 0
	grid columnconfig .code.frame 0 -weight 1 -minsize 0
    } else {
	wm deiconify .code
	raise .code
    }
    wm title .code "Demo code: [file join $::zinc_demos $file]"
    wm iconname .code $file
    set id [open [file join $::zinc_demos $file]]
    .code.text delete 1.0 end
    .code.text insert 1.0 [read $id]
    .code.text mark set insert 1.0
    close $id
}

# aboutBox --
#
#	Pops up a message box with an "about" message
#
proc aboutBox {} {
    tk_messageBox -icon info -type ok -title "About Zinc Demo" -message \
	"Tkzinc widget demonstration\n\n\
Copyright (c) 2003 CENA\n\n
The demo framework \n
Copyright (c) 1996-1997 Sun Microsystems, Inc."
    }

Added jni/tkzinc/doc/alledges.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/allgradients.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/alllineshapes.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/allreliefs.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/alphastip.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/atcsymb.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/fillrule.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/index.html.

























>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
<html>
  <head>
    <title>Zinc, an advanced scriptable Canvas.</title>
    <base target="viewer">
  </head>

  <frameset cols="30%,70%"  framespacing="0" frameborder="1" >
    <frame src="refman.html" name="navig" frameborder="0" marginwidth=0 marginheight=0>
    <frame src="refmanch1.html" name="viewer" frameborder="0" marginwidth=0 marginheight=0>
  </frameset>

</html>

Added jni/tkzinc/doc/refman.cfg.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
\Preamble{2,index=2}

\Configure{@HEAD}
  {\HCode{<base target="viewer">}}
\Configure{@BODY}
  {\HCode{<div class="r\FileNumber"><div class="bodylayout">}}
\Configure{@/BODY}
  {\HCode{</div></div>}}

\Configure{crosslinks+}{}{}{}{}
\Configure{tableofcontents*}{chapter,section,subsection}

\Css{div.r1 { background-color: \#E5ECF9; }}
\Css{p.noindent { margin: 0px; padding: 0px; }}
\Css{div.bodylayout { color: \#000000;      
	padding: 8px; font-family: sans-serif; font-size: 12px; }}

\Css{a { color: \#002AAA; text-decoration: none; }}
\Css{a:hover { color: \#A00000; text-decoration: underline; font-style: italic; }}
\Css{.titleHead { background-color: \#FFFFFF; border: 2px \#507BBF solid; padding: 4px; }}
\Css{div.maketitle { margin-bottom: 10px; padding-bottom: 10px; border-bottom-style: groove; }}
\Css{.author { font-weight: bold; }}
\Css{.sectionToc { padding: 6px; }}
\Css{.subsectionToc { padding-left: 12px; }}

\Css{h1, h2 {
	background-color: \#E5ECF9;     
	border: 1px \#507BBF solid;
	padding: 2px;
}}

\Css{h3, h4 {
	background-color: \#FFF8DB;     
	border: 1px \#FFCC33 solid;
	padding: 2px;
}}

\Css{th, td {
	padding: 5px; 
}}


\Css{tt {
	font-style: italic;
	font-size: 12px;
	font-weight: bold;
}}

\Css{pre {
	background-color: \#F9F9FC;      
	border: 1px \#D4DDE9 solid;
	padding: 6px;
}}

\begin{document}

\EndPreamble


Added jni/tkzinc/doc/refman.tex.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
\documentclass[11pt,twoside,a4paper]{book}

%----------------------------------------------------------------------
% $Revision$

%
% TODO
%
% Relire et reprendre l'item Track et compléter les attributs
% Même chose pour triangles
% Vérifier que les couleurs sont bien décrites comme des gradients
% Les reliefs sont calculés sur le linecolor/bordercolor et non
%  sur le fillcolor comme avant
% Ecrire les quelques descriptions d'item qui manquent.
% Mettre quelques images: au moins une par item, une pour chaque relief,
% une pour chaque type de gradient.
%
%

\newif\ifpdf
  \ifx\pdfoutput\undefined
    \pdffalse           % we are not running PDFLaTeX
  \else
    \pdfoutput=1        % we are running PDFLaTeX
     \pdftrue
  \fi

\ifpdf
  \usepackage[pdftex,
    colorlinks=true,
    urlcolor=rltblue,
    anchorcolor=rltbrightblue,
    filecolor=rltgreen,
    linkcolor=rltred,
    menucolor=webdarkblue,
    citecolor=webbrightgreen,
    pdftitle={Zinc, an advanced scriptable Canvas.},
    pdfauthor={Patrick Lecoanet, Christophe Mertz, Centre d'Étude de la Navigation Aérienne},
    pdfsubject={The 3.3.4 Reference Manual.},
    pdfkeywords={tk tcl perl x11 canvas opengl script gui TkZinc},
    pagebackref,
    pdfpagemode=None,
    bookmarksopen=true
  ]{}
%  \pdfpagewidth=210truemm
%  \pdfpageheight=297truemm
  \pdfcompresslevel=9
  \usepackage[pdftex]{graphicx}
  \usepackage{thumbpdf}
  \usepackage{color}
  \definecolor{rltred}{rgb}{0.75,0,0.20}
  \definecolor{rltgreen}{rgb}{0,0.5,0}
  \definecolor{rltblue}{rgb}{0,0,0.75}
  \usepackage[pdftex,hyperindex=false]{hyperref}
\else
%  \usepackage[html,2]{tex4ht}
  \usepackage{graphicx}
  \usepackage[tex4ht,hyperindex=true]{hyperref}
\fi


\usepackage[widemargins]{a4}
\usepackage{calc}
\usepackage{makeidx}


\newcommand{\cident}[1] {%
  {\tt #1}}

\newcommand{\code}[1] {%
  {\tt #1}}

\newcommand{\ident}[1] {%
  {\bf\large #1}}

\newcommand{\linkface}[1] {%
  {\bf\large #1}}

\newenvironment{blockindent} {%
  \begin{quote}\vspace{-0.8\baselineskip}%
} {%
  \end{quote}\vspace{-0.5\baselineskip}%
}

\newcommand{\option}[3]{%
  \label{opt:#1}
  \index{#1|hyperpage}
  \begin{tabular}{rl}
    Command line switch: & \ident{-#1} \\
    Database name: & \ident{#2} \\
    Database class: & \ident{#3}
  \end{tabular}}
%  \begin{blockindent}#4\end{blockindent}}


\newcommand{\command}[3]{%
  \label{cmd:#2}
  \index{#2|hyperpage}
  {\tt\large #1 {\bf #2} #3}}

\newcommand{\zinccmd}[2]{%
  \subsection{#1}
  \command{pathname}{#1}{#2}}

\newcommand{\mapinfocmd}[3]{%
  \label{mapcmd:#2}
  \index{#2|hyperpage}
  {\tt\large mapinfo #1 {\bf #2} #3}\\
  {\tt\large \$mainwindow->mapinfo(#1, {\bf #2}, #3) }
  % slightly buggy XXX : missing commas when #3 contains many words
}

\newcommand{\attrtype}[1]{%
  \label{attrtype:#1}
  \index{#1|hyperpage}
  {\tt {\bf #1}}
}

\newcommand{\attrtyperef}[1]{%
  \hyperref[attrtype:#1]{\linkface{#1}}
}

% the following command is never used!!
\newcommand{\available}[1]{%
  \hyperref[obj:#1]{\linkface{#1}}
}

\newcommand{\optref}[1]{%
  \hyperref[opt:#1]{\linkface{-#1}}
}

\newcommand{\cmdref}[1]{%
\hyperref[cmd:#1]{\linkface{#1}}
}

%first argument : item type or 'option'
%second argument: attribute
%third argument : type
%fourth argument; explanation
\newcommand{\attribute}[4]{%
  \label{attribute:#1:#2}
  \ident{-#2 }%
  \index{#2|hyperpage}
  \hyperref[attrtype:#3]{\linkface{#3}}
  \begin{quote}\vspace{-\baselineskip}#4\vspace{-0.8\baselineskip}\end{quote}
}

% first argument : item type or 'option'
% second argument: attribute
\newcommand{\attributeref}[2]{%
  \hyperref[attribute:#1:#2]{\linkface{-#2}}
}

\newcommand{\object}[1]{%
  \label{obj:#1}
  \index{#1|hyperpage}
}

\newcommand{\concept}[1]{%
  \label{concept:#1}
}

\newcommand{\objectref}[1]{%
  \hyperref[obj:#1]{\linkface{#1}}
}

\newcommand{\conceptref}[2]{%
  \hyperref[concept:#2]{\linkface{#1}}
}

% Premier parametre : nom du fichier image
% Deuxieme parametre : legende
% Troisieme parametre : scaling (e.g. 2.2 1 ou 0.54) à appliquer en pdf / dvi
\newcommand{\fig}[3]{%
  \begin{figure}[htbp]%
    \centering%
    \label{fig:#1}%
    \includegraphics[scale=#3]{#1.png}%
    \caption{#2}%
  \end{figure}}{%
}


\newcommand{\anurl}[1]{%
\href{#1}{\linkface{#1}}
}


\makeindex

\setlength{\parindent}{0cm}
\setlength{\parskip}{0.2cm}
\setlength{\oddsidemargin}{10pt}
\setlength{\evensidemargin}{20pt}
\setlength{\marginparwidth}{20pt}
\setlength{\textwidth}{480pt}

\title{Zinc, an advanced scriptable Canvas.\\The 3.3.4 Reference Manual.\\\small{[CENA technical Note NT03-532]} }
\author{Patrick Lecoanet, Christophe Mertz}
\date{12 September 2006}


\begin{document}
%pdfpagewidth: \the\pdfpagewidth pdfpageheight: \the\pdfpageheight voffset: \the\voffset ~topmargin: \the\topmargin ~textheight: \the\textheight \linebreak

\ifpdf\voffset=-0.5in \setlength\textheight{ (\textheight+0.5in) }\fi

%voffset: \the\voffset ~topmargin: \the\topmargin ~textheight: \the\textheight \linebreak


\DeclareGraphicsExtensions{.png,.ps,.eps,.pdf}

\maketitle

\tableofcontents

%%
%%
%% C h a p t e r :   I n t r o d u c t i o n
%%
%%
\chapter{Introduction}
\concept{introduction}


\section{What is TkZinc ?}

TkZinc widgets are very similar to Tk Canvases in that they support
structured graphics. Like the Canvas, TkZinc implements items used to
display graphical entities. Those items can be manipulated and bindings can be
associated with them to implement interaction behaviors. But unlike the
Canvas, TkZinc can structure the items in a hierarchy (with the use of
group items), has support for affine 2D transforms (i.e.\ translation, scaling, and
rotation), clipping can be set for sub-trees of the item hierarchy, the item set
is quite more powerful including field specific items for Air Traffic systems and
new rendering techniques such as transparency and gradients. If needed, it is also
possible to extend the item set in an additionnal dynamic library through the use
of a C api.

Since the 3.2.2 version, TkZinc also offers as a runtime option, the support
for openGL rendering, giving access to features such as antialiasing, transparency,
color gradients and even a new, openGL oriented, item type : \objectref{triangles}.
In order to use the openGL features, you need the support of the GLX extension on
your X11 server. Of course, performances will be dependant of your graphic card.  At
the time of writing, NVidia drivers for XFree86 R4.1 are doing a nice job. A laptop
with a GeForce GO graphic card works nice for non trivial applications.  We also
succeeded in using TkZinc with openGL on the Exceed X11 server (running on windows and
developped by Hummingbird) with the 3D extension.

As an example of TkZinc capabilities when combined with openGL, we implemented
the TkZinc logo as a Perl module (available as a goodie in \ident{LogoZinc.pm}).
This logo (see below) was designed with Adobe Illustrator and then programmed in Perl.


%\includefigure{tkzinclogo}{Zinc logo written as a Perl/Tk module}{fig:logozinc}

\fig{tkzinclogo}{Zinc Logo written as a Perl/Tk module}{1}

Like the canvas TkZinc focuses on the notion of script language. We strongly
believe that the script environments are very powerful for rapid prototyping and for
developping small to medium scale field specific applications. In these cases
developper know-how and time are a scarce resource and the application either has few
clients or is short lived. It is important to grant non-specialists an access to the
powerful tools that are available today for HMI building, through a rather simple
product.

The TkZinc widget is available for the Tcl/Tk and the Perl/Tk scripting
environments.  A binding over Tcl/Tk is also provided for Python. It should be easy
to do the same for Ruby, a binding for Tk is provided in the standard distribution of
Ruby. Other scripting languages may be used as well depending on the availability
of a Tk interface.

As of the 3.3.2 release, a C++ binding has been added thanks to Intuilab \anurl{www.intuilab.com}.
It doesn't cover the full Tk/Tkzinc extent but it should be quite adequate to test the concept
and write small apps. It can be found in the directoy zinclib.d. It is provide in source
form only, makefiles are available to build it for linux and windows.

This document is Tcl/Tk and Perl/Tk oriented but it should be easy for Python or Ruby
programmers to adapt. Every time a TkZinc command is described in this
document, it is given first in Tcl/Tk idiom and then in Perl/Tk idiom.

This document is also referenced as CENA technical note NT03-532.

\section{Differences with previous versions}

\subsection{Differences between 3.3.X and 3.3 release}
\begin{itemize}
\item  Items ot type window have a new attribute -windowtitle to
  retrieve and display any top-level window whose title matches the
  value of windowtitle
\item  Damage support can now be controlled by a new TkZinc option
  -usedamage 
\item  TkZinc now supports MouseWheel events under Windows
\end{itemize}

\subsection{Differences between 3.3 and 3.2.97 release}
This release has been mainly focused on producing a stable code
base that compile and run on all three supported platforms with
as little effort as possible. 

The only functional change is the integration of the fieldbbox
command into the bbox command.


\subsection{Differences between 3.2.97 and 3.2.6 release}
\begin{itemize}
\item  TkZinc now works with Perl ptk 8.4 and utf8; However there remains 
some serious performance hit at launch time, when combinig openGL and ptk8.4,  
due to utf8 fonts management.
\item  text and icons can now be scaled and rotated in X (i.e. without openGL)
\item  translate method accepts an additionnal argument 'absolute'
\item  scale method accepts additionnal arguments: unit and rotation center
\item  find and addtag methods can now search inside atomic group
\item  the bbox method accepts into account the clipping area of a group
\item  TkZinc option -trackmanagehistory is replaced by -trackvisiblehistorysize
and in for track items the attribute -visiblehistorysize has been removed and
replaced by  -historyvisible. {\bf Beware: Incompatible change}
\item  Default value of -composescale and -composerotation of texts
and icons is now false. This is coherent with the default behavior
of these items (being rigids). The impact of this change is
greatly minored by the new processing of the -position attribute.
\item  transformation of items with a -position has been slightly
modified. The point described by -position is no longer considered
in the coordinate space of the item but in the coordinate space
of its parent group. The item is always located in 0,0 of its
own coordinate space. This is so to make use of -composescale and
-composerotation a lot more useful (and compatible).
\item  The fieldbbox method has been added to get item filed bounding box.
\item  Four new methods are now available for managing the transforms: 
tcompose, tget, tset and skew. A predefined named transformation is also available 
'identity' to be used with tsave. A predefined tag 'device' can be used to 
convert coordinates in or from device coordinates (with transform method).
\item  TkZinc with Tcl/Tk now works on windows and MacOS X (with X11 and fink).
\item  compilation on Linux works fine now, and TkZinc for Perl is on the CPAN
\item  A powerful perl module Tk::Zinc::Graphics has been added to help creating
complex curves. French man pages are available. A port in Tcl is also available.
\item  png images with transparencies can now be displayed (requires openGL rendering)
\item  bezier items have been suppressed; they can now be easily replaced by curve items.
\item  curve items support now a higher level of description: they may be composed of line
segments, and bezier segments. In the future they may also support other kinds of segments
(such as arcs...).
\item  the coords method accepts a list of arrays as well as flat list of coordinates.
When coords returns more than one point it is always a list of arrays.
(and no more a flat list of x y x y ...). {\bf Beware this is a small incompatible change in the API}.
\item  operators of the contour command have been replaced by a flag which indicates
if the contour must be taken as counterclockwise, clockwise or unchanged.
Contours ids are now predictable. The GPC ``not-so-free'' library is no more used.
It has been replaced by the GLU library. So TkZinc is again fully free software.
\item  curve item have a new -fillrule attribute. 
\item  the syntax of gradient has been changed, mainly to accomodate with any color specification
defined for X. {\bf Beware that old gradient are no more compatible}
\item  conical gradient type has been added; gradient paramaters has been extended.
\item  Perl modules ZincText, ZincDebug, ZincTrace and ZincTraceErrors have been renamed Tk::Zinc::Text Tk::Zinc::Debug
Tk::Zinc::Trace and Tk::Zinc::Trace.
\item  TkZinc comes now with a ZincTrace.pm module to trace every TkZinc method call
\item  the hierarchical view in ZincDebug.pm can now display some choosen attributes
in a choosen format.
\item  6 new Perl demos in zinc-demos: ``testGraphics'',  ``magic Lens'', ``pathTags'', ``tiger'' and ``curve with bezier control points''
and ``fillrule''. Many Perl/Tk demos have been ported to Tcl/Tk.
\item  pathTags introduced in 3.2.6 have been documented. Label and label
format documentation has been enhanced.
\end{itemize}


\section{Where can I find TkZinc and documentation ?}

\ident{TkZinc} is available as source in tar.gz format or as Debian or RedHat/Mandrake
packages at \anurl{http://www.tkzinc.org/}.

The public Tkzinc CVS repository can be browsed at \anurl{cvs.tkzinc.org}. The most up to
date copy can be grabbed anonymously with the following command:
\begin{verbatim}
cvs -d :pserver:anonymous@cvs.tkzinc.org:/srv/tkzinc/cvsroot login
\end{verbatim}
(press return when asked for a password), and then:
\begin{verbatim}
cvs -d :pserver:anonymous@cvs.tkzinc.org:/srv/tkzinc/cvsroot co Tkzinc
\end{verbatim}

Developpers can obtain a read/write access to the CVS database by giving their ssh public key
to the Tkzinc maintainer. Once acknowledged as a developper they will be able to checkout with
the command:
\begin{verbatim}
cvs -d :ext:login@cvs.tkzinc.org:/srv/tkzinc/cvsroot co Tkzinc
\end{verbatim}
Then they'll be able to commit theirs changes into the base.

This documentation is available as part of the TkZinc software.  It is also
available separately on the web sites. This document is formatted with \LaTeX\ 
and is distributed as either html pages or a pdf file.

As a complement to this reference manual, small Perl/Tk demos of TkZinc are
also available through a small application named \conceptref{zinc-demos}{zinc-demos},
highly inspired from the \emph{widget} application included in Tk. The aim of these demos
are both to demonstrates the power of TkZinc and to help newcomers start using
Zinc with small examples.


\section{What is this document about ?}

This reference manual describes the TkZinc widget interface. It shows how to
create and configure a TkZinc widget, and how to use the commands it provides to
create and manipulate items. The next chapter \conceptref{Widget creation and
options}{options} describes how to create a new widget and which options and resources are
available to configure it.
The chapter \conceptref{Groups, Display List and Transformations}{coordinates} describes
the use of groups and coordinates transformations.
The chapter \conceptref{Item ids, tags and indices} {tagOrId} describes the item tags
along with their main purposes. Also introduced is the concept of part name used by some
items (\objectref{track} and \objectref{waypoint}).  Finally, this chapter provides a
description of textual indices.

The chapter \conceptref{Widget commands}{commands} describes the commands which apply to a
Zinc widget. They are used for creating, modifying or deleting objects, applying
transforms ...
The chapter \conceptref{Item types}{items} describes all the items provided by TkZinc along
with their attributes.
The chapter \conceptref{Labels, fields and labelformat}{labelsandfields} describes the
use of labels, the possible attributes of fields and finally the labelformat syntax.
The chapter \conceptref{Attributes types}{types} describes the legal form of all item
attributes.
The chapter \conceptref{The mapinfo commands}{mapinfocmds} introduces the mapinfo, a
simple map description structure, and describes the commands used to create and
manipulate mapinfos.
Finally the chapter \conceptref{Other resources provided by the widget}{otherresources}
describes some resources provided by or with TkZinc.


\section{Copyright and License}

Zinc has been developed by the CENA (Centres d'Etudes de la Navigation
Aérienne) for its own needs in advanced HMI (Human Machine Interfaces or Interactions).
Because we are confident in the benefit of free software, the CENA delivered this
toolkit under the GNU Lesser General Public License.

This software is copyrighted by the Centre d'études de la Navigation
Aérienne, Patrick Lecoanet, and other parties.  The following terms
apply to all files associated with the software unless explicitly
disclaimed in individual files.

Here is the license text:

Copyright (c) 2005, Centre d'études de la Navigation Aérienne, Patrick Lecoanet
All rights reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

Parts of this software are derived from the Tk toolkit which is copyrighted by
The Regents of the University of California and Sun Microsystems, Inc..
The GL font rendering is derived from Mark Kilgard code described in ``A Simple
OpenGL-based API for Texture Mapped Text'' and is copyrighted by Mark Kilgard
under an open source license.


\section{Authors and credits}

Zinc has been developed by Patrick Lecoanet. He also developed two previous
version called \emph{Radar Widget} which share some characteristics with this
version. The \emph{Radar Widget} was heavily used at CENA for many projects over nearly
10 years. The release 2 is still in use. It was enhanced and then used for actual
radar displays in two main French Air Traffic Control Centres 24 hours a
day. Dominique Ruiz, Frederic Lepied helped a lot in the developement of these
earlier versions.

Zinc benefited greatly from the close interaction and the needs expressed by
Jean-Luc Vinot. Jean-Luc has a background of Graphic Designer and is now an HMI
developer at CENA. He envisions many, many new ideas for advanced HMI. Many of them
would have been difficult to implement if at all possible with similar widgets.
Zinc would have been less interesting without his ideas.

Didier Pavet and his team as well as Daniel Etienne and Herve Damiano were the first
users and helped a lot either by reporting bugs, problems or solutions. Thanks to all
these people and to the CENA for supporting this work.

The core of this documentation has been written by Patrick Lecoanet, the main author
of TkZinc. This documentation has been enriched by Christophe Mertz.


\section{How can I find help with TkZinc}

If you are stuck with a feature you don't understand. If you don't know how to
do something with TkZinc. If you think you have found a bug or a mismatch between
the documentation and the behavior of the widget. Please feel free to contact us.
Mail either {\tt lecoanet@cena.fr} or the TkZinc mailing list. To subscribe to the mailing
list, please consult the site \anurl{http://www.tkzinc.org/}.
Bugs can be looked up or reported using the Bugzilla facility located at \anurl{bugzilla.tkzinc.org}


\section{How may I contribute to TkZinc development}

If you think TkZinc is an interesting tool, they are many ways to help with TkZinc
development. First of all, subscribe to the TkZinc mailing list and get in touch with us. To
subscribe, please consult the site \anurl{http://www.tkzinc.org/}.

\begin{itemize}
\item The very first way to contribute is to use TkZinc and to report
any bug or problem you may experiment. Of course, if you send a script that
exhibits the problem or even better a patch, your problem will have more
chance to find a solution. Please use the Bugzilla bug management system located
at \anurl{bugzilla.tkzinc.org} to report bugs and attach any scripts or report
material to the opened bug.
\item The second way to contribute is by commenting on and proposing enhancement to
this reference manual. As it has been written by french writers, english readers may
really help in making this document easier to use. If you really feel ambitious, you
may even try to write a tutorial, but that may be quite an undertaking! Some 
documentation (currently Tk::Zinc::Graphics) are in French only. Translating it in
english would be great.
\item The third way to contribute, and may be the funniest way, is to enrich the set
of demos (see chapter \conceptref{Other resources provided by the
widget}{otherresources}). Feel free to send us your productions. They may be simple
but demonstrative or more complex. It is up to you! They will be integrated in the
next release of TkZinc if they are worth it.
\item The fourth way to contribute, and may be the most difficult, is to enrich the set
of items (see section \conceptref{C api for adding new items}{Capi}) in an separate
dynamic library. Then send us source code (with appropriate copyright and license)
if you want them to be integrated in a future release of TkZinc.
\end{itemize}


%%
%%
%% C h a p t e r :   W i d g e t   c r e a t i o n   a n d   o p t i o n s
%%
%%
\chapter{Widget creation and options}
\concept{options}

The TkZinc command creates a new TkZinc widget, the general form are in Tcl and Perl:

\begin{quote}
{\tt\large zinc}\medskip

{\tt\large \$version = \$mainwindow->zinc();}\smallskip

{\tt\large \$Tk::Zinc::VERSION;}
\end{quote}

These expressions can be used to get the version of TkZinc. The string returned by the last expression also details the graphic head available. For example : ``zinc-version-3205d X11 GL''.

\begin{quote}
{\tt\large zinc pathname ?options?}\medskip

{\tt\large \$mainwindow->Zinc(?option=>value?, ..., ?option=>value?);}
\end{quote}

{\tt pathname} name the new widget and specifies where in the widget hierarchy
it will be located.

You can set the {\tt \$ZINC\_GLX\_INFO} environment variable in order to display some information about the OpenGL instance used by TkZinc \textit{(New since TkZinc v3.2.6i)}.

Any new TkZinc widget comes with a root group item, always identified by
the item id 1. This group will contain all other items, either directly or through
groups created themselves in the root group. Together the items form a tree rooted
at the root group, hence its name.
The chapter \conceptref{Groups, Display List and Transformations}{coordinates}
describes the use of groups. The chapter \conceptref{Item ids, tags and indices}{tagOrId}
describes the item ids and item tags, used as argument in most commands.

The options are used to configure how the newly created widget will behave.
They can be changed later by using the \cmdref{configure} and \cmdref{itemconfigure}
Tk commands.

Options apply only to the widget itself.  They are a Tk supported concept and
benefit from the option database an other mechanisms used to externally adapt the
application to different environments. Attributes are a similar concept available for
items and other TkZinc objects. But they are private to TkZinc and do not benefit from Tk
support. They have been named differently to avoid confusion.

Any number of options may be specified on the command line or in the option
database to modify the global behavior of the widget. Available options are
described below.


\option{backcolor}{backColor}{BackColor}
\begin{blockindent}
This is the color that will
be used to fill the TkZinc window. It is also used as a default color
for some item color attributes. See each color attribute for the
actual source of the default color. Its default value is
{\tt \#c3c3c3}, a light grey.
\end{blockindent}

\option{borderwidth}{borderWidth}{BorderWidth}
\begin{blockindent}
  Specifies the width of the 3d border that should be displayed around the widget
  window. This border does overlap the active TkZinc display area. The area
  requested from the geometry manager (or the window manager if applicable)
  is the area defined by \optref{width} and \optref{height}, the border is not
  taken into account. This value can be given in any of the forms valid for
  coordinates (See \cident{TkGet\_Pixels}). The default value is {\tt 2}.
\end{blockindent}

\option{confine}{confine}{Confine}
\begin{blockindent}
  Specifies a boolean value that indicates whether or not it should be allowable
  to set the TkZinc's view outside the region defined by the \optref{scrollregion}.
  Defaults to true, which means that the view will be constrained within the scroll region.
\end{blockindent}

\option{cursor}{cursor}{Cursor}
\begin{blockindent}
  Specifies the cursor to use when the pointer is in the TkZinc window.  The default
  value is set to preserve the cursor inherited at widget creation.
\end{blockindent}

\option{followpointer}{followPointer}{FollowPointer}
\begin{blockindent}
  Set this option to zero to disable emission of enter and leave events. Motion
  processing is still performed as usual. It is in some application state annoying
  to receive enter and leave events which may result in an endless loop. This is
  a mean to temporarily deactivate the cause. Use with care. The default value is
  one, enabled. The name is somewhat a misnommer for Tkzinc is still following the
  pointer.
\end{blockindent}

\option{font}{font}{Font}
\begin{blockindent}
  The font specified by this option is used as a default font for item attributes of
  type font. Its default value is {\tt -adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*}.
\end{blockindent}

\option{forecolor}{foreColor}{Foreground}
\begin{blockindent}
  The color specified by this option is used as a default color for many item color
  attributes. See each each color attribute for the actual source of the default
  color. Its default value is {\tt black}.
\end{blockindent}

\option{fullreshape}{fullReshape}{FullReshape}
\begin{blockindent}
  If this option is True, the shape applied to the TkZinc window will propagate up the
  window hierarchy to the toplevel window. The result will be a shaped toplevel.
  See also the \optref{reshape} option, it controls whether a shape is applied
  to the TkZinc window or not.  The default is {\tt true}.
\end{blockindent}

\option{height}{height}{Height}
\begin{blockindent}
  Specifies the height of the TkZinc window. This value can be given in any of the
  forms valid for coordinates (See \cident{Tk\_GetPixels}). The default is {\tt 100}
  pixels.
\end{blockindent}

\option{highlightbackground}{highlightBackground}{HighlightBackground}
\begin{blockindent}
  Specifies the color to display in the traversal highlight region when the
  widget does not have the input focus. The default value is {\tt \#c3c3c3}.
\end{blockindent}

\option{highlightcolor}{highlightColor}{HighlightColor}
\begin{blockindent}
  Specifies the color to use for the traversal highlight rectangle that is drawn
  around the widget when it has the input focus. The default value is {\tt black}.
\end{blockindent}

\option{highlightthickness}{highlightThickness}{HighlightThickness}
\begin{blockindent}
  Specifies a non-negative value indicating the width of the highlight rectangle
  drawn around the outside of the widget when it has the input focus. The value may
  have any of the forms acceptable to \cident{Tk\_GetPixels}.  If the value is zero,
  no focus highlight is drawn around the widget.  The default value is {\tt 2}.
\end{blockindent}

\option{insertbackground}{insertBackground}{Foreground}
\begin{blockindent}
  Specifies the color to use as background in the area covered by the insertion
  cursor. This color will normally override either the normal background for the
  widget (or the selection background if the insertion cursor happens to fall in the
  selection). The default value is {\tt black}.
\end{blockindent}

\option{insertofftime}{insertOffTime}{OffTime}
\begin{blockindent}
  Specifies a non-negative integer value indicating the number of milliseconds the
  insertion cursor should remain off in each blink cycle.  If this option is zero
  then the cursor is on all the time. The default value is {\tt 300}.
\end{blockindent}

\option{insertontime}{insertOnTime}{OnTime}
\begin{blockindent}
  Specifies a non-negative integer value indicating the number of milliseconds the
  insertion cursor should remain on in each blink cycle.  The default value is {\tt 600}.
\end{blockindent}

\option{insertwidth}{insertWidth}{InsertWidth}
\begin{blockindent}
  Specifies a value indicating the width of the insertion cursor.  The value may have
  any of the forms acceptable to \cident{Tk\_GetPixels}.  The default value is {\tt 2}.
\end{blockindent}

\option{lightangle}{lightAngle}{LightAngle}
\begin{blockindent}
  Specifies the lighting angle in degre used when displaying relief. The default value is {\tt 120}. %%% XXX CM to be completed!
\end{blockindent}

\option{mapdistancesymbol}{mapDistanceSymbol}{MapDistanceSymbol}
\begin{blockindent}
  This option specifies the symbol to be used as a milestone along map lines. This
  option can be given any Tk bitmap which can be obtained by
  \cident{Tk\_GetBitmap}. The spacing between markers is 10 nautic miles. The default
  value is {\tt AtcSymbol19} (see \conceptref{Other resources provided by the widget}{otherresources}).
\end{blockindent}

\option{maptextfont}{mapTextFont}{MapTextFont}
\begin{blockindent}
  Specifies the font used to draw the texts contained in maps. The default is
  {\tt -adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*}.
\end{blockindent}

\option{overlapmanager}{overlapManager}{OverlapManager}
\begin{blockindent}
  This option accepts an item id. It specifies if the label overlapping avoidance
  algorithm should be allowed to do its work on the track labels and which group
  should be considered to look for tracks. The default is to enable the avoidance
  algorithm in the root group (id 1). To disable the algorithm this option should
  be set to {\tt 0}.
\end{blockindent}

\option{pickaperture}{pickAperture}{PickAperture}
\begin{blockindent}
  Specifies the size of an area around the pointer that is used to tell if the
  pointer is inside an item. This is useful to lessen the precision required when
  picking graphical elements. This value must be a positive integer. It defaults to
  {\tt 1}.
\end{blockindent}

\option{relief}{relief}{Relief}
\begin{blockindent}
  Specifies the border relief. This option can be given any legal value for a relief
  (See \attrtyperef{relief} for a description of possible values). The default
   value is {\tt flat}.
\end{blockindent}

\option{render}{render}{Render}
\begin{blockindent}
  Specifies whether to use or not the openGL rendering. The value is
  a positive integer that can have the values 0, 1 and 2. The value 0
  specifies a X11 rendering while the other two ask for an OpenGL
  rendering and as such requires the GLX extension to the X server.
  A value of 1 asks for direct OpenGL rendering which is the faster but
  is limited to a local session with the display while a value of 2
  requests an indirect rendering which is slower but can be streamed
  to a distant display (at least under X11). If a direct rendering
  mode is requested but can't be achieved the indirect render mode
  will be tried automatically. If neither OpenGL modes are available
  the X11 mode is used as a fallback.
  This option must be defined at widget creation time and is readonly
  for the rest of the session. It can be used to ask if the widget is
  drawing in OpenGL mode or in plain X mode (to adapt the
  application code for example). The default value is {\tt 0}.
\end{blockindent}

\option{reshape}{reshape}{Reshape}
\begin{blockindent}
  Specifies if the clipping shape that can be set in the root group item should clip
  the root group children or be used to reshape the TkZinc window. This option can be
  used with the fullreshape option to reshape the toplevel window as well. The
  default value is {\tt true}.
\end{blockindent}

\option{scrollregion}{scrollRegion}{ScrollRegion}
\begin{blockindent}
  Specifies a list with four coordinates describing the left, top, right, and bottom
  coordinates of a rectangular region. This region is used for scrolling purposes and
  is considered to be the boundary of the information in the TkZinc.
\end{blockindent}

\option{selectbackground}{selectBackground}{Foreground}
\begin{blockindent}
  Specifies the background color to use for displaying the selection in text
  items. The default value is {\tt \#a0a0a0}.
\end{blockindent}

\option{speedvectorlength}{speedVectorLength}{SpeedVectorLength}
\begin{blockindent}
  Specifies the duration of track speed vectors. This option is expressed using a
  time unit that should be chosen by the application (usually minutes) and kept
  coherent with the unit of the track attribute \attributeref{track}{speedvector} (usually nautic
  mile / minute). The default value is {\tt 3}.
\end{blockindent}

\option{takefocus}{takeFocus}{TakeFocus}
\begin{blockindent}
  (Slightly adapted from the Tk options manpage).

  Determines whether the window accepts the focus during keyboard traversal (e.g., Tab and
  Shift-Tab).  Before setting the focus to a window, the traversal scripts consult the
  value of the takeFocus option.  A value of 0 means that the window should be skipped
  entirely during keyboard traversal.  1 means that the window should receive the input
  focus as long as it is viewable (it and all of its ancestors are mapped).  An empty
  value for the option means that the traversal scripts make the decision about whether or
  not to focus on the window: the current algorithm is to skip the window if it is
  disabled, if it has no key bindings, or if it is not viewable.  If the value has any
  other form, then the traversal scripts take the value, append the name of the window to
  it (with a separator space), and evaluate the resulting string as a callback.  The
  script must return 0, 1, or an empty string: a 0 or 1 value specifies whether the window
  will receive the input focus, and an empty string results in the default decision
  described above.  \emph{Note: this interpretation of the option is defined entirely by
  the callbacks (part of the keyboard traversal scripts) that implement traversal; the
  widget implementations ignore the option entirely, so you can change its meaning if you
  redefine the keyboard traversal scripts.}
  The default value is empty.
\end{blockindent}

\option{tile}{tile}{Tile}
\begin{blockindent}
  Specifies an image name to be used as a tile for painting the TkZinc window
  background. The default value is {\tt ""} (the empty string).
\end{blockindent}

\option{trackmanagedhistorysize}{trackManagedHistorySize}{TrackManagedHistorySize}
\begin{blockindent}
  This option accepts only positive integers. It specifies the number of positions
  collected in the history list by the track items. When this many positions have
  been collected, the oldest is dropped to make room for a new one on a first-in
  first-out basis. See also the \optref{trackvisiblehistorysize} option and the
  \attributeref{track}{historyvisible} track attribute. The default value is {\tt 6}.
\end{blockindent}


\option{trackvisiblehistorysize}{trackVisibleHistorySize}{TrackVisibleHistorySize}
\begin{blockindent}
  This option accepts only positive integers. It specifies the number of
  past positions to display for tracks. It is a widget wide control. Users
  of previous releases used the {\tt -visiblehistorysize} track attribute
  for the same effect. The number of past positions displayed can not exceed
  the accumulated positions controlled by the option \optref{trackmanagedhistorysize}.
  The track \attributeref{track}{historyvisible} attribute controls whether
  a track should display its history. The default value is {\tt 6}.
\end{blockindent}


\option{tracksymbol}{trackSymbol}{TrackSymbol}
\begin{blockindent}
  Specifies the symbol displayed at the current position of a track. This option
  accepts a \attrtyperef{bitmap}. The default value is {\tt AtcSymbol15}.
\end{blockindent}

\option{usedamage}{useDamage}{UseDamage}
\begin{blockindent}
  Specifies whether to use or not damage optimizations with the openGL
  rendering. Damage are drawable regions which are in need of
  redisplay to repair the effects of window manipulation or to apply
  data change. The value is an integer that can have the values 0, 1 or
  2. The value 0 specifies that no optimization is applied, ie that
  the whole area of our widget is redisplayed. A value of 1 or 2 activates
  OpenGL optimization: TkZinc records an update area where the change
  have been made and then use this area to confine redrawing. It will
  speed up redrawing in most cases but with some graphic cards it may
  generate visual trails. A value of 1 is equivalent to the
  GL\_DAMAGE compilation flag in older version of TkZinc: it provides
  significantly better performance with Nvidia cards but it creates a
  strange trail effect with other cards (Ati, etc). A value of 2
  provides optimizations that are a bit slower but have a much better
  compatibility with Ati or Intel cards. The default value is {\tt 0}.
\end{blockindent}

\option{xscrollcommand}{xScrollCommand}{ScrollCommand}
\begin{blockindent}
  Specifies a callback used to communicate with horizontal scrollbars. When
  the view in the widget's window changes (or whenever anything else occurs
  that could change the display in a scrollbar, such as a change in the total
  size of the widget's contents), the widget will make a callback passing two
  numeric arguments in addition to any specified in the callback. Each of the
  numbers is a fraction between 0 and 1, which indicates a position in the
  document. 0 indicates the beginning of the document, 1 indicates the end,
  .333 indicates a position one third the way through the document, and so on.
  The first fraction indicates the first information in the document that is
  visible in the window, and the second fraction indicates the information
  just after the last portion that is visible. Typically the xScrollCommand
  option consists of the scrollbar widget object and the method ``set'' i.e.
  [set => \$sb]: this will cause the scrollbar to be updated whenever the view
  in the window changes. If this option is not specified, then no command
  will be executed.
\end{blockindent}

\option{xscrollincrement}{xScrollincrement}{ScrollIncrement}
\begin{blockindent}
  Specifies an increment for horizontal scrolling. If the value of this option
  is greater than zero, the horizontal view in the window will be constrained
  so that the TkZinc x coordinate at the left edge of the window is always an
  even multiple of {\tt xScrollIncrement}; furthermore, the units for scrolling
  (e.g., the change in view when the left and right arrows of a scrollbar are
  selected) will also be {\tt xScrollIncrement}. If the value of this option
  is less than or equal to zero, then horizontal scrolling is unconstrained.
\end{blockindent}

\option{yscrollcommand}{yScrollCommand}{ScrollCommand}
\begin{blockindent}
  Specifies a callback used to communicate with vertical scrollbars. This option
  is treated in the same way as the {\tt xScrollCommand option}, except that it is used
  for vertical scrollbars and is provided by widgets that support vertical
  scrolling. See the description of {\tt xScrollCommand} for details on how this option is used.
\end{blockindent}

\option{yscrollincrement}{yScrollincrement}{ScrollIncrement}
\begin{blockindent}
  Specifies an increment for vertical scrolling. If the value of this option
  is greater than zero, the vertical view in the window will be constrained
  so that the TkZinc y coordinate at the left edge of the window is always an
  even multiple of {\tt yScrollIncrement}; furthermore, the units for scrolling
  (e.g., the change in view when the top and bottom arrows of a scrollbar are
  selected) will also be {\tt yScrollIncrement}. If the value of this option
  is less than or equal to zero, then vertical scrolling is unconstrained.
\end{blockindent}

\option{width}{width}{Width}
\begin{blockindent}
  Specifies the width of the TkZinc window. This value can be given in any of
  the forms valid for coordinates (See \cident{Tk\_GetPixels}). The default is
  {\tt 100} pixels.
\end{blockindent}



%%
%%
%% C h a p t e r :   G r o u p s ,   D i s p l a y   l i s t s ,   C l i p p i n g
%%
%%
\chapter{Groups, Display lists, Clipping and Transformations}
\concept{coordinates}

Groups are very powerful items. They have no graphics of their own but are used to
bundle items together so that they can be manipulated easily as a whole. Groups can
modify in several way how items are displayed and how they react to events. They have
many uses in TkZinc and we will describe them in this chapter. The main usages
are:

\begin{itemize}
\item to bundle items together so they can be cloned, destroyed, hidden, 
  moved and more as a whole,
\item to bundle several items together so that they form a new single item
  composed of several simpler one. This is done by modifying the way events
  are associated with items (see \attributeref{group}{atomic}),
\item to interpose a new coordinate system in a hierarchy of items. This
  can be very useful to manage panning, zooming and other kind of viewing
  transformation. See below for an explanation of the transformation system
\item to compose some specific attributes such as transparency, sensitivity,
  visibility, ...\ with those of their children items,
\item to apply a clipping to their children items,
\item to manage display ordering between items and to do the display lists
  housekeeping.
\end{itemize}


\section{The root group and the item tree}

An item, be it simple like a rectangle or more complex like a group, is always
created relative to a group which is known as its parent, the group's items are its
children. The items form a tree whose nodes are the group items. The top-most node is
known as the root group, of id 1, which is automatically created with TkZinc. By
convention, the root group is its own parent. It is not possible to change the parent
of the root group and it is not possible to delete it. However, it is possible to
change the group of all other items after creation, and thus modify the item tree at
any time. This is the use of the \cmdref{chggroup} command.


\section{Attributes composed with children}

The following attributes are composed down the item tree to form the
resulting attribute value in the leaf items:
\begin{itemize}
\item\ident{-sensitive}: the sensitivity (to keyboards or mouse event) of an
  item is the result of and-ing together the \ident{-sensitive} attributes
  found when descending from the root group to a specific leaf item.
\item\ident{-visible}: the visibility of an item is the result of and-ing together
  the \ident{-visible} attributes found when descending from the root group to a
  specific leaf item.
\item\ident{-alpha}: the transparency of an item is the result of combining
  the \ident{-alpha} attributes of the groups found when descending from the
  root group to a specific item with the alpha channel found in a given color
  of this item. The transparency is a percentage between 0 and 100, two
  transparencies are combined by multiplying both and then dividing by 100.
  The transparency can be used only if the environment support openGL and if
  the widget was created with the \optref{render} option set to True.
\end{itemize}


\section{Atomic groups}

It may seem at first that there is a contradiction in this title, but there is not. It is
possible to built complex objects from simple items simply by assembling those items
together in a group (using other intervening groups if the need arise). Once this is
done, it would be convenient if the whole acted as a single item, the top assembling
group. It is already so for many commands that act on a group, it is possible to move,
resize, rotate, restack, clone, hide, change the transparency, delete the group as a whole
without knowing anything of its children. But when it comes to event dispatching, the
group is completly transparent so far. So the event dispatch mecanism will try to locate
the smallest most visible item containing the pointer and will trigger the associated
bindings. Not exactly what we meant. So groups have a feature, the
\attributeref{group}{atomic} attribute, that is used to seal a group so that events cannot
propagate past it downward. If an item part of an atomic group is under the pointer, TkZinc
will try to trigger bindings associated with the atomic group not with the item under the
pointer. This improves greatly the metaphor of an indivisible item.

It must also be noted that commands such as \cmdref{find} {\tt 'enclosed'/'overlapping'} or
\cmdref{addtag} {\tt 'enclosed'/'overlapping'} {\bf act differently on an atomic group}.
Such search command will not traverse an atomic group. So if a part of the atomic
group is enclosed or overlapping, the search command will return the atomic group
and not its part.

A small program, \ident{Atomic groups} is available as part of
\conceptref{zinc-demos}{zinc-demos} to demonstrate the atomic groups behaviour.


\section{Display order and display lists}

The items are displayed in a specific order which determines how they stack. This
order is also important for associating events with items. The items are arranged in
a display list for each group. The display list imposes a total ordering among its
items. The group display lists are connected in a tree identical to the group tree and
form a hierarchical display list. The items are drawn by traversing the display
list from the least visible item to the most visible one. Each time a group is
encoutered the traversal proceed with this group display list before resuming the
upper display list traversal. The search to find the item that should receive an
event is done in the opposite direction. In this way, items are drawn according to
their relative stacking order and events are dispatched to the top-most item at a
given location.

It is important to note as a consequence of this structuring, that items of a group are
stacked between the items that are under the group and the items that are on top of the
group. Thus, items of two groups cannot be intertwinned, they stack exactly as their groups
stack, that is items of the underneath group a drawn then the items of the other group are
drawn on top.

The item ordering imposed by the display lists can be ajusted in three ways. The two
first are local to a group's display list. The third can be used to rearrange between
groups.

\begin{itemize}
\item
  The attribute \ident{-priority} can be used to give an absolute stacking position
  to an item amongst the items of its group. When a new item is added to a group with a
  priority matching the priority of existing items of the group, the new item is placed on
  top of the those items. Last comer is most visible. The same rule is followed when
  changing the priority of an item and when moving an item to a new group.
  \objectref{map} and \objectref{reticle} default priority is 0. \objectref{window}
  item attribute is meaningless. All other items default priority is 1. 
\item 
 The commands \cmdref{raise} and \cmdref{lower} adjust the relative order of an item
 in its group. These commands can be used to bring an item in front or to the back of
 its group. It is also possible to place an item before or after a given item of its group.
 These commands act in such a way as to preserve the absolute relationship set by the
 \ident{-priority} attribute. To do so they may adjust the priority of the
 moved item to match the priority of the item just below (raise) or just above (lower).
 If the priority of the moved item is not in conflict with its new neighborhood, it is
 not affected.
\item
  It is also possible to move the item to another group. This has an effect on the item
  stacking as it will be forced to the stacking location of its new group.
\end{itemize}


\section{Event sensitivity}

An item will catch an event if all the following conditions are satisfied:
\begin{itemize}
\item
  the item \ident{-catchevent} attribute must be set (this is the default).
\item
 the item \ident{-sensitive} attribute must be set to true (this is the default).
\item
 the item must be under the pointer location.
\item
 the item must be on top of the display list (at the pointer location). Beware
 that an other item with its \ident{-visible} set to false DOES catch event
 before any underneath items.
\item
 the item must not be clipped (at the pointer location)
\item
 the item must not belong to an atomic group, since an atomic group catchs the event
 instead of the item.
\end{itemize}

An item satisfying all the above conditions can have its \ident{-visible} set
to false, or can be fully transparent (when  using openGL). It will still catch
the events.


\section{Transformations}

In TkZinc each item is geometrically defined in its own coordinate space. So
each time a new item is created, a new coordinate system is attached to it.
This coordinate system must be related to the coordinate systems of the other
items to place the items with respect to each other. This relationship is
defined by an affine transformation associated with the item. This transformation
establishes the relationship between an item and its group. The items being
arranged in a tree by their groups, its possible via the transformations to place
all the items in an absolute coordinate system known as the window space.

Just after item creation, the item transformation is set to identity, i.e the item
coordinate system maps exactly on the system of its group. The commands
\cmdref{translate}, \cmdref{scale}, \cmdref{rotate} , \cmdref{skew} can be 
used to modify this relationship to the effect of translating, enlarging, shrinking,
rotating or skewing the item. It must be emphasized that those commands act on the
relation between two coordinate spaces, \emph{not} on the item geometry itself.
If the goal is to change the item (except for groups, see next paragraph) geometry,
the command \cmdref{coords} may be more appropriate (but see below the command
\cmdref{tapply}).

As it should be clear, groups are like any other items, they are defined in
their own coordinate space and are assembled with their parents by transformations.
This is a very powerful tool to manage the geometry of clusters of items.
One must not refrain from using groups only to assign them a transformation
task such as panning a whole set of items or scaling a set while another is
kept in place in another group. For the developper convenience, the \cmdref{coords}
method on a group change its transformation. It defines the absolute translation
applied to the group.

Another very interesting use of a group as a transformation tool is to manage a window
coordinate space where the origin is not in the top left corner and where the Y axis goes
from bottom to top. It is quite simple to write a function that is triggerred on the
window resize event whose only goal is to compute a new transformation for the group.
Other parts of the application and the other items are not aware of this happening. A
good factorization example.

In fact, transformation are so useful that a whole set of functions are available
to help use them in full. Apart from the already mentioned \cmdref{translate},
\cmdref{scale}, \cmdref{rotate}, and \cmdref{skew} commands, it is also possible 
to restore a transformation to its initial state, identity, with the 
\cmdref{treset} command. 
It is also possible to compose a transformation with another name transform with 
the \cmdref{tcompose} command.

An item transformation can be saved under a name, in fact creating
a named transformation which can be manipulated just as an item transformation (i.e
using translate, scale, rotate, treset). Once a transformation has been named it
can be used to set the transformation of any item using with the command \cmdref{trestore}.
And it can be disposed of with the command \cmdref{tdelete}.

An item can be physically modified by applying its own transformation to itself. This is
the goal of the \cmdref{tapply} command. It applies the item transformation to its own
coordinates an then reset the item transformation. Visually nothing has changed but in
fact the item is irrevocably modified. Be aware that if it is quite easy to undo a change
in a transformation by using treset or by saving and then restoring a transformation, it
is not so easy to revert a physical modification on an item. The exact order of the
operations must be recorded and even then there is no shield against round off errors
that will probably occur. This command may be used together with the translate, scale and
rotate commands if someone really want, even after reading this paragraph, to implement
the canvas move, scale and even rotate commands.

A predefined named transformation exists. Its name is \ident{identity} and refers to the 
identity transform. it can not be modified by the user.

When dealing with mouse events and other sources of window coordinates, it is
often useful to map the window coordinates to an appropriate coordinate space. The
command \cmdref{transform} is just what is needed to do so. It is powerful enough to be
able to convert coordinates from any coordinate space to any other. A special provision
has been made to facilitate conversion from window space to another space. The opposite
is not impossible but rely on a small trick: the root group transformation must be left as
identity (the default at creation time). In this way, it is possible to use the root group
space, which is then the same as the window space, as the target space of the
\cmdref{transform} command.

If you need to manage many different transformations independently, it is a good
practice to apply these transformations to different groups. For example, a group
can be used for translation and an other group (father or son) for scaling.

When a rotation or a scale appear in a transformation, all items do not behave exactly in
the same manner. For example text items do not scale or rotate. Only their
position moves according to the rotation or the scaling factor. Here is how items react
to the scale and rotation factors of the transformation.

\begin{itemize}
\item \objectref{group} They have no graphical shape by themselves;
\item \objectref{track} The position, past positions, speedvector are fully transformed. The
  circular marker is transformed by the X scale factor, it always remains circular. The label
  position is computed relative to the new position and speedvector direction but is otherwise
  rigid and its distance (in pixels) to the position is unchanged.
\item \objectref{waypoint} The position is fully transformed. The label position is computed
  relative to the new position and new rotation but is otherwise rigid and its distance
  (in pixels) to the position is unchanged.
\item \objectref{tabular}, \objectref{text} Only the position (relative to the
  anchor) is affected.
\item \objectref{icon} With openGL, icon items can be rotated and zoomed.
\item \objectref{reticle} Only the center and the spacing between circles are affected.
\item \objectref{map} lines and arcs are fully transformed. For texts and symbols only the position
  is affected.
\item \objectref{rectangle}, \objectref{arc}, and \objectref{curve} are fully transformed.
\item \objectref{window} Only the position (relative to the anchor) is affected.
\end{itemize}

However, every item has a couple of attributes \ident{-composescale} and
\ident{-composerotation} that can be used to control how the scale and rotation factors
are inherited from the parents' transformations. These attributes default to \ident{true}
(i.e.\ rotation and scale from parents are meaningful, except for \objectref{icon} where these attributes
defaulted to \ident{false}). When one of these attributes is set
to false the corresponding factor is reset from the inherited transformation. Scale factors
are reset to 1.0 and rotation is reset to 0. Be careful that this applies to the inherited
transformation, \emph{not} to the item transformation itself which is composed \emph{after}
taking into account the composition attributes.

As you can see, the transformation process is quite powerful but complex. A small program,
\ident{Tranformation testbed} is available as part of \conceptref{zinc-demos}{zinc-demos}
to demonstrate the transformation capabilities of TkZinc. This is also a great resource
to understand how it works and to tame its complexity. It is possible to use this program
to test one's idea on a given transformation problem before coding it as part of a
complex application.


\section{Clipping and groups}
Groups can set a clip boundary before drawing their children. Thought of this feature as
if a group can be made to act as a window on its children. Except that the window can have
any shape you like to give it. Each group has a \attributeref{group}{clip} attribute which
can be set to an item of the group. This item, known as the clipper of the group, defines
the shape of the clipping. All item types except \objectref{group}, \objectref{track},
\objectref{waypoint}, \objectref{reticle} and \objectref{map} can be used as clippers
but the clipper must be a direct child of the clipped group. The clipper defines the shape
of the clipping but is also drawn as a regular group item. It is typical to either mask
explicitly the clipper by turning off its \ident{-visible} attribute or to fill and lower
it so it can act as the background. Of course, other creative uses can be found but be
warned that the clipper outline will never be easthetically drawn due to round off or
quantization errors, it is better to turn off borders or outlines in this case.

It is also possible to clip the root group (only on X11 system. Does not work on windows
systems). Depending on the value of TkZinc options \optref{reshape} and
\optref{fullreshape}, the clipping form can be used either to clip all items in the TkZinc
widget, or reshape the TkZinc widget, or to propagate the TkZinc widget shape to the parent
windows. In the latter case, this allows to build non-rectangulaire applications. This
requires both the SHAPE X11 extension and a compliant Window Manager (fvwm is known
to support non rectangulaire top windows). The clipping form should have a bounding box
with the same ratio as the topwindow or some normalisation will occur. Example:

\begin{verbatim}
  use Tk::Zinc;

  my $mw = MainWindow->new();
  my $zinc = $mw->Zinc(-reshape => 1, -fullreshape => 1)->pack;

  # creating a triangulaire curve
  my $triangle= $zinc->add('curve',1, [ [0,0], [100,0], [50,100] ], -closed => 1);
  # using the triangulaire curve to reshape both TkZinc and Mainwindow widgets
  $zinc->itemconfigure(1, -clip => $triangle);

  $zinc->add('arc',1, [ [0,0], [100,100] ], -filled => 1, -fillcolor => 'darkblue');
  ...
  Tk::MainLoop;
\end{verbatim}


%%
%%
%% C h a p t e r :   I t e m   I d s ,   t a g s   a n d   i n d i c e s
%%
%%
\chapter{Item ids, tags and indices}
\concept{tagOrId}

\section{Item ids}
Each item is associated with a unique numerical id which is returned by the
\cmdref{add} or \cmdref{clone} commands. All commands on items accept those
ids as (often first) parameter in order to uniquely identify on which item
they should operate. When an id has been allocated to an item, it is never
collected even after the item has been destroyed, in a TkZinc session two
items cannot have the same id. This property can be quite useful when used
in conjonction with tags, which are described below.

\section{Tags}
Apart from an id, an item can be associated with as many symbolic names as
it may be needed by an application. Those names are called tags and can be
any string which does not form a valid id (an integer). However the
following characters may not be used to form a tag: \verb+. * ! ( ) & | :+.
Tags exists, and may be used in commands, even if no item are associated
with them. In contrast an item id doesn't exist if its item is no longer
around and thus it is illegal to use it. Tags can be used to group items to
do some action, or to mark an item that has a special function. Many other
tasks can be solved with tags once one gets used to them.

Two special tags are implicitly managed by TkZinc. The tag \ident{all} is
associated with all items in TkZinc. The tag \ident{current} is always
associated with the topmost item that lies under the mouse pointer. If no
such item exists, no item has this tag.

In commands, tags can be used almost anywhere an item id would be legal.
In the command descriptions, the expression \ident{tagOrId} means that it
is legal to provide either a tag or an item id. This means that virtually
all actions can be either performed on a specific item by using its id or
on a whole set of items by using a tag. In order for this collective
behavior to be useful, if a command or an attribute does not apply to an
item named by the tag, it is simply ignored, no error will be reported
(This may yet not be the case with all commands, please report
infringements).

Everywhere a \ident{tagOrId} can be specified as a target for some action,
it is possible to give a logical expression of tags and ids. The available
boolean operators include logical and \verb+&&+, logical or \verb+||+,
logical xor \verb+^+, logical not \verb+!+ and subexpression grouping
\verb+()+. Here is an example of a \cmdref{bbox} command called on a set of
items defined by a logical expression. Note that tags and ids can be mixed. For example:
\begin{verbatim}
 ($xo, $yo, $xc, $yc) = $zinc->bbox("(red && black)||(pink && !$thisitem)");
\end{verbatim}

Many methods only operate on a single item at a time; if \ident{tagOrId} is
specified in a way that names multiple items, then the normal behavior for
these methods is to use the first of these items in the display list (most
visible) that is suitable for the method. Exceptions are noted in the
method descriptions below.

Tags can be associated with items by giving a tag list to the \ident{-tags}
attribute or by using the more powerful \cmdref{addtag} command. A tag can
be removed by the \cmdref{dtag} command, by setting the \ident{-tags}
attribute to the empty list, all tags are remove from an item at once
(except the implicit ones). Tags can be read with the \cmdref{gettags} or
by querying the \ident{-tags} attribute. The items named by a tag are
returned in a list by the \cmdref{find} command which as exactly the same
capabilities as \cmdref{addtag}.

\section{PathTags}
\concept{pathTags}
A special form of tag called a pathTag can be used as a tagOrId argument in all
commands except \cmdref{bind}. This special tag describes an item or a group of
items in the absolute item hierarchy. The pathTag consists in a path down the
group hierarchy followed by an (optionnal) effective tag, in the usual sense.

The path is an ordered list of tags set up on groups that drives the search
from the root group down the group hierarchy. The path starts with either a dot
or a star, and the tags in the path are separated by dots or stars. The dot
means that the next tag selects a group item that is a direct child of the
current group, starting with the root group. The star selects a group item that
is a possibly indirect child of the current group, the candidate is found
in display list order. The first tag in the path, the one just after the first
dot or star, can be a group id; This is useful in order to limit the search in a
specific sub-hierarchy.

The last tag of a pathTag, the one not followed by a dot or a star, is the
effective tag searched for. It can be omitted, in this case the search
proceed with the tag all. The dot or star just before the effective tag,
even if the tag is implied, controls how the tag is searched. If a dot is
present, the search is limited to the current group level. If a star is
present, the search proceed from the current group level down the whole
group subtree.

A demo called ``Using pathTags'' in zinc-demos may help you better understand pathTags.
Here are some commonly used pathTags idioms:

\begin{itemize}

\item{\ident{.group1Tag.group2Tag.aTag}}
  Selects all \underline{direct} children with the tag {\it aTag} in the group obtained by
following the path {\it .group1Tag.group2Tag} from the root group.
The search proceed from the root group to the first direct child group in display
list order with tag {\it group1Tag}. Then it searches for the first direct child group
with tag {\it group2Tag}. Finally in this group, the search ends by finding all direct
children items (including groups) with tag {\it aTag}. If a tag is not found the whole
search is aborted and no item is selected.

\item{\ident{.group1Tag.group2Tag*aTag}}
Selects all children, \underline{direct or indirect}, with the tag {\it aTag} in
the group obtained by following the path {\it .group1Tag.group2Tag} from the root group.

\item{\ident{.group1Tag*group2Tag.aTag}}
Selects all \underline{direct} children with the tag {\it aTag} in
the group obtained by following the path {\it .group1Tag*group2Tag} from the root group.
The search proceed from the root group to the first direct child group in display
list order with tag {\it group1Tag}. Then it searches in display list order down the
hierearchy for the first group with tag {\it group2Tag} . Finally in this group, the
search ends by finding all direct children items (including groups) with tag {\it aTag}.
If a tag is not found the whole search is aborted and no item is selected.

\item{\ident{.group1Tag*group2Tag*aTag}}
Selects all items with the tag {\it aTag} in the hierarchy
of the group obtained by following the path {\it .group1Tag*group2Tag} from the root
group. The search proceed from the root group to the first direct child group in
display list order with tag {\it group1Tag}. Then it searches in display list order down
the hierearchy for the first group with tag {\it group2Tag} . Finally in this group, the
search ends by finding all direct children items (including groups) with tag {\it aTag}.
If a tag is not found the whole search is aborted and no item is selected.

\item{\ident{.group1Tag.group2Tag.}}
Selects all \underline{direct} children of the group obtained
by following the path {\it .group1Tag.group2Tag} from the root group. If a tag is not
found the whole search is aborted and no item is selected.

\item{\ident{.group1Tag.group2Tag*}}
Selects all items in the hierarchy of the group obtained
by following the path {\it .group1Tag.group2Tag} from the root group. If a tag is not
found the whole search is aborted and no item is selected.

\item{\ident{.groupId.aTag}}
Selects all \underline{direct} children with tag {\it aTag} of the group with id {\it groupId}.
If {\it groupId} is not found or is not a group id, the search is aborted and no item
is selected. This form together with the next is specially useful with cloned
items hierarchies where only the topmost group item is known after cloning. Using
pathTags it is now possible to make use of designs using components with named
sub-components. It is possible to clone a component and afterward to change the
behavior of named sub-components with pathTags of the form
{\it .componentId.subComponentName} or perhaps better {\it .componentId*subComponentName}.
Some care is needed in order to avoid sub-component name clash. Remember that the search
for tags proceed in \underline{display list order}, not in hierarchy order. In other more
technical words the search walks the item tree \underline{depth first} not breadth first.

\item{\ident{.groupId*aTag}}
Selects all items with tag {\it aTag} in the hierarchy of the
group with id {\it groupId}. If {\it groupId} is not found or is not a group id, the search
is aborted and no item is selected.

\item{\ident{.groupId.}}
Selects all \underline{direct} children of the group with id {\it groupId}. It is the only
way to get direct children of a group.

\item{\ident{.groupId*}}
Selects all items in the hierarchy of the group with id {\it groupId}.

\item{\ident{.}}
Selects all \underline{direct} children of the root group.

\item{\ident{*}}
Selects all items in the hierarchy (not counting the root group itself).

\item{\ident{.aTag}}
Selects all \underline{direct} children of the root group with the tag {\it aTag}.

\item{\ident{*aTag}}
Selects all items in the whole hierarchy (starting a the root group)
with the tag {\it aTag}. It is the same as using the simple tag {\it aTag}.

\end{itemize}


\section{Tags and bindings}
\concept{tagsAndBindings}
Tags are also very useful to associate scripts with events. The \cmdref{bind}
command is used to specify a script to be invoqued when an event sequence is
associated with a tag.

The event dispatch mecanism in TkZinc collects which tags are related to a given event and
then use the bindings established by \cmdref{bind} to activate the related scripts. Event
dispatching operates on three event sources: mouse events, keyboard events and internally
generated enter/leave events. Mouse events are dispatched to the item under the mouse
pointer, if any; keyboard events are dispatched to the focus item, if any; leave events
are dispatched to the item previously under the pointer, enter events to the item newly
under the pointer. Tags are collected from the item found.
 
Special tags are managed for items with fields or parts (e.g.\ a \objectref{track} has both, a
\objectref{tabular} has only \ident{fields} and a \objectref{rectangle} has none). They are built
from a tag or an id followed by a \verb+:+ followed by a (zero based) field index or by the
name of a part. Those tags can only be used in event bindings.

Here is the complete list of tags, either real or implicit, that are tried to find bindings.
They are listed in the order they are processed.
\begin{enumerate}
\item the implicit tag \verb+all+ (associated with all items),
\item the other tags (in some not reliable order),
\item the item id,
\item the implicit tags build from the tags and the current part name or field index, if any,,
\item the implicit tag build from the item id and the current part name or field index, if any.
\end{enumerate}

An exception is made for the \ident{Leave} event when dispatched to an item with parts
or fields. This is needed to process the exit of a field/part before the exit of the
corresponding item. In this case the order is shown by the following list.
\begin{enumerate}
\item the implicit tags build from the tags and the current part name or field index,
\item the implicit tag build from the item id and the current part name or field index,
\item the implicit tag \verb+all+,
\item the other tags,
\item the item id.
\end{enumerate}

Here are examples of possible bindings.

\begin{enumerate}
\item \verb+$zinc->bind($id, '<1>', \&acallback);+\\
  will call \verb+acallback+ if mouse button 1 is clicked anywhere over item \verb+$id+;
\item \verb+$zinc->bind('selected', '<1>', \&acallback);+\\
  the click must be anywhere over any item associated with the \verb+selected+ tag;
\item \verb+$zinc->bind('foo:0', '<1>', \&acallback);+\\
  the click must occurs over field 0 of an item with tag \verb+foo+;
\item \verb+$zinc->bind("$id:3", '<1>', \&acallback);+\\
  the click must be over field 3 of item \verb+$id+, and the field must exists in the item;
\item \verb+$zinc->bind("$id:speedvector", '<1>', \&acallback);+\\
  the click must be over a part named \verb+speedvector+ (item track) in item \verb+$id+,
  the part must exists in the
item.%$
\end{enumerate}


\section{Text indices}
\concept{indices}

Indices are used to specify a character position in textual items such as the \objectref{text}
item. Indices are accepted as parameters by commands managing text: \cmdref{cursor},
\cmdref{index}, \cmdref{insert}, \cmdref{dchars} and \cmdref{select}.

\begin{itemize}
\item{\ident{number}} This should be an integer giving the character position within the
  text of the item. The indices are zero based. A number less than zero is treated as zero
  and a number greater than the text length is rounded to the text length. A number equal to
  the text length refers to the position past the last character in the text.
\item{\ident{end}} Refers to the position past the last character in the text. This is the
  same as specifying a number equal to the text length.
\item{\ident{insert}} Refers to the character just before the insertion cursor in the
  item.
\item{\ident{sel.first}} Refers to the first character of the selection in the item. If
  the selection is not in the item, this form returns an error.
\item{\ident{sel.last}} Refers to the last character of the selection in the item. If the
  selection is not in the item, this form returns an error.
\item{\ident{@x,y}} Refers to the character at the point given by {\it x} and {\it y},
  {\it x} and {\it y} are interpreted as window coordinates. If the point lies outside
  of the area corvered by the item, they refer to the first or last character in the line
  that is closest to the point.
\item{\ident{bol}} refers to the beginning of line
\item{\ident{eol}} refers to the end of line
\item{\ident{bow}} refers to the beginning of word
\item{\ident{eow}} refers to the end of word
\item{\ident{up}}  refers to previous line
\item{\ident{down}} refers to next line
\end{itemize}


%%
%%
%% C h a p t e r :   W i d g e t   c o m m a n d s
%%
%%
\chapter{Widget commands}
\concept{commands}

In this chapter, we first list all commands by categories, then we details each command, by alphabetical order.

\section{Categories of commands}
\concept{commandsCategories}

\begin{itemize}

\item{Items creation and deletion} : \cmdref{add} \cmdref{becomes}  \cmdref{clone} \cmdref{remove}

\item{Accessing options and attributes} : \cmdref{chggroup} \cmdref{configure} 
\cmdref{coords} \cmdref{gettags} \cmdref{group} \cmdref{itemcget} \cmdref{itemconfigure}    

\item{Accessing field attributes of track, waypoint and tabular} :  \cmdref{currentpart}
\cmdref{hasfields} \cmdref{itemcget} \cmdref{itemconfigure}  \cmdref{numparts}

\item{Transformations} :  \cmdref{coords} \cmdref{rotate}  \cmdref{scale} \cmdref{skew} \cmdref{tapply}
\cmdref{tcompose} \cmdref{tdelete} \cmdref{tget} \cmdref{transform} \cmdref{translate} \cmdref{treset}
\cmdref{tsave} \cmdref{tset}

\item{Groups, Display list and Priorities} : \cmdref{chggroup} \cmdref{find}('ancestors') \cmdref{group} \cmdref{lower}
\cmdref{raise} 

\item{Tag management} : \cmdref{addtag} \cmdref{dtag} \cmdref{find} \cmdref{gettags} \cmdref{hastag}

\item{Text management (text item and text fields} : \cmdref{cursor} \cmdref{dchars} \cmdref{focus}
\cmdref{index} \cmdref{insert} \cmdref{select}

\item{Bindings} : \cmdref{bind} \cmdref{focus}

\item{Coordinates} : \cmdref{anchorxy} \cmdref{bbox} \cmdref{coords} \cmdref{contour}
\cmdref{fit} \cmdref{hasanchors} \cmdref{smooth} \cmdref{transform} \cmdref{vertexat}

\item{Named resources} : \cmdref{gname} \cmdref{gdelete} \cmdref{tsave}

\item{Miscellaneous} : \cmdref{monitor} \cmdref{postscript} \cmdref{type} \cmdref{collapsemotions}

\end{itemize}


\section{Commands by alphabetical order}
\concept{commandsAlphabetically}

The available commands are listed in alphabetical order.

The command set for the TkZinc widget is much inspired by the Canvas command set. Someone
comfortable with the Canvas should not have much trouble using the TkZinc's commands.
Eventually, the command set will be a superset of the Canvas command set. Anyway
some commands depart radically from the equivalent in the Canvas. For example, the user
should be aware that \cmdref{scale} and \cmdref{translate} do not behave in the same
way at all; \cmdref{find} and \cmdref{addtag} have been extended to support groups,
etc. So use the available knowledge with some care.

In the Perl/Tk version, the commands returning a list, return a Perl array (not a
reference) and all list parameters are given as array references.

\vspace{.5cm}
\zinccmd{add}{?type group? ?initargs? ?option value? ... ?option value?}

{\tt\large @types = \$zinc->{\bf add}();}\\
{\tt\large \$id = \$zinc->{\bf add}(type, group);}\\
{\tt\large \$id = \$zinc->{\bf add}(type, group, initargs);}\\
{\tt\large \$id = \$zinc->{\bf add}(type, group, initargs, option=>value, ..., ?option=>value?);}

\begin{blockindent}
  This command is used to create new items in a TkZinc widget. It can be called with no
  parameters to return the list of all item types currently known by TkZinc. It can also be
  called with a valid item type as first parameter and a group item as second parameter to
  create a new item of this type in the given group.

  After these first two parameters come some item type specific arguments.  Here is
  detailed description of these arguments by type:
  \begin{description}
  \item{\objectref{arc}}\\
    The arc type expects a list of four floating point numbers \verb+xo yo xc yc+,
    giving the coordinates of the origin and the corner of the enclosing rectangle.
    The origin should be the top left vertex of the enclosing rectangle and the
    corner the bottom right vertex of the rectangle.
  \item{\objectref{curve}}\\
    The curve type expects either a flat list or a list of lists. In the first case, the flat list
    must be a list of floating point numbers \verb+x0 y0 x1 y1 ... xn yn+,
    giving the coordinates of the curve vertices. The number of values should be
    even (or the last value will be discarded) but the list can be empty to build
    an empty invisible curve. In the second case, the list must contain lists of 2 or 3
    elements: xi, yi and and an optionnal point type. Currently, the only available point type
    is 'c' for a cubic bezier control point. For example in Perl/Tk, the following list
    is an example of 2 beziers segments with a straight segment in-between:

    \begin{verbatim}
( [x0, y0], [x1, y1, 'c'], [x2, y2, 'c'], [x3, y3], [x4, y4, 'c'], [x5, y5] )
    \end{verbatim}

    As there is only on control point, \code{[x4, y4, 'c']} , for the second cubic bezier,
    the omitted second control point will be defaulted to the same point.
    A curve can be defined later with the \cmdref{contour}
    or \cmdref{coords} commands. As a side effect of the curve behavior, a one vertex
    curve is essentially the same as an empty curve, it only waste some more memory.
  \item{\objectref{rectangle}}\\
    The rectangle type expects a list of four floating point numbers \verb+xo yo xc yc+,
    giving the coordinates of the origin and the corner of the rectangle.
  \item{\objectref{triangles}}\\
    The triangles type expects a list of at least 6 floating point numbers
    \verb+x0 y0 x1 y1+ \verb+... xn yn+, giving the coordinates of the vertices of the triangles
    composing this item. The triangles layout is defined by the attribute
    \attributeref{triangles}{fan}. If \attributeref{triangles}{fan} is true, the triangles
    are arranged in a fan with the first point being the center and the other
    points defining the perimeter.  If \attributeref{triangles}{fan} is false, the
    triangles are arranged in a strip.
  \item{\objectref{tabular}, \objectref{track}, \objectref{waypoint}}\\
    These types expect the number of fields they will manage in the label or
    tabular form. This number must be greater or equal to zero.
  \item{\objectref{group}, \objectref{icon}, \objectref{map}, \objectref{reticle}, \objectref{text}, \objectref{window}}\\
    These types do not expect type specific arguments.
  \end{description}
  
  Following the creation args the command accept any number of
  attributes\ -\ values pairs to configure the newly created item.
  All the configurable item type attributes are valid in this context. The
  command returns the item id.
\end{blockindent}


\zinccmd{addtag}{tag searchSpec ?arg arg ...?}

{\tt\large \$zinc->{\bf addtag}(tag, searchSpec);}

\begin{blockindent}
  This command add the given tag to all items matching the
  search specification. If the tag is already present on some item,
  nothing is done for that item. The command has no effect if no
  item satisfy the given criteria. The command returns an empty
  string.

  Many commands take a group as a starting point for the search. If no
  group is given, the root group is assumed. In any cases, the starting
  group will not be reported in the search result. This means that the
  root group will never be reported in a search and that tags cannot be
  attached to it except in specifying its id.
  
  The search specification and the associated arguments can
  take the following forms:

  \begin{itemize}
  \item{\tt\large
        pathname {\bf addtag} tag above tagOrId \\
        \$zinc->{\bf addtag}(tag, 'above', tagOrId);}
  
    Selects the item just above the one given by {\tt tagOrId}. If
    {\tt tagOrId} names more than one item, the topmost of these
    items in the display list will be used. If {\tt tagOrId} does
    not refer to any item then nothing happen.

  \item{\tt\large
        pathname {\bf addtag} tag all ?inGroup? ?recursive?\\
        \$zinc->{\bf addtag}(tag, 'all', ?inGroup?, ?recursive?);}
    
    This form is no more allowed since version 3.2.6 of TkZinc.
    Please use a form '"withtag", "all"' as documented below.

  \item{\tt\large
        pathname {\bf addtag} tag atpriority priority ?tagOrId?\\
        \$zinc->{\bf addtag}(tag, 'atpriority', priority, ?tagOrId?);}
        
    Selects all the items at the given priority. The tagOrId optional
    parameter can be specified to restrict the search. It specifies a
    group to start with instead of the root group and it can be used to
    control if the search should be recursive or not (see \conceptref{PathTags}{pathTags} for
    more on this subject).

  \item{\tt\large
        pathname {\bf addtag} tag ancestors tagOrId ?tagOrId2?\\
        \$zinc->{\bf addtag}(tag, 'ancestors', tagOrId, ?tagOrId2?);}

        Selects all ancestors (i.e.\ parent groups) of tagOrId. If
        {\tt tagOrId} names more than one item, the first, (or the topmost)
        of these items in the display list will be used. If ?tagOrId2? is specified,
        only parent groups with this tag are selected.

  \item{\tt\large
        pathname {\bf addtag} tag below tagOrId\\ 
        \$zinc->{\bf addtag}(tag, 'below', tagOrId);}

    Selects the item just below the one given by {\tt tagOrId}. If
    {\tt tagOrId} names more than one item, the lowest of these
    items in the display list will be used. If {\tt tagOrId} does
    not refer to any item then nothing happen.

  \item{\tt\large
        pathname {\bf addtag} tag closest x y ?halo? ?startItem?, ?recursive?\\ 
        \$zinc->{\bf addtag}(tag, 'closest', x, y, ?halo?, ?startItem?, ?recursive?);}

    Selects the item closest to the point {\tt x - y}. Any item overlapping
    the point is considered as closest and the topmost is selected. If {\tt halo}
    is given, it defines the size of the point {\tt x - y}. {\tt halo} must
    be a non negative integer. If {\tt start} is specified, it must be
    an item tag or id. If it names a group and this group is not atomic,
    the search starts with the first item of this group.
    If it names a non group item or an atomic group (for a tag, the lowest
    item with the tag is considered), the search starts with the item
    below {\tt start} instead of the first item in the display
    order. If {\tt startItem} does not name a valid item, it is ignored.
    If {\tt recursive} is false the search is limited to
    the starting group. If set to true, not specified or ``override'',
    the search proceed from the starting group down the hierarchy
    rooted at this group. ``override'' forces the search to explore
    atomic groups and report the most specific item instead of the
    group itself.

  \item{\tt\large
        pathname {\bf addtag} tag enclosed xo yo xc yc ?inGroup? ?recursive?\\ 
        \$zinc->{\bf addtag}(tag, 'enclosed', xo, yo, xc, yc, ?inGroup?, ?recursive?);}

    Selects all the items completely enclosed in the rectangle whose
    origin is at {\tt xo - yo} and corner at {\tt xc - yc}. {\tt xc}
    must be no greater than {\tt xo} and {\tt yo} must be no greater
    than {\tt yc}. All coordinates must be integers. {\tt inGroup} specifies
    a group to start with instead of the root group.
    If {\tt recursive} is false the search is limited to
    the starting group. If set to true, not specified or ``override'',
    the search proceed from the starting group down the hierarchy
    rooted at this group. ``override'' forces the search to explore
    atomic groups and report the most specific item instead of the
    group itself.

    It may be necessary to update the TkZinc internal geometry with a call
    to {\tt update} if the current state is not stable (i.e before calling
    the main loop or in a callback after modifying the transform or doing
    something else affecting the geometry of items).

  \item{\tt\large
        pathname {\bf addtag} tag overlapping xo yo xc yc ?inGroup? ?recursive?\\ 
        \$zinc->{\bf addtag}(tag, 'overlapping', xo, yo, xc, yc, ?inGroup?, ?recursive?);}

    Selects all the items that overlaps or are enclosed in the rectangle
    whose origin is at {\tt xo - yo} and corner at {\tt xc - yc}. {\tt xc}
    must be no greater than {\tt xo} and {\tt yo} must be no greater than
    {\tt yc}. All coordinates must be integers. {\tt inGroup} specifies
    a group to start with instead of the root group.
    If {\tt recursive} is false, the search is limited to the starting
    group. If set to true, not specified or ``override'',
    the search proceed from the starting group down the hierarchy
    rooted at this group. ``override'' forces the search to explore
    atomic groups and report the most specific item instead of the
    group itself.

    See also the {\tt enclosed} variant above for a discussion on updating the geometry.    

  \item{\tt\large
        pathname {\bf addtag} tag withtag tagOrId\\ 
        \$zinc->{\bf addtag}(tag, 'withtag', tagOrId);}
    
    Selects all the items given by {\tt tagOrId}.

  \item{\tt\large
        pathname {\bf addtag} tag withtype type ?tagOrId?\\ 
        \$zinc->{\bf addtag}(tag, 'withtype', type, ?tagOrId?);}
    
    Selects all the items of type {\tt type}.  The tagOrId optional
    parameter can be specified to restrict the search. It specifies a
    group to start with instead of the root group and it can be used to
    control if the search should be recursive or not (see \conceptref{PathTags}{pathTags} for
    more on this subject).
  \end{itemize}
\end{blockindent}


\zinccmd{anchorxy}{tagOrId anchor}

{\tt\large (\$x, \$y) = \$zinc->{\bf anchorxy}(tagOrId, anchor);}

\begin{blockindent}
  Returns the \emph{window coordinates} of an item anchor. If no item is named by {\tt tagOrId}
  or if the item doesn't support anchors, an error is raised. If more than one item match
  {\tt tagOrId}, the topmost in display list order is used.
  \begin{verbatim}
  # for example to get the lower right corner of a text item
  ($x ,$y) = $zinc->anchorxy('myTextTag', 'se');
  \end{verbatim}

\end{blockindent}


\zinccmd{bbox}{?-field fieldNo? ?-label? tagOrId ?tagOrId ...?}

{\tt\large (\$xo, \$yo, \$xc, \$yc) = \\
\$zinc->{\bf bbox}(?-field fieldNo? ?-label? tagOrId, ?tagOrId ...?);}

\begin{blockindent}
  Returns a list of 4 numbers describing the \emph{window coordinates} of the origin
  and corner of a rectangle bounding all the items named by the {\tt tagOrId}
  arguments. 
  If no items are named by {\tt tagOrId} or if the matching items have an empty bounding
  box, an empty string is returned.
  The {\tt -field} and {\tt -label} options can be used to query the bounding box
  of an item's field or an item's label. These two options are mutually exclusives.
  When one of these options is specified, the bbox command is applied to the first
  item selected by the tagOrId arguments. If no labelformat has been set for the item,
  bbox will return an empty array.
\end{blockindent}


\zinccmd{becomes}{}

{\tt\large \$zinc->{\bf becomes}();}

\begin{blockindent}
  Not yet implemented.
\end{blockindent}


\zinccmd{bind}{tagOrId ?part? ?sequence? ?command?}

{\tt\large @bindings = \$zinc->{\bf bind}(tagOrId, ?part?);}\\
{\tt\large @binding = \$zinc->{\bf bind}(tagOrId, ?fpart?, sequence);}\\
{\tt\large \$zinc->{\bf bind}(tagOrId, ?part?, sequence, '');}\\
{\tt\large \$zinc->{\bf bind}(tagOrId, ?part?, sequence, command);}

\begin{blockindent}
  This command associates {\tt command} with the item tag, item id, part tag {\tt
  tagOrId}. If an event sequence matching {\tt sequence} occurs for an item, or an item
  part, the command will be invoked. If all parameters are specified a new binding
  between {\tt sequence} and {\tt command} is established, overriding any existing binding
  for the sequence. If the first character of {\tt command} is ``+'', then {\tt command}
  augments the existing binding instead of replacing it. In this case the command returns
  an empty string. If the {\tt command} parameter is omitted, the command returns the {\tt
  command} associated with {\tt tagOrId} and {\tt sequence} or an error is raised if there
  is no such binding. If only {\tt tagOrId} is specified the command returns a list of all
  the sequences for which there are bindings for {\tt tagOrId}.
  
  This widget command is similar to the Tk \ident{bind} command except that it operates on
  TkZinc items instead of widgets. Another difference with the \ident{bind} command
  is that only mouse and keyboard related events can be specified (such as \ident{Enter},
  \ident{Leave}, \ident{ButtonPress}, \ident{ButtonRelease}, \ident{Motion},
  \ident{KeyPress}, \ident{KeyRelease}). The \ident{bind} manual page is the most
  accurate place to look for a definition of {\tt sequence} and {\tt command} and for a
  general understanding of how the binding mecanism works.

  The handling of events in the widget is done with respect to the current item and when
  applicable the current item part (see \conceptref{Item ids, tags and indices}{tagOrId} for a
  discussion of the \ident{current} tag and the special tags used in
  bindings). \ident{Enter} and \ident{Leave} events are trigerred for an item when it
  becomes or cease to be the current item. Mouse related events are reported with respect
  to the current item. Keyboard related events are reported with respect to the focus item
  if it exists (See the \cmdref{focus} command for more on this).

  It is possible that several bindings match a particular event sequence. When this
  occurs, all matching bindings are triggered. The order of invocation is as follow: the
  binding associated with the tag \ident{all} is invoked first, followed by the bindings
  associated with the item tags in order, followed by the binding associated with the item
  id, followed by bindings associated with the item part tags if relevant, followed by
  the binding associated with the item part if relevant. If there are more than one
  binding for a single tag or id, only the most specific is triggered.
  
  Two syntaxes are available for addressing item parts (for items having part ie. 
  \objectref{track} \objectref{waypoint} and \objectref{tabular}): either an Id 
  of the following form: {\tt id:part} or by using the optionnal {\tt part} argument.
  
  If bindings have been registered for the widget window using the \ident{bind} command,
  they are invoked in addition to bindings registered for the items using this widget
  command. The bindings for items will be invoked before the bindings for the window.
\end{blockindent}


\zinccmd{cget}{option}

{\tt\large \$val = \$zinc->{\bf cget}(option);}

\begin{blockindent}
  Returns the current value of the widget option given by {\tt option}.
  {\tt option} may be any of the options described in the
  chapter \conceptref{Widget options}{options}.
\end{blockindent}


\zinccmd{chggroup}{tagOrId group ?adjustTransform?}

{\tt\large \$zinc->{\bf chggroup}(tagOrId, group, ?adjustTransform.?);}

\begin{blockindent} Move the item described by {\tt tagOrId} in the group described by
{\tt group}. If {\tt tagOrId} or {\tt group} describes more than one item, the first in
display list order will be used. If {\tt adjustTransform} is specified, it will be
interpreted as a boolean. A true value will lead to an adjustment of the item transform in
order to maintain an identical display rendering of the item regardless of its new
position in the display hierarchy. If {\tt adjustTransform} is omitted, it defaults to
false.
\end{blockindent}


\zinccmd{clone}{tagOrId ?attr value ...?}

{\tt\large \$id = \$zinc->{\bf clone}(tagOrId, ?attr=>value, ...?);}

\begin{blockindent}
  Create an exact copy of all the items described by {\tt tagOrId}. The copy goes
  recursively for group items (deep copy). After copying the pairs {\tt attr value} are
  used, if any, to reconfigure the items. Any attribute that as no meaning in the context
  of some item is ignored. The items down the hierarchy of group items are not concerned
  by the configuration phase. The command returns the list of cloned items id in creation
  order (display list order of the models). No item id will be returned for items cloned
  in the hierarchy of cloned groups.

\end{blockindent}


\zinccmd{collapsemotions}{?boolean?}

{\tt\large \$current = \$zinc->{\bf collapsemotions}(?boolean?);}

\begin{blockindent} This command controls how the motion events are handled by
  the Tk event loop. Pass a boolean true to ask for compression of consecutive
  motion events accumulated in the event queue. Pass a boolean false to suspend
  the compression process. The change affects all the windows opened by the
  application on the same display, so use with care. The command returns the
  previous state as a boolean. If the parameter is omitted the command simply
  returns the current state.
\end{blockindent}


\zinccmd{configure}{?option? ?value? ?option value ...?}

{\tt\large @options = \$zinc->{\bf configure}();}\\
{\tt\large @option = \$zinc->{\bf configure}(option);}\\
{\tt\large \$zinc->{\bf configure}(option=>value, ?option=>value,...?);}

\begin{blockindent}
  Query or modify the options of the widget. If no {\tt option} is given, returns a list
  describing all the supported options in the standard format for Tk options (see the
  chapter \conceptref{Widget options}{options} for a list of available options). If an
  {\tt option} is specified without a {\tt value}, the command returns a list describing
  the named option in the standard Tk format. If some {\tt option - value} pairs are
  given, then the corresponding options are changed and the command returns an empty
  string.
\end{blockindent}


\zinccmd{contour}{tagOrId ?operatorSpec coordListOrTagOrId?}

{\tt\large \$contourNum = \$zinc->{\bf contour}(tagOrId);}\\
{\tt\large \$contourNum = \$zinc->{\bf contour}(tagOrId, operatorAndFlag, coordListOrTagOrId);}

\begin{blockindent}
  Manipulate contours on items that can handle multiples geometric contours. Currently
  only curve items can do this.

  {\tt tagOrId} specifies the item whose contours will be modified. If {\tt tagOrId}
  describes more than one item, the first in display list order will be used.
  
  If the command is invoked with only the tagOrId parameter, it returns the number of
  contours composing the item. In fact it always returns the number of contours after
  a command has been conducted, it happens that with this reduced form nothing is done
  except returning the number of contours.

  On items that do not support multiple contours, the returned value is 0 or 1 depending
  on the item having a contour or not. \objectref{track}, \objectref{waypoint},
  \objectref{reticle}, \objectref{group},  \objectref{map}, and yield 0
  while \objectref{rectangle}, \objectref{tabular}, \objectref{arc}, \objectref{icon},
  \objectref{triangles}, \objectref{text}, and \objectref{window} yield 1.

  {\tt coordListOrTagOrId} specifies a list of coordinates (either a flat list of X and Y, or
  a list similar to the one allowed for a curve item) or an item describing a
  contour. If a flat list is specified it should contain an even number of floating point values
  specifying the contour vertices X and Y in order. If a tag or an id is specified, it is
  should be from one of these classes: arc, curve, icon, rectangle, tabular, text,
  window. The external shape of the item will be used as the contour. If {\tt
  coordListOrTagOrId} describes more than one item, the first in display list order will
  be used.

  {\tt operatorAndFlag} specifies the operation that will be carried. This can be:
  
  \begin{description}
  \item{\ident{add}} to extend the surface of the curve. In this case there is a mandatory
  flag describing the way the contour will be added. It may take the following values:
  \begin{description}
        \item{0} the list of points is taken unchanged. In this case, the {\tt coordListOrTagOrId}
        parameter cannot be a tag and must be an explicit list of points.
        \item{1} the list of points is reverted, if needed, so that the points defines
                 a {\bf counterclockwise} contour.
        \item{-1} the list of points is reverted,if needed, so that the points  defines
                 a {\bf clockwise} contour.
  \end{description}
  The exact graphical effect depends on the value of the \attributeref{curve}{fillrule}
  as described in the \attrtyperef{fillrule} type description.
  \item{\ident{remove}} to remove an existing contour
  \end{description}

  The following operations are no more available: \ident{diff},
  \ident{inter}, \ident{union}, \ident{xor}; 
  An error is generated if the items are not of a correct type or if the coordinate list
  is malformed.

\end{blockindent}


\zinccmd{coords}{tagOrId ?add/remove? ?contour? ?index? ?coordList?}

{\tt\large \$zinc->{\bf coords}(tagOrId, ?add/remove?, ?contour?, ?index?, ?coordList?);}

\begin{blockindent}
  Query or changes the coordinates of the item described by {\tt tagOrId}. If the
  item is a group, query or set the translation applied to the group. If {\tt
  tagOrId} describes more than one item, the first in display list order is used. The
  optional {\tt contour} gives the contour, if available, that should be operated. The
  default contour is 0. The optional {\tt index} gives the vertex index that should be
  operated in the given contour. The optional {\tt coordList} is either a flat list (of
  one or more vertices described as X, Y floating point values) or a list of lists
  [X Y ?type?] such as described in the curve item. The coordinates will be used to
  replace or add coordinates to the current contour.

  Almost all items can be manipulated by this command, the map item is the only current
  exception. The effect of the command can be quite different depending on the item. For
  icons, texts, windows, tabulars, the coordinates of the anchor can be modified or
  read. For groups, the coordinates of the origin of the transformation can be set or
  read. For tracks and waypoints, the coordinates of the current position can be set or
  read. For tracks setting the current position this way will make the previous position
  shift into the history. For reticles, the coordinates of the center can be set or
  read. For arcs and rectangles, the coordinates of the origin and corner can be set or
  read. For curves and triangles, coordinates of all points defining the item can be set or
  read. For all items that do not support multiple contours (currently all except curves)
  the {\tt contour} parameter should be omitted or specified as zero.

  When {\tt coords} is used to get potentially more than one point, it returns {\bf always}
  a list of lists. Each sub list contains X, Y, and 'c' if the point is a
  bezier control point.

  When {\tt coords} is used to get exactly one point (either because it is used to
  get the nth point of an item or because the item always has exactly one point (e.g.
  the item is a group, track, waypoint, map, or reticle)), it returns
  a flat list of 2 (or may be 3 for control points of curve items) values.

  The optional parameters must be combined to produce a given behavior. Here are the
  various form recognized by the command:

  \begin{itemize}
  \item{\tt\large
        pathname {\bf coords} tagOrId contourIndex\\
        @coords = \$zinc->{\bf coords}(tagOrId, contourIndex);}
        
    Get all coordinates of contour at contourIndex. All items can answer if contourIndex
    is zero. Curves can handle other contours.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId contourIndex coordList\\
        \$zinc->{\bf coords}(tagOrId, contourIndex, coordList);}
  
    Set all coordinates of contour at contourIndex. All items can do it if contourIndex is
    zero. Curves can handle other contours. For groups, icons, texts, windows, tabulars,
    reticles, tracks, waypoints, only the first vertex will be used. For rectangles and
    arcs, only the first two vertices will be used. Curves can handle any number of vertices.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId contourIndex coordIndex\\
        (\$x, \$y) = \$zinc->{\bf coords}(tagOrId, contourIndex, coordIndex);}
  
    Get coordinate at coordIndex in contour at contourIndex. All items can answer if
    contourIndex is zero. Curves can handle other contours. For groups, icons, texts,
    windows, tabulars, reticles, tracks, waypoints, coordIndex must be zero. For
    rectangles and arcs, coordIndex must zero or one.
    
  \item{\tt\large
         pathname {\bf coords} tagOrId contourIndex coordIndex coordList\\      
        \$zinc->{\bf coords}(tagOrId, contourIndex, coordIndex, coordList);}
  
    Set coordinate at coordIndex in contour at contourIndex. All items can do it if
    contourIndex is zero. Curves can handle other contours. For groups, icons, texts,
    windows, tabulars, reticles, tracks, waypoints, coordIndex must be zero. For
    rectangles and arcs, coordIndex must zero or one.  {\bf WARNING:} coordList must be a
    list of one list describing x, y and optionnaly the point type.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId remove contourIndex coordIndex\\
        \$zinc->{\bf coords}(tagOrId, 'remove', contourIndex, coordIndex);}
  
    Remove coordinate at coordIndex in contour at contourIndex. Can only be handled by
    curves. Only curves can handle contourIndex other than zero.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId add contourIndex coordList\\
        \$zinc->{\bf coords}(tagOrId, 'add', contourIndex, coordList);}
    
    Add coordinates at the end of contour at contourIndex. Can only be handled by curves.
    Only curves can handle contourIndex other than zero.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId add contourIndex coordIndex coordList\\
        \$zinc->{\bf coords}(tagOrId, 'add', contourIndex, coordIndex, coordList);}
  
    Add coordinates at coordIndex in contour at contourIndex. Can only be handled by
    curves. Only curves can handle contourIndex other than zero.
  \end{itemize}
  
  And the slightly abbreviated forms:
  
  \begin{itemize}
  \item{\tt\large
        pathname {\bf coords} tagOrId\\
        @coords = \$zinc->{\bf coords}(tagOrId);}

  Get all coordinates of contour 0. See first form.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId coordList\\      
        \$zinc->{\bf coords}(tagOrId, coordList);}
  
    Set all coordinates of contour 0. See second form.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId remove coordIndex\\
        \$zinc->{\bf coords}(tagOrId, 'remove', coordIndex);}
      
    Remove coordinate at coordIndex in contour 0. See fifth form.
    
  \item{\tt\large
        pathname {\bf coords} tagOrId add coordList\\
        \$zinc->{\bf coords}(tagOrId, 'add', coordList);}
  
    Add coordinates at the end of contour 0. See sixth form.
  \end{itemize}
\end{blockindent}


\zinccmd{currentpart}{}

{\tt\large \$num = \$zinc->{\bf currentpart}();}

\begin{blockindent}
  Returns a string specifying the item part that has the pointer. If the current item
  doesn't have parts or if the pointer is not over an item (no item has the
  \ident{current} tag) the command returns {\tt ""}. The string can be either an integer
  describing a field index or the name of a special part of the item. Consult each item
  description to find out which part names can be reported.
\end{blockindent}


\zinccmd{cursor}{tagOrId index}

{\tt\large \$zinc->{\bf cursor}(tagOrId, index);}

\begin{blockindent}
  Set the position of the insertion cursor for the items described by {\tt tagOrId} to be
  just before the character at {\tt index}. If some of the items described by {\tt
  tagOrId} don't support an insertion cursor, the command doesn't change them. The
  possible values for {\tt index} are described in the section \conceptref{Text indices}
  {indices}. The command returns an empty string.
\end{blockindent}


\zinccmd{dchars}{tagOrId first ?last?}

{\tt\large \$zinc->{\bf dchars}(tagOrId, first);}\\
{\tt\large \$zinc->{\bf dchars}(tagOrId, first, last);}

\begin{blockindent}
  Delete the character range defined by the parameters {\tt first} and {\tt last}
  inclusive in all the items described by {\tt tagOrId}. Items that doesn't support text
  indexing are skipped by the command. If {\tt last} is not specified, the command
  deletes the character located at {\tt first}. The command returns an empty string. {\tt
  first} and {\tt last} are indices as described in \conceptref{Text indices}{indices}.
\end{blockindent}


\zinccmd{dtag}{tagOrId ?tagToDelete?}

{\tt\large \$zinc->{\bf dtag}(tagOrId);}\\
{\tt\large \$zinc->{\bf dtag}(tagOrId, tagToDelete);}

\begin{blockindent}
  Delete the tag {\tt tagToDelete} from the list of tags associated with each item named
  by {\tt tagOrId}. If an item doesn't have the tag then it is leaved unaffected. If {\tt
  tagToDelete} is omitted, {\tt tagOrId} is used instead. The command returns an empty
  string as result.
\end{blockindent}


\zinccmd{find}{searchCommand ?arg arg ...?}

{\tt\large @items = \$zinc->{\bf find}(searchCommand, ?arg?, ...);}

\begin{blockindent}
  This command returns the list of all items selected by {\tt searchCommand} and the {\tt
  args}. See the \cmdref{addtag} command for an explanation of {\tt searchCommand} and the
  various {\tt args}. The items are sorted in drawing order, topmost first. For example:\\
  \begin{verbatim}
  # to get the item under the mouse cursor:
  $item = $zinc->find('withtag', 'current');

  # to get the closest item of a point:
  $closest = $zinc->find('closest', $x, $y);

  # to get direct children of an atomic group with a pathTag:
  @children = $zinc->find('withtag', ".atomicGroup.");

	# to get all groups recursively contained in a group
	@groups = $zinc->find('withtype', 'group', ".aGroup*");
  \end{verbatim}

  As detailled in \cmdref{addtag} command the following searchCommands are possible:
  \begin{itemize}
        \item{\tt\large
                pathname {\bf find} above tagOrId \\
                \$zinc->{\bf find}('above', tagOrId);}
        \item{\tt\large
                pathname {\bf find} atpriority priority ?tagOrId?\\
                \$zinc->{\bf find}('atpriority', priority, ?tagOrId?);}
        \item{\tt\large
                pathname {\bf find} ancestors tagOrId ?tagOrId2?\\
                \$zinc->{\bf find}('ancestors', tagOrId, ?tagOrId2?);}
        \item{\tt\large
                pathname {\bf find} below tagOrId\\ 
                \$zinc->{\bf find}('below', tagOrId);}
        \item{\tt\large
                pathname {\bf find} closest x y ?halo? ?startItem?, ?recursive?\\ 
                \$zinc->{\bf find}('closest', x, y, ?halo?, ?startItem?, ?recursive?);}
        \item{\tt\large
                pathname {\bf find} enclosed xo yo xc yc ?inGroup? ?recursive?\\ 
                \$zinc->{\bf find}('enclosed', xo, yo, xc, yc, ?inGroup?, ?recursive?);}
        \item{\tt\large
                pathname {\bf find} overlapping xo yo xc yc ?inGroup? ?recursive?\\ 
                \$zinc->{\bf find}('overlapping', xo, yo, xc, yc, ?inGroup?, ?recursive?);}
        \item{\tt\large
                pathname {\bf find} withtag tagOrId\\ 
                \$zinc->{\bf find}('withtag', tagOrId);}
        \item{\tt\large
                pathname {\bf find} withtype type ?tagOrId?\\ 
                \$zinc->{\bf find}('withtype', type, ?tagOrId?);}
  \end{itemize}
\end{blockindent}


\zinccmd{fit}{coordList error}

{\tt\large @controls = \$zinc->{\bf fit}(coordList, error);}

\begin{blockindent}
  This command fits a sequence of Bezier segments on the curve described by the vertices
  in {\tt coordList} and returns a list of lists describing the points and control points
  for the generated segments. All the points on the fitted segments will be within {\tt error}
  distance from the given curve.  {\tt coordList} should be either a flat list of an even
  number of coordinates in x, y order or a list of lists of point coordinates X, Y.
  The returned list can be directly used to create or change a curve item contour.
\end{blockindent}


\zinccmd{focus}{?tagOrId? ?itemPart?}

{\tt\large (\$item, \$part) = \$zinc->{\bf focus}();}\\
{\tt\large \$zinc->{\bf focus}(tagOrId, ?itemPart?);}

\begin{blockindent}
  Set the keyboard focus to the item described by {\tt tagOrId}, and to
  its {\tt itemPart} if the item has parts. If {\tt tagOrId} describes
  more than one item, the first item in display list order that accept the focus is
  used. If no such item exists, the command has no effect. If {\tt tagOrId} is an empty
  string the focus is reset and no item has the focus. If {\tt tagOrId} is not specified,
  the command returns a list of two elements. The first is the id of the item with the focus
  or an empty string if no item has the focus. The second is the item part or an empty
  string if not appliable.

  When the focus has been set to an item that support an insertion cursor, the item will
  display its cursor and the keyboard events will be directed to that item.

  The widget receive keyboard events only if it has the window focus. It may be necessary
  to use the Tk \ident{focus} command to force the focus to the widget window.

\end{blockindent}


\zinccmd{gdelete}{gradientName}

{\tt\large \$zinc->{\bf gdelete}('fading');}

\begin{blockindent}
  This command breaks the binding between the given gradient name and the named
  gradient. When the gradient will be no longer used it will be deallocated.
\end{blockindent}


\zinccmd{gettags}{tagOrId}

{\tt\large @tags = \$zinc->{\bf gettags}(tagOrId);}

\begin{blockindent}
  This command returns the list of all the tags associated with the item specified by {\tt
  tagOrId}. If more than one item is named by {\tt tagOrId}, then the topmost in display
  list order is used to return the result. If no item is named by {\tt tagOrId}, then the
  empty list is returned.
\end{blockindent}


\zinccmd{gname}{?gradientDesc? gradientName}

{\tt\large \$zinc->{\bf gname}('black:100|white:0/0', 'fading');}\\
{\tt\large \$exist = \$zinc->{\bf gname}('nameOrGradient');}

\begin{blockindent}
  This command sets a name binding between the given gradient description and the given
  name. The name can be used in the same way the gradient description would be. The
  gradient will not be deallocated until the \cmdref{gdelete} command is invoqued on the
  name (and no item use the gradient). This feature can be a big performance gain when
  using many gradients in an animation, the name acts here as a caching mecanism.

  When gname is called with only one argument, it returns iehter false or the
  name of a named gradient if the argument is either a named gradient or the name
  of a named gradient.
\end{blockindent}


\zinccmd{group}{tagOrId}

{\tt\large \$group = \$zinc->{\bf group}(tagOrId);}

\begin{blockindent}
  Returns the group containing the item described by {\tt tagOrId}. If more than one item
  is named by {\tt tagOrId}, then the topmost in display list order is used to return the
  result.
\end{blockindent}


\zinccmd{hasanchors}{tagOrId}

{\tt\large \$bool = \$zinc->{\bf hasanchors}(tagOrId);}

\begin{blockindent}
  This command returns a boolean telling if the item specified by {\tt tagOrId} supports
  anchors. If more than one item is named by {\tt tagOrId}, then the topmost in display
  list order is used to return the result. If no items are named by {\tt tagOrId}, an
  error is raised.
\end{blockindent}


\zinccmd{hasfields}{tagOrId}

{\tt\large \$bool = \$zinc->{\bf hasfields}(tagOrId);}

\begin{blockindent}
  This command returns a boolean telling if the item specified by {\tt tagOrId} supports
  fields. If more than one item is named by {\tt tagOrId}, then the topmost in display
  list order is used to return the result. If no items are named by {\tt tagOrId}, an
  error is raised.
\end{blockindent}


\zinccmd{hastag}{tagOrId tag}

{\tt\large \$bool = \$zinc->{\bf hastag}(tagOrId, tag);}

\begin{blockindent}
  This command returns a boolean telling if the item specified by {\tt tagOrId} has the
  specified tag. If more than one item is named by {\tt tagOrId}, then the topmost in
  display list order is used to return the result. If no items are named by {\tt tagOrId},
  an error is raised.
\end{blockindent}


\zinccmd{index}{tagOrId index}

{\tt\large \$num = \$zinc->{\bf index}(tagOrId, index);}

\begin{blockindent}
  This command returns a number which is the numerical index in the item described by {\tt
  tagOrId} corresponding to {\tt index}. The possible forms for {\tt index} are described
  in \conceptref{Text indices}{indices}. The command returns a value between 0 and the
  number of character in the item. If {\tt tagOrId} describes more than one item, the index
  is processed in the first item supporting text indexing in display list order.
\end{blockindent}


\zinccmd{insert}{tagOrId before string}

{\tt\large \$zinc->{\bf insert}(tagOrId, before, string);}

\begin{blockindent}
  This command inserts {\tt string} in each item described by {\tt tagOrId} just before
  the text position described by {\tt before}. The possible values for {\tt before} are
  described in \conceptref{Text indices}{indices}. Items that doesn't support text
  indexing are skipped by the command. The command returns an empty string.
\end{blockindent}


\zinccmd{itemcget}{tagOrId ?fieldId? attr}

{\tt\large \$val = \$zinc->{\bf itemcget}(tagOrId, attr);}\\
{\tt\large \$val = \$zinc->{\bf itemcget}(tagOrId, field, attr);}

\begin{blockindent}
  Returns the current value of the attribute given by {\tt attr} for the item named by
  {\tt tagOrId}. If {\tt tagOrId} name more than one item, the topmost in display list
  order is used. If {\tt field} is given, it must be a valid field index for the item or
  an error will be reported. If a field index is given, the command will interpret {\tt
  attr} as a field attribute (see \objectref{field}), otherwise it will be interpreted as
  an item attribute (see the chapter \conceptref{Item types}{items}). If the attribute is
  not available for the field or item type, an error is reported.
\end{blockindent}


\zinccmd{itemconfigure}{tagOrId ?fieldId? ?attr? ?value? ?attr value ...?}

{\tt\large @attribs = \$zinc->{\bf itemconfigure}(tagOrId);}\\
{\tt\large @attrib = \$zinc->{\bf itemconfigure}(tagOrId, attrib);}\\
{\tt\large \$zinc->{\bf itemconfigure}(tagOrId, attrib=>value, ?attrib=>value?, ...);}\\
{\tt\large @attrib = \$zinc->{\bf itemconfigure}(tagOrId, fieldId, attrib);}\\
{\tt\large \$zinc->{\bf itemconfigure}(tagOrId, fieldId, attrib=>value, ?attrib=>value?, ...);}

\begin{blockindent}
  Query or modify the attributes of an item or field. If no attribute is given, returns a
  list of lists describing all the supported attributes in the same format as for a single
  attribute, as described next. If a single attribute is specified without a value, the
  command returns a list describing the named attribute. Each attribute is described by a
  list with the following content: the attribute name, the attribute type, a boolean
  telling if the attribute is read-only, an empty string, and the current value of the
  attribute. In the two querying forms of the command the topmost item described by {\tt
  tagOrId} is used.

  If at least one attribute - value pair is given, then the corresponding attributes are
  changed for all the items described by {\tt tagOrId} and the command returns an empty
  string. If {\tt field} is given, it must be a valid field index for the item or an
  error will be reported. If a field index is given, the command will interpret the given
  attributes as field attributes, otherwise they will be interpreted as item attributes.
  If an attribute does not belong to the item or field, an error is reported. When configuring
  a set of item defiend by a tag, all items must then accept these attributes.
\end{blockindent}


\zinccmd{lower}{tagOrId ?belowThis?}

{\tt\large \$zinc->{\bf lower}(tagOrId);}\\
{\tt\large \$zinc->{\bf lower}(tagOrId, belowThis);}

\begin{blockindent}
  Reorder all the items given by {\tt tagOrId} so that they will be under the item given
  by {\tt belowThis}. If {\tt tagOrId} name more than one item, their relative order will
  be preserved. If {\tt tagOrId} doesn't name an item, an error is raised. If {\tt
  belowThis} name more than one item, the bottom most them is used. If {\tt belowThis}
  doesn't name an item, an error is raised. If {\tt belowThis} is omitted the items are
  put at the bottom most position of their respective groups. The command ignore all items
  named by {\tt tagOrId} that are not in the same group than {\tt belowThis} or, if not
  specified, in the same group than the first item named by {\tt tagOrId}. The command
  returns an empty string. As a side affect of this command, the \ident{-priority}
  attribute of all the reordered items is ajusted to match the priority of the {\tt
  belowThis} item (or the priority of the bottom most item).
\end{blockindent}


\zinccmd{monitor}{?onOff?}

{\tt\large \$bool = \$zinc->{\bf monitor}();}\\
{\tt\large \$zinc->{\bf monitor}(onOff);}

\begin{blockindent}
  This command controls the gathering of performance data. The data gathering is inited
  and turned on when the command is called with a boolean true parameter. The gathering is
  stopped if the command is called with a boolean false parameter. If the command is
  called with no parameters or with a boolean false parameter, it returns a string
  describing the currently collected data. The other form of the command returns the empty
  string.
\end{blockindent}


\zinccmd{numparts}{tagOrId}

{\tt\large \$num = \$zinc->{\bf numparts}(tagOrId);}

\begin{blockindent}
  This command tells how many fieldId are available for event bindings or for field
  configuration commands in the item specified by {\tt tagOrId}. If more than one item is
  named by {\tt tagOrId}, the topmost in display list order is used to return the
  result. If no items are named by {\tt tagOrId}, an error is raised. This command
  returns always 0 for items which do not support fields. The command \cmdref{hasfields}
  may be used to decide whether an item has fields.
\end{blockindent}


\zinccmd{postscript}{}

{\tt\large \$zinc->{\bf postscript}();}

\begin{blockindent}
  Not yet implemented.
\end{blockindent}


\zinccmd{raise}{tagOrId ?aboveThis?}

{\tt\large \$zinc->{\bf raise}(tagOrId);}\\
{\tt\large \$zinc->{\bf raise}(tagOrId, aboveThis);}

\begin{blockindent}
  Reorder all the items given by {\tt tagOrId} so that they will be above the item given
  by {\tt aboveThis}. If {\tt tagOrId} name more than one item, their relative order will
  be preserved. If {\tt tagOrId} doesn't name an item, an error is raised. If {\tt
  aboveThis} name more than one item, the topmost in display list order is used. If {\tt
  aboveThis} doesn't name an item, an error is raised. If {\tt aboveThis} is omitted the
  items are put at the top most position of their respective groups. The command ignore
  all items named by {\tt tagOrId} that are not in the same group than {\tt aboveThis} or,
  if not specified, in the same group than the first item named by {\tt tagOrId}. The
  command returns an empty string. As a side affect of this command, the \ident{-priority}
  attribute of all the reordered items is ajusted to match the priority of the {\tt
  aboveThis} item (or the priority of the topmost item).
\end{blockindent}


\zinccmd{remove}{tagOrId ?tagOrId ...?}

{\tt\large \$zinc->{\bf remove}(tagOrId, ?tagOrId?, ...);}

\begin{blockindent}
  Delete all the items named by each {\tt tagOrId}. The command returns an empty string.
\end{blockindent}


\zinccmd{rotate}{tagOrId angle ?degree? ?centerX centerY?}

{\tt\large \$zinc->{\bf rotate}(tagOrId, angle);}\\
{\tt\large \$zinc->{\bf rotate}(tagOrId, angle, centerX, centerY);}

\begin{blockindent}
  Add a rotation to the items or the transform described by {\tt tagOrId}. If {\tt
  tagOrId} describes a named transform then this transform is used to do the operation.
  If {\tt tagOrId} describes more than one item then all the items are affected by the
  operation. If {\tt tagOrId} describes neither a named transform nor an item, an error
  is raised. The angle is given in radian if {\tt degree} is omitted or false, if it is
  specified as true, the angle is in degrees. The last two optional parameters describe
  the center of rotation, which defaults to the origin.
\end{blockindent}


\zinccmd{scale}{tagOrIdOrTName xFactor yFactor ?centerX centerY?}

{\tt\large \$zinc->{\bf scale}(tagOrIdOrTName, xFactor, yFactor);}\\
{\tt\large \$zinc->{\bf scale}(tagOrIdOrTName, xFactor, yFactor, centerX, centerY);}

\begin{blockindent}
  Add a scale factor to the items or the transform described by {\tt tagOrId}. If {\tt
  tagOrId} describes a named transform then this transform is used to do the operation.
  If {\tt tagOrId} describes more than one item then all the items are affected by the
  operation. If {\tt tagOrId} describes neither a named transform nor an item, an error
  is raised. A separate factor is specified for X and Y. The optional parameters
  describe the center of scaling, which defaults to the origin.
\end{blockindent}


\zinccmd{select}{option ?tagOrId? ?arg?}

{\tt\large \$zinc->{\bf select}(option, ?tagOrId?, ?arg?);}

\begin{blockindent}
  Manipulates the selection as requested by {\tt option}. {\tt tagOrId} describes the
  target item. This item must support text indexing and selection. If more than one item
  is referred to by {\tt tagOrId}, the first in display list order that support both text
  indexing and selection will be used. Some forms of the command include an {\tt index}
  parameter, this parameter describes a textual position within the item and should be a
  valid index as described in \conceptref{Text indices}{indices}. The valid forms of the
  command are :

  \begin{itemize}
  \item{\tt\large
        pathname {\bf select} adjust tagOrId index\\ 
        \$zinc->{\bf select}('adjust', tagOrdId, index);}
    
    Adjust the end of the selection in {\tt tagOrId} that is nearest to the character
    given by {\tt index} so that it is at {\tt index}. The other end of the selection is
    made the anchor for future select to commands. If the selection is not currently in
    {\tt tagOrId}, this command behaves as the select to command. The command returns an
    empty string.
    
  \item{\tt\large
        pathname {\bf select} clear\\ 
        \$zinc->{\bf select}('clear');}
    
    Clear the selection if it is in the widget. If the selection is not in the widget, the
    command has no effect. Return an empty string.

  \item{\tt\large
        pathname {\bf select} from tagOrId index\\ 
        \$zinc->{\bf select}('from', tagOrdId, index);}

    Set the selection anchor point for the widget to be just before the character given by
    {\tt index} in the item described by {\tt tagOrId}. The command has no effect on the
    selection, it sets one end of the selection so that future select to can actually set
    the selection. The command returns an empty string.

  \item{\tt\large
        pathname {\bf select} item\\   
        (\$item, \$part) = \$zinc->{\bf select}('item');}
      
    Returns a list of two elements. The first is the id of the selected item if the selection
    is in an item on this widget; Otherwise the first element is an empty string. The second
    element is the part of the item (track, waypoint or tabular item only) or the empty string.

  \item{\tt\large
        pathname {\bf select} to tagOrId index\\
        \$zinc->{\bf select}('to', tagOrdId, index);}
      
    Set the selection to be the characters that lies between the selection anchor and {\tt
    index} in the item described by {\tt tagOrId}. The selection includes the character
    given by {\tt index} and includes the character given by the anchor point if {\tt
    index} is greater or equal to the anchor point. The anchor point is set by the most
    recent select adjust or select from command issued for this widget. If the selection
    anchor point for the widget is not currently in {\tt tagOrId}, it is set to the
    character given by index. The command returns an empty string.
  \end{itemize}

\end{blockindent}


\zinccmd{skew}{tagOrIdOrTName xSkewAngle ySkewAngle}

{\tt\large \$zinc->{\bf skew}(tagOrIdOrTName, xSkewAngle, ySkewAngle);}

\begin{blockindent}
  Add a skew (or shear) transform to the  to the items or the transform described 
  by {\tt tagOrIdOrTName}. If {\tt tagOrId} describes a named transform then this 
  transform is used to do the operation. If {\tt tagOrId} describes more than 
  one item then all the items are affected by the operation. 
  If {\tt tagOrId} describes neither a named transform nor an item, an 
  error is raised. The angles are given in radian.
\end{blockindent}


\zinccmd{smooth}{coordList}

{\tt\large @coords = \$zinc->{\bf smooth}(coordList);}

\begin{blockindent}
  This command computes a sequence of segments that will smooth the polygon
  described by the vertices in {\tt coordList} and returns a list of lists describing
  points of the generated segments. These segments are approximating a Bezier curve.
  {\tt coordList} should be either a
  flat list of an even number of coordinates in x, y order, or a list of lists of point
  coordinates X, Y. The returned list can be used to create or change the contour of a
  curve item.
\end{blockindent}


\zinccmd{tapply}{}

{\tt\large \$zinc->{\bf tapply}();}

\begin{blockindent}
  Not yet implemented.
\end{blockindent}


\zinccmd{tcompose}{tagOrIdOrTName tName ?invert?}

{\tt\large \$zinc->{\bf tcompose}(tagOrIdOrTName, tName);}\\
{\tt\large \$zinc->{\bf tcompose}(tagOrIdOrTName, tName, invert);}

\begin{blockindent}
  Modify either the named transform {\tt tagOrIdOrTName} or the corresponding 
  item by composing the {\tt tName} transform. The {\tt invert} boolean, if specified, 
  causes the {\tt tName} transform to be inverted prior composition.

  If {\tt tagOrIdOrTName} describes neither a named transform nor an item, an error is
  raised. If {\tt tName} does not describe a named transform an error is raised.
\end{blockindent}


\zinccmd{tdelete}{tName}

{\tt\large \$zinc->{\bf tdelete}(tName);}

\begin{blockindent}
  Destroy a named transform. If the given name is not found among the named transforms, an
  error is raised.
\end{blockindent}


\zinccmd{tget}{tagOrIdOrTName ?selector?}

{\tt\large (\$m00, \$m01, \$m10, \$m11, \$m20, \$m21) = \$zinc->{\bf tget}(tagOrIdOrTName);}\\
{\tt\large (\$xtranslate, \$ytranslate, \$xscale, \$yscale, \$angle, \$xskew) =\\
                        \$zinc->{\bf tget}(tagOrIdOrTName, 'all');}\\
{\tt\large (\$xtranslate, \$ytranslate) = \$zinc->{\bf tget}(tagOrIdOrTName,  'translate');}\\
{\tt\large (\$xscale, \$yscale) = \$zinc->{\bf tget}(tagOrIdOrTName, 'scale');}\\
{\tt\large (\$angle) = \$zinc->{\bf tget}(tagOrIdOrTName, 'rotate');}\\
{\tt\large (\$xskew) = \$zinc->{\bf tget}(tagOrIdOrTName, 'skew');}

\begin{blockindent}
  With only one argument, get the six elements of the 3x4 matrix used in affine 
  transformation for {\tt tagOrIdOrTName}. The result is compatible with the tset method.
  With optional second parameter 'all' returns the transform decomposed in translation, 
  scale, rotation, skew and return the list in this order,
  With 'translation', 'scale', 'rotation', 'skew' optional second parameter, 
  returns the corresponding values.
\end{blockindent}


\zinccmd{transform}{?tagOrIdFrom? tagOrIdTo coordList}

{\tt\large @coords = \$zinc->{\bf transform}(tagOrIdTo, coordList);}\\
{\tt\large @coords = \$zinc->{\bf transform}(tagOrIdFrom, tagOrIdTo, coordList);}

\begin{blockindent}
  This command returns a list of coordinates obtained by transforming the coordinates
  given in {\tt coordList} from the coordinate space of the transform or item described by
  {\tt tagOrIdFrom} to the coordinate space of the transform or item described by {\tt
  tagOrIdTo}. If {\tt tagOrIdFrom} is omitted it defaults to the window coordinate
  space. If either {\tt tagOrIdFrom} or {\tt tagOrIdTo} describes more than one item,
  the topmost in display list order is used.  If either {\tt tagOrIdFrom} or {\tt tagOrIdTo}
  doesn't describe either a transform or an item, an error is raised.
  The {\tt coordList} should either be a flat list containing an even number of
  coordinates each point having two coordinates, or a list of lists each sublist of the form
  [ X Y ?pointtype? ]. The returned coordinates list will be isomorphic to the list given
  as argument.

  It is possible to convert from window coordinate space to the coordinate space of any
  item. This is done by omitting {\tt ?tagOrIdFrom?} and specifying in {\tt tagOrIdTo},
  the id of the item. It can also be done by using the predefined tag 'device' as first argument.

  It is also possible to convert from the coordinate space of an item to the window
  coordinate space by using the predefined tag 'device' as second argument.

  For example:

  \begin{itemize}
    \item{\verb+($x, $y) = $zinc->transform('device', $mygroup, [$xdev, $ydev]);+}\\
      transforms the point described by \verb+$xdev,$ydev+ in window coordinates,
      to \verb+$mygroup+ coordinates in \verb+$x,$y+;
    \item{\verb+($xdev, $ydev) = $zinc->transform($mygroup, 'device', [$x, $y]);+}\\
      transforms the point described by \verb+$x,$y+ in \verb+$mygroup+
      coordinates, to window coordinates in \verb+$xdev,$ydev+
    \item{\verb+($x2, $y2) = $zinc->transform($group1, $group2, [$x1, $y1]);+}\\
      transforms the point described by \verb+$x1,$y1+ in \verb+$group1+ coordinates,
      to \verb+$group2+ coordinates in \verb+$x2,$y2+;%$
  \end{itemize}
\end{blockindent}


\zinccmd{translate}{tagOrIdOrTName xAmount yAmount ?absolute?}

{\tt\large \$zinc->{\bf translate}(tagOrdIdOrTName, xAmount, yAmount, ?absolute?);}

\begin{blockindent}
  Add a translation to the items or the transform described by {\tt tagOrIdOrTName}. If {\tt
  tagOrIdOrTName} describes a named transform then this transform is used to do the operation. If
  {\tt tagOrIdOrTName} describes more than one item then all the items are affected by the
  opration. If {\tt tagOrIdOrTName} describes neither a named transform nor an item, an error is
  raised. A separate value is specified for X and Y.
  If the optionnal {\tt ?absolute?} parameter is true, it will set an absolute translation to
  the {\tt tagOrIdOrTName}
\end{blockindent}


\zinccmd{treset}{tagOrIdOrTName}

{\tt\large \$zinc->{\bf treset}(tagOrdIdOrTName);}

\begin{blockindent}
  Set the named transform or the transform for the items described by {\tt tagOrIdOrTName} to
  identity. If {\tt tagOrIdOrTName} describes neither a named transform nor an item, an error is
  raised.
\end{blockindent}


\zinccmd{trestore}{tagOrId tName}

{\tt\large \$zinc->{\bf trestore}(tagOrdId, tName);}

\begin{blockindent}
  Set the transform for the items described by {\tt tagOrId} to the transform named by
  {\tt tName}. If {\tt tagOrId} doesn't describe any item or if the transform named {\tt
  tName} doesn't exist, an error is raised.
\end{blockindent}


\zinccmd{tsave}{?tagOrIdOrTName? tName ?invert?}

{\tt\large \$zinc->{\bf tsave}(tName);}\\
{\tt\large \$zinc->{\bf tsave}(tagOrdIdOrTName, tName);}\\
{\tt\large \$zinc->{\bf tsave}(tagOrdIdOrTName, tName, invert);}

\begin{blockindent}
  Create (or reset) a transform associated with the name {\tt tName} with initial
  value the transform associated with the item {\tt tagOrIdOrTName}. If {\tt tagOrIdOrTName} describes
  more than one item, the topmost in display list order is used. If {\tt tagOrIdOrTName} doesn't
  describe any item or named transformation, an error is raised. If {\tt tName} already exists, 
  the transform is set to the new value. This command is the only way to create a named transform.
  If {\tt tagOrIdOrTName} is not specified, the command returns a boolean telling if the
  name is already in use. The {\tt invert} boolean, if specified, cause the transform
  to be inverted prior to be saved.

  It is possible to create a new named transformation from the identity by using the predefined tag 'identity': {\verb+$zinc->tsave('identity', 'myTransfo');+}
% $  this comment is for emacs colorization only!
\end{blockindent}

\zinccmd{tset}{tagOrIdOrTName m00 m01 m10 m11 m20 m21}

{\tt\large \$zinc->{\bf tset}(tagOrIdOrTName, m00, m01, m10, m11, m20, m21);}

\begin{blockindent}
  Set the six elements of the 3x4 matrix used in affine transformation for 
  {\tt tagOrIdOrTName}. \bf{ BEWARE that depending on mij values, it is possible 
  to define a not inversible matrix which will end up in core dump. This 
  method must BE USED CAUTIOUSLY. }
\end{blockindent}


\zinccmd{type}{tagOrId}

{\tt\large \$name = \$zinc->{\bf type}(tagOrdId);}

\begin{blockindent}
  This command returns the type of the item specified by {\tt tagOrId}. If more than one
  item is named by {\tt tagOrId}, then the type of the topmost item in display list order
  is returned. If no items are named by {\tt tagOrId}, an error is raised.
\end{blockindent}


\zinccmd{vertexat}{tagOrId x y}

{\tt\large (\$contour, \$vertex, \$edgevertex) = \$zinc->{\bf vertexat}(tagOrdId, x, y);}

\begin{blockindent}
  Return a list of values describing the vertex and edge closest to the \emph{window
  coordinates} {\tt x} and {\tt y} in the item described by {\tt tagOrId}. If {\tt
  tagOrId} describes more than one item, the first item in display list order that
  supports vertex picking is used. The list consists of the index of the contour
  containing the returned vertices, the index of the closest vertex and the index of a
  vertex next to the closest vertex that identify the closest edge (located between the
  two returned vertices).
\end{blockindent}


%%
%%
%% C h a p t e r :   I t e m   t y p e s
%%
%%
\chapter{Item types}
\concept{items}

This chapter introduces the item types that can be used in TkZinc. Each item type
provides a set of options that may be used to query or change the item behavior. Some item
types cannot be used with some widget commands, or use special parameters with some
commands. Those cases are noted in the description of the item.

%%% XXX CM : the two previous sentences are really not clear!

\section{Group items}
\object{group}

Group items are used for grouping objects together. Their usage is very powerfull and
their use is best described in the previous chapter \conceptref{Groups, Display List, Clipping
and Transformations}{coordinates}.

Applicable attributes for \ident{group} are:

\attribute{group}{alpha}{alpha}{Specifies the transparency to compose with the children
transparencies. Needs the openGL extension.}

\attribute{group}{atomic}{boolean}{Specifies if the group should report itself or its
components during a search or for binding related operations. This attribute enable the
use of a group as a single complex object build from smaller parts. It is possible to
search for this item or use it in bindings without dealing with its smaller parts. The
defaut value is {\tt false}.}

\attribute{group}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. If a group is not catching events, its
children will not receive events for processing regardless of their own state.
The default value is {\tt true}.}

\attribute{group}{clip}{item}{The item used to clip the children of the group. The shape
of this item define an area that is used as a clipping shape when drawing the children of
the group. Most items can be used here but notable exceptions are the \objectref{reticle} and
\objectref{map} items. The default value is {\tt ""} which means that no clipping will be
performed.}

\attribute{group}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group must be composed with the alpha of this group. The default value is
{\tt true}.}

\attribute{group}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{group}{composescale}{boolean}{Specifies if the current scale should be composed
with the local transform. The default value is {\tt true}.}

\attribute{group}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{group}{sensitive}{boolean}{Specifies if the item and all its children should
react to events. The defaut value is {\tt true}.}

\attribute{group}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{group}{visible}{boolean}{Specifies if the item and all its children is
displayed. The defaut value is {\tt true}.}


\section{Track items}
\object{track}

Track items have been designed for figuring out typical radar information for Air Traffic
Control. However they may certainly be used by other kinds of radar view and surely by
other kind of plan view with many moving objects and associated textual information.

A track is composed of two main parts:
\begin{itemize} 
\item The first one is purely graphic and is composed of many parts, some of them being
identified by their ``partName'':

\begin{itemize}
\item the {\bf current position} of the object. Its partName is \ident{position}.
\item a {\bf speed vector} which size depends on the attribute
\attributeref{track}{speedvector} for the track and the option \optref{speedvectorlength}.
This speed vector may be set visible or not, sensitive or other attributes can be set such
as color, width, ticks, mark at the end... Its partName is \ident{speedvector}.
\item a {\bf leader} which links the current position to the label. The leader may be
visible or not, sensitive or not, and other graphic characteristics can be modified. Its
partName is \ident{leader}.
\item {\bf past positions} which are previous position after the track has been moved by
the \cmdref{coords} command. The number of such past positions, their visibility and other
graphic characteristics can be be modified. This part is never sensitive.
\item a {\bf marker}, which is a circle around the current position. This marker can be
visible or not and other graphic characteristics can be configured. The marker is never
sensitive.
\item a {\bf connection}, which is a link with another track or waypoint item; links are
drawn between their {\bf current position}. This connection may be visible or not,
sensitive or not, and other graphic characteristics can be be modified. Its partName
is \ident{connection}.
\end{itemize}

\item the second part is a block of texts described by a labelformat (see chapter
\conceptref{Labels, labelformats, and fields}{labelformat}. Each text can have its graphic
decorations (alignment, background, images, borders...). These attributes are listed in
the chapter \conceptref{Labels, label formats and fields}{labelformat} and can be changed
by the command \cmdref{itemconfigure}.
\end{itemize}

The following picture shows a simple \ident{track} with a label of 5 fields and 5 past
positions. This track also shows a marker, the circle around the current position.

\fig{trackexample}{A track with a label composed of 5 fields}{1}


%%% XXX CM add here an image with a openGL track (end ticks,... antialising...)
An other very important feature of \ident{track} item is that TkZinc offers an
anti-overlap manager. This manager tries to avoid any overlap of tracks labels. It also
avoids that the label overlap the speedvector. This manager is stable over time: there
should be few cases where labels are moved to a very different position. This manager
applies to all tracks included in a group (by default the group 1). It can be
enabled/disabled with the TkZinc attribute \optref{overlapmanager}.
New labels positions are computed by the overlap
manager every time a track is moved, a track is created or destroyed and every time the
TkZinc widget is resized. Due to software license limitation, TkZinc \emph{do not include}
the very last version of this anti-overlap manager. If you are interested
in this anti-overlap manager, please contact Didier Pavet at {\tt pavet@cena.fr}.

Track items can be linked together or to waypoint items. The line figuring the link
is configurable.

Applicable attributes for \ident{track} are :

\attribute{track}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{track}{circlehistory}{boolean}{If set to true the track history will be plotted
as circles otherwise it will be plotted as squares. The default value is {\tt false}.}

\attribute{track}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group must be composed with the alpha of this item. The default value is
{\tt true}.}

\attribute{track}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{track}{composescale}{boolean}{Specifies if the current scale should be composed
with the local transform. The default value is {\tt true}.}

\attribute{track}{connecteditem}{item}{The \ident{track} or \ident{waypoint} item at the
other end of the connection link. The default value is {\tt ""} which means that
no connection link will be drawn.}

\attribute{track}{connectioncolor}{gradient}{The uniform (possibly transparent)
color of the connection link. The first color of a real gradient color
will be used. The default value is the current value of the widget option \optref{forecolor}.}

\attribute{track}{connectionsensitive}{boolean}{Specifies if the connection link is
sensitive. The actual sensitivity is the logical \ident{and} of this attribute and of the
item \attributeref{track}{sensitive} attribute. The default value is {\tt true}.}

\attribute{track}{connectionstyle}{linestyle}{The line style of the connection link. The
default value is {\tt simple}.}

\attribute{track}{connectionwidth}{dimension}{The width of the connection link. The
default value is {\tt 1}.}

\attribute{track}{filledhistory}{boolean}{If set to true the track history will be filled
otherwise it will be outlined. The default value is {\tt true}.}

\attribute{track}{filledmarker}{boolean}{If set to true the circular marker will be filled
otherwise it will be outlined. The default value is {\tt false}.}

\attribute{track}{frozenlabel}{boolean}{Specifies if the label should be frozen at its
current location to prevent the anti overlapping system from moving it. The default value
is {\tt false}.}

\attribute{track}{historycolor}{gradient}{The uniform (possibly transparent) color of the
track history. The first color of a real gradient color will be used. The default
value is the current value of the widget option \optref{forecolor}.}

\attribute{track}{historywidth}{dimension}{The starting width for drawing the monotonically
shrinking track history. The default value is {\tt 8}. This value used to be derived from
the \attributeref{track}{symbol} width, proscribing the use of large symbols.}

\attribute{track}{labelanchor}{anchor}{The anchor used in positionning the label. The
default value is {\tt center}.}

\attribute{track}{labelangle}{angle}{The angle in degrees between the label anchor and the
normal to the speed vector. This attribute works with the \attributeref{track}{labeldistance} attribute to
specify a position for the label anchor with respect to the item origin. There is another
alternative method for label positioning which is implemented with the \attributeref{track}{labeldx} and
\attributeref{track}{labeldy} methods. Simultaneous use of the two methods should be done with care as
there is no automatic update of values from the \attributeref{track}{labeldx},
\attributeref{track}{labeldy} set to the \attributeref{track}{labeldistance},
\attributeref{track}{labelangle} set. The default value is {\tt 20}.}

\attribute{track}{labelconvergencestyle}{integer}{This attribute is a pass through to the
anti-overlap module intended to select the convergence method. The exact meaning is
left to the designer of the anti-overlap module actually used. The default value is 0.}

\attribute{track}{labeldistance}{dimension}{The minimum distance in pixels between the
track position and the label anchor. See the explanation of the \attributeref{track}{labelangle} attribute
for some more details. The default value is 50.}

\attribute{track}{labeldx}{dimension}{The X offset between the track position and the
label anchor. The default value is computed from the values in the \attributeref{track}{labeldistance} and
\attributeref{track}{labelangle} attributes.}

\attribute{track}{labeldy}{dimension}{The Y offset between the track position and the
label anchor. The default value is computed from the values in the \attributeref{track}{labeldistance} and
\attributeref{track}{labelangle} attributes.}

\attribute{track}{labelformat}{labelformat}{Geometry of the label fields. The default
value is {\tt ""} which means that no label will be displayed.}

\attribute{track}{labelpreferredangle}{angle}{XXX New. To be documented. The default value
is ??.}

\attribute{track}{lastasfirst}{boolean}{If set to true, the last position in the history
will be drawn in the same color as the current position instead of being drawn in the
history color. The default value is {\tt false}.}

\attribute{track}{leaderanchors}{leaderanchors}{The attachment of the leader on the label
left or right side (whether the label is on the right or left of the current position). 
The default value is {\tt ""} which means that the leader anchor is at the label
center, whatever the label position.}

\attribute{track}{leadercolor}{gradient}{The uniform (possibly transparent) color of the label
leader. The first color of a real gradient color will be used. The default
value is the current value of the widget option \optref{forecolor}.}

\attribute{track}{leaderfirstend}{lineend}{Describes the arrow shape at the current
position end of the leader. The default value is {\tt ""}.}

\attribute{track}{leaderlastend}{lineend}{Describes the arrow shape at the label end of the
leader. The default value is {\tt ""}.}

\attribute{track}{leadersensitive}{boolean}{Specifies if the label leader is sensitive.
The actual sensitivity is the logical \ident{and} of this attribute and of the item
\attributeref{track}{sensitive} attribute. The default value is {\tt true}.}

\attribute{track}{leadershape}{lineshape}{The shape of the label leader. The default value
is {\tt straight}.}

\attribute{track}{leaderstyle}{linestyle}{The line style of the label leader. The default
value is {\tt simple}.}

\attribute{track}{leaderwidth}{dimension}{The width of the label leader. The default value
is {\tt 1}.}

\attribute{track}{markercolor}{gradient}{The uniform (possibly transparent) color of the
circular marker. The first color of a real gradient color will be used. The
default value is the current value of the widget option \optref{forecolor}.}

\attribute{track}{markerfillpattern}{bitmap}{The pattern to use when filling the circular
marker. The default value is {\tt ""}.}

\attribute{track}{markersize}{dimension}{The (scale sensitive) size of the circular marker.
The default value is {\tt 0} which turn off the display of the marker.}

\attribute{track}{markerstyle}{linestyle}{The line style of the marker outline. The
default value is {\tt simple}.}

\attribute{track}{mixedhistory}{boolean}{If true the track history will be plotted with
dots every other position. The default value is {\tt false}.}

\attribute{track}{numfields}{unsignedint}{Gives the number of fields available for the
label. This attribute is read only.}

\attribute{track}{position}{point}{The current location of the track. The default value
is {\tt "0 0"}.}

\attribute{track}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{track}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt true}.}

\attribute{track}{speedvector}{point}{The speed vector $\Delta x$ and $\Delta y$ in
unit / minute. The default value is {\tt "0 0"} which results in no speed vector
displayed.}

\attribute{track}{speedvectorcolor}{gradient}{The uniform (possibly transparent) color of
the track's speed vector. The first color of a real gradient color will be used.
The default value is the current value of the widget option \optref{forecolor}.}

\attribute{track}{speedvectormark}{boolean}{If set a small point is drawn at the end of
the speed vector. The point is drawn with the speed vector color. The default is {\tt
false}.Not yet available without openGL}

\attribute{track}{speedvectorsensitive}{boolean}{Specifies if the track's speed vector is
sensitive. The actual sensitivity is the logical \ident{and} of this attribute and of the
item \attributeref{track}{sensitive} attribute. The default value is {\tt true}. }

\attribute{track}{speedvectorticks}{boolean}{If set a mark is drawn at each minute
position. The default is {\tt false}. Not yet available without openGL}

\attribute{track}{speedvectorwidth}{dimension}{New. XXX To be documented. The default value is
{\tt 1}.}

\attribute{track}{symbol}{bitmap}{The symbol displayed at the current position. The
default value is the current value of the widget option \optref{tracksymbol}.} 

\attribute{track}{symbolcolor}{gradient}{The uniforme (possibly transparent) color of the symbol
displayed at the current position. The first color of a real gradient color will be used.
The default value is the current value of the widget option
\optref{forecolor}.}

\attribute{track}{symbolsensitive}{boolean}{Specifies if the current position's symbol is
sensitive to events. The actual sensitivity is the logical \ident{and} of this attribute
and of the item \attributeref{track}{sensitive} attribute. The default value is {\tt true}.}

\attribute{track}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{track}{visible}{boolean}{Specifies if the item is displayed. The default value
is {\tt true}.}

\attribute{track}{historyvisible}{boolean}{Specifies whether the item should display
its history according to the options \optref{trackvisiblehistorysize} and
\optref{trackmanagedhistorysize}. The default value is {\tt true}.}


\section{WayPoint items}
\object{waypoint}

Waypoints items have been initially designed for figuring out typical fixed position
objects (i.e. beacons or fixes in the ATC vocabulary) with associated block of texts on a
radar display for Air Traffic Control. They supports mouse event handling and
interactions. However they may certainly be used by other kinds of radar view or even by
other kind of plan view with many geographical objects and associated textual information.

A waypoint is composed of the following parts:
\begin{itemize} 
\item the {\bf position} of the waypoint. Its partName is \ident{position}.
\item a {\bf leader} which links the current position to the label. The leader may be
visible or not, sensitive or not, and other graphic characteristics can be be modified. Its
partName is \ident{leader}.
\item a {\bf label} which is a block of texts described by a labelformat (see chapter
\conceptref{Labels, labelformat, and fields}{labelformat}. Each text can have its graphic
decorations (alignment, background, images, borders...). These attributes are listed in
the chapter \conceptref{Labels, label formats and fields}{labelformat} and can be changed
by the command \cmdref{itemconfigure}.
\item a {\bf connection}, which is a link with another \ident{waypoint} or \ident{track} item.
This connection may be visible or not, sensitive or not, and other graphic characteristics
can be be modified. Its partName is \ident{connection}.
\end{itemize}


\fig{waypointexample}{A waypoint with a label composed of five fields; fields have
borders}{1}


Applicable attributes for \ident{waypoint} are:

\attribute{waypoint}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{waypoint}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group must be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{waypoint}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}. }

\attribute{waypoint}{composescale}{boolean}{Specifies if the current scale should be
composed with the local transform. The default value is {\tt true}. }

\attribute{waypoint}{connecteditem}{item}{The \ident{track} or \ident{waypoint} item at the
other end of the connection link. The default value is {\tt ""} which means that
no connection link will be drawn.}

\attribute{waypoint}{connectioncolor}{gradient}{The uniform (possibly transparent) color of
the connection link. The first color of a real gradient color will be used. The
default value is the current value of the widget option \optref{forecolor}.}

\attribute{waypoint}{connectionsensitive}{boolean}{Specifies if the connection link is
sensitive. The actual sensitivity is the logical \ident{and} of this attribute and of the
item \attributeref{waypoint}{sensitive} attribute. The default value is {\tt true}.}

\attribute{waypoint}{connectionstyle}{linestyle}{The line style of the connection link.
The default value is {\tt simple}.}

\attribute{waypoint}{connectionwidth}{dimension}{The width of the connection link. The
default value is {\tt 1}.}

\attribute{waypoint}{filledmarker}{boolean}{If set to true the circular marker will be
filled otherwise it will be outlined. The default value is {\tt false}.}

\attribute{waypoint}{labelanchor}{anchor}{The anchor used in positionning the label. The
default value is {\tt center}.}

\attribute{waypoint}{labelangle}{angle}{The angle in degrees between the label anchor and
the normal to the speed vector. This attribute works with the \attributeref{track}{labeldistance}
attribute to specify a position for the label anchor with respect to the item origin.
There is another alternative method for label positioning which is implemented with the
\attributeref{track}{labeldx} and \attributeref{track}{labeldy} methods. Simultaneous use
of the two methods should be done with care as there is no automatic update of values from the
\attributeref{track}{labeldx}, \attributeref{track}{labeldy} set to the
\attributeref{track}{labeldistance}, \attributeref{track}{labelangle} set. The default value is {\tt
20}.}

\attribute{waypoint}{labeldistance}{dimension}{The minimum distance in pixels between the
way point position and the label anchor. See the explanation of the \attributeref{waypoint}{labelangle}
attribute for some more details. The default value is {\tt 50}.}

\attribute{waypoint}{labeldx}{dimension}{The X offset between the way point position and
the label anchor. The default value is computed from the values in the
\attributeref{waypoint}{labeldistance} and \attributeref{waypoint}{labelangle} attributes.}

\attribute{waypoint}{labeldy}{dimension}{The Y offset between the way point position and
the label anchor. The default value is computed from the values in the
\attributeref{waypoint}{labeldistance} and \attributeref{waypoint}{labelangle} attributes.}

\attribute{waypoint}{labelformat}{labelformat}{Geometry of the label fields. The default
value is {\tt ""} which means that no label will be displayed.}

\attribute{waypoint}{leaderanchors}{leaderanchors}{The attachment of the leader on the label
left or right side (whether the label is on the right or left of the current position). 
The default value is {\tt ""} which means that the leader anchor is at the label
center, whatever the label position.}

\attribute{waypoint}{leadercolor}{gradient}{The uniform (possibly transparent) color of the
label leader. The first color of a real gradient color will be used. The
default value is the current value of the widget option \optref{forecolor}.}

\attribute{waypoint}{leaderfirstend}{lineend}{Describes the arrow shape at the current
position end of the leader. The default value is {\tt ""}.}

\attribute{waypoint}{leaderlastend}{lineend}{Describes the arrow shape at the label end of
the leader. The default value is {\tt ""}.}

\attribute{waypoint}{leadersensitive}{boolean}{Specifies if the label leader is sensitive.
The actual sensitivity is the logical \ident{and} of this attribute and of the item
\attributeref{waypoint}{sensitive} attribute. The default value is {\tt true}.}

\attribute{waypoint}{leadershape}{lineshape}{The shape of the label leader. The default
value is {\tt straight}.}

\attribute{waypoint}{leaderstyle}{linestyle}{The line style of the label leader. The
default value is {\tt simple}.}

\attribute{waypoint}{leaderwidth}{dimension}{The width of the label leader. The default
value is {\tt 1}.}

\attribute{waypoint}{markercolor}{gradient}{The uniform (possibly transparent) color of the
circular marker. The first color of a real gradient color will be used. The
default value is the current value of the widget option \optref{forecolor}.}

\attribute{waypoint}{markerfillpattern}{bitmap}{The pattern to use when filling the
circular marker. The default value is {\tt ""}.}

\attribute{waypoint}{markersize}{dimension}{The (scale sensitive) size of the circular
marker. The default value is {\tt 0} which turn off the display of the marker.}
\attribute{waypoint}{markerstyle}{linestyle}{The line style of the marker outline. The
default value is {\tt simple}.}

\attribute{waypoint}{numfields}{unsignedint}{Gives the number of fields available for the
label. This attribute is read only.}

\attribute{waypoint}{position}{point}{The current location of the way point. The
default value is {\tt "0 0"}.}

\attribute{waypoint}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{waypoint}{sensitive}{boolean}{Specifies if the item should react to events.
The default value is {\tt true}.}

\attribute{waypoint}{symbol}{bitmap}{The symbol displayed at the current position. The
default value is {\tt AtcSymbol15}.}

\attribute{waypoint}{symbolcolor}{gradient}{The uniform (possibly transparent) color of the
symbol displayed at the current position. The first color of a real gradient color will be used.
The default value is the current value of the widget option
\optref{forecolor}.}

\attribute{waypoint}{symbolsensitive}{boolean}{Specifies if the current position's symbol
is sensitive to events. The actual sensitivity is the logical \ident{and} of this
attribute and of the item \attributeref{waypoint}{sensitive} attribute. The default value is {\tt true}.}

\attribute{waypoint}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{waypoint}{visible}{boolean}{Specifies if the item is displayed. The default
value is {\tt true}.}


\section{Tabular items}
\object{tabular}

Tabular items have been initially designed for displaying block of textual information,
organised in lists or spread out on a radar display.

A tabular item is mainly composed of a \emph{label} which is a block of texts described
by a labelformat (see chapter \conceptref{Labels, labelformats and fields}{labelformat}.
Each text can have its graphic decorations (alignment, background, images, borders...).
This attributes are listed in the chapter \conceptref{Labels, label formats and
fields}{labelformat} and can be changed by the command \cmdref{itemconfigure}.
A tabular can be attached with the \attributeref{tabular}{connecteditem} attribute to the
label of a \objectref{track}, \objectref{waypoint} or another \objectref{tabular}. 

Applicable attributes for \ident{tabular} are:

\attribute{tabular}{anchor}{anchor}{The anchor used in positionning the item. The default
value is {\tt nw}.}

\attribute{tabular}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{tabular}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{tabular}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{tabular}{composescale}{boolean}{Specifies if the current scale should be
composed with the local transform. The default value is {\tt true}.}

\attribute{tabular}{connecteditem}{item}{Specifies the The \ident{track}, \ident{waypoint} or
\ident{tabular} item relative to which this item is
placed. Connected item should be in the same group. The default value is {\tt ""}.}

\attribute{tabular}{connectionanchor}{anchor}{Specifies the anchor on the connected item.
The default value is {\tt sw}.}

\attribute{tabular}{labelformat}{labelformat}{Geometry of the label fields. The default
value is {\tt ""} which means that nothing will be displayed.}

\attribute{tabular}{numfields}{unsignedint}{Gives the number of fields available for the
label. This attribute is read only.}

\attribute{tabular}{position}{point}{The item's position relative to the anchor (if no
connected item specified). The default value is {\tt "0 0"}.}

\attribute{tabular}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}. }

\attribute{tabular}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt true}.}

\attribute{tabular}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{tabular}{visible}{boolean}{Specifies if the item is displayed. The default
value is {\tt true}.}


\section{Text items}
\object{text}

Text items are used for displaying text. They can also be used for text input. In this
case, they must get the focus for keyboards events with the command \cmdref{focus}. Many
TkZinc options (see chapter \conceptref{Widget options}{options} can be used for
configuring the text input (for example : \optref{insertbackground},
\optref{insertofftime} \optref{insertontime}, \optref{insertwidth}).

With and without openGL, text items can be rotated or scaled. However, 
attributes \attributeref{text}{composerotation} and \attributeref{text}{composescale} 
must be set before rotation and scaling.

A Tcl module, zincText is available, it provides simple bindings for interactive
text input. For enabling interactive text editing on an item, the item should
be sensitive and should have the tag ``text''.

A Perl module, called Tk::Zinc::Text (see the section
\conceptref{Tk::Zinc::Text}{zinctext}) is provided for easing text input in text items
(it can also be used for text input in labelled items such as \objectref{track},
\objectref{waypoint} or \objectref{tabular}).



Applicable attributes for \ident{text} are:

\attribute{text}{alignment}{alignment}{Specifies the horizontal alignment of the lines in
the item. The default value is {\tt left}.}

\attribute{text}{anchor}{anchor}{The anchor used in positionning the item. The default
value is {\tt nw}.}

\attribute{text}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{text}{color}{gradient}{Specifies the uniform (possibly transparent) color for
drawing the text characters, the overstrike and underline lines. The first color of a
real gradient color will be used. The default value is the current value of
the widget option \optref{forecolor}.}

\attribute{text}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{text}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt false}.}

\attribute{text}{composescale}{boolean}{Specifies if the current scale should be composed
with the local transform. The default value is {\tt false}.}

\attribute{text}{connecteditem}{item}{Specifies the item relative to which this item is
placed. Connected item should be in the same group. The default value is {\tt ""}.}

\attribute{text}{connectionanchor}{anchor}{Specifies the anchor on the connected item.
The default value is {\tt sw}.}

\attribute{text}{fillpattern}{bitmap}{Specifies the pattern used to draw the text
characters, the overstrike and underline lines. The default value is {\tt ""}.}

\attribute{text}{font}{font}{Specifies the font for the text. The default value is the
current value of the widget option \optref{font}.}

\attribute{text}{overstriked}{boolean}{If true, a thin line will be drawn horizontally
across the text characters. The default value is {\tt false}.}

\attribute{text}{position}{point}{The item's position relative to the anchor (if no
connected item specified). The default value is {\tt "0 0"} (Tcl/Tk) or {\tt [0,0]} (Perl/Tk).}

\attribute{text}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{text}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt true}.}

\attribute{text}{spacing}{short}{Specifies a pixel value that will be added to the
inter-line spacing specified in the font. The value can be positive to increase the
spacing or negative to reduce it. The default value is {\tt 0}.}

\attribute{text}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{text}{text}{string}{Specifies the text characters. Newline characters can be
embedded to force line ends. The default value is {\tt ""}.}

\attribute{text}{underlined}{boolean}{If true, a thin line will be drawn under the text
characters. The default value is {\tt false}.}

\attribute{text}{visible}{boolean}{Specifies if the item is displayed. The default value
is {\tt true}.}

\attribute{text}{width}{short}{Specifies the maximum pixel width of the text, a line
break will be automatically inserted at the closest character position to match this
constraint. If the value is zero, the width is not under the item control and line breaks
must be inserted in the text to have multiple lines. The default value is {\tt 0}.}


\section{Icon items}
\object{icon}

Icon items are used for displaying bitmap images. Any bitmap file format
supported by Tk can be used. If the bitmap file supports transparency
(not alpha-blending, only full transparency), TkZinc will render this transparent area.
With and without openGL, icons can be rotated or scaled. However, 
attributes \attributeref{icon}{composerotation} and \attributeref{icon}{composescale} 
must be set before rotation and scaling.

Applicable attributes for \ident{icon} are:

\attribute{icon}{anchor}{anchor}{The anchor used in positionning the item. The default
value is {\tt nw}.}

\attribute{icon}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{icon}{color}{gradient}{Specifies the uniform (possibly transparent) fill color
used for drawing the bitmap. The first color of a real gradient color will be used. If
The icon contains an image, only the transparency of the color is used and
defines the alpha transparency of the image when \optref{render} is set to true.
The default value is the current value of the widget option \optref{forecolor}.}

\attribute{icon}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is
{\tt true}.}

\attribute{icon}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt false}.}

\attribute{icon}{composescale}{boolean}{Specifies if the current scale should be composed
with the local transform. The default value is {\tt false}.}

\attribute{icon}{connecteditem}{item}{Specifies the item relative to which this item is
placed. Connected item should be in the same group. The default value is {\tt ""}.}

\attribute{icon}{connectionanchor}{anchor}{Specifies the anchor on the connected item.
The default value is {\tt sw}.}

\attribute{icon}{image}{image}{Specifies a Tk image that will be displayed by the item.
The image may have a mask (depend on the image format) that clip some parts. This option
has precedence over the {\tt mask} option if both are specified. The default value is {\tt
""}.}

\attribute{icon}{mask}{bitmap}{Specifies a Tk bitmap that will be displayed by the
item. The bitmap is filled with the color specified with the {\tt color} option. This
option is inactive if an image has been specified with the {\tt image} option.
The default value is {\tt ""}.}

\attribute{icon}{position}{point}{The item's position relative to the anchor (if no
connected item specified). The default value is {\tt "0 0"} (Tcl/Tk) or {\tt [0,0]} (Perl/Tk.}

\attribute{icon}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{icon}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt true}.}

\attribute{icon}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{icon}{visible}{boolean}{Specifies if the item is displayed. The default value
is {\tt true}.}


\section{Reticle items}
\object{reticle}

Reticle items are set of concentric circles. The number of circles can be either
finite or not. Some periodic circles may be different, they are called bright circles; they
can be configured differently from other circles. This item has mainly be designed for
radar display images, to help user evaluationg distances from the central point.
Reticle cannot handle events.

Applicable attributes for \ident{reticle} are:

\attribute{reticle}{brightlinecolor}{gradient}{This is the uniform (possibly transparent)
color of highlighted circles. The first color of a real gradient color will be used.
The default value is the current value of the widget option \optref{forecolor}.}

\attribute{reticle}{brightlinestyle}{linestyle}{This is the line style of the highlighted
circles. The default value is {\tt simple}.}

\attribute{reticle}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt false}.}
In the current implementation, this item will not react to events even if this attribute
is set.

\attribute{reticle}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{reticle}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{reticle}{composescale}{boolean}{Specifies if the current scale should be
composed with the local transform. The default value is {\tt true}.}

\attribute{reticle}{firstradius}{dimension}{This is the radius of the innermost circle of the
reticle. The default value is {\tt 80}.}

\attribute{reticle}{linecolor}{gradient}{This is the uniform (possibly transparent) color of
regular (not highlighted) circles. The first color of a real gradient color will be used.
The default value is the current value of the widget option
\optref{forecolor}.}

\attribute{reticle}{linestyle}{linestyle}{This is the line style of the regular (not
highlighted) circles. The default value is {\tt simple}.}

\attribute{reticle}{numcircles}{unsignedint}{Specifies how many circles should be drawn. The
default value is {\tt -1} which means draw as many circles as needed to encompass the
current widget window. This does not take into account any possible clipping that can mask
part of the reticle. The idea behind this trick is to draw an infinite reticle that is
optimized for the current scale.}

\attribute{reticle}{period}{unsignedint}{Specifies the recurrence of the bright circles over
the regulars. The default value is {\tt 5} which means that a bright circle is drawn then
4 regulars, etc.}

\attribute{reticle}{position}{point}{Location of the center of the reticle. The default
value is {\tt "0 0"}.}

\attribute{reticle}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 0}.}

\attribute{reticle}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt false} as the item cannot handle events.}

\attribute{reticle}{stepsize}{dimension}{The (scale sensitive) size of the step between two
consecutive circles. The default value is {\tt 80}.}

\attribute{reticle}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{reticle}{visible}{boolean}{Specifies if the item is displayed. The default value
is {\tt true}.}


\section{Map items}
\object{map}


Map items are typically used for displaying maps on a radar display view. Maps are
not be sensitive to mouse or keyboard events, but have been designed to efficiently display
large set of points, segments, arcs, and simple texts. A map item is associated to a mapinfo.
This mapinfo entity can be either initialized with the \conceptref{videomap}{videomapcmd}
command or more generally created and edited with a set of commands described in the  
\conceptref{The mapinfo related commands}{mapinfocmds} section.

  Applicable attributes for \ident{map} are:

\attribute{map}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt false}.}
In the current implementation, this item will not react to events even if this attribute
is set.

\attribute{map}{color}{gradient}{Specifies the uniform (possibly transparent) color used
to draw or fill the map. The texts and symbols that are part of the map are also drawn in
this color. The first color of a real gradient color will be used. The
default value is the current value of the widget option \optref{forecolor}.}

\attribute{map}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{map}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{map}{composescale}{boolean}{Specifies if the current scale should be composed
with the local transform. The default value is {\tt true}.}

\attribute{map}{filled}{boolean}{If set to true the map wil be filled otherwise it will be
drawn as thin lines. The default is {\tt false}.}

\attribute{map}{fillpattern}{bitmap}{Specifies the pattern to be used when filling the
map. The value should be a legal Tk bitmap. The default value is {\tt ""}.}

\attribute{map}{font}{font}{Specifies the font that will be used to drawn the texts of the
map. The default value is the current value of the widget option \optref{maptextfont}.}

\attribute{map}{mapinfo}{mapinfo}{Specifies the lines, texts, symbols and other various
graphical components that should be displayed by the map item. All these graphical
components will share the graphical attributes (color, font, etc) of the item and its
coordinate system. The default value is {\tt ""} which means that nothing will be
displayed by the map.}

\attribute{map}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 0}.}

\attribute{map}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt false} as the item cannot handle events.}

\attribute{map}{symbols}{bitmaplist}{XXX to be detailed. The default value is {\tt ??}.}

\attribute{map}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{map}{visible}{boolean}{Specifies if the item is displayed. The default value is
{\tt true}.}


\section{Rectangle items}
\object{rectangle}


  Items of type \ident{rectangle} display a rectangular shape, optionally filled. The
  rectangle is described by its bottom-left and top right corners.

  It is possible to use this item as a clip item for its group. It is also possible to use
  the rectangle in a \cmdref{contour} command to build a complex shape in a \objectref{curve}
  item. The two points describing the rectangle can be read and modified with the
  \cmdref{coords} command.

%%%% XXX CM insert here two rectangles, one rotated and with a relief!! One used as a clipper! 

  Applicable attributes for \ident{rectangle} are:

\attribute{rectangle}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{rectangle}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{rectangle}{composerotation}{boolean}{Specifies if the current rotation should
be composed with the local transform. The default value is {\tt true}.}

\attribute{rectangle}{composescale}{boolean}{Specifies if the current scale should be
composed with the local transform. The default value is {\tt true}.}

\attribute{rectangle}{fillcolor}{gradient}{Specifies the color that will be used to
fill the rectangle if requested by the \attributeref{rectangle}{filled} attribute. The default
value is a one color gradient based on the current value of the widget option \optref{forecolor}.}

\attribute{rectangle}{filled}{boolean}{Specifies if the item should be filled. The default
value is {\tt false}.}

\attribute{rectangle}{fillpattern}{bitmap}{Specifies the pattern to use when filling the
item. The default value is {\tt ""}.}

\attribute{rectangle}{linecolor}{gradient}{Specifies the uniform (possibly transparent)
color used to draw the item outline. The first color of a real gradient color
will be used. The default value is the current value of the widget option
\optref{forecolor}.}

\attribute{rectangle}{linepattern}{bitmap}{Specifies the pattern to use when drawing the
outline. The default value is {\tt ""}.}

\attribute{rectangle}{linestyle}{linestyle}{Specifies the line style to use when drawing
the outline. The default value is {\tt simple}.}

\attribute{rectangle}{linewidth}{dimension}{Specifies the width of the item outline (not
scalable). The default value is {\tt 1}.}

\attribute{rectangle}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{rectangle}{relief}{relief}{Specifies the relief used to drawn the rectangle
outline. This attribute has priority over the \attributeref{rectangle}{linepattern} and
\attributeref{rectangle}{linestyle} attributes. The color of the relief is derived from
the color in \attributeref{rectangle}{linecolor}. The default value is {\tt flat}.}

\attribute{rectangle}{sensitive}{boolean}{Specifies if the item should react to events.
The default value is {\tt true}.}

\attribute{rectangle}{tags}{taglist}{The list of tags associated with the item. The
default value is {\tt ""}.}

\attribute{rectangle}{tile}{image}{Specifies an image used for filling the item with
tiles. This will be done only if filling is requested by the \attributeref{rectangle}{filled}
attribute. This attribute has priority over the \attributeref{rectangle}{fillcolor} attribute
and the \attributeref{rectangle}{fillpattern} attribute. The default value is {\tt ""}.}

\attribute{rectangle}{visible}{boolean}{Specifies if the item is displayed. The default
value is {\tt true}.}


\section{Arc items}
\object{arc}

  Items of type \ident{arc} display an oval section, optionally filled, delimited by two
  angles. The oval is described by its enclosing rectangle. The arc can be closed either
  by a straight line joining its end points or by two segments going throught the center
  to form a pie-slice.
  
  It is possible to use this item as a clip item for its group, the clip shape will be the
  polygon obtained by closing the arc. It is also possible to use this polygon in a
  \cmdref{contour} command to build a complex shape in a \objectref{curve} item. The two points
  describing the enclosing rectangle can be read and modified with the \cmdref{coords}
  command. The first point should be the top left vertex of the rectangle and the second
  should be the bottom right.

  Applicable attributes for \ident{arc} are:

\attribute{arc}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{arc}{closed}{boolean}{Specifies if the outline of the arc should be
closed. This is only pertinent if the arc extent is less than 360 degrees. The default
value is {\tt false}.}

\attribute{arc}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{arc}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{arc}{composescale}{boolean}{Specifies if the current scale should be composed
with the local transform. The default value is {\tt true}.}

\attribute{arc}{extent}{angle}{Specifies the angular extent of the arc relative to the
start angle. The angle is expressed in degrees in the trigonometric system. The default
value is {\tt 360}.}

\attribute{arc}{fillcolor}{gradient}{ Specifies the color used to fill
the arc if requested by the \attributeref{arc}{filled} attribute. The default value is a one color
gradient based on the current value of the widget option \optref{backcolor}.}

\attribute{arc}{filled}{boolean}{Specifies if the item should be filled. The default value
is {\tt false}.}

\attribute{arc}{fillpattern}{bitmap}{Specifies the pattern to use when filling the
item. The default value is {\tt ""}.}

\attribute{arc}{firstend}{lineend}{Describes the arrow shape at the start end of the
arc. This attribute is applicable only if the item is not closed and not filled. The
default value is {\tt ""}.}

\attribute{arc}{lastend}{lineend}{Describes the arrow shape at the extent end of the
arc. This attribute is applicable only if the item is not closed and not filled. The
default value is {\tt ""}.}

\attribute{arc}{linecolor}{gradient}{Specifies the uniform (possibly transparent) color
used to draw the item outline. The first color of a real gradient color
will be used. The default value is the current value of the widget option
\optref{forecolor}.}

\attribute{arc}{linepattern}{bitmap}{Specifies the pattern to use when drawing the
outline. The default value is {\tt ""}.}

\attribute{arc}{linestyle}{linestyle}{Specifies the line style to use when drawing the
outline. The default value is {\tt simple}.}

\attribute{arc}{linewidth}{dimension}{Specifies the with of the item outline (not
scalable). The default value is {\tt 1}.}

\attribute{arc}{pieslice}{boolean}{This attribute tells how to draw an arc whose extent is
less than 360 degrees. If this attribute is true the arc open end will be drawn as a pie
slice otherwise it will be drawn as a chord. The default value is {\tt false}.}

\attribute{arc}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{arc}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt true}.}

\attribute{arc}{startangle}{angle}{Specifies the arc starting angle. The angle is
expressed in degrees in the trigonometric system. The default value is {\tt 0}.}

\attribute{arc}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{arc}{tile}{image}{Specifies an image used for filling the item with tiles. This
will be done only if filling is requested by the \attributeref{arc}{filled} attribute. This
attribute has priority over the \attributeref{arc}{fillcolor} attribute and the
\attributeref{arc}{fillpattern} attribute. The default value is {\tt ""}.}

\attribute{arc}{visible}{boolean}{Specifies if the item is displayed. The default value is
{\tt true}.}


\section{Curve items}
\object{curve}


  Items of type \ident{curve} display pathes of line segments and/or cubic bezier connected
  by their end points. A cubic Bezier is defined by four points. The first and last
  ones are the extremities of the cubic Bezier. The second and the third ones are control point
  (i.e. they must have a third ``coordinate'' with the value 'c'). If both control points
  are identical, one may be omitted. As a consequence, it is an error to have more than
  two succcessive control points or to start or finish a curve with a control point. 

  The polygon delimited by the path can optionally be filled.
  It is possible to build curve items with more than one path to
  describe complex shapes with the \cmdref{contour} command. This command can be used to
  perform boolean operations between a curve and almost any other item available in TkZinc
  including another curve. The exact appearance of a multi-contour curve (i.e. which parts
  are filled and which are holes) depends on the value of an attribute, called
  \attributeref{curve}{fillrule}. 
  In the following figure (a snapshot of \conceptref{zinc-demos}{zinc-demos}) two curves
  with four holes each are in front of a text. You can partially see the text through the holes.

\fig{textthroughholes}{Two curves with 4 holes each. A text is visible behind}{0.8}
  
  It is possible to use this item as a clip item for its group, the clip shape will be the
  polygon obtained by closing the path. The vertices can be read, modified, added or
  removed with the \cmdref{coords} command.

  Applicable attributes for \ident{curve} are:

\attribute{curve}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{curve}{capstyle}{capstyle}{Specifies the form of the outline ends. This
attribute is only applicable if the curve is not closed and the outline relief is
flat. The default value is {\tt round}.}

\attribute{curve}{closed}{boolean}{Specifies if the curve outline should be drawn between
the first and last vertex or not. The default value is {\tt false}.}

\attribute{curve}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{curve}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{curve}{composescale}{boolean}{Specifies if the current scale should be composed
with the local transform. The default value is {\tt true}.}

\attribute{curve}{fillcolor}{gradient}{Specifies the color used to fill
the curve if requested by the \attributeref{curve}{filled} attribute. The default value is
a one color gradient based on the current value of the widget option \optref{backcolor}.}

\attribute{curve}{filled}{boolean}{Specifies if the item should be filled. The default
value is {\tt false}.}

\attribute{curve}{fillpattern}{bitmap}{Specifies the pattern to use when filling the
item. The default value is {\tt ""}.}

\attribute{curve}{fillrule}{fillrule}{Specifies the way contours are combined together to
specify complex surfaces, with holes and disjoint surfaces. The default value is {\tt "odd"}.
This means that a point of the space is considered inside the curve surface if an odd number
of contours are surrounding the point. This attribute should only be modified for curves with
multiple or complicated contours.}

\attribute{curve}{firstend}{lineend}{Describes the arrow shape at the start of the curve.
This attribute is applicable only if the item is not closed, not filled and the relief of
the outline is flat. The default value is {\tt ""}.}

\attribute{curve}{joinstyle}{joinstyle}{Specifies the form of the joint between the curve
segments. This attribute is only applicable if the curve outline relief is flat. The
default value is {\tt round}.}

\attribute{curve}{lastend}{lineend}{Describes the arrow shape at the end of the curve.
This attribute is applicable only if the item is not closed, not filled and the relief of
the outline is flat. The default value is {\tt ""}.}

\attribute{curve}{linecolor}{gradient}{Specifies the uniform (possibly transparent) color
used to draw the item outline. The first color of a real gradient color will be used.
The default value is the current value of the widget option \optref{forecolor}.}

\attribute{curve}{linepattern}{bitmap}{Specifies the pattern to use when drawing the
outline. The default value is {\tt ""}.}

\attribute{curve}{linestyle}{linestyle}{Specifies the line style to use when drawing the
outline. The default value is {\tt simple}.}

\attribute{curve}{linewidth}{dimension}{Specifies the with of the item outline (not
scalable). The default value is {\tt 1}.}

\attribute{curve}{marker}{bitmap}{Specifies a bitmap that will be used to draw a mark at
each vertex of the curve. This attribute is not applicable if the outline relief is not
flat. The default value is {\tt ""} which means do not draw markers.}

\attribute{curve}{markercolor}{gradient}{Specifies the uniform (possibly transparent) color of the
markers. The first color of a real gradient color will be used.
The default value is the current value of the widget option \optref{forecolor}.}

\attribute{curve}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{curve}{relief}{relief}{Specifies the relief used to drawn the curve
outline. This attribute has priority over the \attributeref{curve}{linepattern} and
\attributeref{curve}{linestyle} attributes. The color of the relief is derived from
the color in \attributeref{curve}{linecolor}. The default value is {\tt flat}.}

\attribute{curve}{sensitive}{boolean}{Specifies if the item should react to events. The
default value is {\tt true}.}

\attribute{curve}{smoothrelief}{boolean}{Specifies if the relief should be smoothed along
the curve. This is useful to obtain smooth curved reliefs instead of facets The default
value is {\tt false}.}

\attribute{curve}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{curve}{tile}{image}{Specifies an image used for filling the item with
tiles. This will be done only if filling is requested by the \attributeref{curve}{filled} attribute.
This attribute has priority over the \attributeref{curve}{fillcolor} attribute and the
\attributeref{curve}{fillpattern} attribute. The default value is {\tt ""}.}

\attribute{curve}{visible}{boolean}{Specifies if the item is displayed. The default value
is {\tt true}.}


\section{Triangles items}
\object{triangles}

Triangles items are used for displaying complexe surfaces with variables colors
and transparencies. For example, it can be used to create a circular color selector
displaying a range of colors. The way triangles composing a triangle item are arranged
is defined by the \attributeref{triangles}{fan} option.
 
This item has been added to provide access to a basic openGL geometric construction but
it is also available in the X environment albeit with less features.

Applicable attributes for \ident{triangles} are:

\attribute{triangles}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}.}

\attribute{triangles}{colors}{gradientlist}{Specifies the colors of each vertex of the
triangles. If the list has less colors than the number of vertices the last color is
propagated on the remaining vertices. If the list contains colors in excess they are
discarded.}

\attribute{triangles}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{triangles}{composerotation}{boolean}{Specifies if the current rotation should
be composed with the local transform. The default value is {\tt true}.}

\attribute{triangles}{composescale}{boolean}{Specifies if the current scale should be
composed with the local transform. The default value is {\tt true}.}

\attribute{triangles}{fan}{boolean}{ If true, triangles are created with a fan like layout.
Otherwise triangles are arranged like a strip. The default value is {\tt true}.}

\attribute{triangles}{priority}{priority}{The absolute position in the stacking order among
siblings of the same parent group. The default value is {\tt 1}.}

\attribute{triangles}{sensitive}{boolean}{Specifies if the item should react to events.
The default value is {\tt true}.}

\attribute{triangles}{tags}{taglist}{The list of tags associated with the item. The
default value is {\tt ""}.}

\attribute{triangles}{visible}{boolean}{Specifies if the item is displayed. The default
value is {\tt true}.}


\section{Window items}
\object{window}

  Items of type \ident{window} display a Tk window, an X11 window or a Win32 window at a given position in the widget.

  It is possible to use this item as a clip item for its group, the clip shape will be the
  window rectangle. It is also possible to use the rectangular shape of the window item in
  a \cmdref{contour} command to build a complex shape in a \objectref{curve} item. The
  position of the window, relative to the anchor, can be set or read with the \cmdref{coords}
  command (i.e. if no connected item is specified).

  One of the most frequent use of this item is to embed any Tk widget into TkZinc,
  including, of course, another TkZinc instance. 

  (Compatible with old version) Another less obvious use is to embed a whole Tk application into
  TkZinc, here is how to do it: The embedding application should
  create a frame with the \ident{-container} option set to true; Add a
  window item to the relevant TkZinc widget with the
  \attributeref{window}{window} attribute set to the id of the
  container frame; The embedded application should create its toplevel
  with the  \ident{-use} option set to the id of the container frame;
  Or, as an alternative, the embedded \cident{wish} can be launched
  with the \ident{-use} option set to the container frame id.

  (With the \attributeref{windowtitle}{windowtitle} attribute) It is possible to embed a whole
  external application into TkZinc using the \ident{-windowtitle}
  attribute. The \ident{-windowtitle} attribute must specify a string
  pattern to match against the title of any running applications. The
  external application will be embedded in TkZinc and released when
  the window item is destroyed.
  
Applicable attributes for \ident{window} items are:

\attribute{window}{anchor}{anchor}{The anchor used in positionning the item. The default
value is {\tt nw}.}

\attribute{triangles}{catchevent}{boolean}{Specifies if the item should block and possibly
react to events or be transparent event wise. The default value is {\tt true}. It is not
possible to actually turn off event catching when this attribute is reset. The events are
caught by the embedded window and nothing can prevent this to happen.}

\attribute{window}{composealpha}{boolean}{Specifies if the alpha value inherited from
the parent group should be composed with the alpha of this item. The default value is {\tt true}.}

\attribute{window}{composerotation}{boolean}{Specifies if the current rotation should be
composed with the local transform. The default value is {\tt true}.}

\attribute{window}{composescale}{boolean}{Specifies if the current scale should be
composed with the local transform. The default value is {\tt true}.}

\attribute{window}{connecteditem}{item}{Specifies the item relative to which this item is
placed. Connected item should be in the same group. The default value is {\tt ""}.}

\attribute{window}{connectionanchor}{anchor}{Specifies the anchor on the connected item
used for the placement. The default value is {\tt sw}.}

\attribute{window}{height}{integer}{Specifies the height of the item window in screen
units. The default value is {\tt 0}.}

\attribute{window}{position}{point}{The item's position relative to the anchor (if no
connected item specified). The default value is {\tt "0 0"} (Tcl/Tk) or {\tt [0,0]} (Perl/Tk).}

\attribute{window}{priority}{priority}{Constraints of the underlying window system dictate
the stacking order of window items. They can't be lowered under the other
items. Additionally, to manipulate their stacking order, you must use the raise and lower
Tk commands on the associated Tk window. The value of this attribute is meaningless.}

\attribute{window}{sensitive}{boolean}{This option has no effect on window items. The
default value is {\tt false}.}

\attribute{window}{tags}{taglist}{The list of tags associated with the item. The default
value is {\tt ""}.}

\attribute{window}{visible}{boolean}{Specifies if the item is displayed. The default value
is {\tt true}.}

\attribute{window}{width}{integer}{Specifies the width of the item window in screen
units. The default value is {\tt 0}.}

\attribute{window}{window}{window}{Specifies the X id of the window that is displayed by
the item. This id can be obtained by the Tk command \ident{winfo id widgetname}. The
default value is {\tt ""}.}

\attribute{window}{windowtitle}{string}{Specifies a string pattern to
  match against the title of any running application. It may contain
  special characters from the set *?[]\textbackslash.}


%%
%%
%% C h a p t e r :   L a b e l s ,   l a b e l   f o r m a t s   a n d   f i e l d s
%%
%%
\chapter{Labels, label formats and fields}
\concept{labelsandfields}

TkZinc was initially developed for building interactive radar image working on X
server. This requires very good performances, for displaying many hundred tracks and
moving them every few second. Tracks are typically composed of some geometric parts and
some textual parts. These two parts are connected together with a leader. The geometric
parts are subject to scaling. For example the speed vector length in pixel depends on the
scale. But the textual part must not be zoomed. Managing parts which are scaled and others
which are not, can be a real challenge. Usual toolkits or widget are not suited to such
behaviours, but TkZinc is.

To be able to manage many items mixing geometric parts and non-geometric parts,
TkZinc introduces the concepts of label, labelformat, fields and fields attributes.

\section {Labels and labelformats}
\concept{label} \concept{labelformat}

A label is a set of rectangular fields attached to the following item types :
\objectref{track}, \objectref{waypoint} and \objectref{tabular}. The fields of a
label may contain either text or bitmaps or images. A label cannot be identified
or manipulated by itself; There is no function nor method to get or manipulate a
label as an object or an item. A label is always associated to an item and
is manipulated through this item.

Some label global characteristics are set/get at the item level:

\begin{itemize}
\item The maximum number of fields is defined at item creation, as the second
argument of the \cmdref{add} method. The field number can not be changed after creation.
These fields will be indexed from 0 to n-1. The number of fields can be read
with the command \cmdref{numparts}. For example:
\begin{verbatim}
 $track = $zinc->add('track',1, 4, ....);
 # this creates a track item in root group with 4 fields, indexed from 0 to 3
\end{verbatim}
% $ comment for emacs colorization only!
\item The rectangular geometries of displayable fields are defined through
the item attribut \ident{-labelformat}. The value is a string following
the syntax of the \attrtyperef{labelformat} type. This attribute can be set at any time;
thus modifying its value is a way to quickly change the geometry (or the visibility) of
some fields. Fields may overlap. They are drawn according to the index order:
field 0 is drawn before (thus under) field 1. The labelformat also optionnaly
describes a clipping rectangle. For example:
\begin{verbatim}
 $zinc->itemconfigure($track, -labelformat => 'a12a0+0+0 x20x10^0>0 a2a0>1>0');
 #                                             ^         ^          ^
 #                                             field0    field1     field2
 # the labelformat indicates that only the first 3 fields will be displayed:
 #  field 0 expands for the size of the text + 12 pixels.
 #       It starts at the top left point
 #  field 1 has a size of 20x10 pixels.
 #       It is left aligned with field 0, just under field 0
 #  field 2 expands for the size of the text + 2 pixels.
 #       It is adjacent to the right of field 1, just under field 0
\end{verbatim}
\end{itemize}

Characteristics of each individual field are called field attributes. They are all
described in next section \conceptref{Attributes for fields}{fieldAttributes}.
They may be set or get with the \cmdref{itemcget} and \cmdref{itemconfigure} command.
These commands require as a second argument the field number. By configuring
field attributes you can modify :
\begin{itemize}
\item the field content : \attributeref{field}{text}, \attributeref{field}{image},
\attributeref{field}{tile}, \attributeref{field}{fillpattern},
\item the field colors : \attributeref{field}{backcolor}, \attributeref{field}{bordercolor},
\attributeref{field}{color},
\item the text general appearance : \attributeref{field}{alignment},
\attributeref{field}{autoalignment}, \attributeref{field}{font},
\item the field border : \attributeref{field}{border}, \attributeref{field}{relief},
\attributeref{field}{reliefthickness},
\item and the field visibility and sensitivity: \attributeref{field}{sensitive},
\attributeref{field}{visible}. 
\end{itemize}

As an example:
\begin{verbatim}
 # this should display "Hello World" in white on black in field 0
 $zinc->itemconfigure($track, 0, -text => 'Hello World',
                                 -color => 'white',
                                 -backcolor => 'black',
                                 -filled => 1);
\end{verbatim}

It is possible to bind callbacks to fields, with the command \cmdref{bind} and
special tags (described \conceptref{Tags and bindings}{tagsAndBindings}).
As an example:
\begin{verbatim}
 # this binds &acallback to field 1
 $zinc->bind("$track:1", '<1>', \&acallback);
\end{verbatim}

Inside a callback function, it is possible to know which field the mouse cursor is over
with the command \cmdref{currentpart}.

A Perl module, called Tk::Zinc::Text (see the section \conceptref{Tk::Zinc::Text}{zinctext})
is provided for easing text input in text fields (it can also be used for easing text input
in \objectref{text} item).



\section{Attributes for fields}
\object{field}
\concept{fieldAttributes}

Fields are item parts of items supporting labelformat (i.e.\ \objectref{track},
\objectref{waypoint} and \objectref{tabular}). They can be configured in a similar way of
items themselves, with the command \cmdref{itemconfigure}, but this command requires an
additionnal parameter (in second position) the \ident{fieldId}. To get the value of a
field attribute, you can use the command {itemcget} with the \ident{fieldId} as an
additionnal second parameter.\\ NB: Field attributes cannot be configured at item creation
with the command \cmdref{add}.

Applicable attributes for fields are:


\attribute{field}{alignment}{alignment}{ The horizontal alignment of both the text and the
image. The default value is {\tt left}.}

\attribute{field}{autoalignment}{autoalignment}{ The dynamic horizontal alignments used
depending on the label orientation. The default value is {\tt "-"} which means do not use
dynamic alignment.}

\attribute{field}{backcolor}{gradient}{ The field background color. The default value is the
current value of the widget option \optref{backcolor}.}

\attribute{field}{border}{edgelist}{ The border description edge by edge. The border is a
one pixel wide outline that is drawn around the field outside the relief. Some border
edges can be omitted, this attribute describes the edges that should be displayed as part
of the border. The default value is {\tt ""}.}

\attribute{field}{bordercolor}{gradient}{ The border uniform (possibly transparent) color.
The first color of a real gradient color will be used.
The default value is the current value of the widget option \optref{forecolor}.}

\attribute{field}{color}{gradient}{ The text uniform (possibly transparent) color.
The first color of a real gradient color will be used.
The default value is the current value of the widget option \optref{forecolor}.}

\attribute{field}{filled}{boolean}{ Specifies if the field background should be
filled. The default value is {\tt false}.}

\attribute{field}{fillpattern}{bitmap}{ The fill pattern used when filling the
background. This attribute is overrided by the tile attribute. The default value is {\tt
""}.}

\attribute{field}{font}{font}{ The text font. The default value is the current value of
the widget option \optref{font}.}

\attribute{field}{image}{image}{ An image to be displayed in the field. The image will be
centered vertically in the field. The default value is {\tt ""}.}

\attribute{field}{relief}{relief}{ Specifies the relief to be drawn around the field,
inside the border. The color of the relief is derived from the color in
\attributeref{field}{backcolor}. The default value is {\tt flat}.}

\attribute{field}{reliefthickness}{dimension}{ Width of the relief drawn around the
field. The default value is {\tt 0} which means that no relief should be drawn around the
field.}

\attribute{field}{sensitive}{boolean}{ Specifies if the field should react to input
events. The default value is {\tt true}.}

\attribute{field}{text}{string}{ A line of text to be displayed in the field. The text
will be centered vertically in the field. The default value is {\tt ""}.}

\attribute{field}{tile}{image}{ Specifies an image that will be tiled over the field
background is the field is filled. This attribute has precedence over the
\attributeref{field}{fillpattern} attribute. The default value is {\tt ""}.}

\attribute{field}{visible}{boolean}{ Specifies if the field is displayed. The default
value is {\tt true}.}


%%
%%
%% C h a p t e r :   A t t r i b u t e   t y p e s
%%
%%
\chapter{Attribute types}
\concept{types}

We describe in this chapter all the available types in TkZinc. They are listed by
alphabetical order.

\emph{NB: Two types are very important and their existence should be known
by any new user of TkZinc: \attrtyperef{gradient} and \attrtyperef{labelformat}.}


\attrtype{alignment}
\begin{blockindent}
  Specifies the horizontal alignment of an entity. The legal values are: {\tt left}, {\tt
  right}, {\tt center}.
\end{blockindent}

\attrtype{alpha}
\begin{blockindent}
  Specifies the transparency of an item. The value must be an integer from 0 (fully
  transparent) to 100 (fully opaque).
\end{blockindent}

\attrtype{anchor}
\begin{blockindent}
  Specifies one of the nine characteristic points of a rectangle or a bounding box that will
  be used to position the object. These points include the four corners, the four edge
  centers, and the center of the rectangle. The possible values are: {\tt nw}, {\tt n},
  {\tt ne}, {\tt e}, {\tt se}, {\tt s}, {\tt sw}, {\tt w}, {\tt center}.
\end{blockindent}

\attrtype{angle}
\begin{blockindent}
  Specifies an angle in degrees, the value must be an integer from 0 to 360 inclusive.
\end{blockindent}

\attrtype{autoalignment}
\begin{blockindent}
  Specifies the horizontal alignments that should be used for track or way point fields
  depending on the label position relative to the position of the item. The attribute may
  have two forms: a single dash {\tt -} means turning of the automatic alignment feature
  for the field; The other form consists in three letters which describe in order: the
  alignment to be used when the label is to the left of the item position, above or below
  the item position and to the right of the item position. The possible values for each
  letter is: {\tt l} for left alignment, {\tt c} for center alignment and {\tt r} for
  right alignment. Here is an example: {\tt rll} means right align the field if the label
  is on the left side of the item, and left align if the label is above, below or on the
  right of the item.
\end{blockindent}

\attrtype{bitmap}
\begin{blockindent}
  This should be a string naming a valid Tk bitmap. The bitmap should be known to Tk prior
  to its use. TkZinc registers a set of bitmaps that can be used for any bitmap valued
  attribute (see section \conceptref{Bitmaps}{builtinbitmaps}). Extensions to Tk are available to create or
  manipulate bitmaps from a script. The value may also name a file containing a valid X11
  bitmap description. The syntax in this case is {\tt @filename}.
\end{blockindent}

\attrtype{bitmaplist}
\begin{blockindent}
  This is an extension of the \attrtyperef{bitmap} attribute type. It describes a list of
  bitmaps that will be the value of the attribute.
\end{blockindent}

\attrtype{boolean}
\begin{blockindent}
  This is the description of a standard Tcl boolean value. The possible values are {\tt
  0}, {\tt false}, {\tt no} or {\tt off} for the false value and {\tt 1}, {\tt true}, {\tt
  yes} or {\tt on} for the true value.
\end{blockindent}

\attrtype{capstyle}
\begin{blockindent}
  This the description of a line cap. The possible values are {\tt butt}, {\tt projecting}
  and {\tt round}.
\end{blockindent}

\attrtype{dimension}
\begin{blockindent}
  This is a string that represent distance. The string consists in a floating point signed
  number.
\end{blockindent}

\attrtype{edgelist}
\begin{blockindent}
  This is a list describing the edges of a border that should be considered for processing
  (e.g for drawing). The possible values are {\tt left}, {\tt right}, {\tt top}, {\tt
  bottom}, {\tt contour}, {\tt oblique} and {\tt counteroblique}. The {\tt contour} value
  is the same as the {\tt "left top right bottom"} list. The {\tt oblique} and {\tt
  counteroblique} values describe diagonal segments from top-left to bottom-right and from
  top-right to bottom-left respectively. The following picture gives some edges examples.

\fig{alledges}{edgelist examples}{0.5}

\end{blockindent}


\attrtype{fillrule}
\begin{blockindent}
  This is a string describing the rule used to compose the different contours or pathes of
  a curve. The allowed values are directly inspired from the openGL GLU tesselators as
described for example in the chapter 11 of the ``The OpenGL Programming Guide 3rd Edition
The Official Guide to Learning OpenGL Version 1.2'',  ISBN 0201604582. You can also refer to
the example fillrule provided with TkZinc in \conceptref{zinc-demos}{zinc-demos}. The allowed values are
{\tt odd}, {\tt nonzero}, {\tt positive}, {\tt negative}, and {\tt abs\_geq\_2}.
The following figure shows the effect of fillrule value on curves with multiple contours:

\fig{fillrule}{Examples of fillrule on curves}{0.4}

\end{blockindent}


\attrtype{font}
\begin{blockindent}
  This is a string describing a font. For an exhaustive description of what is legal as a
  font description, refer to the Tk \ident{font} command man page. Just to mention to
  popular methods, it is possible to specify a font by it's X11 font name or by a list
  whose elements are the font family, the font size and then zero or more styles including
  {\tt normal}, {\tt bold}, {\tt roman}, {\tt italic}, {\tt underline}, {\tt overstrike}.

  {\bf Please note, that some font data are cached by TkZinc, on the application level. 
   This is specially usefull with openGL}. To avoid breaking the cache mecanism, you 
   should avoid using a font once on only one item, then modifiy this item font
   and repeat this again and again.
\end{blockindent}

\attrtype{gradient}
\begin{blockindent}
  This is a string describing a color gradient to be used for example to fill a surface.
  Gradient are also used to describe color of lines, even if in this case the lines are
  limited to one color with and optionnal alpha percentage.

  The string may consist in a single color specification that will be used to paint a solid surface
  or a color with an alpha value or a list of gradient steps separated by \verb+|+ characters.

  \begin{itemize}
  \item  The general pattern for an axial gradient is :
  
  \verb+"=axial degre | gradient_step1 | ... | gradient_stepn"+ or

  \verb+"=axial x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn"+

  The \verb+degre+ parameter defines the angle of the axe in the usual
  trigonometric sense. It defaults to 0. The \verb+x1 y1 x2 y2+ parameters
  define both the angle and the extension of the axe.


  \item The general pattern for a radial gradient is :

  \verb+"=radial x y | gradient_step1 | ... | gradient_stepn"+ or

  \verb+"=radial x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn"+

  The \verb+x y+ parameters define the center of the radial. The \verb+x1 y1 x2 y2+
  parameters define both the center and the extension of the radial.


  \item The general pattern for a path gradient is :

  \verb+"=path x y | gradient_step1 | ... | gradient_stepn"+

  The \verb+x y+ parameters define the center of the gradient.


  \item The general pattern for a conical gradient is :

  \verb+"=conical degre | gradient_step1 | ... | gradient_stepn"+ or

  \verb+"=conical degre x y | gradient_step1 | ... | gradient_stepn"+ or

  \verb+"=conical x1 y1 x2 y2 | gradient_step1 | ... | gradient_stepn"+

  The \verb+degre+ parameter defines the angle of the cone in the usual
  trigonometric sense. The optional \verb+x y+ parameters define the center of
  the cone. By default, it is the center of the bounding-box.
  The \verb+x1 y1 x2 y2+ parameters define the center and the angle of the cone.

  \end{itemize}

  All x and y coordinates are expressed in percentage of the bounding box, relatively
  to the center of the bounding box. So \verb+0 0+ means the center while \verb+-50 -50+
  means the lower left corner of the bounding box.

  If none of the above gradient type specification is given, the gradient will be drawn as
  an axial gradient with a null angle.

  Each gradient segment section has the general form:
  
    \verb+color;alpha color_position mid_span_position+

  Each color can be specified as a valid X color : either a named color or \#rrggbb value
  or any valid X color specification such as  standard device-independent color specification
  (e.g. \verb+CIEuvY:<u>/<v>/<Y>+ as defined in the X man page). An alpha value
  can be applied to the color using the optional \verb+;alpha+ parameter whose value should be in the
  0..100 intervalle.

  The color position tells where in the gradient surface, measured as a percentage of the
  total gradient distance, the color should start. The first gradient segment has its
  position set to 0 and the last segment has its position set to 100, regardless of the
  specification. The position can thus be safely omitted for these segments. The in
  between segments must have a position explicitly set. If not given, the position will
  default to 0.

  The mid span position tells where in the current gradient segment should be the median
  color. The position is given in percentage of the current gradient segment distance.
  The mid span position can be used to obtain a non linear gradient segment, this is
  useful to describe relief shapes. This parameter can be omitted in which case it
  defaults to 50 and the gradient segment is perfectly linear.

  A gradient segment can be specified as a single color. In this case a flat uniform fill
  will result.

  The following picture gives many examples of gradients. They correspond to the following values:

\verb+axial 1 :  '=axial 0 | black|white'  :=  'black|white'+

\verb+axial 2 :  '=axial 90 | black|white'+

\verb+axial 3 :  '=axial 30 |black|white'+

\verb+axial 4 :  '=axial 30|black|black;0'+

\verb+radial 1 : '=radial -14 -20|white|black'+

\verb+radial 2 : '=radial 0 0 | white;50 0 70|black 50|white 100'+

\verb+path 1 :   '=path -14 -20|white|black;80'+

\verb+path 2 :   '=path -14 -20 |white|white 30|black;80'+

\fig{allgradients}{Examples of axial, radial and path gradients}{0.5}

\end{blockindent}

\attrtype{gradientlist}
\begin{blockindent}
  This is an extension of the \attrtyperef{gradient} attribute type. It describes a list of
  gradients that will be the value of the attribute.
\end{blockindent}

\attrtype{image}
\begin{blockindent}
  This should be the name of a previously registered Tk image. 

  In pure Tcl-Tk only GIF, PPM
  and bitmap formats are available as source for images. With the Img extension many
  others popular formats are added including JPEG, XPM and PNG.

  In Perl/Tk most image formats can be used, specially with Tk::JPEG or Tk::PNG modules.

  {\bf Please note, that some image data are cached by TkZinc, on the application level. 
   This is specially usefull with openGL}. To avoid breaking the cache mecanism, you 
   should avoid using an image once on only one item option, then modifiy this item option
   and repeat this again and again.

\end{blockindent}

\attrtype{item}
\begin{blockindent}
  Describes an item id or a tag. If a tag is provided an item will be searched for the tag
  and the first matching in display list order will be used.
\end{blockindent}

\attrtype{joinstyle}
\begin{blockindent}
  Describes a join style. The possible values are {\tt bevel}, {\tt miter} and {\tt
  round}.
\end{blockindent}

\attrtype{labelformat}
\begin{blockindent}
  The format is as follow. Parameters between \verb+[]+ are optional and take default values
  when omitted. Spaces can appear between blocks but not inside.
  
  \verb+[WidthxHeight] [<field0Spec>] [<field1Spec>] ... [<fieldnSpec>]+
  
  \verb+Width+ and \verb+Height+ are strictly positive integers. They set
  the size of the clipping box surrounding the label. If not specified,
  there will be no clipping. If specified alone, they specify the size of
  the only displayed field which index is 0.

  \verb+<fieldiSpec> ::= <fieldiSize>[<fieldiPos>]+

  Each fieldiSpec specify the size and position of the field numbered i.

  \verb+<fieldiSize> ::= <sChar><fieldWidth><sChar><fieldHeight>+

  \verb+<sChar> ::= x|f|i|a|l+

  \verb+<sChar>+ specifies the meaning of the following \verb+<fieldWidth>+ or
  \verb+<fieldHeight>+. Those are positive integers. Values for \verb+<sChar>+
  have the following meaning :

  \begin{itemize}
  \item \verb+'x'+ : the corresponding dimension (either width or height) is in pixel,
   according to the value of the \verb+<fieldWidth>+ or \verb+<fieldHeight>+
  \item \verb+'f'+ : the corresponding dimension is in percentage of the mean
   width/height of a character (in the field font). The following \verb+<fieldWidth>+
   or \verb+<fieldHeight>+ gives the percentage. The value must be an integer between
   0 and 100.
%%% XXX CM How is computed ``the mean width/height of a character''
  \item \verb+'i'+ : the corresponding dimension is in percentage of the size of the
   image in the field. The following \verb+<fieldWidth>+ or \verb+<fieldHeight>+ gives
   the percentage. The value must be an integer between 0 and 100. If the field contains
   no image, the dimension is 0.
  \item \verb+'a'+ : the corresponding dimension is automatically adjusted to match
   the field's content plus the given value in pixels.
  \item \verb+'l'+ : the corresponding dimension is adjusted to match the
   global size of the label (not counting fields with \verb+'l'+ size specs). The
   corresponding integer parameter is not used with this size specification.
   The global size of the label is considered when the labelformat is set. If some fields
   sizes change afterwards, you should set again the labelformat so that fields using
   a \verb+'l'+ specification are re-computed.
   It is not possible to reference the field in another \verb+<fieldiPos>+ (see below).
  \end{itemize}
  
  \verb+<fieldiPos> ::= <pChar><fieldX><pChar><fieldY>+.

  \verb-<pChar> ::= +|<|>|^|$-
%$ this comment if for emacs coloring only!

  \verb+<fieldX>+  and \verb+<fieldY>+ are either integer or index refering an
  other field of the labelformat. 

  Values for \verb+pChar+ have the following meaning :

  \begin{itemize}
  \item \verb-'+'- : the position, either on the X or Y axis, is in pixel, possibly
  negative. XXX what does it mean if negative? The value is given by the corresponding
 \verb+<fieldX>+ or \verb+<fieldY>+.
  \item \verb+'<'+ : The field will be at the left (or top) of the field refered
  by the corresponding index \verb+<fieldX>+ (or \verb+<fieldY>+)
  \item \verb+'>'+ : The field will be at the right (or bottom) of the field refered
  by the corresponding index \verb+<fieldX>+ (or \verb+<fieldY>+)
  \item \verb+'^'+ :  The field will be left (or top) aligned with the field refered
  by the corresponding index \verb+<fieldX>+ (or \verb+<fieldY>+).
  \item \verb+'$'+ : The field will be right (or bottom) aligned with the field refered
  by the corresponding index \verb+<fieldX>+ (or \verb+<fieldY>+).
%$ this comment if for emacs coloring only!
  \end{itemize}
  
  \verb+<fieldiPos>+ can be omitted if there is only one field.
\end{blockindent}

\attrtype{leaderanchors}
\begin{blockindent}
  Describes where to attach the label leader on the label. Two positions can be defined: one 
  when the label is at the right of current position and the other when the label is at the 
  left of current position. {\bf Not to be confused with the regular rectangular anchors}.
  
  The format is: \verb+lChar leftLeaderAnchor [lChar rightLeaderAnchor]+
  
  If \verb+lChar+ is a \verb+|+, \verb+leftLeaderAnchor+ and \verb+rightLeaderAnchor+ are
  the indices of the field that serve to anchor the label's leader. More specifically the
  bottom right corner is used when \verb+leftLeaderAnchor+ is active and the bottom left
  corner is used when \verb+rightLeaderAnchor+ is active.

  If \verb+lChar+ is \verb+%+, \verb+leftLeaderAnchor+ and \verb+rightLeaderAnchor+ should
  be specified as \verb+widthPercentxheightPercent+, each value being a percentage
  (between 1 and 100) of the width or height of the label bounding box. If
  \verb+rightLeaderAnchor+ is not specified it defaults to \verb+leftLeaderAnchor+. If
  neither are specified, the center of the label is used as an anchor.
\end{blockindent}

\attrtype{lineend}
\begin{blockindent}
  Describes the shape of the arrow at the beginning or end of a path. This is a list of
  three numbers describing the arrow shape in the following order: distance along the axis
  from neck to tip of the arrowhead, distance from trailing points to tip and distance
  from outside edge of the line to the trailing points (see canvas). If an empty list is
  given, there is no arrow.
\end{blockindent}

\attrtype{lineshape}
\begin{blockindent}
  Describes the shape of a path connecting two points. The possible values are {\tt
  straight}, {\tt rightlightning}, {\tt leftlightning}, {\tt rightcorner}, {\tt
  leftcorner}, {\tt doublerightcorner} and {\tt doubleleftcorner}. The following figure
  shows these different line shapes:

\fig{alllineshapes}{Examples of all available line shapes}{0.4}

\end{blockindent}

\attrtype{linestyle}
\begin{blockindent}
  Describes the style of the dashes that should be used to draw a line. The possible
  values are {\tt simple}, {\tt dashed}, {\tt mixed} and {\tt dotted}.
\end{blockindent}

\attrtype{mapinfo}
\begin{blockindent}
  This is the name of a previously registered mapinfo object (see the chapter
  \conceptref{The mapinfo related commands}{mapinfocmds}) that will define the lines, arcs,
  symbols, and texts displayed in a map item.
\end{blockindent}

\attrtype{point}
\begin{blockindent}
  This is a list of two floating point values that describes a point position or some two
  dimensional delta (used for example to describe the speed vector of a track item).
\end{blockindent}

\attrtype{priority}
\begin{blockindent}
  A strictly positive integer value for the display priority.
\end{blockindent}

\attrtype{relief}
\begin{blockindent}
  Describes a border relief. The possible values, illustrated in the following figure are
  {\tt flat},
  {\tt raised},  {\tt sunken}, {\tt ridge}, {\tt groove},
  {\tt roundraised}, {\tt roundsunken},  {\tt roundridge}, {\tt roundgroove},
  {\tt raisedrule}, {\tt sunkenrule}.

\fig{allreliefs}{Examples of all available non-flat reliefs}{0.5}

\end{blockindent}

\attrtype{string}
\begin{blockindent}
  Just what its name implies, a string.
\end{blockindent}

\attrtype{taglist}
\begin{blockindent}
  This should be a list of strings describing the tags that are set for an item.
\end{blockindent}

\attrtype{unsignedint}
\begin{blockindent}
  Describes an unsigned integer value.
\end{blockindent}

\attrtype{window}
\begin{blockindent}
  A string describing an X window id. This id can be returned by the {\tt winfo id
  a-widget-path} command.
\end{blockindent}



%%
%%
%% C h a p t e r :   T h e   m a p i n f o   c o m m a n d s
%%
%%
\chapter{The mapinfo related commands}
\concept{mapinfocmds}

  MapInfo objects are used to describe graphical primitives that will be displayed in map
  items. It is possible to describe lines, arcs, symbols and texts as part of a
  MapInfo. The \ident{mapinfo} and \ident{videomap} commands are provided to create and
  manipulate the mapinfo objects.

\section{The mapinfo command}

\mapinfocmd{name}{create}{}
\begin{blockindent}
  Create a new empty map description. The new mapinfo object named {\tt name}.
\end{blockindent}

\mapinfocmd{mapInfoName}{delete}{}
\begin{blockindent}
  Delete the mapinfo object named by {\tt mapInfoName}. All maps that refer to the deleted
  mapinfo are updated to reflect the change.
\end{blockindent}

\mapinfocmd{mapInfoName}{duplicate}{newName}
\begin{blockindent}
  Create a new mapinfo that is a exact copy of the mapinfo named {\tt mapInfoName}. The
  new mapinfo object will be named {\tt newName}.
\end{blockindent}

\mapinfocmd{name}{add}{type args}
\begin{blockindent}
  Add a new graphical element to the mapinfo object named by {\tt name}. The {\tt type}
  parameter select which element should be added while the {\tt args} arguments provide
  some type specific values such as coordinates. Here is a description of recognized types
  and their associated parameters.
  
  \begin{description}
  \item{line} \\ This element describes a line segment. Its parameters consists in a line
  style ({\tt simple}, {\tt dashed}, {\tt dotted}, {\tt mixed}, {\tt marked}), an integer
  value setting the line width in pixels and four integer values setting the X and Y
  coordinates of the two end vertices.
  \item{arc} \\ This element describes an arc segment. Its parameters consists in a line
  style ({\tt simple}, {\tt dashed}, {\tt dotted}, {\tt mixed}, {\tt marked}), an integer
  value setting the line width in pixels, two integer values setting the X and Y of the
  arc center, integer value setting the arc radius and two integer values setting the
  start angle (in degree) and the angular extent of the arc (in degree).
  \item{symbol} \\ This element describes a symbol. Its parameters consists in two integer
  values setting the X and Y of the symbol position and an integer setting the symbol
  index in the {\tt -symbols} list of the map item.
  \item{text} \\ This element describes a line of text. Its parameters consists in a text
  style ({\tt normal}, {\tt underlined}), a line style ({\tt simple}, {\tt dashed}, {\tt
  dotted}, {\tt mixed}, {\tt marked}) to be used for the underline, two integer values
  setting the X and Y of the text position and a string describing the text.
  \end {description}
  
\end{blockindent}

\mapinfocmd{name}{count}{type}
\begin{blockindent}
  Return an integer value that is the number of elements matching {\tt type} in the
  mapinfo named {\tt name}. {\tt type} may be one the legal element types as described in
  the {\tt mapinfo add} command.
\end{blockindent}

\mapinfocmd{name}{get}{type index}
\begin{blockindent}
  Return the parameters of the element at {\tt index} with type {\tt type} in the mapinfo
  named {\tt name}. The returned value is a list. The exact number of parameters in the
  list and their meaning depend on {\tt type} and is accurately described in
  \ident{mapinfo add}. {\tt type} may be one the legal element types as described in the
  {\tt mapinfo add} command. Indices are zero based and elements are listed by type.
\end{blockindent}

\mapinfocmd{name}{replace}{type index args}
\begin{blockindent}
  Replace all parameters for the element at {\tt index} with type {\tt type} in the
  mapinfo named {\tt name}. The exact number and content for {\tt args} depend on {\tt
  type} and is accurately described in \ident{mapinfo add}. {\tt type} may be one the
  legal element types as described in the {\tt mapinfo add} command. Indices are zero
  based and elements are listed by type.
\end{blockindent}

\mapinfocmd{name}{remove}{type index}
\begin{blockindent}
  Remove the element at {\tt index} with type {\tt type} in the mapinfo named {\tt
  name}. {\tt type} may be one the legal element types as described in the {\tt mapinfo
  add} command. Indices are zero based and elements are listed by type.
\end{blockindent}

\mapinfocmd{name}{scale}{factor}
\begin{blockindent}
  Scale all coordinates of all the elements described in the mapinfo named {\tt name} by
  {\tt factor}. The same value is used for X and Y axes.
\end{blockindent}

\mapinfocmd{name}{translate}{xAmount yAmount}
\begin{blockindent}
  Translate all coordinates of all the elements described in the mapinfo named {\tt
  name}. The {\tt xAmount} value is used for the X axis and the {\tt yAmount} value is
  used for the Y axis.
\end{blockindent}



\section{The videomap command}
\concept{videomapcmd}

 This section describes the videomap command, used to create a mapinfo from a proprietary
 file format for simple maps, in use in french Air Traffic Control Centres. The format is the
 binary cautra4 (with x and y in 1/8nm units) 

\command{videomap}{ids}{fileName}
\begin{blockindent}
  Return all sub-map ids that are described in the videomap file described by {\tt
  fileName}. The ids are listed in file order. This command makes possible to iterate
  through a videomap file one sub-map at a time, to know how much sub-maps are there and
  to sort them according to their ids.
\end{blockindent}

\command{videomap}{load}{fileName index mapInfoName}
\begin{blockindent}
  Load the videomap sub-map located at position {\tt index} in the file named {\tt
  fileName} into a mapinfo object named {\tt mapInfoName}. It is possible, if needed, to
  use the \ident{videomap ids} command to help translate a sub-map id into a sub-map file
  index.
\end{blockindent}


%%
%%
%% C h a p t e r :   O t h e r   r e s o u r c e s   p r o v i d e d
%%
%%
\chapter{Other resources provided by the widget}
\concept{otherresources}

In this chapter we describe resources included in TkZinc widget. This include
bitmaps sets (used as symbols for some items or used as stipples), Perl modules goodies
and TkZinc simple demonstrations.

\section{Bitmaps}
\concept{builtinbitmaps}

TkZinc creates two sets of bitmaps.

The first set contains symbols for ATC tracks position, waypoints position and maps
symbols. These bitmaps are named AtcSymbol1 to AtcSymbol22.

\fig{atcsymb}{Bitmaps available for position of tracks, waypoints, and maps}{0.5}


The second set provides stipples that can be used to implement transparency, they are
named AlphaStipple0 to AlphaStipple15, AlphaStipple0 being the most transparent.

\fig{alphastip}{Bitmaps available for creating stipples}{0.5}

\tolerance 2000  %allow somewhat looser lines.
\hbadness 10000  %don't complain about underfull lines.


\section{Tk::Zinc::Debug Perl module}

\ident{Tk::Zinc::Debug.pm} is a Perl module useful for debugging purpose. It can be used in a
Perl application using TkZinc to display the hierarchical tree of items, to display
items selected by their id or tags, to grab items with the mouse and to get the list of
items enclosed or overlapped by a rectangle designated by the mouse. You will be
presented a list of items, with many interesting attributes such as position, priority,
visibility, group...\ and even more information on request. Much of the selected items
attributes can be interactively modified. When an application uses
\ident{Tk::Zinc::Debug.pm}, you can get a short reminder by depressing the {\tt Esc} key in
the main window of this application. For more information, please refer to the
\ident{Tk::Zinc::Debug.pm} man pages with the classical command {\tt man Tk::Zinc::Debug}

To use this module, you can import it either by adding, for example, the following
statements in your source code:
\begin{verbatim}
  use Tk::Zinc::Debug;

  finditems($zinc);
  tree($zinc, -optionsToDisplay => '-tags', -optionsFormat => 'row');
\end{verbatim}

or simply by using the -M option of Perl:

\begin{verbatim}
  perl -MTk::Zinc::Debug yourscript.pl
\end{verbatim}

\section{Tracing TkZinc methods call in Perl/Tk}

TkZinc package includes two tools for helping you debugging your Perl/Tk scripts
or tracking some nasty segfault which should never occure since TkZinc is
(almost) totally bugfree.

\subsection{Tracking Perl/Tk script errors}

Because you sometime get some errors inside \ident{TkZinc} with a cryptic message
like {\tt ".... errors in Tk.pm line 228"}, it may be usefull to know where exactly
in your code is the error. There is a simple and convenient mean to do this, just
by using a small module called \ident{Tk::Zinc::TraceErrors}, released with \ident{TkZinc}.
It traces every call of a TkZinc method inducing a Tk error. It prints on
the standard output the following informations:
\begin{itemize}
\item the filename where the method has been invoked
\item the line number in the source file
\item the TkZinc method name
\item the list of arguments in a human-readable form
\item the error message
\end{itemize}

To use this module you can import it either by adding the following
statement in your source code:
\begin{verbatim}
  use Tk::Zinc::TraceErrors;
\end{verbatim}

or better, by using the -M option of Perl:

\begin{verbatim}
  perl -MTk::Zinc::TraceErrors yourscript.pl
\end{verbatim}

\subsection{Tracking TkZinc segfaults in Perl/Tk}

If you encounters a segfault in one Perl/Tk script and you suspects
that TkZinc might be responsible, you should use a small module called
\ident{Tk::Zinc::Trace}, released with \ident{TkZinc}.
It traces every call of a TkZinc method. The method call is printed
on the standard output before the effective call, and the
result of the invokation is printed after the call. To be sure
to identify a segfault at the proper time, it forces an update of TkZinc
widget. Thus, this might slow down your script, but should dramatically 
speed up the identification of the call which makes TkZinc segfaulting.
It prints on the standard output the following informations:
\begin{itemize}
\item the filename where the method has been invoked
\item the line number in the source file
\item the TkZinc method name
\item the list of arguments in a human-readable form
\item the returned value
\end{itemize}

To use this module you can import it either by adding the following
statement in your source code:
\begin{verbatim}
  use Tk::Zinc::Trace;
\end{verbatim}

or better, by using the -M option of Perl:

\begin{verbatim}
  perl -MTk::Zinc::Trace yourscript.pl
\end{verbatim}


\section{zinc-demos}
\concept{zinc-demos}

Starting at version 3.2.4 of TkZinc small applications are included as demos. They
are all accessible through an application called \ident{zinc-demos}. These numerous
(about 30) tiny demos are useful for newcomers and as starting points for developing
real applications. They consists in toy applications, graphically advanced examples
or even a TkZinc port of \ident{TkTetris} from Slaven Rezic.

\section{Tk::Zinc::Graphics Perl module}
\concept{zincGraphics}

The Tk::Zinc::Graphics Perl module implements many high level functions for 
building high quality graphic objects with TkZinc.

Please read the man page for more details: {\tt man Tk::Zinc::Graphics}, french 
version only currently. Any volontear to translate it in English?

NB: There is also a tcl version of this module.

\section{Tk::Zinc::Text Perl module}
\concept{zinctext}

The Tk::Zinc::Text Perl module implements bindings for text input 'a la emacs'.
It works for text item or for text fields of track, waypoint or tabular items.
The item which requires text input must just be tagged with the 'text' tag.

Please read the man page for more details: {\tt man Tk::Zinc::Text}

\section{C api for adding new items}
\concept{Capi}

The C function AddItemClass provided with the source code of TkZinc, can be used to extent
the default set of items in TkZinc in an additionnal dynamic library. The AddItemClass C
function is extensively used for implementing the core item set. So please refer to the source
code for examples or send email for more information on precise problems.

We will try to further document this feature in the future.

\section{C++ api to TkZinc}
\concept{C++api}

In the course of the development of IntuiKit, IntuiLab developed a C++ API to TkZinc. 
This wrapper gives access to functions of TkZinc for opening/closing of a Tkzinc window, 
creating/destroying items, using colour gradients, events, access to the mainloop... 
directly in C++ by hiding the use of Tk. This source code (as well as samples and tests) are
distributed with TkZinc. IntuiLab choose the same licence than TkZinc, ie LGPL. 
The C++ API does not fully cover all TkZinc functions, but most of them can be 
easily extended (e.g. the access of some ATC items currently not wrapped such as 
track, waypoint, tabular...).

The C++ api is fully documented and have been largely tested by IntuiLab for its own need.

IntuiLab hopes this wrapper will be useful to the TkZinc community.

%\listoftables

\listoffigures


\printindex

\label{interne:DernierePage}


\end{document}

Added jni/tkzinc/doc/tabularexample.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/textthroughholes.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/tkzinclogo.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/trackexample.png.

cannot compute difference between binary files

Added jni/tkzinc/doc/waypointexample.png.

cannot compute difference between binary files

Added jni/tkzinc/generic/Arc.c.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
/*
 * Arc.c -- Implementation of Arc item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Wed Mar 30 16:24:09 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Item.h"
#include "Geo.h"
#include "Draw.h"
#include "Types.h"
#include "Image.h"
#include "WidgetInfo.h"
#include "tkZinc.h"


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 * Bit offset of flags.
 */
#define FILLED_BIT      1<<0    /* If the arc is filled with color/pattern */
#define CLOSED_BIT      1<<1    /* If the arc outline is closed */
#define PIE_SLICE_BIT   1<<2    /* If the arc is closed as a pie slice or a chord */

#define FIRST_END_OK    1<<3
#define LAST_END_OK     1<<4
#define USING_POLY_BIT  1<<5


static double Pick(ZnItem item, ZnPick ps);


/*
 **********************************************************************************
 *
 * Specific Arc item record.
 *
 **********************************************************************************
 */
typedef struct _ArcItemStruct {
  ZnItemStruct  header;
  
  /* Public data */
  ZnPoint       coords[2];
  int           start_angle;
  int           angle_extent;
  ZnImage       line_pattern;
  ZnGradient    *fill_color;
  ZnGradient    *line_color;
  ZnDim         line_width;
  ZnLineStyle   line_style;
  ZnLineEnd     first_end;
  ZnLineEnd     last_end;
  ZnImage       tile;
  unsigned short flags;

  /* Private data */
  ZnPoint       orig;
  ZnPoint       corner;
  ZnList        render_shape;
  ZnPoint       *grad_geo;
} ArcItemStruct, *ArcItem;


static ZnAttrConfig     arc_attrs[] = {
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(ArcItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-closed", NULL,
    Tk_Offset(ArcItemStruct, flags), CLOSED_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(ArcItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(ArcItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(ArcItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ANGLE, "-extent", NULL,
    Tk_Offset(ArcItemStruct, angle_extent), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
    Tk_Offset(ArcItemStruct, fill_color), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-filled", NULL,
    Tk_Offset(ArcItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
    Tk_Offset(ArcItemStruct, tile), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_END, "-firstend", NULL,
    Tk_Offset(ArcItemStruct, first_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_END, "-lastend", NULL,
    Tk_Offset(ArcItemStruct, last_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
    Tk_Offset(ArcItemStruct, line_color), 0,
    ZN_DRAW_FLAG|ZN_BORDER_FLAG, False },
  { ZN_CONFIG_BITMAP, "-linepattern", NULL,
    Tk_Offset(ArcItemStruct, line_pattern), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
    Tk_Offset(ArcItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-linewidth", NULL,
    Tk_Offset(ArcItemStruct, line_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-pieslice", NULL,
    Tk_Offset(ArcItemStruct, flags), PIE_SLICE_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(ArcItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(ArcItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_ANGLE, "-startangle", NULL,
    Tk_Offset(ArcItemStruct, start_angle), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(ArcItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_IMAGE, "-tile", NULL,
    Tk_Offset(ArcItemStruct, tile), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(ArcItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
      Tcl_Obj *CONST    *args[])
{
  ZnWInfo       *wi = item->wi;
  ArcItem       arc = (ArcItem) item;
  unsigned int  num_points;
  ZnPoint       *points;

  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 1;

  arc->start_angle = 0;
  arc->angle_extent = 360;
  CLEAR(arc->flags, FILLED_BIT);
  CLEAR(arc->flags, CLOSED_BIT);
  CLEAR(arc->flags, PIE_SLICE_BIT);
  CLEAR(arc->flags, USING_POLY_BIT);
  arc->line_pattern = ZnUnspecifiedImage;
  arc->tile = ZnUnspecifiedImage;
  arc->line_style = ZN_LINE_SIMPLE;
  arc->line_width = 1;
  arc->first_end = arc->last_end = NULL;
  arc->render_shape = NULL;
  arc->grad_geo = NULL;
  
  if (*argc < 1) {
    Tcl_AppendResult(wi->interp, " arc coords expected", NULL);
    return TCL_ERROR;
  }
  if (ZnParseCoordList(wi, (*args)[0], &points,
                       NULL, &num_points, NULL) == TCL_ERROR) {
    return TCL_ERROR;
  }
  if (num_points != 2) {
    Tcl_AppendResult(wi->interp, " malformed arc coords", NULL);
    return TCL_ERROR;
  };
  arc->coords[0] = points[0];
  arc->coords[1] = points[1];
  (*args)++;
  (*argc)--;

  arc->fill_color = ZnGetGradientByValue(wi->fore_color);
  arc->line_color = ZnGetGradientByValue(wi->fore_color);
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  ArcItem       arc = (ArcItem) item;

  if (arc->tile != ZnUnspecifiedImage) {
    arc->tile = ZnGetImageByValue(arc->tile, ZnUpdateItemImage, item);
  }
  if (arc->first_end) {
    ZnLineEndDuplicate(arc->first_end);
  }
  if (arc->last_end) {
    ZnLineEndDuplicate(arc->last_end);
  }
  if (arc->line_pattern != ZnUnspecifiedImage) {
    arc->line_pattern = ZnGetImageByValue(arc->line_pattern, NULL, NULL);
  }
  arc->line_color = ZnGetGradientByValue(arc->line_color);
  arc->fill_color = ZnGetGradientByValue(arc->fill_color);
  arc->grad_geo = NULL;
  if (arc->render_shape) {
    arc->render_shape = ZnListDuplicate(arc->render_shape);
  }
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  ArcItem       arc = (ArcItem) item;

  if (arc->render_shape) {
    ZnListFree(arc->render_shape);
  }
  if (arc->first_end) {
    ZnLineEndDelete(arc->first_end);
  }
  if (arc->last_end) {
    ZnLineEndDelete(arc->last_end);
  }
  if (arc->tile != ZnUnspecifiedImage) {
    ZnFreeImage(arc->tile, ZnUpdateItemImage, item);
    arc->tile = ZnUnspecifiedImage;
  }
  if (arc->line_pattern != ZnUnspecifiedImage) {
    ZnFreeImage(arc->line_pattern, NULL, NULL);
    arc->line_pattern = ZnUnspecifiedImage;
  }
  if (arc->grad_geo) {
    ZnFree(arc->grad_geo);
  }
  ZnFreeGradient(arc->fill_color);
  ZnFreeGradient(arc->line_color);
}


/*
 **********************************************************************************
 *
 * Setup flags to control the precedence between the
 * graphical attributes.
 *
 **********************************************************************************
 */
static void
SetRenderFlags(ArcItem  arc)
{
  ASSIGN(arc->flags, FIRST_END_OK,
         (arc->first_end != NULL) && ISCLEAR(arc->flags, CLOSED_BIT) &&
         ISCLEAR(arc->flags, FILLED_BIT) && arc->line_width
         /*&& ISCLEAR(arc->flags, RELIEF_OK)*/);

  ASSIGN(arc->flags, LAST_END_OK,
         (arc->last_end != NULL) && ISCLEAR(arc->flags, CLOSED_BIT) &&
         ISCLEAR(arc->flags, FILLED_BIT) && arc->line_width
         /*&& ISCLEAR(arc->flags, RELIEF_OK)*/);
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  ArcItem       arc = (ArcItem) item;
  int           status = TCL_OK;

  status = ZnConfigureAttributes(item->wi, item, item, arc_attrs, argc, argv, flags);
  if (arc->start_angle < 0) {
    arc->start_angle = 360 + arc->start_angle;
  }

  SetRenderFlags(arc);
  
  return status;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int                   argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, arc_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }  

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
UpdateRenderShape(ArcItem       arc)
{
  ZnPoint       *p_list, p, p2, o, o2;
  ZnReal        width, height, d;
  int           quality;
  unsigned int  i, num_p;
  ZnTransfo     *t = ((ZnItem) arc)->wi->current_transfo;
  
  if (!arc->render_shape) {
    arc->render_shape = ZnListNew(8, sizeof(ZnPoint));
  }
  o.x = (arc->coords[1].x + arc->coords[0].x)/2.0;
  o.y = (arc->coords[1].y + arc->coords[0].y)/2.0;
  width = (arc->coords[1].x - arc->coords[0].x)/2.0;
  height = (arc->coords[1].y - arc->coords[0].y)/2.0;
  d = MAX(width, height);
  quality = ZN_CIRCLE_COARSE;
  p_list = ZnGetCirclePoints(ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2,
                             quality,
                             ZnDegRad(arc->start_angle),
                             ZnDegRad(arc->angle_extent),
                             &num_p,
                             arc->render_shape);

  /*
   * Adapt the number of arc points to the radius of the arc.
   */
  p.x = o.x + p_list->x*d;
  p.y = o.y + p_list->y*d;
  ZnTransformPoint(t, &o, &o2);
  ZnTransformPoint(t, &p, &p2);
  d = hypot(o2.x-p2.x, o2.y-p2.y);
  if (d > 100.0) {
    quality = ZN_CIRCLE_FINER;
  }
  else if (d > 30.0) {
    quality = ZN_CIRCLE_FINE;
  }
  else if (d > 9.0) {
    quality = ZN_CIRCLE_MEDIUM;
  }

  if (quality != ZN_CIRCLE_COARSE) {
    p_list = ZnGetCirclePoints(ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2,
                               quality,
                               ZnDegRad(arc->start_angle),
                               ZnDegRad(arc->angle_extent),
                               &num_p,
                               arc->render_shape);
  }
    
  for (i = 0; i < num_p; i++, p_list++) {
    p.x = o.x + p_list->x*width;
    p.y = o.y + p_list->y*height;
    ZnTransformPoint(t, &p, p_list);
  }
}

static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  ArcItem       arc = (ArcItem) item;
  ZnReal        angle, tmp;
  unsigned int  num_p;
  ZnPoint       *p_list;
  ZnPoint       end_points[ZN_LINE_END_POINTS];
  
  ZnResetBBox(&item->item_bounding_box);
  /*
   * If it is neither filled nor outlined, then nothing to show.
   */
  if (!arc->line_width && ISCLEAR(arc->flags, FILLED_BIT)) {
    return;
  }

  /*
   * Special case for ellipse rotation and gradient.
   */
  if (!wi->render) {
    ZnTransfoDecompose(wi->current_transfo, NULL, NULL, &angle, NULL);
  }
  if (wi->render || (angle >= PRECISION_LIMIT) || (ABS(arc->angle_extent) != 360) ||
      ISSET(arc->flags, FIRST_END_OK) || ISSET(arc->flags, LAST_END_OK)) {
    SET(arc->flags, USING_POLY_BIT);
    UpdateRenderShape(arc);
    p_list = ZnListArray(arc->render_shape);
    num_p = ZnListSize(arc->render_shape);
    ZnAddPointsToBBox(&item->item_bounding_box, p_list, num_p);

    tmp = (arc->line_width + 1.0) / 2.0 + 1.0;
    item->item_bounding_box.orig.x -= tmp;
    item->item_bounding_box.orig.y -= tmp;
    item->item_bounding_box.corner.x += tmp;
    item->item_bounding_box.corner.y += tmp;
    
    /*
     * Add the arrows if any.
     */
    if (ISSET(arc->flags, FIRST_END_OK)) {
      ZnGetLineEnd(p_list, p_list+1, arc->line_width, CapRound,
                   arc->first_end, end_points);
      ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
    }
    if (ISSET(arc->flags, LAST_END_OK)) {
      ZnGetLineEnd(&p_list[num_p-1], &p_list[num_p-2], arc->line_width, CapRound,
                   arc->last_end, end_points);
      ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
    }

#ifdef GL
    if (!ZnGradientFlat(arc->fill_color)) {
      ZnPoly  shape;
      ZnPoint p[4];
      
      if (!arc->grad_geo) {
        arc->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
      }
      if (arc->fill_color->type == ZN_AXIAL_GRADIENT) {
        p[0] = arc->coords[0];
        p[2] = arc->coords[1];
        p[1].x = p[2].x;
        p[1].y = p[0].y;
        p[3].x = p[0].x;
        p[3].y = p[2].y;
        ZnPolyContour1(&shape, p, 4, False);
      }
      else {
        ZnPolyContour1(&shape, arc->coords, 2, False);
      }
      ZnComputeGradient(arc->fill_color, wi, &shape, arc->grad_geo);
    }
    else {
      if (arc->grad_geo) {
        ZnFree(arc->grad_geo);
        arc->grad_geo = NULL;
      }
    }
#endif 
    return;
  }

  /*
   *******              ********                        **********
   * This part is for X drawn arcs: full extent, not rotated.
   *******              ********                        **********
   */
  CLEAR(arc->flags, USING_POLY_BIT);
  ZnTransformPoint(wi->current_transfo, &arc->coords[0], &arc->orig);
  ZnTransformPoint(wi->current_transfo, &arc->coords[1], &arc->corner);

  ZnAddPointToBBox(&item->item_bounding_box, arc->orig.x, arc->orig.y);
  ZnAddPointToBBox(&item->item_bounding_box, arc->corner.x, arc->corner.y);

  tmp = (arc->line_width + 1.0) / 2.0 + 1.0;
  item->item_bounding_box.orig.x -= tmp;
  item->item_bounding_box.orig.y -= tmp;
  item->item_bounding_box.corner.x += tmp;
  item->item_bounding_box.corner.y += tmp;
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  ArcItem       arc = (ArcItem) item;
  ZnPoint       *points;
  ZnPoint       pts[20]; /* Should be at least ZN_LINE_END_POINTS large */
  ZnPoint       center;
  ZnBBox        *area = ta->area;
  unsigned int  num_points;
  int           result=-1, result2;
  ZnReal        lw = arc->line_width;
  ZnReal        width, height;

  if (ISSET(arc->flags, USING_POLY_BIT)) {
    if (ISSET(arc->flags, FILLED_BIT) || (arc->line_width)) {
      points = ZnListArray(arc->render_shape);
      num_points = ZnListSize(arc->render_shape);
      
      if (ISSET(arc->flags, FILLED_BIT)) {
        result = ZnPolygonInBBox(points, num_points, area, NULL);
        if (result == 0) {
          return 0;
        }
      }
      if (arc->line_width > 0) {
        result2 = ZnPolylineInBBox(points, num_points, arc->line_width,
                                   CapRound, JoinRound, area);
        if (ISCLEAR(arc->flags, FILLED_BIT)) {
          if (result2 == 0) {
            return 0;
          }
          result = result2;
        }
        else if (result2 != result) {
          return 0;
        }
        if (ISSET(arc->flags, CLOSED_BIT) && ISSET(arc->flags, PIE_SLICE_BIT)) {
          pts[0] = points[num_points-1];
          pts[1] = points[0];
          if (ZnPolylineInBBox(pts, 2, arc->line_width,
                               CapRound, JoinRound, area) != result) {
            return 0;
          }
        }
        /*
         * Check line ends.
         */
        if (ISSET(arc->flags, FIRST_END_OK)) {
          ZnGetLineEnd(&points[0], &points[1], arc->line_width, CapRound,
                       arc->first_end, pts);
          if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
            return 0;
          }
        }
        if (ISSET(arc->flags, LAST_END_OK)) {
          ZnGetLineEnd(&points[num_points-1], &points[num_points-2], arc->line_width,
                       CapRound, arc->last_end, pts);
          if (ZnPolygonInBBox(pts, ZN_LINE_END_POINTS, area, NULL) != result) {
            return 0;
          }
        }
      }
      return result;
    }
    else {
      return -1;
    }
  }

  /*
   *******              ********                        **********
   * The rest of this code deal with non rotated, full extent    *
   * arcs. It has been stolen from tkRectOval.c                  *
   *******              ********                        **********
   */
  /*
   * Transform both the arc and the rectangle so that the arc's oval
   * is centered on the origin.
   */
  center.x = (arc->orig.x + arc->corner.x)/2.0;
  center.y = (arc->orig.y + arc->corner.y)/2.0;
  width = (arc->corner.x - arc->orig.x) +  lw;
  height = (arc->corner.y - arc->orig.y) + lw;

  result = ZnOvalInBBox(&center, width, height, area);
 
   /*
    * If the area appears to overlap the oval and the oval
    * isn't filled, do one more check to see if perhaps all four
    * of the area's corners are totally inside the oval's
    * unfilled center, in which case we should return "outside".
    */
  if ((result == 0) && lw && ISCLEAR(arc->flags, FILLED_BIT)) {
    ZnReal x_delta1, x_delta2, y_delta1, y_delta2;

    width /= 2.0;
    height /= 2.0;
    x_delta1 = (area->orig.x - center.x) / width;
    x_delta1 *= x_delta1;
    y_delta1 = (area->orig.y - center.y) / height;
    y_delta1 *= y_delta1;
    x_delta2 = (area->corner.x - center.x) / width;
    x_delta2 *= x_delta2;
    y_delta2 = (area->corner.y - center.y) / height;
    y_delta2 *= y_delta2;
    if (((x_delta1 + y_delta1) < 1.0) && ((x_delta1 + y_delta2) < 1.0) &&
        ((x_delta2 + y_delta1) < 1.0) && ((x_delta2 + y_delta2) < 1.0)) {
      return -1;
    }
  }

  return result;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  ArcItem       arc = (ArcItem) item;
  XGCValues     values;
  int           x=0, y=0, width=0, height=0;
  ZnPoint       *p=NULL;
  XPoint        *xp=NULL;
  unsigned int  num_points=0, i;

  if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
    return;
  }
  if (ISSET(arc->flags, USING_POLY_BIT)) {
    p = ZnListArray(arc->render_shape);
    num_points = ZnListSize(arc->render_shape);
    ZnListAssertSize(ZnWorkXPoints, num_points);
    xp = ZnListArray(ZnWorkXPoints);
    for (i = 0; i < num_points; i++, p++) {
      xp[i].x = (short) p->x;
      xp[i].y = (short) p->y;
    }
    p = ZnListArray(arc->render_shape);
  }
  else {
    if (arc->corner.x > arc->orig.x) {
      x = ((int) arc->orig.x);
      width = ((int) (arc->corner.x - arc->orig.x));
    }
    else {
      x = ((int) arc->corner.x);
      width = ((int) (arc->orig.x - arc->corner.x));
    }
    if (arc->corner.y > arc->orig.y) {
      y = ((int) arc->orig.y);
      height = ((int) (arc->corner.y - arc->orig.y));
    }
    else {
      y = ((int) arc->corner.y);
      height = ((int) (arc->orig.y - arc->corner.y));
    }
  }
  
  /* Fill if requested */
  if (ISSET(arc->flags, FILLED_BIT)) {
    values.foreground = ZnGetGradientPixel(arc->fill_color, 0.0);
    values.arc_mode = ISSET(arc->flags, PIE_SLICE_BIT) ? ArcPieSlice : ArcChord;
    if (arc->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(arc->tile)) { /* Fill tiled */
        values.fill_style = FillTiled;
        values.tile = ZnImagePixmap(arc->tile, wi->win);
        values.ts_x_origin = (int) item->item_bounding_box.orig.x;
        values.ts_y_origin = (int) item->item_bounding_box.orig.y;
        XChangeGC(wi->dpy, wi->gc,
                  GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile|GCArcMode,
                  &values);
      }
      else { /* Fill stippled */
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(arc->tile, wi->win);
        values.ts_x_origin = (int) item->item_bounding_box.orig.x;
        values.ts_y_origin = (int) item->item_bounding_box.orig.y;
        XChangeGC(wi->dpy, wi->gc,
                  GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground|GCArcMode,
                  &values);
      }
    }
    else { /* Fill solid */
      values.fill_style = FillSolid;
      XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCArcMode, &values);
    }

    if (ISSET(arc->flags, USING_POLY_BIT)) {
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc,
                   xp, (int) num_points, Nonconvex, CoordModeOrigin);
    }
    else {
      XFillArc(wi->dpy, wi->draw_buffer, wi->gc,
               x, y, (unsigned int) width, (unsigned int) height,
               -arc->start_angle*64, -arc->angle_extent*64);
    }
  }

  /*
   * Draw the arc.
   */
  if (arc->line_width) {
    ZnPoint  end_points[ZN_LINE_END_POINTS];
    XPoint      xap[ZN_LINE_END_POINTS];
      
    ZnSetLineStyle(wi, arc->line_style);
    values.foreground = ZnGetGradientPixel(arc->line_color, 0.0);
    values.line_width = (int) arc->line_width;
    values.cap_style = CapRound;
    values.join_style = JoinRound;
    if (arc->line_pattern == ZnUnspecifiedImage) {
      values.fill_style = FillSolid;
      XChangeGC(wi->dpy, wi->gc,
                GCFillStyle|GCLineWidth|GCCapStyle|GCJoinStyle|GCForeground, &values);
    }
    else {
      values.fill_style = FillStippled;
      values.stipple = ZnImagePixmap(arc->line_pattern, wi->win);
      XChangeGC(wi->dpy, wi->gc,
                GCFillStyle|GCStipple|GCLineWidth|GCCapStyle|GCJoinStyle|GCForeground,
                &values);
    }
    if (ISSET(arc->flags, USING_POLY_BIT)) {
      if (ISCLEAR(arc->flags, CLOSED_BIT) && arc->angle_extent != 360) {
        num_points--;
        if (ISSET(arc->flags, PIE_SLICE_BIT)) {
          num_points--;
        }
      }
      XDrawLines(wi->dpy, wi->draw_buffer, wi->gc,
                 xp, (int) num_points, CoordModeOrigin);
      if (ISSET(arc->flags, FIRST_END_OK)) {
        p = (ZnPoint *) ZnListArray(arc->render_shape);
        ZnGetLineEnd(p, p+1, arc->line_width, CapRound,
                     arc->first_end, end_points);
        for (i = 0; i < ZN_LINE_END_POINTS; i++) {
          xap[i].x = (short) end_points[i].x;
          xap[i].y = (short) end_points[i].y;
        }
        XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xap, ZN_LINE_END_POINTS,
                     Nonconvex, CoordModeOrigin);
      }
      if (ISSET(arc->flags, LAST_END_OK)) {
        p = (ZnPoint *) ZnListArray(arc->render_shape);
        num_points = ZnListSize(arc->render_shape);
        ZnGetLineEnd(&p[num_points-1], &p[num_points-2], arc->line_width,
                     CapRound, arc->last_end, end_points);
        for (i = 0; i < ZN_LINE_END_POINTS; i++) {
          xap[i].x = (short) end_points[i].x;
          xap[i].y = (short) end_points[i].y;
        }
        XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xap, ZN_LINE_END_POINTS,
                     Nonconvex, CoordModeOrigin);
      }
    }
    else {
      XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
               x, y, (unsigned int) width, (unsigned int) height,
               -arc->start_angle*64, -arc->angle_extent*64);
    }
  }
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
ArcRenderCB(void *closure)
{
  ZnItem        item = (ZnItem) closure;
  ArcItem       arc = (ArcItem) item;
  int           num_points=0, i;
  ZnPoint       *p=NULL;
  ZnPoint       center;

  center.x = (item->item_bounding_box.corner.x + item->item_bounding_box.orig.x) / 2.0;
  center.y = (item->item_bounding_box.corner.y + item->item_bounding_box.orig.y) / 2.0;
  p = ZnListArray(arc->render_shape);
  num_points = ZnListSize(arc->render_shape);
  glBegin(GL_TRIANGLE_FAN);
  glVertex2d(center.x, center.y);
  for (i = 0; i < num_points; i++) {
    glVertex2d(p[i].x, p[i].y);
  }
  glEnd();
}
#endif

#ifdef GL
static void
Render(ZnItem   item)
{
  ZnWInfo       *wi = item->wi;
  ArcItem       arc = (ArcItem) item;
  unsigned int  num_points=0;
  ZnPoint       *p=NULL;
  
  if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
    return;
  }
  
#ifdef GL_LIST
  if (!item->gl_list) {
    item->gl_list = glGenLists(1);
    glNewList(item->gl_list, GL_COMPILE);
#endif
    /* Fill if requested */
    if (ISSET(arc->flags, FILLED_BIT)) {
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      
      if (!ZnGradientFlat(arc->fill_color)) {
        ZnPoly poly;
        
        ZnPolyContour1(&poly, ZnListArray(arc->render_shape),
                       ZnListSize(arc->render_shape), False);
        ZnRenderGradient(wi, arc->fill_color, ArcRenderCB, arc,
                         arc->grad_geo, &poly);
      }
      else if (arc->tile != ZnUnspecifiedImage) { /* Fill tiled/stippled */
        ZnRenderTile(wi, arc->tile, arc->fill_color, ArcRenderCB, arc,
                     (ZnPoint *) &item->item_bounding_box);
      }
      else {
        unsigned short alpha;
        XColor *color = ZnGetGradientColor(arc->fill_color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
        ArcRenderCB(arc);
      }
    }
    
    /*
     * Draw the arc.
     */
    if (arc->line_width) {
      ZnLineEnd first = ISSET(arc->flags, FIRST_END_OK) ? arc->first_end : NULL;
      ZnLineEnd last = ISSET(arc->flags, LAST_END_OK) ? arc->last_end : NULL;
      ZnBool    closed = ISSET(arc->flags, CLOSED_BIT);
      
      p = ZnListArray(arc->render_shape);
      num_points = ZnListSize(arc->render_shape);
      if (!closed) {
        if (arc->angle_extent != 360) {
          num_points--;
          if (ISSET(arc->flags, PIE_SLICE_BIT)) {
            num_points--;
          }
        }
      }
      ZnRenderPolyline(wi, p, num_points, arc->line_width,
                       arc->line_style, CapRound, JoinRound, first, last,
                       arc->line_color);
    }
#ifdef GL_LIST
    glEndList();
  }
  
  glCallList(item->gl_list);
#endif
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static ZnReal
Pick(ZnItem     item,
     ZnPick     ps)
{
  ArcItem       arc = (ArcItem) item;
  double        dist = 1e40, new_dist;
  ZnPoint       center;
  ZnPoint       *points, *p = ps->point;
  ZnPoint       end_points[ZN_LINE_END_POINTS];
  unsigned int  num_points;
  ZnDim         lw = arc->line_width;
  
  if (ISCLEAR(arc->flags, FILLED_BIT) && ! arc->line_width) {
    return dist;
  }
  if (ISSET(arc->flags, USING_POLY_BIT)) {
    points = ZnListArray(arc->render_shape);
    num_points = ZnListSize(arc->render_shape);

    if (ISSET(arc->flags, FILLED_BIT)) {
      dist = ZnPolygonToPointDist(points, num_points, p);
      if (dist <= 0.0) {
        return 0.0;
      }
    }
    if (arc->line_width > 0) {
      if (ISCLEAR(arc->flags, CLOSED_BIT) && arc->angle_extent != 360) {
        num_points--;
        if (ISSET(arc->flags, PIE_SLICE_BIT)) {
          num_points--;
        }
      }
      new_dist = ZnPolylineToPointDist(points, num_points, arc->line_width,
                                       CapRound, JoinRound, p);
      if (new_dist < dist) {
        dist = new_dist;
      }
      if (dist <= 0.0) {
        return 0.0;
      }

      /*
       * Check line ends.
       */
      if (ISSET(arc->flags, FIRST_END_OK)) {
        ZnGetLineEnd(&points[0], &points[1], arc->line_width, CapRound,
                     arc->first_end, end_points);
        new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
        if (new_dist < dist) {
          dist = new_dist;
        }
        if (dist <= 0.0) {
          return 0.0;
        }
      }
      if (ISSET(arc->flags, LAST_END_OK)) {
        ZnGetLineEnd(&points[num_points-1], &points[num_points-2], arc->line_width,
                     CapRound, arc->last_end, end_points);
        new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
        if (new_dist < dist) {
          dist = new_dist;
        }
        if (dist <= 0.0) {
          return 0.0;
        }
      }
    }
    return dist;
  }

  /*
   *******              ********                          **********
   * The rest of this code deal with non rotated full extent arcs. *
   *******              ********                          **********
   */
  center.x = (arc->orig.x + arc->corner.x) / 2.0;
  center.y = (arc->orig.y + arc->corner.y) / 2.0;
  dist = ZnOvalToPointDist(&center, arc->corner.x - arc->orig.x,
                           arc->corner.y - arc->orig.y, lw, p);
  if (dist < 0.0) {
    if (ISSET(arc->flags, FILLED_BIT)) {
      dist = 0.0;
    }
    else {
      dist = -dist;
    }
  }
  return dist;
}

/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static void
UpdateRenderShapeX(ArcItem      arc)
{
  ZnReal        ox, oy, width_2, height_2;
  unsigned int  i, num_p;
  ZnPoint       *p_list;
  
  if (!arc->render_shape) {
    arc->render_shape = ZnListNew(8, sizeof(ZnPoint));
  }
  p_list = ZnGetCirclePoints(ISCLEAR(arc->flags, PIE_SLICE_BIT) ? 1 : 2,
                             ZN_CIRCLE_FINE,
                             ZnDegRad(arc->start_angle),
                             ZnDegRad(arc->angle_extent),
                             &num_p, arc->render_shape);
  ox = (arc->corner.x + arc->orig.x) / 2.0;
  oy = (arc->corner.y + arc->orig.y) / 2.0;
  width_2 = (arc->corner.x - arc->orig.x) / 2.0;
  height_2 = (arc->corner.y - arc->orig.y) / 2.0;
  for (i = 0; i < num_p; i++, p_list++) {
    p_list->x = ox + p_list->x*width_2;
    p_list->y = oy + p_list->y*height_2;
  }
}

static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  ArcItem       arc = (ArcItem) item;
  ZnPoint       center;

  if (ISCLEAR(arc->flags, USING_POLY_BIT) || !arc->render_shape) {
    UpdateRenderShapeX(arc);
    SET(arc->flags, USING_POLY_BIT);
  }

  
  center.x = (item->item_bounding_box.corner.x + item->item_bounding_box.orig.x) / 2.0;
  center.y = (item->item_bounding_box.corner.y + item->item_bounding_box.orig.y) / 2.0;
  ZnListEmpty(ZnWorkPoints);
  ZnListAdd(ZnWorkPoints, &center, ZnListTail);
  ZnListAppend(ZnWorkPoints, arc->render_shape);
  ZnTriStrip1(tristrip, ZnListArray(ZnWorkPoints),
              ZnListSize(ZnWorkPoints), True);
  
  return False;
}


/*
 **********************************************************************************
 *
 * GetContours --
 *      Get the external contour(s).
 *      Never ever call ZnPolyFree on the tristrip returned by GetContours.
 *
 **********************************************************************************
 */
static ZnBool
GetContours(ZnItem      item,
            ZnPoly      *poly)
{
  ArcItem       arc = (ArcItem) item;
  
  if (ISCLEAR(arc->flags, USING_POLY_BIT) || !arc->render_shape) {
    UpdateRenderShapeX(arc);
  }

  ZnPolyContour1(poly, ZnListArray(arc->render_shape),
                 ZnListSize(arc->render_shape), True);
  poly->contour1.controls = NULL;

  return False;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item vertices.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  ArcItem       arc = (ArcItem) item;

  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " arcs can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if (cmd == ZN_COORDS_REPLACE_ALL) {
    if (*num_pts != 2) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 2 points on arcs", NULL);
      return TCL_ERROR;
    }
    arc->coords[0] = (*pts)[0];
    arc->coords[1] = (*pts)[1];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if (cmd == ZN_COORDS_REPLACE) {
    if (*num_pts < 1) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need at least 1 point", NULL);
      return TCL_ERROR;
    }
    if (index < 0) {
      index += 2;
    }
    if ((index < 0) || (index > 1)) {
    range_err:
      Tcl_AppendResult(item->wi->interp,
                       " incorrect coord index, should be between -2 and 1", NULL);
      return TCL_ERROR;
    }
    arc->coords[index] = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if (cmd == ZN_COORDS_READ_ALL) {
    *num_pts = 2;
    *pts = arc->coords;
  }
  else if (cmd == ZN_COORDS_READ) {
    if (index < 0) {
      index += 2;
    }
    if ((index < 0) || (index > 1)) {
      goto range_err;
    }
    *num_pts = 1;
    *pts = &arc->coords[index];
  }

  return TCL_OK;
}

/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  ZnBBox *bbox = &item->item_bounding_box;

  ZnOrigin2Anchor(&bbox->orig,
                  bbox->corner.x - bbox->orig.x,
                  bbox->corner.y - bbox->orig.y,
                  anchor, p);
}

/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ArcItem arc = (ArcItem) item;
  ZnWInfo *wi = item->wi;
  ZnPoint *p;
  int     i, num_points;
  char    path[500];

  if (ISCLEAR(arc->flags, FILLED_BIT) && !arc->line_width) {
    return TCL_OK;
  }

  /*
   * Create the arc path.
   */
  if (ISSET(arc->flags, USING_POLY_BIT)) {
    p = ZnListArray(arc->render_shape);
    num_points = ZnListSize(arc->render_shape);
    sprintf(path, "%.15g %.15g moveto ", p[0].x, p[0].y);
    Tcl_AppendResult(wi->interp, path, NULL);
    for (i = 0; i < num_points; i++) {
      sprintf(path, "%.15g %.15g lineto ", p[i].x, p[i].y);
      Tcl_AppendResult(wi->interp, path, NULL);
    }
    Tcl_AppendResult(wi->interp, "closepath\n", NULL);
  }
  else {
    sprintf(path,
            "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale 1 0 moveto 0 0 1 0 360 arc\nsetmatrix\n",
            (arc->corner.x + arc->orig.x) / 2.0, (arc->corner.y + arc->orig.y) / 2.0,
            (arc->corner.x - arc->orig.x) / 2.0, (arc->corner.y - arc->orig.y) / 2.0);
    Tcl_AppendResult(wi->interp, path, NULL);
  }
  
  /*
   * Emit code to draw the filled area.
   */
  if (ISSET(arc->flags, FILLED_BIT)) {
    if (arc->line_width) {
      Tcl_AppendResult(wi->interp, "gsave\n", NULL);
    }
    if (!ZnGradientFlat(arc->fill_color)) {
      if (ZnPostscriptGradient(wi->interp, wi->ps_info, arc->fill_color,
                               arc->grad_geo, NULL) != TCL_OK) {
        return TCL_ERROR;
      }
    }
    else if (arc->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(arc->tile)) { /* Fill tiled */
        /* TODO No support yet */
      }
      else { /* Fill stippled */
        if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                               ZnGetGradientColor(arc->fill_color, 0.0, NULL)) != TCL_OK) {
          return TCL_ERROR;
        }
        Tcl_AppendResult(wi->interp, "clip ", NULL);
        if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
                                 ZnImagePixmap(arc->tile, wi->win)) != TCL_OK) {
          return TCL_ERROR;
        }
      }
    }
    else { /* Fill solid */
      if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                             ZnGetGradientColor(arc->fill_color, 0.0, NULL)) != TCL_OK) {
        return TCL_ERROR;
      }
      Tcl_AppendResult(wi->interp, "fill\n", NULL);
    }
    if (arc->line_width) {
      Tcl_AppendResult(wi->interp, "grestore\n", NULL);
    }
  }

  /*
   * Then emit code code to stroke the outline.
   */
  if (arc->line_width) {
    Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
    if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
                            arc->line_width, arc->line_style,
                            arc->line_color, arc->line_pattern) != TCL_OK) {
      return TCL_ERROR;
    }
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct ARC_ITEM_CLASS = {
  "arc",
  sizeof(ArcItemStruct),
  arc_attrs,
  0,                    /* num_parts */
  0,                    /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  GetClipVertices,
  GetContours,
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnArc = (ZnItemClassId) &ARC_ITEM_CLASS;

Added jni/tkzinc/generic/Attrs.c.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
/*
 * Attrs.c -- Various attributes manipulation routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Fri Dec 31 10:03:34 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Attrs.h"
#include "Item.h"
#include "List.h"
#include "Geo.h"
#include "WidgetInfo.h"

#if defined(MAC_OSX_TK)
  #include <AGL/glu.h>
#elif defined(__APPLE__)
  #include <OpenGL/glu.h>
#else
  #include <GL/glu.h>
#endif
#include <memory.h>
#include <stdlib.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 ****************************************************************
 *
 * Code for reliefs.
 *
 ****************************************************************
 */
#define RELIEF_FLAT_SPEC        "flat"
#define RELIEF_RAISED_SPEC      "raised"
#define RELIEF_SUNKEN_SPEC      "sunken"
#define RELIEF_GROOVE_SPEC      "groove"
#define RELIEF_RIDGE_SPEC       "ridge"
#define RELIEF_ROUND_RAISED_SPEC "roundraised"
#define RELIEF_ROUND_SUNKEN_SPEC "roundsunken"
#define RELIEF_ROUND_GROOVE_SPEC "roundgroove"
#define RELIEF_ROUND_RIDGE_SPEC "roundridge"
#define RELIEF_SUNKEN_RULE_SPEC "sunkenrule"
#define RELIEF_RAISED_RULE_SPEC "raisedrule"

int
ZnGetRelief(ZnWInfo             *wi,
            char                *name,
            ZnReliefStyle       *relief)
{
  size_t length;
  
  length = strlen(name);
  if (strncmp(name, RELIEF_FLAT_SPEC, length) == 0) {
    *relief = ZN_RELIEF_FLAT;
  }
  else if (strncmp(name, RELIEF_SUNKEN_SPEC, length) == 0) {
    *relief = ZN_RELIEF_SUNKEN;
  }
  else if ((strncmp(name, RELIEF_RAISED_SPEC, length) == 0) && (length >= 2)) {
    *relief = ZN_RELIEF_RAISED;
  }
  else if ((strncmp(name, RELIEF_RIDGE_SPEC, length) == 0) && (length >= 2)) {
    *relief = ZN_RELIEF_RIDGE;
  }
  else if (strncmp(name, RELIEF_GROOVE_SPEC, length) == 0) {
    *relief = ZN_RELIEF_GROOVE;
  }
  else if ((strncmp(name, RELIEF_ROUND_SUNKEN_SPEC, length) == 0) && (length >= 6)) {
    *relief = ZN_RELIEF_ROUND_SUNKEN;
  }
  else if ((strncmp(name, RELIEF_ROUND_RAISED_SPEC, length) == 0) && (length >= 7)) {
    *relief = ZN_RELIEF_ROUND_RAISED;
  }
  else if ((strncmp(name, RELIEF_ROUND_RIDGE_SPEC, length) == 0) && (length >= 7)) {
    *relief = ZN_RELIEF_ROUND_RIDGE;
  }
  else if ((strncmp(name, RELIEF_ROUND_GROOVE_SPEC, length) == 0) && (length >= 6)) {
    *relief = ZN_RELIEF_ROUND_GROOVE;
  }
  else if ((strncmp(name, RELIEF_SUNKEN_RULE_SPEC, length) == 0) && (length >= 7)) {
    *relief = ZN_RELIEF_SUNKEN_RULE;
  }
  else if ((strncmp(name, RELIEF_RAISED_RULE_SPEC, length) == 0) && (length >= 7)) {
    *relief = ZN_RELIEF_RAISED_RULE;
  }
  else {
    Tcl_AppendResult(wi->interp, "bad relief \"", name, "\": must be ",
                     RELIEF_FLAT_SPEC, ", ",
                     RELIEF_RAISED_SPEC, ", ",
                     RELIEF_SUNKEN_SPEC, ", ",
                     RELIEF_GROOVE_SPEC, ", ",
                     RELIEF_RIDGE_SPEC, ", ",
                     RELIEF_ROUND_RAISED_SPEC, ", ",
                     RELIEF_ROUND_SUNKEN_SPEC, ", ",
                     RELIEF_ROUND_GROOVE_SPEC, ", ",
                     RELIEF_ROUND_RIDGE_SPEC, ", ",
                     RELIEF_SUNKEN_RULE_SPEC, ", ",
                     RELIEF_RAISED_RULE_SPEC,
                     NULL);
    return TCL_ERROR;
  }
  if (!wi->render) {
    *relief = *relief & ~(ZN_RELIEF_ROUND|ZN_RELIEF_RULE);
  }

  return TCL_OK;
}

char *
ZnNameOfRelief(ZnReliefStyle relief)
{
  switch (relief) {
  case ZN_RELIEF_FLAT:
    return RELIEF_FLAT_SPEC;
  case ZN_RELIEF_SUNKEN:
    return RELIEF_SUNKEN_SPEC;
  case ZN_RELIEF_RAISED:
    return RELIEF_RAISED_SPEC;
  case ZN_RELIEF_GROOVE:
    return RELIEF_GROOVE_SPEC;
  case ZN_RELIEF_RIDGE:
    return RELIEF_RIDGE_SPEC;
  case ZN_RELIEF_ROUND_SUNKEN:
    return RELIEF_ROUND_SUNKEN_SPEC;
  case ZN_RELIEF_ROUND_RAISED:
    return RELIEF_ROUND_RAISED_SPEC;
  case ZN_RELIEF_ROUND_GROOVE:
    return RELIEF_ROUND_GROOVE_SPEC;
  case ZN_RELIEF_ROUND_RIDGE:
    return RELIEF_ROUND_RIDGE_SPEC;
  case ZN_RELIEF_SUNKEN_RULE:
    return RELIEF_SUNKEN_RULE_SPEC;
  case ZN_RELIEF_RAISED_RULE:
    return RELIEF_RAISED_RULE_SPEC;
  default:
    return "unknown relief";
  }
}

/*
 ****************************************************************
 *
 * Code for borders.
 *
 ****************************************************************
 */
#define BORDER_LEFT_SPEC        "left"
#define BORDER_RIGHT_SPEC       "right"
#define BORDER_TOP_SPEC         "top"
#define BORDER_BOTTOM_SPEC      "bottom"
#define BORDER_CONTOUR_SPEC     "contour"
#define BORDER_COUNTER_OBLIQUE_SPEC     "counteroblique"
#define BORDER_OBLIQUE_SPEC     "oblique"
#define NO_BORDER_SPEC          "noborder"

int
ZnGetBorder(ZnWInfo     *wi,
            Tcl_Obj     *name,
            ZnBorder    *border)
{
  unsigned int len;
  int          j, largc;
  Tcl_Obj      **largv;
  char         *str;

  *border = ZN_NO_BORDER;
  if (Tcl_ListObjGetElements(wi->interp, name,
                             &largc, &largv) == TCL_ERROR) {
  border_error:
    Tcl_AppendResult(wi->interp, "bad line shape \"", Tcl_GetString(name),
                     "\": must be a list of ",
                     BORDER_LEFT_SPEC, ", ",
                     BORDER_RIGHT_SPEC, ", ",
                     BORDER_TOP_SPEC, ", ",
                     BORDER_BOTTOM_SPEC, ", ",
                     BORDER_COUNTER_OBLIQUE_SPEC, ", ",
                     BORDER_OBLIQUE_SPEC, " or ",
                     BORDER_CONTOUR_SPEC, ", ",
                     NO_BORDER_SPEC, " alone",
                     NULL);
    return TCL_ERROR;
  }
  for (j = 0; j < largc; j++) {
    str = Tcl_GetString(largv[j]);
    len = strlen(str);
    if (strncmp(str, BORDER_LEFT_SPEC, len) == 0) {
      *border |= ZN_LEFT_BORDER;
    }
    else if (strncmp(str, BORDER_RIGHT_SPEC, len) == 0) {
      *border |= ZN_RIGHT_BORDER;
    }
    else if (strncmp(str, BORDER_TOP_SPEC, len) == 0) {
      *border |= ZN_TOP_BORDER;
    }
    else if (strncmp(str, BORDER_BOTTOM_SPEC, len) == 0) {
      *border |= ZN_BOTTOM_BORDER;
    }
    else if (strncmp(str, BORDER_CONTOUR_SPEC, len) == 0) {
      *border |= ZN_CONTOUR_BORDER;
    }
    else if (strncmp(str, BORDER_OBLIQUE_SPEC, len) == 0) {
      *border |= ZN_OBLIQUE;
    }
    else if (strncmp(str, BORDER_COUNTER_OBLIQUE_SPEC, len) == 0) {
      *border |= ZN_COUNTER_OBLIQUE;
    }
    else if (strncmp(str, NO_BORDER_SPEC, len) == 0) {
      *border = ZN_NO_BORDER;
    }
    else {
      goto border_error;
    }
  }
  return TCL_OK;
}

/*
 * name must be large enough to hold the returned string.
 * 64 chars should be enough with the current values.
 */
void
ZnNameOfBorder(ZnBorder border,
               char     *name)
{
  if (border == ZN_NO_BORDER) {
    strcpy(name, NO_BORDER_SPEC);
    return;
  }
  name[0] = 0;
  if ((border & ZN_CONTOUR_BORDER) == ZN_CONTOUR_BORDER) {
    strcat(name, BORDER_CONTOUR_SPEC);
  }
  else {
    if (border & ZN_LEFT_BORDER) {
      strcat(name, BORDER_LEFT_SPEC);
    }
    if (border & ZN_RIGHT_BORDER) {  
      if (name[0] != 0) {
        strcat(name, " ");
      }
      strcat(name, BORDER_RIGHT_SPEC);
    }
    if (border & ZN_TOP_BORDER) {
      if (name[0] != 0) {
        strcat(name, " ");
      }
      strcat(name, BORDER_TOP_SPEC);
    }
    if (border & ZN_BOTTOM_BORDER) {
      if (name[0] != 0) {
            strcat(name, " ");
      }
      strcat(name, BORDER_BOTTOM_SPEC);
    }
  }
  if (border & ZN_OBLIQUE) {
    if (name[0] != 0) {
      strcat(name, " ");
    }
    strcat(name, BORDER_OBLIQUE_SPEC);
  }
  if (border & ZN_COUNTER_OBLIQUE) {
    if (name[0] != 0) {
      strcat(name, " ");
    }
    strcat(name, BORDER_COUNTER_OBLIQUE_SPEC);
  }
}

/*
 ****************************************************************
 *
 * Code for line shapes.
 *
 ****************************************************************
 */
#define STRAIGHT_SPEC           "straight"
#define RIGHT_LIGHTNING_SPEC    "rightlightning"
#define LEFT_LIGHTNING_SPEC     "leftlightning"
#define RIGHT_CORNER_SPEC       "rightcorner"
#define LEFT_CORNER_SPEC        "leftcorner"
#define DOUBLE_RIGHT_CORNER_SPEC  "doublerightcorner"
#define DOUBLE_LEFT_CORNER_SPEC "doubleleftcorner"

int
ZnGetLineShape(ZnWInfo          *wi,
               char             *name,
               ZnLineShape      *line_shape)
{
  unsigned int  len;

  len = strlen(name);
  if (strncmp(name, STRAIGHT_SPEC, len) == 0) {
    *line_shape = ZN_LINE_STRAIGHT;
  }
  else if (strncmp(name, RIGHT_LIGHTNING_SPEC, len) == 0) {
    *line_shape = ZN_LINE_RIGHT_LIGHTNING;
  }
  else if (strncmp(name, LEFT_LIGHTNING_SPEC, len) == 0) {
    *line_shape = ZN_LINE_LEFT_LIGHTNING;
  }
  else if (strncmp(name, RIGHT_CORNER_SPEC, len) == 0) {
    *line_shape = ZN_LINE_RIGHT_CORNER;
  }
  else if (strncmp(name, LEFT_CORNER_SPEC, len) == 0) {
    *line_shape = ZN_LINE_LEFT_CORNER;
  }
  else if (strncmp(name, DOUBLE_RIGHT_CORNER_SPEC, len) == 0) {
    *line_shape = ZN_LINE_DOUBLE_RIGHT_CORNER;
  }
  else if (strncmp(name, DOUBLE_LEFT_CORNER_SPEC, len) == 0) {
    *line_shape = ZN_LINE_DOUBLE_LEFT_CORNER;
  }
  else  {
    Tcl_AppendResult(wi->interp, "bad line shape \"", name, "\": must be ",
                     STRAIGHT_SPEC, ", ",
                     RIGHT_LIGHTNING_SPEC, ", ",
                     LEFT_LIGHTNING_SPEC, ", ",
                     RIGHT_CORNER_SPEC, ", ",
                     LEFT_CORNER_SPEC, ", ",
                     DOUBLE_RIGHT_CORNER_SPEC, ", ",
                     DOUBLE_LEFT_CORNER_SPEC,
                     NULL);
    return TCL_ERROR;
  }
  return TCL_OK;
}

char *
ZnNameOfLineShape(ZnLineShape line_shape)
{
  switch (line_shape) {
  case ZN_LINE_STRAIGHT:
    return STRAIGHT_SPEC;
  case ZN_LINE_RIGHT_LIGHTNING:
    return RIGHT_LIGHTNING_SPEC;
  case ZN_LINE_LEFT_LIGHTNING:
    return LEFT_LIGHTNING_SPEC;
  case ZN_LINE_RIGHT_CORNER:
    return RIGHT_CORNER_SPEC;
  case ZN_LINE_LEFT_CORNER:
    return LEFT_CORNER_SPEC;
  case ZN_LINE_DOUBLE_RIGHT_CORNER:
    return DOUBLE_RIGHT_CORNER_SPEC;
  case ZN_LINE_DOUBLE_LEFT_CORNER:
    return DOUBLE_LEFT_CORNER_SPEC;
  default:
    return "unknown line shape";
  }
}

/*
 ****************************************************************
 *
 * Code for line styles.
 *
 ****************************************************************
 */
#define SIMPLE_SPEC             "simple"
#define DASHED_SPEC             "dashed"
#define DOTTED_SPEC             "dotted"
#define MIXED_SPEC              "mixed"

int
ZnGetLineStyle(ZnWInfo          *wi,
               char             *name,
               ZnLineStyle      *line_style)
{
  unsigned int len;

  len = strlen(name);
  if (strncmp(name, SIMPLE_SPEC, len) == 0)
    *line_style = ZN_LINE_SIMPLE;
  else if (strncmp(name, DASHED_SPEC, len) == 0)
    *line_style = ZN_LINE_DASHED;
  else if (strncmp(name, MIXED_SPEC, len) == 0)
    *line_style = ZN_LINE_MIXED;
  else if (strncmp(name, DOTTED_SPEC, len) == 0)
    *line_style = ZN_LINE_DOTTED;
  else  {
    Tcl_AppendResult(wi->interp, "bad line style \"", name, "\": must be ",
                     SIMPLE_SPEC, ", ",
                     DASHED_SPEC, ", ",
                     DOTTED_SPEC, ", ",
                     MIXED_SPEC,
                     NULL);
    return TCL_ERROR;         
  }
  return TCL_OK;
}

char *
ZnNameOfLineStyle(ZnLineStyle line_style)
{
  switch (line_style) {
  case ZN_LINE_SIMPLE:
    return SIMPLE_SPEC;
  case ZN_LINE_DASHED:
    return DASHED_SPEC;
  case ZN_LINE_MIXED:
    return MIXED_SPEC;
  case ZN_LINE_DOTTED:
    return DOTTED_SPEC;
  default:
    return "unknown line style";
  }
}

/*
 ****************************************************************
 *
 * Code for leader anchors.
 *
 * Format is: lChar leftLeaderAnchor [ lChar rightLeaderAnchor]
 *
 * If lChar is a '|', leftLeaderAnchor and rightLeaderAnchor are the indices
 * of the fields that serve to anchor the label's leader. More specifically
 * the bottom left corner of the left field and the bottom right corner of
 * the right field are used as the anchors.
 * If lChar is '%', leftLeaderAnchor and rightLeaderAnchor should be
 * specified as 'valxval', 'val' being a percentage (max 100) of the
 * width/height of the label bounding box.
 * If rightLeaderAnchor is not specified it defaults to leftLeaderAnchor.
 * If neither of them are specified, the center of the label is used as an
 * anchor.
 *
 ****************************************************************
 */
int
ZnGetLeaderAnchors(ZnWInfo              *wi,
                   char                 *name,
                   ZnLeaderAnchors      *leader_anchors)
{
  int   anchors[4];
  int   index, num_tok, anchor_index=0;

  *leader_anchors = NULL;
  while (*name && (*name == ' ')) {
    name++;
  }
  while (*name && (anchor_index < 4)) {
    switch (*name) {
    case '|':
      num_tok = sscanf(name, "|%d%n", &anchors[anchor_index], &index);
      if (num_tok != 1) {
      la_error:
        Tcl_AppendResult(wi->interp, " incorrect leader anchors \"",
                         name, "\"", NULL);
        return TCL_ERROR;
      }
      anchors[anchor_index+1] = -1;
      break;
    case '%':
      num_tok = sscanf(name, "%%%dx%d%n", &anchors[anchor_index],
                       &anchors[anchor_index+1], &index);
      if (num_tok != 2) {
        goto la_error;
      }
      if (anchors[anchor_index] < 0) {
        anchors[anchor_index] = 0;
      }
      if (anchors[anchor_index] > 100) {
        anchors[anchor_index] = 100;
      }
      if (anchors[anchor_index+1] < 0) {
        anchors[anchor_index+1] = 0;
      }
      if (anchors[anchor_index+1] > 100) {
        anchors[anchor_index+1] = 100;
      }
      break;
    default:
      goto la_error;
    }
    anchor_index += 2;
    name += index;
  }
  /*
   * If empty, pick the default (center of the bounding box).
   */
  if (anchor_index != 0) {
    *leader_anchors = ZnMalloc(sizeof(ZnLeaderAnchorsStruct));
    (*leader_anchors)->left_x = anchors[0];
    (*leader_anchors)->left_y = anchors[1];
    if (anchor_index == 2) {
      (*leader_anchors)->right_x = (*leader_anchors)->left_x;
      (*leader_anchors)->right_y = (*leader_anchors)->left_y;
    }
    else {
      (*leader_anchors)->right_x = anchors[2];
      (*leader_anchors)->right_y = anchors[3];
    }
  }
  return TCL_OK;
}

/*
 * name must be large enough to hold the returned string.
 */
void
ZnNameOfLeaderAnchors(ZnLeaderAnchors leader_anchors,
                      char            *name)
{
  unsigned int  count;
  
  if (!leader_anchors) {
    strcpy(name, "%50x50");
  }
  else {
    if (leader_anchors->left_y < 0) {
      count = sprintf(name, "|%d", leader_anchors->left_x);
    }
    else {
      count = sprintf(name, "%%%dx%d", leader_anchors->left_x,
                      leader_anchors->left_y);
    }
    name += count;
    if (leader_anchors->right_y < 0) {
      sprintf(name, "|%d", leader_anchors->right_x);
    }
    else {
      sprintf(name, "%%%dx%d", leader_anchors->right_x, leader_anchors->right_y);
    }
  }
}

/*
 ******************************************************************
 *
 * Code for label formats.
 *
 ******************************************************************
 */
static Tcl_HashTable    format_cache;
static ZnBool           format_inited = False;


static char
CharToAttach(int attach)
{
  switch (attach) {
  case '>':
    return ZN_LF_ATTACH_FWD;
  case '<':
    return ZN_LF_ATTACH_BWD;
  case '^':
    return ZN_LF_ATTACH_LEFT;
  case '$':
    return ZN_LF_ATTACH_RIGHT;
  case '+':
  default:
    return ZN_LF_ATTACH_PIXEL;
  }
}

static char
CharToDim(int   dim)
{
  switch (dim) {
  case 'f':
    return ZN_LF_DIM_FONT;
  case 'i':
    return ZN_LF_DIM_ICON;
  case 'a':
    return ZN_LF_DIM_AUTO;
  case 'l':
    return ZN_LF_DIM_LABEL;
  case 'x':
  default:
    return ZN_LF_DIM_PIXEL;
  }
}

/*
 * The new format is as follow. Parameters between [] are
 * optional and take default values when omitted. The spaces can appear
 * between blocks but not inside.
 *
 *      [ WidthxHeight ] [ field0Spec ][ field1Spec ]...[ fieldnSpec ]
 *
 * Width and Height set the size of the clipping box surrounding
 * the label. If it is not specified, there will be no clipping.
 * It it is specified alone it is the size of the only displayed
 * field (0).
 *
 * fieldSpec is:
 *      sChar fieldWidth sChar fieldHeight [pChar fieldX pChar fieldY].
 *
 * Each field description refers to the field of same index in the field
 * array.
 * If sChar is 'x', the dimension is in pixel. If sChar is 'f', the
 * dimension is in percentage of the mean width/height of a character (in the
 * field font). If sChar is 'i', the dimension is in percentage of the size
 * of the image in the field. If sChar is 'a', the dimension is automatically
 * adjusted to match the field's content plus the given value in pixels.
 * If pChar is '+' the position is in pixel (possibly negative). If it is
 * '<' the position is the index of the field at the left/top of which the
 * current field should be  attached. If it is '>' the position is the index
 * of the field at the right/bottom of which the current field should be
 * attached. If pChar is '^' the position is the index of the field used to
 * align the left/top border (left on left or top on top). If pChar is '$' the
 * position is the index of the field used to align the right/bottom border
 * (right on right or bottom on bottom). 
 * The positional parameters can be omitted if there is only one field.
 *
 */
ZnLabelFormat
ZnLFCreate(Tcl_Interp   *interp,
           char         *format_str,
           unsigned int num_fields)
{
  ZnList        fields;
  Tcl_HashEntry *entry;
  ZnFieldFormatStruct field_struct;
  ZnFieldFormat field_array;
  ZnLabelFormat format;
  int           width, height;
  ZnDim         c_width=0.0, c_height=0.0;
  int           index, num_tok, num_ffs, new;
  unsigned int  field_index=0;
  char          *ptr = format_str, *next_ptr;
  char          x_char, y_char;

  if (!format_inited) {
    Tcl_InitHashTable(&format_cache, TCL_STRING_KEYS);
    format_inited = True;
  }
  entry = Tcl_CreateHashEntry(&format_cache, format_str, &new);
  if (!new) {
    format = (ZnLabelFormat) Tcl_GetHashValue(entry);
    if (format->num_fields <= num_fields) {
      format->ref_count++;
      return format;
    }
    else {
      Tcl_AppendResult(interp, "too many fields in label format: \"",
                       format_str, "\"", NULL);
      return NULL;
    }
  }
  
  fields = ZnListNew(1, sizeof(ZnFieldFormatStruct));
  
  /*
   * Try to see if it starts with a number or a leader spec.
   */
  while (*ptr && (*ptr == ' ')) {
    ptr++;
  }
  if (!*ptr) {
    goto lf_error_syn;
  }
  if ((*ptr != 'x') && (*ptr != 'f') && (*ptr != 'i') &&
      (*ptr != 'a') && (*ptr != 'l')) {
    c_width = (ZnDim) strtod(ptr, &next_ptr);
    if ((ptr == next_ptr) || (*next_ptr != 'x')) {
    lf_error_syn:
      Tcl_AppendResult(interp, "invalid label format specification \"",
                       ptr, "\"", NULL);
    lf_error:
      Tcl_DeleteHashEntry(entry);
      ZnListFree(fields);
      return NULL;
    }
    ptr = next_ptr+1;
    c_height = (ZnDim) strtod(ptr, &next_ptr);
    if (ptr == next_ptr) {
      goto lf_error_syn;
    }
    ptr = next_ptr;
  }
  if (!*ptr) {
    /* It is a simple spec, one field. */
    field_struct.x_attach = field_struct.y_attach = ZN_LF_ATTACH_PIXEL;
    field_struct.x_dim = field_struct.y_dim = ZN_LF_DIM_PIXEL;
    field_struct.x_spec = field_struct.y_spec = 0;
    field_struct.width_spec = (short) c_width;
    field_struct.height_spec = (short) c_height;
    c_width = c_height = 0.0;
    ZnListAdd(fields, &field_struct, ZnListTail);
    goto lf_end_parse;
  }
  
  /*
   * Parse the field specs.
   */
 lf_parse2:
  while (*ptr && (*ptr == ' ')) {
    ptr++;
  }
  if (!*ptr) {
    goto lf_end_parse;
  }
  /* Preset the default field values. */
  field_struct.x_spec = field_struct.y_spec = 0;
  field_struct.x_attach = field_struct.y_attach = ZN_LF_ATTACH_PIXEL;
  field_struct.x_dim = field_struct.y_dim = ZN_LF_DIM_PIXEL;
  if ((*ptr == 'x') || (*ptr == 'f') || (*ptr == 'i') ||
      (*ptr == 'a') || (*ptr == 'l')) {
    num_tok = sscanf(ptr, "%c%d%c%d%n", &x_char, &width,
                     &y_char, &height, &index);
    if (num_tok != 4) {
      goto lf_error_syn;
    }
    //if (width < 0) {
    //  width = 0;
    //}
    //if (height < 0) {
    //  height = 0;
    //}
    field_struct.x_dim = CharToDim(x_char);
    field_struct.y_dim = CharToDim(y_char);

    ptr += index;
    if ((*ptr == '>') || (*ptr == '<') || (*ptr == '+') ||
        (*ptr == '^') || (*ptr == '$')) {
      num_tok = sscanf(ptr, "%c%d%c%d%n", &x_char, &field_struct.x_spec,
                       &y_char, &field_struct.y_spec, &index);
      if (num_tok != 4) {
        goto lf_error_syn;
      }
      field_struct.x_attach = CharToAttach(x_char);
      field_struct.y_attach = CharToAttach(y_char);

      ptr += index;
    }
    else if (!*ptr || (field_index != 0)) {
      /* An incomplete field spec is an error if there are several fields. */
      Tcl_AppendResult(interp, "incomplete field in label format: \"",
                       ptr-index, "\"", NULL);
      goto lf_error;            
    }
    if (field_index >= num_fields) {
      Tcl_AppendResult(interp, "too many fields in label format: \"",
                       format_str, "\"", NULL);
      goto lf_error;
    }
    field_struct.width_spec = (short) width;
    field_struct.height_spec = (short) height;
    ZnListAdd(fields, &field_struct, ZnListTail);
    field_index++;
    goto lf_parse2;
  }
  else {
    goto lf_error_syn;
  }
  
 lf_end_parse:
  field_array = (ZnFieldFormat) ZnListArray(fields);
  num_ffs = ZnListSize(fields);
  
  format = (ZnLabelFormat) ZnMalloc(sizeof(ZnLabelFormatStruct) +
                                    (num_ffs-1) * sizeof(ZnFieldFormatStruct));
  format->clip_width = (short) c_width;
  format->clip_height = (short) c_height;
  format->num_fields = num_ffs;
  memcpy(&format->fields, field_array, num_ffs * sizeof(ZnFieldFormatStruct));
  ZnListFree(fields);

  format->ref_count = 1;
  format->entry = entry;
  Tcl_SetHashValue(entry, (ClientData) format);
  
  return format;
}


ZnLabelFormat
ZnLFDuplicate(ZnLabelFormat     lf)
{
  lf->ref_count++;
  return lf;
}


void
ZnLFDelete(ZnLabelFormat        lf)
{
  lf->ref_count--;
  if (lf->ref_count == 0) {
    Tcl_DeleteHashEntry(lf->entry);
    ZnFree(lf);
  }
}


char *
ZnLFGetString(ZnLabelFormat     lf)
{
  return Tcl_GetHashKey(&format_cache, lf->entry);

#if 0
  ZnFieldFormat ff;
  char          *ptr;
  char          x_char, y_char, w_char, h_char;
  unsigned int  i, count;
  
  ptr = str;
  if ((lf->clip_width != 0) || (lf->clip_height != 0)) {
    count = sprintf(ptr, "%dx%d", lf->clip_width, lf->clip_height);
    ptr += count;
  }
  if (lf->left_y < 0) {
    count = sprintf(ptr, "|%d", lf->left_x);
  }
  else {
    count = sprintf(ptr, "%%%dx%d", lf->left_x, lf->left_y);
  }
  ptr += count;
  if (lf->right_y < 0) {
    count = sprintf(ptr, "|%d", lf->right_x);
  }
  else {
    count = sprintf(ptr, "%%%dx%d", lf->right_x, lf->right_y);
  }
  ptr += count;
  for (i = 0; i < lf->num_fields; i++) {
    ff = &lf->fields[i];
    x_char = AttachToChar(ff->x_attach);
    y_char = AttachToChar(ff->y_attach);
    w_char = DimToChar(ff->x_dim);
    h_char = DimToChar(ff->y_dim);
    count = sprintf(ptr, "%c%d%c%d%c%d%c%d",
                    w_char, ff->width_spec, h_char, ff->height_spec,
                    x_char, ff->x_spec, y_char, ff->y_spec);
    ptr += count;
  }
  *ptr = 0;
#endif
}


/*
 * If the clip box has both its width and its height
 * set to zero, it means that there is no clipbox.
 */
ZnBool
ZnLFGetClipBox(ZnLabelFormat    lf,
               ZnDim            *w,
               ZnDim            *h)
{
  if ((lf->clip_width == 0) && (lf->clip_height == 0)) {
    return False;
  }

  *w = (ZnDim) lf->clip_width;
  *h = (ZnDim) lf->clip_height;
  
  return True;
}


void
ZnLFGetField(ZnLabelFormat      lf,
             unsigned int       field,
             char               *x_attach,
             char               *y_attach,
             char               *x_dim,
             char               *y_dim,
             int                *x_spec,
             int                *y_spec,
             short              *width_spec,
             short              *height_spec)
{
  ZnFieldFormat fptr;

  fptr = &lf->fields[field];
  *x_attach = fptr->x_attach;
  *y_attach = fptr->y_attach;
  *x_dim = fptr->x_dim;
  *y_dim = fptr->y_dim;
  *x_spec = fptr->x_spec;
  *y_spec = fptr->y_spec;
  *width_spec = fptr->width_spec;
  *height_spec = fptr->height_spec;
}


/*
 ****************************************************************
 *
 * Code for line ends.
 *
 ****************************************************************
 */
static Tcl_HashTable    line_end_cache;
static ZnBool           line_end_inited = False;


ZnLineEnd
ZnLineEndCreate(Tcl_Interp      *interp,
                char            *line_end_str)
{
  Tcl_HashEntry *entry;
  ZnLineEnd     le;
  int           new, argc;
  ZnReal        a, b, c;
  
  if (!line_end_inited) {
    Tcl_InitHashTable(&line_end_cache, TCL_STRING_KEYS);
    line_end_inited = True;
  }

  entry = Tcl_CreateHashEntry(&line_end_cache, line_end_str, &new);
  if (!new) {
    le = (ZnLineEnd) Tcl_GetHashValue(entry);
    le->ref_count++;
    return le;
  }

  argc = sscanf(line_end_str, "%lf %lf %lf", &a, &b, &c);
  if (argc == 3) {
    le = (ZnLineEnd) ZnMalloc(sizeof(ZnLineEndStruct));
    le->shape_a = a;
    le->shape_b = b;
    le->shape_c = c;
    le->entry = entry;
    le->ref_count = 1;
    Tcl_SetHashValue(entry, (ClientData) le);
    return le;
  }
  else {
    Tcl_AppendResult(interp, "incorrect line end spec: \"",
                     line_end_str, "\", should be: shapeA shapeB shapeC", NULL);
    return NULL;
  }
}


char *
ZnLineEndGetString(ZnLineEnd    le)
{
  return Tcl_GetHashKey(&line_end_cache, le->entry);
}


void
ZnLineEndDelete(ZnLineEnd       le)
{
  le->ref_count--;
  if (le->ref_count == 0) {
    Tcl_DeleteHashEntry(le->entry);
    ZnFree(le);
  }
}


ZnLineEnd
ZnLineEndDuplicate(ZnLineEnd    le)
{
  le->ref_count++;
  return le;
}


/*
 ******************************************************************
 *
 * Code for fill rules. They are directly inhereted from the
 * GLU tesselator constants.
 *
 ******************************************************************
 */
#define FILL_RULE_ODD_SPEC       "odd"
#define FILL_RULE_NON_ZERO_SPEC  "nonzero"
#define FILL_RULE_POSITIVE_SPEC  "positive"
#define FILL_RULE_NEGATIVE_SPEC  "negative"
#define FILL_RULE_ABS_GEQ_2_SPEC "abs_geq_2"

int
ZnGetFillRule(ZnWInfo    *wi,
              char       *name,
              ZnFillRule *fill_rule)
{
  unsigned int len;

  len = strlen(name);
  if (strncmp(name, FILL_RULE_ODD_SPEC, len) == 0) {
    *fill_rule = GLU_TESS_WINDING_ODD;
  }
  else if (strncmp(name, FILL_RULE_NON_ZERO_SPEC, len) == 0) {
    *fill_rule = GLU_TESS_WINDING_NONZERO;
  }
  else if (strncmp(name, FILL_RULE_POSITIVE_SPEC, len) == 0) {
    *fill_rule = GLU_TESS_WINDING_POSITIVE;
  }
  else if (strncmp(name, FILL_RULE_NEGATIVE_SPEC, len) == 0) {
    *fill_rule = GLU_TESS_WINDING_NEGATIVE;
  }
  else if (strncmp(name, FILL_RULE_ABS_GEQ_2_SPEC, len) == 0) {
    *fill_rule = GLU_TESS_WINDING_ABS_GEQ_TWO;
  }
  else  {
    Tcl_AppendResult(wi->interp, "bad fill rule \"", name, "\": must be ",
                     FILL_RULE_ODD_SPEC, ", ",
                     FILL_RULE_NON_ZERO_SPEC, ", ",
                     FILL_RULE_POSITIVE_SPEC, ", ",
                     FILL_RULE_NEGATIVE_SPEC, ", ",
                     FILL_RULE_ABS_GEQ_2_SPEC,
                     NULL);
    return TCL_ERROR;
  }
  return TCL_OK;
}

char *
ZnNameOfFillRule(ZnFillRule fill_rule)
{
  switch (fill_rule) {
  case GLU_TESS_WINDING_ODD:
    return FILL_RULE_ODD_SPEC;
  case GLU_TESS_WINDING_NONZERO:
    return FILL_RULE_NON_ZERO_SPEC;
  case GLU_TESS_WINDING_POSITIVE:
    return FILL_RULE_POSITIVE_SPEC;
  case GLU_TESS_WINDING_NEGATIVE:
    return FILL_RULE_NEGATIVE_SPEC;
  case GLU_TESS_WINDING_ABS_GEQ_TWO:
    return FILL_RULE_ABS_GEQ_2_SPEC;
  default:
    return "unknown fill rule";
  }
}


/*
 ******************************************************************
 *
 * Code for auto alignments in fields.
 *
 ******************************************************************
 */
int
ZnGetAutoAlign(ZnWInfo          *wi,
               char             *name,
               ZnAutoAlign      *aa)
{
  int       j;
  
  if (strcmp(name, "-") == 0) {
    aa->automatic = False;
  }
  else if (strlen(name) == 3) {
    aa->automatic = True;
    for (j = 0; j < 3; j++) {
      switch(name[j]) {
      case 'l':
      case 'L':
        aa->align[j] = TK_JUSTIFY_LEFT;
        break;
      case 'c':
      case 'C':
        aa->align[j] = TK_JUSTIFY_CENTER;
        break;
      case 'r':
      case 'R':
        aa->align[j] = TK_JUSTIFY_RIGHT;
        break;
      default:
        goto aa_error;
      }
    }
  }
  else {
  aa_error:
    Tcl_AppendResult(wi->interp, "invalid auto alignment specification \"", name,
                     "\" should be - or a triple of lcr", NULL);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
 * name must be large enough to hold the returned string.
 * 64 chars should be enough with the current values.
 */
void
ZnNameOfAutoAlign(ZnAutoAlign *aa,
                  char        *name)
{
  unsigned int i;
  
  if (aa->automatic == False) {
    strcpy(name, "-");
  }
  else {
    name[0] = 0;
    for (i = 0; i < 3; i++) {
      switch (aa->align[i]) {
      case TK_JUSTIFY_LEFT:
        strcat(name, "l");
        break;
      case TK_JUSTIFY_CENTER:
        strcat(name, "c");
        break;
      case TK_JUSTIFY_RIGHT:
        strcat(name, "r");
        break;
      }
    }
  }
}

Added jni/tkzinc/generic/Attrs.h.



































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/*
 * Attrs.h -- Header for the attribute manipulation routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Fri Dec 31 10:06:37 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Attrs_h
#define _Attrs_h

#ifdef __CPLUSPLUS__
extern "C" {
#endif


#include <Types.h>
  

struct _ZnWInfo;

/*
 * Type and constant values for line styles.
 */
typedef unsigned char   ZnLineStyle;

#define ZN_LINE_SIMPLE  0
#define ZN_LINE_DASHED  1
#define ZN_LINE_MIXED   2
#define ZN_LINE_DOTTED  3

int ZnGetLineStyle(struct _ZnWInfo *wi, char *name, ZnLineStyle *line_style);
char *ZnNameOfLineStyle(ZnLineStyle line_style);


/*
 * Type and constant values for line shapes.
 */
typedef unsigned char   ZnLineShape;

#define ZN_LINE_STRAIGHT                0
#define ZN_LINE_LEFT_LIGHTNING          1
#define ZN_LINE_LEFT_CORNER             2
#define ZN_LINE_DOUBLE_LEFT_CORNER      3
#define ZN_LINE_RIGHT_LIGHTNING         4
#define ZN_LINE_RIGHT_CORNER            5
#define ZN_LINE_DOUBLE_RIGHT_CORNER     6

int ZnGetLineShape(struct _ZnWInfo *wi, char *name, ZnLineShape *line_shape);
char *ZnNameOfLineShape(ZnLineShape line_shape);


/*
 * Type and constant values for relief styles.
 */
typedef unsigned char   ZnReliefStyle;
#define ZN_RELIEF_FLAT          0
#define ZN_RELIEF_RAISED        1
#define ZN_RELIEF_SUNKEN        2
#define ZN_RELIEF_GROOVE        (ZN_RELIEF_TWO_FACES|ZN_RELIEF_SUNKEN)
#define ZN_RELIEF_RIDGE         (ZN_RELIEF_TWO_FACES|ZN_RELIEF_RAISED)
#define ZN_RELIEF_ROUND_SUNKEN  (ZN_RELIEF_ROUND|ZN_RELIEF_SUNKEN)
#define ZN_RELIEF_ROUND_RAISED  (ZN_RELIEF_ROUND|ZN_RELIEF_RAISED)
#define ZN_RELIEF_ROUND_GROOVE  (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_SUNKEN)
#define ZN_RELIEF_ROUND_RIDGE   (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_RAISED)
#define ZN_RELIEF_SUNKEN_RULE   (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_SUNKEN|ZN_RELIEF_RULE)
#define ZN_RELIEF_RAISED_RULE   (ZN_RELIEF_ROUND|ZN_RELIEF_TWO_FACES|ZN_RELIEF_RAISED|ZN_RELIEF_RULE)
#define ZN_RELIEF_ROUND         0x80
#define ZN_RELIEF_TWO_FACES     0x40
#define ZN_RELIEF_RULE          0x20
#define ZN_RELIEF_MASK          0x3

/*
 * Number of steps for relief drawing. This translate in
 * RELIEF_STEPS*2+1 color shades in the color gradient.
 */
#define ZN_RELIEF_STEPS         6
  
int ZnGetRelief(struct _ZnWInfo *wi, char *name, ZnReliefStyle *relief);
char *ZnNameOfRelief(ZnReliefStyle relief);


/*
 * Type and constant values for borders.
 */
typedef unsigned char   ZnBorder;
#define ZN_NO_BORDER            0
#define ZN_LEFT_BORDER          1
#define ZN_RIGHT_BORDER         2
#define ZN_TOP_BORDER           4
#define ZN_BOTTOM_BORDER        8
#define ZN_CONTOUR_BORDER       (ZN_LEFT_BORDER|ZN_RIGHT_BORDER|ZN_TOP_BORDER|ZN_BOTTOM_BORDER)
#define ZN_COUNTER_OBLIQUE      16
#define ZN_OBLIQUE              32

void ZnNameOfBorder(ZnBorder border, char *str);
int ZnGetBorder(struct _ZnWInfo *wi, Tcl_Obj *name, ZnBorder *border);


/*
 * Type for leader anchors.
 */
typedef struct {
  int           left_x;         /* left leader anchor field or percent of bbox */
  int           right_x;        /* right leader anchor field or percent of bbox */
  short         left_y;         /* left leader percent of bbox or < 0 if field */
  short         right_y;        /* right leader percent of bbox or < 0 if field */
} ZnLeaderAnchorsStruct, *ZnLeaderAnchors;

int ZnGetLeaderAnchors(struct _ZnWInfo *wi, char *name, ZnLeaderAnchors *leader_anchors);
void ZnNameOfLeaderAnchors(ZnLeaderAnchors leader_anchors, char *name);


/*
 * Type and constant values for automatic alignments.
 */
typedef struct {
  ZnBool        automatic;
  Tk_Justify    align[3];
} ZnAutoAlign;
#define ZN_AA_LEFT              0
#define ZN_AA_CENTER            1
#define ZN_AA_RIGHT             2

int ZnGetAutoAlign(struct _ZnWInfo *wi, char *name, ZnAutoAlign *aa);
void ZnNameOfAutoAlign(ZnAutoAlign *aa, char *name);


/*
 * Label Formats.
 */
  
/*
 * field flags.
 */
#define ZN_LF_ATTACH_PIXEL      0
#define ZN_LF_ATTACH_FWD        1
#define ZN_LF_ATTACH_BWD        2
#define ZN_LF_ATTACH_LEFT       3       /* Align left on left or top on top */
#define ZN_LF_ATTACH_RIGHT      4       /* Align right on right or bottom on bottom */

#define ZN_LF_DIM_PIXEL 0
#define ZN_LF_DIM_FONT  1
#define ZN_LF_DIM_ICON  2
#define ZN_LF_DIM_AUTO  3
#define ZN_LF_DIM_LABEL 4
  
typedef struct {
  int   x_spec;
  int   y_spec;
  short width_spec;
  short height_spec;
  char  x_attach;
  char  y_attach;
  char  x_dim;
  char  y_dim;
} ZnFieldFormatStruct, *ZnFieldFormat;

typedef struct {
  short         clip_width;
  short         clip_height;
  unsigned int  num_fields;
  Tcl_HashEntry *entry;
  unsigned int  ref_count;
  ZnFieldFormatStruct fields[1];
} ZnLabelFormatStruct, *ZnLabelFormat;
  

ZnLabelFormat
ZnLFCreate(Tcl_Interp   * /* interp */,
           char         * /* format_str */,
           unsigned int /* num_fields */);
ZnLabelFormat
ZnLFDuplicate(ZnLabelFormat     /* label_format */);
void
ZnLFDelete(ZnLabelFormat        /* label_format */);
char *
ZnLFGetString(ZnLabelFormat     /* label_format */);
ZnBool
ZnLFGetClipBox(ZnLabelFormat    /* label_format */,
               ZnDim            * /* width */,
               ZnDim            * /* height */);
#define ZnLFNumFields(lf)       ((lf)->num_fields)
void
ZnLFGetField(ZnLabelFormat      /* label_format */,
             unsigned int       /* field */,
             char               * /* x_attach */,
             char               * /* y_attach */,
             char               * /* x_dim */,
             char               * /* y_dim */,
             int                * /* x_spec */,
             int                * /* y_spec */,
             short              * /* width_spec */,
             short              * /* height_spec */);

/*
 * Line Ends.
 */
typedef struct {
  ZnReal        shape_a;
  ZnReal        shape_b;
  ZnReal        shape_c;
  Tcl_HashEntry *entry;
  unsigned int  ref_count;
} ZnLineEndStruct, *ZnLineEnd;

ZnLineEnd
ZnLineEndCreate(Tcl_Interp      *interp,
                char            *line_end_str);
ZnLineEnd
ZnLineEndDuplicate(ZnLineEnd    le);
void
ZnLineEndDelete(ZnLineEnd       le);
char *
ZnLineEndGetString(ZnLineEnd    le);


/*
 * Type and protypes for fill rules.
 */
typedef unsigned int    ZnFillRule;

char *ZnNameOfFillRule(ZnFillRule fill_rule);
int ZnGetFillRule(struct _ZnWInfo *wi, char *name, ZnFillRule *fill_rule);


#ifdef __CPLUSPLUS__
}
#endif

#endif  /* _Attrs_h */

Added jni/tkzinc/generic/CharsetISO8859-15.h.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * These chars are those found in iso8859-15.
 * They are encoded in iso8859-15 right in this file and sorted
 * by ascending value, _keep_ them sorted this way, a dichotomic
 * search rely on this to locate the glyphs and infos.
 */
static unsigned char *ZnDefaultCharset =
  "\x00\x01\x02\x03\x04\x05\x06\x07"
  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
  "\x10\x11\x12\x13\x14\x15\x16\x17"
  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
  " !\"#$%&'()*+,-./"
  "0123456789"
  ":;<=>?@"
  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  "[\\]^_`"
  "abcdefghijklmnopqrstuvwxyz"
  "{|}~"
  ""
  ""
  "";

Added jni/tkzinc/generic/CharsetUTF8.h.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
 * These chars are those found in iso8859-15 and iso8859-1.
 * They are encoded in UTF8 right in this file and sorted
 * by Unicode point, _keep_ them sorted this way, a dichotomic
 * search rely on this to locate the glyphs and infos.
 */
static unsigned char *ZnDefaultCharset =
  " !\"#$%&'()*+,-./"
  "0123456789"
  ":;<=>?@"
  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  "[\\]^_`"
  "abcdefghijklmnopqrstuvwxyz"
  "{|}~"
  "¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿"
  "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß"
  "àáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
  "ŒœŠšŸŽž―€↗↘";

/*
 * Local Variables:
 * coding: utf-8
 * End:
 *
 */

Added jni/tkzinc/generic/Color.c.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
/*
 * Color.c -- Color management module.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Thu Dec 16 15:41:53 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
 * Most of this file is derived from Tk color code and thus
 * also copyrighted:
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
 *
 */


#include <string.h>
#include <stdlib.h>

#include "Types.h"
#include "Image.h"
#include "Color.h"
#include "Geo.h"
#include "Transfo.h"


/*
 * Maximum size of a color name including the \0.
 */
#define COLOR_NAME_SIZE 32

/*
 * Maximum intensity for a color.
 */
#define MAX_INTENSITY 65535

/*
 * Hash table to map from a gradient's values (color, etc.) to a
 * gradient structure for those values.
 */
static Tcl_HashTable gradient_table;

static int initialized = 0;     /* 0 means static structures haven't been
                                 * initialized yet. */


/*
 *----------------------------------------------------------------------
 *
 * ColorInit --
 *
 *      Initialize the structure used for color management.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Read the code.
 *
 *----------------------------------------------------------------------
 */
static void
ColorInit()
{
  initialized = 1;
  Tcl_InitHashTable(&gradient_table, TCL_STRING_KEYS);
}


/*
 *----------------------------------------------------------------------
 *
 * ZnGetGradientColor
 * ZnInterpGradientColor --
 *
 *----------------------------------------------------------------------
 */
XColor *
ZnGetGradientColor(ZnGradient   *grad,
                   ZnReal       position,
                   unsigned short *alpha)
{
  int    index, min, max;
  XColor *shade=NULL;
  
  if ((grad->num_actual_colors == 1) || (position <= 0.0)) {
    if (alpha) {
      *alpha = grad->actual_colors[0].alpha;
    }
    return grad->actual_colors[0].rgb;
  }
  if (position >= 100.0) {
    if (alpha) {
      *alpha = grad->actual_colors[grad->num_actual_colors-1].alpha;
    }
    shade = grad->actual_colors[grad->num_actual_colors-1].rgb;
  }
  else {
    min = 0;
    max = grad->num_actual_colors-1;
    index = (max + min) / 2;
    while (max - min != 1) {
      /*printf("color index %d, min: %d, max: %d\n", index, min, max);*/
      if (grad->actual_colors[index].position < position) {
        min = index;
      }
      else {
        max = index;
      }
      index = (max + min) / 2;
    }
    shade = grad->actual_colors[index].rgb;
    if (alpha) {
      *alpha = grad->actual_colors[index].alpha;
    }
  }

  return shade;
}

void
ZnInterpGradientColor(ZnGradient     *grad,
                      ZnReal         position,
                      XColor         *color,
                      unsigned short *alpha)
{
  int index, min, max;
  ZnGradientColor *gc1, *gc2;
  ZnReal rel_pos;

  if ((grad->num_actual_colors == 1) || (position <= 0.0)) {
    *alpha = grad->actual_colors[0].alpha;
    *color = *grad->actual_colors[0].rgb;
  }
  else if (position >= 100.0) {
    *alpha = grad->actual_colors[grad->num_actual_colors-1].alpha;
    *color = *grad->actual_colors[grad->num_actual_colors-1].rgb;
  }
  else {
    min = 0;
    max = grad->num_actual_colors-1;
    index = (max + min) / 2;
    while (max - min != 1) {
      /*printf("color index %d, min: %d, max: %d\n", index, min, max);*/
      if (grad->actual_colors[index].position < position) {
        min = index;
      }
      else {
        max = index;
      }
      index = (max + min) / 2;
    }
    gc1 = &grad->actual_colors[index];
    gc2 = &grad->actual_colors[index+1];
    rel_pos = (position - gc1->position) * 100.0 / (gc2->position - gc1->position);
    
    if (rel_pos > gc1->control) {
      rel_pos = (rel_pos - gc1->control) * 100.0 / (100.0 - gc1->control);
      color->red = gc1->mid_rgb->red + 
        (unsigned short) ((gc2->rgb->red - gc1->mid_rgb->red) * rel_pos / 100.0);
      color->green = gc1->mid_rgb->green + 
        (unsigned short) ((gc2->rgb->green - gc1->mid_rgb->green) * rel_pos / 100.0);
      color->blue = gc1->mid_rgb->blue +
        (unsigned short) ((gc2->rgb->blue - gc1->mid_rgb->blue) * rel_pos / 100.0);
      *alpha = gc1->mid_alpha +
        (unsigned short) ((gc2->alpha - gc1->mid_alpha) * rel_pos / 100.0);
    }
    else {
      rel_pos = rel_pos * 100.0 / gc1->control;
      color->red = gc1->rgb->red +
        (unsigned short) ((gc1->mid_rgb->red - gc1->rgb->red) * rel_pos / 100.0);
      color->green = gc1->rgb->green +
        (unsigned short) ((gc1->mid_rgb->green - gc1->rgb->green) * rel_pos / 100.0);
      color->blue = gc1->rgb->blue +
        (unsigned short) ((gc1->mid_rgb->blue - gc1->rgb->blue) * rel_pos / 100.0);
      *alpha = gc1->alpha +
        (unsigned short) ((gc1->mid_alpha - gc1->alpha) * rel_pos / 100.0);
    }
  }
}


/*
 *--------------------------------------------------------------
 *
 * ZnGradientFlat --
 *
 *      Returns true if the gradient is defined by a single
 *      color.
 *
 *--------------------------------------------------------------
 */
ZnBool
ZnGradientFlat(ZnGradient       *grad)
{
  return (grad->num_actual_colors == 1);
}


/*
 *--------------------------------------------------------------
 *
 * ZnGetReliefGradient --
 *
 *      Create a data structure containing a range of colors
 *      used to display a 3D border. Name contains the base
 *      color for the border. This is a slight variation on
 *      the syntax of a gradient that make life easier in this
 *      simple case.
 *
 * Results:
 *      The return value is a token for a data structure
 *      describing a gradient.  This token may be passed
 *      to the drawing routines.
 *      If an error prevented the gradient from being created
 *      then NULL is returned and an error message will be
 *      left in interp.
 *
 * Side effects:
 *      Data structures, etc. are allocated.
 *      It is the caller's responsibility to eventually call
 *      ZnFreeGradient to release the resources.
 *
 *--------------------------------------------------------------
 */
ZnGradient *
ZnGetReliefGradient(Tcl_Interp  *interp,
                    Tk_Window   tkwin,
                    Tk_Uid      name,
                    unsigned short alpha)
{
  XColor *base, light_color, dark_color, color;
  char   color_name[COLOR_NAME_SIZE];
  char   buffer[COLOR_NAME_SIZE*(3+2*ZN_RELIEF_STEPS)];
  int    j, tmp1, tmp2;
  int    red_range, green_range, blue_range;
  
  base = Tk_GetColor(interp, tkwin, name);
  /*
   * Compute the border gradient.
   *
   * Always consider that we are dealing with a color display with
   * enough colors available. If the colormap is full (stressed)
   * then just pray, the susbstitution algorithm may return something
   * adequate ;-).
   *
   * The extremum colors get computed using whichever formula results
   * in the greatest change in color:
   * 1. Lighter color is half-way to white, darker color is half
   *    way to dark.
   * 2. Lighter color is 40% brighter than base, darker color
   *    is 40% darker than base.
   * The first approach works better for unsaturated colors, the
   * second for saturated ones.
   *
   * NOTE: Colors are computed with integers not color shorts which
   * may lead to overflow errors.
   */
  tmp1 = (30 * (int) base->red)/100;
  tmp2 = ((int) base->red)/2;
  dark_color.red = MIN(tmp1, tmp2);
  tmp1 = (30 * (int) base->green)/100;
  tmp2 = ((int) base->green)/2;
  dark_color.green = MIN(tmp1, tmp2);
  tmp1 = (30 * (int) base->blue)/100;
  tmp2 = ((int) base->blue)/2;
  dark_color.blue = MIN(tmp1, tmp2);
  
  tmp1 = MAX_INTENSITY;/*(170 * (int) base->red)/10;*/
  if (tmp1 > MAX_INTENSITY) {
    tmp1 = MAX_INTENSITY;
  }
  tmp2 = (MAX_INTENSITY + (int) base->red)/2;
  light_color.red = MAX(tmp1, tmp2);
  tmp1 = MAX_INTENSITY;/*(170 * (int) base->green)/10;*/
  if (tmp1 > MAX_INTENSITY) {
    tmp1 = MAX_INTENSITY;
  }
  tmp2 = (MAX_INTENSITY + (int) base->green)/2;
  light_color.green = MAX(tmp1, tmp2);
  tmp1 = MAX_INTENSITY;/*(170 * (int) base->blue)/10;*/
  if (tmp1 > MAX_INTENSITY) {
    tmp1 = MAX_INTENSITY;
  }
  tmp2 = (MAX_INTENSITY + (int) base->blue)/2;
  light_color.blue = MAX(tmp1, tmp2);

  buffer[0] = 0;
  sprintf(color_name, "#%02x%02x%02x;%d|",
          dark_color.red/256, dark_color.green/256, dark_color.blue/256, alpha);
  red_range = (int) base->red - (int) dark_color.red;
  green_range = (int) base->green - (int) dark_color.green;
  blue_range = (int) base->blue - (int) dark_color.blue;
  strcat(buffer, color_name);
  for (j = 1; j < ZN_RELIEF_STEPS; j++) {
    color.red =(int) dark_color.red +  red_range * j/ZN_RELIEF_STEPS;
    color.green = (int) dark_color.green + green_range * j/ZN_RELIEF_STEPS;
    color.blue = (int) dark_color.blue + blue_range * j/ZN_RELIEF_STEPS;
    sprintf(color_name, "#%02x%02x%02x;%d %d|",
            color.red/256, color.green/256, color.blue/256, alpha, 50/ZN_RELIEF_STEPS*j);
    strcat(buffer, color_name);
  }
  sprintf(color_name, "#%02x%02x%02x;%d 50|",
          base->red/256, base->green/256, base->blue/256, alpha);
  strcat(buffer, color_name);
  red_range = (int) light_color.red - (int) base->red;
  green_range = (int) light_color.green - (int) base->green;
  blue_range = (int) light_color.blue - (int) base->blue;
  for (j = 1; j < ZN_RELIEF_STEPS; j++) {
    color.red = (int) base->red +  red_range * j/ZN_RELIEF_STEPS;
    color.green = (int) base->green + green_range * j/ZN_RELIEF_STEPS;
    color.blue = (int) base->blue + blue_range * j/ZN_RELIEF_STEPS;
    sprintf(color_name, "#%02x%02x%02x;%d %d|",
            color.red/256, color.green/256, color.blue/256, alpha, 50+50/ZN_RELIEF_STEPS*j);
    strcat(buffer, color_name);
  }
  sprintf(color_name, "#%02x%02x%02x;%d",
          light_color.red/256, light_color.green/256, light_color.blue/256, alpha);
  strcat(buffer, color_name);

  /*printf("gradient relief: %s \n", buffer);*/
  return ZnGetGradient(interp, tkwin, buffer);
}


/*
 *--------------------------------------------------------------
 *
 * ZnNameGradient
 * ZnDeleteGradientName --
 *
 *      Save a gradient under a name or suppress the gradient
 *      name binding. The save function returns false if the
 *      name is already in use.
 *
 *--------------------------------------------------------------
 */
ZnBool
ZnNameGradient(Tcl_Interp       *interp,
               Tk_Window        tkwin,
               char             *grad_descr,
               char             *name)
{
  Tcl_HashEntry *hash;
  int           new;
  ZnGradient    *grad;
  XColor        color;

  /*
   * First try to find if the name interfere with a color name,
   * this must be avoided. Gradients may be described by a single
   * color name and gradient descriptions / names share the same
   * name space.
   */
  if (XParseColor(Tk_Display(tkwin), Tk_Colormap(tkwin), name, &color)) {
    Tcl_AppendResult(interp, "gradient name \"", name,
                     "\", is a color name", NULL);
    return False;
  }
  grad = ZnGetGradient(interp, tkwin, grad_descr);
  if (!grad) {
    Tcl_AppendResult(interp, "gradient specification \"", grad_descr,
                     "\", is invalid", NULL);
    return False;
  }
  hash = Tcl_CreateHashEntry(&gradient_table, Tk_GetUid(name), &new);
  if (!new) {
    ZnFreeGradient(grad);
    Tcl_AppendResult(interp, "gradient name \"", name,
                     "\", is already in use", NULL);
    return False;
  }
  else {
    Tcl_SetHashValue(hash, grad);
  }
  
  return True;
}

ZnBool
ZnGradientNameExists(char       *name)
{
  if (!initialized) {
    return False;
  }
  return Tcl_FindHashEntry(&gradient_table, Tk_GetUid(name)) != NULL;
}

void
ZnDeleteGradientName(char       *name)
{
  Tcl_HashEntry *hash;

  if (!initialized) {
    return;
  }
  
  hash = Tcl_FindHashEntry(&gradient_table, Tk_GetUid(name));
  if (hash) {
    Tcl_DeleteHashEntry(hash);
    ZnFreeGradient((ZnGradient *) Tcl_GetHashValue(hash));
  }
}

static void
InterpolateGradientColor(Tk_Window      tkwin,
                         ZnGradientColor *gc1,      /* First color */ 
                         ZnGradientColor *gc2,      /* Next color */
                         ZnGradientColor *gc_interp,/* New interpolated color */
                         ZnGradientColor *gc_adjust,/* Adjusted first color.
                                                     * Needed if interested in
                                                     * the range color1 interp
                                                     * color. */
                         int             interp_pos,
                         int             min_pos,
                         int             span)
{
  ZnReal pos1, pos2, ipos, interp_rel_pos, tmp;
  XColor rgb;

  //printf("interp_pos: %d, min_pos: %d, span: %d\n ", interp_pos, min_pos, span);
  pos1 = ((ZnReal)gc1->position-(ZnReal)min_pos)/(ZnReal)span;
  pos2 = ((ZnReal)gc2->position-(ZnReal)min_pos)/(ZnReal)span;
  ipos = ((ZnReal)interp_pos-(ZnReal)min_pos)/(ZnReal)span;
  interp_rel_pos = (ipos-pos1)*100/(pos2-pos1);

  //printf("pos1: %g, pos2: %g, interp_rel_pos: %g\n", pos1, pos2, interp_rel_pos);
  if (interp_rel_pos < gc1->control) {
    tmp = interp_rel_pos * 100.0 / gc1->control;
  //printf("rgb : %d, mid rgb : %d\n\n", gc1->rgb, gc1->mid_rgb);
    rgb.red = (unsigned short) (gc1->rgb->red + (gc1->mid_rgb->red - gc1->rgb->red) * tmp / 100.0);
    rgb.green = (unsigned short) (gc1->rgb->green + (gc1->mid_rgb->green - gc1->rgb->green) * tmp / 100.0);
    rgb.blue = (unsigned short) (gc1->rgb->blue + (gc1->mid_rgb->blue - gc1->rgb->blue) * tmp / 100.0);
    gc_interp->alpha = (unsigned char) (gc1->alpha + (gc1->mid_alpha - gc1->alpha) * tmp / 100.0);
  }
  else if (interp_rel_pos > gc1->control) {
    tmp = (interp_rel_pos - gc1->control) * 100.0 / (100.0 - gc1->control);
    rgb.red = (unsigned short) (gc1->mid_rgb->red + (gc2->rgb->red - gc1->mid_rgb->red)*tmp / 100.0);
    rgb.green = (unsigned short) (gc1->mid_rgb->green + (gc2->rgb->green - gc1->mid_rgb->green)*tmp / 100.0);
    rgb.blue = (unsigned short) (gc1->mid_rgb->blue + (gc2->rgb->blue - gc1->mid_rgb->blue)*tmp / 100.0);
    gc_interp->alpha = (unsigned char) (gc1->mid_alpha + (gc2->alpha - gc1->mid_alpha)*tmp / 100.0);
  }
  else {
    rgb = *gc1->mid_rgb;
    gc_interp->alpha = gc1->mid_alpha;    
  }
  gc_interp->rgb = Tk_GetColorByValue(tkwin, &rgb);

  if (!gc_adjust) {
    /*
     * Interested in the segment from the interpolated color
     * to color 2.
     */
    gc_interp->position = 0;
    if (interp_rel_pos < gc1->control) {
      gc_interp->control = gc1->control - (int) interp_rel_pos;
      gc_interp->mid_rgb = Tk_GetColorByValue(tkwin, gc1->mid_rgb);
      gc_interp->mid_alpha = gc1->mid_alpha;
    }
    else {
      rgb.red = gc_interp->rgb->red+(gc2->rgb->red-gc_interp->rgb->red)/2;
      rgb.green = gc_interp->rgb->green+(gc2->rgb->green-gc_interp->rgb->green)/2;
      rgb.blue = gc_interp->rgb->blue+(gc2->rgb->blue-gc_interp->rgb->blue)/2;
      gc_interp->mid_rgb = Tk_GetColorByValue(tkwin, &rgb);
      gc_interp->mid_alpha = gc_interp->alpha + (gc2->alpha - gc_interp->alpha)/2;
      gc_interp->control = 50;
    }
  }
  else {
    /*
     * Interested in the segment from color 1 (color adjusted) to
     * the interpolated color.
     */
    gc_interp->position = 100;
    gc_interp->mid_rgb = NULL;
    gc_interp->mid_alpha = 100;
    if (interp_rel_pos <= gc1->control) {
      rgb.red = gc1->rgb->red+(gc_interp->rgb->red-gc1->rgb->red)/2;
      rgb.green = gc1->rgb->green+(gc_interp->rgb->green-gc1->rgb->green)/2;
      rgb.blue = gc1->rgb->blue+(gc_interp->rgb->blue-gc1->rgb->blue)/2;
      Tk_FreeColor(gc_adjust->mid_rgb);
      gc_adjust->mid_rgb = Tk_GetColorByValue(tkwin, &rgb);
      gc_adjust->mid_alpha = gc1->alpha + (gc_interp->alpha - gc1->alpha)/2;
      gc_adjust->control = 50;
    }
  }
  //printf("out of InterpolateGradientColor\n");
}


static void
ReduceGradient(Tk_Window        tkwin,
               ZnGradient       *grad)
{
  ZnReal     dx, dy, len, angle;
  ZnTransfo  t;
  ZnPoint    pbbox[4], pgrad[4];
  ZnReal     maxx, minx, span, start_in_new, end_in_new;
  int        minx100, maxx100, span100;
  int        i, j, first_color, last_color;
  ZnBool     interpolate_first, interpolate_last;

  //printf("In ReduceGradient %d\n", grad->num_colors_in);
  dx = grad->e.x - grad->p.x;
  dy = grad->e.y - grad->p.y;
  len = sqrt(dx*dx+dy*dy);
  angle = acos(dx/len);
  if (dy < 0) {
    angle = 2*M_PI - angle;
  }  
  grad->angle = (int) -ZnRadDeg(angle);

  if (grad->type == ZN_CONICAL_GRADIENT) {
  unchanged:
    grad->actual_colors = grad->colors_in;
    grad->num_actual_colors = grad->num_colors_in;
    return;
  }

  ZnTransfoSetIdentity(&t);
  ZnTranslate(&t, -grad->p.x, -grad->p.y, False);
  ZnRotateRad(&t, -angle);
  ZnScale(&t, 1/len, 1/len);
  pbbox[0].x = -50;
  pbbox[0].y = 50;
  pbbox[1].x = 50;
  pbbox[1].y = 50;
  pbbox[2].x = 50;
  pbbox[2].y = -50;
  pbbox[3].x = -50;
  pbbox[3].y = -50;
  ZnTransformPoints(&t, pbbox, pgrad, 4);
  maxx = minx = pgrad[0].x;
  for (i = 1; i < 4; i++) {
    if (pgrad[i].x > maxx) {
      maxx = pgrad[i].x;
    }
    if (pgrad[i].x < minx) {
      minx = pgrad[i].x;
    }
  }

  span = maxx-minx;
  if (grad->type == ZN_RADIAL_GRADIENT) {
    start_in_new = 0;
    end_in_new = 100/span;
  }
  else {
    start_in_new = -minx*100/span;
    end_in_new = (1-minx)*100/span;
  }

  //printf("minx: %g, maxx: %g, start%%: %g, end%%: %g\n",
    //     minx, maxx, start_in_new, end_in_new);
  
  /*
   * Gradient is unchanged
   */
  if ((ABS(start_in_new) < PRECISION_LIMIT) &&
      (ABS(end_in_new-100.0) < PRECISION_LIMIT)) {
    goto unchanged;
  }
  //printf("start_in_new: %g, end_in_new: %g\n", start_in_new, end_in_new);
  if ((start_in_new > 100.0) || (end_in_new < 0.0)) {
    grad->num_actual_colors = 1;
    grad->actual_colors = ZnMalloc(sizeof(ZnGradientColor));
    grad->actual_colors[0].position = 0;
    grad->actual_colors[0].mid_rgb = NULL;
    if (end_in_new < 0.0) {
      grad->actual_colors[0].alpha = grad->colors_in[grad->num_colors_in-1].alpha;
      grad->actual_colors[0].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[grad->num_colors_in-1].rgb);
    }
    else {
      grad->actual_colors[0].alpha = grad->colors_in[0].alpha;
      grad->actual_colors[0].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[0].rgb);
    }
    return;
  }

  grad->num_actual_colors = grad->num_colors_in;
  interpolate_first = False;
  minx100 = (int) (minx*100);
  maxx100 = (int) (maxx*100);
  span100 = (int) (span*100);

  if (start_in_new < 0.0) {
    /*
     * The gradient starts outside the bbox,
     * Find the color at the bbox edge. First
     * find the correct gradient segment and then
     * interpolate to get the color.
     */
    first_color = 1;
    while ((first_color < (int) grad->num_colors_in) &&
           (grad->colors_in[first_color].position < minx100)) {
      first_color++;
      grad->num_actual_colors--;
    }
    if (grad->colors_in[first_color].position == minx100) {
      grad->num_actual_colors--;
    }
    else {
      interpolate_first = True;
      /*printf("interpolate first color\n");*/
    }
  }
  else {
    first_color = 0;
    if (grad->type != ZN_RADIAL_GRADIENT) {
      grad->num_actual_colors++;
    }
  }
  interpolate_last = False;
  if (end_in_new > 100.0) {
    /*
     * The gradient ends outside the bbox,
     * Find the color at the bbox edge. First
     * find the correct gradient segment and then
     * interpolate to get the color.
     */
    last_color = grad->num_colors_in-2;
    while ((last_color >= 0) &&
           (grad->colors_in[last_color].position > maxx100)) {
      last_color--;
      grad->num_actual_colors--;
    }
    if (grad->colors_in[last_color].position == maxx100) {
      grad->num_actual_colors--;
    }
    else {
      interpolate_last = True;
      /*printf("interpolate last color\n");*/
    }
  }
  else {
    last_color = grad->num_colors_in-1;
    grad->num_actual_colors++;
  }

  grad->actual_colors = ZnMalloc(grad->num_actual_colors*sizeof(ZnGradientColor));
  //printf("allocating %d colors\n", grad->num_actual_colors);
  j = 0;
  if (interpolate_first) {
    //printf("Interpolate first color, index: %d\n", first_color);
    InterpolateGradientColor(tkwin,
                             &grad->colors_in[first_color-1],
                             &grad->colors_in[first_color],
                             &grad->actual_colors[0],
                             NULL,
                             minx100, minx100, span100);
    j++;
  }
  else if ((first_color == 0) && (grad->type != ZN_RADIAL_GRADIENT)) {
    grad->actual_colors[0] = grad->colors_in[0];
    grad->actual_colors[0].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[0].rgb);
    if (grad->colors_in[0].mid_rgb) {
      grad->actual_colors[0].mid_rgb = Tk_GetColorByValue(tkwin, grad->colors_in[0].mid_rgb);
    }
    grad->actual_colors[0].position = 0;
    grad->actual_colors[0].control = 50;
    j++;
    /*printf("adding a color at start\n");*/
  }

  //printf("j: %d, first color: %d, last color: %d, num colors: %d\n",
    //     j, first_color, last_color, grad->num_actual_colors);
  for (i = first_color; i <= last_color; i++, j++) {
    grad->actual_colors[j] = grad->colors_in[i];
    grad->actual_colors[j].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].rgb);
    if (grad->colors_in[i].mid_rgb) {
      grad->actual_colors[j].mid_rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].mid_rgb);
    }
    grad->actual_colors[j].position = (grad->colors_in[i].position-minx100)*100/span100;
    /*printf("i: %d, j: %d, minx: %d, span: %d, position av: %d position ap: %d\n",
      i, j, minx100, span100, grad->colors_in[i].position, grad->actual_colors[j].position);*/
  }

  if (interpolate_last) {
    //printf("Interpolate last color: %d, j :%d\n", last_color, j);
    InterpolateGradientColor(tkwin,
                             &grad->colors_in[last_color],
                             &grad->colors_in[last_color+1],
                             &grad->actual_colors[j],
                             &grad->actual_colors[j-1],
                             maxx100, minx100, span100);
  }
  else if (last_color == ((int) grad->num_colors_in)-1) {
    i = grad->num_colors_in-1;
    //printf("i: %d, j: %d\n", i, j);
    grad->actual_colors[j] = grad->colors_in[i];
    grad->actual_colors[j].rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].rgb);
    if (grad->colors_in[i].mid_rgb) {
      grad->actual_colors[j].mid_rgb = Tk_GetColorByValue(tkwin, grad->colors_in[i].mid_rgb);    
    }
    /*printf("adding a color at end\n");*/
  }
  grad->actual_colors[grad->num_actual_colors-1].position = 100;
  //printf("Out of ReduceGradient\n");
}


/*
 *--------------------------------------------------------------
 *
 * ZnGetGradient --
 *
 *      Create a data structure containing a range of colors
 *      used to display a gradient. 
 *
 *      The gradient should have the following syntax:
 *
 *      gradient := [graddesc|]color[|....|color]
 *        where the | are real characters not meta-syntax.
 *
 *      graddesc := =type args
 *        where type := axial | radial | path
 *
 *        If type = axial
 *              args := angle (0..360) | xs ys xe ye (reals)
 *
 *        The first form define the axial gradiant by its slope.
 *        With this syntax the gradient fits the whole shape.
 *        This is a backward compatible syntax.
 *        The second form specifies a vector which will be used
 *        to draw the gradient. The vector defines both the angle
 *        and the gradient area. Parts of the shape that lie before
 *        the vector origin are filled with the first color and
 *        parts that lie after the vector end are filled with the
 *        last color.
 *
 *        If type = radial or path
 *              args := xs ys [xe ye] (reals)
 *
 *        The vector specified by the 4 coordinates defines the
 *        gradient area.  Parts of the shape that lie before
 *        the vector origin are filled with the first color and
 *        parts that lie after the vector end are filled with the
 *        last color. The vector end may be omitted, in such case
 *        the gradient fits exactly the whole shape to be filled,
 *        this is backward compatible with older gradients.
 *        
 *      color := colorvalue | colorvalue position |
 *               colorvalue control position
 *        where position and control are in (0..100)
 *
 *      colorvalue := (colorname | #rgb | cievalue)[;alpha]
 *        where alpha is in (0..100)
 *
 * Results:
 *      The return value is a token for a data structure
 *      describing a gradient. This token may be passed
 *      to the drawing routines.
 *      If an error prevented the gradient from being created
 *      then NULL is returned and an error message will be
 *      left in interp.
 *
 * Side effects:
 *      Data structures, etc. are allocated.
 *      It is the caller's responsibility to eventually call
 *      ZnFreeGradient to release the resources.
 *
 *--------------------------------------------------------------
 */
ZnGradient *
ZnGetGradientByValue(ZnGradient *grad)
{
  grad->ref_count++;
  return grad;
}


static int
ParseRealList(const char *str,
              const char *stop,
              ZnReal     *list,
              int        max)
{
  int    num;
  char   *end;

  num = 0;
  while ((num < max) && (str != stop)) {
    list[num] = strtod(str, &end);
    if (end == str) {
      /* A syntax error occured, return a 0 count
       * as a hint for the caller.
       */
      return 0;
    }
    num++;
    str = end+strspn(end, " \t");
  }
  return num;
}

ZnGradient *
ZnGetGradient(Tcl_Interp        *interp,
              Tk_Window         tkwin,
              Tk_Uid            desc)
{
  #define SEGMENT_SIZE 64
  Tcl_HashEntry *hash;
  ZnGradient    *grad;
  unsigned int  i, j, nspace, num_colors;
  unsigned int  size, num_coords=0;
  char          type;
  char const    *scan_ptr, *next_ptr, *str_ptr;
  ZnReal        angle, position, control;
  ZnReal        coords[4];
  char          *color_ptr, *end, segment[SEGMENT_SIZE];
  ZnGradientColor *first, *last;
  XColor        color;
  int           new, red_range, green_range, blue_range;
  ZnBool        simple;

  //printf("ZnGetGradient : %s\n", desc);
  if (!desc || !*desc) {
    return NULL;
  }
  if (!initialized) {
    ColorInit();
  }
  
  /*
   * First, check to see if there's already a gradient that will work
   * for this request.
   */  
  desc = Tk_GetUid(desc);

  /*printf("get gradient: %s\n", desc);*/
  hash = Tcl_CreateHashEntry(&gradient_table, desc, &new);
  if (!new) {
    grad = (ZnGradient *) Tcl_GetHashValue(hash);
    grad->ref_count++;
    return grad;
  }

  /*
   * No satisfactory gradient exists yet.  Initialize a new one.
   */
  type = ZN_AXIAL_GRADIENT;
  angle = 0.0;
  /*
   * Skip the trailing spaces.
   */
  while (*desc == ' ') {
    desc++;
  }
  /*
   * Count the sections in the description. It should give
   * the number of colors plus may be the gradient description.
   */
  scan_ptr = desc;
  /*
   * If the first section is the gradient description, start color
   * counts up from zero.
   */
  num_colors = (*scan_ptr == '=') ? 0 : 1;
  while ((scan_ptr = strchr(scan_ptr, '|'))) {
    num_colors++;
    scan_ptr++;
  }
  if (num_colors == 0) {
    Tcl_AppendResult(interp, "gradient should have at least one color \"",
                     desc, "\",", NULL);
  grad_err1:
    Tcl_DeleteHashEntry(hash);
    /*printf("ZnGetGradient error : %s\n", desc);*/
    return NULL;
  }
  /*
   * Then look at the gradient type.
   */
  scan_ptr = desc;
  /*
   * next_ptr can't be NULL in the following code,
   * we checked that at least one color was specified
   * after the gradient description.
   */
  next_ptr = strchr(scan_ptr, '|');
  if (*scan_ptr == '=') {
    scan_ptr++;
    if ((*scan_ptr == 'a') && (strncmp(scan_ptr, "axial", 5) == 0)) {
      scan_ptr += 5;
      num_coords = ParseRealList(scan_ptr, next_ptr, coords, 4);
      if ((num_coords != 1) && (num_coords != 4)) {
      grad_err3:
        Tcl_AppendResult(interp, "invalid gradient parameter \"",
                         desc, "\",", NULL);
        goto grad_err1;
      }
      angle = (int) coords[0];
    }
    else if ((*scan_ptr == 'c') && (strncmp(scan_ptr, "conical", 7) == 0)) {
      scan_ptr += 7;
      type = ZN_CONICAL_GRADIENT;
      num_coords = ParseRealList(scan_ptr, next_ptr, coords, 4);
      if ((num_coords < 1) && (num_coords > 4)) {
        goto grad_err3;
      }
      angle = (int) coords[0];
    }
    else if (((*scan_ptr == 'r') && (strncmp(scan_ptr, "radial", 6) == 0)) ||
             ((*scan_ptr == 'p') && (strncmp(scan_ptr, "path", 4) == 0))) {
      if (*scan_ptr == 'r') {
        type = ZN_RADIAL_GRADIENT;
        scan_ptr += 6;
      }
      else {
        type = ZN_PATH_GRADIENT;
        scan_ptr += 4;
      }
      num_coords = ParseRealList(scan_ptr, next_ptr, coords, 4);
      if ((num_coords != 2) && (num_coords != 4)) {
        goto grad_err3;
      }
    }
    else {
      Tcl_AppendResult(interp, "invalid gradient type \"",
                       desc, "\"", NULL);
      goto grad_err1;
    }
    scan_ptr = next_ptr + 1;
    next_ptr = strchr(scan_ptr, '|');
  }
  
  /*
   * Create the gradient structure.
   */
  grad = (ZnGradient *) ZnMalloc(sizeof(ZnGradient) +
                                 sizeof(ZnGradientColor)*(num_colors-1));
  grad->ref_count = 1;
  simple = True;
  grad->num_colors_in = num_colors;
  grad->type = type;
  grad->p.x = grad->p.y = grad->e.x = grad->e.y = 0.0;
  grad->angle = 0;

  switch (type) {
  case ZN_AXIAL_GRADIENT:
    if ((num_coords == 4) &&
        ((coords[0] != coords[2]) || (coords[1] != coords[3]))) {
      grad->p.x = coords[0];
      grad->p.y = coords[1];
      simple = False;
      grad->e.x = coords[2];
      grad->e.y = coords[3];
    }
    else {
      grad->angle = (int) angle;
    }
    break;
  case ZN_CONICAL_GRADIENT:
    if ((num_coords == 4) &&
        ((coords[0] != coords[2]) || (coords[1] != coords[3]))) {
      grad->p.x = coords[0];
      grad->p.y = coords[1];
      simple = False;
      grad->e.x = coords[2];
      grad->e.y = coords[3];
    }
    else if (num_coords == 2) {
      grad->p.x = coords[0];
      grad->p.y = coords[1];
    }
    else if (num_coords == 3) {
      grad->p.x = coords[0];
      grad->p.y = coords[1];
      grad->angle = (int) coords[2];
    }
    else {
      grad->angle = (int) angle;
    }
    break;
  case ZN_RADIAL_GRADIENT:
    grad->p.x = coords[0];
    grad->p.y = coords[1];
    if ((num_coords == 4) &&
        ((coords[0] != coords[2]) || (coords[1] != coords[3])))  {
      simple = False;
      grad->e.x = coords[2];
      grad->e.y = coords[3];
    }
    break;
  case ZN_PATH_GRADIENT:
    grad->p.x = coords[0];
    grad->p.y = coords[1];
    break;
  }
  grad->hash = hash;
  Tcl_SetHashValue(hash, grad);
  
  for (i = 0; i < num_colors; i++) {
    grad->colors_in[i].alpha = 100;
    /*
     * Try to parse the color name.
     */
    nspace = strspn(scan_ptr, " \t");   
    scan_ptr += nspace;
    str_ptr = strpbrk(scan_ptr, " \t|");
    if (str_ptr) {
      size = str_ptr - scan_ptr;
    }
    else {
      size = strlen(scan_ptr);
    }
    if (size > (SEGMENT_SIZE-1)) {
      Tcl_AppendResult(interp, "color name too long in gradient \"",
                       desc, "\",", NULL);
    grad_err2:
      for (j = 0; j < i; j++) {
        Tk_FreeColor(grad->colors_in[j].rgb);
      }
      ZnFree(grad);
      goto grad_err1;
    }
    strncpy(segment, scan_ptr, size);
    segment[size] = 0;
    scan_ptr += size;
    /*
     * Try to parse the color position.
     */
    grad->colors_in[i].position = 0;
    grad->colors_in[i].control = 50;
    position = strtod(scan_ptr, &end);
    if (end != scan_ptr) {
      grad->colors_in[i].position = (int) position;
      scan_ptr = end;
      /*
       * Try to parse the control point
       */
      control = strtod(scan_ptr, &end);
      if (end != scan_ptr) {
        grad->colors_in[i].control = (int) control;
        scan_ptr = end;
      }
    }
    nspace = strspn(scan_ptr, " \t");
    if ((scan_ptr[nspace] != 0) && (scan_ptr+nspace != next_ptr)) {
      Tcl_AppendResult(interp, "incorrect color description in gradient \"",
                       desc, "\",", NULL);
      goto grad_err2;
    }
    
    color_ptr = strchr(segment, ';');
    if (color_ptr) {
      *color_ptr = 0;
    }
    grad->colors_in[i].rgb = Tk_GetColor(interp, tkwin, Tk_GetUid(segment));
    if (grad->colors_in[i].rgb == NULL) {
      Tcl_AppendResult(interp, "incorrect color value in gradient \"",
                       desc, "\",", NULL);
      goto grad_err2;
    }
    if (color_ptr) {
      color_ptr++;
      grad->colors_in[i].alpha = atoi(color_ptr);
    }
    if (i == 0) {
      grad->colors_in[i].position = 0;
    }
    else if (i == num_colors - 1) {
      grad->colors_in[i].position = 100;
    }
    if ((i > 0) &&
        ((grad->colors_in[i].position > 100) ||
         (grad->colors_in[i].position < grad->colors_in[i-1].position))) {
      Tcl_AppendResult(interp, "incorrect color position in gradient \"",
                       desc, "\",", NULL);
      goto grad_err2;
    }
    if (grad->colors_in[i].control > 100) {
      grad->colors_in[i].control = 100;
    }
    if (grad->colors_in[i].alpha > 100) {
      grad->colors_in[i].alpha = 100;
    }
    if (next_ptr) {
      scan_ptr = next_ptr + 1;
      next_ptr = strchr(scan_ptr, '|');
    }
  }

  /*
   * Compute the mid alpha and mid color values. These will be
   * used by the gradient rendering primitives when a control
   * is not at mid range. The last color has no mid_* values.
   */
  for (i = 0; i < grad->num_colors_in-1; i++) {
    first = &grad->colors_in[i];
    last = &grad->colors_in[i+1];
    red_range = (int) last->rgb->red - (int) first->rgb->red;
    green_range = (int) last->rgb->green - (int) first->rgb->green;
    blue_range = (int) last->rgb->blue - (int) first->rgb->blue;
    color.red =(int) first->rgb->red +  red_range/2;
    color.green = (int) first->rgb->green + green_range/2;
    color.blue = (int) first->rgb->blue + blue_range/2;
    first->mid_rgb = Tk_GetColorByValue(tkwin, &color);
    first->mid_alpha = first->alpha + (last->alpha-first->alpha)/2;
  }
  grad->colors_in[grad->num_colors_in-1].mid_rgb = NULL;

  /*
   * If the gradient is 'simple' ie. described by a single point
   * or an angle for axial gradients, the processing is finished.
   * If not, we have to reduce the gradient to a simple one by adding
   * or suppressing colors and adjusting the relative position of
   * each remaining color.
   */
  if (simple) {
    grad->num_actual_colors = grad->num_colors_in;
    grad->actual_colors = grad->colors_in;
  }
  else if (type != ZN_PATH_GRADIENT) {
    ReduceGradient(tkwin, grad);
  }

  //printf("num in: %d, num actual: %d\n", grad->num_colors_in,grad->num_actual_colors);
  //printf("ZnGetGradient end : %s\n", desc);
  return grad;
}


/*
 *--------------------------------------------------------------
 *
 * ZnNameOfGradient --
 *
 *      Given a gradient, return a textual string identifying
 *      the gradient.
 *
 * Results:
 *      The return value is the string that was used to create
 *      the gradient.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
char *
ZnNameOfGradient(ZnGradient     *grad)
{
  return (char *) grad->hash->key.words;
}


/*
 *--------------------------------------------------------------
 *
 * ZnFreeGradient --
 *
 *      This procedure is called when a gradient is no longer
 *      needed.  It frees the resources associated with the
 *      gradient.  After this call, the caller should never
 *      again use the gradient.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Resources are freed.
 *
 *--------------------------------------------------------------
 */
void
ZnFreeGradient(ZnGradient       *grad)
{
  unsigned int  i;
  
  grad->ref_count--;
  if (grad->ref_count == 0) {
    Tcl_DeleteHashEntry(grad->hash);
    for (i = 0; i < grad->num_colors_in; i++) {
      Tk_FreeColor(grad->colors_in[i].rgb);
      if (grad->colors_in[i].mid_rgb) {
        Tk_FreeColor(grad->colors_in[i].mid_rgb);
      }
    }
    if (grad->actual_colors != grad->colors_in) {
      for (i = 0; i < grad->num_actual_colors; i++) {
        Tk_FreeColor(grad->actual_colors[i].rgb);
        if (grad->actual_colors[i].mid_rgb) {
          Tk_FreeColor(grad->actual_colors[i].mid_rgb);
        }
      }
      ZnFree(grad->actual_colors);
    }
    ZnFree(grad);
  }
}


/*
 *--------------------------------------------------------------
 *
 * ZnComposeAlpha --
 *
 *      This procedure takes two alpha values in percent and
 *      returns the composite value between 0 and 65535.
 *
 *--------------------------------------------------------------
 */
int
ZnComposeAlpha(unsigned short   alpha1,
               unsigned short   alpha2)
{
  return (alpha1*alpha2/100)*65535/100;
}

Added jni/tkzinc/generic/Color.h.











































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
 * Color.h -- Header for color routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Thu Dec 16 15:41:04 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Color_h
#define _Color_h


#include "Types.h"
#include "Geo.h"


/*
 * Types of gradients.
 */
#define ZN_AXIAL_GRADIENT       0
#define ZN_RADIAL_GRADIENT      1
#define ZN_PATH_GRADIENT        2
#define ZN_CONICAL_GRADIENT     3

typedef struct _ZnGradientColor {
  unsigned char position;       /* Color starting position along the gradient axis.
                                 * This is in percent of the gradient total size. */
  unsigned char control;        /* Middle-shade position in percent of this color
                                 * size along the gradient axis. */
  unsigned char alpha;          /* The color alpha channel in percent */
  unsigned char mid_alpha;
  XColor        *rgb;           /* The actual color description */
  XColor        *mid_rgb;
} ZnGradientColor;

typedef struct _ZnGradient {
  int           ref_count;
  Tcl_HashEntry *hash;
  char          type;           /* Either ZN_AXIAL_GRADIENT, ZN_RADIAL_GRADIENT or
                                 * ZN_PATH_GRADIENT. */
  int           angle;          /* Angle for an axial gradient (Degrees). */
  ZnPoint       p;              /* Start for an axial/radial/path gradiant. In
                                 * percent of the bbox. */
  ZnPoint       e;              /* End of the axial/radial gradiant in percent
                                 * of bbox. */
  unsigned int  num_actual_colors;/* Number of adjusted colors */
  ZnGradientColor *actual_colors;/* Actual adjusted gradient color spec. May
                                  * be the same array as color_spec. */
  unsigned int  num_colors_in;  /* Number of colors in gradient spec. */
  ZnGradientColor colors_in[1]; /* Gradient color spec */
} ZnGradient;


#define ZnGetGradientPixel(gradient, position) \
  ZnPixel(ZnGetGradientColor(gradient, position, NULL))

ZnGradient *ZnGetGradient(Tcl_Interp *interp, Tk_Window tkwin,
                          Tk_Uid name);
ZnGradient *ZnGetGradientByValue(ZnGradient *gradient);
ZnGradient *ZnGetReliefGradient(Tcl_Interp *interp, Tk_Window tkwin,
                                Tk_Uid name, unsigned short alpha);
ZnBool ZnGradientFlat(ZnGradient *grad);
XColor *ZnGetGradientColor(ZnGradient *gradient, ZnReal position,
                           unsigned short *alpha);
void ZnInterpGradientColor(ZnGradient *gradient, ZnReal position,
                           XColor *color, unsigned short *alpha);
char *ZnNameOfGradient(ZnGradient *gradient);
void ZnFreeGradient(ZnGradient *gradient);
void ZnDeleteGradientName(char *name);
ZnBool ZnGradientNameExists(char *name);
ZnBool ZnNameGradient(Tcl_Interp *interp, Tk_Window tkwin,
                      char *grad_descr, char *name);
int ZnComposeAlpha(unsigned short alpha1, unsigned short alpha2);

#endif /* _Color_h */

Added jni/tkzinc/generic/Curve.c.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
/*
 * Curve.c -- Implementation of curve item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Fri Mar 25 15:32:17 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

#include "Draw.h"
#include "Item.h"
#include "Geo.h"
#include "Types.h"
#include "WidgetInfo.h"
#include "Image.h"
#include "Color.h"
#include "tkZinc.h"

#if defined(MAC_OSX_TK)
  #include <AGL/glu.h>
#elif defined(__APPLE__)
  #include <OpenGL/glu.h>
#else
  #include <GL/glu.h>
#endif
#include <ctype.h>

static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 * Bit offset of flags.
 */
#define FILLED_BIT      1<<0    /* If the item is filled with color/pattern */
#define MARKED_BIT      1<<1    /* If the vertices are marked by a symbol */
#define CLOSED_BIT      1<<2    /* If the outline should be closed automatically */
#define SMOOTH_RELIEF_BIT 1<<3  /* If the relief should be continuous (arc) or discrete (angle) */

#define FIRST_END_OK    1<<6
#define LAST_END_OK     1<<7
#define FILLED_OK       1<<8
#define RELIEF_OK       1<<10
#define MARKER_OK       1<<12


/*
 **********************************************************************************
 *
 * Specific Curve item record
 *
 **********************************************************************************
 */
typedef struct _CurveItemStruct {
  ZnItemStruct  header;

  /* Public data */
  ZnPoly        shape;
  unsigned short flags;
  ZnImage       marker;
  ZnLineEnd     first_end;      /* These two are considered only if relief is flat */
  ZnLineEnd     last_end;
  ZnLineStyle   line_style;     /* This is considered only if relief is flat */
  int           cap_style;
  int           join_style;
  ZnReliefStyle relief;
  ZnDim         line_width;     /* If 0 the path is not drawn, if <2 relief is flat */
  ZnGradient    *fill_color;
  ZnImage       line_pattern;
  ZnGradient    *line_color;
  ZnGradient    *marker_color;
  int           fill_rule;
  ZnImage       tile;
  
  /* Private data */
  ZnPoly        outlines;
  ZnGradient    *gradient;
  ZnTriStrip    tristrip;
  ZnPoint       *grad_geo;  
} CurveItemStruct, *CurveItem;

static ZnAttrConfig     cv_attrs[] = {
  { ZN_CONFIG_CAP_STYLE, "-capstyle", NULL,
    Tk_Offset(CurveItemStruct, cap_style), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(CurveItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-closed", NULL,
    Tk_Offset(CurveItemStruct, flags), CLOSED_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(CurveItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(CurveItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(CurveItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
    Tk_Offset(CurveItemStruct, fill_color), 0,
    ZN_COORDS_FLAG|ZN_BORDER_FLAG, False },
  { ZN_CONFIG_BOOL, "-filled", NULL,
    Tk_Offset(CurveItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
    Tk_Offset(CurveItemStruct, tile), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_FILL_RULE, "-fillrule", NULL,
    Tk_Offset(CurveItemStruct, fill_rule), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_END, "-firstend", NULL,
    Tk_Offset(CurveItemStruct, first_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_JOIN_STYLE, "-joinstyle", NULL,
    Tk_Offset(CurveItemStruct, join_style), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_END, "-lastend", NULL,
    Tk_Offset(CurveItemStruct, last_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
    Tk_Offset(CurveItemStruct, line_color), 0,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BITMAP, "-linepattern", NULL,
    Tk_Offset(CurveItemStruct, line_pattern), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
    Tk_Offset(CurveItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-linewidth", NULL,
    Tk_Offset(CurveItemStruct, line_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(CurveItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BITMAP, "-marker", NULL,
    Tk_Offset(CurveItemStruct, marker), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-markercolor", NULL,
    Tk_Offset(CurveItemStruct, marker_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_RELIEF, "-relief", NULL, Tk_Offset(CurveItemStruct, relief), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(CurveItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-smoothrelief", NULL,
    Tk_Offset(CurveItemStruct, flags), SMOOTH_RELIEF_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(CurveItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_IMAGE, "-tile", NULL,
    Tk_Offset(CurveItemStruct, tile), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(CurveItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  ZnWInfo       *wi = item->wi;
  CurveItem     cv = (CurveItem) item;
  unsigned int  i, num_points, count;
  ZnPoint       *p, *points;
  char          *controls;

  cv->outlines.num_contours = 0;
  cv->outlines.contours = NULL;
  cv->tristrip.num_strips = 0;
  cv->tristrip.strips = NULL;
  cv->gradient = NULL;
  cv->grad_geo = NULL;
  
  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  CLEAR(cv->flags, CLOSED_BIT);
  CLEAR(cv->flags, SMOOTH_RELIEF_BIT);
  cv->fill_rule = GLU_TESS_WINDING_ODD;
  item->priority = 1;

  if (*argc < 1) {
    Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
    return TCL_ERROR;
  }
  if (ZnParseCoordList(wi, (*args)[0], &points,
                       &controls, &num_points, NULL) == TCL_ERROR) {
    return TCL_ERROR;
  }

  if (num_points == 0) {
    ZnPolyInit(&cv->shape);
  }
  else {
    /*
     * Scan the control array (if any) to detect malformed
     * curves (more than 2 consecutive control points).
     */
    if (controls) {
      count = 0;
      if ((controls[0]) || (controls[num_points-1])) {
        goto contr_err;
      }
      for (i = 1; i < num_points-1; i++) {
        switch (controls[i]) {
        case 'c':
          count++;
          if (count > 2) {
            goto contr_err;
          }
          break;
        case 0:
          count = 0;
          break;
        default:
        contr_err:
          ZnFree(controls);
          Tcl_AppendResult(wi->interp, " curve coords expected", NULL);
          return TCL_ERROR;
        }
      }
    }
    /*
     * Make a local copy of the points. This is not necessary
     * for the optional control list.
     */
    p = ZnMalloc(num_points * sizeof(ZnPoint));
    /*printf("plain contour, numpoints: %d %g@%g\n",
      num_points, points[0].x, points[0].y);*/
    memcpy(p, points, num_points * sizeof(ZnPoint));
    ZnPolyContour1(&cv->shape, p, num_points, !ZnTestCCW(p, num_points));
    cv->shape.contours[0].controls = controls;
  }
  (*args)++;
  (*argc)--;
 
  CLEAR(cv->flags, FILLED_BIT);
  cv->first_end = NULL;
  cv->last_end = NULL;
  cv->line_style = ZN_LINE_SIMPLE;
  cv->relief = ZN_RELIEF_FLAT;
  cv->line_width = 1;
  cv->tile = ZnUnspecifiedImage;
  cv->line_pattern = ZnUnspecifiedImage;
  cv->cap_style = CapRound;
  cv->join_style = JoinRound;
  
  /*
   * In Tk marker visibility is controlled by the bitmap
   * being unspecified.
   */
  SET(cv->flags, MARKED_BIT);
  cv->marker = ZnUnspecifiedImage;
  cv->fill_color = ZnGetGradientByValue(wi->fore_color);
  cv->line_color = ZnGetGradientByValue(wi->fore_color);
  cv->marker_color = ZnGetGradientByValue(wi->fore_color);

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  CurveItem     cv = (CurveItem) item;
  unsigned int  i;
  ZnContour     *conts;

  
  if (cv->shape.num_contours) {
    conts = cv->shape.contours;
    if (cv->shape.contours != &cv->shape.contour1) {
      cv->shape.contours = (ZnContour *) ZnMalloc(cv->shape.num_contours*sizeof(ZnContour));
    }
    for (i = 0; i < cv->shape.num_contours; i++) {
      cv->shape.contours[i].num_points = conts[i].num_points;
      cv->shape.contours[i].cw = conts[i].cw;
      cv->shape.contours[i].points = ZnMalloc(conts[i].num_points*sizeof(ZnPoint));
      memcpy(cv->shape.contours[i].points, conts[i].points,
             conts[i].num_points*sizeof(ZnPoint));
      cv->shape.contours[i].controls = NULL;
      if (conts[i].controls) {
         cv->shape.contours[i].controls = ZnMalloc(conts[i].num_points*sizeof(char));
         memcpy(cv->shape.contours[i].controls, conts[i].controls,
                conts[i].num_points*sizeof(char));
      }
    }
  }
  
  if (cv->gradient) {
    cv->gradient = ZnGetGradientByValue(cv->gradient);
  }
  if (cv->first_end) {
    ZnLineEndDuplicate(cv->first_end);
  }
  if (cv->last_end) {
    ZnLineEndDuplicate(cv->last_end);
  }
  if (cv->tile != ZnUnspecifiedImage) {
    cv->tile = ZnGetImageByValue(cv->tile, ZnUpdateItemImage, item);
  }
  if (cv->line_pattern != ZnUnspecifiedImage) {
    cv->line_pattern = ZnGetImageByValue(cv->line_pattern, NULL, NULL);
  }
  if (cv->marker != ZnUnspecifiedImage) {
    cv->marker = ZnGetImageByValue(cv->marker, NULL, NULL);
  }
  cv->line_color = ZnGetGradientByValue(cv->line_color);
  cv->fill_color = ZnGetGradientByValue(cv->fill_color);
  cv->grad_geo = NULL;
  cv->marker_color = ZnGetGradientByValue(cv->marker_color);
  cv->tristrip.num_strips = 0;
  cv->tristrip.strips = NULL;
  cv->outlines.num_contours = 0;
  cv->outlines.contours = NULL;
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  CurveItem     cv = (CurveItem) item;
  unsigned int  i;

  /*
   * Need to free the control array here, it is only known
   * by the Curve code.
   */
  for (i = 0; i < cv->shape.num_contours; i++) {
    if (cv->shape.contours[i].controls) {
      ZnFree(cv->shape.contours[i].controls);
    }
  }
  ZnPolyFree(&cv->shape);

  if (cv->grad_geo) {
    ZnFree(cv->grad_geo);
  }
  if (cv->first_end) {
    ZnLineEndDelete(cv->first_end);
  }
  if (cv->last_end) {
    ZnLineEndDelete(cv->last_end);
  }
  if (cv->gradient) {
    ZnFreeGradient(cv->gradient);
  }
  if (cv->tile != ZnUnspecifiedImage) {
    ZnFreeImage(cv->tile, ZnUpdateItemImage, item);
    cv->tile = ZnUnspecifiedImage;
  }
  if (cv->line_pattern != ZnUnspecifiedImage) {
    ZnFreeImage(cv->line_pattern, NULL, NULL);
    cv->line_pattern = ZnUnspecifiedImage;
  }
  if (cv->marker != ZnUnspecifiedImage) {
    ZnFreeImage(cv->marker, NULL, NULL);
    cv->marker = ZnUnspecifiedImage;
  }
  ZnFreeGradient(cv->fill_color);
  ZnFreeGradient(cv->line_color);
  ZnFreeGradient(cv->marker_color);

  if (cv->tristrip.num_strips) {
    ZnTriFree(&cv->tristrip);
  }  
  if (cv->outlines.num_contours) {
    ZnPolyFree(&cv->outlines);
  }
}


/*
 **********************************************************************************
 *
 * Setup flags to control the precedence between the
 * graphical attributes.
 *
 **********************************************************************************
 */
static void
SetRenderFlags(CurveItem        cv)
{
  ASSIGN(cv->flags, FILLED_OK,
         ISSET(cv->flags, FILLED_BIT) && (cv->shape.num_contours >= 1));

  ASSIGN(cv->flags, RELIEF_OK,
         (cv->relief != ZN_RELIEF_FLAT) &&
         (cv->shape.num_contours >= 1) &&
         (cv->line_width > 1));

  ASSIGN(cv->flags, MARKER_OK,
         (cv->marker != ZnUnspecifiedImage) &&
         ISCLEAR(cv->flags, RELIEF_OK));
  
  ASSIGN(cv->flags, FIRST_END_OK,
         (cv->first_end != NULL) &&
         (cv->shape.num_contours == 1) && (cv->shape.contours[0].num_points > 1) &&
         ISCLEAR(cv->flags, FILLED_BIT) && cv->line_width &&
         ISCLEAR(cv->flags, RELIEF_OK) &&
         ISCLEAR(cv->flags, CLOSED_BIT));
  ASSIGN(cv->flags, LAST_END_OK,
         (cv->last_end != NULL) &&
         (cv->shape.num_contours == 1) && (cv->shape.contours[0].num_points > 1) &&
         ISCLEAR(cv->flags, FILLED_BIT) && cv->line_width &&
         ISCLEAR(cv->flags, RELIEF_OK) &&
         ISCLEAR(cv->flags, CLOSED_BIT));
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  ZnWInfo       *wi = item->wi;
  CurveItem     cv = (CurveItem) item;
  int           status = TCL_OK;
  XColor        *color;
  unsigned short alpha;
  
  status = ZnConfigureAttributes(wi, item, item, cv_attrs, argc, argv, flags);

  if (cv->gradient &&
      (ISSET(*flags, ZN_BORDER_FLAG) || (cv->relief == ZN_RELIEF_FLAT))) {
    ZnFreeGradient(cv->gradient);
    cv->gradient = NULL;
  }
  if ((cv->relief != ZN_RELIEF_FLAT) && !cv->gradient) {
    color = ZnGetGradientColor(cv->line_color, 51.0, &alpha);
    cv->gradient = ZnGetReliefGradient(wi->interp, wi->win,
                                       Tk_NameOfColor(color), alpha);
    if (cv->gradient == NULL) {
      status = TCL_ERROR;
    }
  }

  return status;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, cv_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}

static void
UpdateTristrip(CurveItem        cv,
               ZnPoly           *poly,
               ZnBool           revert)
{
  ZnCombineData *cdata, *cnext;
  GLdouble      v[3];
  unsigned int  j, k;
  int           i;

  //printf("UpdateTristrips sur %d\n", ((ZnItem) cv)->id);
  gluTessProperty(ZnTesselator.tess, GLU_TESS_WINDING_RULE, (GLdouble) cv->fill_rule);

  if (cv->tristrip.num_strips == 0) {
    gluTessProperty(ZnTesselator.tess, GLU_TESS_BOUNDARY_ONLY, (GLdouble) GL_FALSE);
    gluTessBeginPolygon(ZnTesselator.tess, &cv->tristrip);
    /*
     * We need to take care of the final (after transformation) winding
     * direction of the polygon in order to have the right tesselation
     * taking place.
     */
    if (!revert) {
      for (j = 0; j < poly->num_contours; j++){
        gluTessBeginContour(ZnTesselator.tess);
        //printf("D�ut contour %d num_points %d\n", j, poly->contours[j].num_points);
        for (k = 0; k < poly->contours[j].num_points; k++) {
          /*printf("%g@%g ", poly->contours[j].points[k].x, poly->contours[j].points[k].y);*/
          v[0] = poly->contours[j].points[k].x;
          v[1] = poly->contours[j].points[k].y;
          v[2] = 0;
          gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[k]);
        }
        //printf("\n");
        gluTessEndContour(ZnTesselator.tess);
      }
    }
    else {
      for (j = 0; j < poly->num_contours; j++){
        gluTessBeginContour(ZnTesselator.tess);
        //printf("revert D�ut contour %d num_points %d\n", j, poly->contours[j].num_points);
        for (i = (int) (poly->contours[j].num_points-1); i >= 0; i--) {
          /*printf("%g@%g ", poly->contours[j].points[i].x, poly->contours[j].points[i].y);*/
          v[0] = poly->contours[j].points[i].x;
          v[1] = poly->contours[j].points[i].y;
          v[2] = 0;
          gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[i]);
        }
        //printf("\n");
        gluTessEndContour(ZnTesselator.tess);
      }
    }
    gluTessEndPolygon(ZnTesselator.tess);
    cdata = ZnTesselator.combine_list;
                //printf("Combine length: %d\n", ZnTesselator.combine_length);
    while (cdata) {
                        ZnTesselator.combine_length--;
      cnext = cdata->next;
      ZnFree(cdata);
      cdata = cnext;
    }
    ZnTesselator.combine_list = NULL;
  }
  //printf("Fin UpdateTristrips sur %d\n", ((ZnItem) cv)->id);
}

static void
UpdateOutlines(CurveItem        cv,
               ZnPoly           *poly,
               ZnBool           revert)
{
  ZnCombineData *cdata, *cnext;
  GLdouble      v[3];
  unsigned int  j, k;
  int           i;

  //printf("UpdateOutlines sur %d\n", ((ZnItem) cv)->id);
  gluTessProperty(ZnTesselator.tess, GLU_TESS_WINDING_RULE, (GLdouble) cv->fill_rule);

  if (cv->outlines.num_contours == 0) {
    gluTessProperty(ZnTesselator.tess, GLU_TESS_BOUNDARY_ONLY, (GLdouble) GL_TRUE);
    gluTessBeginPolygon(ZnTesselator.tess, &cv->outlines);

    /*
     * We need to take care of the final (after transformation) winding
     * direction of the polygon in order to have the right tesselation
     * taking place.
     */
    if (!revert) {
      for (j = 0; j < poly->num_contours; j++){
        gluTessBeginContour(ZnTesselator.tess);
        for (k = 0; k < poly->contours[j].num_points; k++) {
          v[0] = poly->contours[j].points[k].x;
          v[1] = poly->contours[j].points[k].y;
          v[2] = 0;
          gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[k]);
        }
        gluTessEndContour(ZnTesselator.tess);
      }
    }
    else {
      for (j = 0; j < poly->num_contours; j++){
        gluTessBeginContour(ZnTesselator.tess);
        for (i = (int) (poly->contours[j].num_points-1); i >= 0; i--) {
          v[0] = poly->contours[j].points[i].x;
          v[1] = poly->contours[j].points[i].y;
          v[2] = 0;
          gluTessVertex(ZnTesselator.tess, v, &poly->contours[j].points[i]);
        }
        gluTessEndContour(ZnTesselator.tess);
      }
    }
    gluTessEndPolygon(ZnTesselator.tess);
    cdata = ZnTesselator.combine_list;
    while (cdata) {
                        ZnTesselator.combine_length--;
      cnext = cdata->next;
      ZnFree(cdata);
      cdata = cnext;
    }
    ZnTesselator.combine_list = NULL;
  }
  //printf("Fin UpdateOutlines sur %d\n", ((ZnItem) cv)->id);
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  CurveItem     cv = (CurveItem) item;
  unsigned int  i, j;
  ZnPoint       end_points[ZN_LINE_END_POINTS];
  ZnPoint       *points;
  unsigned int  num_points, num_contours, segment_start;
  ZnBBox        bbox;
  ZnDim         lw;
  ZnContour     *c1, *c2;
  ZnPoly        dev;
  ZnBool        revert;

  ZnResetBBox(&item->item_bounding_box);

  /*printf("Curve CC: flags %x\n", cv->flags);*/
  SetRenderFlags(cv);

  num_contours = cv->shape.num_contours;
  if (num_contours == 0) {
    return;
  }

  if (cv->tristrip.num_strips) {
    ZnTriFree(&cv->tristrip);
  }
  if (cv->outlines.num_contours) {
    ZnPolyFree(&cv->outlines);
  };

  ZnPolyInit(&dev);
  if (num_contours != 1) {
    dev.contours = ZnMalloc(num_contours * sizeof(ZnContour));
    dev.num_contours = num_contours;
  }
  else {
    dev.contours = &dev.contour1;
    dev.num_contours = 1;
  }

  for (c1 = cv->shape.contours, c2 = dev.contours, i = 0;
       i < cv->shape.num_contours; i++, c1++, c2++) {
    c2->num_points = c1->num_points;
    /*
     * Add a point at the end of the contour to close it
     * if needed. Works only if a single contour is given, in
     * this case it can be used as a path. In the case of
     * multiple contours, the outline is automatically
     * closed by the tesselator.
     */
    if ((num_contours == 1) &&
        (c1->num_points > 2) &&
        ISSET(cv->flags, CLOSED_BIT) &&
        ((c1->points[0].x != c1->points[c1->num_points-1].x) ||
         (c1->points[0].y != c1->points[c1->num_points-1].y)) &&
        (c1->num_points > 2)) {
      c2->num_points++;
    }
    c2->points = ZnMalloc((c2->num_points)*sizeof(ZnPoint));
    /*printf("CC: \"%d\" num_points %d\n", item->id, c1->num_points);*/
    ZnTransformPoints(wi->current_transfo, c1->points, c2->points, c1->num_points); 
    if (c1->num_points != c2->num_points) {
      c2->points[c2->num_points-1] = c2->points[0];
    }
    /*
     * Now expand the bezier segments into polylines.
     */
    if (c1->controls) {
      segment_start = 0;
      ZnListEmpty(ZnWorkPoints);
      ZnListAdd(ZnWorkPoints, &c2->points[0], ZnListTail);
      /*printf("moveto %g@%g\n", c2->points[0].x, c2->points[0].y);*/
      for (j = 1; j < c1->num_points; j++) {
        if (!c1->controls[j]) {
          if (segment_start != j-1) {
            /* traitement bezier */
            /*printf("arcto  %g@%g %g@%g %g@%g\n",
                   c2->points[segment_start+1].x, c2->points[segment_start+1].y,
                   c2->points[j-1].x, c2->points[j-1].y,
                   c2->points[j].x, c2->points[j].y);*/
            ZnGetBezierPoints(&c2->points[segment_start],
                              &c2->points[segment_start+1], &c2->points[j-1],
                              &c2->points[j], ZnWorkPoints, 0.5);
          }
          else {
            /*printf("lineto %g@%g\n", c2->points[j].x, c2->points[j].y);*/
            ZnListAdd(ZnWorkPoints, &c2->points[j], ZnListTail);
          }
          segment_start = j;
        }
      }
      /*
       * Must test if the last point is a control and the contour
       * is closed (either a mono contour with -closed or 
       * multiple contours).
       */
      if (c1->controls[c1->num_points-1]) {
        ZnGetBezierPoints(&c2->points[segment_start],
                          &c2->points[segment_start+1], &c2->points[c1->num_points-1],
                          &c2->points[0], ZnWorkPoints, 0.5);
      }

      /*
       * Replace the original path by the expanded, closing it as
       * needed (one open contour).
       */
      num_points =ZnListSize(ZnWorkPoints);
      if (c2->num_points != c1->num_points) {
        num_points++;
      }
      c2->points = ZnRealloc(c2->points, num_points*sizeof(ZnPoint));
      memcpy(c2->points, ZnListArray(ZnWorkPoints), num_points*sizeof(ZnPoint));
      if (c2->num_points != c1->num_points) {
        c2->points[num_points-1] = c2->points[0];
      }
      c2->num_points = num_points;
    }
  }

  /*
   * Test the scale factors to see if we need to reverse the
   * polygons winding.
   */
  revert = (wi->current_transfo->_[0][0]*wi->current_transfo->_[1][1]) < 0;
  if (num_contours == 1) {
    if (cv->shape.contours[0].num_points > 2) {
      UpdateTristrip(cv, &dev, revert);
      /*if (!cv->tristrip.num_strips) {
        int kk;
        ZnPrintTransfo(wi->current_transfo);
          printf("id: %d, NumCont: %d, NumPoints: %d, Original: %d, Resultat: %d, NumTri: %d\n",
                 item->id, num_contours,cv->shape.contours[0].num_points,
                 cv->shape.contours[0].cw, cw_dev_contour1, cv->tristrip.num_strips);
          for (kk = 0; kk < cv->shape.contours[0].num_points; kk++) {
            printf("%g@%g ", cv->shape.contours[0].points[kk].x,
                   cv->shape.contours[0].points[kk].y);
          }
          printf("\n");
          }*/
    }
    ZnPolyContour1(&cv->outlines, dev.contours[0].points, dev.contours[0].num_points,
                   cv->shape.contours[0].cw);
  }
  else {
    UpdateTristrip(cv, &dev, revert);
    /*if (!cv->tristrip.num_strips) {
      ZnPrintTransfo(wi->current_transfo);
      printf("id: %d, NumCont: %d, NumPoints: %d, Original: %d, Resultat: %d, NumTri: %d\n",
             item->id, num_contours,cv->shape.contours[0].num_points,
             cv->shape.contours[0].cw, cw_dev_contour1, cv->tristrip.num_strips);
             }*/
    UpdateOutlines(cv, &dev, revert);
    ZnPolyFree(&dev);
  }

  lw = cv->line_width;
  num_contours = cv->outlines.num_contours;
  if (ISSET(cv->flags, RELIEF_OK)) {
    c2 = cv->outlines.contours;
    for (i = 0; i < num_contours; i++, c2++) {
      /*
       * Add to bounding box. 
       */
      ZnGetPolygonReliefBBox(c2->points, c2->num_points, lw, &bbox);
      ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
    }
  }
  else {
    c2 = cv->outlines.contours;
    for (i = 0; i < num_contours; i++, c2++) {
      ZnAddPointsToBBox(&item->item_bounding_box, c2->points, c2->num_points);
    }
    
    /*
     * Take care of miters, markers and arrows.
     */
    c2 = cv->outlines.contours;
    for (j = 0; j < num_contours; j++, c2++) {
      if (c2->cw) {
        continue;
      }
      if (cv->join_style == JoinMiter) {
        ZnPoint miter_i, miter_o;
        for (i = c2->num_points-1, points = c2->points; i >= 3; i--, points++) {
          ZnGetMiterPoints(points, points+1, points+2, lw, &miter_i, &miter_o);
          ZnAddPointToBBox(&item->item_bounding_box, miter_i.x, miter_i.y);
          ZnAddPointToBBox(&item->item_bounding_box, miter_o.x, miter_o.y);
        }
      }
      /*
       * Add the markers.
       */
      if (ISSET(cv->flags, MARKER_OK)) {
        int     w, h;
        ZnBBox  bbox;

        ZnSizeOfImage(cv->marker, &w, &h);
        w = w/2 + 2;
        h = h/2 + 2;
        num_points = c2->num_points;
        for (i = 0, points = c2->points; i < num_points; i++, points++) {
          bbox.orig.x = points->x - w;
          bbox.orig.y = points->y - h;
          bbox.corner.x = points->x + w;
          bbox.corner.y = points->y + h;
          ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
        }
      }
      /*
       * Process arrows.
       */
      num_points = c2->num_points;
      points = c2->points;
      if (ISSET(cv->flags, FIRST_END_OK)) {
        ZnGetLineEnd(&points[0], &points[1], lw, cv->cap_style,
                     cv->first_end, end_points);
        ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
      }
      if (ISSET(cv->flags, LAST_END_OK)) {
        ZnGetLineEnd(&points[num_points-1], &points[num_points-2],
                     lw, cv->cap_style, cv->last_end, end_points);
        ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
      }
    }
    
    /*
     * Add the line width in all directions.
     * This overestimates the space needed to draw the polyline
     * but is simple.
     */
    item->item_bounding_box.orig.x -= lw;
    item->item_bounding_box.orig.y -= lw;
    item->item_bounding_box.corner.x += lw;
    item->item_bounding_box.corner.y += lw;
  
    /*
     * Expand again the bounding box by one pixel in all
     * directions to take care of rounding errors.
     */
    item->item_bounding_box.orig.x -= 1;
    item->item_bounding_box.orig.y -= 1;
    item->item_bounding_box.corner.x += 1;
    item->item_bounding_box.corner.y += 1;
  }

#ifdef GL  
  if (!ZnGradientFlat(cv->fill_color)) {
    if (!cv->grad_geo) {
      cv->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
    }
    ZnComputeGradient(cv->fill_color, wi, &cv->shape, cv->grad_geo);
  }
  else {
    if (cv->grad_geo) {
      ZnFree(cv->grad_geo);
      cv->grad_geo = NULL;
    }
  }
#endif
}



/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  CurveItem     cv = (CurveItem) item;
  ZnBBox        bbox, *area = ta->area;
  ZnPoint       *points;
  ZnPoint       triangle[3];
  ZnPoint       end_points[ZN_LINE_END_POINTS];
  unsigned int  i, j, num_points, stop;
  int           width, height, result=-1, result2;
  ZnBool        first_done = False;

  if (cv->outlines.num_contours == 0) {
    return -1;
  }
  /*printf("============== poly %d ==============\n", item->id);*/

  if (ISSET(cv->flags, FILLED_OK)) {
    /*printf("testing surfaces\n");*/
    for (i = 0; i < cv->tristrip.num_strips; i++) {
      num_points = cv->tristrip.strips[i].num_points;
      points = cv->tristrip.strips[i].points;
      j = 0;
      stop = num_points-2;
      if (cv->tristrip.strips[i].fan) {
        triangle[0] = points[0];
        j++;
        points++;
        stop++;
      }
      for (; j < stop; j++, points++) {
        if (cv->tristrip.strips[i].fan) {
          triangle[1] = points[0];
          triangle[2] = points[1];
        }
        else {
          triangle[0] = points[0];
          triangle[1] = points[1];
          triangle[2] = points[2];
        }
        if (!first_done) {
          first_done = True;
          result = ZnPolygonInBBox(triangle, 3, area, NULL);
        }
        else {
          result2 = ZnPolygonInBBox(triangle, 3, area, NULL);
          if (result2 != result) {
            return 0;
          }
        }
      }
    }
  }

  if (cv->line_width > 0) {
    /*printf("testing lines\n");*/
    for (i = 0; i < cv->outlines.num_contours; i++) {
      num_points = cv->outlines.contours[i].num_points;
      points = cv->outlines.contours[i].points;
      if (!first_done) {
        first_done = True;
        if (ISCLEAR(cv->flags, RELIEF_OK)) {
          result = ZnPolylineInBBox(points, num_points,
                                    cv->line_width, cv->cap_style, cv->join_style, area);
        }
        else {
          result = ZnPolygonReliefInBBox(points, num_points, cv->line_width, area);
        }
        if (result == 0) {
          return 0;
        }
      }
      else {
        if (ISCLEAR(cv->flags, RELIEF_OK)) {
          result2 = ZnPolylineInBBox(points, num_points,
                                     cv->line_width, cv->cap_style, cv->join_style, area);
        }
        else {
          result2 = ZnPolygonReliefInBBox(points, num_points, cv->line_width, area);
        }
        if (result2 != result) {
          return 0;
        }
      }
    }
  
    /*
     * Check line ends (only on first contour).
     */
    points = cv->outlines.contours[0].points;
    num_points = cv->outlines.contours[0].num_points;
    if (ISSET(cv->flags, FIRST_END_OK)) {
      ZnGetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
                   cv->first_end, end_points);
      if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != result) {
        return 0;
      }
    }
    if (ISSET(cv->flags, LAST_END_OK)) {
      ZnGetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
                   cv->cap_style, cv->last_end, end_points);
      if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != result) {
        return 0;
      }
    }    
  }
  
  /*
   * Last, check markers
   */
  if (ISSET(cv->flags, MARKER_OK)) {
    for (i = 0; i < cv->outlines.num_contours; i++) {
      points = cv->outlines.contours[i].points;
      num_points = cv->outlines.contours[i].num_points;
      
      if (ISSET(cv->flags, FIRST_END_OK)) {
        num_points--;
        points++;
      }
      if (ISSET(cv->flags, LAST_END_OK)) {
        num_points--;
      }
      
      ZnSizeOfImage(cv->marker, &width, &height);
      for (; num_points > 0; num_points--, points++) {
        bbox.orig.x = points->x - (width+1)/2;
        bbox.orig.y = points->y - (height+1)/2;
        bbox.corner.x = bbox.orig.x + width;
        bbox.corner.y = bbox.orig.y + height;
        if (ZnBBoxInBBox(&bbox, area) != result) {
          return 0;
        }
      }
    }
  }
  
  return result;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  CurveItem     cv = (CurveItem) item;
  XGCValues     values;
  unsigned int  i, j, num_points=0;
  unsigned int  gc_mask;
  ZnPoint       *points=NULL;
  XPoint        *xpoints=NULL;
  
  if ((cv->outlines.num_contours == 0) ||
      (ISCLEAR(cv->flags, FILLED_OK) &&
       !cv->line_width &&
       ISCLEAR(cv->flags, MARKER_OK))) {
    return;
  }

  /*
   * Fill if requested.
   */
  if (ISSET(cv->flags, FILLED_OK)) {
    values.foreground = ZnGetGradientPixel(cv->fill_color, 0.0);
    gc_mask = GCFillStyle;
    if (cv->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(cv->tile)) { /* Fill tiled */
        values.fill_style = FillTiled;
        values.tile = ZnImagePixmap(cv->tile, wi->win);
        values.ts_x_origin = ZnNearestInt(item->item_bounding_box.orig.x);
        values.ts_y_origin = ZnNearestInt(item->item_bounding_box.orig.y);
        gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCTile;
      }
      else { /* Fill stippled */
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(cv->tile, wi->win);
        values.ts_x_origin = ZnNearestInt(item->item_bounding_box.orig.x);
        values.ts_y_origin = ZnNearestInt(item->item_bounding_box.orig.y);
        gc_mask |= GCTileStipXOrigin|GCTileStipYOrigin|GCStipple|GCForeground;
      }
    }
    else { /* Fill solid */
      values.fill_style = FillSolid;
      gc_mask |= GCForeground;
    }
    XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
    

    for (i = 0; i < cv->tristrip.num_strips; i++) {
      num_points = cv->tristrip.strips[i].num_points;
      points = cv->tristrip.strips[i].points;
      if (cv->tristrip.strips[i].fan) {
        XPoint  xpoints[3];
        xpoints[0].x = ZnNearestInt(points[0].x);
        xpoints[0].y = ZnNearestInt(points[0].y);
        xpoints[1].x = ZnNearestInt(points[1].x);
        xpoints[1].y = ZnNearestInt(points[1].y);
        for (j = 2; j < num_points; j++) {
          xpoints[2].x = ZnNearestInt(points[j].x);
          xpoints[2].y = ZnNearestInt(points[j].y);
          XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, 3,
#ifdef ConvexNoAA
                       ConvexNoAA,
#else
                       Convex,
#endif
                       CoordModeOrigin);
          xpoints[1] = xpoints[2];
        }
      }
      else {
        ZnListAssertSize(ZnWorkXPoints, num_points);
        xpoints = ZnListArray(ZnWorkXPoints);
        for (j = 0; j < num_points; j++) {
          xpoints[j].x = ZnNearestInt(points[j].x);
          xpoints[j].y = ZnNearestInt(points[j].y);
        }
        for (j = 0; j < num_points-2; j++) {
          XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, &xpoints[j], 3,
#ifdef ConvexNoAA
                       ConvexNoAA,
#else
                       Convex,
#endif
                       CoordModeOrigin);
        }
      }
    }
  }

  /*
   * Draw the lines between points
   */
  if (cv->line_width) {
    ZnPoint     end_points[ZN_LINE_END_POINTS];
    XPoint      xp[ZN_LINE_END_POINTS];

    /*
     * Drawing with relief disables: ends, line style and line pattern.
     */
    if (ISSET(cv->flags, RELIEF_OK)) {
      for (j = 0; j < cv->outlines.num_contours; j++) {
        num_points = cv->outlines.contours[j].num_points;
        points = cv->outlines.contours[j].points;
        /*printf("Draw: item %d, num_points %d %g@%g %g@%g, cw %d i/o %d\n",
               item->id,
               num_points, points[0].x, points[0].y,
               points[num_points-1].x, points[num_points-1].y,
               cv->outlines.contours[j].cw);*/
        ZnDrawPolygonRelief(wi, cv->relief, cv->gradient, points, num_points, cv->line_width);
      }
    }
    else {
      ZnSetLineStyle(wi, cv->line_style);
      values.foreground = ZnGetGradientPixel(cv->line_color, 0.0);
      values.line_width = (int) cv->line_width;
      values.join_style = cv->join_style;
      values.cap_style = cv->cap_style;
      if (cv->line_pattern == ZnUnspecifiedImage) {
        values.fill_style = FillSolid;
        XChangeGC(wi->dpy, wi->gc,
                  GCFillStyle|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground, &values);
      }
      else {
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(cv->line_pattern, wi->win);
        XChangeGC(wi->dpy, wi->gc,
                  GCFillStyle|GCStipple|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground,
                  &values);
      }
      for (j = 0; j < cv->outlines.num_contours; j++) {
        num_points = cv->outlines.contours[j].num_points;
        points = cv->outlines.contours[j].points;
        ZnListAssertSize(ZnWorkXPoints, num_points);
        xpoints = ZnListArray(ZnWorkXPoints);
        for (i = 0; i < num_points; i++) {
          xpoints[i].x = ZnNearestInt(points[i].x);
          xpoints[i].y = ZnNearestInt(points[i].y);
        }
        XDrawLines(wi->dpy, wi->draw_buffer, wi->gc,
                   xpoints, (int) num_points, CoordModeOrigin);
      }
      if (ISSET(cv->flags, FIRST_END_OK)) {
        ZnGetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
                     cv->first_end, end_points);
        for (i = 0; i < ZN_LINE_END_POINTS; i++) {
          xp[i].x = (short) end_points[i].x;
          xp[i].y = (short) end_points[i].y;
        }
        XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, ZN_LINE_END_POINTS,
                     Nonconvex, CoordModeOrigin);
      }
      if (ISSET(cv->flags, LAST_END_OK)) {
        ZnGetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
                     cv->cap_style, cv->last_end, end_points);
        for (i = 0; i < ZN_LINE_END_POINTS; i++) {
          xp[i].x = (short) end_points[i].x;
          xp[i].y = (short) end_points[i].y;
        }
        XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, ZN_LINE_END_POINTS,
                     Nonconvex, CoordModeOrigin);
      }
    }
  }
  
  /*
   * Draw the marks at each point. If arrows are specified or
   * if last point join first point suppress markers at end points.
   */
  if (ISSET(cv->flags, MARKER_OK)) {
    unsigned int h_width, h_height, width, height;
    int          tmp_x, tmp_y;

    ZnSizeOfImage(cv->marker, (int *) &width, (int *) &height);
    h_width = (width+1)/2;
    h_height = (height+1)/2;
    values.fill_style = FillStippled;
    values.stipple = ZnImagePixmap(cv->marker, wi->win);
    values.foreground = ZnGetGradientPixel(cv->marker_color, 0.0);
    XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCStipple|GCForeground, &values);
    for (j = 0; j < cv->outlines.num_contours; j++) {
      num_points = cv->outlines.contours[j].num_points;
      points = cv->outlines.contours[j].points;
      ZnListAssertSize(ZnWorkXPoints, num_points);
      xpoints = (XPoint *) ZnListArray(ZnWorkXPoints);
      for (i = 0; i < num_points; i++) {
        xpoints[i].x = (short) ZnNearestInt(points[i].x);
        xpoints[i].y = (short) ZnNearestInt(points[i].y);
      }
      if (ISSET(cv->flags, FIRST_END_OK)) {
        num_points--;
        points++;
      }
      if (ISSET(cv->flags, LAST_END_OK)) {
        num_points--;
      }
      for (; num_points > 0; num_points--, points++) {
        tmp_x = ((int) points->x) - h_width;
        tmp_y = ((int) points->y) - h_height;
        values.ts_x_origin = tmp_x;
        values.ts_y_origin = tmp_y;
        XChangeGC(wi->dpy, wi->gc,
                  GCTileStipXOrigin|GCTileStipYOrigin|GCForeground, &values);
        XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
                       tmp_x, tmp_y, width, height);
      }
    }
  }
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
CurveRenderCB(void      *closure)
{
  CurveItem     cv = (CurveItem) closure;
  unsigned int  i, j, num_points;
  ZnPoint       *points;

  for (i = 0; i < cv->tristrip.num_strips; i++) {
    num_points = cv->tristrip.strips[i].num_points;
    points = cv->tristrip.strips[i].points;
    if (cv->tristrip.strips[i].fan) {
      glBegin(GL_TRIANGLE_FAN);
    }
    else {
      glBegin(GL_TRIANGLE_STRIP);
    }
    for (j = 0; j < num_points; j++, points++) {
      glVertex2d(points->x, points->y);
    }
    glEnd();
  }
}
#endif

#ifdef GL
static void
Render(ZnItem   item)
{
  ZnWInfo       *wi  = item->wi;
  CurveItem     cv = (CurveItem) item;
  unsigned int  j, num_points;
  ZnPoint       *points;

  if ((cv->outlines.num_contours == 0) ||
      (ISCLEAR(cv->flags, FILLED_OK) &&
       !cv->line_width &&
       ISCLEAR(cv->flags, MARKER_OK))) {
    return;
  }

#ifdef GL_LIST
  if (!item->gl_list) {
    item->gl_list = glGenLists(1);
    glNewList(item->gl_list, GL_COMPILE);
#endif
    /*
     * Fill if requested.
     */
    if (ISSET(cv->flags, FILLED_OK)) {
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      if (!ZnGradientFlat(cv->fill_color)) {
        ZnRenderGradient(wi, cv->fill_color, CurveRenderCB, cv, cv->grad_geo,
                         &cv->outlines);
      }
      else if (cv->tile != ZnUnspecifiedImage) { /* Fill tiled/stippled */
        ZnRenderTile(wi, cv->tile, cv->fill_color, CurveRenderCB, cv,
                     (ZnPoint *) &item->item_bounding_box);
      }
      else {
        unsigned short alpha;
        XColor *color = ZnGetGradientColor(cv->fill_color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
        CurveRenderCB(cv);
      }
    }
    
    /*
     * Draw the lines between points
     */
    if (cv->line_width) {
      /*
       * Drawing with relief disables: ends, line style and line pattern.
       */
      if (ISSET(cv->flags, RELIEF_OK)) {
        for (j = 0; j < cv->outlines.num_contours; j++) {
          num_points = cv->outlines.contours[j].num_points;
          points = cv->outlines.contours[j].points;
          /*printf("Render: item %d, num_points %d %g@%g %g@%g, cw %d i/o %d\n",
            item->id,
            num_points, points[0].x, points[0].y,
            points[num_points-1].x, points[num_points-1].y,
            cv->outlines.contours[j].cw);*/
          ZnRenderPolygonRelief(wi, cv->relief, cv->gradient,
                                ISSET(cv->flags, SMOOTH_RELIEF_BIT),
                                points, num_points, cv->line_width);
        }
      }
      else {
        ZnLineEnd first = ISSET(cv->flags, FIRST_END_OK) ? cv->first_end : NULL;
        ZnLineEnd last = ISSET(cv->flags, LAST_END_OK) ? cv->last_end : NULL;
        
        for (j = 0; j < cv->outlines.num_contours; j++) {
          ZnRenderPolyline(wi,
                           cv->outlines.contours[j].points,
                           cv->outlines.contours[j].num_points,
                           cv->line_width, cv->line_style, cv->cap_style,
                           cv->join_style, first, last, cv->line_color);
        }
      }
    }
    
    /*
     * Draw the marks at each point. If arrows are specified or
     * if last point join first point suppress markers at end points.
     */
    if (ISSET(cv->flags, MARKER_OK)) {
      int       i_width, i_height;
      ZnReal    r_width, r_height;
      ZnPoint   ptmp;
      
      ZnSizeOfImage(cv->marker, &i_width, &i_height);
      r_width = (i_width+1.0)/2.0;
      r_height = (i_height+1.0)/2.0;
      for (j = 0; j < cv->outlines.num_contours; j++) {
        num_points = cv->outlines.contours[j].num_points;
        points = cv->outlines.contours[j].points;
        if (ISSET(cv->flags, FIRST_END_OK)) {
          num_points--;
          points++;
        }
        if (ISSET(cv->flags, LAST_END_OK)) {
          num_points--;
        }
        for (; num_points > 0; num_points--, points++) {
          ptmp.x = points->x - r_width;
          ptmp.y = points->y - r_height;
          ZnRenderIcon(wi, cv->marker, cv->marker_color, &ptmp, True);
        }
      }
    }
#ifdef GL_LIST    
    glEndList();
  }
  
  glCallList(item->gl_list);
#endif
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  CurveItem     cv = (CurveItem) item;
  ZnBBox        bbox;
  double        dist=1.0e40, new_dist;
  ZnPoint       *points, *p = ps->point;
  ZnPoint       end_points[ZN_LINE_END_POINTS];
  ZnPoint       triangle[3];
  unsigned int  num_points, i, j, stop;
  int           width, height;
  
  if (cv->outlines.num_contours == 0) {
    return dist;
  }
  
/*printf("Pick in curve\n");*/
  if (ISSET(cv->flags, FILLED_OK)) {
    for (i = 0; i < cv->tristrip.num_strips; i++) {
      num_points = cv->tristrip.strips[i].num_points;
      points = cv->tristrip.strips[i].points;
      j = 0;
      stop = num_points-2;
      if (cv->tristrip.strips[i].fan) {
        triangle[0] = points[0];
        j++;
        points++;
        stop++;
      }
      for (; j < stop; j++, points++) {
        if (cv->tristrip.strips[i].fan) {
          triangle[1] = points[0];
          triangle[2] = points[1];
        }
        else {
          triangle[0] = points[0];
          triangle[1] = points[1];
          triangle[2] = points[2];
        }
        new_dist = ZnPolygonToPointDist(triangle, 3, p);
        if (new_dist < dist) {
          dist = new_dist;
        }
        if (dist <= 0.0) {
          return 0.0;
        }
      }
    }
  }

  if (cv->line_width > 0) {
    /*
     * Check all contours.
     */
    for (i = 0; i < cv->outlines.num_contours; i++) {
      points = cv->outlines.contours[i].points;
      num_points = cv->outlines.contours[i].num_points;
      if (ISCLEAR(cv->flags, RELIEF_OK)) {
        new_dist = ZnPolylineToPointDist(points, num_points,
                                         cv->line_width, cv->cap_style, cv->join_style, p);
        if (new_dist < dist) {
          dist = new_dist;
        }
        if (dist <= 0.0) {
          /*printf("dist %g\n", dist);*/
          return 0.0;
        }
      }
      else {
        new_dist = ZnPolygonReliefToPointDist(points, num_points, cv->line_width, p);
        if (new_dist < dist) {
          dist = new_dist;
        }
        if (dist <= 0.0) {
          /*printf("dist %g\n", dist);*/
          return 0.0;
        }
      }
    }
  }
  
  /*
   * Line ends are checked only on the first contour.
   */
  points = cv->outlines.contours[0].points;
  num_points = cv->outlines.contours[0].num_points;
  /*
   * Check line ends.
   */
  if (ISSET(cv->flags, FIRST_END_OK)) {
    ZnGetLineEnd(&points[0], &points[1], cv->line_width, cv->cap_style,
                 cv->first_end, end_points);
    new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
    if (new_dist < dist) {
      dist = new_dist;
    }
    if (dist <= 0.0) {
      /*printf("dist %g\n", dist);*/
      return 0.0;
    }
  }
  if (ISSET(cv->flags, LAST_END_OK)) {
    ZnGetLineEnd(&points[num_points-1], &points[num_points-2], cv->line_width,
                 cv->cap_style, cv->last_end, end_points);
    new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
    if (new_dist < dist) {
      dist = new_dist;
    }
    if (dist <= 0.0) {
      /*printf("dist %g\n", dist);*/
      return 0.0;
    }
  }
  
  /*
   * Last, check markers on all contours.
   */
  if (ISSET(cv->flags, MARKER_OK)) {
    for (i = 0; i < cv->outlines.num_contours; i++) {
      points = cv->outlines.contours[i].points;
      num_points = cv->outlines.contours[i].num_points;
      
      if (ISSET(cv->flags, FIRST_END_OK)) {
        num_points--;
        points++;
      }
      if (ISSET(cv->flags, LAST_END_OK)) {
        num_points--;
      }
      
      ZnSizeOfImage(cv->marker, &width, &height);
      for (; num_points > 0; num_points--, points++) {
        bbox.orig.x = points->x - (width+1)/2;
        bbox.orig.y = points->y - (height+1)/2;
        bbox.corner.x = bbox.orig.x + width;
        bbox.corner.y = bbox.orig.y + height;
        new_dist = ZnRectangleToPointDist(&bbox, p);
        if (new_dist < dist) {
          dist = new_dist;
        }
        if (dist <= 0.0) {
          /*printf("dist %g\n", dist);*/
          return 0.0;
        }
      }
    }
  }

  /*printf("dist %g\n", dist);*/
  return dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ZnWInfo   *wi = item->wi;
  CurveItem cv = (CurveItem) item;
  char      path[500];
  ZnContour *contours;
  ZnPoint   *points;
  int       num_contours, num_points;
  int       i, j;

  num_contours = cv->outlines.num_contours;
  contours = cv->outlines.contours;

  /*
   * Put all contours in an array on the stack
   */
  if (ISSET(cv->flags, FILLED_BIT) || cv->line_width) {
    Tcl_AppendResult(wi->interp, "newpath ", NULL);
    for (i = 0; i < num_contours; i++, contours++) {
      num_points = contours->num_points;
      points = contours->points;
      sprintf(path, "%.15g %.15g moveto\n", points[0].x, points[0].y);
      Tcl_AppendResult(wi->interp, path, NULL);
      for (j = 1; j < num_points; j++) {
        sprintf(path, "%.15g %.15g lineto ", points[j].x, points[j].y);
        Tcl_AppendResult(wi->interp, path, NULL);
        if (((j+1) % 5) == 0) {
          Tcl_AppendResult(wi->interp, "\n", NULL);
        }
      }
    }
  }

  /*
   * Emit code to draw the filled area.
   */
  if (ISSET(cv->flags, FILLED_BIT)) {
    if (cv->line_width) {
      Tcl_AppendResult(wi->interp, "gsave\n", NULL);
    }
    if (!ZnGradientFlat(cv->fill_color)) {
      if (ZnPostscriptGradient(wi->interp, wi->ps_info, cv->fill_color,
                               cv->grad_geo, NULL) != TCL_OK) {
        return TCL_ERROR;
      }
    }
    else if (cv->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(cv->tile)) { /* Fill tiled */
        /* TODO No support yet */
      }
      else { /* Fill stippled */
        if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                               ZnGetGradientColor(cv->fill_color, 0.0, NULL)) != TCL_OK) {
          return TCL_ERROR;
        }
        Tcl_AppendResult(wi->interp, "clip ", NULL);
        if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
                                 ZnImagePixmap(cv->tile, wi->win)) != TCL_OK) {
          return TCL_ERROR;
        }
      }
    }
    else { /* Fill solid */
      if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                             ZnGetGradientColor(cv->fill_color, 0.0, NULL)) != TCL_OK) {
        return TCL_ERROR;
      }
      Tcl_AppendResult(wi->interp, "fill\n", NULL);
    }
    if (cv->line_width) {
      Tcl_AppendResult(wi->interp, "grestore\n", NULL);
    }
  }

  /*
   * Then emit code code to stroke the outline.
   */
  if (cv->line_width) {
    if (cv->relief != ZN_RELIEF_FLAT) {
      /* TODO No support yet */
    }
    else {
      Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
      if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
                              cv->line_width, cv->line_style,
                              cv->line_color, cv->line_pattern) != TCL_OK) {
        return TCL_ERROR;
      }
    }
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  CurveItem     cv = (CurveItem) item;

  tristrip->num_strips = 0;

  if (cv->tristrip.num_strips == 1) {
    ZnTriStrip1(tristrip,
                cv->tristrip.strips[0].points,
                cv->tristrip.strips[0].num_points,
                cv->tristrip.strips[0].fan);
  }
  else if (cv->tristrip.num_strips > 1) {
    tristrip->num_strips = cv->tristrip.num_strips;
    tristrip->strips = cv->tristrip.strips;
  }

  return False;
}


/*
 **********************************************************************************
 *
 * GetContours --
 *      Get the external contour(s).
 *      Never ever call ZnPolyFree on the poly returned by GetContours.
 *
 **********************************************************************************
 */
static ZnBool
GetContours(ZnItem      item,
            ZnPoly      *poly)
{
  CurveItem     cv = (CurveItem) item;

  if (cv->outlines.num_contours == 1) {
    ZnPolyContour1(poly, cv->outlines.contours[0].points,
                   cv->outlines.contours[0].num_points,
                   cv->outlines.contours[0].cw);
  }
  else if (cv->outlines.num_contours > 1) {
    poly->num_contours = cv->outlines.num_contours;
    poly->contours = cv->outlines.contours;
  }
  
  return False;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item vertices.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  CurveItem     cv = (CurveItem) item;
  unsigned int  j, num_controls;
  int           i;
  ZnContour     *c=NULL;

  /*printf("contour %d, num_pts %d, index %d, cmd %d\n",
    contour, *num_pts, index, cmd);*/
  /*printf("nb contours: %d\n", cv->shape.num_contours);*/
  /*
   * Special case for reading an empty curve.
   */
  if (((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) &&
      (cv->shape.num_contours == 0)) {
    *num_pts = 0;
    return TCL_OK;
  }

  if (contour < 0) {
    contour += cv->shape.num_contours;
  }
  if ((contour < 0) || ((unsigned int) contour >= cv->shape.num_contours)) {
    Tcl_AppendResult(item->wi->interp,
                     " curve contour index out of range", NULL);
    return TCL_ERROR;
  }
  if (cv->shape.num_contours != 0) {
    c = &cv->shape.contours[contour];
  }

  /* REPLACE */
  
  if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (cmd == ZN_COORDS_REPLACE_ALL) {
      /*
       * Replacing all the coordinates of a contour by no coordinates
       * is also legal, resulting in the contour being removed.
       */
      if (*num_pts) {
        if (c->points) {
          ZnFree(c->points); 
        }
        c->points = ZnMalloc(*num_pts*sizeof(ZnPoint));
        c->num_points = *num_pts;
        memcpy(c->points, *pts, *num_pts*sizeof(ZnPoint));
        if (c->controls) {
          ZnFree(c->controls);
          c->controls = NULL;
        }
        if (*controls) {
          c->controls = ZnMalloc(*num_pts*sizeof(char));
          memcpy(c->controls, *controls, *num_pts*sizeof(char));
        }
      }
    }
    else {
      if (*num_pts == 0) {
        Tcl_AppendResult(item->wi->interp,
                         " coords replace command need at least 1 point on curves", NULL);
        return TCL_ERROR;
      }
      if (index < 0) {
        index += c->num_points;
      }
      if ((index < 0) || ((unsigned int) index >= c->num_points)) {
      range_err:
        Tcl_AppendResult(item->wi->interp, " coord index out of range", NULL);
        return TCL_ERROR;
      }
      /*printf("--->%g@%g\n", (*pts)[0].x, (*pts)[0].y);*/
      c->points[index] = (*pts)[0];
      if (!c->controls && *controls && (*controls)[0]) {
        c->controls = ZnMalloc(c->num_points*sizeof(char));
        memset(c->controls, 0, c->num_points*sizeof(char));
      }
      if (c->controls) {
        if (!*controls) {
          c->controls[index] = 0;
        }
        else {
          if ((*controls)[0]) {
            /* Check if the edit is allowable, there should be
             * no more than 2 consecutive control points. The first
             * point must not be a control and the last one can
             * be one only if the curve is closed.
             */
            num_controls = 0;
            if (!index) {
            control_first:
              Tcl_AppendResult(item->wi->interp, " the first point must not be a control", NULL);
              return TCL_ERROR;       
            }
            else if ((unsigned int) index == c->num_points-1) {
              if (ISCLEAR(cv->flags, CLOSED_BIT) &&
                  (cv->shape.num_contours == 1)) {
              control_last:
                Tcl_AppendResult(item->wi->interp, " the last point must not be a control", NULL);
                return TCL_ERROR;             
              }
            }
            else {
              for (i = index-1; c->controls[i] && (i >= 0); i--, num_controls++);
            }
            for (j = index+1; c->controls[j] && (j < c->num_points); j++, num_controls++);
            if (num_controls > 1) {
            control_err:
              Tcl_AppendResult(item->wi->interp, " too many consecutive control points in a curve", NULL);
              return TCL_ERROR;
            }
          }
          c->controls[index] = (*controls)[0];
        }
      }
    }
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  
  /* READ */
  
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    if (cmd == ZN_COORDS_READ_ALL) {
      *num_pts = c->num_points;
      *pts = c->points;
      if (c->controls) {
        *controls = c->controls;
      }
    }
    else {
      /* Special case for an empty contour. */
      if (c->num_points == 0) {
        *num_pts = 0;
        return TCL_OK;
      }
      if (index < 0) {
        index += c->num_points;
      }
      if ((index < 0) || ((unsigned int) index >= c->num_points)) {
        goto range_err;
      }
      *num_pts = 1;
      *pts = &c->points[index];
      if (c->controls) {
        *controls = &c->controls[index];
      }
    }
  }

  /* ADD */
  
  else if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST)) {
    if (*num_pts == 0) {
      return TCL_OK;
    }
    if (cmd == ZN_COORDS_ADD_LAST) {
      index = c->num_points;
    }
    if (index < 0) {
      index += c->num_points;
    }
    if ((index < 0) || ((unsigned int) index > c->num_points)) {
      goto range_err;
    }
    if (*controls) {
      /* Check if the edit is allowable, there should be
       * no more than 2 consecutive control points. The first
       * point must not be a control and the last one can
       * be one only if the curve is closed.
       */
      if ((index == 0) && (*controls)[0]) {
        goto control_first;
      }
      else if (((unsigned int) index == (c->num_points-1)) &&
               (*controls)[*num_pts-1] &&
               ISCLEAR(cv->flags, CLOSED_BIT) &&
               (cv->shape.num_contours == 1)) {
        goto control_last;
      }

      num_controls = 0;
      if (c->controls) {
        if (index) {
          for (i = index-1; c->controls[i] && (i >= 0); i--, num_controls++);
        }
      }
      /*printf("******* num controls: %d\n", num_controls);*/
      for (j = 0; j < *num_pts; j++) {
        if (!(*controls)[j]) {
          num_controls = 0;
        }
        else {
          num_controls++;
          if (num_controls > 2) {
            goto control_err;
          }
        }
      }
      /*printf("******* num controls(2): %d\n", num_controls);*/
      if (c->controls) {
        for (j = index; c->controls[j] && (j < c->num_points); j++, num_controls++);
      }
      /*printf("******* num controls(3): %d\n", num_controls);*/
      if (num_controls > 2) {
        goto control_err;
      }
    }
    c->points = ZnRealloc(c->points, (c->num_points+*num_pts)*sizeof(ZnPoint));
    if (*controls || c->controls) {
      if (c->controls) {
        c->controls = ZnRealloc(c->controls, (c->num_points+*num_pts)*sizeof(char));
      }
      else {
        c->controls = ZnMalloc((c->num_points+*num_pts)*sizeof(char));
        memset(c->controls, 0, (c->num_points+*num_pts)*sizeof(char));
      }
    }
    /*
     * Make a hole if needed.
     */
    for (i = c->num_points-1; i >= index; i--) {
      c->points[i+*num_pts] = c->points[i];
      if (c->controls) {
        c->controls[i+*num_pts] = c->controls[i];
      }
    }
    for (j = 0; j < *num_pts; j++, index++) {
      c->points[index] = (*pts)[j];
      if (c->controls) {
        c->controls[index] = (*controls)?(*controls)[j]:0;
      }
    }
    c->num_points += *num_pts;
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }

  /* REMOVE */
  
  else if (cmd == ZN_COORDS_REMOVE) {
    if (index < 0) {
      index += c->num_points;
    }
    if ((index < 0) || ((unsigned int) index >= c->num_points)) {
      goto range_err;
    }

    if (c->controls) {
      /* Check if the edit is allowable, there should be
       * no more than 2 consecutive control points .
       */
      for (num_controls = 0, i = index-1; !c->controls[i]; i--, num_controls++);
      for (i = index+1; !c->controls[i]; i++, num_controls++);
      if (num_controls > 2) {
        goto control_err;
      }
    }

    c->num_points--;
    if ((c->num_points != 0) && ((unsigned int) index != c->num_points)) {
      for (j = index; j < c->num_points; j++) {
        c->points[j] = c->points[j+1];
        if (c->controls) {
          c->controls[j] = c->controls[j+1];
        }
      }
    }
    c->points = ZnRealloc(c->points, (c->num_points)*sizeof(ZnPoint));
    if (c->controls) {
      c->controls = ZnRealloc(c->controls, (c->num_points)*sizeof(char));
    }
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Contour --
 *      Perform geometric operations on curve contours.
 *
 **********************************************************************************
 */
static int
Contour(ZnItem  item,
        int     cmd,
        int     index,
        ZnPoly  *poly)
{
  CurveItem     cv = (CurveItem) item;
  unsigned int  j, num_contours;
  int           i;

  switch (cmd) {
  case ZN_CONTOUR_ADD:
    if (index < 0) {
      index += cv->shape.num_contours;
    }
    if ((unsigned int) index > cv->shape.num_contours) {
      index = cv->shape.num_contours;
    }
    if (index < 0) {
    contour_err:
      Tcl_AppendResult(item->wi->interp, " contour index out of range", NULL);
      return TCL_ERROR;
    }
    num_contours = cv->shape.num_contours + poly->num_contours;
    if (cv->shape.contours == &cv->shape.contour1) {
      cv->shape.contours = ZnMalloc(num_contours*sizeof(ZnContour));
      cv->shape.contours[0].num_points = cv->shape.contour1.num_points;
      cv->shape.contours[0].cw = cv->shape.contour1.cw;
      cv->shape.contours[0].points = cv->shape.contour1.points;
      cv->shape.contours[0].controls = cv->shape.contour1.controls;
    }
    else {
      cv->shape.contours = ZnRealloc(cv->shape.contours, num_contours*sizeof(ZnContour));
      /*printf("Reallocating shape contours (%d) 0x%X\n", num_contours, cv->shape.contours);*/
    }
    /*
     * Make a hole if needed.
     */
    /*printf("index : %d, i : %d\n", index, cv->shape.num_contours-1);*/
    for (i = cv->shape.num_contours-1; i >= index; i--) {
      cv->shape.contours[i+poly->num_contours] = cv->shape.contours[i];
    }
    for (j = 0; j < poly->num_contours; j++, index++) {
      cv->shape.contours[index].num_points = poly->contours[j].num_points;
      cv->shape.contours[index].cw = poly->contours[j].cw;
      cv->shape.contours[index].points = poly->contours[j].points;
      cv->shape.contours[index].controls = NULL;
      if (poly->contours[j].controls) {
        /*
         * The controls array in poly is shared, duplicate it
         * to keep a locally owned copy.
         */
        cv->shape.contours[index].controls = poly->contours[j].controls;
      }
    }
    cv->shape.num_contours = num_contours;
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);  
    break;
  case ZN_CONTOUR_REMOVE:
    if (index < 0) {
      index += cv->shape.num_contours;
    }
    if ((unsigned int) index >= cv->shape.num_contours) {
      index = cv->shape.num_contours - 1;
    }
    if (index < 0) {
      goto contour_err;
    }
    cv->shape.num_contours--;
    if (cv->shape.num_contours == 0) {
      ZnPolyFree(&cv->shape);
    }
    else {
      ZnFree(cv->shape.contours[index].points);
      if (cv->shape.contours[index].controls) {
        ZnFree(cv->shape.contours[index].controls);
      }
      for (j = index; j < cv->shape.num_contours; j++) {
        cv->shape.contours[j] = cv->shape.contours[j+1];
      }
    }
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);  
    break;
  }

  return cv->shape.num_contours;
}


/*
 **********************************************************************************
 *
 * PickVertex --
 *      Return in 'vertex' the vertex closest to p and in 'o_vertex' the
 *      opposite vertex on the closest edge, if such an edge exists or -1
 *      in the other case.
 *
 **********************************************************************************
 */
static void
PickVertex(ZnItem       item,
           ZnPoint      *p,
           int          *contour,
           int          *vertex,
           int          *o_vertex)
{
  CurveItem     cv = (CurveItem) item;
  unsigned int  i, j, k, num_points;
  ZnPoint       *points, po;
  ZnReal        dist=1.0e40, new_dist, dist2;
  ZnTransfo     t, inv;
  
  *contour = *vertex = *o_vertex = -1;
  
  if ((cv->line_width > 0) ||
      ISSET(cv->flags, FILLED_OK) ||
      ISSET(cv->flags, MARKER_OK)) {

    /*
     * Get the point in the item coordinate space.
     */
    ZnITEM.GetItemTransform(item, &t);
    ZnTransfoInvert(&t, &inv);
    ZnTransformPoint(&inv, p, &po);

    /*
     * Check all contours.
     */
    for (i = 0; i < cv->shape.num_contours; i++) {
      points = cv->shape.contours[i].points;
      num_points = cv->shape.contours[i].num_points;
      for (j = 0; j < num_points; j++) {
        new_dist = hypot(points[j].x - po.x, points[j].y - po.y);
        if (new_dist < dist) {
          dist = new_dist;
          *contour = i;
          *vertex = j;
        }
      }
      /*
       * If the closest vertex is in the current contour update
       * the opposite vertex.
       */
      if (i == (unsigned int) *contour) {
        j = (*vertex+1) % num_points;
        new_dist = ZnLineToPointDist(&points[*vertex], &points[j], &po, NULL);
        k = ((unsigned int)(*vertex-1)) % num_points;
        dist2 = ZnLineToPointDist(&points[*vertex], &points[k], &po, NULL);
        if (dist2 < new_dist) {
          *o_vertex = k;
        }
        else {
          *o_vertex = j;
        }
      }
    }
  }
}

/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  ZnBBox *bbox = &item->item_bounding_box;

  ZnOrigin2Anchor(&bbox->orig,
                  bbox->corner.x - bbox->orig.x,
                  bbox->corner.y - bbox->orig.y,
                  anchor, p);
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct CURVE_ITEM_CLASS = {
  "curve",
  sizeof(CurveItemStruct),
  cv_attrs,
  0,                    /* num_parts */
  0,                    /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  GetClipVertices,
  GetContours,
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  Contour,
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  PickVertex,           /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnCurve = (ZnItemClassId) &CURVE_ITEM_CLASS;

Added jni/tkzinc/generic/Draw.c.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
/*
 * Draw.c -- Implementation of common drawing routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Sat Dec 10 12:51:30 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


/*
 **********************************************************************************
 *
 * The algorihms used to draw the arrows, to do the 3d effects and to
 * smooth the polygons are adapted from Tk.
 *
 **********************************************************************************
 */

#include "Types.h"
#include "Draw.h"
#include "Geo.h"
#include "List.h"
#include "WidgetInfo.h"
#include "Image.h"
#include "tkZinc.h"

#include <math.h>
#include <stdarg.h>


#define POLYGON_RELIEF_DRAW     0
#define POLYGON_RELIEF_RENDER   1
#define POLYGON_RELIEF_DIST     2
#define POLYGON_RELIEF_BBOX     3
#define POLYGON_RELIEF_IN_BBOX  4

#define TOP_CONTRAST            13
#define BOTTOM_CONTRAST         6
#define MAX_INTENSITY           65535

#define ARROW_SHAPE_B           10.0
#define ARROW_SHAPE_C           5.0
#define OPEN_ARROW_SHAPE_A      4.0
#define CLOSED_ARROW_SHAPE_A    ARROW_SHAPE_B

#define LIGHTNING_SHAPE_A_RATIO 10.0
#define LIGHTNING_SHAPE_B_RATIO 8.0

#define LIGHTNING_POINTS        4
#define CORNER_POINTS           3
#define DOUBLE_CORNER_POINTS    4
#define STRAIGHT_POINTS         2


/*
 **********************************************************************************
 *
 * ZnSetLineStyle -- 
 *
 **********************************************************************************
 */
void
ZnSetLineStyle(ZnWInfo     *wi,
               ZnLineStyle line_style)
{
  if (wi->render) {
#ifdef GL
    switch (line_style) {
    case ZN_LINE_DASHED :
      glLineStipple(1, 0xF0F0);      
      glEnable(GL_LINE_STIPPLE);
      break;
    case ZN_LINE_MIXED :
      glLineStipple(1, 0x27FF);      
      glEnable(GL_LINE_STIPPLE);
      break;
    case ZN_LINE_DOTTED :
      glLineStipple(1, 0x18C3);      
      glEnable(GL_LINE_STIPPLE);
      break;
    default:
      glDisable(GL_LINE_STIPPLE);
    }
#endif
  }
  else {
    XGCValues           values;
    static const char   dashed[] = { 8 };
    static const char   dotted[] = { 2, 5 };
    static const char   mixed[]  = { 8, 5, 2, 5 };
    
    values.line_style = LineOnOffDash;
    switch (line_style) {
    case ZN_LINE_DASHED :
      XSetDashes(wi->dpy, wi->gc, 0, dashed, 1);
      break;
    case ZN_LINE_MIXED :
      XSetDashes(wi->dpy, wi->gc, 0, mixed, 4);
      break;
    case ZN_LINE_DOTTED :
      XSetDashes(wi->dpy, wi->gc, 0, dotted, 2);
      break;
    default:
      values.line_style = LineSolid;
      break;
    }
    XChangeGC(wi->dpy, wi->gc, GCLineStyle, &values);
  }
}


/*
 **********************************************************************************
 *
 * ZnLineShapePoints --
 *      Compute the points describing the given line shape between point p1 and p2.
 *      If bbox is non null, it is filled with the bounding box of the shape.
 *
 * For the time being this procedure handles straight lines, right and left
 * lightnings, right and left corners, right and left double corners..
 *
 *
 * Here are the parameters for lightnings:
 *
 *                                        *******
 *                                 *******     *
 *                           ******           *
 *                     ******      ******+   *
 *               ******      ******     *   *|
 *         ******      ******          *   * | LIGHTNING_SHAPE_A
 *   ******      ******               *   *  |
 *         ******                    *   *   |
 * ..******.........................+.+.*........................******..
 *   |                             *   *                    ******
 *   |                            *   *               ******      ******
 *   |                           *   *          ******      ******
 *   |                          *   *     ******      ******
 *   |                         *   *******      ******
 *   |                        *          ******
 *   |                       *     ******
 *   |                      ********   
 *   |                         |    | |
 *   |                         |----| | LIGHTNING_SHAPE_B
 *   |                                |
 *   |--------------------------------| LENGTH / 2
 *
 **********************************************************************************
 */
void
ZnLineShapePoints(ZnPoint       *p1,
                  ZnPoint       *p2,
                  ZnDim         line_width,
                  ZnLineShape   shape,
                  ZnBBox        *bbox,
                  ZnList        to_points)
{
  ZnPoint       *points;
  unsigned int  num_points, i;

  /*
   * Compute all line points according to shape.
   */
  if ((shape == ZN_LINE_LEFT_LIGHTNING) ||
      (shape == ZN_LINE_RIGHT_LIGHTNING)) {
    double      alpha, theta;
    double      length, length2;
    double      shape_a, shape_b;
    double      dx, dy;
    double      temp;

    num_points = LIGHTNING_POINTS;
    ZnListAssertSize(to_points, num_points);
    points = (ZnPoint *) ZnListArray(to_points);

    points[0] = *p1;
    points[3] = *p2;

    dx = p2->x - p1->x;
    dy = p2->y - p1->y;
    length = hypot(dx, dy);
    shape_a = length/LIGHTNING_SHAPE_A_RATIO + line_width/2.0;
    shape_b = length/LIGHTNING_SHAPE_B_RATIO + line_width/2.0;

    if (shape == ZN_LINE_LEFT_LIGHTNING)
      alpha = atan2(shape_a, shape_b);
    else
      alpha = -atan2(shape_a, shape_b);
    length2 = hypot(shape_a, shape_b);
    theta = atan2(-dy, dx);

    dx = p1->x + dx/2;
    dy = p1->y + dy/2;
    temp = cos(theta + alpha) * length2;
    points[1].x = dx + temp;
    points[2].x = dx - temp;
    temp = sin(theta + alpha) * length2;
    points[1].y = dy - temp;
    points[2].y = dy + temp;
  }
  else if (shape == ZN_LINE_LEFT_CORNER ||
           shape == ZN_LINE_RIGHT_CORNER) {
    num_points = CORNER_POINTS;
    ZnListAssertSize(to_points, num_points);
    points = (ZnPoint *) ZnListArray(to_points);

    points[0] = *p1;
    points[2] = *p2;

    if (shape == ZN_LINE_LEFT_CORNER) {
      points[1].x = p1->x;
      points[1].y = p2->y;
    }
    else {
      points[1].x = p2->x;
      points[1].y = p1->y;
    }
  }
  else if (shape == ZN_LINE_DOUBLE_LEFT_CORNER ||
           shape == ZN_LINE_DOUBLE_RIGHT_CORNER) {
    int dx, dy;

    num_points = DOUBLE_CORNER_POINTS;
    ZnListAssertSize(to_points, num_points);
    points = (ZnPoint *) ZnListArray(to_points);

    points[0] = *p1;
    points[3] = *p2;

    if (shape == ZN_LINE_DOUBLE_LEFT_CORNER) {
      dy = (int) (p2->y - p1->y);
      points[1].x = p1->x;
      points[2].x = p2->x;
      points[1].y = points[2].y = p1->y + dy/2;
    }
    else {
      dx = (int) (p2->x - p1->x);
      points[1].x = points[2].x = p1->x + dx/2;
      points[1].y = p1->y;
      points[2].y = p2->y;
    }
  }
  else /* if (shape) == ZN_LINE_STRAIGHT) */ {
    num_points = STRAIGHT_POINTS;
    ZnListAssertSize(to_points, num_points);
    points = (ZnPoint *) ZnListArray(to_points);

    points[0] = *p1;
    points[1] = *p2;
  }

  /*
   * Fill in the bbox, if requested.
   */
  if (bbox) {
    ZnResetBBox(bbox);
    for (i = 0; i < num_points; i++) {
      ZnAddPointToBBox(bbox, points[i].x, points[i].y);
    }
    
    /* Enlarge to take line_width into account. */
    if (line_width > 1) {
      ZnDim lw_2 = (line_width+1)/2;
      
      bbox->orig.x -= lw_2;
      bbox->orig.y -= lw_2;
      bbox->corner.x += lw_2;
      bbox->corner.y += lw_2;
    }
  }
}


/*
 **********************************************************************************
 *
 * ZnDrawLineShape --
 *      Draw a line given the points describing its path. It is designed to work
 *      with GetLineShape albeit it does fairly trivial things. In the future some
 *      shapes might need cooperation between the two and the clients will be ready
 *      for that.
 *
 *
 **********************************************************************************
 */
void
ZnDrawLineShape(ZnWInfo         *wi,
                ZnPoint         *p,
                unsigned int    num_p,
                ZnLineStyle     line_style,
                int             foreground_pixel,
                ZnDim           line_width,
                ZnLineShape     shape)
{
  XPoint        *xpoints;
  unsigned int  i;
  XGCValues     values;

  /*
   * Setup GC.
   */
  ZnSetLineStyle(wi, line_style);
  values.foreground = foreground_pixel;
  values.line_width = (int) line_width;
  values.fill_style = FillSolid;
  values.join_style = JoinRound;
  values.cap_style = CapRound;
  XChangeGC(wi->dpy, wi->gc,
            GCFillStyle|GCLineWidth|GCJoinStyle|GCCapStyle|GCForeground, &values);
  ZnListAssertSize(ZnWorkXPoints, num_p);
  xpoints = (XPoint *) ZnListArray(ZnWorkXPoints);
  for (i = 0; i < num_p; i++) {
    xpoints[i].x = (short) p[i].x;
    xpoints[i].y = (short) p[i].y;
  }
  XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, xpoints, (int) num_p, CoordModeOrigin);
}


/*
 **********************************************************************************
 *
 * ZnGetLineEnd --
 *      Compute the points describing the given line end style at point p1 for
 *      the line p1,p2. Point p1 is adjusted to fit the line end.
 *      If bbox is non null, it is filled with the bounding box of the end.
 *
 * For the time being this procedure handles open/filled arrows.
 *
 * Here are the parameters describing arrows.
 *
 *              *  | ARROW_SHAPE_C
 *            **   |
 *          * ***************************
 *        *  *
 *      *   *  +p1                      +p2
 *      | * |*
 *      |   * ***************************
 *      |   | **
 *      |   |   *
 *      |   |   |
 *      |---|   | ARROW_SHAPE_A
 *      |       |
 *      |-------| ARROW_SHAPE_B
 *
 **********************************************************************************
 */
void
ZnGetLineEnd(ZnPoint    *p1,
             ZnPoint    *p2,
             ZnDim      line_width,
             int        cap_style,
             ZnLineEnd  end_style,
             ZnPoint    *points)
{
  ZnReal        dx, dy, length, temp, backup;
  ZnReal        frac_height, sin_theta, cos_theta;
  ZnReal        vert_x, vert_y;
  ZnReal        shape_a, shape_b, shape_c;
  
  if (end_style != NULL) {
    shape_a = end_style->shape_a + 0.001;
    shape_b = end_style->shape_b + 0.001;
    shape_c = end_style->shape_c + line_width/2.0 + 0.001;

    frac_height = (line_width/2.0) / shape_c;
    dx = p1->x - p2->x;
    dy = p1->y - p2->y;
    length = hypot(dx, dy);
    if (length == 0) {
      sin_theta = cos_theta = 0.0;
    }
    else {
      sin_theta = dy/length;
      cos_theta = dx/length;
    }

    if (cap_style != CapProjecting) {
      temp = frac_height;
    }
    else {
      temp = line_width / shape_c;
    }
    backup = temp * shape_b + shape_a * (1.0 - temp) / 2.0;
    points[0].x = points[5].x = p1->x + backup * cos_theta;
    points[0].y = points[5].y = p1->y + backup * sin_theta;
    
    vert_x = points[0].x - shape_a*cos_theta;
    vert_y = points[0].y - shape_a*sin_theta;
    temp = shape_c*sin_theta;
    points[1].x = ZnNearestInt(points[0].x - shape_b*cos_theta + temp);
    points[4].x = ZnNearestInt(points[1].x - 2*temp);
    temp = shape_c*cos_theta;
    points[1].y = ZnNearestInt(points[0].y - shape_b*sin_theta - temp);
    points[4].y = ZnNearestInt(points[1].y + 2*temp);
    points[2].x = ZnNearestInt(points[1].x*frac_height + vert_x*(1.0-frac_height));
    points[2].y = ZnNearestInt(points[1].y*frac_height + vert_y*(1.0-frac_height));
    points[3].x = ZnNearestInt(points[4].x*frac_height + vert_x*(1.0-frac_height));
    points[3].y = ZnNearestInt(points[4].y*frac_height + vert_y*(1.0-frac_height));
  }
}

static ZnReal
SegmentPosInRelief(ZnReal               x1,
                     ZnReal             y1,
                     ZnReal             x2,
                     ZnReal             y2,
                     ZnReliefStyle      relief,
                     int                light_angle)
{
  ZnReal        angle, angle_step, origin, position;
  int           num_colors, color_index;
  
  num_colors = ZN_RELIEF_STEPS*2+1;
  angle_step = M_PI / (num_colors-1);
  origin = -(ZnDegRad(light_angle))-(angle_step/2.0);
  if (relief == ZN_RELIEF_SUNKEN) {
    origin += M_PI;
  }

  angle = ZnProjectionToAngle(y1 - y2, x2 - x1) + M_PI - origin;
  while (angle < 0.0) {
    angle += 2*M_PI;
  }
  while (angle > 2*M_PI) {
    angle -= 2*M_PI;
  }     

  color_index = (int) (angle/angle_step);
  if (color_index > num_colors-1) {
    color_index = 2*(num_colors-1)-color_index;
  }
  if ((color_index < 0) || (color_index >= num_colors)) {
    fprintf(stderr, "Color index out of gradient (should not happen).\n");
    if (color_index < 0) {
      color_index = 0;
    }
    if (color_index >= num_colors) {
      color_index = num_colors-1;
    }
  }
  position = 100*color_index/num_colors;
  /*printf("position %g, angle %g(%g), origin %g\n",
         position,
         RadianToDegrees(angle),
         angle,
         RadianToDegrees(origin));*/
  return position;
}

/*
 * ReliefColorOfSegment --
 * ReliefPixelOfSegment --
 */
static XColor *
ReliefColorOfSegment(ZnReal             x1,
                     ZnReal             y1,
                     ZnReal             x2,
                     ZnReal             y2,
                     ZnReliefStyle      relief,
                     ZnGradient         *gradient,
                     int                light_angle)
{
  return ZnGetGradientColor(gradient,
                            SegmentPosInRelief(x1, y1, x2, y2, relief, light_angle),
                            NULL);
}

static int
ReliefPixelOfSegment(ZnReal             x1,
                     ZnReal             y1,
                     ZnReal             x2,
                     ZnReal             y2,
                     ZnReliefStyle      relief,
                     ZnGradient         *gradient,
                     int                light_angle)
{
  return ZnGetGradientPixel(gradient,
                            SegmentPosInRelief(x1, y1, x2, y2, relief, light_angle));
}


/*
 **********************************************************************************
 *
 * ZnDrawRectangleRelief --
 *      Draw the bevels inside bbox.
 *
 **********************************************************************************
 */
void
ZnDrawRectangleRelief(ZnWInfo           *wi,
                      ZnReliefStyle     relief,
                      ZnGradient        *gradient,
                      XRectangle        *bbox,
                      ZnDim             line_width)
{
  XPoint        bevel[4];
  
  /*
   * If we haven't enough space to draw, exit.
   */
  if ((bbox->width < 2*line_width) || (bbox->height < 2*line_width)) {
    return;
  }
  
  /*
   * Grooves and ridges are drawn with two recursives calls with
   * half the width of the original one.
   */
  if ((relief == ZN_RELIEF_RIDGE) || (relief == ZN_RELIEF_GROOVE)) {
    ZnDim        new_line_width;
    unsigned int offset;
    XRectangle   internal_bbox;
    
    new_line_width = line_width/2.0;
    offset = (unsigned) (line_width - new_line_width);
    ZnDrawRectangleRelief(wi,
                          (ZnReliefStyle) ((relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_SUNKEN:ZN_RELIEF_RAISED),
                          gradient, bbox, new_line_width);
    internal_bbox = *bbox;
    internal_bbox.x += offset;
    internal_bbox.y += offset;
    internal_bbox.width -= offset*2;
    internal_bbox.height -= offset*2;
    ZnDrawRectangleRelief(wi,
                          (ZnReliefStyle) ((relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_RAISED:ZN_RELIEF_SUNKEN),
                          gradient, &internal_bbox, new_line_width);
    return;
  }

  XSetFillStyle(wi->dpy, wi->gc, FillSolid);
  
  bevel[0].x = bbox->x;
  bevel[0].y = bevel[1].y = bbox->y;
  bevel[1].x = bbox->x + bbox->width;
  bevel[2].y = bevel[3].y = bbox->y + (short) line_width;
  bevel[2].x = bevel[1].x - (short) line_width;
  bevel[3].x = bevel[0].x + (short) line_width;  
  XSetForeground(wi->dpy, wi->gc,
                 ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
                                      (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
                                      relief, gradient, wi->light_angle));
  XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);

  bevel[0] = bevel[1];
  bevel[3] = bevel[2];
  bevel[1].y += bbox->height;
  bevel[2].y = bevel[1].y - (short) line_width;
  XSetForeground(wi->dpy, wi->gc,
                 ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
                                      (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
                                      relief, gradient, wi->light_angle));
  XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);

  bevel[0] = bevel[1];
  bevel[3] = bevel[2];
  bevel[1].x -= bbox->width;
  bevel[2].x = bevel[1].x + (short) line_width;
  XSetForeground(wi->dpy, wi->gc,
                 ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
                                      (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
                                      relief, gradient, wi->light_angle));
  XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);

  bevel[0] = bevel[1];
  bevel[3] = bevel[2];
  bevel[1].x = bbox->x;
  bevel[1].y = bbox->y;
  bevel[2].x = bevel[3].x;
  bevel[2].y = bbox->y + (short) line_width;
  XSetForeground(wi->dpy, wi->gc,
                 ReliefPixelOfSegment((ZnReal) bevel[1].x, (ZnReal) bevel[1].y,
                                      (ZnReal) bevel[0].x, (ZnReal) bevel[0].y,
                                      relief, gradient, wi->light_angle));
  XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel, 4, Convex, CoordModeOrigin);
}


typedef struct {
  ZnWInfo       *wi;
  ZnPoint       *pp;
  ZnPoint       *p0;
  ZnPoint       *p1;
  double        dist;
  ZnBBox        *bbox;
  ZnReliefStyle relief;
  ZnGradient    *gradient;
  unsigned short alpha;
  ZnBool        smooth;
  int           result;
  int           count;
  ZnBool        toggle;
} PolygonData;

static void
DoPolygon(ZnPoint       *p,
          unsigned int  num_points,
          ZnDim         line_width,
          ZnBool        (*cb)(ZnPoint *bevels, PolygonData *pd),
          PolygonData   *pd)
{
  int           i;
  unsigned int  processed_points;
  ZnPoint       *p1, *p11=NULL, *p2;
  ZnPoint       pp1, pp2, new_pp1, new_pp2;
  ZnPoint       perp, c, shift1, shift2;
  ZnPoint       bevel_points[4];
  ZnBool        folded, closed, colinear;
  ZnReal        dx, dy;

  if (num_points < 2) {
    return;
  }

  /*
   * If the polygon is closed (last point is the same as first) open it by
   * dropping the last point. The algorithm closes the path automatically.
   * We remember this to decide if we draw the last bevel or not and if we
   * need to generate ends perpendicular to the path..
   */
  closed = False;
  if ((p->x == p[num_points-1].x) && (p->y == p[num_points-1].y)) {
    closed = True;
    num_points--;
  }
  /*printf("num_points=%d(%s)\n", num_points, closed?"closed":"");*/
  
  /*
   * We loop on all vertices of the polygon.
   * At each step we try to compute the corresponding border
   * corner `corner'. Then we build a polygon for the bevel.
   * Things look like this:
   *
   *          bevel[1]     /
   *             *        /
   *             |       /
   *             |      /
   *         pp1 *    * p[i-1]
   *             |    | bevel[0]
   *             |    |
   *             |    |
   *             |    | bevel[3]
   *             |    | p[i]
   *             |    | p1                 p2
   *         pp2 *    *--------------------*
   *             |
   *             |
   *      corner *----*--------------------*
   *     bevel[2]   new_pp1             new_pp2
   *
   * pp1 and pp2 are the ends of a segment // to p1 p2 at line_width
   * from it. These points are *NOT* necessarily on the perpendicular
   * going through p1 or p2.
   * This loop needs a bootstrap phase of two iterations (i.e we need to
   * process two points). This is why we start at the point before the last
   * and then wrap to the first point.
   * The algorithm discards any duplicate contiguous points.
   * It makes a special case if two consecutives edges are folded:
   *
   *  bevel[1]      pp1            pp2        a bevel[2]
   *    *-----------*--------------*----------*
   *                                           \
   *                                            \
   *     p[i-1]                                  \  bevel[3]
   *       *--------*-------------------------*---* corner
   *    bevel[0]    p2                       p1  /
   *                                            /
   *                                           /
   *      ----------*-----------*-------------*
   *             new_pp1     new_pp2          c
   *
   * In such a case we need to compute a, c, corner from pp1, pp2, new_pp1
   * and new_pp2. We compute the perpendicular to p1,p2 through p1, intersect
   * it with pp1,pp2 to obtain a, intersect it with new_pp1, new_pp2 to
   * obtain c, shift a,c and intersect it with p1,p2 to obtain corner.
   *
   */

  processed_points = 0;
  if (!closed) {
    i = 0;
    p1 = p;
  }
  else {
    i = -2;
    p1 = &p[num_points-2];
  }

  for (p2 = p1+1; i < (int) num_points; i++, p2++) {
    /*
     * When it is time to wrap, do it
     */
    if ((i == -1) || (i == (int) num_points-1)) {
      p2 = p;
    }
    /*
     * Skip over close vertices.
     */
    dx = p2->x - p1->x;
    dy = p2->y - p1->y;
    if ((ABS(dx) < 1.0) && (ABS(dy) < 1.0)) {
      continue;
    }

    ZnShiftLine(p1, p2, line_width, &new_pp1, &new_pp2);
    bevel_points[3] = *p1;
    folded = False;
    colinear = False;
    /*
     * The first two cases are for `open' polygons. We compute
     * a bevel closure that is perpendicular to the path.
     */
    if ((processed_points == 0) && !closed) {
      perp.x = p1->x + (p2->y - p1->y);
      perp.y = p1->y - (p2->x - p1->x);
      ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &bevel_points[2]);
    }
    else if ((processed_points == num_points-1) && !closed) {
      perp.x = p1->x + (p11->y - p1->y);
      perp.y = p1->y - (p11->x - p1->x);
      ZnIntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]);      
    }
    else if (processed_points >= 1) {
      ZnReal    dotp, dist, odx, ody;
      
      /*
       * The dot product of the two faces tell if the are
       * folded or colinear. The
       */
      odx = p11->x - p1->x;
      ody = p11->y - p1->y;
      dotp = odx*dx + ody*dy;
      dist = ZnLineToPointDist(p11, p2, p1, NULL);
      if ((dist < 4.0) && (dotp <= 0)) {
        perp.x = p1->x + (p2->y - p1->y);
        perp.y = p1->y - (p2->x - p1->x);
        ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &bevel_points[2]);
        colinear = True;
      }
      else {
        folded = !ZnIntersectLines(&new_pp1, &new_pp2, &pp1, &pp2, &bevel_points[2]);
        /*printf("new_pp1 %g@%g, new_pp2 %g@%g, pp1 %g@%g, pp2 %g@%g, inter %g@%g\n",
               new_pp1.x, new_pp1.y, new_pp2.x, new_pp2.y,
               pp1.x, pp1.y, pp2.x, pp2.y,
               bevel_points[2].x, bevel_points[2].y);*/
        folded = folded && (dotp < 0);
        if (folded) {
          /*printf("DoPolygonRelief: folded edges detected, %g@%g, %g@%g, %g@%g, %g@%g\n",
                 pp1.x, pp1.y, pp2.x, pp2.y, new_pp1.x, new_pp1.y,
                 new_pp2.x, new_pp2.y);*/
          perp.x = p1->x + (p2->y - p1->y);
          perp.y = p1->y - (p2->x - p1->x);
          ZnIntersectLines(p1, &perp, &pp1, &pp2, &bevel_points[2]);
          ZnIntersectLines(p1, &perp, &new_pp1, &new_pp2, &c);
          ZnShiftLine(p1, &perp, line_width, &shift1, &shift2);
          ZnIntersectLines(p1, p2, &shift1, &shift2, &bevel_points[3]);
        }
      }
    }

    if ((processed_points >= 2) || (!closed && (processed_points == 1))) {
      if ((processed_points == num_points-1) && !closed) {
        pd->p0 = pd->p1 = NULL;
      }
      else {
        pd->p0 = p1;
        pd->p1 = p2;
      }
      if ((*cb)(bevel_points, pd)) {
        return;
      }
    }
    
    p11 = p1;
    p1 = p2;
    pp1 = new_pp1;
    pp2 = new_pp2;
    bevel_points[0] = bevel_points[3];
    if (folded) {
      bevel_points[1] = c;
    }
    else if ((processed_points >= 1) || !closed) {
      bevel_points[1] = bevel_points[2];
    }

    processed_points++;
  }
}


/*
 **********************************************************************************
 *
 * ZnGetPolygonReliefBBox --
 *      Returns the bevelled polygon bounding box.
 *
 **********************************************************************************
 */
static ZnBool
PolygonBBoxCB(ZnPoint           *bevels,
              PolygonData       *pd)
{
  int    i;

  for (i = 0; i < 4; i++) {
    ZnAddPointToBBox(pd->bbox, bevels[i].x, bevels[i].y);
  }
  return 0;
}

void
ZnGetPolygonReliefBBox(ZnPoint          *points,
                       unsigned int     num_points,
                       ZnDim            line_width,
                       ZnBBox           *bbox)
{
  PolygonData   pd;

  pd.bbox = bbox;
  ZnResetBBox(bbox);
  DoPolygon(points, num_points, line_width, PolygonBBoxCB, &pd);
}


/*
 **********************************************************************************
 *
 * ZnPolygonReliefInBBox --
 *      Returns (-1) if the relief is entirely outside the bbox, (1) if it is
 *      entirely inside or (0) if in between
 *
 **********************************************************************************
 */
static ZnBool
PolygonInBBoxCB(ZnPoint         *bevels,
                PolygonData     *pd)
{
  if (pd->count == 0) {
    pd->count++;
    pd->result = ZnPolygonInBBox(bevels, 4, pd->bbox, NULL);
    if (pd->result == 0) {
      return 1;
    }
  }
  else {
    if (ZnPolygonInBBox(bevels, 4, pd->bbox, NULL) != pd->result) {
      pd->result = 0;
      return 1;
    }
  }
  return 0;
}

int
ZnPolygonReliefInBBox(ZnPoint           *points,
                      unsigned int      num_points,
                      ZnDim             line_width,
                      ZnBBox            *area)
{
  PolygonData   pd;

  pd.bbox = area;
  pd.count = 0;

  DoPolygon(points, num_points, line_width, PolygonInBBoxCB, &pd);

  return pd.result;
}


/*
 **********************************************************************************
 *
 * ZnPolygonReliefToPointDist --
 *      Returns the distance between the given point and
 *      the bevelled polygon.
 *
 **********************************************************************************
 */
static ZnBool
PolygonDistCB(ZnPoint           *bevels,
              PolygonData       *pd)
{
  double        new_dist;

  new_dist = ZnPolygonToPointDist(bevels, 4, pd->pp);
  if (new_dist < 0.0) {
    new_dist = 0.0;
  }
  if (new_dist < pd->dist) {
    pd->dist = new_dist;
  }
  return 0;
}

double
ZnPolygonReliefToPointDist(ZnPoint      *points,
                           unsigned int num_points,
                           ZnDim        line_width,
                           ZnPoint      *pp)
{
  PolygonData   pd;

  pd.dist = 1.0e40;
  pd.pp = pp;
  DoPolygon(points, num_points, line_width, PolygonDistCB, &pd);

  return pd.dist;
}


/*
 **********************************************************************************
 *
 * ZnDrawPolygonRelief --
 *      Draw the bevels around path.
 *
 **********************************************************************************
 */
static ZnBool
PolygonDrawCB(ZnPoint           *bevels,
              PolygonData       *pd)
{
  ZnWInfo       *wi = pd->wi;
  XPoint        bevel_xpoints[5];
  XGCValues     values;
  int           j;

  values.foreground = ReliefPixelOfSegment(bevels[0].x, bevels[0].y,
                                           bevels[3].x, bevels[3].y,
                                           pd->relief, pd->gradient,
                                           pd->wi->light_angle);

  values.fill_style = FillSolid;
  XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values);
        
  for (j = 0; j < 4; j++) {
    bevel_xpoints[j].x = ZnNearestInt(bevels[j].x);
    bevel_xpoints[j].y = ZnNearestInt(bevels[j].y);
  }

  XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, bevel_xpoints, 4,
               Convex, CoordModeOrigin);

  return 0;
}

void
ZnDrawPolygonRelief(ZnWInfo             *wi,
                    ZnReliefStyle       relief,
                    ZnGradient          *gradient,
                    ZnPoint             *points,
                    unsigned int        num_points,
                    ZnDim               line_width)
{
  PolygonData   pd;

  pd.wi = wi;
  pd.gradient = gradient;

  /*
   * Grooves and ridges are drawn with two calls. The first
   * with the original width, the second with half the width.
   */
  if ((relief == ZN_RELIEF_RIDGE) || (relief == ZN_RELIEF_GROOVE)) {
    pd.relief = (relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_RAISED:ZN_RELIEF_SUNKEN;
    DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
    pd.relief = (relief==ZN_RELIEF_GROOVE)?ZN_RELIEF_SUNKEN:ZN_RELIEF_RAISED;
    DoPolygon(points, num_points, line_width/2, PolygonDrawCB, &pd);
  }
  else {
    pd.relief = relief;
    DoPolygon(points, num_points, line_width, PolygonDrawCB, &pd);
  }
}

/*
 **********************************************************************************
 *
 * ZnRenderPolygonRelief --
 *      Draw the bevels around path using alpha enabled rendering.
 *
 **********************************************************************************
 */
#ifdef GL
static ZnBool
PolygonRenderCB(ZnPoint         *bevels,
                PolygonData     *pd)
{
  int           i;
  ZnPoint       p[6];
  XColor        *c[8];
  XColor        *color = ZnGetGradientColor(pd->gradient, 51.0, NULL);
  ZnReliefStyle relief, int_relief;
  ZnBool        two_faces, round, rule;

  rule = pd->relief & ZN_RELIEF_RULE;
  round = pd->relief & ZN_RELIEF_ROUND;
  two_faces = pd->relief & ZN_RELIEF_TWO_FACES;
  relief = pd->relief & ZN_RELIEF_MASK;
  for (i = 0; i < 4; i++) {
    p[i].x = ZnNearestInt(bevels[i].x);
    p[i].y = ZnNearestInt(bevels[i].y);
  }

  if (two_faces) {
    p[4].x = (p[0].x+p[1].x)/2;
    p[4].y = (p[0].y+p[1].y)/2;
    p[5].x = (p[2].x+p[3].x)/2;
    p[5].y = (p[2].y+p[3].y)/2;

    if (relief == ZN_RELIEF_SUNKEN) {
      int_relief = ZN_RELIEF_RAISED;
    }
    else {
      int_relief = ZN_RELIEF_SUNKEN;
    }
    c[0]=c[1]=c[2]=c[3] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
                                               bevels[3].x, bevels[3].y,
                                               relief, pd->gradient,
                                               pd->wi->light_angle);
    c[4]=c[5]=c[6]=c[7] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
                                               bevels[3].x, bevels[3].y,
                                               int_relief, pd->gradient,
                                               pd->wi->light_angle);
    if (pd->smooth && pd->p0) {
      c[2]=c[3] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
                                       pd->p1->x, pd->p1->y,
                                       relief, pd->gradient,
                                       pd->wi->light_angle);
      c[6]=c[7] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
                                       pd->p1->x, pd->p1->y,
                                       int_relief, pd->gradient,
                                       pd->wi->light_angle);
    }
    if (round) {
      if (!rule) {
        c[0]=c[3]=c[5]=c[6]=color;
      }
      else {
        c[1]=c[2]=c[4]=c[7]=color;
      }
    }
    glBegin(GL_QUADS);
    glColor4us(c[0]->red, c[0]->green, c[0]->blue, pd->alpha);
    glVertex2d(p[0].x, p[0].y);

    glColor4us(c[1]->red, c[1]->green, c[1]->blue, pd->alpha);
    glVertex2d(p[4].x, p[4].y);

    glColor4us(c[2]->red, c[2]->green, c[2]->blue, pd->alpha);
    glVertex2d(p[5].x, p[5].y);

    glColor4us(c[3]->red, c[3]->green, c[3]->blue, pd->alpha);
    glVertex2d(p[3].x, p[3].y);

    glColor4us(c[4]->red, c[4]->green, c[4]->blue, pd->alpha);
    glVertex2d(p[4].x, p[4].y);

    glColor4us(c[5]->red, c[5]->green, c[5]->blue, pd->alpha);
    glVertex2d(p[1].x, p[1].y);

    glColor4us(c[6]->red, c[6]->green, c[6]->blue, pd->alpha);
    glVertex2d(p[2].x, p[2].y);

    glColor4us(c[7]->red, c[7]->green, c[7]->blue, pd->alpha);
    glVertex2d(p[5].x, p[5].y);
    glEnd();
  }
  else { /* Single face */
    c[0]=c[1]=c[2]=c[3] = ReliefColorOfSegment(bevels[0].x, bevels[0].y,
                                               bevels[3].x, bevels[3].y,
                                               relief, pd->gradient,
                                               pd->wi->light_angle);
    if (pd->smooth && pd->p0) {
      c[2]=c[3] = ReliefColorOfSegment(pd->p0->x, pd->p0->y,
                                       pd->p1->x, pd->p1->y,
                                       relief, pd->gradient,
                                       pd->wi->light_angle);
    }
    if (round) {
      c[1]=c[2] = color;
    }
    glBegin(GL_QUADS);
    glColor4us(c[0]->red, c[0]->green, c[0]->blue, pd->alpha);
    glVertex2d(p[0].x, p[0].y);
    glColor4us(c[1]->red, c[1]->green, c[1]->blue, pd->alpha);
    glVertex2d(p[1].x, p[1].y);
    glColor4us(c[2]->red, c[2]->green, c[2]->blue, pd->alpha);
    glVertex2d(p[2].x, p[2].y);
    glColor4us(c[3]->red, c[3]->green, c[3]->blue, pd->alpha);
    glVertex2d(p[3].x, p[3].y);
    glEnd();
  }

  return 0;
}

void
ZnRenderPolygonRelief(ZnWInfo           *wi,
                      ZnReliefStyle     relief,
                      ZnGradient        *gradient,
                      ZnBool            smooth,
                      ZnPoint           *points,
                      unsigned int      num_points,
                      ZnDim             line_width)
{
  PolygonData   pd;

  pd.wi = wi;
  pd.gradient = gradient;
  ZnGetGradientColor(gradient, 0.0, &pd.alpha);
  pd.alpha = ZnComposeAlpha(pd.alpha, wi->alpha);
  pd.smooth = smooth;
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);      
  pd.relief = relief;
  pd.count = 0;

  DoPolygon(points, num_points, line_width, PolygonRenderCB, &pd);
}

void
ZnRenderPolyline(ZnWInfo        *wi,
                 ZnPoint        *points,
                 unsigned int   num_points,
                 ZnDim          line_width,
                 ZnLineStyle    line_style,
                 int            cap_style,
                 int            join_style,
                 ZnLineEnd      first_end,
                 ZnLineEnd      last_end,
                 ZnGradient     *gradient)
{
  int           num_clips = ZnListSize(wi->clip_stack);
  ZnPoint       end_points[ZN_LINE_END_POINTS];
  ZnBool        need_rcaps, thin, closed, transparent;
  int           pass, num_passes, i, k, m;
  ZnPoint       c1, c2;    
  XColor        *color;
  unsigned short alpha;
#ifdef PLATFORM_SDL
  ZnGLContextEntry *ce = wi->ce;
#else
  ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy);
#endif

  /*
   * The code below draws curves thiner than the min
   * of GL_SMOOTH_LINE_WIDTH_RANGE and GL_SMOOTH_POINT_SIZE_RANGE
   * with a mix of anti-aliased lines and points. The curves that
   * are thicker are drawn using regular polygons.
   * TODO: The joints are drawn only rounded.
   * The caps can be either round or butt (but not projecting).
   */
  thin = ((line_width <= ce->max_line_width) &&
          (line_width <= ce->max_point_width));
  closed = (points->x == points[num_points-1].x) && (points->y == points[num_points-1].y);
  color = ZnGetGradientColor(gradient, 0.0, &alpha);
  alpha = ZnComposeAlpha(alpha, wi->alpha);
  glColor4us(color->red, color->green, color->blue, alpha);
  ZnSetLineStyle(wi, line_style);
  glLineWidth((GLfloat) line_width);
  /*
   * Do not use AA under this transparency value.
   */
  transparent = alpha < (65535 * 0.8);
  if (thin && transparent) {
    /*
     * This makes a special case for transparent lines.
     * In this case we need to avoid drawing twice a
     * single pixel. To achieve this we use the stencil
     * buffer to protect already drawn pixels, unfortunately
     * using antialiasing write in the stencil even if
     * the pixel area is not fully covered resulting in
     * a crack that can't be covered by points later on.
     * To handle this case we need to disable the stencil
     * which in turn result in erroneous alpha coverage.
     *
     * We have chosen to drawn transparent lines with a
     * correct coverage but NOT antialiased.
     */
    glPointSize((GLfloat)(line_width>1.0?line_width-1:line_width));
    glDisable(GL_LINE_SMOOTH);
  }
  else {
    glPointSize((GLfloat)(line_width>1.0?line_width-1:line_width));
  }

  num_passes = 1;
  if (transparent) {
    num_passes = 2;
  }
    
  for (pass = 0; pass < num_passes; pass++) {
    if (transparent) {
      if (pass == 0) {
        ZnGlStartClip(num_clips, True);
      }
      else {
        ZnGlRestoreStencil(num_clips, False);
      }
    }
    if (first_end) {
      ZnGetLineEnd(&points[0], &points[1], line_width, cap_style,
                   first_end, end_points);
      glBegin(GL_TRIANGLE_FAN);
      for (m = 0; m < ZN_LINE_END_POINTS; m++) {
        glVertex2d(end_points[m].x, end_points[m].y);
      }
      glEnd();
    }
    if (last_end) {
      ZnGetLineEnd(&points[num_points-1], &points[num_points-2],
                   line_width, cap_style, last_end, end_points);
      glBegin(GL_TRIANGLE_FAN);
      for (m = 0; m < ZN_LINE_END_POINTS; m++) {
        glVertex2d(end_points[m].x, end_points[m].y);
      }
      glEnd();
    }
    if (thin) {
      glBegin(GL_LINE_STRIP);
      for (i = 0; i < (int) num_points; i++) {
        glVertex2d(points[i].x, points[i].y);
      }
      glEnd();
    }
    else {
      glBegin(GL_QUADS);
      for (i = 0; i < (int) num_points-1; i++) {
        ZnGetButtPoints(&points[i+1], &points[i], line_width, False, &c1, &c2);
        glVertex2d(c1.x, c1.y);
        glVertex2d(c2.x, c2.y);
        ZnGetButtPoints(&points[i], &points[i+1], line_width, False, &c1, &c2);
        glVertex2d(c1.x, c1.y);
        glVertex2d(c2.x, c2.y);
      }
      glEnd();
    }

    /* if (pass == 0) {
      ZnGlRenderClipped();
    }
    else {
      ZnGlEndClip(num_clips);
      break;
    }*/
    need_rcaps = ((line_width > 1) && (cap_style == CapRound));
    i = 0;
    k = num_points;
    if (closed) {
      k--;
    }
    if (!need_rcaps || first_end) {
      i++;
    }
    if ((!need_rcaps && !closed) || last_end) {
      k--;
    }

    if (thin) {
      glBegin(GL_POINTS);
      for ( ; i < k; i++) {
        glVertex2d(points[i].x, points[i].y);
      }
      glEnd();
    }
    else {
      int       num_cpoints;
      ZnReal    lw_2 = line_width / 2.0;
      ZnPoint   *cpoints = ZnGetCirclePoints(3, ZN_CIRCLE_COARSE,
                                             0.0, 2*M_PI,
                                             (unsigned int *) &num_cpoints,
                                             NULL);
      
      for ( ; i < k; i++) {
        glBegin(GL_TRIANGLE_FAN);
        glVertex2d(points[i].x, points[i].y);
        for (m = 0; m < num_cpoints; m++) {
          glVertex2d(points[i].x + cpoints[m].x*lw_2,
                     points[i].y + cpoints[m].y*lw_2);
        }
        glEnd();
      }
    }
  }
  
  ZnGlEndClip(num_clips);
  if (thin) {
    glEnable(GL_LINE_SMOOTH);
  }
}


void
ZnRenderIcon(ZnWInfo    *wi,
             ZnImage    image,
             ZnGradient *gradient,
             ZnPoint    *origin,
             ZnBool     modulate)
{
  ZnPoint       p[4];
  int           width, height;

  ZnSizeOfImage(image, &width, &height);
  p[0] = *origin;
  p[1].x = origin->x;
  p[1].y = origin->y + height;
  p[2].x = origin->x + width;
  p[2].y = p[1].y;
  p[3].x = p[2].x;
  p[3].y = origin->y;
  ZnRenderImage(wi, image, gradient, p, modulate);
}


void
ZnRenderImage(ZnWInfo    *wi,
              ZnImage    image,
              ZnGradient *gradient,
              ZnPoint    *quad,
              ZnBool     modulate)
{
  XColor        *color;
  unsigned short alpha;
  ZnReal        t, s;
  GLuint        texobj;
  
  color = ZnGetGradientColor(gradient, 0.0, &alpha);
  alpha = ZnComposeAlpha(alpha, wi->alpha);
  texobj = ZnImageTex(image, &t, &s);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, texobj);
  if (modulate) {
    glColor4us(color->red, color->green, color->blue, alpha);
  }
  else {
    glColor4us(65535, 65535, 65535, alpha);
  }
  glBegin(GL_QUADS);
  glTexCoord2d(0.0, 0.0);
  glVertex2d(quad[0].x, quad[0].y);
  glTexCoord2d(0.0, t);
  glVertex2d(quad[1].x, quad[1].y);
  glTexCoord2d(s, t);
  glVertex2d(quad[2].x, quad[2].y);
  glTexCoord2d(s, 0.0);
  glVertex2d(quad[3].x, quad[3].y);
  glEnd();
  glDisable(GL_TEXTURE_2D);
}

void
ZnRenderTile(ZnWInfo    *wi,
             ZnImage    tile,
             ZnGradient *gradient,
             void       (*cb)(void *),
             void       *closure,
             ZnPoint    *quad) /* Right now it's a ZnBBox */
{
  ZnReal        x, y, nx, ny, lx, ly, s, t, tiles, tilet;
  int           width, height, num_clips = ZnListSize(wi->clip_stack);
  unsigned short alpha;
  GLuint        texobj;
  XColor        *color;

  if (gradient) {
    color = ZnGetGradientColor(gradient, 0.0, &alpha);
    alpha = ZnComposeAlpha(alpha, wi->alpha);
  }
  else {
    color = NULL;
    alpha = ZnComposeAlpha(100, wi->alpha);
  }
  
  if (cb) {
    /*
     * Setup the stencil buffer with the shape to be drawn.
     */
    ZnGlStartClip(num_clips, False);

    (*cb)(closure);  
    ZnGlRestoreStencil(num_clips, True);
  }
  
  /*
   * Then texture map the quad through the shape.
   * The rectangle is drawn using quads, each
   * quad matching the size of the texture tile.
   */
  ZnSizeOfImage(tile, &width, &height);
  texobj = ZnImageTex(tile, &tilet, &tiles);
  glEnable(GL_TEXTURE_2D);
  if (color && ZnImageIsBitmap(tile)) {
    glColor4us(color->red, color->green, color->blue, alpha);
  }
  else {
    glColor4us(65535, 65535, 65535, alpha);
  }
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glBindTexture(GL_TEXTURE_2D, texobj);
  
  y = quad[0].y;
  lx = quad[1].x;
  ly = quad[1].y;
  glBegin(GL_QUADS);
  do {
    x = quad[0].x;
    t = 1.0;
    ny = y + height;
    if (ny > ly) {
      ny = ly;
      t = (ly - y) / (ZnReal) height;
    }
    t *= tilet;
    do {
      s = 1.0;
      nx = x + width;
      if (nx > lx) {
        nx = lx;
        s = (lx - x) / (ZnReal) width;
      }
      s *= tiles;
      glTexCoord2d(0.0, 0.0);
      glVertex2d(x, y);
      glTexCoord2d(0.0, t);
      glVertex2d(x, ny);
      glTexCoord2d(s, t);
      glVertex2d(nx, ny);
      glTexCoord2d(s, 0.0);
      glVertex2d(nx, y);
      x = nx;
    }
    while (x != lx);
    y = ny;
  }
  while (y != ly);
  glEnd();

  if (cb) {
    ZnGlEndClip(num_clips);
  }
  glDisable(GL_TEXTURE_2D);
}


static void
ComputeAxialGradient(ZnWInfo    *wi,
                     ZnPoly     *shape,
                     ZnReal     angle,
                     ZnPoint    *grad_geo)
{
  ZnTransfo     *transfo1, *transfo2;
  ZnContour     *c;
  ZnBBox        bbox;
  ZnPoint       *points, p[4];
  unsigned int  i;
  
  transfo1 = ZnTransfoNew();
  transfo2 = ZnTransfoNew();
  ZnRotateDeg(transfo1, angle);
  ZnRotateDeg(transfo2, -angle);
  c = shape->contours;
  ZnResetBBox(&bbox);
  for (i = 0; i < shape->num_contours; i++, c++) {
    ZnListAssertSize(ZnWorkPoints, c->num_points);
    points = ZnListArray(ZnWorkPoints);
    ZnTransformPoints(transfo1, c->points, points, c->num_points);
    ZnAddPointsToBBox(&bbox, points, c->num_points);
  }
  bbox.orig.x--;
  bbox.orig.y--;
  bbox.corner.x++;
  bbox.corner.y++;
  p[0] = bbox.orig;
  p[2] = bbox.corner;
  p[1].x = p[2].x;
  p[1].y = p[0].y;
  p[3].x = p[0].x;
  p[3].y = p[2].y;
  ZnTransfoSetIdentity(transfo1);
  ZnTransfoCompose(transfo1, transfo2, wi->current_transfo);
  ZnTransformPoints(transfo1, p, grad_geo, 4);
  ZnTransfoFree(transfo1);
  ZnTransfoFree(transfo2);
}

static void
ComputeCircularGradient(ZnWInfo         *wi,
                        ZnPoly          *shape,
                        ZnBool          oval,
                        ZnPoint         *focal_pp, /* in percent of bbox */
                        ZnReal          angle,
                        ZnPoint         *grad_geo)
{
  ZnReal        dist, new, x, y, ff;
  ZnBBox        bbox;
  ZnContour     *c;
  ZnPoint       offset, radius, focal_point;
  ZnPoint       *points;
  ZnTransfo     t1;
  unsigned int  i, j;

  /*
   * Compute the shape bbox (which should be in the item space).
   */
  ZnResetBBox(&bbox);
  c = shape->contours;
  dist = 0.0;
  for (j = 0; j < shape->num_contours; j++, c++) {
    ZnAddPointsToBBox(&bbox, c->points, c->num_points); 
  }

  /*
   * Find the gradient focal point in the item space.
   * The excursion of the focal point outside the item
   * bbox is clamped to avoid distorsions that take
   * place due to the rather simple algorithm used to
   * compute the maximum radius of the gradient.
   */
  focal_pp->x = fmod(focal_pp->x, 500.0);
  focal_pp->y = fmod(focal_pp->y, 500.0);
  offset.x = focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
  offset.y = focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
  focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + offset.x; 
  focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + offset.y; 

  /*
   * Find the max distance from the focal point.
   */
  if (oval) {
    /*
     * radius.x and radius.y are the shape radiuses.
     * ff is the distance from the bbox center to
     * the focal point.
     */
    radius.x = (bbox.corner.x-bbox.orig.x)/2;
    radius.y = (bbox.corner.y-bbox.orig.y)/2;
    ff = sqrt(offset.x*offset.x + offset.y*offset.y);
    /*
     * Compute the farthest point from the focal point 
     * on a unit circle, then map it to the oval and
     * compute the distance between the two points.
     */
    if (ff > PRECISION_LIMIT) {
      x = offset.x/ff;
      y = offset.y/ff;
      x *= radius.x;
      y *= radius.y;
      x = x + offset.x;
      y = y + offset.y;
    }
    else {
      x = 0;
      y = MAX(radius.x, radius.y);
    }
    dist = x*x + y*y;
  }
  else {
    /*
     * Use the given shape
     */
    c = shape->contours;
    for (j = 0; j < shape->num_contours; j++, c++) {
      for (i = 0, points = c->points; i < c->num_points; i++, points++) {
        x = points->x - focal_point.x;
        y = points->y - focal_point.y;
        new = x*x+y*y;
        if (new > dist) {
          dist = new;
        }
      }
    }
  }
  
  /*
   * Create a transform to map a unit circle to another one that
   * could fill the item when centered at the focal point.
   */
  dist = sqrt(dist); /* Max radius plus a fuzz factor */
  ZnTransfoSetIdentity(&t1);
  ZnScale(&t1, dist, dist);
  ZnRotateDeg(&t1, -angle);

  /*
   * Then, center the oval on the focal point.
   */
  ZnTranslate(&t1, focal_point.x, focal_point.y, False);
  /*
   * Last, compose with the current transform.
   */
  ZnTransfoCompose((ZnTransfo *) grad_geo, &t1, wi->current_transfo);
}

static void
ComputePathGradient(ZnWInfo     *wi,
                    ZnPoly      *shape,
                    ZnPoint     *focal_pp, /* in percent of the bbox */
                    ZnPoint     *grad_geo)
{
  ZnBBox        bbox;
  ZnContour     *c;
  ZnPoint       focal_point;
  unsigned int  j;

  /*
   * Compute the shape bbox (which should be in the item space).
   */
  ZnResetBBox(&bbox);
  c = shape->contours;
  for (j = 0; j < shape->num_contours; j++, c++) {
    ZnAddPointsToBBox(&bbox, c->points, c->num_points); 
  }

  /*
   * Find the gradient center in the item space.
   */
  focal_point.x = (bbox.corner.x+bbox.orig.x)/2 + focal_pp->x * (bbox.corner.x-bbox.orig.x)/100.0;
  focal_point.y = (bbox.corner.y+bbox.orig.y)/2 + focal_pp->y * (bbox.corner.y-bbox.orig.y)/100.0;
  /*
   * Then convert it to device space.
   */
  ZnTransformPoint(wi->current_transfo, &focal_point, &grad_geo[0]);
}

void
ZnComputeGradient(ZnGradient    *grad,
                  ZnWInfo       *wi,
                  ZnPoly        *shape,
                  ZnPoint       *grad_geo)
{
  switch (grad->type) {
  case ZN_AXIAL_GRADIENT:
    ComputeAxialGradient(wi, shape, grad->angle, grad_geo);
    break;
  case ZN_RADIAL_GRADIENT:
  case ZN_CONICAL_GRADIENT:
    ComputeCircularGradient(wi, shape, False, &grad->p, grad->angle, grad_geo);
    break;
  case ZN_PATH_GRADIENT:
    ComputePathGradient(wi, shape, &grad->p, grad_geo);
    break;
  }
}

void
ZnRenderGradient(ZnWInfo        *wi,
                 ZnGradient     *gradient,      /* The gradient to be drawn (static
                                                 * parameters). */
                 void           (*cb)(void *),  /* A callback called to clip the shape
                                                 * containing the gradient. */
                 void           *closure,       /* The callback parameter. */
                 ZnPoint        *quad,          /* The gradient geometric parameters
                                                 * (dynamic). */
                 ZnPoly         *poly           /* Used only by ZN_PATH_GRADIENT */
                 )
{
  unsigned short alpha, alpha2;
  int           angle;
  unsigned int  i, j;
  int           type = gradient->type;
  XColor        *color;
  ZnPoint       dposa, dposb, dposc, dposd;
  ZnPoint       p, dcontrol;
  ZnReal        npos, pos, control;
  unsigned int  num_clips = ZnListSize(wi->clip_stack);
  ZnPoint       iquad[4];
  
  if (!cb && (type == ZN_AXIAL_GRADIENT)) { /* Render an aligned
                                             * axial gradient in the quad */
    angle = gradient->angle;
    /*
     * Adjust the quad for 90 180 and 270 degrees axial
     * gradients. Other angles not supported.
     */
    switch (angle) {
    case 90:
      iquad[0] = quad[3];
      iquad[3] = quad[2];
      iquad[2] = quad[1];
      iquad[1] = quad[0];
      quad = iquad;
      break;
    case 180:
      iquad[0] = quad[2];
      iquad[3] = quad[1];
      iquad[2] = quad[0];
      iquad[1] = quad[3];
      quad = iquad;
      break;
    case 270:
      iquad[0] = quad[1];
      iquad[3] = quad[0];
      iquad[2] = quad[3];
      iquad[1] = quad[2];      
      quad = iquad;
      break;
    }
  }

  if (cb) {
    /*
     * Draw the gradient shape in the stencil using the provided
     * callback (clipping).
     */
    ZnGlStartClip(num_clips, False);
    (*cb)(closure);
    ZnGlRestoreStencil(num_clips, True);
  }

  if (type == ZN_AXIAL_GRADIENT) {
    /*
     * Then fill the axial gradient using the provided
     * quad and colors. The stencil will be restored
     * to its previous state in the process.
     */
    glBegin(GL_QUAD_STRIP);
    for (i = 0; i < gradient->num_actual_colors; i++) {
      color = gradient->actual_colors[i].rgb;
      alpha = ZnComposeAlpha(gradient->actual_colors[i].alpha, wi->alpha);
      glColor4us(color->red, color->green, color->blue, alpha);

      pos = gradient->actual_colors[i].position;
      control = gradient->actual_colors[i].control;
      dposa.x = (quad[1].x - quad[0].x)*pos/100.0;
      dposa.y = (quad[1].y - quad[0].y)*pos/100.0;
      p.x = quad[0].x + dposa.x;
      p.y = quad[0].y + dposa.y;
      glVertex2d(p.x, p.y);
      
      dposb.x = (quad[2].x - quad[3].x)*pos/100.0;
      dposb.y = (quad[2].y - quad[3].y)*pos/100.0;      
      p.x = quad[3].x + dposb.x;
      p.y = quad[3].y + dposb.y;
      glVertex2d(p.x, p.y);
      
      if ((control != 50.0) && (i != gradient->num_actual_colors-1)) {
        color = gradient->actual_colors[i].mid_rgb;
        alpha = ZnComposeAlpha(gradient->actual_colors[i].mid_alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
        
        npos = gradient->actual_colors[i+1].position;
        dposc.x = (quad[1].x - quad[0].x)*npos/100.0;
        dposc.y = (quad[1].y - quad[0].y)*npos/100.0;
        dcontrol.x = (dposc.x - dposa.x)*control/100.0;
        dcontrol.y = (dposc.y - dposa.y)*control/100.0;
        p.x = quad[0].x + dposa.x + dcontrol.x;
        p.y = quad[0].y + dposa.y + dcontrol.y;
        glVertex2d(p.x, p.y);
        
        dposd.x = (quad[2].x - quad[3].x)*npos/100.0;
        dposd.y = (quad[2].y - quad[3].y)*npos/100.0;
        dcontrol.x = (dposd.x - dposb.x)*control/100.0;
        dcontrol.y = (dposd.y - dposb.y)*control/100.0;      
        p.x = quad[3].x + dposb.x + dcontrol.x;
        p.y = quad[3].y + dposb.y + dcontrol.y;
        glVertex2d(p.x, p.y);
      }
      
    }
    glEnd();
  }
  else if (type == ZN_RADIAL_GRADIENT) {
    ZnReal       x, y, position, position2, position3;
    unsigned int num_p;
    ZnPoint      *genarc, *tarc, p, focalp;
    XColor       *color2;

    genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINE, 0.0, 2*M_PI, &num_p, NULL);
    ZnListAssertSize(ZnWorkPoints, num_p);
    tarc = ZnListArray(ZnWorkPoints);
    ZnTransformPoints((ZnTransfo *) quad, genarc, tarc, num_p);
    p.x = p.y = 0;
    ZnTransformPoint((ZnTransfo *) quad, &p, &focalp);
    
    position = 0.0;
    color = gradient->actual_colors[0].rgb;
    alpha = ZnComposeAlpha(gradient->actual_colors[0].alpha, wi->alpha);
    control = gradient->actual_colors[0].control;
    for (j = 1; j < gradient->num_actual_colors; j++) {
      position2 = gradient->actual_colors[j].position/100.0;
      if ((control != 50) && (j != gradient->num_actual_colors-1)) {
        glBegin(GL_QUAD_STRIP);
        color2 = gradient->actual_colors[j-1].mid_rgb;
        alpha2 = ZnComposeAlpha(gradient->actual_colors[j-1].mid_alpha, wi->alpha);
        position3 = position + (position2-position)*control/100.0;
        for (i = 0; i < num_p; i++) {
          x = focalp.x + (tarc[i].x-focalp.x) * position;
          y = focalp.y + (tarc[i].y-focalp.y) * position;
          glColor4us(color->red, color->green, color->blue, alpha);
          glVertex2d(x, y);
          x = focalp.x + (tarc[i].x-focalp.x) * position3;
          y = focalp.y + (tarc[i].y-focalp.y) * position3;
          glColor4us(color2->red, color2->green, color2->blue, alpha);
          glVertex2d(x, y);
        }
        position = position3;
        color = color2;
        alpha = alpha2;
        glEnd();
      }
      glBegin(GL_QUAD_STRIP);
      color2 = gradient->actual_colors[j].rgb;
      alpha2 = ZnComposeAlpha(gradient->actual_colors[j].alpha, wi->alpha);
      for (i = 0; i < num_p; i++) {
        x = focalp.x + (tarc[i].x-focalp.x) * position;
        y = focalp.y + (tarc[i].y-focalp.y) * position;
        glColor4us(color->red, color->green, color->blue, alpha);
        glVertex2d(x, y);
        x = focalp.x + (tarc[i].x-focalp.x) * position2;
        y = focalp.y + (tarc[i].y-focalp.y) * position2;
        glColor4us(color2->red, color2->green, color2->blue, alpha2);
        glVertex2d(x, y);
      }
      glEnd();
      position = position2;
      color = color2;
      alpha = alpha2;
      control = gradient->actual_colors[j].control;
    }
  }
  else if (type == ZN_PATH_GRADIENT) {
    ZnPoint      p, pp, p2, pp2, p3, pp3;
    unsigned int num_p, k, ii;
    ZnPoint      *points;
    ZnReal       position;
    
    for (k = 0; k < poly->num_contours; k++) {
      /*if (poly->contours[k].cw) {
        continue;
        }*/
      points = poly->contours[k].points;
      num_p = poly->contours[k].num_points;
      
      for (i = 0; i < num_p; i++) {
        if (i == num_p-1) {
          ii = 0;
        }
        else {
          ii = i+1;
        }
        
        glBegin(GL_QUAD_STRIP);
        p.x = p.y = pp.x = pp.y = 0;
        control = gradient->actual_colors[0].control;
        position = gradient->actual_colors[0].position;
        alpha = ZnComposeAlpha(gradient->actual_colors[0].alpha, wi->alpha);
        color = gradient->actual_colors[0].rgb;
        glColor4us(color->red, color->green, color->blue, alpha);
        glVertex2d(quad[0].x+p.x, quad[0].y+p.y);
        glVertex2d(quad[0].x+pp.x, quad[0].y+pp.y);
        for (j = 0; j < gradient->num_actual_colors-1; j++) {
          position = gradient->actual_colors[j+1].position;
          p2.x = (points[i].x-quad[0].x)*position/100.0;
          p2.y = (points[i].y-quad[0].y)*position/100.0;
          pp2.x = (points[ii].x-quad[0].x)*position/100.0;
          pp2.y = (points[ii].y-quad[0].y)*position/100.0;
          if (control != 50) {
            color = gradient->actual_colors[j].mid_rgb;
            alpha = ZnComposeAlpha(gradient->actual_colors[j].mid_alpha, wi->alpha);
            p3.x = p.x+(p2.x-p.x)*control/100.0;
            p3.y = p.y+(p2.y-p.y)*control/100.0;
            pp3.x = pp.x+(pp2.x-pp.x)*control/100.0;
            pp3.y = pp.y+(pp2.y-pp.y)*control/100.0;
            glColor4us(color->red, color->green, color->blue, alpha);
            glVertex2d(quad[0].x+p3.x, quad[0].y+p3.y);
            glVertex2d(quad[0].x+pp3.x, quad[0].y+pp3.y);
          }
          control = gradient->actual_colors[j+1].control;
          alpha = ZnComposeAlpha(gradient->actual_colors[j+1].alpha, wi->alpha);
          color = gradient->actual_colors[j+1].rgb;
          p = p2;
          pp = pp2;
          glColor4us(color->red, color->green, color->blue, alpha);
          glVertex2d(quad[0].x+p.x, quad[0].y+p.y);
          glVertex2d(quad[0].x+pp.x, quad[0].y+pp.y);
        }
        glEnd();
      }
    }
  }
  else if (type == ZN_CONICAL_GRADIENT) {
    ZnReal       position;
    unsigned int num_p;
    ZnPoint      *genarc, *tarc, p, focalp;
    XColor       col;

    genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINEST, 0.0, 2*M_PI, &num_p, NULL);
    ZnListAssertSize(ZnWorkPoints, num_p);
    tarc = ZnListArray(ZnWorkPoints);
    ZnTransformPoints((ZnTransfo *) quad, genarc, tarc, num_p);
    p.x = p.y = 0;
    ZnTransformPoint((ZnTransfo *) quad, &p, &focalp);
    
    glBegin(GL_TRIANGLE_STRIP);
    for (i = 0; i < num_p; i++) {
      position = i*100.0/(num_p-1);
      ZnInterpGradientColor(gradient, position, &col, &alpha);
      alpha = ZnComposeAlpha(alpha, wi->alpha);

      /*printf("position: %g --> color: %d %d %d, alpha: %d\n",
        position, col.red, col.green, col.blue, alpha);*/

      glColor4us(col.red, col.green, col.blue, alpha);
      glVertex2d(tarc[i].x, tarc[i].y);
      glVertex2d(focalp.x, focalp.y);
    }
    glEnd();
  }
  
  if (cb) {
    /*
     * Restore the previous GL state.
     */
    ZnGlEndClip(num_clips);
  }
}


void
ZnRenderHollowDot(ZnWInfo       *wi,
                  ZnPoint       *p,
                  ZnReal        size)
{
  int   num_clips = ZnListSize(wi->clip_stack);
  
  ZnGlStartClip(num_clips, False);
  
  glPointSize((GLfloat) (size-2));
  glBegin(GL_POINTS);
  glVertex2d(p->x, p->y);
  glEnd();

  ZnGlRenderClipped();

  glPointSize((GLfloat) size);
  glBegin(GL_POINTS);
  glVertex2d(p->x, p->y);
  glEnd();

  ZnGlRestoreStencil(num_clips, False);

  glBegin(GL_POINTS);
  glVertex2d(p->x, p->y);
  glEnd();

  ZnGlEndClip(num_clips);
}
#endif


#ifdef GL
void
ZnRenderGlyph(ZnTexFontInfo     *tfi,
              int               c)
{
  ZnTexGVI *tgvi;

  tgvi = ZnTexFontGVI(tfi, c);
  if (!tgvi) {
    return;
  }
  //printf("%c --> x0,y0: %d %d, tx0,ty0: %g %g, x1,y1: %d %d, tx1,ty1: %g %g, advance: %g\n",
    //     c, tgvi->v0x, tgvi->v0y, tgvi->t0x, tgvi->t0y,
    //     tgvi->v1x, tgvi->v1y, tgvi->t1x, tgvi->t1y,
    //     tgvi->advance);
  glBegin(GL_QUADS);
  glTexCoord2f(tgvi->t0x, tgvi->t0y); glVertex2s(tgvi->v0x, tgvi->v0y);
  glTexCoord2f(tgvi->t0x, tgvi->t1y); glVertex2s(tgvi->v0x, tgvi->v1y);
  glTexCoord2f(tgvi->t1x, tgvi->t1y); glVertex2s(tgvi->v1x, tgvi->v1y);
  glTexCoord2f(tgvi->t1x, tgvi->t0y); glVertex2s(tgvi->v1x, tgvi->v0y);
  glEnd();
  glTranslatef(tgvi->advance, 0.0, 0.0);
}

#ifdef PTK_800
void
ZnRenderString(ZnTexFontInfo    *tfi,
               unsigned char    *string,
               unsigned int     len)
{
  while (len) {
    ZnRenderGlyph(tfi, *string);
    string++;
    len--;
  }
}
#else
void
ZnRenderString(ZnTexFontInfo    *tfi,
               unsigned char    *string,
               unsigned int     len)
{
  unsigned int  clen;
  Tcl_UniChar   c;

  while (len) {
    clen = Tcl_UtfToUniChar((char *) string, &c);

    ZnRenderGlyph(tfi, c);

    string += clen;
    len -= clen;
  }
}
#endif
#endif

/*
 **********************************************************************************
 *
 * RenderTriangle --
 *      This routine maps an image onto a triangle.
 *      Image coordinates are chosen for  each vertex of the triangle.
 *      A simple affine tex mapping is used as in Zinc there is no way
 *      to specify perspective deformation. No filtering is attempted
 *      on the output pixels. 
 *
 *      In the comments below u and v are image coordinates and x and
 *      y are triangle coordinates.
 *      RenderAffineScanline is an helper function that draws a whole
 *      scan line to the image with linear interpolation.
 *
 **********************************************************************************
 */
static void
RenderAffineScanline(XImage     *image,
                     XImage     *mapped_image,
                     ZnReal     x1,
                     ZnReal     x2,
                     ZnReal     u1,
                     ZnReal     u2,
                     ZnReal     v1,
                     ZnReal     v2,
                     int        y)
{
  ZnReal        du, dv, width;
  int           intx1, intx2, intu, intv;
  int           i;
  
  /* Revert span ends if needed */
  if (x2 < x1) {
    ZnReal      tmp;
    tmp = x1; x1 = x2; x2 = tmp;
    tmp = u1; u1 = u2; u2 = tmp;
    tmp = v1; v1 = v2; v2 = tmp;
  }
  
  /* Compute the interpolation factors */
  width = x2 - x1;
  if (width) {
    du = (u2 - u1) / width;
    dv = (v2 - v1) / width;
  }
  else {
    du = dv = 0;
  }
  intx1 = (int) floor(x1);
  intx2 = (int) floor(x2);
  
  /* Draw the line */
  for (i = intx1; i < intx2; i++) {
    intu = (int) floor(u1);
    intv = (int) floor(v1);
    XPutPixel(mapped_image, i, y, XGetPixel(image, intu, intv));
    u1 += du;
    v1 += dv;
  }
}

static void
RenderTriangle(XImage   *image,
               XImage   *mapped_image,
               ZnPoint  *tri,
               ZnPoint  *im_coords)
{
  ZnReal        dx_A, dx_B;     /* Interpolation factor in x / y */
  ZnReal        du_A, du_B;     /* in u / y */
  ZnReal        dv_A, dv_B;     /* in v / y */
  ZnReal        x1, x2;         /* Span in x */
  ZnReal        u1, u2;         /* Span in u */
  ZnReal        v1, v2;         /* Span in v */
  int           height_A;       /* Scan line # from top top vertex A */
  int           height_B;       /* Scan line # from top top vertex B */
  int           y;              /* Current scan line */
  int           top, a, b;      /* Top triangle vertex and other two */
  int           i;

  /* Find top vertex and deduce the others. */
  top = 0;
  for (i = 1; i < 3; i++) {
    if (tri[i].y <= tri[top].y)
      top = i;
  }
  a = (top+1)%3;
  b = top-1;
  if (b < 0)
    b = 2;
  
  /* Initialize conversion parameters. */
  y = ZnNearestInt(tri[top].y);
  height_A = ZnNearestInt(tri[a].y - tri[top].y);
  height_B = ZnNearestInt(tri[b].y - tri[top].y);
  x1 = x2 = tri[top].x;
  u1 = u2 = im_coords[top].x;
  v1 = v2 = im_coords[top].y;
  if (height_A) {
    dx_A = (tri[a].x - tri[top].x) / height_A;
    du_A = (im_coords[a].x - im_coords[top].x) / height_A;
    dv_A = (im_coords[a].y - im_coords[top].y) / height_A;
  }
  else {
    dx_A = du_A = dv_A = 0;
  }
  if (height_B) {
    dx_B = (tri[b].x - tri[top].x) / height_B;
    du_B = (im_coords[b].x - im_coords[top].x) / height_B;
    dv_B = (im_coords[b].y - im_coords[top].y) / height_B;
  }
  else {
    dx_B = du_B = dv_B = 0;
  }
  
  /* Convert from top to bottom */
  for (i = 2; i > 0; ) {
    while (height_A && height_B) {

      /* Draw a scanline */
      RenderAffineScanline(image, mapped_image, x1, x2, u1, u2, v1, v2, y);

      /* Step the parameters*/
      y++;
      height_A--;
      height_B--;
      x1 += dx_A;
      x2 += dx_B;
      u1 += du_A;
      u2 += du_B;
      v1 += dv_A;
      v2 += dv_B;
    }
    
    /* If either height_A or height_B steps to zero, we have
     * encountered a vertex (A or B) and we are starting conversion
     * along a new edge. Update the parameters before proceeding. */
    if (!height_A) {
      int       na = (a+1)%3;
      
      height_A = ZnNearestInt(tri[na].y - tri[a].y);
      if (height_A) {
        dx_A = (tri[na].x - tri[a].x) / height_A;
        du_A = (im_coords[na].x - im_coords[a].x) / height_A;
        dv_A = (im_coords[na].y - im_coords[a].y) / height_A;
      }
      else {
        dx_A = du_A = dv_A = 0;
      }
      x1 = tri[a].x;
      u1 = im_coords[a].x;
      v1 = im_coords[a].y;
      a = na;
      /* One less vertex to do */
      i--;
    }
    
    if (!height_B) {
      int       nb = b - 1;
      
      if (nb < 0)
        nb = 2;
      height_B = ZnNearestInt(tri[nb].y - tri[b].y);
      if (height_B) {
        dx_B = (tri[nb].x - tri[b].x) / height_B;
        du_B = (im_coords[nb].x - im_coords[b].x) / height_B;
        dv_B = (im_coords[nb].y - im_coords[b].y) / height_B;
      }
      else {
        dx_B = du_B = dv_B = 0;
      }
      x2 = tri[b].x;
      u2 = im_coords[b].x;
      v2 = im_coords[b].y;
      b = nb;
      /* One less vertex to do */
      i--;
    }
  }
}


/*
 **********************************************************************************
 *
 * MapImage --
 *      This procedure maps an image on a parallelogram given in poly.
 *      The given parallelogram should fit in the destination image.
 *      The parallelogram vertices must be ordered as for a triangle
 *       strip: 
 *
 *    v0 ------------ v2
 *       |          |
 *       |          |
 *    v1 ------------ v3
 *
 *      The mapping is done by a simple affine mapping of the image on the
 *      two triangles obtained by cutting the parallelogram along the diogonal
 *      from the second vertex to the third vertex.
 *
 **********************************************************************************
 */
void
ZnMapImage(XImage       *image,
           XImage       *mapped_image,
           ZnPoint      *poly)
{
  ZnPoint       triangle[3];
  ZnPoint       im_coords[3];
  
  triangle[0] = poly[0];
  triangle[1] = poly[1];
  triangle[2] = poly[2];
  im_coords[0].x = 0.0;
  im_coords[0].y = 0.0;
  im_coords[1].x = 0.0;
  im_coords[1].y = image->height-1;
  im_coords[2].x = image->width-1;
  im_coords[2].y = 0.0;
  RenderTriangle(image, mapped_image, triangle, im_coords);

  triangle[0] = poly[1];
  triangle[1] = poly[2];
  triangle[2] = poly[3];
  im_coords[0].x = 0.0;
  im_coords[0].y = image->height-1;
  im_coords[1].x = image->width-1;
  im_coords[1].y = 0.0;
  im_coords[2].x = image->width-1;
  im_coords[2].y = image->height-1;
  RenderTriangle(image, mapped_image, triangle, im_coords);
}

Added jni/tkzinc/generic/Draw.h.















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * Draw.h -- Header for common drawing routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Sat Dec 10 12:51:30 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Draw_h
#define _Draw_h

#include "List.h"
#include "Types.h"
#include "Color.h"
#include "Attrs.h"
#include "Image.h"


#define ZN_LINE_SHAPE_POINTS    4       /* Maximum of all *_SHAPE_POINTS */

struct _ZnWInfo;

#ifdef GL
#define ZnGlStartClip(num_clips, render) { \
  if (!num_clips) { \
    glEnable(GL_STENCIL_TEST); \
  } \
  glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF); \
  glStencilOp(GL_KEEP, GL_INCR, GL_INCR); \
  if (!render) { \
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
  } \
}
#define ZnGlRenderClipped() { \
  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); \
  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
  }
#define ZnGlRestoreStencil(num_clips, render) { \
  glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF); \
  glStencilOp(GL_KEEP, GL_DECR, GL_DECR); \
  if (render) { \
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
  } \
  else { \
   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \
  } \
}
#define ZnGlEndClip(num_clips) { \
  glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF); \
  glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); \
  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \
  if (!num_clips) { \
    glDisable(GL_STENCIL_TEST); \
  } \
}
#endif


void ZnSetLineStyle(struct _ZnWInfo *wi, ZnLineStyle line_style);
void ZnLineShapePoints(ZnPoint *p1, ZnPoint *p2, ZnDim line_width,
                       ZnLineShape shape, ZnBBox *bbox, ZnList to_points);
void ZnDrawLineShape(struct _ZnWInfo *wi, ZnPoint *points, unsigned int num_points,
                     ZnLineStyle line_style, int foreground_pixel,
                     ZnDim line_width, ZnLineShape shape);
void
ZnGetLineEnd(ZnPoint *p1, ZnPoint *p2, ZnDim line_width,
             int cap_style, ZnLineEnd end_style, ZnPoint *points);

int ZnPolygonReliefInBBox(ZnPoint *points, unsigned int num_points,
                          ZnDim line_width, ZnBBox *bbox);
void ZnGetPolygonReliefBBox(ZnPoint *points, unsigned int num_points,
                            ZnDim line_width, ZnBBox *bbox);
double ZnPolygonReliefToPointDist(ZnPoint *points, unsigned int num_points,
                                  ZnDim line_width, ZnPoint *pp);
void ZnDrawRectangleRelief(struct _ZnWInfo *wi,
                           ZnReliefStyle relief, ZnGradient *gradient,
                           XRectangle *bbox, ZnDim line_width);
void ZnDrawPolygonRelief(struct _ZnWInfo *wi, ZnReliefStyle relief,
                         ZnGradient *gradient, ZnPoint *points,
                         unsigned int num_points, ZnDim line_width);
#ifdef GL
void ZnRenderPolygonRelief(struct _ZnWInfo *wi, ZnReliefStyle relief,
                           ZnGradient *gradient, ZnBool smooth,
                           ZnPoint *points, unsigned int num_points, ZnDim line_width);
void ZnRenderPolyline(struct _ZnWInfo *wi, ZnPoint *points, unsigned int num_points,
                      ZnDim line_width, ZnLineStyle line_style, int cap_style,
                      int join_style, ZnLineEnd first_end, ZnLineEnd last_end,
                      ZnGradient *gradient);
void ZnComputeGradient(ZnGradient *grad, struct _ZnWInfo *wi, ZnPoly *shape,
                       ZnPoint *grad_geo);
void ZnRenderGradient(struct _ZnWInfo *wi, ZnGradient *gradient,
                      void (*cb)(void *), void *closure, ZnPoint *quad,
                      ZnPoly *poly);
void ZnRenderTile(struct _ZnWInfo *wi, ZnImage tile, ZnGradient *gradient,
                  void (*cb)(void *), void *closure, ZnPoint *quad);
void ZnRenderIcon(struct _ZnWInfo *wi, ZnImage image, ZnGradient *gradient,
                  ZnPoint *origin, ZnBool modulate);
void ZnRenderImage(struct _ZnWInfo *wi, ZnImage image, ZnGradient *gradient,
                   ZnPoint *quad, ZnBool modulate);
void RenderHollowDot(struct _ZnWInfo *wi, ZnPoint *p, ZnReal size);

void ZnRenderGlyph(ZnTexFontInfo *tfi, int c);
void ZnRenderString(ZnTexFontInfo *tfi, unsigned char *str, unsigned int len);
#endif

void ZnMapImage(XImage *image, XImage *mapped_image, ZnPoint *poly);


#endif  /* _Draw_h */

Added jni/tkzinc/generic/Field.c.





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
/*
 * Field.c -- Implementation of fields.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : 
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Item.h"
#include "Types.h"
#include "WidgetInfo.h"
#include "Draw.h"
#include "Geo.h"
#include "tkZinc.h"

#include <string.h>
#include <stdlib.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


#define FIELD_SENSITIVE_BIT     1
#define FIELD_VISIBLE_BIT       2
#define FILLED_BIT              4
#define TEXT_ON_TOP_BIT         8
#define CACHE_OK                16


/*
 * Field record.
 */
typedef struct _FieldStruct {
  /* Public data */
  ZnGradient    *color;
  ZnGradient    *fill_color;
  ZnGradient    *border_color;
  char          *text;
  ZnImage       image;
  ZnImage       tile;
  Tk_Font       font;
  unsigned short flags;
  ZnBorder      border_edges;
  Tk_Justify    alignment;
  ZnReliefStyle relief;
  ZnDim         relief_thickness;
  ZnAutoAlign   auto_alignment;
  
  /* Private data */
  ZnGradient    *gradient;
  ZnPoint       *grad_geo;
  short         orig_x;
  short         orig_y;
  short         corner_x;
  short         corner_y;
  int           insert_index;
#ifdef GL
  ZnTexFontInfo *tfi;
#endif
} FieldStruct, *Field;


/*
 * The -text, -image, -border, -relief, -visible and
 * -filled attributes set the ZN_COORDS_FLAG to update
 * the leader that might protude if not clipped by the text.
 */
static ZnAttrConfig field_attrs[] = {
  { ZN_CONFIG_ALIGNMENT, "-alignment", NULL,
    Tk_Offset(FieldStruct, alignment), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_AUTO_ALIGNMENT, "-autoalignment", NULL,
    Tk_Offset(FieldStruct, auto_alignment), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-backcolor", NULL,
    Tk_Offset(FieldStruct, fill_color), 0,
    ZN_DRAW_FLAG|ZN_BORDER_FLAG, False },
  { ZN_CONFIG_EDGE_LIST, "-border", NULL,
    Tk_Offset(FieldStruct, border_edges), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-bordercolor", NULL,
    Tk_Offset(FieldStruct, border_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-color", NULL,
    Tk_Offset(FieldStruct, color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-filled", NULL,
    Tk_Offset(FieldStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
    Tk_Offset(FieldStruct, tile), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_FONT, "-font", NULL,
    Tk_Offset(FieldStruct, font), 0, ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
  { ZN_CONFIG_IMAGE, "-image", NULL,
    Tk_Offset(FieldStruct, image), 0,
    ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
  { ZN_CONFIG_RELIEF, "-relief", NULL,
    Tk_Offset(FieldStruct, relief), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-reliefthickness", NULL,
    Tk_Offset(FieldStruct, relief_thickness), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(FieldStruct, flags),
    FIELD_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
  { ZN_CONFIG_STRING, "-text", NULL,
    Tk_Offset(FieldStruct, text), 0, ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
  { ZN_CONFIG_IMAGE, "-tile", NULL,
    Tk_Offset(FieldStruct, tile), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(FieldStruct, flags), FIELD_VISIBLE_BIT, 
    ZN_COORDS_FLAG|ZN_CLFC_FLAG, False }, /* Keep ZN_COORDS_FLAG here */

  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};

static  void GetLabelBBox(ZnFieldSet field_set, ZnDim *w, ZnDim *h);



/*
 **********************************************************************************
 *
 * ComputeFieldAttachment --
 *      Compute the location/size of the field, computing attachments if any.
 * 
 **********************************************************************************
 */
static void
ComputeFieldAttachment(ZnFieldSet       field_set,
                       unsigned int     field,
                       ZnBBox           *field_bbox)
{
  
  ZnBBox        ref_bbox;
  ZnDim         real_width, real_height;
  unsigned int  ref_field, num_fields;
  char          x_attach, y_attach, x_dim, y_dim;
  short         width_spec, height_spec;
  int           x_spec, y_spec, icon_width=0, icon_height=0;
  Field         fptr;
  Tk_FontMetrics fm;

  /*printf("ComputeFieldAttachment in\n");*/
  fptr = &field_set->fields[field];
  if (ISSET(fptr->flags, CACHE_OK)) {
    field_bbox->orig.x = (ZnPos) fptr->orig_x;
    field_bbox->orig.y = (ZnPos) fptr->orig_y;
    field_bbox->corner.x = fptr->corner_x;
    field_bbox->corner.y = fptr->corner_y;
    /*printf("ComputeFieldAttachment in cache\n");*/
    return;
  }

  /*
   * Preset this field to a default position/size and pretend
   * its cache is ok to break any deadlocks.
   */
  fptr->orig_x = fptr->orig_y = 0;
  fptr->corner_x = fptr->corner_y = 0;
  field_bbox->orig.x = field_bbox->orig.y = 0;
  field_bbox->corner.x = field_bbox->corner.y = 0;
  SET(fptr->flags, CACHE_OK);

  num_fields = ZnLFNumFields(field_set->label_format);
  ZnLFGetField(field_set->label_format, field,
               &x_attach, &y_attach, &x_dim, &y_dim,
               &x_spec, &y_spec, &width_spec, &height_spec);
  
  /*
   * First try to compute the field size which may be a factor
   * of the field content (but not a factor of other fields).
   */
  if ((fptr->image != ZnUnspecifiedImage) &&
      ((x_dim == ZN_LF_DIM_ICON) || (y_dim == ZN_LF_DIM_ICON) ||
       (x_dim == ZN_LF_DIM_AUTO) || (y_dim == ZN_LF_DIM_AUTO))) {
    ZnSizeOfImage(fptr->image, &icon_width, &icon_height);
  }

  switch (x_dim) {
  case ZN_LF_DIM_FONT:
    real_width = (ZnDim) (width_spec*Tk_TextWidth(fptr->font, "N", 1)/100);
    break;
  case ZN_LF_DIM_ICON:
    real_width = (ZnDim) (width_spec*icon_width/100);
    break;
  case ZN_LF_DIM_AUTO:
    {
      int       len = 0;
      ZnDim     text_width;

      if (fptr->text) {
        len = strlen(fptr->text);
      }
      real_width = 0.0;
      if (fptr->image != ZnUnspecifiedImage) {
        real_width = (ZnDim) icon_width;
      }
      if (len) {
        /*
         * The 4 extra pixels are needed for border and padding.
         */
        text_width = (ZnDim) Tk_TextWidth(fptr->font, fptr->text, len) + 4;
        real_width = text_width < real_width ? real_width : text_width;
      }
      real_width += (ZnDim) width_spec;
      if (real_width < 0) {
        real_width = 0;
      }
      break;
    }
  case ZN_LF_DIM_LABEL:
    {
      ZnDim     lh;

      GetLabelBBox(field_set, &real_width, &lh);
      break;
    }
  case ZN_LF_DIM_PIXEL:
  default:
    real_width = (ZnDim) width_spec;
    break;
  }
  /*printf("field %d, width = %g\n", field, real_width);*/

  switch (y_dim) {
  case ZN_LF_DIM_FONT:
    {
      Tk_GetFontMetrics(fptr->font, &fm);
      real_height = (ZnDim) (height_spec*(fm.ascent + fm.descent)/100);
      break;
    }
  case ZN_LF_DIM_ICON:
    real_height = (ZnDim) (height_spec*icon_height/100);
    break;
  case ZN_LF_DIM_AUTO:
    {
      ZnDim     text_height;
      
      real_height = 0.0;
      if (fptr->image != ZnUnspecifiedImage) {
        real_height = (ZnDim) icon_height;
      }
      if (fptr->text && strlen(fptr->text)) {
        Tk_GetFontMetrics(fptr->font, &fm);
        text_height = (ZnDim) (fm.ascent + fm.descent);
        real_height = text_height < real_height ? real_height : text_height;
      }
      real_height += (ZnDim) height_spec;
      if (real_height < 0) {
        real_height = 0;
      }
      break;
    }
  case ZN_LF_DIM_LABEL:
    {
      ZnDim     lw;
      
      GetLabelBBox(field_set, &lw, &real_height);
      break;
    }
  case ZN_LF_DIM_PIXEL:
  default:
    real_height = (ZnDim) height_spec;
    break;
  }
  /*printf("field %d, height = %g\n", field, real_height);*/

  /*
   * Update the cache with the newly computed infos
   * (breaking of deadlocks).
   */
  field_bbox->corner.x = real_width;
  field_bbox->corner.y = real_height;
  fptr->corner_x = (short) real_width;
  fptr->corner_y = (short) real_height;

  /*
   * Then try to deduce the position, resolving any attachments
   * if needed.
   */
  
  /*
   * Do the x axis.
   */
  if (x_dim != ZN_LF_DIM_LABEL) {
    if (x_attach == ZN_LF_ATTACH_PIXEL) {
      field_bbox->orig.x = (ZnPos) x_spec;
      field_bbox->corner.x = field_bbox->orig.x + real_width;
    }
    else {
      ref_field = x_spec;
      field_bbox->orig.x = field_bbox->corner.x = 0;
      if (ref_field >= num_fields) {
        ZnWarning ("Attached (x) to an inexistant field geometry\n");
      }
      else {
        ComputeFieldAttachment(field_set, ref_field, &ref_bbox);
        switch (x_attach) {
        case ZN_LF_ATTACH_FWD:
          if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
            field_bbox->orig.x = ref_bbox.corner.x;
          }
          else {
            field_bbox->orig.x = ref_bbox.orig.x;
          }
          field_bbox->corner.x = field_bbox->orig.x + real_width;
          break;
        case ZN_LF_ATTACH_BWD:
          if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
            field_bbox->corner.x = ref_bbox.orig.x;
          }
          else {
            field_bbox->corner.x = ref_bbox.corner.x;
          }
          field_bbox->orig.x = field_bbox->corner.x - real_width;
          break;
        case ZN_LF_ATTACH_LEFT:
          field_bbox->orig.x = ref_bbox.orig.x;
          field_bbox->corner.x = field_bbox->orig.x + real_width;
          break;
        case ZN_LF_ATTACH_RIGHT:
          if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
            field_bbox->corner.x = ref_bbox.corner.x;
          }
          else {
            field_bbox->corner.x = ref_bbox.orig.x;
          }
          field_bbox->orig.x = field_bbox->corner.x - real_width;       
          break;
        }
      }
    }
    /*printf("field %d, x = %g\n", field, field_bbox->orig.x);*/
  }
  
  /*
   * Then the y axis.
   */
  if (y_dim != ZN_LF_DIM_LABEL) {
    if (y_attach == ZN_LF_ATTACH_PIXEL) {
      field_bbox->orig.y = (ZnPos) y_spec;
      field_bbox->corner.y = field_bbox->orig.y + real_height;
    }
    else {
      ref_field = y_spec;
      field_bbox->orig.y = field_bbox->corner.y = 0;
      if (ref_field >= num_fields) {
        ZnWarning ("Attached (y) to an inexistant field geometry\n");
      }
      else {
        ComputeFieldAttachment(field_set, ref_field, &ref_bbox);
        switch (y_attach) {
        case ZN_LF_ATTACH_FWD:
          if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
            field_bbox->orig.y = ref_bbox.corner.y;
          }
          else {
            field_bbox->orig.y = ref_bbox.orig.y;
          }
          field_bbox->corner.y = field_bbox->orig.y + real_height;
          break;
        case ZN_LF_ATTACH_BWD:
          if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
            field_bbox->corner.y = ref_bbox.orig.y;
          }
          else {
            field_bbox->corner.y = ref_bbox.corner.y;
          }
          field_bbox->orig.y = field_bbox->corner.y - real_height;
          break;
        case ZN_LF_ATTACH_LEFT:
          field_bbox->orig.y = ref_bbox.orig.y;
          field_bbox->corner.y = field_bbox->orig.y + real_height;
          break;
        case ZN_LF_ATTACH_RIGHT:
          if (ISSET(field_set->fields[ref_field].flags, FIELD_VISIBLE_BIT)) {
            field_bbox->corner.y = ref_bbox.corner.y;
          }
          else {
            field_bbox->corner.y = ref_bbox.orig.y;
          }
          field_bbox->orig.y = field_bbox->corner.y - real_height;      
          break;
        }
      }
    }
    /*printf("field %d, y = %g\n", field, field_bbox->orig.y);*/
  }
  
  fptr->orig_x = (short) field_bbox->orig.x;
  fptr->orig_y = (short) field_bbox->orig.y;
  fptr->corner_x = (short) field_bbox->corner.x;
  fptr->corner_y = (short) field_bbox->corner.y;
  SET(fptr->flags, CACHE_OK);

  /*printf("ComputeFieldAttachment out\n");*/
}


/*
 **********************************************************************************
 *
 * ClearFieldCache --
 *      Reset the geometric cache of all fields depending on a given field (or
 *      of all fields if the field is < 0). Clear also the label bounding box
 *      cache if some action has been taken on a field.
 * 
 **********************************************************************************
 */
static void
ClearFieldCache(ZnFieldSet      field_set,
                int             field)
{
  unsigned int  i, num_fields; 
  ZnBool        clear_bbox;
  int           x_spec, y_spec;
  char          x_attach, y_attach, x_dim, y_dim;
  short         width_spec, height_spec;

  if (!field_set->num_fields) {
    return;
  }
  if (field < 0) {
    for (i = 0; i < field_set->num_fields; i++) {
      CLEAR(field_set->fields[i].flags, CACHE_OK);
    }
    field_set->label_width = field_set->label_height = -1.0;
    return;
  }

  clear_bbox = False;
  if (!field_set->label_format) {
    return;
  }
  num_fields = ZnLFNumFields(field_set->label_format);
  if ((unsigned int) field >= num_fields) {
    return;
  }
  ZnLFGetField(field_set->label_format, (unsigned int) field,
               &x_attach, &y_attach, &x_dim, &y_dim,                  
               &x_spec, &y_spec, &width_spec, &height_spec);
  if ((x_dim != ZN_LF_DIM_PIXEL) || (y_dim != ZN_LF_DIM_PIXEL)) {
    CLEAR(field_set->fields[field].flags, CACHE_OK);
    clear_bbox = True;
  }
  for (i = 0; i < num_fields; i++) {
    ZnLFGetField(field_set->label_format, i,
                 &x_attach, &y_attach, &x_dim, &y_dim,
                 &x_spec, &y_spec, &width_spec, &height_spec);
    if ((x_attach == ZN_LF_ATTACH_PIXEL) && (y_attach == ZN_LF_ATTACH_PIXEL)) {
      continue;
    }
    if (x_attach != ZN_LF_ATTACH_PIXEL) {
      if ((x_spec == field) && ISSET(field_set->fields[i].flags, CACHE_OK)) {
        CLEAR(field_set->fields[i].flags, CACHE_OK);
        ClearFieldCache(field_set, (int) i);
        clear_bbox = True;
      }
    }
    if (y_attach != ZN_LF_ATTACH_PIXEL) {
      if ((y_spec == field) && ISSET(field_set->fields[i].flags, CACHE_OK)) {
        CLEAR(field_set->fields[i].flags, CACHE_OK);
        ClearFieldCache(field_set, (int) i);
        clear_bbox = True;
      }
    }
  }

  if (clear_bbox) {
    field_set->label_width = field_set->label_height = -1.0;
  }
}


/*
 **********************************************************************************
 *
 * GetLabelBBox --
 * 
 **********************************************************************************
 */
static void
GetLabelBBox(ZnFieldSet field_set,
             ZnDim      *w,
             ZnDim      *h)
{
  ZnBBox        bbox, tmp_bbox;
  ZnLabelFormat lf;
  unsigned int  i, num_fields;
  ZnDim         clip_w, clip_h;
  
  /*printf("GetLabelBBox in\n");*/
  if ((field_set->label_width >= 0.0) && (field_set->label_height >= 0.0)) {
    *w = field_set->label_width;
    *h = field_set->label_height;
    /*printf("GetLabelBBox in cache\n");*/
    return;
  }

  lf = field_set->label_format;
  if (lf == NULL) {
    *w = *h = field_set->label_width = field_set->label_height = 0.0;
    /*printf("GetLabelBBox no labelformat\n");*/
    return;
  }

  ZnResetBBox(&bbox);
  num_fields = ZnLFNumFields(lf);
  for (i = 0; i < num_fields; i++) {
    ComputeFieldAttachment(field_set, i, &tmp_bbox);
    /*printf("field %d bbox %g %g %g %g\n", i, tmp_bbox.orig.x, tmp_bbox.orig.y,
      tmp_bbox.corner.x, tmp_bbox.corner.y);*/
    ZnAddBBoxToBBox(&bbox, &tmp_bbox);
  }
  field_set->label_width = bbox.corner.x;
  field_set->label_height = bbox.corner.y;

  /*printf("GetLabelBBox size before clipping; w = %g, h = %g\n",
         field_set->label_width, field_set->label_height);*/
  if (ZnLFGetClipBox(lf, &clip_w, &clip_h)) {
    if (clip_w < field_set->label_width) {
      field_set->label_width = clip_w;
    }
    if (clip_h < field_set->label_height) {
      field_set->label_height = clip_h;
    }
  }
  
  *w = field_set->label_width;
  *h = field_set->label_height;
  /*printf("GetLabelBBox returns computed size; w = %g, h = %g\n", *w, *h);*/
}


/*
 **********************************************************************************
 *
 * GetFieldBBox --
 *      Compute the location of the field described
 *      by the field entry index in the item current LabelFormat.
 * 
 **********************************************************************************
 */
static void
GetFieldBBox(ZnFieldSet         field_set,
             unsigned int       index,
             ZnBBox             *field_bbox)
{
  ZnReal        ox, oy;
  
  /*printf("GetFieldBBox in\n");*/
  if (field_set->label_format) {
    ox = ZnNearestInt(field_set->label_pos.x);
    oy = ZnNearestInt(field_set->label_pos.y);
    ComputeFieldAttachment(field_set, index, field_bbox);
    field_bbox->orig.x += ox;
    field_bbox->orig.y += oy;
    field_bbox->corner.x += ox;
    field_bbox->corner.y += oy;
  }
  else {
    ZnResetBBox(field_bbox);
  }
  /*printf("GetFieldBBox out\n");*/
}


/*
 **********************************************************************************
 *
 * ComputeFieldTextLocation -- 
 *      Compute the position of the text in a field. This is a position
 *      that we can give to XDrawText. The position is deduced from the
 *      field bounding box passed in bbox.
 *      Return also the text bounding box.
 *
 **********************************************************************************
 */
static void
ComputeFieldTextLocation(Field          fptr,
                         ZnBBox         *bbox,
                         ZnPoint        *pos,
                         ZnBBox         *text_bbox)
{
  ZnDim         w, h;
  Tk_FontMetrics fm;

  Tk_GetFontMetrics(fptr->font, &fm);
  w = 0;
  if (fptr->text) {
    int width;
    Tk_MeasureChars(fptr->font, fptr->text, strlen(fptr->text), -1, 0, &width);
    w = width;
  }
  h = fm.ascent + fm.descent;
  text_bbox->orig.y = (bbox->orig.y + bbox->corner.y - h) / 2.0;
  text_bbox->corner.y = text_bbox->orig.y + h;
  pos->y = text_bbox->orig.y + fm.ascent;
  
  switch (fptr->alignment) {
  case TK_JUSTIFY_LEFT:
    text_bbox->orig.x = bbox->orig.x + 2;
    break;
  case TK_JUSTIFY_RIGHT:
    text_bbox->orig.x = bbox->corner.x - w - 2;
    break;
  default:
    text_bbox->orig.x = ZnNearestInt((bbox->orig.x + bbox->corner.x - w) / 2.0);
    break;
  }
  text_bbox->corner.x = text_bbox->orig.x + w;
  pos->x = text_bbox->orig.x;
}


/*
 **********************************************************************************
 *
 * LeaderToLabel --
 *      Compute the segment part of segment <start, end> that lies
 *      outside the fields of item.
 *
 **********************************************************************************
 */
static void
LeaderToLabel(ZnFieldSet        field_set,
              ZnPoint   *start,
              ZnPoint   *end)
{
  int           b_num;
  ZnPoint       delta, inf, sup;
  ZnPos         xt=0, yu=0, yw=0, xv=0;
  Field         fptr;
  unsigned int  i;
  ZnBBox        field_bbox;

  /* Intersection points :                                              */
  /*   T |xt / delta_y  U |x1           V |y1           W |yw / delta_x */
  /*     |y2              |yu / delta_x   |xv / delta_y   |x2           */
  /*                                            */
  /* y = ax + b;                                */
  /* a = delta_y / delta_x                      */
  /* b = (y * delta_x - x * delta_y) / delta_x  */

  delta.x = start->x - end->x;
  delta.y = start->y - end->y;
  b_num   = (int) (start->y*delta.x - start->x*delta.y);
  
  for (i = 0; i < ZnLFNumFields(field_set->label_format); i++) {
    fptr = &field_set->fields[i];
    /*
     * If the field is made invisible or has no graphics of
     * its own, don't clip.
     */
    if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT) ||
        (!fptr->text &&
         ISCLEAR(fptr->flags, FILLED_BIT) &&
         (fptr->border_edges == ZN_NO_BORDER) &&
         (fptr->relief == ZN_RELIEF_FLAT) &&
         (fptr->image == ZnUnspecifiedImage))) {
      continue;
    }

    /*
     * field_bbox is in absolute device coordinates.
     */
    GetFieldBBox(field_set, i, &field_bbox);

    /*
     * Adjust leader on real text, not on field boundaries. This is
     * important when there are leading and trailing spaces.
     */
    if (fptr->text &&
        ISCLEAR(fptr->flags, FILLED_BIT) &&
        (fptr->border_edges == ZN_NO_BORDER) &&
        (fptr->relief == ZN_RELIEF_FLAT) &&
        (fptr->image == ZnUnspecifiedImage)) {
      ZnBBox   text_bbox;
      ZnPoint  text_pos;        /* dummy */
      int      space_width;
      int      scan_forw, scan_back;
      space_width = Tk_TextWidth(fptr->font, " ", 1);

      ComputeFieldTextLocation(fptr, &field_bbox, &text_pos, &text_bbox);
      /*
       * Correct adjusments made by ComputeFieldTextLocation (Vincent Pomey).
       *
       * PLC: IMHO, this is to compensate for exotic fonts like 'symbolesATC'.
       *      I am not planning to port this to Tk for two reasons:
       *          1/ Current positions are no longer implemented as characters
       *      and 2/ Tk does not give access (easily) to lbearings and rbearings.
       * This patch has been contributed by Phidias team. I don't know the
       * problem it was meant to solve.
       * text_bbox.x -= fptr->font->per_char[fptr->text[0]].lbearing + 3;
       * text_bbox.width += fptr->font->per_char[fptr->text[0]].lbearing + 3;
       */
      /*
       * Change bbox according to leading and trailing spaces.
       */
      scan_forw = 0;
      while (fptr->text[scan_forw] == ' ') {
        /* leading spaces */
        text_bbox.orig.x += space_width;
        scan_forw++;
      }

      /*
       * Empty text.
       */
      if (!fptr->text || (fptr->text[scan_forw] == 0)) {
        continue;
      }
      
      scan_back = strlen(fptr->text)-1;
      while ((fptr->text[scan_back] == ' ') && (scan_back > scan_forw)) {
        /* trailing spaces */
        text_bbox.corner.x -= space_width;
        scan_back--;
      }

      field_bbox = text_bbox;
    }

    if (field_bbox.corner.x <= field_bbox.orig.x) {
      continue;
    }
    
    if ((start->x >= field_bbox.orig.x) && (start->x < field_bbox.corner.x) &&
        (start->y >= field_bbox.orig.y) && (start->y < field_bbox.corner.y)) {
      end->x = start->x;
      end->y = start->y;
    }
    if (delta.x) {
      yu = (field_bbox.orig.x*delta.y + b_num) / delta.x;
      yw = (field_bbox.corner.x*delta.y + b_num) / delta.x;
    }
    if (delta.y) {
      xt = (field_bbox.corner.y*delta.x - b_num) / delta.y;
      xv = (field_bbox.orig.y*delta.x - b_num) / delta.y;
    }
    
    inf.x = MIN(start->x, end->x);
    sup.x = MAX(start->x, end->x);
    inf.y = MIN(start->y, end->y);
    sup.y = MAX(start->y, end->y);
    
    if (delta.x) {
      if ((yu >= field_bbox.orig.y) && (yu <= field_bbox.corner.y) &&
          (field_bbox.orig.x >= inf.x) && (field_bbox.orig.x <= sup.x) &&
          (yu >= inf.y) && (yu <= sup.y)) {
        end->x = field_bbox.orig.x;
        end->y = yu;
        inf.x = MIN(start->x, end->x);
        sup.x = MAX(start->x, end->x);
        inf.y = MIN(start->y, end->y);
        sup.y = MAX(start->y, end->y);
      }
      if ((yw >= field_bbox.orig.y) && (yw <= field_bbox.corner.y) &&
          (field_bbox.corner.x >= inf.x) && (field_bbox.corner.x <= sup.x) &&
          (yw >= inf.y) && (yw <= sup.y)) {
        end->x = field_bbox.corner.x;
        end->y = yw;
        inf.x = MIN(start->x, end->x);
        sup.x = MAX(start->x, end->x);
        inf.y = MIN(start->y, end->y);
        sup.y = MAX(start->y, end->y);
      }
    }
    if (delta.y) {
      if ((xt >= field_bbox.orig.x) && (xt <= field_bbox.corner.x) &&
          (xt >= inf.x) && (xt <= sup.x) &&
          (field_bbox.corner.y >= inf.y) && (field_bbox.corner.y <= sup.y)) {
        end->x = xt;
        end->y = field_bbox.corner.y;
        inf.x = MIN(start->x, end->x);
        sup.x = MAX(start->x, end->x);
        inf.y = MIN(start->y, end->y);
        sup.y = MAX(start->y, end->y);
      }
      if ((xv >= field_bbox.orig.x) && (xv <= field_bbox.corner.x) &&
          (xv >= inf.x) && (xv <= sup.x) &&
          (field_bbox.orig.y >= inf.y) && (field_bbox.orig.y <= sup.y)) {
        end->x = xv;
        end->y = field_bbox.orig.y;
        inf.x = MIN(start->x, end->x);
        sup.x = MAX(start->x, end->x);
        inf.y = MIN(start->y, end->y);
        sup.y = MAX(start->y, end->y);
      }
    }
  }
}


/*
 **********************************************************************************
 *
 * InitFields --
 *
 *      Perform the init of each field in a ZnFieldSet. The number of such
 *      fields must have been inited before calling this fun.
 *
 **********************************************************************************
 */
static void
InitFields(ZnFieldSet   field_set)
{
  ZnWInfo               *wi = field_set->item->wi;
  Field                 field;
  unsigned int          i, num_fields;

  /*printf("size of a field = %d\n", sizeof(FieldStruct));*/
  
  if (!field_set->num_fields) {
    return;
  }
  num_fields = field_set->num_fields;
  field_set->fields = (Field) ZnMalloc(num_fields*sizeof(FieldStruct));

  for (i = 0; i < num_fields; i++){
    field = &field_set->fields[i];

    field->color = ZnGetGradientByValue(wi->fore_color);
    field->fill_color = ZnGetGradientByValue(wi->back_color);
    field->border_color = ZnGetGradientByValue(wi->fore_color);
    SET(field->flags, FIELD_VISIBLE_BIT);
    SET(field->flags, FIELD_SENSITIVE_BIT);
    CLEAR(field->flags, FILLED_BIT);
    CLEAR(field->flags, CACHE_OK);
    field->text = NULL;
    field->image = ZnUnspecifiedImage;
    field->tile = ZnUnspecifiedImage;
    field->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(wi->font));
#ifdef GL
    field->tfi = ZnGetTexFont(wi, field->font);
#endif
    field->border_edges = ZN_NO_BORDER;
    field->alignment = TK_JUSTIFY_LEFT;
    field->auto_alignment.automatic = False;

    field->relief = ZN_RELIEF_FLAT;
    field->relief_thickness = 2;
    SET(field->flags, TEXT_ON_TOP_BIT);

    field->gradient = NULL;
    field->grad_geo = NULL;
  }
  field_set->label_pos.x = field_set->label_pos.y = 0.0;
  field_set->label_width = field_set->label_height = -1.0;
}


/*
 **********************************************************************************
 *
 * CloneFields --
 *
 **********************************************************************************
 */
static void
CloneFields(ZnFieldSet  field_set)
{
  ZnWInfo       *wi = field_set->item->wi;
  Field         field, fields_ret;
  unsigned int  i, num_fields;
  char          *text;

  num_fields = field_set->num_fields;
  if (!num_fields) {
    return;
  }
  if (field_set->label_format) {
    field_set->label_format = ZnLFDuplicate(field_set->label_format);
  }
  fields_ret = (Field) ZnMalloc(num_fields*sizeof(FieldStruct));
  memcpy(fields_ret, field_set->fields, num_fields*sizeof(FieldStruct));
  field_set->fields = fields_ret;
  
  for (i = 0; i < num_fields; i++) {
    field = &fields_ret[i];
    if (field->gradient) {
      field->gradient = ZnGetGradientByValue(field->gradient);
    }
    if (field->grad_geo) {
      ZnPoint *grad_geo = ZnMalloc(4*sizeof(ZnPoint));
      memcpy(grad_geo, field->grad_geo, 4*sizeof(ZnPoint));
      field->grad_geo = grad_geo;    
    }    
    if (field->image != ZnUnspecifiedImage) {
      field->image = ZnGetImageByValue(field->image, ZnUpdateItemImage, field_set->item);
    }
    if (field->tile != ZnUnspecifiedImage) {
      field->tile = ZnGetImageByValue(field->tile, ZnUpdateItemImage, field_set->item);
    }
    field->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(field->font));
#ifdef GL
    field->tfi = ZnGetTexFont(wi, field->font);
#endif
    field->color = ZnGetGradientByValue(field->color);
    field->fill_color = ZnGetGradientByValue(field->fill_color);
    field->border_color = ZnGetGradientByValue(field->border_color);

    if (field->text) {
      text = (char *) ZnMalloc((strlen(field->text) + 1) * sizeof(char));
      strcpy(text, field->text);
      field->text = text;
    }
  }
}


/*
 **********************************************************************************
 *
 * ConfigureField -- 
 *
 **********************************************************************************
 */
static int
ConfigureField(ZnFieldSet       fs,
               int              field,
               int              argc,
               Tcl_Obj *CONST   argv[],
               int              *flags)
{
  unsigned int  i;
  Field         fptr;
  ZnBBox        bbox;
  ZnWInfo       *wi = fs->item->wi;
  XColor        *color;
  unsigned short alpha;
  int           old_num_chars, num_chars;
#ifdef GL
  Tk_Font       old_font;
#endif

  if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
    Tcl_AppendResult(wi->interp, "invalid field index", NULL);
    return TCL_ERROR;
  }
  
  fptr = &fs->fields[field];
#ifdef GL
  old_font = fptr->font;
#endif
  old_num_chars = 0;
  if (fptr->text) {
    old_num_chars = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
  }

  if (ZnConfigureAttributes(wi, fs->item, fptr, field_attrs,
                            argc, argv, flags) == TCL_ERROR) {
    return TCL_ERROR;
  }

  num_chars = 0;
  if (fptr->text) {
    num_chars = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
  }
  if (old_num_chars != num_chars) {
    ZnTextInfo *ti = &wi->text_info;
    /*
     * The text has changed, update the selection and
     * insertion pos to keep them valid.
     */
    if ((fs->item == ti->sel_item) && (field == ti->sel_field)) {
      if (ti->sel_last > num_chars) {
        ti->sel_last = num_chars;
      }
      if (ti->sel_first >= ti->sel_last) {
        ti->sel_item = ZN_NO_ITEM;
        ti->sel_field = ZN_NO_PART;
      }
      if ((ti->anchor_item == fs->item) && (ti->anchor_field == field) &&
          (ti->sel_anchor > num_chars)) {
        ti->sel_anchor = num_chars;
      }
    }
    if (fptr->insert_index > num_chars) {
      fptr->insert_index = num_chars;
    }
  }

#ifdef GL
  if (old_font != fptr->font) {
    if (fptr->tfi) {
      ZnFreeTexFont(fptr->tfi);
      fptr->tfi = ZnGetTexFont(wi, fptr->font);
    }
  }
#endif

  if (ISSET(*flags, ZN_REPICK_FLAG)) {
    SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
  }
  if (ISSET(*flags, ZN_CLFC_FLAG)) {
    ClearFieldCache(fs, field);
  }
  
  if (fptr->gradient &&
      (ISSET(*flags, ZN_BORDER_FLAG) || (fptr->relief == ZN_RELIEF_FLAT))) {
    ZnFreeGradient(fptr->gradient);
    fptr->gradient = NULL;
  }
  if ((fptr->relief != ZN_RELIEF_FLAT) && !fptr->gradient) {
    color = ZnGetGradientColor(fptr->border_color, 51.0, &alpha);
    fptr->gradient = ZnGetReliefGradient(wi->interp, wi->win,
                                              Tk_NameOfColor(color), alpha);
    if (fptr->gradient == NULL) {
      return TCL_ERROR;      
    }
  }

  /*
   * This is done here to limit the redraw to the area of the
   * modified fields.
   */
  if (ISCLEAR(*flags, ZN_COORDS_FLAG) &&
      fs->label_format && ISSET(*flags, ZN_DRAW_FLAG)) {
    for (i = 0; i < ZnLFNumFields(fs->label_format); i++) {
      if (i == (unsigned int) field) {
        GetFieldBBox(fs, i, &bbox);
        ZnDamage(wi, &bbox);
        break;
      }
    }
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * QueryField --
 *
 **********************************************************************************
 */
static int
QueryField(ZnFieldSet           fs,
           int                  field,
           int                  argc,
           Tcl_Obj *CONST       argv[])
{
  if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
    Tcl_AppendResult(fs->item->wi->interp, "invalid field index \"", NULL);
    return TCL_ERROR;
  }
    
  if (ZnQueryAttribute(fs->item->wi->interp, &fs->fields[field], field_attrs,
                       argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * FreeFields --
 *
 **********************************************************************************
 */
static void
FreeFields(ZnFieldSet   field_set)
{
  unsigned int  i, num_fields;
  Field         field;

  if (field_set->label_format) {
    ZnLFDelete(field_set->label_format);
  }
  
  num_fields = field_set->num_fields;
  for (i = 0; i < num_fields; i++) {
    field = &field_set->fields[i];
    
    if (field->text) {
      ZnFree(field->text);
    }
    if (field->gradient) {
      ZnFreeGradient(field->gradient);
    }
    if (field->grad_geo) {
      ZnFree(field->grad_geo);
    }
    if (field->image != ZnUnspecifiedImage) {
      ZnFreeImage(field->image, ZnUpdateItemImage, &field->image);
      field->image = ZnUnspecifiedImage;
    }
    if (field->tile != ZnUnspecifiedImage) {
      ZnFreeImage(field->tile, ZnUpdateItemImage, &field->tile);
      field->tile = ZnUnspecifiedImage;
    }
    Tk_FreeFont(field->font);
#ifdef GL
    if (field->tfi) {
      ZnFreeTexFont(field->tfi);
    }
#endif
    ZnFreeGradient(field->color);
    ZnFreeGradient(field->fill_color);
    ZnFreeGradient(field->border_color);
  }
  if (num_fields) {
    ZnFree(field_set->fields);
  }
}


/*
 **********************************************************************************
 *
 * FieldIndex,
 * FieldInsertChars,
 * FieldDeleteChars,
 * FieldCursor,
 * FieldSelection --
 *      These functions implement text edition in fields. The behavior
 * is the same as for Text items.
 *
 **********************************************************************************
 */
static int
FieldPointToChar(ZnFieldSet     fs,
                 unsigned int   field,
                 int            x,
                 int            y)
{
  Field         fptr;
  int           byte_index;
  ZnBBox        f_bbox, t_bbox;
  ZnPoint       t_orig;
  unsigned int  num_bytes, n;
  int           dummy;

  fptr = &fs->fields[field];
  num_bytes = 0;
  byte_index = 0;
  if (fptr->text) {
    num_bytes = strlen(fptr->text);
  }

  if (num_bytes == 0) {
    return 0;
  }
  
  GetFieldBBox(fs, field, &f_bbox);
  ComputeFieldTextLocation(fptr, &f_bbox, &t_orig, &t_bbox);

  /*
   * Point above text, returns index 0.
   */
  if (y < t_bbox.orig.y) {
    return 0;
  }
  
  if (y < t_bbox.corner.y) {
    if (x < t_bbox.orig.x) {
      /*
       * Point to the left of the current line, returns
       * index of first char.
       */
      return 0;
    }
    if (x >= t_bbox.corner.x) {
      /*
       * Point to the right of the current line, returns
       * index past the last char.
       */
      byte_index = num_bytes;
      goto convrt;
    }
    n = Tk_MeasureChars(fptr->font, fptr->text, num_bytes,
                        x + 2 - (int) t_bbox.orig.x, TK_PARTIAL_OK, &dummy);
    byte_index = n - 1;
    goto convrt;
  }
  /*
   * Point below all lines, return the index after
   * the last char.
   */ 
  byte_index = num_bytes;
 convrt:
  return Tcl_NumUtfChars(fptr->text, byte_index);
}

static int
WordMoveFromIndex(char  *text,
                  int   index,
                  int   fwd)
{
  char const *strp;

  if (!text) {
    return index;
  }

  strp = Tcl_UtfAtIndex(text, index);
  if (fwd) {
    while ((strp[1] == ' ') || (strp[1] == '\n')) {
      strp++;
    }
    while ((strp[1] != ' ') && (strp[1] != '\n') && strp[1]) {
      strp++;
    }
    return Tcl_NumUtfChars(text, strp + 1 - text);
  }
  else {
    while ((strp != text) && ((strp[-1] == ' ') || (strp[-1] == '\n'))) {
      strp--;
    }
    while ((strp != text) && (strp[-1] != ' ') && (strp[-1] != '\n')) {
      strp--;
    }
    return Tcl_NumUtfChars(text, strp - text);
  }
}

static int
FieldIndex(ZnFieldSet   fs,
           int          field,
           Tcl_Obj      *index_spec,
           int          *index)
{
  Field         fptr;
  ZnWInfo       *wi = fs->item->wi;
  ZnTextInfo    *ti = &wi->text_info;
  unsigned int  length;
  int           c, x, y;
  double        tmp;
  char          *end, *p;

  if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
    *index = 0;
    return TCL_OK;
  }

  fptr = &fs->fields[field];

  p = Tcl_GetString(index_spec);
  c = p[0];
  length = strlen(p);
  
  if ((c == 'e') && (strncmp(p, "end", length) == 0)) {
    *index = fptr->text ? Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text)) : 0;
  }
  else if ((c == 'e') && (length > 1) && (strncmp(p, "eol", length) == 0)) {
    *index = fptr->text ? Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text)) : 0;
  }
  else if ((c == 'b') && (length > 1) && (strncmp(p, "bol", length) == 0)) {
    *index = 0;
  }
  else if ((c == 'e') && (length > 1) && (strncmp(p, "eow", length) == 0)) {
    *index = WordMoveFromIndex(fptr->text, fptr->insert_index, 1);
  }
  else if ((c == 'b') && (length > 1) && (strncmp(p, "bow", length) == 0)) {
    *index = WordMoveFromIndex(fptr->text, fptr->insert_index, 0);
  }
  else if ((c == 'u') && (strncmp(p, "up", length) == 0)) {
    *index = fptr->insert_index;
  }
  else if ((c == 'd') && (strncmp(p, "down", length) == 0)) {
    *index = fptr->insert_index;
  }
  else if ((c == 'i') && (strncmp(p, "insert", length) == 0)) {
    *index = fptr->insert_index;
  }
  else if ((c == 's') && (strncmp(p, "sel.first", length) == 0) &&
           (length >= 5)) {
    if ((ti->sel_item != fs->item) || (ti->sel_field != field)) {
    sel_err:
      Tcl_AppendResult(wi->interp, "selection isn't in field", (char *) NULL);
      return TCL_ERROR;
    }
    *index = ti->sel_first;
  }
  else if ((c == 's') && (strncmp(p, "sel.last", length) == 0) &&
           (length >= 5)) {
    if ((ti->sel_item != fs->item) || (ti->sel_field != field)) {
      goto sel_err;
    }
    /*
     * We return a modified selection end so that it reflect
     * the text index of the last character _not_ the insertion
     * point between the last and the next.
     */
    *index = ti->sel_last-1;
  }
  else if (c == '@') {
    p++;
    tmp = strtod(p, &end);
    if ((end == p) || (*end != ',')) {
      goto badIndex;
    }
    x = (int) tmp;
    p = end+1;
    tmp = strtod(p, &end);
    if ((end == p) || (*end != 0)) {
      goto badIndex;
    }
    y = (int) tmp;
    
    *index = FieldPointToChar(fs, (unsigned int) field, x, y);
  }
  else if (Tcl_GetIntFromObj(wi->interp, index_spec, index) == TCL_OK) {
    int num_chars = fptr->text ? Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text)) : 0;
    if (*index < 0){
      *index = 0;
    }
    else if (*index > num_chars) {
      *index = num_chars;
    }
  }
  else {
  badIndex:
    Tcl_AppendResult(wi->interp, "bad index \"", p, "\"", (char *) NULL);
    return TCL_ERROR;
  }
  
  return TCL_OK;  
}

static ZnBool
FieldInsertChars(ZnFieldSet     fs,
                 int            field,
                 int            *index,
                 char           *chars)
{
  Field          fptr;
  ZnTextInfo    *ti = &fs->item->wi->text_info;
  int           num_chars, num_bytes, chars_added;
  unsigned int  byte_index, bytes_added = strlen(chars);
  char          *new;

  if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
    return False;
  }

  if (bytes_added == 0) {
    return False;
  }

  fptr = &fs->fields[field];
  num_chars = 0;
  num_bytes = 0;
  if (fptr->text) {
    num_bytes = strlen(fptr->text);
    num_chars = Tcl_NumUtfChars(fptr->text, num_bytes);
  }
  if (*index < 0) {
    *index = 0;
  }
  if (*index > num_chars) {
    *index = num_chars;
  }
  chars_added = Tcl_NumUtfChars(chars, (int) bytes_added);

  if (fptr->text) {
    byte_index = Tcl_UtfAtIndex(fptr->text, *index) - fptr->text;
    new = ZnMalloc(num_bytes + bytes_added + 1);
    /*
     * Copy the part before and the part after the new
     * text (if any).
     */
    memcpy(new, fptr->text, (size_t) byte_index);
    strcpy(new + byte_index + bytes_added, fptr->text + byte_index);
    ZnFree(fptr->text);
  }
  else {
    byte_index = 0;
    new = ZnMalloc(num_bytes + 1);
    new[num_bytes] = 0;
  }
  /*
   * Insert the new text.
   */
  memcpy(new + byte_index, chars, bytes_added);
  fptr->text = new;
  
  if (fptr->insert_index >= *index) {
    fptr->insert_index += chars_added;
  }
  if ((ti->sel_item == fs->item) && (ti->sel_field == field)) {
    if (ti->sel_first >= *index) {
      ti->sel_first += chars_added;
    }
    if (ti->sel_last >= *index) {
      ti->sel_last += chars_added;
    }
    if ((ti->anchor_item == fs->item) && (ti->anchor_field == field) &&
        (ti->sel_anchor >= *index)) {
      ti->sel_anchor += chars_added;
    }
  }

  /*
   * Need to redo the fields layout (maybe).
   */
  ClearFieldCache(fs, field);
  return True;
}

static ZnBool
FieldDeleteChars(ZnFieldSet     fs,
                 int            field,
                 int            *first,
                 int            *last)
{
  Field          fptr;
  ZnTextInfo    *ti = &fs->item->wi->text_info;
  unsigned int  char_count, byte_count;
  unsigned int  num_bytes, num_chars, first_offset;
  char          *new;

  if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
    return False;
  }

  fptr = &fs->fields[field];
  num_chars = 0;
  num_bytes = 0;
  if (fptr->text) {
    num_bytes = strlen(fptr->text);
    num_chars = Tcl_NumUtfChars(fptr->text, (int) num_bytes);
  }
  if (num_chars == 0) {
    return False;
  }
  
  if (*first < 0) {
    *first = 0;
  }
  if (*last >= (int) num_chars) {
    *last = num_chars-1;
  }
  if (*first > *last) {
    return False;
  }
  char_count = *last + 1 - *first;
  first_offset = Tcl_UtfAtIndex(fptr->text, *first)-fptr->text;
  byte_count = Tcl_UtfAtIndex(fptr->text + first_offset, (int) char_count) -
    (fptr->text+first_offset);

  if (num_bytes - byte_count) {
    new = ZnMalloc(num_bytes + 1 - byte_count);
    memcpy(new, fptr->text, (size_t) first_offset);
    strcpy(new + first_offset, fptr->text + first_offset + byte_count);
    ZnFree(fptr->text);
    fptr->text = new;
  }
  else {
    ZnFree(fptr->text);
    fptr->text = NULL;
  }

  /*
   * Update the cursor to reflect the new string.
   */
  if (fptr->insert_index > *first) {
    fptr->insert_index -= char_count;
    if (fptr->insert_index < *first) {
      fptr->insert_index = *first;
    }
  }
  if ((ti->sel_item == fs->item) && (ti->sel_field == field)) {
    if (ti->sel_first > *first) {
      ti->sel_first -= char_count;
      if (ti->sel_first < *first) {
        ti->sel_first = *first;
      }
    }
    if (ti->sel_last >= *first) {
      ti->sel_last -= char_count;
      if (ti->sel_last < *first - 1) {
        ti->sel_last = *first - 1;
      }
    }
    if (ti->sel_first > ti->sel_last) {
      ti->sel_item = ZN_NO_ITEM;
    }
    if ((ti->anchor_item == fs->item) && (ti->anchor_field == field) &&
        (ti->sel_anchor > *first)) {
      ti->sel_anchor -= char_count;
      if (ti->sel_anchor < *first) {
        ti->sel_anchor = *first;
      }
    }
  }
  
  /*
   * Need to redo the fields layout (maybe).
   */
  ClearFieldCache(fs, field);
  return True;
}

static void
FieldCursor(ZnFieldSet  fs,
            int         field,
            int         index)
{
  Field fptr;
  int   num_chars;

  if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
    return;
  }

  fptr = &fs->fields[field];
  num_chars = 0;
  if (fptr->text) {
    num_chars = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
  }

  if (index < 0) {
    fptr->insert_index = 0;
  }
  else if (index > num_chars) {
    fptr->insert_index = num_chars;
  }
  else {
    fptr->insert_index = index;
  }
}

static int
FieldSelection(ZnFieldSet       fs,
               int      field,
               int      offset,
               char     *chars,
               int      max_bytes)
{
  Field    fptr;
  int      count;
  char  const *sel_first, *sel_last;
  ZnTextInfo *ti;

  if ((field < 0) || ((unsigned int) field >= fs->num_fields)) {
    return 0;
  }
  ti = &fs->item->wi->text_info;
  if ((ti->sel_first < 0) ||
      (ti->sel_first > ti->sel_last)) {
    return 0;
  }
  
  fptr = &fs->fields[field];
  if (!fptr->text) {
    return 0;
  }

  sel_first = Tcl_UtfAtIndex(fptr->text, ti->sel_first);
  sel_last = Tcl_UtfAtIndex(sel_first, ti->sel_last + 1 - ti->sel_first);
  count = sel_last - sel_first - offset;
  if (count <= 0) {
    return 0;
  }
  if (count > max_bytes) {
    count = max_bytes;
  }

  memcpy(chars, sel_first + offset, (size_t) count);
  chars[count] = 0;
  
  return count;
}


/*
 **********************************************************************************
 *
 * ComputeFieldImageLocation -- 
 *      Compute the bounding box of the pixmap in a field. The position is
 *      deduced from the field bounding box passed in bbox.
 *
 **********************************************************************************
 */
static void
ComputeFieldImageLocation(Field         fptr,
                          ZnBBox        *bbox,
                          ZnBBox        *pm_bbox)
{
  int   width, height;

  ZnSizeOfImage(fptr->image, &width, &height);
  pm_bbox->orig.y = (bbox->orig.y + bbox->corner.y - height) / 2;
  pm_bbox->corner.y = pm_bbox->orig.y + height;
  
  switch (fptr->alignment) {
  case TK_JUSTIFY_LEFT:
    pm_bbox->orig.x = bbox->orig.x;
    break;
  case TK_JUSTIFY_RIGHT:
    pm_bbox->orig.x = bbox->corner.x - width - 1;
    break;
  default:
    pm_bbox->orig.x = (bbox->orig.x + bbox->corner.x - width) / 2;
    break;
  }
  pm_bbox->corner.x = pm_bbox->orig.x + width;
}


/*
 **********************************************************************************
 *
 * FieldsEngine -- 
 *
 **********************************************************************************
 */
static void
FieldsEngine(ZnFieldSet field_set,
             void       (*cb)())
{
  ZnWInfo       *wi = field_set->item->wi;
  /*int         i;      This one *NEED* to be an int */
  unsigned int  i, num_fields, num_chars;
  Field         fptr;
  ZnTextInfo    *ti = &wi->text_info;
  ZnBBox        lclip_bbox, fclip_bbox, bbox, *global_clip_box;
  ZnBBox        tmp_bbox, text_bbox, pm_bbox;
  ZnPoint       pts[2];
  ZnTriStrip    tristrip;
  ZnPoint       text_pos;
  ZnBool        restore = False;
  ZnDim         lwidth, lheight;
  ZnReal        val;
  int           cursor;
  int           sel_start, sel_stop;

  if (!field_set->num_fields) {
    return;
  }

  if (field_set->label_format && ZnLFNumFields(field_set->label_format)) {
    bbox.orig.x = ZnNearestInt(field_set->label_pos.x);
    bbox.orig.y = ZnNearestInt(field_set->label_pos.y);
    GetLabelBBox(field_set, &lwidth, &lheight);
    bbox.corner.x = bbox.orig.x + lwidth;
    bbox.corner.y = bbox.orig.y + lheight;
    ZnCurrentClip(wi, NULL, &global_clip_box, NULL);

    if (!wi->render) {
      ZnIntersectBBox(global_clip_box, &bbox, &lclip_bbox);
      if (ZnIsEmptyBBox(&lclip_bbox)) {
        return;
      }
    }
    else {
      lclip_bbox = bbox;
    }

    num_fields = ZnLFNumFields(field_set->label_format);
    for (i = 0; i < num_fields; i++) {
      fptr = &field_set->fields[i];

      if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT)) {
        continue;
      }
      
      GetFieldBBox(field_set, i, &bbox);
      ZnIntersectBBox(&lclip_bbox, &bbox, &fclip_bbox);
      if (ZnIsEmptyBBox(&fclip_bbox)) {
        continue;
      }
      
      /* we must call XSetClipRectangles only if it's required  */
      val = fclip_bbox.orig.x - bbox.orig.x;
      restore = val > 0;
      val = fclip_bbox.orig.y - bbox.orig.y;
      restore |= val > 0;
      val = fclip_bbox.corner.x - bbox.corner.x;
      restore |= val < 0;
      val = fclip_bbox.corner.y - bbox.corner.y;
      restore |= val < 0;

      cursor = ((field_set->item == wi->focus_item) &&
                ((unsigned int) wi->focus_field == i) &&
                ISSET(wi->flags, ZN_GOT_FOCUS) && ti->cursor_on) ? 0 : -1;
      sel_start = -1, sel_stop = -1;
      ComputeFieldTextLocation(fptr, &bbox, &text_pos, &text_bbox);

      if (fptr->text) {
        if (cursor != -1) {
          cursor = Tk_TextWidth(fptr->font, fptr->text,
                                Tcl_UtfAtIndex(fptr->text,
                                               fptr->insert_index)-fptr->text);
        }
        num_chars  = Tcl_NumUtfChars(fptr->text, (int) strlen(fptr->text));
        if (num_chars) {
          if ((field_set->item == ti->sel_item) && ((unsigned int) ti->sel_field == i) &&
              (ti->sel_last >= 0) && (ti->sel_first <= (int) num_chars)) {
            sel_start = Tk_TextWidth(fptr->font, fptr->text,
                                     Tcl_UtfAtIndex(fptr->text,
                                                    ti->sel_first)-fptr->text);
            sel_stop = Tk_TextWidth(fptr->font, fptr->text,
                                    Tcl_UtfAtIndex(fptr->text,
                                                   ti->sel_last)-fptr->text);
          }
          
          ZnIntersectBBox(&fclip_bbox, &text_bbox, &tmp_bbox);
          
          val = tmp_bbox.orig.x - text_bbox.orig.x;
          restore |= val > 0;
          val = tmp_bbox.orig.y - text_bbox.orig.y;
          restore |= val > 0;
          val = tmp_bbox.corner.x - text_bbox.corner.x;
          restore |= val < 0;
          val = tmp_bbox.corner.y - text_bbox.corner.y;
          restore |= val < 0;
        }
      }

      if (fptr->image != ZnUnspecifiedImage) {
        ComputeFieldImageLocation(fptr, &bbox, &pm_bbox);

        ZnIntersectBBox(&fclip_bbox, &pm_bbox, &tmp_bbox);
        
        val = tmp_bbox.orig.x - pm_bbox.orig.x;
        restore |= val > 0;
        val = tmp_bbox.orig.y - pm_bbox.orig.y;
        restore |= val > 0;
        val = tmp_bbox.corner.x - pm_bbox.corner.x;
        restore |= val < 0;
        val = tmp_bbox.corner.y - pm_bbox.corner.y;
        restore |= val < 0;
      }
      
      /*restore = True;*/
      if (restore) {
        /* we must clip. */
        /*printf("clip: %d\n", i);*/
        pts[0] = fclip_bbox.orig;
        pts[1] = fclip_bbox.corner;
        ZnTriStrip1(&tristrip, pts, 2, False);
        ZnPushClip(wi, &tristrip, True, True);
      }

      (*cb)(wi, fptr, &bbox, &pm_bbox,
            &text_pos, &text_bbox, cursor, sel_start, sel_stop);

      if (restore) {
        /* Restore the previous clip. */
        ZnPopClip(wi, True);
        restore = False;
      }
    }
  }
}


/*
 **********************************************************************************
 *
 * DrawFields -- 
 *
 **********************************************************************************
 */
static void
DrawField(ZnWInfo       *wi,
          Field         fptr,
          ZnBBox        *bbox,
          ZnBBox        *pm_bbox,
          ZnPoint       *text_pos,
          ZnBBox        *text_bbox,
          int           cursor,
          int           sel_start,
          int           sel_stop)
{
  ZnTextInfo    *ti = &wi->text_info;
  XGCValues     values;
  XRectangle    r;
  int           j, xs, num_bytes;
  int           pw, ph, fw, fh;
  TkRegion      clip_region;
  ZnBool        simple;
  Pixmap        pixmap;
  TkRegion      photo_region, clip;

  ZnBBox2XRect(bbox, &r);

  /*
   * Draw the background.
   */
  if (ISSET(fptr->flags, FILLED_BIT)) {
    values.foreground = ZnGetGradientPixel(fptr->fill_color, 0.0);
    
    if (fptr->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(fptr->tile)) { /* Fill tiled */
        values.fill_style = FillTiled;
        values.tile = ZnImagePixmap(fptr->tile, wi->win);
        values.ts_x_origin = (int) bbox->orig.x;
        values.ts_y_origin = (int) bbox->orig.y;
        XChangeGC(wi->dpy, wi->gc,
                  GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile,
                  &values);
      }
      else { /* Fill stippled */
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(fptr->tile, wi->win);
        values.ts_x_origin = (int) bbox->orig.x;
        values.ts_y_origin = (int) bbox->orig.y;
        XChangeGC(wi->dpy, wi->gc,
                  GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground,
                  &values);
      }
    }
    else { /* Fill solid */
      values.fill_style = FillSolid;
      XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle, &values);
    }
    XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y, r.width, r.height);
  }
  
  /*
   * Draw the image and the text, which is in back depends on
   * the value of text_on_top.
   */
  for (j = 0; j < 2; j++) {
    if ((j == 0 && ISSET(fptr->flags, TEXT_ON_TOP_BIT)) ||
        (j == 1 && ISCLEAR(fptr->flags, TEXT_ON_TOP_BIT))) {
      /*
       * Draw the image.
       */
      if (fptr->image != ZnUnspecifiedImage) {
        pw = ZnNearestInt(pm_bbox->corner.x - pm_bbox->orig.x);
        ph = ZnNearestInt(pm_bbox->corner.y - pm_bbox->orig.y);
        fw = ZnNearestInt(bbox->corner.x - bbox->orig.x);
        fh = ZnNearestInt(bbox->corner.y - bbox->orig.y);

        pixmap = ZnImagePixmap(fptr->image, wi->win);
        photo_region = ZnImageRegion(fptr->image);
        ZnCurrentClip(wi, &clip_region, NULL, &simple);
        clip = TkCreateRegion();
        /*
         * ZnImageRegion may fail: perl/Tk 800.24 doesn't support
         * some internal TkPhoto functions.
         * This is a workaround using a rectangular region based
         * on the image size.
         */
        if (photo_region == NULL) {
          XRectangle rect;
          rect.x = rect.y = 0;
          rect.width = pw;
          rect.height = ph;
          TkUnionRectWithRegion(&rect, clip, clip);
        }
        else {
          ZnUnionRegion(clip, photo_region, clip);
        }
        ZnOffsetRegion(clip, (int) pm_bbox->orig.x, (int) pm_bbox->orig.y);
        TkIntersectRegion(clip_region, clip, clip);
        TkSetRegion(wi->dpy, wi->gc, clip);
        XCopyArea(wi->dpy, pixmap, wi->draw_buffer, wi->gc,
                  (int) ZnNearestInt(bbox->orig.x-pm_bbox->orig.x),
                  (int) ZnNearestInt(bbox->orig.y-pm_bbox->orig.y),
                  (unsigned int) MIN(pw, fw),
                  (unsigned int) MIN(ph, fh),
                  (int) MAX(bbox->orig.x, pm_bbox->orig.x),
                  (int) MAX(bbox->orig.y, pm_bbox->orig.y));

        TkSetRegion(wi->dpy, wi->gc, clip_region);
        TkDestroyRegion(clip);
      }
    }
    else if (fptr->text) {
      /*
       * Draw the text.
       */
      num_bytes = strlen(fptr->text);
      if (num_bytes) {
        if (sel_start >= 0) {
          values.foreground = ZnGetGradientPixel(ti->sel_color, 0.0);
          values.fill_style = FillSolid;
          XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle, &values);
          XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
                         (int) (text_bbox->orig.x+sel_start),
                         (int) text_bbox->orig.y,
                         (unsigned int) (sel_stop-sel_start),
                         (unsigned int) (text_bbox->corner.y-text_bbox->orig.y));
        }
        values.foreground = ZnGetGradientPixel(fptr->color, 0.0);
        values.fill_style = FillSolid;
        values.font = Tk_FontId(fptr->font);
        XChangeGC(wi->dpy, wi->gc, GCForeground | GCFillStyle | GCFont, &values);
        Tk_DrawChars(wi->dpy, wi->draw_buffer, wi->gc, fptr->font,
                     fptr->text, num_bytes, (int) text_pos->x, (int) text_pos->y);
      }
    }
  }
  if (cursor >= 0) {
    values.line_width = ti->insert_width;
    values.foreground = ZnGetGradientPixel(ti->insert_color, 0.0);
    values.fill_style = FillSolid;
    XChangeGC(wi->dpy, wi->gc, GCForeground|GCLineWidth|GCFillStyle, &values);
    xs = (int) text_bbox->orig.x + cursor;
    XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
              xs, (int) text_bbox->orig.y,
              xs, (int) text_bbox->corner.y);
  }
  
  /*
   * Draw the border relief.
   */
  if ((fptr->relief != ZN_RELIEF_FLAT) && (fptr->relief_thickness > 1)) {
    ZnDrawRectangleRelief(wi, fptr->relief, fptr->gradient,
                          &r, fptr->relief_thickness);
  }
  
  /*
   * Draw the border line.
   */
  if (fptr->border_edges != ZN_NO_BORDER) {
    values.foreground = ZnGetGradientPixel(fptr->border_color, 0.0);
    values.line_width = 1;
    values.line_style = LineSolid;
    values.fill_style = FillSolid;
    XChangeGC(wi->dpy, wi->gc,
              GCForeground | GCLineWidth | GCLineStyle | GCFillStyle, &values);
    if (fptr->border_edges & ZN_LEFT_BORDER) {
      XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
                r.x, r.y + r.height - 1);
    }
    if (fptr->border_edges & ZN_RIGHT_BORDER) {
      XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, 
                r.x + r.width - 1, r.y,
                r.x + r.width - 1, r.y + r.height - 1);
    }
    if (fptr->border_edges & ZN_TOP_BORDER) {
      XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, 
                r.x, r.y, r.x + r.width - 1, r.y);
    }
    if (fptr->border_edges & ZN_BOTTOM_BORDER) {
      XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, 
                r.x, r.y + r.height - 1,
                r.x + r.width - 1, r.y + r.height - 1);
    }
    if (fptr->border_edges & ZN_OBLIQUE) {
      XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, 
                r.x, r.y, r.x + r.width - 1, r.y + r.height - 1);
    }
    if (fptr->border_edges & ZN_COUNTER_OBLIQUE) {
      XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, 
                r.x, r.y + r.height - 1,
                r.x + r.width - 1, r.y);
    }
  }
}

static void
DrawFields(ZnFieldSet   field_set)
{
  FieldsEngine(field_set, DrawField);
}


/*
 **********************************************************************************
 *
 * RenderFields -- 
 *
 **********************************************************************************
 */
#ifdef GL
static void
FieldRenderCB(void *closure)
{
  ZnBBox *bbox = (ZnBBox *) closure;
  
  glBegin(GL_QUADS);
  glVertex2d(bbox->orig.x, bbox->orig.y);
  glVertex2d(bbox->orig.x, bbox->corner.y);
  glVertex2d(bbox->corner.x, bbox->corner.y);
  glVertex2d(bbox->corner.x, bbox->orig.y);
  glEnd();
}

static void
RenderField(ZnWInfo     *wi,
            Field       fptr,
            ZnBBox      *bbox,
            ZnBBox      *pm_bbox,
            ZnPoint     *text_pos,
            ZnBBox      *text_bbox,
            int         cursor,
            int         sel_start,
            int         sel_stop)
{
  unsigned short alpha;
  unsigned int  j, num_bytes;
  XColor        *color;
  ZnReal        xs;
  ZnTextInfo    *ti = &wi->text_info;

  /*
   * Draw the background.
   */
  if (ISSET(fptr->flags, FILLED_BIT)) {
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    if (!ZnGradientFlat(fptr->fill_color)) {
#if 0 /* TODO_GL Faire le dégradé dans le fond des champs. */
      int       type = fptr->fill_color->type;
      ZnBool    fast = (type == ZN_AXIAL_GRADIENT) && !fptr->grad_geo;

      RenderGradient(wi, fptr->fill_color,
                     fast ? NULL : FieldRenderCB,
                     bbox, fast ? (ZnPoint *) bbox : fptr->grad_geo);
#endif
    }
    else {
      if (fptr->tile != ZnUnspecifiedImage) { /* Fill tiled/stippled */
        ZnRenderTile(wi, fptr->tile, fptr->fill_color, FieldRenderCB, bbox,
                     (ZnPoint *) bbox);
      }
      else { /* Fill solid */
        color = ZnGetGradientColor(fptr->fill_color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
        FieldRenderCB(bbox);
      }
    }
  }

  /*
   * Draw the image and the text, which one is back depends on
   * the value of text_on_top.
   */
  for (j = 0; j < 2; j++) {
    if ((j == 0 && ISSET(fptr->flags, TEXT_ON_TOP_BIT)) ||
        (j == 1 && ISCLEAR(fptr->flags, TEXT_ON_TOP_BIT))) {
      /*
       * Draw the image.
       */
      if (fptr->image != ZnUnspecifiedImage) {
        ZnRenderIcon(wi, fptr->image, fptr->fill_color,
                     &pm_bbox->orig, False);
      }
    }
    else if (fptr->text) {
      /*
       * Draw the text.
       */
      num_bytes = strlen(fptr->text);
      if (num_bytes) {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        if (sel_start >= 0) {
          color = ZnGetGradientColor(ti->sel_color, 0.0, &alpha);
          alpha = ZnComposeAlpha(alpha, wi->alpha);
          glColor4us(color->red, color->green, color->blue, alpha);
          glBegin(GL_QUADS);
          glVertex2d(text_bbox->orig.x+sel_start, text_bbox->orig.y);
          glVertex2d(text_bbox->orig.x+sel_stop, text_bbox->orig.y);
          glVertex2d(text_bbox->orig.x+sel_stop, text_bbox->corner.y);
          glVertex2d(text_bbox->orig.x+sel_start, text_bbox->corner.y);
          glEnd();
        }
        glEnable(GL_TEXTURE_2D);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        color = ZnGetGradientColor(fptr->color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
        glBindTexture(GL_TEXTURE_2D, ZnTexFontTex(fptr->tfi));
        glPushMatrix();
        glTranslated(text_pos->x, text_pos->y, 0.0);
        ZnRenderString(fptr->tfi, (unsigned char *) fptr->text, num_bytes);
        glPopMatrix();
        glDisable(GL_TEXTURE_2D);
      }
    }
    if (cursor >= 0) {
      glLineWidth((GLfloat) ti->insert_width);
      color = ZnGetGradientColor(ti->insert_color, 0.0, &alpha);
      alpha = ZnComposeAlpha(alpha, wi->alpha);
      glColor4us(color->red, color->green, color->blue, alpha);
      xs = text_bbox->orig.x + cursor;
      glBegin(GL_LINES);
      glVertex2d(xs, text_bbox->orig.y);
      glVertex2d(xs, text_bbox->corner.y);
      glEnd();
    }
  }
  
  /*
   * Draw the border relief.
   */  
  if ((fptr->relief != ZN_RELIEF_FLAT) && (fptr->relief_thickness > 1)) {
    ZnPoint p[5];

    p[0].x = bbox->orig.x;
    p[0].y = bbox->orig.y;
    p[2].x = bbox->corner.x;
    p[2].y = bbox->corner.y;
    p[1].x = p[0].x;
    p[1].y = p[2].y;
    p[3].x = p[2].x;
    p[3].y = p[0].y;
    p[4] = p[0];
    ZnRenderPolygonRelief(wi, fptr->relief, fptr->gradient,
                          False, p, 5, fptr->relief_thickness);
  }

  /*
   * Draw the border line.
   */
  if (fptr->border_edges != ZN_NO_BORDER) {
    color = ZnGetGradientColor(fptr->border_color, 0.0, &alpha);
    alpha = ZnComposeAlpha(alpha, wi->alpha);
    glColor4us(color->red, color->green, color->blue, alpha);
    glLineWidth(1.5);
    ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
    glBegin(GL_LINES);
    if (fptr->border_edges & ZN_LEFT_BORDER) {
      glVertex2d(bbox->orig.x, bbox->orig.y);
      glVertex2d(bbox->orig.x, bbox->corner.y);
    }
    if (fptr->border_edges & ZN_RIGHT_BORDER) {
      glVertex2d(bbox->corner.x, bbox->orig.y);
      glVertex2d(bbox->corner.x, bbox->corner.y);
    }
    if (fptr->border_edges & ZN_TOP_BORDER) {
      glVertex2d(bbox->orig.x, bbox->orig.y);
      glVertex2d(bbox->corner.x, bbox->orig.y);
    }
    if (fptr->border_edges & ZN_BOTTOM_BORDER) {
      glVertex2d(bbox->orig.x, bbox->corner.y);
      glVertex2d(bbox->corner.x, bbox->corner.y);
    }
    if (fptr->border_edges & ZN_OBLIQUE) {
      glVertex2d(bbox->orig.x, bbox->orig.y);
      glVertex2d(bbox->corner.x, bbox->corner.y);
    }
    if (fptr->border_edges & ZN_COUNTER_OBLIQUE) {
      glVertex2d(bbox->orig.x, bbox->corner.y);
      glVertex2d(bbox->corner.x, bbox->orig.y);
    }
    glEnd();
  }
}
#endif

#ifdef GL
static void
RenderFields(ZnFieldSet field_set)
{
  /*  glDisable(GL_LINE_SMOOTH);*/
  FieldsEngine(field_set, RenderField);
  /*  glEnable(GL_LINE_SMOOTH);*/
}
#else
static void
RenderFields(ZnFieldSet field_set)
{
}
#endif


/*
 **********************************************************************************
 *
 * PostScriptFields --
 *
 **********************************************************************************
 */
static int
PsField(ZnWInfo *wi,
        ZnBool  prepass,
        Field   fptr,
        ZnBBox  *bbox,
        ZnBBox  *pm_bbox,
        ZnPoint *text_pos,
        ZnBBox  *text_bbox)
{
  int j;
  char path[250];

  /*
   * Must set the clip rect for the whole field, not only for stipple fill.
   */
  if (ISSET(fptr->flags, FILLED_BIT)) {
    if (fptr->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(fptr->tile)) { /* Fill tiled */
        /* TODO No support yet */
      }
      else { /* Fill stippled */
        Tcl_AppendResult(wi->interp, "gsave\n", NULL);
        if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                               ZnGetGradientColor(fptr->fill_color, 0.0, NULL)) != TCL_OK) {
          return TCL_ERROR;
        }
        if (Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
                                 ZnImagePixmap(fptr->tile, wi->win)) != TCL_OK) {
          return TCL_ERROR;
        }
        Tcl_AppendResult(wi->interp, "grestore\n", NULL);
      }
    }
    else { /* Fill solid */
      if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                             ZnGetGradientColor(fptr->fill_color, 0.0, NULL)) != TCL_OK) {
        return TCL_ERROR;
      }
      Tcl_AppendResult(wi->interp, "fill\n", NULL);
    }
  }

  /*
   * Draw the image and the text, which is in back depends on
   * the value of text_on_top.
   */
  for (j = 0; j < 2; j++) {
    if ((j == 0 && ISSET(fptr->flags, TEXT_ON_TOP_BIT)) ||
        (j == 1 && ISCLEAR(fptr->flags, TEXT_ON_TOP_BIT))) {
      /*
       * Draw the image.
       */
      if (fptr->image != ZnUnspecifiedImage) {
	int w, h;

        Tcl_AppendResult(wi->interp, "gsave\n", NULL);
        sprintf(path, "%.15g %.15g translate 1 -1 scale\n",
                pm_bbox->orig.x, pm_bbox->corner.y);
        Tcl_AppendResult(wi->interp, path, NULL);
        w = ZnNearestInt(pm_bbox->corner.x - pm_bbox->orig.x);
        h = ZnNearestInt(pm_bbox->corner.y - pm_bbox->orig.y);
        if (Tk_PostscriptImage(ZnImageTkImage(fptr->image), wi->interp, wi->win,
                               wi->ps_info, 0, 0, w, h, prepass) != TCL_OK) {
          return TCL_ERROR;
        }
        Tcl_AppendResult(wi->interp, "grestore\n", NULL);
      }
    }
    else if (fptr->text) {
      Tcl_AppendResult(wi->interp, "gsave\n", NULL);
      if (Tk_PostscriptFont(wi->interp, wi->ps_info, fptr->font) != TCL_OK) {
        return TCL_ERROR;
      }
      if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                             ZnGetGradientColor(fptr->color, 0.0, NULL)) != TCL_OK) {
        return TCL_ERROR;
      }
      /*
       * TODO pourquoi la text_bbox ne donne pas un texte centré verticalement ?
       * Apparement la fonte PostScript n'est pas centrée comme la fonte X.
       * Il faut donc opérer le calcul dans le code PostScript de DrawText.
       */
      sprintf(path, "%.15g %.15g translate 1 -1 scale 0 0 [\n",
              text_bbox->orig.x, text_bbox->orig.y);
      Tcl_AppendResult(wi->interp, path, NULL);
      /*
       * strlen should do the work of counting _bytes_ in the utf8 string.
       */
      ZnPostscriptString(wi->interp, fptr->text, strlen(fptr->text));
      Tcl_AppendResult(wi->interp, "] 0 0.0 0.0 0.0 false DrawText\n", NULL);
      Tcl_AppendResult(wi->interp, "grestore\n", NULL);
    }
  }

  /*
   * Draw the border relief.
   */
  if ((fptr->relief != ZN_RELIEF_FLAT) && (fptr->relief_thickness > 1)) {
  }

  /*
   * Draw the border line.
   */
  if (fptr->border_edges != ZN_NO_BORDER) {
    if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                           ZnGetGradientColor(fptr->border_color, 0.0, NULL)) != TCL_OK) {
      return TCL_ERROR;
    }
    Tcl_AppendResult(wi->interp, "1 setlinewidth 0 setlinejoin 2 setlinecap\n", NULL);
    if (fptr->border_edges & ZN_LEFT_BORDER) {
      sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
              bbox->orig.x, bbox->orig.y, bbox->orig.x, bbox->corner.y);
      Tcl_AppendResult(wi->interp, path, NULL);
    }
    if (fptr->border_edges & ZN_RIGHT_BORDER) {
      sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
              bbox->corner.x, bbox->orig.y, bbox->corner.x, bbox->corner.y);
      Tcl_AppendResult(wi->interp, path, NULL);
    }
    if (fptr->border_edges & ZN_TOP_BORDER) {
      sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
              bbox->orig.x, bbox->orig.y, bbox->corner.x, bbox->orig.y);
      Tcl_AppendResult(wi->interp, path, NULL);
    }
    if (fptr->border_edges & ZN_BOTTOM_BORDER) {
      sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
              bbox->orig.x, bbox->corner.y, bbox->corner.x, bbox->corner.y);
      Tcl_AppendResult(wi->interp, path, NULL);
    }
    if (fptr->border_edges & ZN_OBLIQUE) {
      sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
              bbox->orig.x, bbox->orig.y, bbox->corner.x, bbox->corner.y);
      Tcl_AppendResult(wi->interp, path, NULL);
    }
    if (fptr->border_edges & ZN_COUNTER_OBLIQUE) {
      sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto stroke\n",
              bbox->corner.x, bbox->orig.y, bbox->orig.x, bbox->corner.y);
      Tcl_AppendResult(wi->interp, path, NULL);
    }
  }

  return TCL_OK;
}

static int
PostScriptFields(ZnFieldSet field_set,
                 ZnBool     prepass,
                 ZnBBox     *area)
{
  ZnWInfo *wi = field_set->item->wi;
  ZnBBox  lclip_bbox, fclip_bbox;
  ZnBBox  bbox, text_bbox, pm_bbox;
  ZnPoint text_pos;
  int     i, num_fields;
  ZnDim   lwidth, lheight;
  Field   fptr;
  char    path[250];
  
  if (!field_set->num_fields) {
    return TCL_OK;
  }


  if (field_set->label_format && ZnLFNumFields(field_set->label_format)) {
    /*
     * Fields are drawn with respect to a point already converted
     * to device space, so we need to reinstate the initial transform.
     */
    Tcl_AppendResult(wi->interp, "/InitialTransform load setmatrix\n", NULL);

    lclip_bbox.orig.x = ZnNearestInt(field_set->label_pos.x);
    lclip_bbox.orig.y = ZnNearestInt(field_set->label_pos.y);
    GetLabelBBox(field_set, &lwidth, &lheight);
    lclip_bbox.corner.x = lclip_bbox.orig.x + lwidth;
    lclip_bbox.corner.y = lclip_bbox.orig.y + lheight;
    
    num_fields = ZnLFNumFields(field_set->label_format);
    for (i = 0; i < num_fields; i++) {
      fptr = &field_set->fields[i];

      if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT)) {
        continue;
      }
      
      GetFieldBBox(field_set, i, &bbox);
      ZnIntersectBBox(&lclip_bbox, &bbox, &fclip_bbox);
      if (ZnIsEmptyBBox(&fclip_bbox)) {
        /* The field is outside the label bbox */
        continue;
      }
      
      /*
       * Setup a clip area around the field
       */
      Tcl_AppendResult(wi->interp, "gsave\n", NULL);
      sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto %.15g %.15g lineto %.15g %.15g",
              fclip_bbox.orig.x, fclip_bbox.orig.y, fclip_bbox.corner.x+1, fclip_bbox.orig.y,
              fclip_bbox.corner.x+1, fclip_bbox.corner.y+1, fclip_bbox.orig.x,
              fclip_bbox.corner.y+1);
      Tcl_AppendResult(wi->interp, path, " lineto closepath clip\n", NULL);

      if (fptr->text) {
        ComputeFieldTextLocation(fptr, &bbox, &text_pos, &text_bbox);
      }
      if (fptr->image != ZnUnspecifiedImage) {
        ComputeFieldImageLocation(fptr, &bbox, &pm_bbox);
      }

      if (PsField(wi, prepass, fptr, &bbox, &pm_bbox, &text_pos, &text_bbox) != TCL_OK) {
        return TCL_ERROR;
      }

      Tcl_AppendResult(wi->interp, "grestore\n", NULL);
    }
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * IsFieldsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsFieldSensitive(ZnFieldSet     field_set,
                 int            part)
{
  if ((part >= 0) && ((unsigned int) part < field_set->num_fields)) {
    return ISSET(field_set->fields[part].flags, FIELD_SENSITIVE_BIT);
  }
  else {
    return False;
  }
}


/*
 **********************************************************************************
 *
 * FieldsPick --
 *      Return the first field that contains <x, y>.
 *      A field is selected if <x, y> is over a non transparent area.
 *      Such areas are : a solid filled background, a text, an icon.
 *      This does *NOT* do with *GLOBAL* visible and sensitive.
 *      But we need to take into account local field visible and
 *      sensitive as they modifiy local transparency. Local means
 *      within a single item.
 *
 **********************************************************************************
 */
static double
FieldsPick(ZnFieldSet   field_set,
           ZnPoint      *p,
           int          *part)
{
  Field         fptr;
  ZnBBox        bbox;
  unsigned int  best_field = 0;
  int           i;
  ZnReal        new_dist, dist = 1e40;

  if (!field_set->num_fields) {
    return dist;
  }

  if (field_set->label_format) {
    for (i = ZnLFNumFields(field_set->label_format)-1; i >= 0; i--) {    
      fptr = &field_set->fields[i];
      
      if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT) &&
          ISCLEAR(fptr->flags, FIELD_SENSITIVE_BIT)) {
        continue;
      }
      
      GetFieldBBox(field_set, (unsigned int) i, &bbox);

      new_dist = ZnRectangleToPointDist(&bbox, p);
      if (new_dist < dist) {
        dist = new_dist;
        best_field = i;
      }
      if (dist <= 0.0) {
        dist = 0.0;
        break;
      }
    }
  }
  
  *part = best_field;
  return dist;
}


/*
 **********************************************************************************
 *
 * FieldsToArea --
 *      Return -1 if no field is in the given area, 1 if they are
 *      all in it or 0 if there is some overlap. The function consider
 *      only fields that are either sensible or visible.
 *
 **********************************************************************************
 */
static int
FieldsToArea(ZnFieldSet field_set,
             ZnBBox     *area)
{
  Field         fptr;
  ZnBBox        bbox;
  int           i, inside = -1;
  ZnBool        first_done = False;
  
  if (!field_set->num_fields) {
    return inside;
  }

  for (i = ZnLFNumFields(field_set->label_format)-1; i >= 0; i--) {
    fptr = &field_set->fields[i];

    if (ISCLEAR(fptr->flags, FIELD_VISIBLE_BIT) &&
        ISCLEAR(fptr->flags, FIELD_SENSITIVE_BIT)) {
      continue;
    }

    GetFieldBBox(field_set, (unsigned int) i, &bbox);
    if (!first_done) {
      first_done = True;
      inside = ZnBBoxInBBox(&bbox, area);
      if (inside == 0) {
        return 0;
      }
    }
    else {
      if (ZnBBoxInBBox(&bbox, area) != inside) {
        return 0;
      }
    }
  }

  return inside;
}


/*
 **********************************************************************************
 *
 * SetFieldsAutoAlign --
 *
 **********************************************************************************
 */
static void
SetFieldsAutoAlign(ZnFieldSet   fs,
                   int          alignment)
{
  unsigned int  i;
  Field         field;

  if (!fs->num_fields) {
    return;
  }
  if ((alignment >= ZN_AA_LEFT) && (alignment <= ZN_AA_RIGHT)) {
    for (i = 0; i < fs->num_fields; i++) {
      field = &fs->fields[i];
      if (field->auto_alignment.automatic) {
        field->alignment = field->auto_alignment.align[alignment];
      }
    }
  }
}

static char *
GetFieldStruct(ZnFieldSet       fs,
               int              field)
{
  if ((unsigned int) field >= fs->num_fields) {
    return NULL;
  }
  return (char *) &fs->fields[field];
}


static unsigned int
NumFields(ZnFieldSet    fs)
{
  return fs->num_fields;
}


struct _ZnFIELD ZnFIELD = {
  field_attrs,

  InitFields,
  CloneFields,
  FreeFields,
  ConfigureField,
  QueryField,
  DrawFields,
  RenderFields,
  PostScriptFields,
  FieldsToArea,
  IsFieldSensitive,
  FieldsPick,
  FieldIndex,
  FieldInsertChars,
  FieldDeleteChars,
  FieldCursor,
  FieldSelection,
  LeaderToLabel,
  GetLabelBBox,
  GetFieldBBox,
  SetFieldsAutoAlign,
  ClearFieldCache,
  GetFieldStruct,
  NumFields
};

Added jni/tkzinc/generic/Field.h.











































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
 * Field.h -- Header for field item parts.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 2002 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Field_h
#define _Field_h

#include "Attrs.h"
#include "Types.h"
#include "List.h"
#include "Color.h"
#include "Image.h"


struct _ZnItemStruct;
struct _ZnAttrConfig;


/*
 * Field array management record.
 *
 *   This structure should be used only for internal
 * management by items with fields. The rest of the code
 * should use the methods in FIELD.
 *
 */
typedef struct _ZnFieldSetStruct {
  struct _ZnItemStruct  *item;
  ZnLabelFormat         label_format;
  unsigned int          num_fields;
  struct _FieldStruct   *fields;
  ZnDim                 label_width;    /* Describe the label size. Access these */
  ZnDim                 label_height;   /* 2 only with GetLabelBBox. -1 means
                                         * not up to date. */
  ZnPoint               label_pos;      /* Describe the label origin. */
} ZnFieldSetStruct, *ZnFieldSet;


extern struct _ZnFIELD {
  struct _ZnAttrConfig  *attr_desc;

  void (*InitFields)(ZnFieldSet fs);
  void (*CloneFields)(ZnFieldSet fs);
  void (*FreeFields)(ZnFieldSet fs);
  int (*ConfigureField)(ZnFieldSet fs, int field, int argc, Tcl_Obj *CONST argv[], int *flags);
  int (*QueryField)(ZnFieldSet fs, int field, int argc, Tcl_Obj *CONST argv[]);
  void (*DrawFields)(ZnFieldSet fs);
  void (*RenderFields)(ZnFieldSet fs);
  int (*PostScriptFields)(ZnFieldSet fs, ZnBool prepass, ZnBBox *area);
  int (*FieldsToArea)(ZnFieldSet fs, ZnBBox *area);
  ZnBool (*IsFieldSensitive)(ZnFieldSet fs, int part);
  double (*FieldsPick)(ZnFieldSet fs, ZnPoint *p, int *part);
  int (*FieldIndex)(ZnFieldSet fs, int field, Tcl_Obj *index_spec, int *index);
  ZnBool (*FieldInsertChars)(ZnFieldSet fs, int field, int *index, char *chars);
  ZnBool (*FieldDeleteChars)(ZnFieldSet fs, int field,
                             int *first, int *last);
  void (*FieldCursor)(ZnFieldSet fs, int field, int index);
  int (*FieldSelection)(ZnFieldSet fs, int field, int offset,
                        char *chars, int max_chars);
  void (*LeaderToLabel)(ZnFieldSet fs, ZnPoint *start, ZnPoint *end);
  void (*GetLabelBBox)(ZnFieldSet fs, ZnDim *w, ZnDim *h);
  void (*GetFieldBBox)(ZnFieldSet fs, unsigned int index,
                       ZnBBox *field_bbox);
  void (*SetFieldsAutoAlign)(ZnFieldSet fs, int alignment);
  void (*ClearFieldCache)(ZnFieldSet fs, int field);
  char *(*GetFieldStruct)(ZnFieldSet fs, int field);
  unsigned int (*NumFields)(ZnFieldSet fs);
} ZnFIELD;


#endif /* _Field_h */

Added jni/tkzinc/generic/Geo.c.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
/*
 * Geo.c -- Implementation of common geometric routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
 * Much of the code here is inspired by (or copied from) the Tk code.
 */


#include "Geo.h"
#include "WidgetInfo.h"

#include <memory.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


void
ZnPolyInit(ZnPoly       *poly)
{
  poly->num_contours = 0;
  poly->contours = NULL;
}

void
ZnPolyContour1(ZnPoly           *poly,
               ZnPoint          *pts,
               unsigned int     num_pts,
               ZnBool           cw)
{
  poly->num_contours = 1;
  poly->contours = &poly->contour1;
  poly->contour1.num_points = num_pts;
  poly->contour1.points = pts;
  poly->contour1.cw = cw;
  poly->contour1.controls = NULL;
}

void
ZnPolySet(ZnPoly        *poly1,
          ZnPoly        *poly2)
{
  ZnPolyFree(poly1);
  if (poly2->num_contours == 1) {
    ZnPolyContour1(poly1, poly2->contours[0].points, poly2->contours[0].num_points,
                   poly2->contours[0].cw);
    if (poly2->contours != &poly2->contour1) {
      ZnFree(poly2->contours);
    }
  }
  else {
    poly1->num_contours = poly2->num_contours;
    poly1->contours = poly2->contours;
  }
}

void
ZnPolyFree(ZnPoly       *poly)
{
  if (poly->num_contours) {
    unsigned int i;
    for (i = 0; i < poly->num_contours; i++) {
      ZnFree(poly->contours[i].points);
/*      if (poly->contours[i].controls) {
          ZnFree(poly->contours[i].controls);
      }*/
    }
    if (poly->contours != &poly->contour1) {
      ZnFree(poly->contours);
    }
    poly->num_contours = 0;
    poly->contours = NULL;
  }
}

void
ZnTriStrip1(ZnTriStrip          *tristrip,
            ZnPoint             *pts,
            unsigned int        num_pts,
            ZnBool              fan)
{
  tristrip->num_strips = 1;
  tristrip->strips = &tristrip->strip1;
  tristrip->strip1.points = pts;
  tristrip->strip1.num_points = num_pts;
  tristrip->strip1.fan = fan;
}

void
ZnTriFree(ZnTriStrip    *tristrip)
{
  if (tristrip->num_strips) {
    unsigned int i;
    for (i = 0; i < tristrip->num_strips; i++) {
      ZnFree(tristrip->strips[i].points);
    }
    if (tristrip->strips != &tristrip->strip1) {
      ZnFree(tristrip->strips);
    }
    tristrip->num_strips = 0;
    tristrip->strips = NULL;
  }
}

/*
 * Compute the origin of the rectangle given
 * by position, anchor, width and height.
 */
void
ZnAnchor2Origin(ZnPoint         *position,
                ZnDim           width,
                ZnDim           height,
                Tk_Anchor       anchor,
                ZnPoint         *origin)
{
  switch (anchor) {
  case TK_ANCHOR_CENTER:
    origin->x = position->x - width/2;
    origin->y = position->y - height/2;
    break;
  case TK_ANCHOR_NW:
    *origin = *position;
    break;
  case TK_ANCHOR_N:
    origin->x = position->x - width/2;
    origin->y = position->y;
    break;
  case TK_ANCHOR_NE:
    origin->x = position->x - width;
    origin->y = position->y;
    break;
  case TK_ANCHOR_E:
    origin->x = position->x - width;
    origin->y = position->y - height/2;
    break;
  case TK_ANCHOR_SE:
    origin->x = position->x - width;
    origin->y = position->y - height;
    break;
  case TK_ANCHOR_S:
    origin->x = position->x - width/2;
    origin->y = position->y - height;
    break;
  case TK_ANCHOR_SW:
    origin->x = position->x;
    origin->y = position->y - height;
    break;
  case TK_ANCHOR_W:
    origin->x = position->x;
    origin->y = position->y - height/2;
    break;
  }
}


/*
 * Compute the anchor position given the bbox origin, width,
 * height and the anchor.
 */
void
ZnOrigin2Anchor(ZnPoint         *origin,
                ZnDim           width,
                ZnDim           height,
                Tk_Anchor       anchor,
                ZnPoint         *position)
{
  switch (anchor) {
  case TK_ANCHOR_CENTER:
    position->x = origin->x + width/2;
    position->y = origin->y + height/2;
    break;
  case TK_ANCHOR_NW:
    *position = *origin;
    break;
  case TK_ANCHOR_N:
    position->x = origin->x + width/2;
    position->y = origin->y;
    break;
  case TK_ANCHOR_NE:
    position->x = origin->x + width;
    position->y = origin->y;
    break;
  case TK_ANCHOR_E:
    position->x = origin->x + width;
    position->y = origin->y + height/2;
    break;
  case TK_ANCHOR_SE:
    position->x = origin->x + width;
    position->y = origin->y + height;
    break;
  case TK_ANCHOR_S:
    position->x = origin->x + width/2;
    position->y = origin->y + height;
    break;
  case TK_ANCHOR_SW:
    position->x = origin->x;
    position->y = origin->y + height;
    break;
  case TK_ANCHOR_W:
    position->x = origin->x;
    position->y = origin->y + height/2;
    break;
  }
}

/*
 * Compute the anchor position given a rectangle and
 * the anchor. The rectangle vertices must be ordered
 * as for a triangle strip: 
 *
 *    v0 ------------ v2
 *       |          |
 *       |          |
 *    v1 ------------ v3
 */
void
ZnRectOrigin2Anchor(ZnPoint     *rect,
                    Tk_Anchor   anchor,
                    ZnPoint     *position)
{
  switch (anchor) {
  case TK_ANCHOR_CENTER:
    position->x = (rect[0].x + rect[3].x) / 2.0;
    position->y = (rect[0].y + rect[3].y) / 2.0;
    break;
  case TK_ANCHOR_NW:
    *position = *rect;
    break;
  case TK_ANCHOR_N:
    position->x = (rect[0].x + rect[2].x) / 2.0;
    position->y = (rect[0].y + rect[2].y) / 2.0;
    break;
  case TK_ANCHOR_NE:
    *position = rect[2];
    break;
  case TK_ANCHOR_E:
    position->x = (rect[2].x + rect[3].x) / 2.0;
    position->y = (rect[2].y + rect[3].y) / 2.0;
    break;
  case TK_ANCHOR_SE:
    *position = rect[3];
    break;
  case TK_ANCHOR_S:
    position->x = (rect[1].x + rect[3].x) / 2.0;
    position->y = (rect[1].y + rect[3].y) / 2.0;
    break;
  case TK_ANCHOR_SW:
    *position = rect[1];
    break;
  case TK_ANCHOR_W:
    position->x = (rect[0].x + rect[1].x) / 2.0;
    position->y = (rect[0].y + rect[1].y) / 2.0;
    break;
  }
}

void
ZnBBox2XRect(ZnBBox     *bbox,
             XRectangle *r)
{
  r->x = ZnNearestInt(bbox->orig.x);
  r->y = ZnNearestInt(bbox->orig.y);
  r->width = ZnNearestInt(bbox->corner.x) - r->x;
  r->height = ZnNearestInt(bbox->corner.y) - r->y;
}


void
ZnGetStringBBox(char    *str,
                Tk_Font font,
                ZnPos   x,
                ZnPos   y,
                ZnBBox  *str_bbox)
{
  Tk_FontMetrics fm;

  str_bbox->orig.x = x;
  str_bbox->corner.x  = x + Tk_TextWidth(font, str, (int) strlen(str));
  Tk_GetFontMetrics(font, &fm);
  str_bbox->orig.y = y - fm.ascent;
  str_bbox->corner.y = str_bbox->orig.y + fm.ascent + fm.descent;
}


void
ZnResetBBox(ZnBBox *bbox)
{
  bbox->orig.x = bbox->orig.y = 0;
  bbox->corner = bbox->orig;
}


void
ZnCopyBBox(ZnBBox *bbox_from,
           ZnBBox *bbox_to)
{
  bbox_to->orig = bbox_from->orig;
  bbox_to->corner = bbox_from->corner;
}


void
ZnIntersectBBox(ZnBBox *bbox1,
                ZnBBox *bbox2,
                ZnBBox *bbox_inter)
{
  if ((bbox1->corner.x < bbox2->orig.x) ||
      (bbox1->corner.y < bbox2->orig.y) ||
      (bbox2->corner.x < bbox1->orig.x) ||
      (bbox2->corner.y < bbox1->orig.y)) {
    ZnResetBBox(bbox_inter);
  }
  else {
    bbox_inter->orig.x = MAX(bbox1->orig.x, bbox2->orig.x);
    bbox_inter->orig.y = MAX(bbox1->orig.y, bbox2->orig.y);
    bbox_inter->corner.x = MIN(bbox1->corner.x, bbox2->corner.x);
    bbox_inter->corner.y = MIN(bbox1->corner.y, bbox2->corner.y);
  }
}


ZnBool
ZnIsEmptyBBox(ZnBBox *bbox)
{
  return (bbox->orig.x >= bbox->corner.x) || (bbox->orig.y >= bbox->corner.y);
}


void
ZnAddBBoxToBBox(ZnBBox *bbox,
                ZnBBox *bbox2)
{
  if (ZnIsEmptyBBox(bbox2)) {
    return;
  }
  if (ZnIsEmptyBBox(bbox)) {
    ZnCopyBBox(bbox2, bbox);
  }
  else {
    bbox->orig.x = MIN(bbox->orig.x, bbox2->orig.x);
    bbox->orig.y = MIN(bbox->orig.y, bbox2->orig.y);
    bbox->corner.x = MAX(bbox->corner.x, bbox2->corner.x);
    bbox->corner.y = MAX(bbox->corner.y, bbox2->corner.y);
  }
}


void
ZnAddPointToBBox(ZnBBox *bbox,
                 ZnPos  px,
                 ZnPos  py)
{
  if (ZnIsEmptyBBox(bbox)) {
    bbox->orig.x = px;
    bbox->orig.y = py;
    bbox->corner.x = bbox->orig.x + 1;
    bbox->corner.y = bbox->orig.y + 1;
  }
  else {
    bbox->orig.x = MIN(bbox->orig.x, px);
    bbox->orig.y = MIN(bbox->orig.y, py);
    bbox->corner.x = MAX(bbox->corner.x, px + 1);
    bbox->corner.y = MAX(bbox->corner.y, py + 1);
  }
}


void
ZnAddPointsToBBox(ZnBBox        *bbox,
                  ZnPoint       *points,
                  unsigned int  num_points)
{
  ZnReal x1, y1, x2, y2, cur;

  if (points == NULL) {
    return;
  }
  
  if (num_points == 0) {
    return;
  }
  
  if (ZnIsEmptyBBox(bbox)) {
    x1 = points->x;
    y1 = points->y;
    x2 = x1 + 1;
    y2 = y1 + 1;
    num_points--;
    points++;
  }
  else {
    x1 = bbox->orig.x;
    y1 = bbox->orig.y;
    x2 = bbox->corner.x;
    y2 = bbox->corner.y;
  }

  for ( ; num_points > 0; num_points--, points++) {
    cur = points->x;
    if (cur < x1) {
      x1 = cur;
    }
    if (cur > x2) {
      x2 = cur;
    }
    cur = points->y;
    if (cur < y1) {
      y1 = cur;
    }
    if (cur > y2) {
      y2 = cur;
    }
  }
  bbox->orig.x = x1;
  bbox->orig.y = y1;
  if (x1 == x2) {
    x2++;
  }
  if (y1 == y2) {
    y2++;
  }
  bbox->corner.x = x2;
  bbox->corner.y = y2;
}


void
ZnAddStringToBBox(ZnBBox        *bbox,
                  char          *str,
                  Tk_Font       font,
                  ZnPos         cx,
                  ZnPos         cy)
{
  ZnBBox        str_bbox;
  
  ZnGetStringBBox(str, font, cx, cy, &str_bbox);
  ZnAddBBoxToBBox(bbox, &str_bbox);
}

ZnBool
ZnPointInBBox(ZnBBox    *bbox,
              ZnPos     x,
              ZnPos     y)
{
  return ((x >= bbox->orig.x) && (x < bbox->corner.x) &&
          (y >= bbox->orig.y) && (y < bbox->corner.y));
}


/*
 * Tell where aa area is with respect to another area.
 * Return -1 if the first is entirely outside the second,
 * 1 if it is entirely inside and 0 otherwise.
 */
int
ZnBBoxInBBox(ZnBBox     *bbox1,
             ZnBBox     *bbox2)
{
  if ((bbox1->corner.x <= bbox2->orig.x) ||
      (bbox1->orig.x >= bbox2->corner.x) ||
      (bbox1->corner.y <= bbox2->orig.y) ||
      (bbox1->orig.y >= bbox2->corner.y)) {
    return -1;
  }
  if ((bbox2->orig.x <= bbox1->orig.x) &&
      (bbox1->corner.x <= bbox2->corner.x) &&
      (bbox2->orig.y <= bbox1->orig.y) &&
      (bbox1->corner.y <= bbox2->corner.y)) {
    return 1;
  }
  return 0;
}

/*
 * Tell where a line is with respect to an area.
 * Return -1 if the line is entirely outside the bbox, 1
 * if it is entirely inside and 0 otherwise.
 */
int
ZnLineInBBox(ZnPoint    *p1,
             ZnPoint    *p2,
             ZnBBox     *bbox)
{
  ZnBool p1_inside = ZnPointInBBox(bbox, p1->x, p1->y);
  ZnBool p2_inside = ZnPointInBBox(bbox, p2->x, p2->y);

  if (p1_inside != p2_inside) {
    return 0;
  }

  if (p1_inside && p2_inside) {
    return 1;
  }
  
  /*
   * Segment may intersect area, check it more thoroughly.
   */
  /* Vertical line */
  if (p1->x == p2->x) {
    if (((p1->y >= bbox->orig.y) ^ (p2->y >= bbox->orig.y)) &&
        (p1->x >= bbox->orig.x) &&
        (p1->x <= bbox->corner.x)) {
      return 0;
    }
  }
  /* Horizontal line */
  else if (p1->y == p2->y) {
    if (((p1->x >= bbox->orig.x) ^ (p2->x >= bbox->orig.x)) &&
        (p1->y >= bbox->orig.y) &&
        (p1->y <= bbox->corner.y)) {
      return 0;
    }
  }
  /* Diagonal, do it the hard way. */
  else {
    ZnReal      slope = (p2->y - p1->y) / (p2->x - p1->x);
    ZnDim       low, high, x, y;
    ZnDim       bbox_width = bbox->corner.x - bbox->orig.x;
    ZnDim       bbox_height = bbox->corner.y - bbox->orig.y;

    /* Check against left edge */
    if (p1->x < p2->x) {
      low = p1->x;
      high = p2->x;
    }
    else {
      low = p2->x;
      high = p1->x;
    }

    y = p1->y + (bbox->orig.x - p1->x) * slope;
    if ((bbox->orig.x >= low) && (bbox->orig.x <= high) &&
        (y >= bbox->orig.y) && (y <= bbox->corner.y))
      return 0;

    /* Check against right edge */
    y += bbox_width * slope;
    if ((y >= bbox->orig.y) && (y <= bbox->corner.y) &&
        (bbox->corner.x >= low) && (bbox->corner.x <= high))
      return 0;
        
    /* Check against bottom edge */
    if (p1->y < p2->y) {
      low = p1->y;
      high = p2->y;
    }
    else {
      low = p2->y;
      high = p1->y;
    }

    x = p1->x + (bbox->orig.y - p1->y) / slope;
    if ((x >= bbox->orig.x) && (x <= bbox->corner.x) &&
        (bbox->orig.y >= low) && (bbox->orig.y <= high))
      return 0;

    /* Check against top edge */
    x += bbox_height / slope;
    if ((x >= bbox->orig.x) && (x <= bbox->corner.x) &&
        (bbox->corner.y >= low) && (bbox->corner.y <= high))
      return 0;
  }

  return -1;
}


ZnBool
ZnTestCCW(ZnPoint               *points,
          unsigned int  num_points)
{
  ZnPoint       *p, *p_p=NULL, *p_n=NULL, min;
  ZnReal        xprod;
  unsigned int  i, min_index;
  
  if (num_points < 3) {
    return True;
  }

  /*
   * First find the lowest rightmost vertex. In X11 this is the
   * topmost one.
   */
  p = points;
  min = *p;
  min_index = 0;
  for (i = 1, p++; i < num_points; i++, p++) {
    if ((p->y < min.y) ||
        ((p->y == min.y) && (p->x > min.x))) {
      min_index = i;
      min = *p;
    }
  }
  /*
   * Then find the indices of the previous and next
   * vertices.
   */
  p = &points[min_index];
  /*printf("min index %d, prev %d, next %d\n", min_index,
    (min_index+(num_points-1))%num_points, (min_index+1)%num_points);*/
  /*printf("lower point index %d %d %d\n",
    (min_index+(num_points-1))%num_points, min_index, (min_index+1)%num_points);*/
  /*
   * Try to find preceding and following points that are not
   * the same as the base point.
   */
  for (i = 1; i < num_points; i++) {
    p_p = &points[(min_index+(num_points-i))%num_points]; /* min_index-1 */
    if ((p_p->x != p->x) || (p_p->y != p->y)) {
      break;
    }
  }
  for (i = 1; i < num_points; i++) {
    p_n = &points[(min_index+i)%num_points];
    if ((p_p->x != p->x) || (p_p->y != p->y)) {
      break;
    }
  }
  xprod = ((p->x - p_p->x) * (p_n->y - p->y)) - ((p->y - p_p->y) * (p_n->x - p->x));
  return (xprod < 0.0); /* Should be > 0 but X11 has Y axis reverted. */
}


/*
 * ZnShiftLine --
 *      Given two points describing a line and a distance, return
 *      to points describing a line parallel to it at the given distance.
 *      When looking the line from p1 to p2 the new line will be dist away
 *      on its left. Negative values are allowed for dist, resulting in a line
 *      on the right.
 */
void
ZnShiftLine(ZnPoint     *p1,
            ZnPoint     *p2,
            ZnReal      dist,
            ZnPoint     *p3,
            ZnPoint     *p4)
{
  static int    shift_table[129];
  ZnBool        dx_neg, dy_neg;
  int           dx, dy;

  /*
   * Initialize the conversion table.
   */
  if (shift_table[0] == 0) {
    int         i;
    ZnReal      tangent, cosine;
    
    for (i = 0; i <= 128; i++) {
      tangent = i/128.0;
      cosine = 128/cos(atan(tangent)) + 0.5;
      shift_table[i] = (int) cosine;
    }
  }

  *p3 = *p1;
  dx = (int) (p2->x - p1->x);
  dy = (int) (p2->y - p1->y);
  if (dx < 0) {
    dx = -dx;
    dx_neg = True;
  }
  else {
    dx_neg = False;
  }
  if (dy < 0) {
    dy = -dy;
    dy_neg = True;
  }
  else {
    dy_neg = False;
  }
  if ((dy < PRECISION_LIMIT) && (dx < PRECISION_LIMIT)) {
    fprintf(stderr, "ShiftLine: segment is a point\n");
    return;
  }

  if (dy <= dx) {
    dy = (((int) dist * shift_table[(dy*128)/dx]) + 64) / 128;
    if (!dx_neg) {
      dy = -dy;
    }
    p3->y += dy;
  }
  else {
    dx = (((int) dist * shift_table[(dx*128)/dy]) + 64) / 128;
    if (dy_neg) {
      dx = -dx;
    }
    p3->x += dx;
  }

  p4->x = p3->x + (p2->x - p1->x);
  p4->y = p3->y + (p2->y - p1->y);
}


/*
 * IntersectLines --
 *      Given two lines described by two points, compute their intersection.
 *      The function returns True if the lines are not parallel and False
 *      otherwise.
 */
ZnBool
ZnIntersectLines(ZnPoint        *a1,
                 ZnPoint        *a2,
                 ZnPoint        *b1,
                 ZnPoint        *b2,
                 ZnPoint        *pi)
{
  ZnReal dxadyb, dxbdya, dxadxb, dyadyb, p, q;

  dxadyb = (a2->x - a1->x)*(b2->y - b1->y);
  dxbdya = (b2->x - b1->x)*(a2->y - a1->y);
  dxadxb = (a2->x - a1->x)*(b2->x - b1->x);
  dyadyb = (a2->y - a1->y)*(b2->y - b1->y);
  
  if (dxadyb == dxbdya) {
    return False;
  }
  
  p = a1->x*dxbdya - b1->x*dxadyb + (b1->y - a1->y)*dxadxb;
  q = dxbdya - dxadyb;
  if (q < 0) {
    p = -p;
    q = -q;
  }
  if (p < 0) {
    pi->x = - ((-p + q/2)/q);
  }
  else {
    pi->x = (p + q/2)/q;
  }
  
  p = a1->y*dxadyb - b1->y*dxbdya + (b1->x - a1->x)*dyadyb;
  q = dxadyb - dxbdya;
  if (q < 0) {
    p = -p;
    q = -q;
  }
  if (p < 0) {
    pi->y = - ((-p + q/2)/q);
  }
  else {
    pi->y = (p + q/2)/q;
  }
  
  return True;
}


/*
 * InsetPolygon --
 *      Inset the given polygon by the given amount. The
 *     value can be negative, in this case the polygon will
 *     be outset.
 */
/**** A FINIR ****/
void
ZnInsetPolygon(ZnPoint          *p,
               unsigned int     num_points,
               ZnDim            inset)
{
  ZnPoint       *p1, *p2;
  ZnPoint       new_p1, new_p2;
  /*  ZnPoint   shift1, shift2;*/
  unsigned int  i, processed_points;

  processed_points = 0;
  
  if ((p->x == p[num_points-1].x) && (p->y == p[num_points-1].y)) {
    num_points--;
  }
  for (p1 = p, p2 = p1+1, i = 0; i < num_points; i++, p1 = p2, p2++) {
    /*
     * Wrap to the first point.
     */
    if (i == num_points-1) {
      p2 = p;
    }
    /*
     * Skip duplicate vertices.
     */
    if ((p2->x == p1->x) && (p2->y == p1->y)) {
      continue;
    }
    
    ZnShiftLine(p1, p2, inset, &new_p1, &new_p2);

    if (processed_points >= 1) {
    }
  }
}


/*
 * Compute the two corner points of a thick line end.
 * Two points describing the line segment and the width
 * are given as input. If projecting is true this function
 * mimics the X11 line projecting behaviour. The computed
 * end is located around p2.
 */
void
ZnGetButtPoints(ZnPoint *p1,
                ZnPoint *p2,
                ZnDim   width,
                ZnBool  projecting,
                ZnPoint *c1,
                ZnPoint *c2)
{
  ZnReal        w_2 = width/2.0;
  ZnDim         length = hypot(p2->x - p1->x, p2->y - p1->y);
  ZnReal        delta_x, delta_y;
  
  if (length == 0.0) {
    c1->x = c2->x = p2->x;
    c1->y = c2->y = p2->y;
  }
  else {
    delta_x = -w_2 * (p2->y - p1->y) / length;
    delta_y = w_2 * (p2->x - p1->x) / length;
    c1->x = p2->x + delta_x;
    c2->x = p2->x - delta_x;
    c1->y = p2->y + delta_y;
    c2->y = p2->y - delta_y;
    if (projecting) {
      c1->x += delta_y;
      c2->x += delta_y;
      c1->y -= delta_x;
      c2->y -= delta_x;
    }
  }
}

/*
 * Compute the inside and outside points of the mitered
 * corner formed by a thick line going through 3 points.
 * If the angle formed by the three points is less than
 * 11 degrees, False is returned an no points are computed.
 * Else True is returned and the points are in c1, c2.
 *
 * If someday the code is switched to REAL coordinates, we
 * must round each coordinate to the nearer integer to mimic
 * the way pixels are drawn. Sample code: floor(p->x+0.5);
 *
 * Hmmm, the switch has been done but not the rounding ;-)
 */
ZnBool
ZnGetMiterPoints(ZnPoint        *p1,
                 ZnPoint        *p2,
                 ZnPoint        *p3,
                 ZnDim          width,
                 ZnPoint        *c1,
                 ZnPoint        *c2)
{
  static ZnReal deg11 = (11.0*2.0*M_PI)/360.0;
  ZnReal        theta1;         /* angle of p2-p1 segment. */
  ZnReal        theta2;         /* angle of p2-p3 segment. */
  ZnReal        theta;          /* angle of the joint */
  ZnReal        theta3;         /* angle of bisector of the joint toward
                                 * the external point of the joint. */
  ZnReal        dist;           /* distance of the external points
                                 * of the corner from the mid point
                                 * p2. */
  ZnReal        delta_x, delta_y; /* projection of (dist,theta3) on x
                                   * and y. */
  
  if (p2->y == p1->y) {
    theta1 = (p2->x < p1->x) ? 0.0 : M_PI;
  }
  else if (p2->x == p1->x) {
    theta1 = (p2->y < p1->y) ? M_PI/2.0 : -M_PI/2.0;
  }
  else {
    theta1 = atan2(p1->y - p2->y, p1->x - p2->x);
  }
  if (p3->y == p2->y) {
    theta2 = (p3->x > p2->x) ? 0.0 : M_PI;
  }
  else if (p3->x == p2->x) {
    theta2 = (p3->y > p2->y) ? M_PI/2.0 : -M_PI/2.0;
  }
  else {
    theta2 = atan2(p3->y - p2->y, p3->x - p2->x);
  }
  theta = theta1 - theta2;
  if (theta > M_PI) {
    theta -= 2.0*M_PI;
  }
  else if (theta < -M_PI) {
    theta += 2*M_PI;
  }
  if ((theta < deg11) && (theta > -deg11)) {
    return False;
  }
  /*
   * Compute the distance of the internal and external
   * corner points from the intersection p2 (considered
   * at 0,0).
   */
  dist = 0.5*width / sin(0.5*theta);
  dist = ABS(dist);

  /*
   * Compute the angle of the bisector of the joint that
   * goes toward the outside of the joint (the left hand
   * when looking from p1-p2).
   */
  theta3 = (theta1 + theta2)/2.0;
  if (sin(theta3 - (theta1 + M_PI)) < 0.0) {
    theta3 += M_PI;
  }
  
  delta_x = dist * cos(theta3);
  c1->x = p2->x + delta_x;
  c2->x = p2->x - delta_x;
  delta_y = dist * sin(theta3);
  c1->y = p2->y + delta_y;
  c2->y = p2->y - delta_y;
  
  return True;
}

/*
 * Tell where a thick polyline is with respect to an area.
 * Return -1 if the polyline is entirely outside the bbox, 1
 * if it is entirely inside and 0 otherwise. The joints can
 * be specified as JoinMiter, JoinRound, JoinBevel. The ends
 * can be: CapRound, CapButt, CapProjecting.
 */
int
ZnPolylineInBBox(ZnPoint        *points,
                 unsigned int   num_points,
                 ZnDim          width,
                 int            cap_style,
                 int            join_style,
                 ZnBBox         *bbox)
{
  unsigned int  count;
  int           inside = -1;
  ZnBool        do_miter_as_bevel;
  ZnPoint       poly[4];
  
  /*
   * If the first point is inside the area, change inside
   * accordingly.
   */
  if ((points[0].x >= bbox->orig.x) && (points[0].x <= bbox->corner.x) &&
      (points[0].y >= bbox->orig.y) && (points[0].y <= bbox->corner.y)) {
    inside = 1;
  }

  /*
   * Now iterate through all the edges. Compute a polygon for
   * each and test it against the area. At each vertex an oval
   * of radius width/2 is also tested to account for round ends
   * and joints.
   */
  do_miter_as_bevel = False;
  for (count = num_points; count >= 2; count--, points++) {

    /*
     * Test a circle around the first point if CapRound or
     * around every joint if JoinRound.
     */
    if (((cap_style == CapRound) && (count == num_points)) ||
        ((join_style == JoinRound) && (count != num_points))) {
      if (ZnOvalInBBox(points, width, width, bbox) != inside) {
        return 0;
      }
    }
    /*
     * Build a polygon to represent an edge from the current
     * point to the next. Special cases for the first and
     * last edges to implement the line ends.
     */
    /*
     * First vertex of the edge
     */
    if (count == num_points) {
      ZnGetButtPoints(&points[1], points, width,
                      cap_style == CapProjecting, poly, &poly[1]);
    }
    /*
     * Here we are at a joint starting a new edge. If the
     * joint is mitered, start by carrying over the points
     * from the previous edge. Otherwise compute new points
     * for a butt end.
     */
    else if ((join_style == JoinMiter) && !do_miter_as_bevel) {
      poly[0] = poly[3];
      poly[1] = poly[2];
    }
    else {
      ZnGetButtPoints(&points[1], points, width, 0, poly, &poly[1]);
      /*
       * If the previous joint was beveled (or considered so),
       * check the polygon that fill the bevel. It has more or
       * less an X shape, i.e, it's self intersecting. If this
       * is not ok, it may be necessary to permutte poly[1] &
       * poly[2].
       */
      if ((join_style == JoinBevel) || do_miter_as_bevel) {
        if (ZnPolygonInBBox(poly, 4, bbox, NULL) != inside) {
          return 0;
        }
        do_miter_as_bevel = False;
      }
    }

    /*
     * Opposite vertex of the edge.
     */
    if (count == 2) {
      ZnGetButtPoints(points, &points[1], width, cap_style == CapProjecting,
                      &poly[2], &poly[3]);
    }
    else if (join_style == JoinMiter) {
      if (ZnGetMiterPoints(points, &points[1], &points[2], width,
                         &poly[2], &poly[3]) == False) {
        do_miter_as_bevel = True;
        ZnGetButtPoints(points, &points[1], width, 0, &poly[2], &poly[3]);
      }
    }
    else {
      ZnGetButtPoints(points, &points[1], width, 0, &poly[2], &poly[3]);
    }

    if (ZnPolygonInBBox(poly, 4, bbox, NULL) != inside) {
      return 0;
    }
  }

  /*
   * Test a circle around the last point if CapRound.
   */
  if (cap_style == CapRound) {
    if (ZnOvalInBBox(points, width, width, bbox) != inside) {
      return 0;
    }
  }

  return inside;
}


/*
 * Tell where a polygon is with respect to an area.
 * Return -1 if the polygon is entirely outside the bbox, 1
 * if it is entirely inside and 0 otherwise. If area_enclosed
 * is not NULL it tells whether the area is enclosed by the
 * polygon or not.
 */
int
ZnPolygonInBBox(ZnPoint         *points,
                unsigned int    num_points,
                ZnBBox          *bbox,
                ZnBool          *area_enclosed)
{
  int           inside, count;
  ZnPoint       *p, *head, *first, *second;
  ZnBool        closed;

  if (area_enclosed) {
    *area_enclosed = False;
  }
  p = head = points;
  closed = True;
  count = num_points-2;
  /*
   * Check to see if closed. If not adjust num_points and
   * record this.
   */
  if ((points[0].x != points[num_points-1].x) ||
      (points[0].y != points[num_points-1].y)) {
    closed = False;
    count = num_points-1;
  }

  /*
   * Get the status of the first edge.
   */
  inside = ZnLineInBBox(&p[0], &p[1], bbox);
  p++;
  if (inside == 0) {
    return 0;
  }
  for (; count > 0; p++, count--) {
    first = &p[0];
    /*
     * Pretend the polygon is closed if this is not the case.
     */
    if (!closed && (count == 1)) {
      second = head;
    }
    else {
      second = &p[1];
    }
    
    if (ZnLineInBBox(first, second, bbox) != inside) {
      return 0;
    }
  }

  /*
   * If all the edges are inside the area, the polygon is
   * inside the area. If all the edges are outside, the polygon
   * may completely enclose the area. Test if the origin of
   * the area is inside the polygon to decide this.
   */
  if (inside == 1) {
    return 1;
  }

  /*printf("PolygonInBBox, np = %d, x = %g, y = %g, dist = %g\n",
         num_points, bbox->orig.x, bbox->orig.y,
         PolygonToPointDist(points, num_points, &bbox->orig));*/
  if (ZnPolygonToPointDist(points, num_points, &bbox->orig) <= 0.0) {
    if (area_enclosed) {
      *area_enclosed = True;
    }
    return 0;
  }
  
  return -1;
}


/*
 * Tell where an oval is with respect to an area.
 * Return -1 if the oval is entirely outside the bbox, 1
 * if it is entirely inside and 0 otherwise.
 */
int
ZnOvalInBBox(ZnPoint    *center,
             ZnDim      width,
             ZnDim      height,
             ZnBBox     *bbox)
{
  ZnPoint       origin, corner;
  ZnDim         w_2, h_2;
  ZnReal        delta_x, delta_y;
  
  w_2 = (width+1)/2;
  h_2 = (height+1)/2;
  
  origin.x = center->x - w_2;
  origin.y = center->y - h_2;
  corner.x = center->x + w_2;
  corner.y = center->y + h_2;

  /*
   * This if the oval bbox is completely inside or outside
   * of the area. Trivial case first.
   */
  if ((bbox->orig.x <= origin.x) && (bbox->corner.x >= corner.x) &&
      (bbox->orig.y <= origin.y) && (bbox->corner.y >= corner.y)) {
    return 1;
  }
  if ((bbox->corner.x < origin.x) || (bbox->orig.x > corner.x) ||
      (bbox->corner.y < origin.y) || (bbox->orig.y > corner.y)) {
    return -1;
  }

  /*
   * Then test all sides of the area against the oval center.
   * If the point of a side closest to the center is inside
   * the oval, then the oval intersects the area.
   */

  /*
   * Compute the square of the Y axis distance, reducing
   * the oval to a unit circle to take into account the
   * shape factor.
   */
  delta_y = bbox->orig.y - center->y;
  if (delta_y < 0.0) {
    delta_y = center->y - bbox->corner.y;
    if (delta_y < 0.0) {
      delta_y = 0.0;
    }
  }
  delta_y /= h_2;
  delta_y *= delta_y;

  /*
   * Test left and then right edges.
   */
  delta_x = (bbox->orig.x - center->x) / w_2;
  delta_x *= delta_x;
  if ((delta_x + delta_y) <= 1.0) {
    return 0;
  }
  delta_x = (bbox->corner.x - center->x) / w_2;
  delta_x *= delta_x;
  if ((delta_x + delta_y) <= 1.0) {
    return 0;
  }
  
  /*
   * Compute the square of the X axis distance, reducing
   * the oval to a unit circle to take into account the
   * shape factor.
   */
  delta_x = bbox->orig.x - center->x;
  if (delta_x < 0.0) {
    delta_x = center->x - bbox->corner.x;
    if (delta_x < 0.0) {
      delta_x = 0.0;
    }
  }
  delta_x /= w_2;
  delta_x *= delta_x;
  
  /*
   * Test top and then bottom edges.
   */
  delta_y = (bbox->orig.y - center->y) / h_2;
  delta_y *= delta_y;
  if ((delta_x + delta_y) <= 1.0) {
    return 0;
  }
  delta_y = (bbox->corner.y - center->y) / h_2;
  delta_y *= delta_y;
  if ((delta_x + delta_y) <= 1.0) {
    return 0;
  }

  return -1;
}


/*
 * Tell if a point is in an angular range whose center is 0,0.
 * The range is specified by a starting angle and an angle extent.
 * The use of a double here is important, don't change it. In some
 * case we need to normalize a figure to take care of its shape and
 * the result needs precision.
 */
ZnBool
ZnPointInAngle(int      start_angle,
               int      angle_extent,
               ZnPoint  *p)
{
  ZnReal point_angle;
  int    angle_diff;

  if ((p->x == 0) && (p->y == 0)) {
    point_angle = 0.0;
  }
  else {
    point_angle = atan2(p->y, p->x) * 180.0 / M_PI;
  }
  angle_diff = (ZnNearestInt(point_angle) - start_angle) % 360;
  if (angle_diff < 0) {
    angle_diff += 360;
  }
  return ((angle_diff <= angle_extent) ||
          ((angle_extent < 0) && ((angle_diff - 360) >= angle_extent)));
}

/*
 * PointCartesianToPolar --
 *	Convert a point in cartesian coordinates (delta_x, delta_y)
 *  in polar coordinates (rho, theta)
 *	in a reference system described by angle heading
 *	(angles running clockwise) to a point .
 *
 */
void
ZnPointCartesianToPolar(ZnReal heading,
                        ZnReal *rho,
                        ZnReal *theta,  /* in degree -180 , + 180 */
                        ZnReal delta_x,
                        ZnReal delta_y)
{
  ZnReal theta_rad;
  theta_rad = heading - ZnProjectionToAngle(delta_x,delta_y) - M_PI_2;
  *theta = ZnRadDeg(theta_rad); 
  *rho = sqrt( delta_x * delta_x + delta_y * delta_y );
}

/*
 * PointPolarToCartesian --
 *      Convert a point in polar coordinates (rho, theta)
 *      in a reference system described by angle heading
 *      (angles running clockwise) to a point in cartesian
 *      coordinates (delta_x, delta_y).
 *
 */
void
ZnPointPolarToCartesian(ZnReal  heading,
                        ZnReal  rho,
                        ZnReal  theta,
                        ZnReal  *delta_x,
                        ZnReal  *delta_y)
{
  ZnReal        to_angle;

  /* Compute angle in trigonometric system */
  /*  to_angle = ZnDegRad(theta) + heading - M_PI_2;*/
  to_angle = heading - ZnDegRad(theta) - M_PI_2;
  /* Compute cartesian coordinates */
  *delta_x = rho * cos(to_angle);
  *delta_y = rho * sin(to_angle);
}

/*
 * Return a vector angle given its projections
 */
ZnReal
ZnProjectionToAngle(ZnReal      dx,
                    ZnReal      dy)
{
  if (dx == 0) {
    if (dy < 0) {
      return -M_PI_2;
    }
    else if (dy > 0) {
      return M_PI_2;
    }
    else {
      return 0.0;
    }
  }
  else if (dx < 0) {
    return atan(dy / dx) - M_PI;
  }
  else {
    return atan(dy / dx);
  }
  return 0.0;
}


/*
 * Tell if an horizontal line intersect an axis aligned
 * elliptical arc.
 *
 * Returns True if the line described by (x1, x2, y) intersects
 * the arc described by (r1, r2, start_angle and angle_extent).
 * This arc is origin centered.
 */
ZnBool
ZnHorizLineToArc(ZnReal x1,
                 ZnReal x2,
                 ZnReal y,
                 ZnReal rx,
                 ZnReal ry,
                 int    start_angle,
                 int    angle_extent)
{
  ZnReal        tmp, x;
  ZnPoint       t;
  
  /*
   * Compute the x-coordinate of one possible intersection point
   * between the arc and the line.  Use a transformed coordinate
   * system where the oval is a unit circle centered at the origin.
   * Then scale back to get actual x-coordinate.
   */
  t.y = y/ry;
  tmp = 1 - t.y*t.y;
  if (tmp < 0.0) {
    return False;
  }
  t.x = sqrt(tmp);
  x = t.x*rx;
  
  /*
   * Test both intersection points.
   */  
  if ((x >= x1) && (x <= x2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
    return True;
  }
  t.x = -t.x;
  if ((-x >= x1) && (-x <= x2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
    return True;
  }
  return False;
}


/*
 * Tell if an vertical line intersect an axis aligned
 * elliptical arc.
 *
 * Returns True if the line described by (x1, x2, y) intersects
 * the arc described by (r1, r2, start_angle and angle_extent).
 * This arc is origin centered.
 */
ZnBool
ZnVertLineToArc(ZnReal  x,
                ZnReal  y1,
                ZnReal  y2,
                ZnReal  rx,
                ZnReal  ry,
                int     start_angle,
                int     angle_extent)
{
  ZnReal        tmp, y;
  ZnPoint       t;
  
  /*
   * Compute the y-coordinate of one possible intersection point
   * between the arc and the line.  Use a transformed coordinate
   * system where the oval is a unit circle centered at the origin.
   * Then scale back to get actual y-coordinate.
   */
  t.x = x/rx;
  tmp = 1 - t.x*t.x;
  if (tmp < 0.0) {
    return False;
  }
  t.y = sqrt(tmp);
  y = t.y*ry;

  /*
   * Test both intersection points.
   */
  if ((y > y1) && (y < y2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
    return True;
  }
  t.y = -t.y;
  if ((-y > y1) && (-y < y2) && ZnPointInAngle((int) start_angle, (int) angle_extent, &t)) {
    return True;
  }
  return False;
}


/*
 * Return the distance of the given point to the rectangle
 * described by rect. Return negative values for points in
 * the rectangle.
 */
ZnDim
ZnRectangleToPointDist(ZnBBox   *bbox,
                       ZnPoint  *p)
{
  ZnDim         new_dist, dist;
  ZnPoint       p1, p2;

  p1.x = bbox->orig.x;
  p1.y = p2.y = bbox->orig.y;
  p2.x = bbox->corner.x;
  dist = ZnLineToPointDist(&p1, &p2, p, NULL);
  if (dist == 0.0) {
    return 0.0;
  }

  p1 = p2;
  p2.y = bbox->corner.y;
  new_dist = ZnLineToPointDist(&p1, &p2, p, NULL);
  dist = MIN(dist, new_dist);
  if (dist == 0.0) {
    return 0.0;
  }

  p1 = p2;
  p2.x = bbox->orig.x;
  new_dist = ZnLineToPointDist(&p1, &p2, p, NULL);
  dist = MIN(dist, new_dist);
  if (dist == 0.0) {
    return 0.0;
  }
  
  p1 = p2;
  p2.y = bbox->orig.y;
  new_dist = ZnLineToPointDist(&p1, &p2, p, NULL);
  dist = MIN(dist, new_dist);

  if (ZnPointInBBox(bbox, p->x, p->y)) {
    return -dist;
  }
  else {
    return dist;
  }
}


/*
 * Return the distance of the given point to the line
 * described by <xl1,yl1>, <xl2,yl2>..
 */
ZnDim
ZnLineToPointDist(ZnPoint       *p1,
                  ZnPoint       *p2,
                  ZnPoint       *p,
                  ZnPoint       *closest)
{
  ZnReal        x, y;
  ZnReal        x_int, y_int;

  /*
   * First compute the closest point on the line. This is done
   * separately for vertical, horizontal, other lines.
   */

  /* Vertical */
  if (p1->x == p2->x) {
    x = p1->x;
    if (p1->y >= p2->y) {
      y_int = MIN(p1->y, p->y);
      y_int = MAX(y_int, p2->y);
    }
    else {
      y_int = MIN(p2->y, p->y);
      y_int = MAX(y_int, p1->y);
    }
    y = y_int;
  }

  /* Horizontal */
  else if (p1->y == p2->y) {
    y = p1->y;
    if (p1->x >= p2->x) {
      x_int = MIN(p1->x, p->x);
      x_int = MAX(x_int, p2->x);
    }
    else {
      x_int = MIN(p2->x, p->x);
      x_int = MAX(x_int, p1->x);
    }
    x = x_int;
  }

  /*
   * Other. Compute its parameters of form y = a1*x + b1 and
   * then compute the parameters of the perpendicular passing
   * through the point y = a2*x + b2, last find the closest point
   * on the segment.
   */
  else {
    ZnReal      a1, a2, b1, b2;

    a1 = (p2->y - p1->y) / (p2->x - p1->x);
    b1 = p1->y - a1*p1->x;

    a2 = -1.0/a1;
    b2 = p->y - a2*p->x;

    x = (b2 - b1) / (a1 - a2);
    y = a1*x + b1;

    if (p1->x > p2->x) {
      if (x > p1->x) {
        x = p1->x;
        y = p1->y;
      }
      else if (x < p2->x) {
        x = p2->x;
        y = p2->y;
      }
    }
    else {
      if (x > p2->x) {
        x = p2->x;
        y = p2->y;
      }
      else if (x < p1->x) {
        x = p1->x;
        y = p1->y;
      }
    }
  }
  
  if (closest) {
    closest->x = x;
    closest->y = y;
  }

  /* Return the distance */
  return hypot(p->x - x, p->y - y);
}


/*
 * Return the distance of the polygon described by
 * points, to the given point. If the point is
 * inside return values are negative.
 */
ZnDim
ZnPolygonToPointDist(ZnPoint            *points,
                     unsigned int       num_points,
                     ZnPoint            *p)
{
  ZnDim         best_distance, dist;
  int           intersections;
  int           x_int, y_int;
  ZnPoint       *first_point;
  ZnReal        x, y;
  ZnPoint       p1, p2;

  /*
   * The algorithm iterates through all the edges of the polygon
   * computing for each the distance to the point and whether a vertical
   * ray starting at the point, intersects the edge. The smallest
   * distance of all edges is stored in best_distance while intersections
   * hold the count of edges to rays intersections. For more informations
   * on how the distance is computed see LineToPointDist.
   */
  best_distance = 1.0e40;
  intersections = 0;

  first_point = points;

  /*
   * Check to see if closed. Adjust num_points to open it (the
   * algorithm always consider a set of points as a closed polygon).
   */
  if ((points[0].x == points[num_points-1].x) &&
      (points[0].y == points[num_points-1].y)) {
    num_points--;
  }

  for ( ; num_points >= 1; num_points--, points++) {
    p1 = points[0];
    /*
     * Wrap over to the first point.
     */
    if (num_points == 1) {
      p2 = *first_point;
    }
    else {
      p2 = points[1];
    }
    
    /*
     * First try to find the closest point on this edge.
     */

    /* Vertical edge */
    if (p1.x == p2.x) {
      x = p1.x;
      if (p1.y >= p2.y) {
        y_int = (int) MIN(p1.y, p->y);
        y_int = (int) MAX(y_int, p2.y);
      }
      else {
        y_int = (int) MIN(p2.y, p->y);
        y_int = (int) MAX(y_int, p1.y);
      }
      y = y_int;
    }

    /* Horizontal edge */
    else if (p1.y == p2.y) {
      y = p1.y;
      if (p1.x >= p2.x) {
        x_int = (int) MIN(p1.x, p->x);
        x_int = (int) MAX(x_int, p2.x);
        if ((p->y < y) && (p->x < p1.x) && (p->x >= p2.x)) {
          intersections++;
        }
      }
      else {
        x_int = (int) MIN(p2.x, p->x);
        x_int = (int) MAX(x_int, p1.x);
        if ((p->y < y) && (p->x < p2.x) && (p->x >= p1.x)) {
          intersections++;
        }
      }
      x = x_int;
    }

    /* Other */
    else {
      ZnReal    a1, b1, a2, b2;

      a1 = (p2.y - p1.y) / (p2.x - p1.x);
      b1 = p1.y - a1 * p1.x;

      a2 = -1.0/a1;
      b2 = p->y - a2 * p->x;

      x = (b2 - b1)/(a1 - a2);
      y = a1 * x + b1; 

      if (p1.x > p2.x) {
        if (x > p1.x) {
          x = p1.x;
          y = p1.y;
        }
        else if (x < p2.x) {
          x = p2.x;
          y = p2.y;
        }
      }
      else {
        if (x > p2.x) {
          x = p2.x;
          y = p2.y;
        }
        else if (x < p1.x) {
          x = p1.x;
          y = p1.y;
        }
      }

      if (((a1 * p->x + b1) > p->y) &&  /* True if point is lower */
          (p->x >= MIN(p1.x, p2.x)) &&
          (p->x < MAX(p1.x, p2.x))) {
        intersections++;
      }
    }

    /*
     * Now compute the distance to the closest point and
     * keep it if it is the shortest.
     */
    dist = hypot(p->x - x, p->y - y);
    best_distance = MIN(best_distance, dist);
    /*
     * We can safely escape here if distance is zero.
     */
    if (best_distance == 0.0) {
      return 0.0;
    }
  }

  /*
   * Well, all the edges are processed, if the
   * intersection count is odd the point is inside.
   */
  if (intersections & 0x1) {
    return -best_distance;
  }
  else {
    return best_distance;
  }
}


/*
 * Return the distance of a thick polyline to the
 * given point. Cap and Join parameters are considered
 * in the process.
 */
ZnDim
ZnPolylineToPointDist(ZnPoint           *points,
                      unsigned int      num_points,
                      ZnDim             width,
                      int               cap_style,
                      int               join_style,                
                      ZnPoint           *p)
{
  ZnBool        miter2bevel = False;
  unsigned int  count;
  ZnPoint       *ptr;
  ZnPoint       outline[5];
  ZnDim         dist, best_dist, h_width;

  best_dist = 1.0e36;
  h_width = width/2.0;

  for (count = num_points, ptr = points; count >= 2; count--, ptr++) {
    if (((cap_style == CapRound) && (count == num_points)) ||
        ((join_style == JoinRound) && (count != num_points))) {
      dist = hypot(ptr->x - p->x, ptr->y - p->y) - h_width;
      if (dist <= 0.0) {
        best_dist = 0.0;
        goto done;
      }
      else if (dist < best_dist) {
        best_dist = dist;
      }
    }
    /*
     * Build the polygonal outline of the current edge.
     */
    if (count == num_points) {
      ZnGetButtPoints(&ptr[1], ptr, width, cap_style==CapProjecting, outline, &outline[1]);
    }
    else if ((join_style == JoinMiter) && !miter2bevel) {
      outline[0] = outline[3];
      outline[1] = outline[2];
    }
    else {
      ZnGetButtPoints(&ptr[1], ptr, width, 0, outline, &outline[1]);
      /*
       * If joints are beveled, check the distance to the polygon
       * that fills the joint.
       */
      if ((join_style == JoinBevel) || miter2bevel) {
        outline[4] = outline[0];
        dist = ZnPolygonToPointDist(outline, 5, p);
        if (dist <= 0.0) {
          best_dist = 0.0;
          goto done;
        }
        else if (dist < best_dist) {
          best_dist = dist;
        }
        miter2bevel = False;
      }
    }
    if (count == 2) {
      ZnGetButtPoints(ptr, &ptr[1], width, cap_style==CapProjecting,
                      &outline[2], &outline[3]);
    }
    else if (join_style == JoinMiter) {
      if (ZnGetMiterPoints(ptr, &ptr[1], &ptr[2], width,
                         &outline[2], &outline[3]) == False) {
        miter2bevel = True;
        ZnGetButtPoints(ptr, &ptr[1], width, 0, &outline[2], &outline[3]);
      }
      /*printf("2=%g+%g, 3=%g+%g\n",
        outline[2].x, outline[2].y, outline[3].x, outline[3].y);*/
    }
    else {
      ZnGetButtPoints(ptr, &ptr[1], width, 0, &outline[2], &outline[3]);
    }
    outline[4] = outline[0];
    /*printf("0=%g+%g, 1=%g+%g, 2=%g+%g, 3=%g+%g, 4=%g+%g\n",
           outline[0].x, outline[0].y, outline[1].x, outline[1].y,
           outline[2].x, outline[2].y, outline[3].x, outline[3].y,
           outline[4].x, outline[4].y);*/
    dist = ZnPolygonToPointDist(outline, 5, p);
    if (dist <= 0.0) {
      best_dist = 0.0;
      goto done;
    }
    else if (dist < best_dist) {
      best_dist = dist;
    }
  }

  /*
   * Test the final point if cap style is round. The code so far
   * has only handled the butt and projecting cases.
   */
  if (cap_style == CapRound) {
    dist = hypot(ptr->x - p->x, ptr->y - p->y) - h_width;
    if (dist <= 0.0) {
      best_dist = 0.0;
      goto done;
    }
    else if (dist < best_dist) {
      best_dist = dist;
    }
  }
  
 done:
  return best_dist;
}


/*
 * Return the distance of the given oval to the point given.
 * The oval is described by its bounding box <xbb,ybb,wbb,hbb>,
 * the thickness of its outline <width>. Return values are negative
 * if the point is inside.
 */
ZnDim
ZnOvalToPointDist(ZnPoint       *center,
                  ZnDim         width,
                  ZnDim         height,
                  ZnDim         line_width,
                  ZnPoint       *p)
{
  ZnReal x_delta, y_delta;
  /*  ZnReal    x_diameter, y_diameter;*/
  ZnDim scaled_distance;
  ZnDim distance_to_outline;
  ZnDim distance_to_center;

  /*
   * Compute the distance from the point given to the center
   * of the oval. Then compute the same distance in a coordinate
   * system where the oval is a circle with unit radius.
   */

  x_delta = p->x - center->x;
  y_delta = p->y - center->y;
  distance_to_center = hypot(x_delta, y_delta);
  scaled_distance = hypot(x_delta / ((width + line_width) / 2.0),
                          y_delta / ((height + line_width) / 2.0));

  /*
   * If the scaled distance is greater than 1.0 the point is outside
   * the oval. Compute the distance to the edge and convert it back
   * to the original coordinate system. This distance is not much
   * accurate and can overestimate the real distance if the oval is
   * very eccentric.
   */
  if (scaled_distance > 1.0) {
    distance_to_outline = (distance_to_center / scaled_distance) * (scaled_distance - 1.0);
    return distance_to_outline;
  }

  /*
   * The point is inside the oval. Compute the distance as above and check
   * if the point is within the outline.
   */
  if (scaled_distance > 1.0e-10) {
    distance_to_outline = (distance_to_center / scaled_distance) * (1.0 - scaled_distance) - line_width;
  }
  else {
    /*
     * If the point is very close to the center avoid dividing by a
     * very small number, take another method.
     */
    if (width < height)
      distance_to_outline = (width - line_width) / 2;
    else
      distance_to_outline = (height - line_width) / 2;
  }

  if (distance_to_outline < 0.0)
    return 0.0;
  else
    return -distance_to_outline;
}


static int bezier_basis[][4] =
{
    {   -1,     3,     -3,      1},
    {    3,    -6,      3,      0},
    {   -3,     3,      0,      0},
    {    1,     0,      0,      0}
};

/*
 **********************************************************************************
 *
 * Arc2Param --
 *
 *      Given a Bezier curve describing an arc and an angle return the parameter
 *      value for the intersection point between the arc and the ray at angle.
 *
 **********************************************************************************
 */
#define EVAL(coeff, t) (((coeff[0]*t + coeff[1])*t + coeff[2]) * t + coeff[3])
static ZnReal
Arc2Param(ZnPoint       *controls,
          ZnReal        angle)
{
  ZnReal        coeff_x[4], coeff_y[4];
  ZnReal        min_angle, min_t, max_angle, max_t, cur_angle, cur_t;
  int           i, j, depth = 0;

  /* assume angle >= 0 */
  while (angle > M_PI) {
    angle -= 2 * M_PI;
  }

  for (i = 0; i < 4; i++) {
    coeff_x[i] = coeff_y[i] = 0.0;
    for (j = 0; j < 4; j++) {
      coeff_x[i] += bezier_basis[i][j] * controls[j].x;
      coeff_y[i] += bezier_basis[i][j] * controls[j].y;
    }
  }

  min_angle = atan2(controls[0].y, controls[0].x);
  max_angle = atan2(controls[3].y, controls[3].x);
  if (max_angle < min_angle) {
    min_angle -= M_PI+M_PI;
  }
  if (angle > max_angle) {
    angle -= M_PI+M_PI;
  }

  min_t = 0.0; max_t = 1.0;

  while (depth < 15) {
    cur_t = (max_t + min_t) / 2.0;
    cur_angle = atan2(EVAL(coeff_y, cur_t), EVAL(coeff_x, cur_t));
    if (angle > cur_angle) {
      min_t = cur_t;
      min_angle = cur_angle;
    }
    else {
      max_t = cur_t;
      max_angle = cur_angle;
    }
    depth += 1;
  }

  if ((max_angle-angle) < (angle-min_angle)) {
    return max_t;
  }

  return min_t;
}
#undef EVAL


/*
 **********************************************************************************
 *
 * BezierSubdivide --
 *
 *      Subdivide a Bezier curve given by controls at parameter t. Return
 *      in controls, the first or the last part depending on boolean first.
 *
 **********************************************************************************
 */
static void
BezierSubdivide(ZnPoint *controls,
                ZnReal  t,
                ZnBool  first)
{
  ZnReal        s = 1.0 - t;
  ZnPoint       r[7];
  ZnPoint       a;

  r[0] = controls[0];
  r[6] = controls[3];
  a.x = s*controls[1].x + t*controls[2].x;
  a.y = s*controls[1].y + t*controls[2].y;
  r[1].x = s*r[0].x + t*controls[1].x;
  r[1].y = s*r[0].y + t*controls[1].y;
  r[2].x = s*r[1].x + t*a.x;
  r[2].y = s*r[1].y + t*a.y;
  r[5].x = s*controls[2].x + t*r[6].x;
  r[5].y = s*controls[2].y + t*r[6].y;
  r[4].x = s*a.x + t*r[5].x;
  r[4].y = s*a.y + t*r[5].y;
  r[3].x = s*r[2].x + t*r[4].x;
  r[3].y = s*r[2].y + t*r[4].y;

  if (first) {
    memcpy(controls, r, 4*sizeof(ZnPoint));
  }
  else {
    memcpy(controls, &r[3], 4*sizeof(ZnPoint));
  }      
}


/*
 **********************************************************************************
 *
 * ZnGetBezierPoints --
 *      Use recursive subdivision to approximate the curve. The subdivision stops
 *      when the error is under eps.
 *      This algorithm is adaptive, meaning that it computes the minimum number
 *      of segments needed to render each curve part.
 *
 **********************************************************************************
 */
void
ZnGetBezierPoints(ZnPoint       *p1,
                  ZnPoint       *c1,
                  ZnPoint       *c2,
                  ZnPoint       *p2,
                  ZnList        to_points,
                  ZnReal        eps)
{
  ZnReal        dist;

  dist = ZnLineToPointDist(p1, p2, c1, NULL);
  if ((dist < eps) && ((c1->x != c2->x) || (c1->y != c2->y))) {
    dist = ZnLineToPointDist(p1, p2, c2, NULL);
  }

  if (dist > eps) {
    ZnPoint     mid_segm, new_c1, new_c2;
    /*
     * Subdivide the curve at t = 0.5
     * and compute each new curve.
     */
    mid_segm.x = (p1->x + 3*c1->x + 3*c2->x + p2->x) / 8.0;
    mid_segm.y = (p1->y + 3*c1->y + 3*c2->y + p2->y) / 8.0;
    new_c1.x = (p1->x + c1->x) / 2.0;
    new_c1.y = (p1->y + c1->y) / 2.0;
    new_c2.x = (p1->x + 2*c1->x + c2->x) / 4.0;
    new_c2.y = (p1->y + 2*c1->y + c2->y) / 4.0;
    ZnGetBezierPoints(p1, &new_c1, &new_c2, &mid_segm, to_points, eps);
    
    new_c1.x = (c1->x + 2*c2->x + p2->x) / 4.0;
    new_c1.y = (c1->y + 2*c2->y + p2->y) / 4.0;
    new_c2.x = (c2->x + (p2->x)) / 2.0;
    new_c2.y = (c2->y + (p2->y)) / 2.0;
    ZnGetBezierPoints(&mid_segm, &new_c1, &new_c2, p2, to_points, eps);
  }
  else {
    /*
     * Flat enough add the end to the current path.
     * The start should already be there.
     */
    ZnListAdd(to_points, p2, ZnListTail);
  }
}


/*
 **********************************************************************************
 *
 * ZnGetBezierPath --
 *      Compute in to_points a new set of points describing a Bezier path based
 *      on the control points given in from_points.
 *      If more than four points are given, the algorithm iterate over the
 *      set using the last point of a segment as the first point of the next.
 *      If 3 points are left, they are interpreted as a Bezier segment with
 *      coincident internal control points. If 2 points are left a straight
 *      is emitted.
 *
 **********************************************************************************
 */
void
ZnGetBezierPath(ZnList  from_points,
                ZnList  to_points)
{
  ZnPoint       *fp;
  int           num_fp, i;
  
  fp = ZnListArray(from_points);
  num_fp = ZnListSize(from_points);

  /*
   * make sure the output vector is empty, then add the first point.
   */
  ZnListEmpty(to_points);
  ZnListAdd(to_points, fp, ZnListTail);

  for (i = 0; i < num_fp; ) {
    if (i < (num_fp-3)) {
      ZnGetBezierPoints(fp, fp+1, fp+2, fp+3, to_points, 1.0);
      if (i < (num_fp-4)) {
        fp += 3;
        i += 3;
      }
      else {
        break;
      }
    }
    else if (i == (num_fp-3)) {
      ZnGetBezierPoints(fp, fp+1, fp+1, fp+2, to_points, 1.0);
      break;
    }
    else if (i == (num_fp-2)) {
      ZnListAdd(to_points, fp+1, ZnListTail);
      break;
    }
  }
}


/*
 **********************************************************************************
 *
 * ZnGetCirclePoints --
 *      Return a pointer to an array of points describing a
 *      circle arc of radius 1.0. The arc is described by start_angle,
 *      end_angle and the type: 0 for arc, 1 for chord, 2 for pie slice,
 *      3 for a full circle (in which case start_angle and end_angle are
 *      not used.
 *      The number of points is returned in num_points. If type is not 3,
 *      point_list must not be NULL. If not NULL, it is filled with the
 *      computed points.
 *
 **********************************************************************************
 */
ZnPoint *
ZnGetCirclePoints(int           type,
                  int           quality,
                  ZnReal        start_angle,
                  ZnReal        angle_extent,
                  unsigned int  *num_points,
                  ZnList        point_list)
{
  static CONST ZnPoint genarc_finest[] = { /* 128 */
    {1.0, 0.0},
    {0.99879545617, 0.0490676750517},
    {0.99518472653, 0.0980171417729},
    {0.989176509646, 0.146730476607},
    {0.980785279837, 0.195090324861},
    {0.970031252314, 0.24298018342},
    {0.956940334469, 0.290284681418},
    {0.941544063473, 0.336889858172},
    {0.923879530291, 0.382683437725},
    {0.903989290333, 0.42755509933},
    {0.88192126093, 0.471396743221},
    {0.857728605899, 0.514102751035},
    {0.831469607468, 0.555570240255},
    {0.803207525865, 0.595699312064},
    {0.773010446922, 0.634393292011},
    {0.74095111805, 0.671558962907},
    {0.707106772982, 0.707106789391},
    {0.671558945713, 0.740951133634},
    {0.634393274074, 0.773010461643},
    {0.595699293426, 0.803207539688},
    {0.555570220961, 0.83146962036},
    {0.514102731131, 0.857728617829},
    {0.471396722756, 0.881921271869},
    {0.427555078353, 0.903989300254},
    {0.382683416286, 0.923879539171},
    {0.336889836323, 0.94154407129},
    {0.290284659212, 0.956940341205},
    {0.242980160911, 0.970031257952},
    {0.195090302102, 0.980785284364},
    {0.146730453653, 0.98917651305},
    {0.0980171186795, 0.995184728805},
    {0.0490676518746, 0.998795457308},
    {-2.32051033331e-08, 1.0},
    {-0.0490676982289, 0.998795455031},
    {-0.0980171648663, 0.995184724256},
    {-0.146730499561, 0.989176506241},
    {-0.19509034762, 0.98078527531},
    {-0.24298020593, 0.970031246675},
    {-0.290284703624, 0.956940327733},
    {-0.33688988002, 0.941544055655},
    {-0.382683459163, 0.923879521411},
    {-0.427555120307, 0.903989280412},
    {-0.471396763686, 0.881921249991},
    {-0.514102770939, 0.85772859397},
    {-0.555570259549, 0.831469594576},
    {-0.595699330703, 0.803207512042},
    {-0.634393309949, 0.773010432201},
    {-0.6715589801, 0.740951102467},
    {-0.707106805799, 0.707106756574},
    {-0.740951149217, 0.671558928519},
    {-0.773010476365, 0.634393256136},
    {-0.803207553511, 0.595699274787},
    {-0.831469633252, 0.555570201666},
    {-0.857728629759, 0.514102711228},
    {-0.881921282808, 0.471396702291},
    {-0.903989310176, 0.427555057376},
    {-0.923879548052, 0.382683394847},
    {-0.941544079108, 0.336889814474},
    {-0.956940347941, 0.290284637006},
    {-0.97003126359, 0.242980138401},
    {-0.980785288892, 0.195090279343},
    {-0.989176516455, 0.146730430699},
    {-0.995184731079, 0.0980170955862},
    {-0.998795458447, 0.0490676286974},
    {-1.0, -4.64102066663e-08},
    {-0.998795453892, -0.049067721406},
    {-0.995184721981, -0.0980171879596},
    {-0.989176502836, -0.146730522515},
    {-0.980785270783, -0.195090370379},
    {-0.970031241037, -0.24298022844},
    {-0.956940320997, -0.29028472583},
    {-0.941544047838, -0.336889901869},
    {-0.923879512531, -0.382683480602},
    {-0.90398927049, -0.427555141284},
    {-0.881921239052, -0.471396784151},
    {-0.85772858204, -0.514102790842},
    {-0.831469581684, -0.555570278844},
    {-0.803207498218, -0.595699349341},
    {-0.77301041748, -0.634393327887},
    {-0.740951086883, -0.671558997294},
    {-0.707106740165, -0.707106822208},
    {-0.671558911325, -0.740951164801},
    {-0.634393238198, -0.773010491086},
    {-0.595699256149, -0.803207567335},
    {-0.555570182372, -0.831469646144},
    {-0.514102691324, -0.857728641689},
    {-0.471396681826, -0.881921293746},
    {-0.427555036399, -0.903989320097},
    {-0.382683373409, -0.923879556932},
    {-0.336889792626, -0.941544086926},
    {-0.2902846148, -0.956940354677},
    {-0.242980115891, -0.970031269229},
    {-0.195090256583, -0.980785293419},
    {-0.146730407745, -0.98917651986},
    {-0.0980170724928, -0.995184733354},
    {-0.0490676055202, -0.998795459585},
    {6.96153097774e-08, -1.0},
    {0.0490677445832, -0.998795452754},
    {0.098017211053, -0.995184719707},
    {0.146730545469, -0.989176499431},
    {0.195090393139, -0.980785266256},
    {0.242980250949, -0.970031235398},
    {0.290284748036, -0.956940314261},
    {0.336889923717, -0.94154404002},
    {0.382683502041, -0.923879503651},
    {0.427555162262, -0.903989260569},
    {0.471396804617, -0.881921228114},
    {0.514102810746, -0.85772857011},
    {0.555570298138, -0.831469568792},
    {0.59569936798, -0.803207484395},
    {0.634393345825, -0.773010402759},
    {0.671559014488, -0.740951071299},
    {0.707106838616, -0.707106723757},
    {0.740951180385, -0.671558894131},
    {0.773010505807, -0.63439322026},
    {0.803207581158, -0.59569923751},
    {0.831469659036, -0.555570163078},
    {0.857728653619, -0.51410267142},
    {0.881921304685, -0.471396661361},
    {0.903989330019, -0.427555015421},
    {0.923879565812, -0.38268335197},
    {0.941544094743, -0.336889770777},
    {0.956940361414, -0.290284592594},
    {0.970031274867, -0.242980093382},
    {0.980785297946, -0.195090233824},
    {0.989176523265, -0.146730384792},
    {0.995184735628, -0.0980170493994},
    {0.998795460724, -0.0490675823431},
    {1.0, 0.0}
  };
  static CONST ZnPoint genarc_finer[] = { /* 64 */
    {1.0, 0.0},
    {0.99518472653, 0.0980171417729},
    {0.980785279837, 0.195090324861},
    {0.956940334469, 0.290284681418},
    {0.923879530291, 0.382683437725},
    {0.88192126093, 0.471396743221},
    {0.831469607468, 0.555570240255},
    {0.773010446922, 0.634393292011},
    {0.707106772982, 0.707106789391},
    {0.634393274074, 0.773010461643},
    {0.555570220961, 0.83146962036},
    {0.471396722756, 0.881921271869},
    {0.382683416286, 0.923879539171},
    {0.290284659212, 0.956940341205},
    {0.195090302102, 0.980785284364},
    {0.0980171186795, 0.995184728805},
    {-2.32051033331e-08, 1.0},
    {-0.0980171648663, 0.995184724256},
    {-0.19509034762, 0.98078527531},
    {-0.290284703624, 0.956940327733},
    {-0.382683459163, 0.923879521411},
    {-0.471396763686, 0.881921249991},
    {-0.555570259549, 0.831469594576},
    {-0.634393309949, 0.773010432201},
    {-0.707106805799, 0.707106756574},
    {-0.773010476365, 0.634393256136},
    {-0.831469633252, 0.555570201666},
    {-0.881921282808, 0.471396702291},
    {-0.923879548052, 0.382683394847},
    {-0.956940347941, 0.290284637006},
    {-0.980785288892, 0.195090279343},
    {-0.995184731079, 0.0980170955862},
    {-1.0, -4.64102066663e-08},
    {-0.995184721981, -0.0980171879596},
    {-0.980785270783, -0.195090370379},
    {-0.956940320997, -0.29028472583},
    {-0.923879512531, -0.382683480602},
    {-0.881921239052, -0.471396784151},
    {-0.831469581684, -0.555570278844},
    {-0.77301041748, -0.634393327887},
    {-0.707106740165, -0.707106822208},
    {-0.634393238198, -0.773010491086},
    {-0.555570182372, -0.831469646144},
    {-0.471396681826, -0.881921293746},
    {-0.382683373409, -0.923879556932},
    {-0.2902846148, -0.956940354677},
    {-0.195090256583, -0.980785293419},
    {-0.0980170724928, -0.995184733354},
    {6.96153097774e-08, -1.0},
    {0.098017211053, -0.995184719707},
    {0.195090393139, -0.980785266256},
    {0.290284748036, -0.956940314261},
    {0.382683502041, -0.923879503651},
    {0.471396804617, -0.881921228114},
    {0.555570298138, -0.831469568792},
    {0.634393345825, -0.773010402759},
    {0.707106838616, -0.707106723757},
    {0.773010505807, -0.63439322026},
    {0.831469659036, -0.555570163078},
    {0.881921304685, -0.471396661361},
    {0.923879565812, -0.38268335197},
    {0.956940361414, -0.290284592594},
    {0.980785297946, -0.195090233824},
    {0.995184735628, -0.0980170493994},
    {1.0, 0.0}
  };
  static CONST ZnPoint genarc_fine[] = { /* 40 */
    {1.0, 0.0},
    {0.987688340232, 0.156434467332},
    {0.951056514861, 0.309016998789},
    {0.891006521028, 0.453990505942},
    {0.809016988919, 0.587785259802},
    {0.707106772982, 0.707106789391},
    {0.587785241028, 0.809017002559},
    {0.453990485266, 0.891006531563},
    {0.309016976719, 0.951056522032},
    {0.156434444413, 0.987688343862},
    {-2.32051033331e-08, 1.0},
    {-0.156434490252, 0.987688336602},
    {-0.309017020858, 0.95105650769},
    {-0.453990526618, 0.891006510493},
    {-0.587785278575, 0.809016975279},
    {-0.707106805799, 0.707106756574},
    {-0.809017016198, 0.587785222255},
    {-0.891006542098, 0.453990464591},
    {-0.951056529203, 0.30901695465},
    {-0.987688347492, 0.156434421493},
    {-1.0, -4.64102066663e-08},
    {-0.987688332972, -0.156434513171},
    {-0.951056500519, -0.309017042928},
    {-0.891006499958, -0.453990547294},
    {-0.80901696164, -0.587785297348},
    {-0.707106740165, -0.707106822208},
    {-0.587785203482, -0.809017029838},
    {-0.453990443915, -0.891006552633},
    {-0.309016932581, -0.951056536373},
    {-0.156434398574, -0.987688351122},
    {6.96153097774e-08, -1.0},
    {0.15643453609, -0.987688329342},
    {0.309017064997, -0.951056493349},
    {0.45399056797, -0.891006489423},
    {0.587785316122, -0.809016948},
    {0.707106838616, -0.707106723757},
    {0.809017043478, -0.587785184709},
    {0.891006563167, -0.453990423239},
    {0.951056543544, -0.309016910511},
    {0.987688354752, -0.156434375655},
    {1.0, 0.0}
  };  
  static CONST ZnPoint genarc_medium[] = { /* 20 */
    {1.0, 0.0},
    {0.951056514861, 0.309016998789},
    {0.809016988919, 0.587785259802},
    {0.587785241028, 0.809017002559},
    {0.309016976719, 0.951056522032},
    {-2.32051033331e-08, 1.0},
    {-0.309017020858, 0.95105650769},
    {-0.587785278575, 0.809016975279},
    {-0.809017016198, 0.587785222255},
    {-0.951056529203, 0.30901695465},
    {-1.0, -4.64102066663e-08},
    {-0.951056500519, -0.309017042928},
    {-0.80901696164, -0.587785297348},
    {-0.587785203482, -0.809017029838},
    {-0.309016932581, -0.951056536373},
    {6.96153097774e-08, -1.0},
    {0.309017064997, -0.951056493349},
    {0.587785316122, -0.809016948},
    {0.809017043478, -0.587785184709},
    {0.951056543544, -0.309016910511},
    {1.0, 0.0}
  };
  static CONST ZnPoint genarc_coarse[] = { /* 10 */
    {1.0, 0.0},
    {0.809016988919, 0.587785259802},
    {0.309016976719, 0.951056522032},
    {-0.309017020858, 0.95105650769},
    {-0.809017016198, 0.587785222255},
    {-1.0, -4.64102066663e-08},
    {-0.80901696164, -0.587785297348},
    {-0.309016932581, -0.951056536373},
    {0.309017064997, -0.951056493349},
    {0.809017043478, -0.587785184709},
    {1.0, 0.0}
  };
  unsigned int  num_p, i;
  ZnPoint       *p, *p_from;
  ZnPoint       center_p = { 0.0, 0.0 };
  ZnPoint       start_p, wp;
  ZnReal        iangle, end_angle=0;

  switch (quality) {
  case ZN_CIRCLE_COARSE:
    num_p = sizeof(genarc_coarse)/sizeof(ZnPoint);
    p = p_from = (ZnPoint *) genarc_coarse;
    break;
  case ZN_CIRCLE_MEDIUM:
    num_p = sizeof(genarc_medium)/sizeof(ZnPoint);
    p = p_from = (ZnPoint *) genarc_medium;
    break;
  case ZN_CIRCLE_FINER:
    num_p = sizeof(genarc_finer)/sizeof(ZnPoint);
    p = p_from = (ZnPoint *) genarc_finer;
    break;
  case ZN_CIRCLE_FINEST:
    num_p = sizeof(genarc_finest)/sizeof(ZnPoint);
    p = p_from = (ZnPoint *) genarc_finest;
    break;
  default:
  case ZN_CIRCLE_FINE:
    num_p = sizeof(genarc_fine)/sizeof(ZnPoint);
    p = p_from = (ZnPoint *) genarc_fine;
  }
  
  /*printf("start: %g, extent: %g\n", start_angle, angle_extent);*/
  if (angle_extent == 2*M_PI) {
    type = 3;
  }
  if (type != 3) {
    end_angle = start_angle+angle_extent;
    if (angle_extent < 0) {
      iangle = start_angle;
      start_angle = end_angle;
      end_angle = iangle;
    }
    /*
     * normalize start_angle and end_angle.
     */
    if (start_angle < 0.0) {
      start_angle += 2.0*M_PI;
    }
    if (end_angle < 0.0) {
      end_angle += 2.0*M_PI;
    }
    if (end_angle < start_angle) {
      end_angle += 2.0*M_PI;
    }
    /*printf("---start: %g, end: %g\n", start_angle, end_angle);*/
  }
  
  /*
   * Now 0 <= start_angle < 2 * M_PI and start_angle <= end_angle.
   */
  if ((type != 3) || (point_list != NULL)) {
    if (type == 3) {
      ZnListAssertSize(point_list, num_p);
      p = ZnListArray(point_list);
      for (i = 0; i < num_p; i++, p++, p_from++) {
        *p = *p_from;
      }
    }
    else {
      ZnListEmpty(point_list);
      iangle = 2*M_PI / (num_p-1);
      start_p.x = cos(start_angle);
      start_p.y = sin(start_angle);
      ZnListAdd(point_list, &start_p, ZnListTail);
      i = (unsigned int) (start_angle / iangle);
      if ((i * iangle) < start_angle) {
        i++;
      }
      while (1) {
        if (start_angle + iangle <= end_angle) {
          if (i == num_p-1) {
            i = 0;
          }
          ZnListAdd(point_list, &p_from[i], ZnListTail);
          start_angle += iangle;
          i++;
        }
        else {
          wp.x = cos(end_angle);
          wp.y = sin(end_angle);
          ZnListAdd(point_list, &wp, ZnListTail);
          break;
        }
      }
      if (type == 1) {
        ZnListAdd(point_list, &start_p, ZnListTail);
      }
      else if (type == 2) {
        ZnListAdd(point_list, &center_p, ZnListTail);
        ZnListAdd(point_list, &start_p, ZnListTail);
      }
    }
    p = ZnListArray(point_list);
    num_p = ZnListSize(point_list);
  }
  
  *num_points = num_p;
  return p;
}

/*
 **********************************************************************************
 *
 * ZnGetArcPath --
 *      Compute in to_points a set of Bezier control points describing an arc
 *      path given the start angle, the stop angle and the type: 0 for arc,
 *      1 for chord, 2 for pie slice.
 *      To obtain the actual polygonal shape, the client should use GetBezierPath
 *      on the returned controls (after applying transform). The returned arc
 *      is circular and centered on 0,0.
 *
 **********************************************************************************
 */
static ZnReal arc_nodes_x[4] = { 1.0, 0.0, -1.0, 0.0 };
static ZnReal arc_nodes_y[4] = { 0.0, 1.0,  0.0, -1.0 };
static ZnReal arc_controls_x[8] = { 1.0, 0.55197, -0.55197, -1.0, -1.0, -0.55197, 0.55197, 1.0 };
static ZnReal arc_controls_y[8] = { 0.55197, 1.0, 1.0, 0.55197, -0.55197, -1.0, -1.0, -0.55197 };
void
ZnGetArcPath(ZnReal     start_angle,
             ZnReal     end_angle,
             int        type,
             ZnList     to_points)
{
  int           start_quad, end_quad, quadrant;
  ZnPoint       center_p = { 0.0, 0.0 };
  ZnPoint       start_p = center_p;
  
  /*
   * make sure the output vector is empty.
   */
  ZnListEmpty(to_points);
  
  /*
   * normalize start_angle and end_angle.
   */
  start_angle = fmod(start_angle, 2.0*M_PI);
  if (start_angle < 0.0) {
    start_angle += 2.0*M_PI;
  }
  end_angle = fmod(end_angle, 2.0*M_PI);
  if (end_angle < 0.0) {
    end_angle += 2.0*M_PI;
  }
  if (start_angle >= end_angle) {
    if (start_angle == end_angle) {
      type = 3;
    }
    end_angle += 2.0*M_PI;
  }
  
  /*
   * Now 0 <= start_angle < 2 * M_PI and start_angle <= end_angle.
   */

  start_quad = (int) (start_angle / (M_PI / 2.0));
  end_quad = (int) (end_angle / (M_PI / 2.0));

  for (quadrant = start_quad; quadrant <= end_quad; quadrant++) {
    ZnPoint controls[4];
    ZnReal  t;
    
    controls[0].x = arc_nodes_x[quadrant % 4];
    controls[0].y = arc_nodes_y[quadrant % 4];
    controls[1].x = arc_controls_x[2 * (quadrant % 4)];
    controls[1].y = arc_controls_y[2 * (quadrant % 4)];
    controls[2].x = arc_controls_x[2 * (quadrant % 4) + 1];
    controls[2].y = arc_controls_y[2 * (quadrant % 4) + 1];
    controls[3].x = arc_nodes_x[(quadrant + 1) % 4];
    controls[3].y = arc_nodes_y[(quadrant + 1) % 4];
    
    if (quadrant == start_quad) {
      t = Arc2Param(controls, start_angle);
      BezierSubdivide(controls, t, False);
      /*
       * The path is still empty and we have to create the first
       * vertex.
       */
      start_p = controls[0];
      ZnListAdd(to_points, &controls[0], ZnListTail);
    }
    if (quadrant == end_quad) {
      t = Arc2Param(controls, end_angle);
      if (!t) {
        break;
      }
      BezierSubdivide(controls, t, True);
    }
    ZnListAdd(to_points, &controls[1], ZnListTail);
    ZnListAdd(to_points, &controls[2], ZnListTail);
    ZnListAdd(to_points, &controls[3], ZnListTail);
  }

  if (type == 2) {
    ZnListAdd(to_points, &center_p, ZnListTail);
    /*
     * Can't add this one, it would be interpreted by GetBezierPath
     * as an off-curve control. The path should be closed by the client
     * after expansion by GetBezierPath.
     *
      ZnListAdd(to_points, &start_p, ZnListTail); 
     */
  }
  else if (type == 1) {
    ZnListAdd(to_points, &start_p, ZnListTail); 
  }
}


/*
 **********************************************************************************
 *
 * SmoothPathWithBezier --
 *      Compute in to_points a new set of points describing a smoothed path based
 *      on the path given in from_points. The algorithm use Bezier cubic curves.
 *
 **********************************************************************************
 */
void
ZnSmoothPathWithBezier(ZnPoint          *fp,
                       unsigned int     num_fp,
                       ZnList           to_points)
{
  ZnBool        closed;
  ZnPoint       s[4];
  unsigned int  i;

  /*
   * make sure the output vector is empty
   */
  ZnListEmpty(to_points);

  /*
   * If the curve is closed, generates a Bezier curve that
   * spans the closure. Else simply add the first point to
   * the path.
   */
  if ((fp[0].x == fp[num_fp-1].x) && (fp[0].y == fp[num_fp-1].y)) {
    closed = True;
    s[0].x = 0.5*fp[num_fp-2].x + 0.5*fp[0].x;
    s[0].y = 0.5*fp[num_fp-2].y + 0.5*fp[0].y;
    s[1].x = 0.167*fp[num_fp-2].x + 0.833*fp[0].x;
    s[1].y = 0.167*fp[num_fp-2].y + 0.833*fp[0].y;
    s[2].x = 0.833*fp[0].x + 0.167*fp[1].x;
    s[2].y = 0.833*fp[0].y + 0.167*fp[1].y;
    s[3].x = 0.5*fp[0].x + 0.5*fp[1].x;
    s[3].y = 0.5*fp[0].y + 0.5*fp[1].y;
    ZnListAdd(to_points, s, ZnListTail);
    ZnGetBezierPoints(s, s+1, s+2, s+3, to_points, 1.0);
  }
  else {
    closed = False;
    ZnListAdd(to_points, &fp[0], ZnListTail);
  }

  for (i = 2; i < num_fp; i++, fp++) {
    /*
     * Setup the first two control points. This differ
     * for first segment of open curves.
     */
    if ((i == 2) && !closed) {
      s[0] = fp[0];
      s[1].x = 0.333*fp[0].x + 0.667*fp[1].x;
      s[1].y = 0.333*fp[0].y + 0.667*fp[1].y;
    }
    else {
      s[0].x = 0.5*fp[0].x + 0.5*fp[1].x;
      s[0].y = 0.5*fp[0].y + 0.5*fp[1].y;
      s[1].x = 0.167*fp[0].x + 0.833*fp[1].x;
      s[1].y = 0.167*fp[0].y + 0.833*fp[1].y;
    }

    /*
     * Setup the last two control points. This also differ
     * for last segment of open curves.
     */
    if ((i == num_fp-1) && !closed) {
      s[2].x = 0.667*fp[1].x + 0.333*fp[2].x;
      s[2].y = 0.667*fp[1].y + 0.333*fp[2].y;
      s[3] = fp[2];
    }
    else {
      s[2].x = 0.833*fp[1].x + 0.167*fp[2].x;
      s[2].y = 0.833*fp[1].y + 0.167*fp[2].y;
      s[3].x = 0.5*fp[1].x + 0.5*fp[2].x;
      s[3].y = 0.5*fp[1].y + 0.5*fp[2].y;
    }

    /*
     * If the first two points or the last two are equal
     * output the last control point. Else generate the
     * Bezier curve.
     */
    if (((fp[0].x == fp[1].x) && (fp[0].y == fp[1].y)) ||
        ((fp[1].x == fp[2].x) && (fp[1].y == fp[2].y))) {
      ZnListAdd(to_points, &s[3], ZnListTail);
    }
    else {
      ZnGetBezierPoints(s, s+1, s+2, s+3, to_points, 1.0);
    }
  }
}


/*
 **********************************************************************************
 *
 * FitBezier --
 *      Fit a Bezier curve to a (sub)set of digitized points.
 *
 *      From: An Algorithm for Automatically Fitting Digitized Curves
 *            by Philip J. Schneider in "Graphics Gems", Academic Press, 1990
 *
 **********************************************************************************
 */

static ZnReal
V2DistanceBetween2Points(ZnPoint        *a,
                         ZnPoint        *b)
{
  ZnReal dx = a->x - b->x;
  ZnReal dy = a->y - b->y;
  return sqrt((dx*dx)+(dy*dy));
}

static ZnReal
V2SquaredLength(ZnPoint *a)
{       
  return (a->x * a->x)+(a->y * a->y);
}

static ZnReal
V2Length(ZnPoint        *a)
{
  return sqrt(V2SquaredLength(a));
}
        
static ZnPoint *
V2Scale(ZnPoint *v,
        ZnReal  newlen)
{
  ZnReal len = V2Length(v);
  if (len != 0.0) {
    v->x *= newlen/len;
    v->y *= newlen/len;
  }
  return v;
}

static ZnPoint *
V2Negate(ZnPoint *v)
{
  v->x = -v->x;  v->y = -v->y;
  return v;
}

static ZnPoint *
V2Normalize(ZnPoint *v)
{
  ZnReal len = sqrt(V2Length(v));
  if (len != 0.0) {
    v->x /= len;
    v->y /= len;
  }
  return v;
}
static ZnPoint *
V2Add(ZnPoint   *a,
      ZnPoint   *b,
      ZnPoint   *c)
{
  c->x = a->x + b->x;
  c->y = a->y + b->y;
  return c;
}
        
static ZnReal
V2Dot(ZnPoint   *a,
      ZnPoint   *b) 
{
  return (a->x*b->x) + (a->y*b->y);
}

static ZnPoint
V2AddII(ZnPoint a,
        ZnPoint b)
{
  ZnPoint c;
  c.x = a.x + b.x;
  c.y = a.y + b.y;
  return c;
}

static ZnPoint
V2ScaleIII(ZnPoint      v,
           ZnReal       s)
{
  ZnPoint result;
  result.x = v.x * s;
  result.y = v.y * s;
  return result;
}

static ZnPoint
V2SubII(ZnPoint a,
        ZnPoint b)
{
  ZnPoint c;
  c.x = a.x - b.x;
  c.y = a.y - b.y;
  return c;
}

/*
 * B0, B1, B2, B3, Bezier multipliers.
 */
static ZnReal
B0(ZnReal       u)
{
  ZnReal tmp = 1.0 - u;
  return tmp * tmp * tmp;
}

static ZnReal
B1(ZnReal       u)
{
  ZnReal tmp = 1.0 - u;
  return 3 * u * (tmp * tmp);
}

static ZnReal
B2(ZnReal       u)
{
  ZnReal tmp = 1.0 - u;
  return 3 * u * u * tmp;
}

static ZnReal
B3(ZnReal       u)
{
  return u * u * u;
}

/*
 * ChordLengthParameterize  --
 *      Assign parameter values to digitized points 
 *      using relative distances between points.
 */
static ZnReal *
ChordLengthParameterize(ZnPoint         *d,
                        unsigned int    first,
                        unsigned int    last)
{
  unsigned int  i;
  ZnReal        *u;

  u = (ZnReal *) ZnMalloc((unsigned) (last-first+1) * sizeof(ZnReal));
  
  u[0] = 0.0;
  for (i = first+1; i <= last; i++) {
    u[i-first] = u[i-first-1] + V2DistanceBetween2Points(&d[i], &d[i-1]);
  }
  
  for (i = first + 1; i <= last; i++) {
    u[i-first] = u[i-first] / u[last-first];
  }
  
  return u;
}

/*
 * Bezier --
 *      Evaluate a Bezier curve at a particular parameter value
 * 
 */
static ZnPoint
BezierII(int            degree,
         ZnPoint        *V,
         ZnReal         t)
{
  int           i, j;           
  ZnPoint       Q;              /* Point on curve at parameter t        */
  ZnPoint       *Vtemp;         /* Local copy of control points         */
  
  /* Copy array */
  Vtemp = (ZnPoint *) ZnMalloc((unsigned)((degree+1) * sizeof (ZnPoint)));
  for (i = 0; i <= degree; i++) {
    Vtemp[i] = V[i];
  }
  
  /* Triangle computation */
  for (i = 1; i <= degree; i++) {       
    for (j = 0; j <= degree-i; j++) {
      Vtemp[j].x = (1.0 - t) * Vtemp[j].x + t * Vtemp[j+1].x;
      Vtemp[j].y = (1.0 - t) * Vtemp[j].y + t * Vtemp[j+1].y;
    }
  }
  
  Q = Vtemp[0];
  ZnFree(Vtemp);
  return Q;
}

/*
 * NewtonRaphsonRootFind --
 *      Use Newton-Raphson iteration to find better root.
 */
static ZnReal
NewtonRaphsonRootFind(ZnPoint   *Q,
                      ZnPoint   P,
                      ZnReal    u)
{
  ZnReal        numerator, denominator;
  ZnPoint       Q1[3], Q2[2];           /*  Q' and Q''                  */
  ZnPoint       Q_u, Q1_u, Q2_u;        /*u evaluated at Q, Q', & Q''   */
  ZnReal        uPrime;                 /*  Improved u                  */
  unsigned int  i;
    
  /* Compute Q(u)       */
  Q_u = BezierII(3, Q, u);
    
  /* Generate control vertices for Q'   */
  for (i = 0; i <= 2; i++) {
    Q1[i].x = (Q[i+1].x - Q[i].x) * 3.0;
    Q1[i].y = (Q[i+1].y - Q[i].y) * 3.0;
  }
    
  /* Generate control vertices for Q'' */
  for (i = 0; i <= 1; i++) {
    Q2[i].x = (Q1[i+1].x - Q1[i].x) * 2.0;
    Q2[i].y = (Q1[i+1].y - Q1[i].y) * 2.0;
  }
  
  /* Compute Q'(u) and Q''(u)   */
  Q1_u = BezierII(2, Q1, u);
  Q2_u = BezierII(1, Q2, u);
    
  /* Compute f(u)/f'(u) */
  numerator = (Q_u.x - P.x) * (Q1_u.x) + (Q_u.y - P.y) * (Q1_u.y);
  denominator = (Q1_u.x) * (Q1_u.x) + (Q1_u.y) * (Q1_u.y) +
                (Q_u.x - P.x) * (Q2_u.x) + (Q_u.y - P.y) * (Q2_u.y);
    
  /* u = u - f(u)/f'(u) */
  uPrime = u - (numerator/denominator);
  return (uPrime);
}

/*
 * Reparameterize --
 *      Given set of points and their parameterization, try to find
 *      a better parameterization.
 */
static ZnReal *
Reparameterize(ZnPoint          *d,
               unsigned int     first,
               unsigned int     last, 
               ZnReal           *u,
               ZnPoint          *bezCurve)
{
  unsigned int  nPts = last-first+1;    
  unsigned int  i;
  ZnReal        *uPrime;        /*  New parameter values        */

  uPrime = (ZnReal *) ZnMalloc(nPts * sizeof(ZnReal));
  for (i = first; i <= last; i++) {
    uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i-first]);
  }
  return (uPrime);
}

/*
 * GenerateBezier --
 *      Use least-squares method to find Bezier control
 *      points for region.
 */
static void
GenerateBezier(ZnPoint          *d,
               unsigned int     first,
               unsigned int     last, 
               ZnReal           *uPrime, 
               ZnPoint          tHat1,
               ZnPoint          tHat2,
               ZnPoint          *bez_curve)
{
  unsigned int  i;
  ZnPoint       *A0, *A1;       /* Precomputed rhs for eqn      */
  unsigned int  num_points;     /* Number of pts in sub-curve */
  ZnReal        C[2][2];        /* Matrix C             */
  ZnReal        X[2];           /* Matrix X                     */
  ZnReal        det_C0_C1;      /* Determinants of matrices     */
  ZnReal        det_C0_X, det_X_C1;
  ZnReal        alpha_l;        /* Alpha values, left and right */
  ZnReal        alpha_r;
  ZnPoint       tmp;            /* Utility variable             */
  
  num_points = last - first + 1;
  A0 = (ZnPoint *) ZnMalloc(num_points * sizeof(ZnPoint));
  A1 = (ZnPoint *) ZnMalloc(num_points * sizeof(ZnPoint));
  
  /* Compute the A's    */
  for (i = 0; i < num_points; i++) {
    ZnPoint     v1, v2;
    v1 = tHat1;
    v2 = tHat2;
    V2Scale(&v1, B1(uPrime[i]));
    V2Scale(&v2, B2(uPrime[i]));
    A0[i] = v1;
    A1[i] = v2;
  }

  /* Create the C and X matrices        */
  C[0][0] = 0.0;
  C[0][1] = 0.0;
  C[1][0] = 0.0;
  C[1][1] = 0.0;
  X[0]    = 0.0;
  X[1]    = 0.0;

  for (i = 0; i < num_points; i++) {
    C[0][0] += V2Dot(&A0[i], &A0[i]);
    C[0][1] += V2Dot(&A0[i], &A1[i]);
    C[1][0] = C[0][1];
    C[1][1] += V2Dot(&A1[i], &A1[i]);

    tmp = V2SubII(d[first + i],
                  V2AddII(V2ScaleIII(d[first], B0(uPrime[i])),
                          V2AddII(V2ScaleIII(d[first], B1(uPrime[i])),
                                  V2AddII(V2ScaleIII(d[last], B2(uPrime[i])),
                                          V2ScaleIII(d[last], B3(uPrime[i]))))));

    X[0] += V2Dot(&A0[i], &tmp);
    X[1] += V2Dot(&A1[i], &tmp);
  }

  /* Compute the determinants of C and X        */
  det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
  det_C0_X  = C[0][0] * X[1]    - C[0][1] * X[0];
  det_X_C1  = X[0]    * C[1][1] - X[1]    * C[0][1];

  /* Finally, derive alpha values       */
  if (det_C0_C1 == 0.0) {
    det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
  }
  alpha_l = det_X_C1 / det_C0_C1;
  alpha_r = det_C0_X / det_C0_C1;

  /*  If alpha negative, use the Wu/Barsky heuristic (see text) */
  if (alpha_l < 0.0 || alpha_r < 0.0) {
    ZnReal dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
    
    bez_curve[0] = d[first];
    bez_curve[3] = d[last];
    V2Add(&bez_curve[0], V2Scale(&tHat1, dist), &bez_curve[1]);
    V2Add(&bez_curve[3], V2Scale(&tHat2, dist), &bez_curve[2]);
  }
  else {
    /*  First and last control points of the Bezier curve are */
    /*  positioned exactly at the first and last data points */
    /*  Control points 1 and 2 are positioned an alpha distance out */
    /*  on the tangent vectors, left and right, respectively */
    bez_curve[0] = d[first];
    bez_curve[3] = d[last];
    V2Add(&bez_curve[0], V2Scale(&tHat1, alpha_l), &bez_curve[1]);
    V2Add(&bez_curve[3], V2Scale(&tHat2, alpha_r), &bez_curve[2]);
  }
  ZnFree(A0);
  ZnFree(A1);
}

/*
 * ComputeMaxError --
 *      Find the maximum squared distance of digitized points
 *      to fitted curve.
*/
static ZnReal
ComputeMaxError(ZnPoint         *d,
                unsigned int    first,
                unsigned int    last, 
                ZnPoint         *bez_curve,
                ZnReal          *u, 
                unsigned int    *splitPoint)
{
  unsigned int  i;
  ZnReal        maxDist;        /*  Maximum error               */
  ZnReal        dist;           /*  Current error               */
  ZnPoint       P;              /*  Point on curve              */
  ZnPoint       v;              /*  Vector from point to curve  */
  
  *splitPoint = (last - first + 1)/2;
  maxDist = 0.0;
  for (i = first + 1; i < last; i++) {
    P = BezierII(3, bez_curve, u[i-first]);
    v = V2SubII(P, d[i]);
    dist = V2SquaredLength(&v);
    if (dist >= maxDist) {
      maxDist = dist;
      *splitPoint = i;
    }
  }
  return (maxDist);
}

/*
 * ComputeLeftTangent,
 * ComputeRightTangent,
 * ComputeCenterTangent --
 *      Approximate unit tangents at endpoints and
 *      center of digitized curve.
 */
static ZnPoint
ComputeLeftTangent(ZnPoint      *d,
                   unsigned int end)
{
  ZnPoint tHat1;
  tHat1 = V2SubII(d[end+1], d[end]);
  tHat1 = *V2Normalize(&tHat1);
  return tHat1;
}

static ZnPoint
ComputeRightTangent(ZnPoint      *d,
                    unsigned int end)
{
  ZnPoint tHat2;
  tHat2 = V2SubII(d[end-1], d[end]);
  tHat2 = *V2Normalize(&tHat2);
  return tHat2;
}


static ZnPoint
ComputeCenterTangent(ZnPoint      *d,
                     unsigned int center)
{
  ZnPoint       V1, V2, tHatCenter;

  V1 = V2SubII(d[center-1], d[center]);
  V2 = V2SubII(d[center], d[center+1]);
  tHatCenter.x = (V1.x + V2.x)/2.0;
  tHatCenter.y = (V1.y + V2.y)/2.0;
  tHatCenter = *V2Normalize(&tHatCenter);
  return tHatCenter;
}

static void
FitCubic(ZnPoint        *d,
         unsigned int   first,
         unsigned int   last,
         ZnPoint        tHat1, 
         ZnPoint        tHat2,
         ZnReal         error,
         ZnList         controls)
{
  ZnPoint       *bez_curve;     /* Control points of fitted Bezier curve*/
  ZnReal        *u;             /* Parameter values for point  */
  ZnReal        *uPrime;        /* Improved parameter values */
  ZnReal        max_err;        /* Maximum fitting error         */
  unsigned int  splitPoint;     /* Point to split point set at   */
  unsigned int  num_points;     /* Number of points in subset  */
  ZnReal        iteration_err;  /* Error below which you try iterating  */
  unsigned int  max_iter = 4;   /* Max times to try iterating  */
  ZnPoint       tHatCenter;     /* Unit tangent vector at splitPoint */
  unsigned int  i;              

  iteration_err = error * error;
  num_points = last - first + 1;
  ZnListAssertSize(controls, ZnListSize(controls)+4);
  bez_curve = ZnListAt(controls, ZnListSize(controls)-4);
  
  /*  Use heuristic if region only has two points in it */
  if (num_points == 2) {
    ZnReal dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;

    bez_curve[0] = d[first];
    bez_curve[3] = d[last];
    V2Add(&bez_curve[0], V2Scale(&tHat1, dist), &bez_curve[1]);
    V2Add(&bez_curve[3], V2Scale(&tHat2, dist), &bez_curve[2]);
    return;
  }

  /*  Parameterize points, and attempt to fit curve */
  u = ChordLengthParameterize(d, first, last);
  GenerateBezier(d, first, last, u, tHat1, tHat2, bez_curve);
  
  /*  Find max deviation of points to fitted curve */
  max_err = ComputeMaxError(d, first, last, bez_curve, u, &splitPoint);
  if (max_err < error) {
    ZnFree(u);
    return;
  }
  
  /*
   * If error not too large, try some reparameterization
   *  and iteration.
   */
  if (max_err < iteration_err) {
    for (i = 0; i < max_iter; i++) {
      uPrime = Reparameterize(d, first, last, u, bez_curve);
      GenerateBezier(d, first, last, uPrime, tHat1, tHat2, bez_curve);
      max_err = ComputeMaxError(d, first, last,
                                bez_curve, uPrime, &splitPoint);
      if (max_err < error) {
        ZnFree(u);
        return;
      }
      ZnFree(u);
      u = uPrime;
    }
  }
  
  /* Fitting failed -- split at max error point and fit recursively */
  ZnFree(u);
  ZnListAssertSize(controls, ZnListSize(controls)-4);
  tHatCenter = ComputeCenterTangent(d, splitPoint);
  FitCubic(d, first, splitPoint, tHat1, tHatCenter, error, controls);
  V2Negate(&tHatCenter);
  FitCubic(d, splitPoint, last, tHatCenter, tHat2, error, controls);
}

void
ZnFitBezier(ZnPoint             *pts,
            unsigned int        num_points,
            ZnReal              error,
            ZnList              controls)
{
  ZnPoint       tHat1, tHat2;   /*  Unit tangent vectors at endpoints */

  tHat1 = ComputeLeftTangent(pts, 0);
  tHat2 = ComputeRightTangent(pts, num_points-1);
  FitCubic(pts, 0, num_points-1, tHat1, tHat2, error, controls);
}

Added jni/tkzinc/generic/Geo.h.















































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
/*
 * Geo.h -- Header for common geometric routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Geo_h
#define _Geo_h


#include "Attrs.h"
#include "List.h"

#include <math.h>
#include <limits.h>


#ifndef M_PI
#define M_PI            3.14159265358979323846264338327
#endif
#ifndef M_PI_2
#define M_PI_2          1.57079632679489661923
#endif
#ifndef M_PI_4
#define M_PI_4          0.78539816339744830962
#endif

#define PRECISION_LIMIT         1.0e-10
#define X_PRECISION_LIMIT       5.0e-2
#define ZN_LINE_END_POINTS      6

/*
 * Constants used to specify circle approximation quality.
 */
#define ZN_CIRCLE_COARSE 0
#define ZN_CIRCLE_MEDIUM ZN_CIRCLE_COARSE+1
#define ZN_CIRCLE_FINE ZN_CIRCLE_MEDIUM+1
#define ZN_CIRCLE_FINER ZN_CIRCLE_FINE+1
#define ZN_CIRCLE_FINEST ZN_CIRCLE_FINER+1
  

/*
 * I would like to make these be floats,
 * but have to investigate how. Structures
 * handed to GL or GLU tess _must_ have
 * points has doubles.
 */
typedef struct {
  double        x, y;
} ZnPoint;

typedef struct {
  double        x, y, w, h;
} ZnRect;

/*
 * ZnBBox: orig is into the area while corner is not.
 * Thus the test: ((bbox.orig.x == bbox.corner.x) ||
 *                 (bbox.orig.y == bbox.corner.y))
 * tells whether the bbox is empty or not.
 * When interpreting bboxes the X coordinate system is
 * the norm. x goes from left toward the right and y
 * goes from the top toward the bottom. Bboxes are
 * always axes aligned.
 */
typedef struct {
  ZnPoint       orig, corner;
} ZnBBox;

typedef struct {
  unsigned int  num_points;
  ZnPoint       *points;
  char          *controls;
  ZnBool        cw;
} ZnContour;

/*
 * contour1 can be used to store a single contour
 * without having to alloc the contours array.
 */
typedef struct {
  unsigned int  num_contours;
  ZnContour     *contours;
  ZnContour     contour1;
} ZnPoly;

/*
 * Keep this enum in sync with op_strings in Contour()
 * in tkZinc.c.
 */
typedef enum {
  ZN_CONTOUR_ADD, ZN_CONTOUR_REMOVE
} ZnContourCmd;

typedef struct {
  unsigned int  num_points;
  ZnPoint       *points;
  ZnBool        fan;    /* When using a fan, all contour vertices must be
                         * included to describe the contour as a polygon
                         * (clipping code use that to speed up region
                         * rendering) and the center must be the first
                         * vertex. */
} ZnStrip;
  
typedef struct {
  unsigned int  num_strips;
  ZnStrip       *strips;
  ZnStrip       strip1;
} ZnTriStrip;


#ifndef MIN
#define MIN(a, b)       ((a) <= (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b)       ((a) >= (b) ? (a) : (b))
#endif
#ifndef ABS
#define ABS(a)          ((a) < 0 ? -(a) : (a))
#endif

#define ZnDegRad(angle) \
  (M_PI * (double) (angle) / 180.0)
#define ZnRadDeg(angle) \
  (fmod((angle) * 180.0 / M_PI, 360.0))
#define ZnRadDeg360(angle) \
  (fmod(ZnRadDeg(angle)+360.0,360.0))

#define ZnNearestInt(d) \
  (((int) ((d) + (((d) > 0) ? 0.5 : -0.5))))

void
ZnPolyInit(ZnPoly       *poly);
void
ZnPolyContour1(ZnPoly           *poly,
               ZnPoint          *pts,
               unsigned int     num_pts,
               ZnBool           cw);
void
ZnPolySet(ZnPoly        *poly1,
          ZnPoly        *poly2);
void
ZnPolyFree(ZnPoly       *poly);
void
ZnTriStrip1(ZnTriStrip          *tristrip,
            ZnPoint             *pts,
            unsigned int        num_pts,
            ZnBool              fan);
void
ZnTriFree(ZnTriStrip    *tristrip);

void
ZnAnchor2Origin(ZnPoint         *position,
                ZnDim           width,
                ZnDim           height,
                Tk_Anchor       anchor,
                ZnPoint         *origin);
void
ZnOrigin2Anchor(ZnPoint         *origin,
                ZnDim           width,
                ZnDim           height,
                Tk_Anchor       anchor,
                ZnPoint         *position);
void ZnRectOrigin2Anchor(ZnPoint *rect, Tk_Anchor anchor, ZnPoint *position);
void
ZnBBox2XRect(ZnBBox     *bbox,
             XRectangle *rect);
void
ZnGetStringBBox(char    *str,
                Tk_Font font,
                ZnPos   x,
                ZnPos   y,
                ZnBBox  *str_bbox);
void
ZnResetBBox(ZnBBox *bbox);
void
ZnCopyBBox(ZnBBox *bbox_from,
           ZnBBox *bbox_to);
void
ZnIntersectBBox(ZnBBox *bbox1,
                ZnBBox *bbox2,
                ZnBBox *bbox_inter);
ZnBool
ZnIsEmptyBBox(ZnBBox *bbox);
void
ZnAddBBoxToBBox(ZnBBox *bbox,
                ZnBBox *bbox2);
void
ZnAddPointToBBox(ZnBBox *bbox,
                 ZnPos  px,
                 ZnPos  py);
void
ZnAddPointsToBBox(ZnBBox     *bbox,
                  ZnPoint     *points,
                  unsigned int num_points);
void
ZnAddStringToBBox(ZnBBox        *bbox,
                  char          *str,
                  Tk_Font       font,
                  ZnPos         cx,
                  ZnPos         cy);
ZnBool
ZnPointInBBox(ZnBBox    *bbox,
              ZnPos     x,
              ZnPos     y);

int
ZnLineInBBox(ZnPoint    *p1,
             ZnPoint    *p2,
             ZnBBox     *bbox);

int
ZnBBoxInBBox(ZnBBox     *bbox1,
             ZnBBox     *bbox2);

int
ZnPolylineInBBox(ZnPoint        *points,
                 unsigned int   num_points,
                 ZnDim          width,
                 int            cap_style,
                 int            join_style,
                 ZnBBox         *bbox);

int
ZnPolygonInBBox(ZnPoint         *points,
                unsigned int    num_points,
                ZnBBox          *bbox,
                ZnBool          *area_enclosed);

int
ZnOvalInBBox(ZnPoint    *center,
             ZnDim      width,
             ZnDim      height,
             ZnBBox     *bbox);

ZnBool
ZnHorizLineToArc(ZnReal x1,
                 ZnReal x2,
                 ZnReal y,
                 ZnReal rx,
                 ZnReal ry,
                 int    start_angle,
                 int    angle_extent);

ZnBool
ZnVertLineToArc(ZnReal  x,
                ZnReal  y1,
                ZnReal  y2,
                ZnReal  rx,
                ZnReal  ry,
                int     start_angle,
                int     angle_extent);

ZnBool
ZnPointInAngle(int      start_angle,
               int      angle_extent,
               ZnPoint  *p);

void
ZnPointCartesianToPolar(ZnReal heading,
                        ZnReal *rho,
                        ZnReal *theta,
                        ZnReal delta_x,
                        ZnReal delta_y);

void
ZnPointPolarToCartesian(ZnReal  heading,
                        ZnReal  rho,
                        ZnReal  theta,
                        ZnReal  *delta_x,
                        ZnReal  *delta_y);

ZnReal
ZnProjectionToAngle(ZnReal      dx,
                    ZnReal      dy);

ZnDim
ZnRectangleToPointDist(ZnBBox   *bbox,
                       ZnPoint  *p);
ZnDim ZnLineToPointDist(ZnPoint *p1, ZnPoint *p2, ZnPoint *p, ZnPoint *closest);

ZnDim
ZnPolygonToPointDist(ZnPoint            *points,
                     unsigned int       num_points,
                     ZnPoint            *p);

ZnDim
ZnPolylineToPointDist(ZnPoint           *points,
                      unsigned int      num_points,
                      ZnDim             width,
                      int               cap_style,
                      int               join_style,                
                      ZnPoint           *p);

ZnDim
ZnOvalToPointDist(ZnPoint       *center,
                  ZnDim         width,
                  ZnDim         height,
                  ZnDim         line_width,
                  ZnPoint       *p);

void
ZnGetButtPoints(ZnPoint *p1,
                ZnPoint *p2,
                ZnDim   width,
                ZnBool  projecting,
                ZnPoint *c1,
                ZnPoint *c2);

ZnBool
ZnGetMiterPoints(ZnPoint        *p1,
                 ZnPoint        *p2,
                 ZnPoint        *p3,
                 ZnDim          width,
                 ZnPoint        *c1,
                 ZnPoint        *c2);

ZnBool
ZnIntersectLines(ZnPoint        *a1,
                 ZnPoint        *a2,
                 ZnPoint        *b1,
                 ZnPoint        *b2,
                 ZnPoint        *pi);

void
ZnShiftLine(ZnPoint     *p1,
            ZnPoint     *p2,
            ZnDim       dist,
            ZnPoint     *p3,
            ZnPoint     *p4);

void
ZnInsetPolygon(ZnPoint          *p,
               unsigned int     num_points,
               ZnDim            inset);

void
ZnSmoothPathWithBezier(ZnPoint          *from_points,
                       unsigned int     num_points,
                       ZnList           to_points);

void
ZnGetBezierPoints(ZnPoint       *p1,
                  ZnPoint       *c1,
                  ZnPoint       *c2,
                  ZnPoint       *p2,
                  ZnList        to_points,
                  double        eps);
void
ZnGetBezierPath(ZnList  from_points,
                ZnList  to_points);


ZnPoint *
ZnGetCirclePoints(int           type,
                  int           quality,
                  ZnReal        start_angle,
                  ZnReal        angle_extent,
                  unsigned int  *num_points,
                  ZnList        point_list);

void
ZnGetArcPath(ZnReal     start_angle,
             ZnReal     end_angle,
             int        type,
             ZnList     to_points);

void
ZnFitBezier(ZnPoint     *pts,
            unsigned int num_points,
            ZnReal      error,
            ZnList      controls);

ZnBool
ZnTestCCW(ZnPoint               *p,
          unsigned int  num_points);


#endif  /* _Geo_h */

Added jni/tkzinc/generic/Group.c.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
/*
 * Group.c -- Implementation of Group item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Wed Jun 23 10:09:20 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Types.h"
#include "WidgetInfo.h"
#include "Item.h"
#include "Group.h"
#include "Geo.h"
#include "tkZinc.h"

#if defined(SHAPE)
#include <X11/extensions/shape.h>
#endif


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 * Group item special record.
 */
typedef struct _GroupItemStruct {
  ZnItemStruct          header;

  /* Public data */
  ZnItem                clip;
  unsigned char         alpha;

  /* Private data */
  ZnItem                head;           /* Doubly linked list of all items.     */
  ZnItem                tail;
  ZnList                dependents;     /* List of dependent items.             */
#ifdef ATC
  /* Overlap manager variables.
   * These variables are valid *only* if the overlap
   * manager is active. */
  ZnBool                call_om;        /* Tell if there is a need to call the  */
                                        /* overlap manager.                     */
#endif
} GroupItemStruct, *GroupItem;


#define ATOMIC_BIT      (1<<ZN_PRIVATE_FLAGS_OFFSET)


/*
 **********************************************************************************
 *
 * Specific Group item record
 *
 **********************************************************************************
 */
static ZnAttrConfig     group_attrs[] = {
  { ZN_CONFIG_ALPHA, "-alpha", NULL,
    Tk_Offset(GroupItemStruct, alpha), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-atomic", NULL,
    Tk_Offset(GroupItemStruct, header.flags), ATOMIC_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(GroupItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_ITEM, "-clip", NULL,
    Tk_Offset(GroupItemStruct, clip), 0,
    ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(GroupItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(GroupItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_TRANSFO_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(GroupItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_TRANSFO_FLAG, False },
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(GroupItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(GroupItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(GroupItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(GroupItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  GroupItem     group = (GroupItem) item;
  
  group->head = ZN_NO_ITEM;
  group->tail = ZN_NO_ITEM;
  group->clip = ZN_NO_ITEM;
  group->alpha = 100;
  group->dependents = NULL;
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  CLEAR(item->flags, ATOMIC_BIT);
  item->priority = 1;
#ifdef ATC
  group->call_om = False;
#endif
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  GroupItem     group = (GroupItem) item;  
  ZnList        dependents;
  ZnItem        connected, current_item, new_item;
  ZnItem        *items;
  Tcl_HashTable mapping;
  Tcl_HashEntry *entry;
  int           new, num_items, i;

  if (item == item->wi->top_group) {
    /* Do not try to clone the top group */
    return;
  }

  current_item = group->tail;
  group->head = group->tail = ZN_NO_ITEM;
#ifdef ATC
  group->call_om = False;
#endif
  dependents = group->dependents;
  if (dependents) {
    Tcl_InitHashTable(&mapping, TCL_ONE_WORD_KEYS);
  }

  /*
   * First clone all the children, and build a mapping
   * table if there is some attachments to relink.
   */
  while (current_item != ZN_NO_ITEM) {
    connected = current_item->connected_item;
    new_item = ZnITEM.CloneItem(current_item);
    new_item->connected_item = connected;
    ZnITEM.InsertItem(new_item, item, ZN_NO_ITEM, True);
    
    if (dependents) {
      entry = Tcl_CreateHashEntry(&mapping, (char *) current_item, &new);
      Tcl_SetHashValue(entry, (ClientData) new_item);
    }
    if (current_item == group->clip) {
      group->clip = new_item;
    }
    current_item = current_item->previous;
  }
  
  /*
   * Then rebuild the dependency list with
   * the new items.
   */
  if (dependents) {
    /*printf("rebuilding dependents\n");*/
    group->dependents = NULL;
    items = (ZnItem *) ZnListArray(dependents);
    num_items = ZnListSize(dependents);
    for (i = 0; i < num_items; i++, items++) {
      entry = Tcl_FindHashEntry(&mapping, (char *) *items);
      if (entry == NULL) {
        ZnWarning("Can't find item correspondance in Group Clone\n");
        abort();
      }
      else {
        current_item = (ZnItem) Tcl_GetHashValue(entry);
      }
      entry = Tcl_FindHashEntry(&mapping, (char *) current_item->connected_item);
      if (entry == NULL) {
        ZnWarning("Can't found item correspondance in Group Clone\n");
        abort();
      }
      else {
        /*printf("item %d correspond to ", current_item->connected_item->id);*/
        current_item->connected_item = (ZnItem) Tcl_GetHashValue(entry);
        /*printf("%d\n", current_item->connected_item->id);*/
        ZnInsertDependentItem(current_item);
      }
    }
    Tcl_DeleteHashTable(&mapping);
  }
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  GroupItem     group = (GroupItem) item;
  ZnItem        current_item, next_item;

  current_item = group->head;
  while (current_item != ZN_NO_ITEM) {
    next_item = current_item->next;
    ZnITEM.DestroyItem(current_item);
    current_item = next_item;
  }
  if (group->dependents) {
    ZnListFree(group->dependents);
  }
}


/*
 **********************************************************************************
 *
 * SetXShape --
 *
 **********************************************************************************
 */
#if defined(SHAPE)
static void
SetXShape(ZnItem        grp)
{
  ZnWInfo       *wi = grp->wi;
  ZnItem        clip = ((GroupItem) grp)->clip;
  unsigned int  i, j, num_pts, max_num_pts;
  ZnPos         min_x, min_y, max_x, max_y;
  ZnTriStrip    tristrip;
  ZnPoint       *p;
  ZnBool        simple;
  ZnDim         width, height;
  XPoint        xpts[3], *xp2, *xpts2;
  TkRegion      reg, reg_op, reg_to;
  
  if (ISCLEAR(wi->flags, ZN_HAS_X_SHAPE)) {
    return;
  }

  if ((clip == ZN_NO_ITEM) || !wi->reshape) {
    /*
     * Reset both clip just to be sure (the application can have
     * changed wi->full_reshape while resetting wi->reshape).
     */
    XShapeCombineMask(wi->dpy, Tk_WindowId(wi->win), ShapeBounding,
                      0, 0, None, ShapeSet);
    XShapeCombineMask(wi->dpy, wi->real_top, ShapeBounding,
                      0, 0, None, ShapeSet);
  }
  else {
    /*
     * Get the clip shape.
     */
    tristrip.num_strips = 0;
    simple = clip->class->GetClipVertices(clip, &tristrip);
    if (simple || (tristrip.num_strips == 0)) {
      /*
       * Nothing to do: after normalisation the rectangular shape will
       * fit exactly the window. We may test here if a shape is currently
       * active and reset the mask only in this case (need a flag in wi).
       */
      XShapeCombineMask(wi->dpy, Tk_WindowId(wi->win), ShapeBounding,
                        0, 0, None, ShapeSet);
      XShapeCombineMask(wi->dpy, wi->real_top, ShapeBounding,
                        0, 0, None, ShapeSet);
    }
    else {
      /*
       * First make the vertices start at zero.
       * In case of a fan we benefit from the fact that
       * ALL the contour vertices are included in
       * the tristrip, so we dont need to consider the
       * center (arc in pie slice mode).
       */
      max_x = min_x = tristrip.strips[0].points[0].x;
      max_y = min_y = tristrip.strips[0].points[0].y;
      max_num_pts = tristrip.strips[0].num_points;
      for (j = 0; j < tristrip.num_strips; j++) {
        p = tristrip.strips[j].points;
        num_pts = tristrip.strips[j].num_points;
        if (num_pts > max_num_pts) {
          max_num_pts = num_pts;
        }
        for (i = 0; i < num_pts; p++, i++) {
          if (p->x < min_x) {
            min_x = p->x;
          }
          if (p->y < min_y) {
            min_y = p->y;
          }
          if (p->x > max_x) {
            max_x = p->x;
          }
          if (p->y > max_y) {
            max_y = p->y;
          }
        }
      }
      max_x -= min_x;
      max_y -= min_y;
      XShapeCombineMask(wi->dpy, wi->full_reshape?Tk_WindowId(wi->win):wi->real_top,
                        ShapeBounding, 0, 0, None, ShapeSet);
      reg = TkCreateRegion();
      
      /*
       * Now normalize the shape and map it to the window size,
       * then Translate it in a region and apply this region to
       * the window.
       */
      width = wi->width;
      height = wi->height;
      for (j = 0; j < tristrip.num_strips; j++) {
        p = tristrip.strips[j].points;
        num_pts = tristrip.strips[j].num_points;

        /*
         * In case of a fan we benefit from the fact that
         * ALL the contour vertices are included in
         * the tristrip, so we can use the corresponding
         * polygon instead of going through all the triangles.
         */
        if (tristrip.strips[j].fan) {
          /* Skip the center */
          p++;
          num_pts--;
          xp2 = xpts2 = ZnMalloc(num_pts*sizeof(XPoint));
          for (i = 0 ; i < num_pts; i++, p++, xp2++) {
            xp2->x = (short) ((p->x - min_x) * width / max_x);
            xp2->y = (short) ((p->y - min_y) * height / max_y);
          }
          reg_op = ZnPolygonRegion(xpts2, num_pts, EvenOddRule);
          reg_to = TkCreateRegion();
          ZnUnionRegion(reg, reg_op, reg_to);
          TkDestroyRegion(reg);
          TkDestroyRegion(reg_op);
          reg = reg_to;
          ZnFree(xpts2);
        }
        else {
          xpts[0].x = (short) ((p->x - min_x) * width / max_x);
          xpts[0].y = (short) ((p->y - min_y) * height / max_y);
          p++;
          xpts[1].x = (short) ((p->x - min_x) * width / max_x);
          xpts[1].y = (short) ((p->y - min_y) * height / max_y);
          p++;
          for (i = 2 ; i < num_pts; i++, p++) {
            xpts[2].x = (short) ((p->x - min_x) * width / max_x);
            xpts[2].y = (short) ((p->y - min_y) * height / max_y);
            reg_op = ZnPolygonRegion(xpts, 3, EvenOddRule);
            reg_to = TkCreateRegion();
            ZnUnionRegion(reg, reg_op, reg_to);
            TkDestroyRegion(reg);
            TkDestroyRegion(reg_op);
            reg = reg_to;
            xpts[0] = xpts[1];
            xpts[1] = xpts[2];
          }
        }
      }
      XShapeCombineRegion(wi->dpy, wi->full_reshape?wi->real_top:Tk_WindowId(wi->win),
                          ShapeBounding, 0, 0, (Region) reg, ShapeSet);
      TkDestroyRegion(reg);
    }
  }
}
#else
static void
SetXShape(ZnItem        grp)
{
}
#endif


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  GroupItem     group = (GroupItem) item;
  ZnWInfo       *wi = item->wi;
  
  if (ZnConfigureAttributes(wi, item, item, group_attrs, argc, argv, flags) == TCL_ERROR) {
    return TCL_ERROR;
  }

  /*
   * If the clip item changed, check if it is a legal
   * item type that is inside this group.
   */
  if (ISSET(*flags, ZN_ITEM_FLAG)) {
    if (group->clip &&
        (!group->clip->class->GetClipVertices || (group->clip->parent != item))) {
      group->clip = ZN_NO_ITEM;
      Tcl_AppendResult(wi->interp,
                       " clip item must be a child of the group", NULL);
      return TCL_ERROR;
    }
    if (!group->clip && (item == wi->top_group)) {
      SetXShape(item);
    }
  }
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, group_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * PushClip --
 *      Save the current clip shape and current clipbox if needed.
 *      Intersect the previous shape and the local to obtain the
 *      new current shape. Use this shape to compute the current
 *      clipbox and if set_gc is True compute the current region.
 *
 **********************************************************************************
 */
static void
PushClip(GroupItem      group,
         ZnBool         set_gc)
{
  ZnWInfo       *wi = ((ZnItem) group)->wi;
  ZnTriStrip    tristrip;
  ZnBool        simple;

  if ((group->clip != ZN_NO_ITEM) &&
      ((((ZnItem) group) != wi->top_group)
#if defined(SHAPE)
       || !wi->reshape
#endif
       )) {
    simple = group->clip->class->GetClipVertices(group->clip, &tristrip);
    /*printf("Group: PushClip group %d\n", ((ZnItem) group)->id);*/
    if (tristrip.num_strips) {
      ZnPushClip(wi, &tristrip, simple, set_gc);
    }
  }
}


/*
 **********************************************************************************
 *
 * PopClip --
 *      Re-install the previous clip shape if any (stack can be empty).
 *
 **********************************************************************************
 */
static void
PopClip(GroupItem       group,
        ZnBool          set_gc)
{
  ZnWInfo       *wi = ((ZnItem) group)->wi;

  if ((group->clip != ZN_NO_ITEM) &&
      ((((ZnItem) group) != wi->top_group)
#if defined(SHAPE)
       || !wi->reshape
#endif
       )) {
    /*printf("Group: PopClip group %d\n", ((ZnItem) group)->id);*/
    ZnPopClip(wi, set_gc);
  }
}


/*
 **********************************************************************************
 *
 * PushTransform --
 *      Save the current transform then concatenate the item transform to
 *      form the new current transform.
 *
 **********************************************************************************
 */
static void
PushTransform(ZnItem    item)
{
  ZnPoint *pos;
  
  pos = NULL;
  if (item->class->pos_offset >= 0) {
    pos = (ZnPoint *) (((char *) item) + item->class->pos_offset);
    if (pos->x == 0 && pos->y == 0) {
      pos = NULL;
    }
  }
  if (!item->transfo &&
      !pos &&
      ISSET(item->flags, ZN_COMPOSE_SCALE_BIT) &&
      ISSET(item->flags, ZN_COMPOSE_ROTATION_BIT)) {
    return;
  }

  ZnPushTransform(item->wi, item->transfo, pos,
                  ISSET(item->flags, ZN_COMPOSE_SCALE_BIT),
                  ISSET(item->flags, ZN_COMPOSE_ROTATION_BIT));
  /*printf("Pushing transfo for item: %d\n;", item->id);
    ZnPrintTransfo(wi->current_transfo);*/
}


/*
 **********************************************************************************
 *
 * PopTransform --
 *      Restore the previously saved transform from the stack.
 *
 **********************************************************************************
 */
static void
PopTransform(ZnItem     item)
{
  ZnPoint *pos;
  
  pos = NULL;
  if (item->class->pos_offset >= 0) {
    pos = (ZnPoint *) (((char *) item) + item->class->pos_offset);
    if (pos->x == 0 && pos->y == 0) {
      pos = NULL;
    }
  }
  if (!item->transfo &&
      !pos &&
      ISSET(item->flags, ZN_COMPOSE_SCALE_BIT) &&
      ISSET(item->flags, ZN_COMPOSE_ROTATION_BIT)) {
    return;
  }

  ZnPopTransform(item->wi);
  /*printf("Popping transfo for item: %d\n", item->id);
  ZnPrintTransfo(wi->current_transfo);*/
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *      Compute the geometrical elements of a group. First of all save the current
 *      transform and combine it with the item transform. Then call the item
 *      ComputeCoordinates method.
 *      For regular child items (not groups) some of the code of the item
 *      itself is factored out in CallRegularCC.
 *
 **********************************************************************************
 */
static void
CallRegularCC(ZnItem    item)
{
  ZnWInfo       *wi = item->wi;
  /*ZnBBox      *clip_box;*/
  
  /*
   * Do some generic pre-work in behalf of the (regular) children.
   */
  if (ISSET(item->flags, ZN_VISIBLE_BIT)) {
    ZnDamage(wi, &item->item_bounding_box);
  }
  PushTransform(item);
  
  /*printf("calling cc on regular item %d\n", item->id);*/
  /*ZnPrintTransfo(wi->current_transfo);*/
  item->class->ComputeCoordinates(item, False);
  /*
   * If a current clipbox exists adjust the item
   * bounding box accordingly. When computing coordinates
   * the damaged area is not pushed onto the clipstack,
   * the following predicate is thus valid for testing
   * a clipbox. 
   */
  /* Tue Nov 14 15:21:05 2000 Suppressed to have a real
     bbox to align tiles (i.e if an object is larger than
     its enclosing clipping, the bbox is equal to the clip
     area and the tiling will not move with the object until
     it partially uncovered the clip area.
     Have to watch any possible breakage.

    if (ZnCurrentClip(wi, NULL, &clip_box, NULL)) {
    ZnBBox inter;
    
    ZnIntersectBBox(&item->item_bounding_box, clip_box, &inter);
    item->item_bounding_box = inter;
  }*/
  /*
   * Do some generic post-work in behalf of the (regular) children.
   */
#ifdef GL
#ifdef GL_LIST
  /*
   * Remove the item display list so that it will be recreated
   * to reflect the changes.
   */
  if (item->gl_list) {
    glDeleteLists(item->gl_list, 1);
    item->gl_list = 0;
  }
#endif
#endif
  if (ISSET(item->inv_flags, ZN_REPICK_FLAG)) {
    SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
  }
  if (ISSET(item->inv_flags, ZN_COORDS_FLAG) &&
      (ISSET(item->flags, ZN_SENSITIVE_BIT) ||
       ISSET(item->flags, ZN_VISIBLE_BIT))) {
    SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
  }
  /*
   * Damage if the item is visible or if it is
   * a group clipper.
   */
  if (ISSET(item->flags, ZN_VISIBLE_BIT) ||
      (item == ((GroupItem) item->parent)->clip)) {
    ZnDamage(wi, &item->item_bounding_box);
  }
  PopTransform(item);
  item->inv_flags = 0;
  /*printf("Done cc on regular item %d\n", item->id);*/
}

static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  GroupItem     group = (GroupItem) item;
  ZnItem        current_item;
  ZnItem        *deps;
  int           num_deps, i;
  ZnBBox        *clip_box;

  PushTransform(item);
  //printf("Entering Group: %d\n", item->id);
  //ZnPrintTransfo(item->wi->current_transfo);    
  //printf("\n");

  force |= ISSET(item->inv_flags, ZN_TRANSFO_FLAG);

  /*
   * If the clip item changed or there is no clip anymore
   * force an update.
   */
  force |= ISSET(item->inv_flags, ZN_ITEM_FLAG);

  /*
   * Clip shape is computed in the group's local
   * coordinates.
   */
  if (group->clip != ZN_NO_ITEM) {
    /*
     * Update the geometry of the clip item if needed.
     * Its bounding box will be clipped by the current
     * clipbox (i.e the clipbox of the group's parent).
     */
    if (force ||
        ISSET(group->clip->inv_flags, ZN_COORDS_FLAG) ||
        ISSET(group->clip->inv_flags, ZN_TRANSFO_FLAG)) {
      /*printf("calling cc on clip item %d for group %d\n",
        group->clip->id, item->id);*/
      CallRegularCC(group->clip);
      if (item == item->wi->top_group) {
        SetXShape(item);
      }
      /*
       * If the clip item has changed we need to compute
       * new clipped bounding boxes for all the children.
       */
      force = True;
    }
  }
  
  PushClip(group, False);
  
  for (current_item = group->head; current_item != ZN_NO_ITEM;
       current_item = current_item->next) {
    /*
     * Skip the clip item, it has been already updated.
     * Skip as well items with a dependency, they will
     * be updated later.
     */
    //printf("Trying to update: %d\n", current_item->id);
    if ((current_item == group->clip) ||
        (current_item->connected_item != ZN_NO_ITEM)) {
      continue;
    }
    if (force ||
        ISSET(current_item->inv_flags, ZN_COORDS_FLAG) ||
        ISSET(current_item->inv_flags, ZN_TRANSFO_FLAG)) {
      if (current_item->class != ZnGroup) {
        //printf("Updating item %d\n", current_item->id);
        CallRegularCC(current_item);
      }
      else {
        //printf("Updating group %d\n", current_item->id);
        current_item->class->ComputeCoordinates(current_item, force);
      }
    }
  }
  /*
   * Update coordinates and bounding boxes following
   * a possible change in connected items. Only regular
   * items can be concerned.
   */
  if (group->dependents) {
    num_deps = ZnListSize(group->dependents);
    deps = (ZnItem *) ZnListArray(group->dependents);
    for (i = 0; i < num_deps; i++) {
      current_item = deps[i];
      if (force ||
          ISSET(current_item->inv_flags, ZN_COORDS_FLAG) ||
          ISSET(current_item->inv_flags, ZN_TRANSFO_FLAG) ||
          ISSET(current_item->connected_item->flags, ZN_UPDATE_DEPENDENT_BIT)) {        
        //printf("Updating dependent: %d\n", current_item->id);       
        CallRegularCC(current_item);
      }
    }
    /*
     * Now, we must reset the update_dependent flag
     */
    for (i = 0; i < num_deps; i++) {
      CLEAR(deps[i]->connected_item->flags, ZN_UPDATE_DEPENDENT_BIT);
    }
    /*printf("... done\n");*/
  }
  /*
   * Compute the bounding box.
   */
  ZnResetBBox(&item->item_bounding_box);
  current_item = group->head;
  while (current_item != ZN_NO_ITEM) {
    if (ISSET(current_item->flags, ZN_VISIBLE_BIT)) {
      ZnAddBBoxToBBox(&item->item_bounding_box, &current_item->item_bounding_box);
    }
    current_item = current_item->next;    
  }
  /*
   * Limit the group actual bounding box to
   * the clip shape boundary.
   */
  if (group->clip) {
    clip_box = &group->clip->item_bounding_box;
    ZnIntersectBBox(&item->item_bounding_box, clip_box, &item->item_bounding_box);
  }
  item->inv_flags = 0;

  PopClip(group, False);
  PopTransform(item);

  //printf("Leaving Group: %d\n", item->id);
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  GroupItem     group = (GroupItem) item;
  ZnItem        current_item;
  ZnBBox        enclosing, inter;
  int           result = -1;
  ZnBool        outside, inside;
  ZnBool        atomic, report, empty = True;
  

  PushTransform(item);
  report = ta->report;

  /*
   * Is this group the target group ?
   */
  if ((ta->in_group != ZN_NO_ITEM) && (ta->in_group != item)) {
    /* No, try the subgroups. */
    for (current_item = group->head;
         current_item != ZN_NO_ITEM;
         current_item = current_item->next) {
      if (current_item->class != ZnGroup) {
        continue;
      }
      result = current_item->class->ToArea(current_item, ta);
      if (ta->in_group == ZN_NO_ITEM) {
        /* The target group has been found, return its result. */
        goto out;
      }
    }
    /* No group found in this subtree. */
    goto out;
  }

  /*
   * At this point we are either in the target group
   * or one of its sub-groups. If in the target group,
   * erase the target in the call struct to remember
   * the fact.
   */
  if (ta->in_group == item) {
    /*
     * We are in the target group, mark the fact and bypass the group
     * atomicity.
     */
    ta->in_group = ZN_NO_ITEM;
    atomic = False;
  }
  else {
    /*
     * We are below the start group, If this group is ATOMIC,
     * ask the child groups to report instead of adding their
     * children to the result.
     */
    atomic = ISSET(item->flags, ATOMIC_BIT) && !ta->override_atomic;
    ta->report |= atomic;
  }

  enclosing.orig.x = ta->area->orig.x - 1;
  enclosing.orig.y = ta->area->orig.y - 1;
  enclosing.corner.x = ta->area->corner.x + 1;
  enclosing.corner.y = ta->area->corner.y + 1;
  outside = inside = True;
  /*
   * Process each item and proceed with subtrees if
   * asked for by the recursive flag.
   */
  /*  printf("searching in group %d\n", item?item->id:0);*/
  for (current_item = group->head;
       current_item != ZN_NO_ITEM;
       current_item = current_item->next) {
    if (ISCLEAR(current_item->flags, ZN_VISIBLE_BIT) &&
        ISCLEAR(current_item->flags, ZN_SENSITIVE_BIT)) {
      continue;
    }
    /*printf("visible&sensitive %d\n", current_item?current_item->id:0);*/
    ZnIntersectBBox(&enclosing, &current_item->item_bounding_box, &inter);
    if (ZnIsEmptyBBox(&inter)) {
      continue;
    }
    /*printf("bbox test passed %d\n", current_item?current_item->id:0);*/
    if ((current_item->class != ZnGroup) || atomic || ta->recursive || ISSET(current_item->flags, ATOMIC_BIT)) {
      if (current_item->class != ZnGroup) {
        /*printf("testing %d\n", current_item?current_item->id:0);*/
        PushTransform(current_item);
        result = current_item->class->ToArea(current_item, ta);
        PopTransform(current_item);
      }
      else {
        result = current_item->class->ToArea(current_item, ta);
      }
      outside &= (result == -1);
      inside &= (result == 1);
      empty = False;

      /*
       * If this group is ATOMIC, it must report itself as matching
       * if a/ the request is 'enclosed' and all the children are
       * enclosed or b/ the request is 'overlapping' and at least one
       * child overlaps (or is enclosed).
       * So here we can do early tests to shortcut the search when
       * the most stringent conditions are met.
       */
      if (atomic) {
        if (!ta->enclosed && (result >= 0)) {
          result = 0;
          goto out;
        } else if (ta->enclosed && (result == 0)) {
          goto out;
        }
      }
      if (!ta->report && (result >= ta->enclosed)) {
        /*printf("Doing %d\n", current_item?current_item->id:0);*/
        ZnDoItem(item->wi->interp, current_item, ZN_NO_PART, ta->tag_uid);
      }
    }
  }

  /*
   * If there are no items or only sub-groups in this group and
   * the search is not recursive we must report outside.
   */
  if (empty) {
    result = -1;    
  }
  else {
    if (atomic) {
      result = outside ? -1 : 1;
    }
    else if (ta->report) { /* Need to report matching children to ancestor */
      if (outside && inside) {
        result = 0;
      }
      else {
        result = outside ? -1 : 1;
      }
    }
    else {
      result = -1;
    }
  }

 out:
  ta->report = report;
  PopTransform(item);
  return result;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  GroupItem     group = (GroupItem) item;
  ZnWInfo       *wi = item->wi;
  ZnItem        current_item;
  ZnBBox        bbox, old_damaged_area, *clip_box;
  
  PushTransform(item);
  PushClip(group, True);
  old_damaged_area = wi->damaged_area;
  if (group->clip != ZN_NO_ITEM) {
    if (ZnCurrentClip(wi, NULL, &clip_box, NULL)) {
      ZnIntersectBBox(&wi->damaged_area, clip_box, &bbox);
      wi->damaged_area = bbox;
    }
  }
  
  current_item = group->tail;
  while (current_item != ZN_NO_ITEM) {
    if (ISSET(current_item->flags, ZN_VISIBLE_BIT)) {
      ZnIntersectBBox(&wi->damaged_area, &current_item->item_bounding_box, &bbox);
      if (!ZnIsEmptyBBox(&bbox)) {
        if (current_item->class != ZnGroup) {
          PushTransform(current_item);
        }
        current_item->class->Draw(current_item);
        if (wi->draw_bboxes) {
          XGCValues     values;
          values.foreground = ZnGetGradientPixel(wi->bbox_color, 0.0);
          values.fill_style = FillSolid;
          values.line_width = 1;
          values.line_style = (current_item->class==ZnGroup)?LineOnOffDash:LineSolid;
          XChangeGC(wi->dpy, wi->gc, GCForeground|GCLineStyle|GCLineWidth|GCFillStyle,
                    &values);
          XDrawRectangle(wi->dpy, wi->draw_buffer, wi->gc,
                         (int) current_item->item_bounding_box.orig.x,
                         (int) current_item->item_bounding_box.orig.y,
                         (unsigned int) (current_item->item_bounding_box.corner.x -
                                         current_item->item_bounding_box.orig.x),
                         (unsigned int) (current_item->item_bounding_box.corner.y -
                                         current_item->item_bounding_box.orig.y));
        }
        if (current_item->class != ZnGroup) {
          PopTransform(current_item);
        }
      }
    }
    current_item = current_item->previous;
  }

  if (group->clip != ZN_NO_ITEM) {
    wi->damaged_area = old_damaged_area;
  }
  PopClip(group, True);
  PopTransform(item);
}



/*
 **********************************************************************************
 *
 * PreRender --
 *
 **********************************************************************************
 */
#ifdef GL
static void
PreRender(ZnItem   item)
{
  GroupItem     group = (GroupItem) item;
  ZnItem        current_item;
  ZnWInfo       *wi = item->wi;
  unsigned char save_alpha = wi->alpha;
  unsigned char save_alpha2;

  if (ISSET(item->flags, ZN_COMPOSE_ALPHA_BIT)) {
    wi->alpha = wi->alpha * group->alpha / 100;
  }
  else {
    wi->alpha = group->alpha;
  }
  save_alpha2 = wi->alpha;

  PushTransform(item);
 
  current_item = group->tail;
  while (current_item != ZN_NO_ITEM) {
    if (ISSET(current_item->flags, ZN_VISIBLE_BIT)) {

      if (  current_item->class->PreRender != NULL )
      {
        if (current_item->class != ZnGroup) {
          PushTransform(current_item);
          if (ISCLEAR(current_item->flags, ZN_COMPOSE_ALPHA_BIT)) {
            wi->alpha = 100;
          }
        }
        
        current_item->class->PreRender(current_item);
        
        if (current_item->class != ZnGroup) {
          PopTransform(current_item);
          wi->alpha = save_alpha2;
        }
      }
    }
    current_item = current_item->previous;
  }

  PopTransform(item);

  wi->alpha = save_alpha;
}
#else
static void
PreRender(ZnItem   item)
{
}
#endif




/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
Render(ZnItem   item)
{
  GroupItem     group = (GroupItem) item;
  ZnItem        current_item;
  ZnWInfo       *wi = item->wi;
//#ifdef GL_DAMAGE
  ZnBBox        *clip_box;
  ZnBBox        bbox, old_damaged_area;
//#endif
  unsigned char save_alpha = wi->alpha;
  unsigned char save_alpha2;

  if (ISSET(item->flags, ZN_COMPOSE_ALPHA_BIT)) {
    wi->alpha = wi->alpha * group->alpha / 100;
  }
  else {
    wi->alpha = group->alpha;
  }
  save_alpha2 = wi->alpha;

  PushTransform(item);
  PushClip(group, True);

  /* Test if we are using damage or not */
  old_damaged_area = wi->damaged_area;
  if (wi->usedamage) {
    /* Damage is on */
    if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT) && (group->clip != ZN_NO_ITEM)) {
      if (ZnCurrentClip(wi, NULL, &clip_box, NULL)) {
         ZnIntersectBBox(&wi->damaged_area, clip_box, &bbox);
         wi->damaged_area = bbox;
      }
    }
   }
  
  current_item = group->tail;
  while (current_item != ZN_NO_ITEM) {
    if (ISSET(current_item->flags, ZN_VISIBLE_BIT)) {
      /* test if we are using dmaage or not */
      if (wi->usedamage) {
         /* Damage is on */
         ZnIntersectBBox(&wi->damaged_area, &current_item->item_bounding_box, &bbox);
         if (!ZnIsEmptyBBox(&bbox) || ISSET(wi->flags, ZN_CONFIGURE_EVENT)) {
         
            if (current_item->class != ZnGroup) {
               PushTransform(current_item);
               if (ISCLEAR(current_item->flags, ZN_COMPOSE_ALPHA_BIT)) {
                  wi->alpha = 100;
               }
            }
            current_item->class->Render(current_item);
            if (current_item->class != ZnGroup) {
               PopTransform(current_item);
               wi->alpha = save_alpha2;
            }
         }
         
      } else {
        /* Damage is off */
        if (current_item->class != ZnGroup) {
          PushTransform(current_item);
          if (ISCLEAR(current_item->flags, ZN_COMPOSE_ALPHA_BIT)) {
            wi->alpha = 100;
          }
        }
        current_item->class->Render(current_item);
        if (current_item->class != ZnGroup) {
          PopTransform(current_item);
          wi->alpha = save_alpha2;
        }
      }
      
    }
    current_item = current_item->previous;
  }

   /* Test if we are using damage or not */
   if (wi->usedamage) {
      if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT) && (group->clip != ZN_NO_ITEM)) {
         wi->damaged_area = old_damaged_area;
      }
   }
  
  PopClip(group, True);
  PopTransform(item);

  wi->alpha = save_alpha;
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  ZnBool        sensitive = ISSET(item->flags, ZN_SENSITIVE_BIT);
  ZnItem        parent = item->parent;
  
  while (sensitive && (parent != ZN_NO_ITEM)) {
    sensitive &= ISSET(parent->flags, ZN_SENSITIVE_BIT);
    parent = parent->parent;
  }
  return sensitive;
}


/*
 **********************************************************************************
 *
 * Pick --
 *      Given a point an an aperture, find the topmost group item/part
 *      that is (a) within the pick_aperture
 *              (b) the top most
 *              (c) has either its sensibility or its visibility set.
 *
 * Results:
 *      The return value is the distance of the picked item/part if one
 *      has been found or a really big distance if not. a_item and a_part
 *      are set to point the picked item/part or to ZN_NO_ITEM/ZN_NO_PART.
 *      If the group is ATOMIC, a_item points the group instead of the
 *      actual item.
 *
 * Side effects:
 *      None.
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  GroupItem     group = (GroupItem) item;
  ZnItem        p_item=ZN_NO_ITEM, current_item;
  ZnWInfo       *wi = item->wi;
  int           p_part=0, aperture = ps->aperture;
  double        dist, best = 1e10;
  ZnBBox        bbox, inter, *clip_box;
  ZnPoint       *p = ps->point;
  ZnBool        atomic;
  TkRegion      reg;

  ps->a_item= ZN_NO_ITEM;
  ps->a_part = ZN_NO_PART;

  if (group->head == ZN_NO_ITEM) {
    return best;
  }
  
  PushTransform(item);
  PushClip(group, False);
  
  /*
   * Is this group the target group ?
   */
  if ((ps->in_group != ZN_NO_ITEM) && (ps->in_group != item)) {
    /* No, try the subgroups. */
    for (current_item = group->head;
         current_item != ZN_NO_ITEM;
         current_item = current_item->next) {
      if (current_item->class != ZnGroup) {
        continue;
      }
      best = current_item->class->Pick(current_item, ps);
      if (ps->in_group == ZN_NO_ITEM) {
        /* The target group has been found, return its result. */
        goto out;
      }
    }
    /* No group found in this subtree. */
    goto out; 
  }

  /*
   * At this point we are either in the target group
   * or one of its sub-groups. If in the target group,
   * erase the target in the call struct to remember
   * the fact.
   */
  if (ps->in_group == item) {
    ps->in_group = ZN_NO_ITEM;
  }

  bbox.orig.x = p->x - aperture;
  bbox.orig.y = p->y - aperture;
  bbox.corner.x = p->x + (aperture?aperture:1);
  bbox.corner.y = p->y + (aperture?aperture:1);

  if (ZnCurrentClip(wi, &reg, &clip_box, NULL)) {
    ZnIntersectBBox(&bbox, clip_box, &inter);
    if (ZnIsEmptyBBox(&inter)) {
      goto out;
    }
    if (reg && !ZnPointInRegion(reg, (int) p->x, (int) p->y)) {
      goto out;
    }
  }

  current_item = (ps->start_item == ZN_NO_ITEM) ? group->head : ps->start_item;
  atomic = ISSET(item->flags, ATOMIC_BIT) && !ps->override_atomic;

  for ( ; current_item != ZN_NO_ITEM; current_item = current_item->next) {
    /*
     * If an item doesn't catch events it can be safely skipped 
     * right now.
     * Sensitive item must be reported even if they are invisible.
     * It is legal to fire bindings on invisible sensitive items.
     * This is _not_ a bug do _not_ modify the test below.
     */
    if (ISCLEAR(current_item->flags, ZN_CATCH_EVENT_BIT) ||
        (ISCLEAR(current_item->flags, ZN_SENSITIVE_BIT) &&
         ISCLEAR(current_item->flags, ZN_VISIBLE_BIT))) {
      continue;
    }
    ZnIntersectBBox(&bbox, &current_item->item_bounding_box, &inter);
    if (ZnIsEmptyBBox(&inter)) {
      continue;
    }
    if (current_item->class != ZnGroup) {
      PushTransform(current_item);
      p_item = ps->a_item;
      p_part = ps->a_part;
      ps->a_item = current_item;
      ps->a_part = ZN_NO_PART;
      dist = current_item->class->Pick(current_item, ps);
      dist -= aperture;
      PopTransform(current_item);
    }
    else if (!atomic && !ps->recursive) {
      continue;
    }
    else {
      dist = current_item->class->Pick(current_item, ps);
    }
    if (dist < 0.0) {
      dist = 0.0;
    }
    if (dist >= best) {
      /* Not a good one, restore the previous best and try again. */
      ps->a_item = p_item;
      ps->a_part = p_part;
      continue;
    }
    if (atomic) {
      /* If ATOMIC, this group is the item to be reported. */
      ps->a_item = item;
      ps->a_part = ZN_NO_PART;
    }

    best = dist;
    /*printf("found %d:%d, at %g\n", (ps->a_item)->id, ps->a_part, dist);*/
    if (dist == 0.0) {
      /* No need to look further, the item found is the topmost
       * closest. */
      break;
    }
  }

 out:
  PopClip(group, False);
  PopTransform(item);
  
  return best;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the group translation (can be also interpreted as the
 *      position of the group origin in the group's parent).
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " can't add or remove vertices in groups", NULL);
    return TCL_ERROR;
  }
  else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (*num_pts == 0) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 1 point on groups", NULL);
      return TCL_ERROR;
    }
    if (!item->transfo && ((*pts)[0].x == 0.0) && ((*pts)[0].y == 0.0)) {
      return TCL_OK;
    }
    if (!item->transfo) {
      item->transfo = ZnTransfoNew();
    }
    ZnTranslate(item->transfo, (*pts)[0].x, (*pts)[0].y, True);
    ZnITEM.Invalidate(item, ZN_TRANSFO_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    ZnPoint     *p;
    
    ZnListAssertSize(ZnWorkPoints, 1);
    p = (ZnPoint *) ZnListArray(ZnWorkPoints);
    ZnTransfoDecompose(item->transfo, NULL, p, NULL, NULL);
    *num_pts = 1;
    *pts = p;
  }
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  GroupItem group = (GroupItem) item;
  ZnWInfo   *wi = item->wi;
  ZnItem    current_item;
  ZnBBox    bbox;
  int       result = TCL_OK;
  char      msg[500];

  PushTransform(item);
  PushClip(group, True);

  for (current_item = group->tail; current_item != ZN_NO_ITEM;
       current_item = current_item->previous) {
    if (ISCLEAR(current_item->flags, ZN_VISIBLE_BIT)) {
      continue;
    }
    //printf("area %g %g %g %g\n", area->orig.x, area->orig.y,
    //       area->corner.x, area->corner.y);
    ZnIntersectBBox(area, &current_item->item_bounding_box, &bbox);
    if (ZnIsEmptyBBox(&bbox)) {
      continue;
    }
    if (current_item->class->PostScript == NULL) {
      continue;
    }

    if (current_item->class != ZnGroup) {
      PushTransform(current_item);
      if (!prepass) {
        Tcl_AppendResult(wi->interp, "gsave\n", NULL);
      }
      ZnPostscriptTrace(current_item, 1);
    }
    result = current_item->class->PostScript(current_item, prepass, area);
    if (current_item->class != ZnGroup) {
      ZnPostscriptTrace(current_item, 0);
      if (!prepass && (result == TCL_OK)) {
        Tcl_AppendResult(wi->interp, "grestore\n", NULL);
      }
      PopTransform(current_item);
    }
    if (result == TCL_ERROR) {
      if (!prepass) {
        /*
         * Add some trace to ease the error lookup.
         */
        sprintf(msg, "\n    (generating Postscript for item %d)", current_item->id);
        Tcl_AddErrorInfo(wi->interp, msg);
        break;
      }
    }
  }

  PopClip(group, True);
  PopTransform(item);

  if (!prepass && (result == TCL_OK)) {
    ZnFlushPsChan(wi->interp, wi->ps_info);
  }
  return result;
}



ZnItem
ZnGroupHead(ZnItem      group)
{
  if (group->class != ZnGroup) {
    return ZN_NO_ITEM;
  }
  return ((GroupItem) group)->head;
}

ZnItem
ZnGroupTail(ZnItem      group)
{
  if (group->class != ZnGroup) {
    return ZN_NO_ITEM;
  }
  return ((GroupItem) group)->tail;
}

#ifdef ATC
ZnBool
ZnGroupCallOm(ZnItem    group)
{
  if (group->class != ZnGroup) {
    return False;
  }
  return ((GroupItem) group)->call_om;
}

void
ZnGroupSetCallOm(ZnItem group,
                 ZnBool set)
{
  if (group->class != ZnGroup) {
    return;
  }
  ((GroupItem) group)->call_om = set;
}
#else
ZnBool
ZnGroupCallOm(ZnItem    group)
{
  return False;
}

void
ZnGroupSetCallOm(ZnItem group,
                 ZnBool set)
{
  return;
}
#endif

ZnBool
ZnGroupAtomic(ZnItem    group)
{
  if (group->class != ZnGroup) {
    return True;
  }
  return ISSET(group->flags, ATOMIC_BIT);
}

void
ZnGroupRemoveClip(ZnItem        group,
                  ZnItem        clip)
{
  GroupItem grp = (GroupItem) group;

  if (grp->clip == clip) {
    grp->clip = ZN_NO_ITEM;
    ZnITEM.Invalidate(group, ZN_COORDS_FLAG);
  }
}


/*
 **********************************************************************************
 *
 * ZnInsertDependentItem --
 *
 **********************************************************************************
 */
void
ZnInsertDependentItem(ZnItem item)
{
  GroupItem    group = (GroupItem) item->parent;
  ZnItem       *dep_list;
  unsigned int i, num_deps;

  if (!group) {
    return;
  }
  if (!group->dependents) {
    group->dependents = ZnListNew(2, sizeof(ZnItem));
  }
  dep_list = (ZnItem *) ZnListArray(group->dependents);
  num_deps = ZnListSize(group->dependents);
  //
  // Insert the farther possible but not past an item
  // dependent on this item.
  for (i = 0; i < num_deps; i++) {
    if (dep_list[i]->connected_item == item) {
      //printf("item %d depends on %d inserting before\n",
      //       dep_list[i]->id, item->id);
      break;
    }
  }
  //printf("adding %d at position %d\n", item->id, i);
  ZnListAdd(group->dependents, &item, i);
}


/*
 **********************************************************************************
 *
 * ZnExtractDependentItem --
 *
 **********************************************************************************
 */
void
ZnExtractDependentItem(ZnItem   item)
{
  GroupItem     group = (GroupItem) item->parent;
  unsigned int  index, num_items;
  ZnItem        *deps;
  
  if (!group || !group->dependents) {
    return;
  }
  num_items = ZnListSize(group->dependents);
  deps = (ZnItem *) ZnListArray(group->dependents);
  for (index = 0; index < num_items; index++) {
    if (deps[index]->id == item->id) {
      ZnListDelete(group->dependents, index);
      if (ZnListSize(group->dependents) == 0) {
        ZnListFree(group->dependents);
        group->dependents = NULL;
        break;
      }
    }
  }
}


/*
 **********************************************************************************
 *
 * ZnDisconnectDependentItems --
 *      
 *
 **********************************************************************************
 */
void
ZnDisconnectDependentItems(ZnItem       item)
{
  ZnItem        current_item;
  GroupItem     group = (GroupItem) item->parent;
  ZnItem        *deps;
  unsigned int  num_deps;
  int           i;
  
  if (!group || !group->dependents) {
    return;
  }
  deps = (ZnItem *) ZnListArray(group->dependents);
  num_deps = ZnListSize(group->dependents);
  
  for (i = num_deps-1; i >= 0; i--) {
    current_item = deps[i];
    if (current_item->connected_item == item) {
      current_item->connected_item = ZN_NO_ITEM;
      ZnListDelete(group->dependents, i);
      ZnITEM.Invalidate(current_item, ZN_COORDS_FLAG);
    }
  }
  if (ZnListSize(group->dependents) == 0) {
    ZnListFree(group->dependents);
    group->dependents = NULL;
  }
}


/*
 **********************************************************************************
 *
 * ZnGroupExtractItem --
 *
 **********************************************************************************
 */
void
ZnGroupExtractItem(ZnItem       item)
{
  GroupItem     group;
  
  if (!item->parent) {
    return;
  }
  group = (GroupItem) item->parent;
  
  if (item->previous != ZN_NO_ITEM) {
    item->previous->next = item->next;
  }
  else {
    group->head = item->next;
  }
  
  if (item->next != ZN_NO_ITEM) {
    item->next->previous = item->previous;
  }
  else {
    group->tail = item->previous;
  }
  
  ZnITEM.Invalidate((ZnItem) group, ZN_COORDS_FLAG);

  item->previous = ZN_NO_ITEM;
  item->next = ZN_NO_ITEM;
  item->parent = NULL;
}


/*
 **********************************************************************************
 *
 * ZnGroupInsertItem --
 *
 **********************************************************************************
 */
void
ZnGroupInsertItem(ZnItem        group,
                  ZnItem        item,
                  ZnItem        mark_item,
                  ZnBool        before)
{
  GroupItem     grp = (GroupItem) group;

  /*
   * Empty list, add the first item.
   */
  if (grp->head == ZN_NO_ITEM) {
    grp->head = grp->tail = item;
    item->previous = item->next = ZN_NO_ITEM;
    return;
  }

  if (mark_item != ZN_NO_ITEM) {
    /*
     * Better leave here, mark_item will not
     * have the links set right.
     */
    if (mark_item == item) {
      return;
    }
    /*
     * Force the priority to be the same as the reference
     * item;
     */
    item->priority = mark_item->priority;
  }
  else {
    mark_item = grp->head;
    while ((mark_item != ZN_NO_ITEM) &&
           (mark_item->priority > item->priority)) {
      mark_item = mark_item->next;
    }
    before = True;
  }
  
  if (before && (mark_item != ZN_NO_ITEM)) {
    /*
     * Insert before mark.
     */
    item->next = mark_item;
    item->previous = mark_item->previous;
    if (mark_item->previous == ZN_NO_ITEM) {
      grp->head = item;
    }
    else {
      mark_item->previous->next = item;
    }
    mark_item->previous = item;
  }
  else {
    /*
     * Insert after mark either because 'before' is False
     * and mark_item valid or because the right place is at
     * the end of the list and mark_item is ZN_NO_ITEM.
     */
    if (mark_item == ZN_NO_ITEM) {
      grp->tail->next = item;
      item->previous = grp->tail;
      grp->tail = item;
    }
    else {
      item->previous = mark_item;
      item->next = mark_item->next;
      if (item->next == ZN_NO_ITEM) {
        grp->tail = item;
      }
      else {
        item->next->previous = item;
      }
      mark_item->next = item;
    }
  }

  ZnITEM.Invalidate(group, ZN_COORDS_FLAG);
}

/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  ZnBBox *bbox = &item->item_bounding_box;

  ZnOrigin2Anchor(&bbox->orig,
                  bbox->corner.x - bbox->orig.x,
                  bbox->corner.y - bbox->orig.y,
                  anchor, p);
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct GROUP_ITEM_CLASS = {
  "group",
  sizeof(GroupItemStruct),
  group_attrs,
  0,                    /* num_parts */
  ZN_CLASS_ONE_COORD,   /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  NULL,                 /* GetClipVertices */
  NULL,                 /* GetContours */
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  PreRender,            /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnGroup = (ZnItemClassId) &GROUP_ITEM_CLASS;

Added jni/tkzinc/generic/Group.h.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * Group.h -- Header for Group items.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 2002 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Group_h
#define _Group_h


ZnItem ZnGroupHead(ZnItem group);
ZnItem ZnGroupTail(ZnItem group);
ZnBool ZnGroupCallOm(ZnItem group);
ZnBool ZnGroupAtomic(ZnItem group);
void ZnGroupSetCallOm(ZnItem group, ZnBool set);
void ZnInsertDependentItem(ZnItem item);
void ZnExtractDependentItem(ZnItem item);
void ZnDisconnectDependentItems(ZnItem item);
void ZnGroupInsertItem(ZnItem group, ZnItem item, ZnItem mark_item, ZnBool before);
void ZnGroupExtractItem(ZnItem item);
void ZnGroupRemoveClip(ZnItem group, ZnItem clip);

#endif /* _Group_h */

Added jni/tkzinc/generic/Icon.c.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
/*
 * Icon.c -- Implementation of Icon item.
 *
 * Authors              : Patrick LECOANET
 * Creation date        : Sat Mar 25 13:53:39 1995
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Item.h"
#include "Geo.h"
#include "Draw.h"
#include "Types.h"
#include "Image.h"
#include "WidgetInfo.h"
#include "tkZinc.h"


static const char rcsid[] = "$Id$";
static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 **********************************************************************************
 *
 * Specific Icon item record
 *
 **********************************************************************************
 */
typedef struct _IconItemStruct {
  ZnItemStruct  header;

  /* Public data */
  ZnPoint       pos;
  ZnImage       image;
  Tk_Anchor     anchor;
  Tk_Anchor     connection_anchor;
  ZnGradient    *color; /* Used only if the image is a bitmap (in GL alpha part
                         * is always meaningful). */
  
  /* Private data */
  ZnPoint       dev[4];
} IconItemStruct, *IconItem;


static ZnAttrConfig     icon_attrs[] = {
  { ZN_CONFIG_ANCHOR, "-anchor", NULL,
    Tk_Offset(IconItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(IconItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-color", NULL,
    Tk_Offset(IconItemStruct, color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(IconItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(IconItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(IconItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ITEM, "-connecteditem", NULL,
    Tk_Offset(IconItemStruct, header.connected_item), 0,
    ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
  { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
    Tk_Offset(IconItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_IMAGE, "-image", NULL,
    Tk_Offset(IconItemStruct, image), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-mask", NULL,
    Tk_Offset(IconItemStruct, image), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(IconItemStruct, pos), 0,
    ZN_COORDS_FLAG, False},
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(IconItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(IconItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(IconItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(IconItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};



/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  ZnWInfo       *wi = item->wi;
  IconItem      icon = (IconItem) item;

  /*printf("size of an icon(header) = %d(%d)\n",
    sizeof(IconItemStruct), sizeof(ZnItemStruct));*/

  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 1;

  icon->pos.x = icon->pos.y = 0.0;
  icon->image = ZnUnspecifiedImage;
  icon->anchor = TK_ANCHOR_NW;
  icon->connection_anchor = TK_ANCHOR_SW;
  icon->color = ZnGetGradientByValue(wi->fore_color);
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  IconItem      icon = (IconItem) item;
  
  if (icon->image != ZnUnspecifiedImage) {
    icon->image = ZnGetImageByValue(icon->image, ZnUpdateItemImage, item);
  }
  icon->color = ZnGetGradientByValue(icon->color);
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  IconItem      icon = (IconItem) item;

  if (icon->image != ZnUnspecifiedImage) {
    ZnFreeImage(icon->image, ZnUpdateItemImage, item);
    icon->image = ZnUnspecifiedImage;
  }
  ZnFreeGradient(icon->color);
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  ZnItem        old_connected;

  old_connected = item->connected_item;
  if (ZnConfigureAttributes(item->wi, item, item, icon_attrs,
                            argc, argv, flags) == TCL_ERROR) {
    item->connected_item = old_connected;
    return TCL_ERROR;
  }  

  if (ISSET(*flags, ZN_ITEM_FLAG)) {
    /*
     * If the new connected item is not appropriate back up
     * to the old one.
     */
    if ((item->connected_item == ZN_NO_ITEM) ||
        (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
         (item->parent == item->connected_item->parent))) {
      ZnITEM.UpdateItemDependency(item, old_connected);
    }
    else {
      item->connected_item = old_connected;
    }
  }  

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, icon_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }  

  return TCL_OK;
}


/*
 * Compute the transformation to be used and the origin
 * of the icon (upper left point in item coordinates).
 */
static ZnTransfo *
ComputeTransfoAndOrigin(ZnItem    item,
                        ZnPoint   *origin)
{
  IconItem icon = (IconItem) item;
  int       w, h;
  ZnTransfo *t;

  ZnSizeOfImage(icon->image, &w, &h);

  /*
   * The connected item support anchors, this is checked by configure.
   */
  if (item->connected_item != ZN_NO_ITEM) {
    ZnTransfo inv;

    item->connected_item->class->GetAnchor(item->connected_item,
                                           icon->connection_anchor,
                                           origin);

    /* GetAnchor return a position in device coordinates not in
     * the item coordinate space. To compute the icon origin
     * (upper left corner), we must apply the inverse transform
     * to the ref point before calling anchor2origin.
     */
    ZnTransfoInvert(item->transfo, &inv);
    ZnTransformPoint(&inv, origin, origin);
    /*
     * The relevant transform in case of an attachment is the item
     * transform alone. This is case of local coordinate space where
     * only the translation is a function of the whole transform
     * stack, scale and rotation are reset.
     */
    t = item->transfo;
  }
  else {
    origin->x = origin->y = 0;
    t = item->wi->current_transfo;
  }

  ZnAnchor2Origin(origin, (ZnReal) w, (ZnReal) h, icon->anchor, origin);
  //origin->x = ZnNearestInt(origin->x);
  //origin->y = ZnNearestInt(origin->y);

  return t;
}

/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  //ZnWInfo   *wi = item->wi;
  IconItem  icon = (IconItem) item;
  int       width, height, i;
  ZnPoint   quad[4];
  ZnTransfo *t;
  
  ZnResetBBox(&item->item_bounding_box);

  /*
   * If there is no image then nothing to show.
   */
  if (icon->image == ZnUnspecifiedImage) {
    return;
  }
    
  ZnSizeOfImage(icon->image, &width, &height);
  t = ComputeTransfoAndOrigin(item, quad);

  quad[1].x = quad[0].x;
  quad[1].y = quad[0].y + height;
  quad[2].x = quad[0].x + width;
  quad[2].y = quad[1].y;
  quad[3].x = quad[2].x;
  quad[3].y = quad[0].y;
  ZnTransformPoints(t, quad, icon->dev, 4);
  
  for (i = 0; i < 4; i++) {
    icon->dev[i].x = ZnNearestInt(icon->dev[i].x);
    icon->dev[i].y = ZnNearestInt(icon->dev[i].y);
  }
  
  /*
   * Compute the bounding box.
   */
  ZnAddPointsToBBox(&item->item_bounding_box, icon->dev, 4);

  /*
   * Update connected items.
   */
  SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  IconItem      icon = (IconItem) item;
  
  if (icon->image == ZnUnspecifiedImage) {
    return -1;
  }

  return ZnPolygonInBBox(icon->dev, 4, ta->area, NULL);
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  IconItem      icon = (IconItem) item;
  XGCValues     values;
  unsigned int  gc_mask = 0;
  int           w, h;
  ZnBBox        box, inter, *clip_box;
  TkRegion      clip_region, photo_region, clip;
  ZnBool        simple;
  Pixmap        pixmap;
  
  if (icon->image == ZnUnspecifiedImage) {
    return;
  }

  ZnSizeOfImage(icon->image, &w, &h);
  box.orig = *icon->dev;
  box.corner.x = icon->dev->x + w;
  box.corner.y = icon->dev->y + h;
  if (!ZnImageIsBitmap(icon->image)) {
    if (ZnTransfoIsTranslation(item->wi->current_transfo)) {
      /*
       * The code below does not use of Tk_RedrawImage to be
       * able to clip with the current clip region.
       */
      ZnIntersectBBox(&box, &wi->damaged_area, &inter);
      box = inter;
      ZnCurrentClip(wi, &clip_region, NULL, NULL);
      pixmap = ZnImagePixmap(icon->image, wi->win);
      photo_region = ZnImageRegion(icon->image);
      clip = TkCreateRegion();
      /*
       * ZnImageRegion may fail: perl/Tk 800.24 doesn't support
       * some internal TkPhoto functions.
       * This is a workaround using a rectangular region based
       * on the image size.
       */
      if (photo_region == NULL) {
        XRectangle rect;
        rect.x = rect.y = 0;
        rect.width = w;
        rect.height = h;
        TkUnionRectWithRegion(&rect, clip, clip);
      }
      else {
        ZnUnionRegion(clip, photo_region, clip);
      }
      ZnOffsetRegion(clip, (int) icon->dev->x, (int) icon->dev->y);
      TkIntersectRegion(clip_region, clip, clip);
      TkSetRegion(wi->dpy, wi->gc, clip);
      XCopyArea(wi->dpy, pixmap, wi->draw_buffer, wi->gc,
                (int) (box.orig.x-icon->dev->x),
                (int) (box.orig.y-icon->dev->y),
                (unsigned int) (box.corner.x-box.orig.x),
                (unsigned int) (box.corner.y-box.orig.y),
                (int) box.orig.x,
                (int) box.orig.y);
      values.clip_x_origin = values.clip_y_origin = 0;
      XChangeGC(wi->dpy, wi->gc, GCClipXOrigin|GCClipYOrigin, &values);
      TkSetRegion(wi->dpy, wi->gc, clip_region);
      TkDestroyRegion(clip);
    }
    else {
      ZnPoint       box[4];
      int           i;
      XImage        *dest_im, *src_im;
      XImage        *dest_mask, *src_mask;
      Pixmap        drw, mask;
      unsigned int  dest_im_width, dest_im_height;
      unsigned int  max_width, max_height;
      GC            gc, mask_gc;
      TkRegion      current_clip;
      ZnBBox        *current_clip_box;

      dest_im_width = (unsigned int) (item->item_bounding_box.corner.x -
                                      item->item_bounding_box.orig.x);
      max_width = MAX(dest_im_width, (unsigned int) w);
      dest_im_height = (unsigned int) (item->item_bounding_box.corner.y -
                                       item->item_bounding_box.orig.y);
      max_height = MAX(dest_im_height, (unsigned int) h);

      mask = Tk_GetPixmap(wi->dpy, wi->draw_buffer, max_width, max_height, 1);

      drw = Tk_GetPixmap(wi->dpy, wi->draw_buffer, max_width, max_height,
                         Tk_Depth(wi->win));
      mask_gc = XCreateGC(wi->dpy, mask, 0, NULL);
      gc = XCreateGC(wi->dpy, drw, 0, NULL);
      dest_mask = XCreateImage(wi->dpy, Tk_Visual(wi->win), 1,
                             ZPixmap, 0, NULL, dest_im_width, dest_im_height,
                             8, 0);
      dest_mask->data = ZnMalloc(dest_mask->bytes_per_line * dest_mask->height);
      memset(dest_mask->data, 0, dest_mask->bytes_per_line * dest_mask->height);
      XSetForeground(wi->dpy, mask_gc, 0);
      XFillRectangle(wi->dpy, mask, mask_gc, 0, 0, max_width, max_height);
      dest_im = XCreateImage(wi->dpy, Tk_Visual(wi->win), Tk_Depth(wi->win),
                             ZPixmap, 0, NULL, dest_im_width, dest_im_height,
                             32, 0);
      dest_im->data = ZnMalloc(dest_im->bytes_per_line * dest_im->height);
      memset(dest_im->data, 0, dest_im->bytes_per_line * dest_im->height);

      pixmap = ZnImagePixmap(icon->image, wi->win);
      photo_region = ZnImageRegion(icon->image);
      clip = TkCreateRegion();
      /*
       * ZnImageRegion may fail: perl/Tk 800.24 doesn't support
       * some internal TkPhoto functions.
       * This is a workaround using a rectangular region based
       * on the image size.
       */
      if (photo_region == NULL) {
        XRectangle rect;
        rect.x = rect.y = 0;
        rect.width = w;
        rect.height = h;
        TkUnionRectWithRegion(&rect, clip, clip);
      }
      else {
        ZnUnionRegion(clip, photo_region, clip);
      }
      XSetForeground(wi->dpy, mask_gc, 1);
      TkSetRegion(wi->dpy, mask_gc, clip);
      XFillRectangle(wi->dpy, mask, mask_gc, 0, 0, w, h);
  
      src_mask = XGetImage(wi->dpy, mask, 0, 0, w, h, 1, ZPixmap);
      src_im = XGetImage(wi->dpy, pixmap, 0, 0, w, h, ~0L, ZPixmap);

      box[0] = icon->dev[0];
      box[1] = icon->dev[1];
      box[2] = icon->dev[3];
      box[3] = icon->dev[2];
      for (i = 0; i < 4; i++) {
        box[i].x -= item->item_bounding_box.orig.x;
        box[i].y -= item->item_bounding_box.orig.y;
        box[i].x = ZnNearestInt(box[i].x);
        box[i].y = ZnNearestInt(box[i].y);
      }

      ZnMapImage(src_mask, dest_mask, box);
      ZnMapImage(src_im, dest_im, box);

      ZnCurrentClip(wi, &current_clip, &current_clip_box, NULL);
      TkSetRegion(wi->dpy, mask_gc, current_clip);
      XSetClipOrigin(wi->dpy, mask_gc,
                     (int) -item->item_bounding_box.orig.x, (int) -item->item_bounding_box.orig.y);
#ifdef PLATFORM_SDL
      XPutImage(wi->dpy, mask, mask_gc, dest_mask,
                0, 0, 0, 0, dest_im_width, dest_im_height);
      XPutImage(wi->dpy, drw, gc, dest_im,
                0, 0, 0, 0, dest_im_width, dest_im_height);
#else
      TkPutImage(NULL, 0, wi->dpy, mask, mask_gc, dest_mask,
                 0, 0, 0, 0, dest_im_width, dest_im_height);
      TkPutImage(NULL, 0, wi->dpy, drw, gc, dest_im,
                 0, 0, 0, 0, dest_im_width, dest_im_height);
#endif

      XSetClipMask(wi->dpy, gc, mask);
      XSetClipOrigin(wi->dpy, gc,
                     (int) item->item_bounding_box.orig.x,
                     (int) item->item_bounding_box.orig.y);
      XCopyArea(wi->dpy, drw, wi->draw_buffer, gc,
                0, 0, dest_im_width, dest_im_height,
                (int) item->item_bounding_box.orig.x,
                (int) item->item_bounding_box.orig.y);

      XFreeGC(wi->dpy, gc);
      XFreeGC(wi->dpy, mask_gc);
      Tk_FreePixmap(wi->dpy, drw);
      Tk_FreePixmap(wi->dpy, mask);
      XDestroyImage(src_mask);
      XDestroyImage(dest_mask);
      XDestroyImage(src_im);
      XDestroyImage(dest_im);
    }
  }
  else {
    /*
     * If the current transform is a pure translation, it is
     * possible to optimize by directly drawing to the X back
     * buffer. Else, we draw in a temporary buffer, get
     * its content as an image, transform the image into another
     * one and use this last image as a mask to draw in the X
     * back buffer.
     */
    pixmap = ZnImagePixmap(icon->image, wi->win);
    if (ZnTransfoIsTranslation(item->wi->current_transfo)) {
      ZnCurrentClip(wi, NULL, &clip_box, &simple);
      if (simple) {
        ZnIntersectBBox(&box, clip_box, &inter);
        box = inter;
      }
      values.fill_style = FillStippled;
      values.stipple = pixmap;
      values.ts_x_origin = (int) icon->dev->x;
      values.ts_y_origin = (int) icon->dev->y;
      values.foreground = ZnGetGradientPixel(icon->color, 0.0);
      gc_mask |= GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground;
      XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
      XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
                     (int) box.orig.x,
                     (int) box.orig.y,
                     (unsigned int) (box.corner.x-box.orig.x),
                     (unsigned int) (box.corner.y-box.orig.y));
    }
    else {
      ZnPoint       box[4];
      int           i;
      XImage        *dest_im, *src_im;
      Pixmap        drw;
      unsigned int  dest_im_width, dest_im_height;
      unsigned int  max_width, max_height;
      GC            gc;

      dest_im_width = (unsigned int) (item->item_bounding_box.corner.x -
                                      item->item_bounding_box.orig.x);
      max_width = MAX(dest_im_width, (unsigned int) w);
      dest_im_height = (unsigned int) (item->item_bounding_box.corner.y -
                                       item->item_bounding_box.orig.y);
      max_height = MAX(dest_im_height, (unsigned int) h);
      
      drw = Tk_GetPixmap(wi->dpy, wi->draw_buffer, max_width, max_height, 1);
      gc = XCreateGC(wi->dpy, drw, 0, NULL);
      XSetForeground(wi->dpy, gc, 0);
      XFillRectangle(wi->dpy, drw, gc, 0, 0, max_width, max_height);
      dest_im = XCreateImage(wi->dpy, Tk_Visual(wi->win), 1,
                             ZPixmap, 0, NULL, dest_im_width, dest_im_height,
                             8, 0);
      dest_im->data = ZnMalloc(dest_im->bytes_per_line * dest_im->height);
      memset(dest_im->data, 0, dest_im->bytes_per_line * dest_im->height);

      values.fill_style = FillStippled;
      values.stipple = pixmap;
      values.ts_x_origin = 0;
      values.ts_y_origin = 0;
      values.foreground = 1;
      gc_mask |= GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground;
      XChangeGC(wi->dpy, gc, gc_mask, &values);
      XFillRectangle(wi->dpy, drw, gc, 0, 0, w, h);

      src_im = XGetImage(wi->dpy, drw, 0, 0, w, h, 1, ZPixmap);

      box[0] = icon->dev[0];
      box[1] = icon->dev[1];
      box[2] = icon->dev[3];
      box[3] = icon->dev[2];
      for (i = 0; i < 4; i++) {
        box[i].x -= item->item_bounding_box.orig.x;
        box[i].y -= item->item_bounding_box.orig.y;
        box[i].x = ZnNearestInt(box[i].x);
        box[i].y = ZnNearestInt(box[i].y);
      }

      ZnMapImage(src_im, dest_im, box);

#ifdef PLATFORM_SDL
      XPutImage(wi->dpy, drw, gc, dest_im,
                0, 0, 0, 0, dest_im_width, dest_im_height);
#else
      TkPutImage(NULL, 0, wi->dpy, drw, gc, dest_im,
                 0, 0, 0, 0, dest_im_width, dest_im_height);
#endif

      values.foreground = ZnGetGradientPixel(icon->color, 0.0);
      values.stipple = drw;
      values.ts_x_origin = (int) item->item_bounding_box.orig.x;
      values.ts_y_origin = (int) item->item_bounding_box.orig.y;
      values.fill_style = FillStippled;
      XChangeGC(wi->dpy, wi->gc,
                GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground,
                &values);
      XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
                     (int) item->item_bounding_box.orig.x,
                     (int) item->item_bounding_box.orig.y,
                     (int) dest_im_width, (int) dest_im_height);

      XFreeGC(wi->dpy, gc);
      Tk_FreePixmap(wi->dpy, drw);
      XDestroyImage(src_im);
      XDestroyImage(dest_im);
    }
  }
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
Render(ZnItem   item)
{
  ZnWInfo       *wi = item->wi;
  IconItem      icon = (IconItem) item;
  
  if (icon->image != ZnUnspecifiedImage) {
    ZnRenderImage(wi, icon->image, icon->color, icon->dev,
                  ZnImageIsBitmap(icon->image));
  }
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  IconItem      icon = (IconItem) item;
  ZnWInfo       *wi = item->wi;
  double        dist;
  double        off_dist = MAX(1, wi->pick_aperture+1);
  int           x, y, width, height;
  ZnPoint       p;
  ZnBBox        bbox;
  ZnTransfo     t;

  if (icon->image == ZnUnspecifiedImage) {
    return 1.0e40;
  }

  ZnTransfoInvert(wi->current_transfo, &t);
  ZnTransformPoint(&t, ps->point, &p);
  ZnTransformPoint(&t, &icon->dev[0], &bbox.orig);
  ZnSizeOfImage(icon->image, &width, &height);
  bbox.corner.x = bbox.orig.x + width;
  bbox.corner.y = bbox.orig.y + height;
  dist = ZnRectangleToPointDist(&bbox, &p);
  x = (int) (p.x - bbox.orig.x);
  y = (int) (p.y - bbox.orig.y);
  /*printf("dist: %g\n", dist);*/

  /*
   * If inside the icon rectangle, try to see if the point
   * is actually on the image or not. If it lies in an
   * area that is between pick_aperture+1 around the external
   * rectangle and the actual shape, the distance will be reported
   * as pick_aperture+1. Inside the actual shape it will be
   * reported as 0. This is a kludge, there is currently
   * no means to compute the real distance in the icon's
   * vicinity.
   */
  if (dist <= 0) {
    dist = 0.0;
    if (icon->image != ZnUnspecifiedImage) {
      if (ZnPointInImage(icon->image, x, y)) {
        /*
         * The point is actually on the image shape.
         */
        return dist;
      }
      else {
        /*
         * The point is not on the shape but still
         * inside the image's bounding box.
         */
        return off_dist;
      }
    }
    else {
      return dist;
    }
  }
  else if (dist < off_dist) {
    dist = off_dist;
  }

  return dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ZnWInfo       *wi = item->wi;
  IconItem      icon = (IconItem) item;
  int           w, h, result;
  ZnPoint       origin;
  char          path[500];

  if (prepass || (icon->image == ZnUnspecifiedImage)) {
    return TCL_OK;
  }
  
  ZnSizeOfImage(icon->image, &w, &h);

  ComputeTransfoAndOrigin(item, &origin);
  
  sprintf(path, "/InitialTransform load setmatrix\n"
          "[%.15g %.15g %.15g %.15g %.15g %.15g] concat\n"
          "1 -1 scale\n"
          "%.15g %.15g translate\n",
          wi->current_transfo->_[0][0], wi->current_transfo->_[0][1], 
          wi->current_transfo->_[1][0], wi->current_transfo->_[1][1], 
          wi->current_transfo->_[2][0], wi->current_transfo->_[2][1],
          origin.x, origin.y - h);
  Tcl_AppendResult(wi->interp, path, NULL);
  
  if (ZnImageIsBitmap(icon->image)) {
    if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                           ZnGetGradientColor(icon->color, 0.0, NULL)) != TCL_OK) {
      return TCL_ERROR;
    }
    result = ZnPostscriptBitmap(wi->interp, wi->win, wi->ps_info,
                                icon->image, 0, 0, w, h);
  }
  else {
    result = Tk_PostscriptImage(ZnImageTkImage(icon->image), wi->interp, wi->win,
                                wi->ps_info, 0, 0, w, h, prepass);
  }
  
  return result;
}


/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  IconItem      icon = (IconItem) item;
  
  if (icon->image == ZnUnspecifiedImage) {
    *p = *icon->dev;
  }
  else {
    ZnPoint q[4];
    q[0] = icon->dev[0];
    q[1] = icon->dev[1];
    q[2] = icon->dev[3];
    q[3] = icon->dev[2];
    ZnRectOrigin2Anchor(q, anchor, p);
  }
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  IconItem      icon = (IconItem) item;
  ZnPoint       *points;
  
  ZnListAssertSize(ZnWorkPoints, 4);
  points = ZnListArray(ZnWorkPoints);
  points[0] = icon->dev[0];
  points[1] = icon->dev[1];
  points[2] = icon->dev[3];
  points[3] = icon->dev[2];
  ZnTriStrip1(tristrip, points, 4, False);
  
  return False;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item origin. This doesn't take care of
 *      the possible attachment. The change will be effective at the
 *      end of the attachment.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  IconItem      icon = (IconItem) item;
  
  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " icons can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (*num_pts == 0) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 1 point on icons", NULL);
      return TCL_ERROR;
    }
    icon->pos = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    *num_pts = 1;
    *pts = &icon->pos;
  }
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct ICON_ITEM_CLASS = {
  "icon",
  sizeof(IconItemStruct),
  icon_attrs,
  0,                    /* num_parts */
  ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
  Tk_Offset(IconItemStruct, pos),
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  GetClipVertices,
  NULL,                 /* GetContours */
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnIcon = (ZnItemClassId) &ICON_ITEM_CLASS;

Added jni/tkzinc/generic/Image.c.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
/*
 * Image.c -- Image support routines.
 *
 * Authors              : Patrick LECOANET
 * Creation date        : Wed Dec  8 11:04:44 1999
 */

/*
 *  Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Types.h"
#include "tkZinc.h"
#include "Image.h"
#include "WidgetInfo.h"
#include "Geo.h"
#include "Draw.h"
#include "perfos.h"

#include <memory.h>
#include <ctype.h>
#ifdef GL
#include <stdlib.h>
#endif


static const char rcsid[] = "$Id$";
static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


static int              images_inited = 0;
static Tcl_HashTable    images;
#ifdef GL
static Tcl_HashTable    font_textures;
#endif

typedef struct _ClientStruct {
  void  (*inv_proc)(void *cd);
  void  *client_data;
  int   refcount;
} ClientStruct;

typedef struct _ImageStruct {
  union {
    Pixmap      pixmap;
#ifdef GL
    GLuint      texobj;
#endif
  } i;
  Display       *dpy;
  Screen        *screen;
  struct _ImageBits *bits;

  /* Bookkeeping */

  ZnBool        for_gl;
  int           refcount;
  ZnList        clients;
  struct _ImageStruct   *next;
} ImageStruct, *Image;


typedef struct _ImageBits {
  unsigned char *bpixels;  /* Needed for bitmaps. Set to NULL if the image
                            * is not a bitmap. */
  int           rowstride;
#ifdef GL
  ZnReal        t;         /* Texture parameters for the image. */
  ZnReal        s;
  int           t_width;   /* Texture size used for this image. */
  int           t_height;
  unsigned char *t_bits;   /* Can be NULL if texture is not used (no GL
                            * rendering active on this image). */
#endif

  /* Bookeeping */
  Display       *dpy;     /* The tkimage below comes from this display. */
  Tcl_Interp    *interp;  /* The interp that created the tkimage below. */
  Tk_Image      tkimage;  /* Keep this handle to be informed of changes */ 
  Tk_PhotoHandle tkphoto;
  TkRegion      valid_region;
  int           width;
  int           height;
  int           depth;
  Tcl_HashEntry *hash;    /* From this it is easy to get the image/bitmap
                           * name. */
  Image         images;   /* Linked list of widget/display dependant
                           * specializations of this image. If NULL, the
                           * image has no specialization and can be freed. */
} ImageBits;


char *ZnNameOfImage(ZnImage image);

#ifdef GL

int
To2Power(int a)
{
  int result = 1;

  while (result < a) {
    result *= 2;
  }
  return result;
}
#endif
     

/*
 **********************************************************************************
 *
 * ZnGetImage --
 *
 **********************************************************************************
 */
static void
InvalidateImage(ClientData      client_data,
                int             x,
                int             y,
                int             width,
                int             height,
                int             image_width,
                int             image_height)
{
  ImageBits    *bits = (ImageBits *) client_data;
  Image        this;
  int          num_cs, count, i;
  ClientStruct *cs;
  char          *image_name;

  /*  printf("Invalidation, bits: %d, %d %d %d %d %d %d\n",
      client_data, x, y, width, height, image_width, image_height);*/
  if (ZnImageIsBitmap(bits->images)) {
    /* This is a bitmap nothing to update
     * (This should not happen) */
    return;
  }

#ifdef GL
  if (bits->t_bits) {
    ZnFree(bits->t_bits);
    bits->t_bits = NULL;
  }
#endif
  if (bits->valid_region) {
    TkDestroyRegion(bits->valid_region);
    bits->valid_region = NULL;
  }

  bits->width = image_width;
  bits->height = image_height;
  image_name = ZnNameOfImage(bits->images);

  /*
   * The photo pointer must be updated. It changes when creating an new image with
   * the same name as an old. The image is first deleted then re-instantiated.
   * As a side effect we also rely on it for telling if an image is a photo.
   */
  bits->tkphoto = Tk_FindPhoto(bits->interp, image_name);

  count = 0;
  this = bits->images;
  while (this) {
#ifdef GL
    if (this->for_gl) {
      if (this->i.texobj) {
        ZnGLContextEntry *ce;
        ce = ZnGLMakeCurrent(this->dpy, 0);
        glDeleteTextures(1, &this->i.texobj);
        ZnGLReleaseContext(NULL, ce);
        this->i.texobj = 0;
      }
    }
    else {
#endif
      if (this->i.pixmap != None) {
        Tk_FreePixmap(this->dpy, this->i.pixmap);
        this->i.pixmap = None;    
      }
#ifdef GL
    }
#endif
          
    num_cs = ZnListSize(this->clients);
    cs = ZnListArray(this->clients);
    for (i = 0; i < num_cs; i++, cs++) {
      if (cs->inv_proc) {
        (*cs->inv_proc)(cs->client_data);
      }
    }
    count += num_cs;
    this = this->next;
  }
  /*printf("Invalidate on image %s with %d clients\n",
    Tcl_GetHashKey(&images, bits->hash), count);*/
}

ZnImage
ZnGetImage(ZnWInfo      *wi,
           Tk_Uid       image_name,
           void         (*inv_proc)(void *cd),
           void         *client_data)
{
  Tcl_HashEntry *entry;
  int           new, num_cs, i;
  ImageBits     *bits;
  ZnBool        for_gl = wi->render>0;
  Image         image;
  CONST Tk_ImageType *type;
  ClientStruct  cs, *cs_ptr;

  /*printf("ZnGetImage: %s\n", image_name);*/
  if (!images_inited) {
    Tcl_InitHashTable(&images, TCL_STRING_KEYS);
    images_inited = 1;
  }
  image_name = Tk_GetUid(image_name);
  entry = Tcl_FindHashEntry(&images, image_name);
  if (entry != NULL) {
    /*printf("Image \"%s\" is in cache\n", image_name);*/
    bits = (ImageBits *) Tcl_GetHashValue(entry);
  }
  else {
    /*printf("New image \"%s\"\n", image_name);*/
    if (strcmp(image_name, "") == 0) {
      return ZnUnspecifiedImage;
    }

    bits = ZnMalloc(sizeof(ImageBits));
#ifdef GL
    bits->t_bits = NULL;
#endif
    bits->images = NULL;
    bits->bpixels = NULL;
    bits->valid_region = NULL;
    bits->tkimage = NULL;
    bits->tkphoto = NULL;
    bits->interp = wi->interp;
    bits->dpy = wi->dpy;

    if (!Tk_GetImageMasterData(wi->interp, image_name, &type)) {
      /*
       * This doesn't seem to be a Tk image, try to load
       * a Tk bitmap.
       */
      Pixmap    pmap;
      XImage    *mask;
      int       x, y;
      unsigned char *line;
      
      pmap = Tk_GetBitmap(wi->interp, wi->win, image_name);
      if (pmap == None) {
        ZnWarning("unknown bitmap/image \"");
        goto im_error;
      }
      
      Tk_SizeOfBitmap(wi->dpy, pmap, &bits->width, &bits->height);    
      mask = XGetImage(wi->dpy, pmap, 0, 0, (unsigned int) bits->width,
                       (unsigned int) bits->height, 1L, ZPixmap);
      bits->depth = 1;
      bits->rowstride = mask->bytes_per_line;
      bits->bpixels = ZnMalloc((unsigned int) (bits->height * bits->rowstride));
      memset(bits->bpixels, 0, (unsigned int) (bits->height * bits->rowstride));
      line = bits->bpixels;
      for (y = 0; y < bits->height; y++) {
        for (x = 0; x < bits->width; x++) {
          if (XGetPixel(mask, x, y)) {
            line[x >> 3] |= 0x80 >> (x & 7);
          }
        }
        line += bits->rowstride;
      }
      XDestroyImage(mask);
      Tk_FreeBitmap(wi->dpy, pmap);
    }
    
    else if (strcmp(type->name, "photo") == 0) {
      /* Processing will yield an image photo */
      bits->tkphoto = Tk_FindPhoto(wi->interp, image_name);
      Tk_PhotoGetSize(bits->tkphoto, &bits->width, &bits->height);
      if ((bits->width == 0) || (bits->height == 0)) {
        ZnWarning("bogus photo image \"");
        goto im_error;
      }
      bits->depth = Tk_Depth(wi->win);
      bits->tkimage = Tk_GetImage(wi->interp, wi->win, image_name,
                                  InvalidateImage, (ClientData) bits);
    }
    else { /* Other image types */
      bits->depth = Tk_Depth(wi->win);
      bits->tkimage = Tk_GetImage(wi->interp, wi->win, image_name,
                                  InvalidateImage, (ClientData) bits);
      Tk_SizeOfImage(bits->tkimage, &bits->width, &bits->height);
      if ((bits->width == 0) || (bits->height == 0)) {
        ZnWarning("bogus ");
        ZnWarning(type->name);
        ZnWarning(" image \"");
      im_error:
        ZnWarning(image_name);
        ZnWarning("\"\n");
        ZnFree(bits);
        return ZnUnspecifiedImage;      
      }
    }

    entry = Tcl_CreateHashEntry(&images, image_name, &new);
    bits->hash = entry;
    Tcl_SetHashValue(entry, (ClientData) bits);
  }

  /*
   * Try to find an image instance that fits this widget/display.
   */
  for (image = bits->images; image != NULL; image = image->next) {
    if (image->for_gl == for_gl) {
      if ((for_gl && (image->dpy == wi->dpy)) ||
          (!for_gl && (image->screen == wi->screen))) {
        if (!ZnImageIsBitmap(image)) {
          cs_ptr = ZnListArray(image->clients);
          num_cs = ZnListSize(image->clients);
          for (i = 0; i < num_cs; i++, cs_ptr++) {
            if ((cs_ptr->inv_proc == inv_proc) &&
                (cs_ptr->client_data == client_data)) {
              cs_ptr->refcount++;
              return image;
            }
          }
          /* Add a new client reference to call back.
           */
          cs.inv_proc = inv_proc;
          cs.client_data = client_data;
          cs.refcount = 1;
          ZnListAdd(image->clients, &cs, ZnListTail);
          return image;
        }
        image->refcount++;
        return image;
      }
    }
  }

  /*
   * Create a new instance for this case.
   */
  /*printf("new instance for \"%s\"\n", image_name);*/
  image = ZnMalloc(sizeof(ImageStruct));
  image->bits = bits;
  image->refcount = 0;
  image->for_gl = for_gl;
  image->dpy = wi->dpy;
  image->screen = wi->screen;

  if (!ZnImageIsBitmap(image)) {
    image->clients = ZnListNew(1, sizeof(ClientStruct));
    cs.inv_proc = inv_proc;
    cs.client_data = client_data;
    cs.refcount = 1;
    ZnListAdd(image->clients, &cs, ZnListTail);
  }
  else {
    image->refcount++;
  }

  /* Init the real resource and let the client load it
   * on demand */
  if (image->for_gl) {
#ifdef GL
    image->i.texobj = 0;
#endif
  }
  else {
    image->i.pixmap = None;
    /*    image->i.pixmap = Tk_GetBitmap(wi->interp, wi->win, image_name);
          printf("pmap: %d\n", image->i.pixmap);*/
  }
  image->next = bits->images;
  bits->images = image;

  return image;
}


/*
 **********************************************************************************
 *
 * ZnGetImageByValue --
 *
 **********************************************************************************
 */
ZnImage
ZnGetImageByValue(ZnImage       image,
                  void          (*inv_proc)(void *cd),
                  void          *client_data)
{
  Image         this = (Image) image;
  ClientStruct  cs, *cs_ptr;
  int           i, num_cs;

  /*printf("ZnGetImageByValue: %s\n", ZnNameOfImage(image));*/
  if (!ZnImageIsBitmap(image)) {
    cs_ptr = ZnListArray(this->clients);
    num_cs = ZnListSize(this->clients);
    for (i = 0; i < num_cs; i++, cs_ptr++) {
      if ((cs_ptr->inv_proc == inv_proc) &&
          (cs_ptr->client_data == client_data)) {
        cs_ptr->refcount++;
        return image;
      }
    }
    cs.inv_proc = inv_proc;
    cs.client_data = client_data;
    cs.refcount = 1;
    ZnListAdd(this->clients, &cs, ZnListTail);
  }
  else {
    this->refcount++;
  }

  return image;
}

/*
 **********************************************************************************
 *
 * ZnImageIsBitmap --
 *
 **********************************************************************************
 */
ZnBool
ZnImageIsBitmap(ZnImage image)
{
  return (((Image) image)->bits->bpixels != NULL);
}

/*
 **********************************************************************************
 *
 * ZnFreeImage --
 *
 **********************************************************************************
 */
void
ZnFreeImage(ZnImage     image,
            void        (*inv_proc)(void *cd),
            void        *client_data)
{
  Image         prev, scan, this = ((Image) image);
  ImageBits     *bits = this->bits;
  ClientStruct  *cs_ptr;
  int           i, num_cs, rm_image;

  /*printf("ZnFreeImage: %s\n", ZnNameOfImage(image));*/
  /*
   * Search the instance in the list.
   */
  for (prev=NULL, scan=bits->images; (scan!=NULL)&&(scan!=this);
       prev=scan, scan=scan->next);
  if (scan != this) {
    return; /* Not found ? */
  }

  if (!ZnImageIsBitmap(image)) {
    cs_ptr = ZnListArray(this->clients);
    num_cs = ZnListSize(this->clients);
    for (i = 0; i < num_cs; i++, cs_ptr++) {
      if ((cs_ptr->inv_proc == inv_proc) &&
          (cs_ptr->client_data == client_data)) {
        cs_ptr->refcount--;
        if (cs_ptr->refcount == 0) {
          ZnListDelete(this->clients, i);
        }
        break;
      }
    }
    rm_image = ZnListSize(this->clients)==0;
  }
  else {
    this->refcount--;
    rm_image = this->refcount==0;
  }

  if (!rm_image) {
    return;
  }

  /*
   * Unlink the deleted image instance.
   */
  if (prev == NULL) {
    bits->images = this->next;
  }
  else {
    prev->next = this->next;
  }
  if (this->for_gl) {
#ifdef GL
    if (this->i.texobj) {
      ZnGLContextEntry *ce;
      ce = ZnGLMakeCurrent(this->dpy, 0);
      /*      printf("%d Liberation de la texture %d pour l'image %s\n",
              wi, this->i.texobj, ZnNameOfImage(image));*/
      glDeleteTextures(1, &this->i.texobj);
      this->i.texobj = 0;
      ZnGLReleaseContext(NULL, ce);
    }
#endif
  }
  else if (bits->tkimage) {
    /*
     * This is an image, we need to free the instances.
     */
    if (this->i.pixmap != None) {
      Tk_FreePixmap(this->dpy, this->i.pixmap);
    }
  }
  else {
    /*
     * This is a bitmap ask Tk to free the resource.
     */
    if (this->i.pixmap != None) {
      Tk_FreeBitmap(this->dpy, this->i.pixmap);
    }
  }
  ZnFree(this);

  /*
   * No clients for this image, it can be freed.
   */
  if (bits->images == NULL) {
    /*printf("destruction complète de l'image %s\n", ZnNameOfImage(this));*/
#ifdef GL
    if (bits->t_bits) {
      ZnFree(bits->t_bits);
    }
#endif
    if (bits->bpixels) {
      ZnFree(bits->bpixels);
    }
    if (bits->tkimage) {
      Tk_FreeImage(bits->tkimage);
    }
    if (bits->valid_region) {
      TkDestroyRegion(bits->valid_region);
    }
    Tcl_DeleteHashEntry(bits->hash);
    ZnFree(bits);
  }
}


/*
 **********************************************************************************
 *
 * ZnNameOfImage --
 *
 **********************************************************************************
 */
char *
ZnNameOfImage(ZnImage   image)
{
  return Tcl_GetHashKey(&images, ((Image) image)->bits->hash);
}


/*
 **********************************************************************************
 *
 * ZnSizeOfImage --
 *
 **********************************************************************************
 */
void
ZnSizeOfImage(ZnImage   image,
              int       *width,
              int       *height)
{
  Image         this = (Image) image;

  *width = this->bits->width;
  *height = this->bits->height;
}


/*
 **********************************************************************************
 *
 * ZnImagePixmap --
 *
 **********************************************************************************
 */
Pixmap
ZnImagePixmap(ZnImage   image,
              Tk_Window win)
{
  Image         this = (Image) image;
  ImageBits     *bits = this->bits;

  /*printf("ZnImagePixmap: %s\n", ZnNameOfImage(image));*/
  if (this->for_gl) {
    fprintf(stderr,
            "Bogus use of an image, it was created for GL and used in an X11 context\n");
    return None;
  }
  
  if (this->i.pixmap == None) {
    if (ZnImageIsBitmap(image)) {
      this->i.pixmap = Tk_GetBitmap(bits->interp, win, Tk_GetUid(ZnNameOfImage(image)));
    }
    else {
      Tk_Image tkimage;
      
      /*
       * If the original image was created on the same display
       * as the required display, we can get the pixmap from it.
       * On the other hand we need first to obtain an image
       * instance on the right display.
       */
      if (bits->dpy == this->dpy) {
        tkimage = bits->tkimage;
      }
      else {
        /* Create a temporary tkimage to draw the pixmap. */
        tkimage = Tk_GetImage(bits->interp, win, ZnNameOfImage(image), NULL, NULL);
      }
      
      this->i.pixmap = Tk_GetPixmap(this->dpy, Tk_WindowId(win),
                                    bits->width, bits->height, bits->depth);
      Tk_RedrawImage(tkimage, 0, 0, bits->width, bits->height, this->i.pixmap, 0, 0);
      
      if (tkimage != bits->tkimage) {
        Tk_FreeImage(tkimage);
      }
    }
  }

  return this->i.pixmap;
}


/*
 **********************************************************************************
 *
 * ZnPointInImage --
 *
 *      Return whether the given point is inside the image.
 *
 **********************************************************************************
 */
ZnBool
ZnPointInImage(ZnImage  image,
               int      x,
               int      y)
{
  if (ZnImageIsBitmap(image)) {
    ImageBits *bits = ((Image) image)->bits;
    if ((x < 0) || (y < 0) ||
        (x >= bits->width) || (y >= bits->height)) {
      return False;
    }
    return ZnGetBitmapPixel(bits->bpixels, bits->rowstride, x, y);
  }
  else {
    return ZnPointInRegion(ZnImageRegion(image), x, y);
  }
}


/*
 **********************************************************************************
 *
 * ZnImageRegion --
 *
 *      Only defined for Tk images (including Tk images defined from bitmaps).
 *
 **********************************************************************************
 */
static void
BuildImageRegion(Display        *dpy,
                 ImageBits      *bits)
{
  Pixmap        pmap;
  int           x, y, end;
  GC            gc;
  XImage        *im1, *im2;
  XRectangle    rect;

  /*printf("BuildImageRegion: %s\n", ZnNameOfImage(bits->images));*/
  pmap = Tk_GetPixmap(dpy, DefaultRootWindow(dpy), bits->width, bits->height, bits->depth);
  gc = XCreateGC(dpy, pmap, 0, NULL);
  XSetForeground(dpy, gc, 0);
  XFillRectangle(dpy, pmap, gc, 0, 0, bits->width, bits->height);
  Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
  im1 = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap);
  
  XSetForeground(dpy, gc, 1);
  XFillRectangle(dpy, pmap, gc, 0, 0, bits->width, bits->height);
  Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
  im2 = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap);
  Tk_FreePixmap(dpy, pmap);
  XFreeGC(dpy, gc);

  bits->valid_region = TkCreateRegion();

  for (y = 0; y < bits->height; y++) {
    x = 0;
    while (x < bits->width) {
      while ((x < bits->width) &&
             (XGetPixel(im1, x, y) != XGetPixel(im2, x, y))) {
        /* Search the first non-transparent pixel */
        x++;
      }
      end = x;
      while ((end < bits->width) &&
             (XGetPixel(im1, end, y) == XGetPixel(im2, end, y))) {
        /* Search the first transparent pixel */
        end++;
      }
      if (end > x) {
        rect.x = x;
        rect.y = y;
        rect.width = end - x;
        rect.height = 1;
        TkUnionRectWithRegion(&rect, bits->valid_region, bits->valid_region);
      }
      x = end;
    }
  }
  
  XDestroyImage(im1);
  XDestroyImage(im2);
}

TkRegion
ZnImageRegion(ZnImage   image)
{
  if (ZnImageIsBitmap(image)) {
    return NULL;
  }
  else {
    Image       this = (Image) image;
    ImageBits   *bits = this->bits;
#ifdef PTK
    if (!bits->valid_region) {
      BuildImageRegion(this->dpy, bits);
    }
    return bits->valid_region;
#else
    if (bits->tkphoto) {
      return TkPhotoGetValidRegion(bits->tkphoto);
    }
    else {
      if (!bits->valid_region) {
        BuildImageRegion(this->dpy, bits);
      }
      return bits->valid_region;
    }
#endif
  }
}


Tk_Image
ZnImageTkImage(ZnImage image)
{
  return ((Image) image)->bits->tkimage;
}

Tk_PhotoHandle
ZnImageTkPhoto(ZnImage image)
{
  return ((Image) image)->bits->tkphoto;
}

/*
 **********************************************************************************
 *
 * ZnImageTex --
 *
 **********************************************************************************
 */
#ifdef GL
/*
 * Working only for 16 bits displays with 5r6g5b mask,
 * and 24/32 bits displays. Byte ordering ok on Intel
 * plateform only.
 */
static void
From5r6g5b(unsigned char *data,
           int           width,
           int           height,
           int           bytes_per_line,
           unsigned char *t_bits,
           int           t_width,
           int           t_height,
           TkRegion      valid_region)
{
  int           x, y;
  int           rowstride = t_width * 4;
  unsigned char *obptr;
  unsigned char *bptr, *bp2;
  unsigned char alpha;
  unsigned short temp;

  bptr = t_bits;
  
  for (y = 0; y < height; y++) {
    bp2 = bptr;
    obptr = data;
    for (x = 0; x < width; x++) {
      /*
       * Configure the alpha value.
       */
      alpha = ZnPointInRegion(valid_region, x, y) ? 255 : 0;

      /*
       * Dispatch the 3 color components.
       */
      temp = ((unsigned short *)obptr)[0];
      *bp2 = (temp >> 8) & 0xf8; /* r */
      bp2++;
      *bp2 = (temp >> 3) & 0xfc; /* v */
      bp2++;
      *bp2 = (temp << 3);        /* b */
      bp2++;
      *bp2 = alpha;
      bp2++;
      obptr += 2;
    }
    for (x = width; x < t_width; x++) {
      *bp2 = 0;
      bp2++;
      *bp2 = 0;
      bp2++;
      *bp2 = 0;
      bp2++;
      *bp2 = 0;
      bp2++;
    }
    bptr += rowstride;
    data += bytes_per_line;
  }
  for (y = height; y < t_height; y++) {
    memset(bptr, 0, rowstride);
    bptr += rowstride;
  }
}

static void
From8r8g8b(unsigned char *data,
           int           width,
           int           height,
           int           bytes_per_line,
           unsigned char *t_bits,
           int           t_width,
           int           t_height,
           TkRegion      valid_region)
{
  int           x, y;
  int           rowstride = t_width * 4;
  unsigned char *obptr;
  unsigned char *bptr, *bp2;
  unsigned char alpha;

  bptr = t_bits;
  
  for (y = 0; y < height; y++) {
    bp2 = bptr;
    obptr = data;
    for (x = 0; x < width; x++) {
      /*
       * Configure the alpha value.
       */
      alpha = ZnPointInRegion(valid_region, x, y) ? 255 : 0;

      /*
       * Dispatch the 3 color components.
       * Be careful the Red and Blue are swapped it works on an Intel
       * plateform but may need some more tests to be fully generic.
       */
      *bp2++ = obptr[2]; /* r */
      *bp2++ = obptr[1]; /* v */
      *bp2++ = obptr[0]; /* b */
      obptr += 4;
      *bp2++ = alpha;
    }
    for (x = width; x < t_width; x++) {
      *bp2 = 0;
      bp2++;
      *bp2 = 0;
      bp2++;
      *bp2 = 0;
      bp2++;
      *bp2 = 0;
      bp2++;
    }
    bptr += rowstride;
    data += bytes_per_line;
  }
  for (y = height; y < t_height; y++) {
    memset(bptr, 0, rowstride);
    bptr += rowstride;
  }
}

static void
GatherImageTexels(Display       *dpy,
                  ImageBits     *bits)
{
  Pixmap        pmap;
  XImage        *im;
  TkRegion      valid_region;
  int           t_size;

  /*printf("GatherImageTexels: %s\n", ZnNameOfImage(bits->images));*/
  valid_region = ZnImageRegion(bits->images);

  t_size = bits->t_width * 4 * bits->t_height;
  bits->t_bits = ZnMalloc(t_size);  

  pmap = Tk_GetPixmap(dpy, DefaultRootWindow(dpy),
                      bits->width, bits->height, bits->depth);
  Tk_RedrawImage(bits->tkimage, 0, 0, bits->width, bits->height, pmap, 0, 0);
  im = XGetImage(dpy, pmap, 0, 0, bits->width, bits->height, ~0L, ZPixmap);
  Tk_FreePixmap(dpy, pmap);

  if (bits->depth == 16) {
    From5r6g5b((unsigned char *) im->data, bits->width, bits->height,
               im->bytes_per_line,
               bits->t_bits, bits->t_width, bits->t_height, valid_region);
  }
  else if ((bits->depth == 24) || (bits->depth == 32)) {
    From8r8g8b((unsigned char *) im->data, bits->width, bits->height,
               im->bytes_per_line,
               bits->t_bits, bits->t_width, bits->t_height, valid_region);
  }

  XDestroyImage(im);
}

GLuint
ZnImageTex(ZnImage      image,
           ZnReal       *t,
           ZnReal       *s)
{
  Image         this = (Image) image;
  ImageBits     *bits = this->bits;
  ZnBool        is_bmap = ZnImageIsBitmap(image);
  unsigned int  t_size, width, height;

  if (!this->for_gl) {
    fprintf(stderr, "Bogus use of an image, it was created for X11 and used in a GL context\n");
    return 0;
  }
  ZnSizeOfImage(image, (int *) &width, (int *) &height);
  if (!bits->t_bits) {
    /*printf("chargement texture pour image %s\n", ZnNameOfImage(this));*/
    bits->t_width = To2Power((int) width);
    bits->t_height = To2Power((int) height);
    bits->s = width / (ZnReal) bits->t_width;
    bits->t = height / (ZnReal) bits->t_height;

    /*
     * This is a bitmap: use the pixels stored in bpixels.
     */
    if (is_bmap) {
      unsigned int  i, j;
      unsigned char *ostart, *dstart, *d, *o;

      t_size = bits->t_width * bits->t_height;
      bits->t_bits = ZnMalloc(t_size);
      memset(bits->t_bits, 0, t_size);
      ostart = bits->bpixels;
      dstart = bits->t_bits;
      for (i = 0; i < height; i++) {
        d = dstart;
        o = ostart;
        for (j = 0; j < width; j++) {
          *d++ = ZnGetBitmapPixel(bits->bpixels, bits->rowstride, j, i) ? 255 : 0;
        }
        ostart += bits->rowstride;
        dstart += bits->t_width;
      }
    }

    /*
     * This is a photo: use the photo API, it is simple.
     */
    else if (bits->tkphoto) {
      unsigned int       x, y, t_stride;
      unsigned char      *obptr, *bptr, *bp2, *pixels;
      int                green_off, blue_off, alpha_off;
      Tk_PhotoImageBlock block;

      t_stride = bits->t_width * 4;
      t_size = t_stride * bits->t_height;
      /*printf("t_width: %d(%d), t_height: %d(%d)\n", bits->t_width, width, bits->t_height, height);*/
      bits->t_bits = ZnMalloc(t_size);
      Tk_PhotoGetImage(bits->tkphoto, &block);
      green_off = block.offset[1] - block.offset[0];
      blue_off = block.offset[2] - block.offset[0];
#ifdef PTK
      alpha_off = 3;
#else
      alpha_off = block.offset[3] - block.offset[0];
#endif
      /*printf("width %d, height: %d redoff: %d, greenoff: %d, blueoff: %d, alphaoff: %d\n",
             block.width, block.height, block.offset[0], green_off,
             blue_off, alpha_off);*/
      pixels = block.pixelPtr;
      bptr = bits->t_bits;
  
      for (y = 0; y < height; y++) {
        bp2 = bptr;
        obptr = pixels;
        for (x = 0; x < width; x++) {
          *bp2++ = obptr[0];         /* r */
          *bp2++ = obptr[green_off]; /* g */
          *bp2++ = obptr[blue_off];  /* b */
          *bp2++ = obptr[alpha_off]; /* alpha */
          obptr += block.pixelSize;
        }
        /*for (x = width; x < t_width; x++) {
          *bp2 = 0; bp2++;
          *bp2 = 0; bp2++;
          *bp2 = 0; bp2++;
          *bp2 = 0; bp2++;
          }*/
        bptr += t_stride;
        pixels += block.pitch;
      }
      /*for (y = height; y < t_height; y++) {
        memset(bptr, 0, t_stride);
        bptr += t_stride;
        }*/
    }

    /*
     * This is another image format (not a photo): try to
     * guess the pixels and the transparency (on or off)
     * from a locally drawn pixmap.
     */
    else {
      GatherImageTexels(bits->dpy, bits);
    }
  }

  if (!this->i.texobj) {
    glGenTextures(1, &this->i.texobj);
    /*printf("%d creation texture %d pour image %s\n",
      bits, this->i.texobj, ZnNameOfImage(this));*/
    glBindTexture(GL_TEXTURE_2D, this->i.texobj);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glGetError();
    if (is_bmap) {
      glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY4,
                   this->bits->t_width, this->bits->t_height,
                   0, GL_LUMINANCE, GL_UNSIGNED_BYTE, this->bits->t_bits);
    }
    else {
      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                   this->bits->t_width, this->bits->t_height,
                   0, GL_RGBA, GL_UNSIGNED_BYTE, this->bits->t_bits);
    }
    if (glGetError() != GL_NO_ERROR) {
      ZnWarning("Can't allocate the texture for image ");
      ZnWarning(ZnNameOfImage(image));
     ZnWarning("\n");
    }
    glBindTexture(GL_TEXTURE_2D, 0);
  }

  *t = this->bits->t;
  *s = this->bits->s;
  return this->i.texobj;
}
#endif


#ifdef GL

#define MAX_GLYPHS_PER_GRAB 256

typedef struct _TexFontInfo {
  struct _TexFont *txf;
  GLuint        texobj;
  Display       *dpy;
  unsigned int  refcount;
  struct _TexFontInfo *next;
} TexFontInfo;

typedef struct {
  short         width;
} PerGlyphInfo, *PerGlyphInfoPtr;

typedef struct _TexFont {
  TexFontInfo   *tfi;
  Tk_Font       tkfont;
  unsigned int  tex_width;
  unsigned int  tex_height;
  int           ascent;
  int           descent;
  unsigned int  max_char_width;
  unsigned char *teximage;
  unsigned int  num_glyphs;
  PerGlyphInfo  *glyph;
  ZnTexGVI      *tgvi;
  Tcl_HashEntry *hash;
} TexFont;

typedef struct _DeferredGLGlyphs {
  ZnWInfo       *wi;
  TexFont       *txf;
} DeferredGLGlyphsStruct;

ZnList DeferredGLGlyphs;


#ifndef PTK_800
#include "CharsetUTF8.h"
#else
#include "CharsetISO8859-15.h"
#endif

#ifndef PTK_800
#define AA_FONTS 1
#endif

static void
SuckGlyphsFromServer(ZnWInfo    *wi,
                     TexFont    *txf)
{
  Pixmap        offscreen = 0;
  XImage        *image = NULL;
#ifdef AA_FONTS
  XColor        *white, *black;
  unsigned long pixel;
#endif
  GC            xgc = 0;
  unsigned int  height, length, pixwidth;
  unsigned int  i, j, use_max_width;
  unsigned int  wgap=2, hgap=2, tex_width, tex_height;
  unsigned char *to;
  unsigned int  x, y;
  unsigned int  width=0, maxSpanLength;
  int           grabList[MAX_GLYPHS_PER_GRAB];
  unsigned int  glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
  unsigned int  numToGrab, glyph;
  ZnTexGVI      *tgvip;
  Tk_FontMetrics fm;
  CONST unsigned char   *cur, *next;
#ifndef PTK_800
  Tcl_UniChar   uni_ch;
#endif
#ifdef PLATFORM_SDL
  ZnGLContextEntry *ce = wi->ce;
#else
  ZnGLContextEntry *ce = ZnGetGLContext(wi->dpy);
#endif

  //printf("loading a font \n");
  Tk_GetFontMetrics(txf->tkfont, &fm);
#ifndef PTK_800
  txf->num_glyphs = Tcl_NumUtfChars((char *) ZnDefaultCharset,
                                    strlen(ZnDefaultCharset));
#else
  txf->num_glyphs = strlen(ZnDefaultCharset);
#endif
  txf->glyph = ZnMalloc(txf->num_glyphs * sizeof(PerGlyphInfo));
  if (!txf->glyph) {
    goto FreeAndReturn;
  }
  txf->tgvi = ZnMalloc(txf->num_glyphs * sizeof(ZnTexGVI));
  if (!txf->tgvi) {
    goto FreeAndReturn;
  }
  
  txf->ascent = fm.ascent;
  txf->descent = fm.descent;
  txf->max_char_width = 0;
  tex_width = tex_height = 0;
  use_max_width = 0;
  height = txf->ascent + txf->descent;
  tgvip = txf->tgvi;

  /*
   * Compute the max character size in the font. This may be
   * a bit heavy hammer style but it avoid guessing on characters
   * not available in the font.
   */
  cur = ZnDefaultCharset;
  i = 0;
  while (*cur) {
#ifndef PTK_800
    next = Tcl_UtfNext((char *) cur);
#else
    next = cur + 1;
#endif
    Tk_MeasureChars(txf->tkfont, (char *) cur, next - cur, 0,
                    TK_AT_LEAST_ONE, (int *) &length);
    txf->glyph[i].width = length;
    txf->max_char_width = MAX(txf->max_char_width, length);
    
    if (tex_width + length + wgap > ce->max_tex_size) {
      tex_width = 0;
      use_max_width = 1;
      tex_height += height + hgap;
      if ((tex_height > ce->max_tex_size) || (length > ce->max_tex_size)) {
        goto FreeAndReturn;
      }
    }

    tgvip->v0x = 0;
    tgvip->v0y = txf->descent - height;
    tgvip->v1x = length;
    tgvip->v1y = txf->descent;
    tgvip->t0x = (GLfloat) tex_width;
    tgvip->t0y = (GLfloat) tex_height;
    tgvip->t1x = tgvip->t0x + length;
    tgvip->t1y = tgvip->t0y + height;
    tgvip->advance = (GLfloat) length;
#ifndef PTK_800
    Tcl_UtfToUniChar((char *) cur, &uni_ch);
    tgvip->code = uni_ch;
#else
    tgvip->code = *cur;
#endif 
    tex_width += length + wgap;

    cur = next;
    i++;
    tgvip++;
  }

  //
  // If max_char_width is still not known, perhaps because of a bogus
  // font with character width not documented, set the width to an
  // arbitrary value.
  if (!txf->max_char_width) {
    txf->max_char_width = 1;
  }

  if (use_max_width) {
    tex_width = ce->max_tex_size;
  }
  tex_height += height;

  /*
   * Round the texture size to the next power of two.
   */
  tex_height = To2Power(tex_height);
  tex_width = To2Power(tex_width);
  if ((tex_height > ce->max_tex_size) || (tex_width > ce->max_tex_size)) {
    fprintf(stderr, "Font doesn't fit into a texture\n");
    goto FreeAndReturn;
  } 
  txf->tex_width = tex_width;
  txf->tex_height = tex_height;
  //printf("(%s) Texture size is %d x %d for %d chars (max size: %d)\n",
   // Tk_NameOfFont(txf->tkfont), txf->tex_width, txf->tex_height, txf->num_glyphs, ce->max_tex_size);

  /*
   * Now render the font bits into the texture.
   */
  txf->teximage = ZnMalloc(tex_height * tex_width);
  if (!txf->teximage) {
    goto FreeAndReturn;
  }
#ifndef AA_FONTS
  memset(txf->teximage, 0, tex_height * tex_width);
#endif

  maxSpanLength = (txf->max_char_width + 7) / 8;
  /* Be careful determining the width of the pixmap; the X protocol allows
     pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates
     max out at 2^15-1 (signed short size). Some problems have been encountered
     with XFree86, it is safe to limit the width to 4096. */
  if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 12)) {
    glyphsPerGrab = (1 << 12) / (8 * maxSpanLength);
  }
  pixwidth = glyphsPerGrab * 8 * maxSpanLength;
#ifdef AA_FONTS
  offscreen = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
                           (int) pixwidth, (int) height, Tk_Depth(wi->win));
#else
  offscreen = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
                           (int) pixwidth, (int) height, 1);
#endif
  xgc = XCreateGC(wi->dpy, offscreen, 0, NULL);
#ifdef AA_FONTS
  white = Tk_GetColor(wi->interp, wi->win, "white");
  black = Tk_GetColor(wi->interp, wi->win, "black");
  XSetForeground(wi->dpy, xgc, white->pixel);
  XSetBackground(wi->dpy, xgc, white->pixel);
#else
  XSetForeground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
  XSetBackground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
#endif
  XFillRectangle(wi->dpy, offscreen, xgc, 0, 0, pixwidth, height);
#ifdef AA_FONTS
  XSetForeground(wi->dpy, xgc, black->pixel);
#else
  XSetForeground(wi->dpy, xgc, BlackPixelOfScreen(wi->screen));
#endif
  XSetFont(wi->dpy, xgc, Tk_FontId(txf->tkfont));

  numToGrab = 0;
  cur = ZnDefaultCharset;
  i = 0;

  while (*cur) {
#ifndef PTK_800
    next = Tcl_UtfNext((char *) cur);
#else
    next = cur + 1;
#endif
    if (txf->glyph[i].width != 0) {
      Tk_DrawChars(wi->dpy, offscreen, xgc, txf->tkfont, (char *) cur,
                   next - cur,  (int) (8*maxSpanLength*numToGrab), txf->ascent);
      grabList[numToGrab] = i;
      numToGrab++;
    }

    if ((numToGrab >= glyphsPerGrab) || (i == txf->num_glyphs - 1)) {
#ifdef AA_FONTS
      image = XGetImage(wi->dpy, offscreen, 0, 0, pixwidth, height, AllPlanes, ZPixmap);
#else
      image = XGetImage(wi->dpy, offscreen, 0, 0, pixwidth, height, 1, XYPixmap);
#endif
      for (j = 0; j < numToGrab; j++) {
        glyph = grabList[j];
        width = txf->glyph[glyph].width;
        tgvip = &txf->tgvi[glyph];
        to = txf->teximage + (int) (tgvip->t0y * tex_width) + (int) tgvip->t0x;
        tgvip->t0x = tgvip->t0x / (GLfloat) tex_width;
        tgvip->t0y = tgvip->t0y / (GLfloat) tex_height;
        tgvip->t1x = tgvip->t1x / (GLfloat) tex_width;
        tgvip->t1y = tgvip->t1y / (GLfloat) tex_height;
        for (y = 0; y < height; y++) {
          for (x = 0; x < width; x++, to++) {
            /* XXX The algorithm used to suck across the font ensures that
               each glyph begins on a byte boundary.  In theory this would
               make it convienent to copy the glyph into a byte oriented
               bitmap.  We actually use the XGetPixel function to extract
               each pixel from the image which is not that efficient.  We
               could either do tighter packing in the pixmap or more
               efficient extraction from the image.  Oh well.  */
#ifdef AA_FONTS
            pixel = XGetPixel(image, (int) (j*maxSpanLength*8) + x, y);
            *to = 255 - (pixel & 0xFF);
#else
            if (XGetPixel(image, (int) (j*maxSpanLength*8) + x, y) == BlackPixelOfScreen(wi->screen)) {
              *to = 255;
            }
#endif
          }
          to += tex_width - width;
        }
      }
      XDestroyImage(image);
      image = NULL;
      numToGrab = 0;
      /* do we need to clear the offscreen pixmap to get more? */
      if (i < txf->num_glyphs - 1) {
#ifdef AA_FONTS
        XSetForeground(wi->dpy, xgc, white->pixel);
#else
        XSetForeground(wi->dpy, xgc, WhitePixelOfScreen(wi->screen));
#endif
        XFillRectangle(wi->dpy, offscreen, xgc, 0, 0,
                       8 * maxSpanLength * glyphsPerGrab, height);
#ifdef AA_FONTS
        XSetForeground(wi->dpy, xgc, black->pixel);
#else
        XSetForeground(wi->dpy, xgc, BlackPixelOfScreen(wi->screen));
#endif
      }
    }
    
    cur = next;
    i++;
  }

#ifdef AA_FONTS
  Tk_FreeColor(black);
  Tk_FreeColor(white);
#endif
  XFreeGC(wi->dpy, xgc);
  Tk_FreePixmap(wi->dpy, offscreen);
  return;

 FreeAndReturn:
  if (txf->glyph) {
    ZnFree(txf->glyph);
    txf->glyph = NULL;
  }
  if (txf->tgvi) {
    ZnFree(txf->tgvi);
    txf->tgvi = NULL;    
  }
  if (txf->teximage) {
    ZnFree(txf->teximage);
    txf->teximage = NULL;    
  }
  ZnWarning("Cannot load font texture for font ");
  ZnWarning(Tk_NameOfFont(txf->tkfont));
  ZnWarning("\n");
}

static void
ZnNeedToGetGLGlyphs(ZnWInfo     *wi,
                    TexFont     *txf)
{
  DeferredGLGlyphsStruct dgg, *dggp;
  int                    i, num;

  if (!DeferredGLGlyphs) {
    DeferredGLGlyphs = ZnListNew(4, sizeof(DeferredGLGlyphsStruct));
  }
  dggp = ZnListArray(DeferredGLGlyphs);
  num = ZnListSize(DeferredGLGlyphs);
  for (i = 0; i < num; i++, dggp++) {
    if (dggp->txf == txf) {
      return;
    }
  }
  
  dgg.wi = wi;
  dgg.txf = txf;
  ZnListAdd(DeferredGLGlyphs, &dgg, ZnListTail);
  /*printf("adding a font to load\n");*/
}

void
ZnGetDeferredGLGlyphs(void)
{
  DeferredGLGlyphsStruct *dggp;
  int                    i, num = ZnListSize(DeferredGLGlyphs);

  if (!num) {
    return;
  }
  dggp = ZnListArray(DeferredGLGlyphs);
  for (i = 0; i < num; i++, dggp++) {
    SuckGlyphsFromServer(dggp->wi, dggp->txf);
  }
  ZnListEmpty(DeferredGLGlyphs);
}

static void
ZnRemovedDeferredGLGlyph(TexFont        *txf)
{
  DeferredGLGlyphsStruct *dggp;
  int                    i, num;

  dggp = ZnListArray(DeferredGLGlyphs);
  num = ZnListSize(DeferredGLGlyphs);
  for (i = 0; i < num; i++, dggp++) {
    if (dggp->txf == txf) {
      ZnListDelete(DeferredGLGlyphs, i);
      return;
    }
  }
}


/*
 **********************************************************************************
 *
 * ZnGetTexFont --
 *
 **********************************************************************************
 */
ZnTexFontInfo
ZnGetTexFont(ZnWInfo    *wi,
             Tk_Font    font)
{
  TexFont       *txf;
  TexFontInfo   *tfi;
  static int    inited = 0;
  Tcl_HashEntry *entry;
  int           new;

  if (!inited) {
    Tcl_InitHashTable(&font_textures, TCL_STRING_KEYS);
    inited = 1;
  }

  /*  printf("family: %s, size: %d, weight: %d, slant: %d, underline: %d, overstrike: %d\n",
         tft->fa.family, tft->fa.size, tft->fa.weight, tft->fa.slant, tft->fa.underline,
         tft->fa.overstrike);
  */
  entry = Tcl_FindHashEntry(&font_textures, Tk_NameOfFont(font));
  if (entry != NULL) {
    /*printf("Found an already created font %s\n", Tk_NameOfFont(font));*/
    txf = (TexFont *) Tcl_GetHashValue(entry);
  }
  else {
    /*printf("Creating a new texture font for %s\n", Tk_NameOfFont(font));*/
    txf = ZnMalloc(sizeof(TexFont));
    if (txf == NULL) {
      return NULL;
    }
    txf->tfi = NULL;
    txf->tgvi = NULL;
    txf->glyph = NULL;
    txf->teximage = NULL;

    /* Get a local reference to the font, it will be deallocated
     * when no further references on this TexFont exist. */
    txf->tkfont = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(font));

    /*printf("Scheduling glyph loading for font %s\n", ZnNameOfTexFont(tfi));*/
    ZnNeedToGetGLGlyphs(wi, txf);

    entry = Tcl_CreateHashEntry(&font_textures, Tk_NameOfFont(font), &new);
    Tcl_SetHashValue(entry, (ClientData) txf);
    txf->hash = entry;
  }
 
  /*
   * Now locate the texture obj in the texture list for this widget.
   */
  for (tfi = txf->tfi; tfi != NULL; tfi = tfi->next) {
    if (tfi->dpy == wi->dpy) {
      tfi->refcount++;
      return tfi;
    }
  }
  /*
   * Not found allocate a new texture object.
   */
  tfi = ZnMalloc(sizeof(TexFontInfo));
  if (tfi == NULL) {
    return NULL;
  }
  tfi->refcount = 1;
  tfi->dpy = wi->dpy;
  tfi->txf = txf;
  tfi->texobj = 0;
  tfi->next = txf->tfi;
  txf->tfi = tfi;

  return tfi;
}


/*
 **********************************************************************************
 *
 * ZnNameOfTexFont --
 *
 **********************************************************************************
 */
char const *
ZnNameOfTexFont(ZnTexFontInfo   tfi)
{
  return Tk_NameOfFont(((TexFontInfo *) tfi)->txf->tkfont);
}

/*
 **********************************************************************************
 *
 * ZnTexFontTex --
 *
 **********************************************************************************
 */
GLuint
ZnTexFontTex(ZnTexFontInfo      tfi)
{
  TexFontInfo   *this = (TexFontInfo *) tfi;
  TexFont       *txf = this->txf;

  if (!txf->teximage) {
    return 0;
  }
  if (!this->texobj) {
    glGenTextures(1, &this->texobj);
    /*printf("%d creation texture %d pour la fonte %s\n",
      this->dpy, this->texobj, ZnNameOfTexFont(tfi));*/
    glBindTexture(GL_TEXTURE_2D, this->texobj);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glGetError();
    //printf("Demande texture de %d x %d pour %s\n",
      //     txf->tex_width, txf->tex_height, ZnNameOfTexFont(tfi));
    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, txf->tex_width,
                 txf->tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE,
                 txf->teximage);
    if (glGetError() != GL_NO_ERROR) {
      ZnWarning("Can't allocate the texture for font ");
      ZnWarning(ZnNameOfTexFont(tfi));
      ZnWarning("\n");
    }
    glBindTexture(GL_TEXTURE_2D, 0);
  }

  /*printf("%d utilisation de la texture %d\n", this->wi, this->texobj);*/
  return this->texobj;
}


/*
 **********************************************************************************
 *
 * ZnFreeTexFont --
 *
 **********************************************************************************
 */
void
ZnFreeTexFont(ZnTexFontInfo     tfi)
{
  TexFontInfo   *this = ((TexFontInfo *) tfi);
  TexFont       *txf = this->txf;
  TexFontInfo   *prev, *scan;

  for (prev=NULL, scan=this->txf->tfi; (scan!=NULL)&&(scan != this);
       prev=scan, scan=scan->next);
  if (scan != this) {
    return;
  }

  /*
   * Decrement tex font object refcount.
   */
  this->refcount--;
  if (this->refcount != 0) {
    return;
  }

  /*
   * Unlink the deleted tex font info.
   */
  if (prev == NULL) {
    txf->tfi = this->next;
  }
  else {
    prev->next = this->next;
  }
  if (this->texobj) {
    ZnGLContextEntry *ce;
    /*printf("%d Freeing texture %d from font %s\n",
      this->dpy, this->texobj, ZnNameOfTexFont(tfi));*/
    ce = ZnGLMakeCurrent(this->dpy, 0);
    if (ce) {
      glDeleteTextures(1, &this->texobj);
      ZnGLReleaseContext(NULL, ce);
    }
  }
  /*
   * Remove the font from the deferred load list
   */
  ZnRemovedDeferredGLGlyph(txf);

  /*
   * There is no more client for this font
   * deallocate the structures.
   */
  if (txf->tfi == NULL) {
    /*printf("%d Freeing txf for %s\n", this, ZnNameOfTexFont(tfi));*/
    Tk_FreeFont(txf->tkfont);
    ZnFree(txf->glyph);
    ZnFree(txf->tgvi);
    ZnFree(txf->teximage);
    Tcl_DeleteHashEntry(txf->hash);
    ZnFree(txf);
  }

  ZnFree(this);
}


/*
 **********************************************************************************
 *
 * ZnGetFontIndex --
 *
 **********************************************************************************
 */
int
ZnGetFontIndex(ZnTexFontInfo    tfi,
               int              c)
{
  TexFont       *txf;
  ZnTexGVI      *tgvi;
  int           code, min, max, mid;

  if (c < 127) {
    /*
     * It is possible to index the points below 127. Unicode
     * is the same as ascii down there.
     */
    return c - 32;
  }

  /*
   * Else, search by dichotomy in the remaining chars.
   */
  txf = ((TexFontInfo *) tfi)->txf;
  tgvi = txf->tgvi;
  if (!tgvi) {
    return -1;
  }
  min = 127 - 32;
  max = txf->num_glyphs;
  while (min < max) {
    mid = (min + max) >> 1;
    code = tgvi[mid].code;
    if (c == code) {
      return mid;
    }
    if (c < code) {
      max = mid;
    }
    else {
      min = mid + 1;
    }
  }
  //fprintf(stderr, "Tried to access unavailable texture font character %d (Unicode)\n", c);
  return -1;
}

/*
 **********************************************************************************
 *
 * ZnTexFontGVI --
 *
 **********************************************************************************
 */
ZnTexGVI *
ZnTexFontGVI(ZnTexFontInfo      tfi,
             int                c)
{
  TexFont       *txf = ((TexFontInfo *) tfi)->txf;
  ZnTexGVI      *tgvi = NULL;
  int           index;

  index = ZnGetFontIndex(tfi, c);
  if (index >= 0) {
    tgvi = &txf->tgvi[index];
  }

  return tgvi;
}

#endif

Added jni/tkzinc/generic/Image.h.



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
 * Image.h -- Image support routines.
 *
 * Authors              : Patrick LECOANET
 * Creation date        : Wed Dec  8 11:04:44 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1999 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Image_h
#define _Image_h

#include "Types.h"

struct _ZnWInfo;


typedef void    *ZnImage;

#define ZnGetBitmapPixel(bits, stride, x, y)\
  (((bits)[(y)*(stride)+((x)>>3)]<<((x)&7))&0x80)

int To2Power(int a);
ZnImage ZnGetImage(struct _ZnWInfo *wi, Tk_Uid image_name,
                   void (*inv_proc)(void *cd), void *cd);
ZnImage ZnGetImageByValue(ZnImage image, void (*inv_proc)(void *cd), void *cd);
void ZnFreeImage(ZnImage image, void (*inv_proc)(void *cd), void *cd);
char * ZnNameOfImage(ZnImage image);
void ZnSizeOfImage(ZnImage image, int *width, int *height);
Pixmap ZnImagePixmap(ZnImage image, Tk_Window win);
ZnBool ZnImageIsBitmap(ZnImage image);
TkRegion ZnImageRegion(ZnImage image);
Tk_Image ZnImageTkImage(ZnImage image);
Tk_PhotoHandle ZnImageTkPhoto(ZnImage image);
ZnBool
ZnPointInImage(ZnImage image, int x, int y);
#ifdef GL
GLuint ZnImageTex(ZnImage image, ZnReal *t, ZnReal *s);

typedef struct _ZnTexGlyphVertexInfo {
  GLfloat       t0x;
  GLfloat       t0y;
  GLshort       v0x;
  GLshort       v0y;
  GLfloat       t1x;
  GLfloat       t1y;
  GLshort       v1x;
  GLshort       v1y;
  GLfloat       advance;
  int           code;
} ZnTexGVI;


typedef void    *ZnTexFontInfo;

ZnTexFontInfo ZnGetTexFont(struct _ZnWInfo *wi, Tk_Font font);
void ZnFreeTexFont(ZnTexFontInfo tfi);
ZnTexGVI *ZnTexFontGVI(ZnTexFontInfo tfi, int c);
int ZnGetFontIndex(ZnTexFontInfo tfi, int c);
GLuint ZnTexFontTex(ZnTexFontInfo tfi);
void ZnGetDeferredGLGlyphs(void);
#endif

#endif  /* _Image_h */

Added jni/tkzinc/generic/Item.c.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
/*
 * Item.c -- Implementation of items.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : 
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Types.h"
#include "Field.h"
#include "Item.h"
#include "Group.h"
#include "WidgetInfo.h"
#include "Geo.h"
#include "Draw.h"
#include "MapInfo.h"
#include "Image.h"
#include "Color.h"
#include "tkZinc.h"
#ifdef ATC
#include "OverlapMan.h"
#endif

#if defined(MAC_OSX_TK)
  #include <AGL/glu.h>
#elif defined(__APPLE__)
  #include <OpenGL/glu.h>
#else
  #include <GL/glu.h>
#endif
#include <limits.h>             /* For INT_MAX */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


static  ZnList  item_classes = NULL;
static  ZnList  item_stack = NULL;


/*
 * This array must be kept in sync with the
 * corresponding defines in Item.h.
 */
static char *attribute_type_strings[] = {
  "",
  "boolean",
  "bitmap",
  "bitmaplist",
  "string",
  "font",
  "edgelist",
  "relief",
  "dimension",
  "priority",
  "alignment",
  "autoalignment",
  "lineend",
  "labelformat",
  "linestyle",
  "lineshape",
  "item",
  "angle",
  "integer",
  "unsignedint",
  "point",
  "anchor",
  "taglist",
  "mapinfo",
  "image",
  "leaderanchors",
  "joinstyle",
  "capstyle",
  "gradient",
  "gradientlist",
  "window",
  "alpha",
  "fillrule",
  "short",
  "unsignedshort"
  "char"
  "unsignedchar"
};


#ifndef PTK
static int SetAttrFromAny _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *obj));

/*
 * The structure below defines an object type that is used to cache the
 * result of looking up an attribute name.  If an object has this type, then
 * its internalPtr1 field points to the attr_desc table in which it was looked up,
 * and the internalPtr2 field points to the entry that matched.
 */

Tcl_ObjType ZnAttrObjType = {
    "attribute",                        /* name */
    (Tcl_FreeInternalRepProc *) NULL,   /* freeIntRepProc */
    (Tcl_DupInternalRepProc *) NULL,    /* dupIntRepProc */
    (Tcl_UpdateStringProc *) NULL,      /* updateStringProc */
    SetAttrFromAny                      /* setFromAnyProc */
};
#endif


/*
 **********************************************************************************
 *
 * Forward functions
 * 
 **********************************************************************************
 */
static void Invalidate(ZnItem item, int reason);
static Tcl_Obj *AttributeToObj(Tcl_Interp *interp, void *record, ZnAttrConfig *desc);



/*
 **********************************************************************************
 *
 * ZnUpdateItemImage --
 *
 **********************************************************************************
 */
void
ZnUpdateItemImage(void *client_data)
{
  ZnItem item = (ZnItem) client_data;

  /*printf("Invalidation of item %ld\n", item->id);*/
  Invalidate(item, ZN_CLFC_FLAG | ZN_COORDS_FLAG);  
}


/*
 **********************************************************************************
 *
 * InitAttrDesc --
 *
 **********************************************************************************
 */
static void
InitAttrDesc(ZnAttrConfig       *attr_desc)
{
  if (!attr_desc) {
    return;
  }

  while (attr_desc->type != ZN_CONFIG_END) {
    attr_desc->uid = Tk_GetUid(attr_desc->name);
    attr_desc++;
  }
}

/*
 *----------------------------------------------------------------------
 *
 * SetAttrFromAny --
 *
 *      This procedure is called to convert a Tcl object to an attribute
 *      descriptor. This is only possible if given a attr_desc table, so
 *      this method always returns an error.
 *
 *----------------------------------------------------------------------
 */
#ifndef PTK
static int
SetAttrFromAny(Tcl_Interp       *interp,
               Tcl_Obj          *obj)
{
  Tcl_AppendToObj(Tcl_GetObjResult(interp),
                  "can't convert value to attribute except via GetAttrDesc",
                  -1);
  return TCL_ERROR;
}
#endif


/*
 **********************************************************************************
 *
 * GetAttrDesc --
 *
 **********************************************************************************
 */
static ZnAttrConfig *
GetAttrDesc(Tcl_Interp          *interp,
            Tcl_Obj             *arg,
            ZnAttrConfig        *desc_table)
{
  Tk_Uid        attr_uid;
  ZnAttrConfig  *desc;

#ifndef PTK
  if (arg->typePtr == &ZnAttrObjType) {
    if (arg->internalRep.twoPtrValue.ptr1 == (void *) desc_table) {
      return (ZnAttrConfig *) arg->internalRep.twoPtrValue.ptr2;
    }
  }
#endif

  /*
   * Answer not cached, look it up.
   */
  attr_uid = Tk_GetUid(Tcl_GetString(arg));
  desc = desc_table;

  while (True) {
    if (desc->type == ZN_CONFIG_END) {
      Tcl_AppendResult(interp, "unknown attribute \"", attr_uid, "\"", NULL);
      return NULL;
    }
    else if (attr_uid == desc->uid) {
#ifndef PTK
      if ((arg->typePtr != NULL) && (arg->typePtr->freeIntRepProc != NULL)) {
        arg->typePtr->freeIntRepProc(arg);
      }
      arg->internalRep.twoPtrValue.ptr1 = (void *) desc_table;
      arg->internalRep.twoPtrValue.ptr2 = (void *) desc;
      arg->typePtr = &ZnAttrObjType;
#endif
      return desc;
    }
    else {
      desc++;
    }
  }
}


/*
 **********************************************************************************
 *
 * AttributesInfo --
 *
 **********************************************************************************
 */
int
ZnAttributesInfo(Tcl_Interp     *interp,
                 void           *record,
                 ZnAttrConfig   *desc_table,
                 int            argc,
                 Tcl_Obj *CONST args[])
{
  Tcl_Obj       *l, *entries[5];
  
  if (argc == 1) {
    ZnAttrConfig *desc = GetAttrDesc(interp, args[0], desc_table);
    if (!desc) {
      return TCL_ERROR;
    }
    entries[0] = Tcl_NewStringObj(desc->name, -1);
    entries[1] = Tcl_NewStringObj(attribute_type_strings[desc->type], -1);
    entries[2] = Tcl_NewBooleanObj(desc->read_only ? 1 : 0);
    entries[3] = Tcl_NewStringObj("", -1);
    entries[4] = AttributeToObj(interp, record, desc);
    l = Tcl_NewListObj(5, entries);
    Tcl_SetObjResult(interp, l);
  }
  else {
    l = Tcl_NewObj();
    while (desc_table->type != ZN_CONFIG_END) {
      entries[0] = Tcl_NewStringObj(desc_table->name, -1);
      entries[1] = Tcl_NewStringObj(attribute_type_strings[desc_table->type], -1);
      entries[2] = Tcl_NewBooleanObj(desc_table->read_only ? 1 : 0);
      entries[3] = Tcl_NewStringObj("", -1);
      entries[4] = AttributeToObj(interp, record, desc_table);
      Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(5, entries));
      desc_table++;
    }
    Tcl_SetObjResult(interp, l);
  }
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ZnConfigureAttributes --
 *
 **********************************************************************************
 */
int
ZnConfigureAttributes(ZnWInfo           *wi,
                      ZnItem            item,
                      void              *record,
                      ZnAttrConfig      *desc_table,
                      int               argc,
                      Tcl_Obj *CONST    args[],
                      int               *flags)
{
  int           i;
  ZnAttrConfig  *desc;
  ZnPtr         valp;
  char          *str;
  
  for (i = 0; i < argc; i += 2) {
    desc = GetAttrDesc(wi->interp, args[i], desc_table);
    if (!desc) {
      return TCL_ERROR;
    }
    else if (desc->read_only) {
      Tcl_AppendResult(wi->interp, "attribute \"",
                       Tcl_GetString(args[i]), "\" can only be read", NULL);
      return TCL_ERROR;
    }

    valp = ((char *) record) + desc->offset;
    /*printf("record <0x%X>, valp <0x%X>, offset %d\n", record, valp, desc->offset);*/
    switch (desc->type) {
    case ZN_CONFIG_GRADIENT:
      {
        ZnGradient *g;
        Tk_Uid new_name = Tk_GetUid(Tcl_GetString(args[i+1]));
        char   *name = NULL;
        if (*((ZnGradient **) valp)) {
          name = ZnNameOfGradient(*((ZnGradient **) valp));
        }
        if (name != new_name) {
          g = ZnGetGradient(wi->interp, wi->win, new_name);
          if (!g) {
            Tcl_AppendResult(wi->interp,
                             " gradient expected for attribute \"",
                             Tcl_GetString(args[i]), "\"", NULL);
            return TCL_ERROR;
          }
          if (*((ZnGradient **) valp)) {
            ZnFreeGradient(*((ZnGradient **) valp));
          }
          *((ZnGradient **) valp) = g;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_GRADIENT_LIST:
      {
        ZnList   new_grad_list = NULL;
        ZnGradient       **grads;
        unsigned int num_grads, j, k;
        Tcl_Obj  **elems;
            
        if (Tcl_ListObjGetElements(wi->interp, args[i+1],
                                   (int *) &num_grads, &elems) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp,
                           " gradient list expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (num_grads) {
          new_grad_list = ZnListNew(num_grads, sizeof(ZnGradient *));
          ZnListAssertSize(new_grad_list, num_grads);
          grads = ZnListArray(new_grad_list);
          for (j = 0; j < num_grads; j++) {
            str = Tcl_GetString(elems[j]);
            if (!*str) {
              if (j == 0) {
                goto grads_err;
              }
              grads[j] = grads[j-1];
            }
            else {
              grads[j] = ZnGetGradient(wi->interp, wi->win, str);
            }
            if (!grads[j]) {
            grads_err:
              Tcl_AppendResult(wi->interp, " invalid gradient \"", str,
                               "\" in gradient list", NULL);
              for (k = 0; k < j; k++) {
                ZnFreeGradient(grads[k]);
              }
              ZnListFree(new_grad_list);
              return TCL_ERROR;
            }
          }
        }
        if (*((ZnList *) valp)) {
          num_grads = ZnListSize(*((ZnList *) valp));
          grads = ZnListArray(*((ZnList *) valp));
          for (j = 0; j < num_grads; j++) {
            if (grads[j]) {
              ZnFreeGradient(grads[j]);
            }
          }
          ZnListFree(*((ZnList *) valp));
          *((ZnList *) valp) = new_grad_list;
          *flags |= desc->flags;
        }
        else {
          if (new_grad_list) {
            *((ZnList *) valp) = new_grad_list;
            *flags |= desc->flags;
          }
        }
        break;
      }
    case ZN_CONFIG_BOOL:
      {
        int     b;
        if (Tcl_GetBooleanFromObj(wi->interp, args[i+1], &b) != TCL_OK) {
          Tcl_AppendResult(wi->interp, " boolean expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (b ^ (ISSET(*((unsigned short *) valp), desc->bool_bit) != 0)) {
          ASSIGN(*((unsigned short *) valp), desc->bool_bit, b);
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_IMAGE:
    case ZN_CONFIG_BITMAP:
      {
        ZnImage image = ZnUnspecifiedImage;
        ZnBool  is_bmap = True;
        char    *name = "";
        
        if (*((ZnImage *) valp) != ZnUnspecifiedImage) {
          name = ZnNameOfImage(*((ZnImage *) valp));
        }
        str = Tcl_GetString(args[i+1]);
        if (strcmp(name, str) != 0) {
          if (strlen(str) != 0) {
            if (desc->type == ZN_CONFIG_IMAGE) {
              image = ZnGetImage(wi, str, ZnUpdateItemImage, record);
              if (image == ZnUnspecifiedImage) {
                Tcl_AppendResult(wi->interp, " image expected for attribute \"",
                                 Tcl_GetString(args[i]), "\"", NULL);
                return TCL_ERROR;
              }
            }
            else {
              image = ZnGetImage(wi, str, NULL, NULL);
              if ((image == ZnUnspecifiedImage) ||
                  (!(is_bmap = ZnImageIsBitmap(image)))) {
                if (!is_bmap) {
                  ZnFreeImage(image, NULL, NULL);
                }
                Tcl_AppendResult(wi->interp, " bitmap expected for attribute \"",
                                 Tcl_GetString(args[i]), "\"", NULL);
                return TCL_ERROR;
              }
            }
          }
          if (*((ZnImage *) valp) != ZnUnspecifiedImage) {
            ZnFreeImage(*((ZnImage *) valp), ZnUpdateItemImage, record);
          }
          *((ZnImage *) valp) = image;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_BITMAP_LIST:
      {
        ZnList   new_pat_list = NULL;
        ZnImage  *pats;
        unsigned int num_pats, j, k;
        Tcl_Obj  **elems;
        ZnBool   is_bmap = True;
        
        if (Tcl_ListObjGetElements(wi->interp, args[i+1],
                                   (int *) &num_pats, &elems) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp,
                           " pattern list expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (num_pats) {
          new_pat_list = ZnListNew(num_pats, sizeof(Pixmap));
          ZnListAssertSize(new_pat_list, num_pats);
          pats = ZnListArray(new_pat_list);
          for (j = 0; j < num_pats; j++) {
            str = Tcl_GetString(elems[j]);
            if (strlen(str) != 0) {
              pats[j] = ZnGetImage(wi, str, NULL, NULL);
              if ((pats[j] == ZnUnspecifiedImage) ||
                      !(is_bmap = ZnImageIsBitmap(pats[j]))) {
                if (!is_bmap) {
                  ZnFreeImage(pats[j], NULL, NULL);
                }
                for (k = 0; k < j; k++) {
                  ZnFreeImage(pats[k], NULL, NULL);
                }
                ZnListFree(new_pat_list);
                Tcl_AppendResult(wi->interp, " unknown pattern \"", str,
                                 "\" in pattern list", NULL);
                return TCL_ERROR;
              }
            }
            else {
              pats[j] = ZnUnspecifiedImage;
            }
          }
        }
        if (*((ZnList *) valp)) {
          num_pats = ZnListSize(*((ZnList *) valp));
          pats = ZnListArray(*((ZnList *) valp));
          for (j = 0; j < num_pats; j++) {
            if (pats[j] != ZnUnspecifiedImage) {
              ZnFreeImage(pats[j], NULL, NULL);
            }
          }
          ZnListFree(*((ZnList *) valp));
          *((ZnList *) valp) = new_pat_list;
          *flags |= desc->flags;
        }
        else {
          if (new_pat_list) {
            *((ZnList *) valp) = new_pat_list;
            *flags |= desc->flags;
          }
        }
        break;
      }
    case ZN_CONFIG_TAG_LIST:
      {
        int             num_tags, j;
        Tcl_Obj **elems;
        
        if (Tcl_ListObjGetElements(wi->interp, args[i+1],
                                   &num_tags, &elems) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp,
                           " tag list expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (*((ZnList *) valp)) {
          ZnITEM.FreeTags(item);
          *flags |= desc->flags;
        }
        if (num_tags) {
          for (j = 0; j < num_tags; j++) {
            ZnITEM.AddTag(item, Tk_GetUid(Tcl_GetString(elems[j])));
          }
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_STRING:
    case ZN_CONFIG_MAP_INFO:
      {
        char *text = NULL;
        str = Tcl_GetString(args[i+1]);
        if (!*((char **) valp) || strcmp(str, *((char **) valp)) != 0) {
          if (strlen(str)) {
            text = (char *) ZnMalloc(strlen(str)+1);
            strcpy(text, str);
          }
          if (*((char **) valp)) {
            ZnFree(*((char **) valp));
          }
          *((char **) valp) = text;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_FONT:
      {
        Tk_Font font;
        Tk_Uid  name = "";
        if (*((Tk_Font *) valp)) {
          name = Tk_NameOfFont(*((Tk_Font *) valp));
        }
        str = Tcl_GetString(args[i+1]);
        if (strcmp(name, str) != 0) {
          font = Tk_GetFont(wi->interp, wi->win, str);
          if (!font) {
            Tcl_AppendResult(wi->interp, " font expected for attribute \"",
                             Tcl_GetString(args[i]), "\"", NULL);
            return TCL_ERROR;
          }
          if (*((Tk_Font *) valp)) {
            Tk_FreeFont(*((Tk_Font *) valp));
          }
          *((Tk_Font *) valp) = font;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_EDGE_LIST:
      {
        ZnBorder border;

        if (ZnGetBorder(wi, args[i+1], &border) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " edge list expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (border != *((ZnBorder *) valp)) {
          *((ZnBorder *) valp) = border;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_LINE_SHAPE:
      {
        ZnLineShape line_shape;

        if (ZnGetLineShape(wi, Tcl_GetString(args[i+1]), &line_shape) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " line shape expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (line_shape != *((ZnLineShape *) valp)) {
          *((ZnLineShape *) valp) = line_shape;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_LINE_STYLE:
      {
        ZnLineStyle    line_style;

        if (ZnGetLineStyle(wi, Tcl_GetString(args[i+1]), &line_style) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " line style expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (line_style != *((ZnLineStyle *) valp)) {
          *((ZnLineStyle *) valp) = line_style;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_LINE_END:
      {
        ZnLineEnd line_end = NULL;
        str = Tcl_GetString(args[i+1]);
        if (strlen(str) != 0) {
          line_end = ZnLineEndCreate(wi->interp, str);
          if (line_end == NULL) {
            return TCL_ERROR;
          }
        }
        if (*((ZnLineEnd *) valp) != NULL) {
          ZnLineEndDelete(*((ZnLineEnd *) valp));
          *((ZnLineEnd *) valp) = line_end;
          *flags |= desc->flags;
        }
        else {
          if (line_end != NULL) {
            *((ZnLineEnd *) valp) = line_end;
            *flags |= desc->flags;
          }
        }
        break;
      }
    case ZN_CONFIG_RELIEF:
      {
        ZnReliefStyle relief;
        if (ZnGetRelief(wi, Tcl_GetString(args[i+1]), &relief) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " relief expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (relief != *((ZnReliefStyle *) valp)) {
          /*printf("valp <0x%X>, flags <0x%X>, relief %d\n", valp, flags, relief);*/
          *((ZnReliefStyle *) valp) = relief;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_JOIN_STYLE:
      {
        int     join;
        if (Tk_GetJoinStyle(wi->interp, Tcl_GetString(args[i+1]), &join) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " join expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (join != *((int *) valp)) {
          *((int *) valp) = join;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_CAP_STYLE:
      {
        int     cap;
        if (Tk_GetCapStyle(wi->interp, Tcl_GetString(args[i+1]), &cap) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " cap expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (cap != *((int *) valp)) {
          *((int *) valp) = cap;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_POINT:
      {
        ZnPoint point;
        int             largc;
        Tcl_Obj **largv;
        double  d;

        if ((Tcl_ListObjGetElements(wi->interp, args[i+1],
                                    &largc, &largv) == TCL_ERROR) ||
            (largc != 2)) {
        point_error:
          Tcl_AppendResult(wi->interp, " position expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (Tcl_GetDoubleFromObj(wi->interp, largv[0], &d) == TCL_ERROR) {
          goto point_error;
        }
        point.x = d;
        if (Tcl_GetDoubleFromObj(wi->interp, largv[1], &d) == TCL_ERROR) {
          goto point_error;
        }
        point.y = d;
        if ((point.x != ((ZnPoint *) valp)->x) ||
            (point.y != ((ZnPoint *) valp)->y)) {
          *((ZnPoint *) valp) = point;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_ANGLE:
      {
        double angle;
        int    int_angle;
        if (Tcl_GetDoubleFromObj(wi->interp, args[i+1], &angle) == TCL_ERROR) {
          return TCL_ERROR;
        }
        int_angle = (int) angle;
        int_angle = int_angle % 360;
        if (int_angle != *((int *) valp)) {
          *((int *) valp) = int_angle;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_DIM:
      {
        double dim;
        if (Tcl_GetDoubleFromObj(wi->interp, args[i+1], &dim) == TCL_ERROR) {
          return TCL_ERROR;
        }
        if (dim != *((ZnDim *) valp)) {
          *((ZnDim *) valp) = dim;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_PRI:
      {
        int     pri;
        if (Tcl_GetIntFromObj(wi->interp, args[i+1], &pri) == TCL_ERROR) {
          return TCL_ERROR;
        }
        if (pri < 0) {
          Tcl_AppendResult(wi->interp, " priority must be a positive integer \"",
                           Tcl_GetString(args[i+1]), "\"", NULL);
          return TCL_ERROR;
        }
        if (pri != *((unsigned short *) valp)) {
          *((unsigned short *) valp) = pri;
          ZnITEM.UpdateItemPriority(item, ZN_NO_ITEM, True);
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_ITEM:
      /*
       * Can be an item id or a tag. In this last case
       * consider only the first item (unspecified order)
       * associated with the tag.
       */
      {
        ZnItem  item2;
        int             result;
        ZnTagSearch     *search_var = NULL;

        if (strlen(Tcl_GetString(args[i+1])) == 0) {
          item2 = ZN_NO_ITEM;
        }
        else {
          result = ZnItemWithTagOrId(wi, args[i+1], &item2, &search_var);
          ZnTagSearchDestroy(search_var);
          if ((result == TCL_ERROR) || (item2 == ZN_NO_ITEM)) {
            Tcl_AppendResult(wi->interp, " unknown item \"",
                             Tcl_GetString(args[i+1]), "\"", NULL);
            return TCL_ERROR;
          }
        }
        if (item2 != *((ZnItem *) valp)) {
          *((ZnItem *) valp) = item2;
          *flags |= desc->flags;
        }
      }
      break;
    case ZN_CONFIG_WINDOW:
      {
        Tk_Window       win, ancestor, parent;
        str = Tcl_GetString(args[i+1]);
        if (strlen(str) == 0) {
          win = NULL;
        }
        else {
          win = Tk_NameToWindow(wi->interp, str, wi->win);
          if (win == NULL) {
            return TCL_ERROR;
          }
          else {
            /*
             * Make sure that the zinc widget is either the parent of the
             * window associated with the item or a descendant of that
             * parent.  Also, don't allow a toplevel window or the widget
             * itself to be managed.
             */
            parent = Tk_Parent(win);
            for (ancestor = wi->win; ; ancestor = Tk_Parent(ancestor)) {
              if (ancestor == parent) {
                break;
              }
              if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) {
              badWindow:
                Tcl_AppendResult(wi->interp, "can't use ",
                                 Tk_PathName(win),
                                 " in a window item of this zinc widget",
                                 (char *) NULL);
                win = NULL;
                return TCL_ERROR;
              }
            }
            if (((Tk_FakeWin *) (win))->flags & TK_TOP_LEVEL) {
              goto badWindow;
            }
            if (win == wi->win) {
              goto badWindow;
            }
            if (win != *((Tk_Window *) valp)) {
              *((Tk_Window *) valp) = win;
              *flags |= desc->flags;
            }
          }
        }
      }
      break;
    case ZN_CONFIG_CHAR:
    case ZN_CONFIG_UCHAR:
    case ZN_CONFIG_ALPHA:
      {
        int integer;
        if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) {
          return TCL_ERROR;
        }
        switch (desc->type) {
        case ZN_CONFIG_UCHAR:
          if (integer < 0) {
            integer = 0;
          }
        case ZN_CONFIG_ALPHA:
          if (integer < 0) {
            integer = 0;
          }
          if (integer > 100) {
            integer = 100;
          }
          break;
        }
        if (integer != *((char *) valp)) {
          *((char *) valp) = integer;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_SHORT:
    case ZN_CONFIG_USHORT:
      {
        int integer;
        if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) {
          return TCL_ERROR;
        }
        if (desc->type == ZN_CONFIG_SHORT) {
          if (integer < SHRT_MIN) {
            integer = SHRT_MIN;
          }
          else if (integer > SHRT_MAX) {
            integer = SHRT_MAX;
          }
          if (integer != *((short *) valp)) {
            *((short *) valp) = integer;
            *flags |= desc->flags;
          }
        }
        else {
          if (integer < 0) {
            integer = 0;
          }
          else if (integer > USHRT_MAX) {
            integer = USHRT_MAX;
          }
          if (integer != *((unsigned short *) valp)) {
            *((unsigned short *) valp) = integer;
            *flags |= desc->flags;
          }
        }
        break;
      }
    case ZN_CONFIG_INT:
    case ZN_CONFIG_UINT:
      {
        int integer;
        if (Tcl_GetIntFromObj(wi->interp, args[i+1], &integer) == TCL_ERROR) {
          return TCL_ERROR;
        }
        if ((desc->type == ZN_CONFIG_UINT) &&  (integer < 0)) {
            integer = 0;
        }
        if (integer != *((int *) valp)) {
          *((int *) valp) = integer;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_FILL_RULE:
      {
        ZnFillRule fill_rule;

        if (ZnGetFillRule(wi, Tcl_GetString(args[i+1]), &fill_rule) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " fill rule expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (fill_rule != *((ZnFillRule *) valp)) {
          *((ZnFillRule *) valp) = fill_rule;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_ALIGNMENT:
      {
        Tk_Justify justify;
        if (Tk_GetJustify(wi->interp, Tcl_GetString(args[i+1]), &justify) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " justify expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (justify != *((Tk_Justify *) valp)) {
          *((Tk_Justify *) valp) = justify;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_ANCHOR:
      {
        Tk_Anchor       anchor;
        if (Tk_GetAnchor(wi->interp, Tcl_GetString(args[i+1]), &anchor) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " anchor expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (anchor != *((Tk_Anchor *) valp)) {
          *((Tk_Anchor *) valp) = anchor;
          *flags |= desc->flags;
        }
        break;
      }
    case ZN_CONFIG_LABEL_FORMAT:
      {
        ZnLabelFormat frmt = NULL;

        str = Tcl_GetString(args[i+1]);
        while (*str && (*str == ' ')) {
          str++;
        }
        if (strlen(str) != 0) {
          frmt = ZnLFCreate(wi->interp, str,
                            ZnFIELD.NumFields(item->class->GetFieldSet(item)));
          if (frmt == NULL) {
            return TCL_ERROR;
          }
        }

        if (*((ZnLabelFormat *) valp) != NULL) {
          ZnLFDelete(*((ZnLabelFormat *) valp));
          *((ZnLabelFormat *) valp) = frmt;
          *flags |= desc->flags;
        }
        else {
          if (frmt != NULL) {
            *((ZnLabelFormat *) valp) = frmt;
            *flags |= desc->flags;
          }
        }
        break;
      }

    case ZN_CONFIG_AUTO_ALIGNMENT:
      {
        ZnAutoAlign aa;

        if (ZnGetAutoAlign(wi, Tcl_GetString(args[i+1]), &aa) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " auto alignment expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if ((aa.automatic != ((ZnAutoAlign *) valp)->automatic) ||
            (aa.align[0] != ((ZnAutoAlign *) valp)->align[0]) ||
            (aa.align[1] != ((ZnAutoAlign *) valp)->align[1]) ||
            (aa.align[2] != ((ZnAutoAlign *) valp)->align[2])) {
          *((ZnAutoAlign *) valp) = aa;
          *flags |= desc->flags;
        }
        break;
      }

    case ZN_CONFIG_LEADER_ANCHORS:
      {
        ZnLeaderAnchors lanch = NULL;
        if (ZnGetLeaderAnchors(wi, Tcl_GetString(args[i+1]), &lanch) == TCL_ERROR) {
          Tcl_AppendResult(wi->interp, " leader anchors expected for attribute \"",
                           Tcl_GetString(args[i]), "\"", NULL);
          return TCL_ERROR;
        }
        if (*((ZnLeaderAnchors *) valp) != NULL) {
          ZnFree(*((ZnLeaderAnchors *) valp));
          *((ZnLeaderAnchors *) valp) = lanch;
          *flags |= desc->flags;
        }
        else {
          if (lanch != NULL) {
            *((ZnLeaderAnchors *) valp) = lanch;
            *flags |= desc->flags;
          }
        }
        break;
      }
    }
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * AttributeToObj --
 *
 *      Returns the obj representation of the attribute pointed
 *      by 'valp'. The attribute type is given by 'type'. The function
 *      never fail.
 *
 **********************************************************************************
 */
static Tcl_Obj *
AttributeToObj(Tcl_Interp       *interp,
               void             *record,
               ZnAttrConfig     *desc)
{
  char          *valp = ((char *) record) + desc->offset;
  char          *str = "";
  Tcl_Obj       *o, *obj;
  unsigned int  i;
  char          buffer[256];

  switch (desc->type) {
  case ZN_CONFIG_GRADIENT:
    if (*((ZnGradient **) valp)) {
      str = ZnNameOfGradient(*((ZnGradient **) valp));
    }
    break;
  case ZN_CONFIG_GRADIENT_LIST:
    {
      unsigned int num_grads;
      ZnGradient   **grads;

      if (*((ZnList *) valp)) {
        grads = ZnListArray(*((ZnList *) valp));
        num_grads = ZnListSize(*((ZnList *) valp));
        
        obj = Tcl_NewObj();
        for (i = 0; i < num_grads; i++) {
          o = Tcl_NewStringObj(ZnNameOfGradient(grads[i]), -1);
          Tcl_ListObjAppendElement(interp, obj, o);
        }
        return obj;
      }
    }
    break;
  case ZN_CONFIG_BOOL:
    return Tcl_NewBooleanObj(ISSET(*((unsigned short *) valp), desc->bool_bit)?1:0);
  case ZN_CONFIG_IMAGE:
    if (*((ZnImage *) valp)) {
      str = ZnNameOfImage(*((ZnImage *) valp));
#if PTK
      // Just return the perl image object, it is far more
      // useful than the mere string name.
      return LangObjectObj(interp, str);
#endif
    }
    break;
  case ZN_CONFIG_BITMAP:
    if (*((ZnImage *) valp)) {
      str = ZnNameOfImage(*((ZnImage *) valp));
    }
    break;
  case ZN_CONFIG_BITMAP_LIST:
    {
      unsigned int num_pats=0;
      ZnImage      *pats;

      if (*((ZnList *) valp)) {
        pats = (ZnImage *) ZnListArray(*((ZnList *) valp));
        num_pats = ZnListSize(*((ZnList *) valp));

        obj = Tcl_NewObj();
        for (i = 0; i < num_pats; i++) {
          if (pats[i] != ZnUnspecifiedImage) {
            o = Tcl_NewStringObj(ZnNameOfImage(pats[i]), -1);
          }
          else {
            o = Tcl_NewStringObj("", -1);
          }
          Tcl_ListObjAppendElement(interp, obj, o);
        }
        return obj;
      }
      break;
    }
  case ZN_CONFIG_TAG_LIST:
    {
      unsigned int num_tags=0;
      Tk_Uid       *tags;

      if (*((ZnList *) valp)) {
        tags = (Tk_Uid *) ZnListArray(*((ZnList *) valp));
        num_tags = ZnListSize(*((ZnList *) valp));
        obj = Tcl_NewObj();
        for (i = 0; i < num_tags; i++) {
          Tcl_ListObjAppendElement(interp, obj,
                                   Tcl_NewStringObj(tags[i], -1));
        }
        return obj;
      }
      break;
    }
  case ZN_CONFIG_STRING:
  case ZN_CONFIG_MAP_INFO:
    if (*((char **) valp)) {
      str = *((char **) valp);
    }
    break;
  case ZN_CONFIG_FONT:
    if (*((Tk_Font *) valp)) {
      str = (char *) Tk_NameOfFont(*((Tk_Font *) valp));
    }
    break;
  case ZN_CONFIG_EDGE_LIST:
    str = buffer;
    ZnNameOfBorder(*((ZnBorder *) valp), buffer);
    break;
  case ZN_CONFIG_LINE_SHAPE:
    str = ZnNameOfLineShape(*((ZnLineShape *) valp));
    break;
  case ZN_CONFIG_FILL_RULE:
    str = ZnNameOfFillRule(*((ZnFillRule *) valp));
    break;
  case ZN_CONFIG_LINE_STYLE:
    str = ZnNameOfLineStyle(*((ZnLineStyle *) valp));
    break;
  case ZN_CONFIG_LINE_END:
    if (*((ZnLineEnd *) valp)) {
      str = ZnLineEndGetString(*((ZnLineEnd *) valp));
    }
    break;
  case ZN_CONFIG_RELIEF:
    str = ZnNameOfRelief(*((ZnReliefStyle *) valp));
    break;
  case ZN_CONFIG_JOIN_STYLE:
    str = (char *) Tk_NameOfJoinStyle(*((int *) valp));
    break;
  case ZN_CONFIG_CAP_STYLE:
    str = (char *) Tk_NameOfCapStyle(*((int *) valp));
    break;
  case ZN_CONFIG_POINT:
    obj = Tcl_NewObj();
    Tcl_ListObjAppendElement(interp, obj, Tcl_NewDoubleObj(((ZnPoint *) valp)->x));
    Tcl_ListObjAppendElement(interp, obj, Tcl_NewDoubleObj(((ZnPoint *) valp)->y));
    return obj;
  case ZN_CONFIG_ITEM:
    if (*((ZnItem *) valp) != ZN_NO_ITEM) {
      return Tcl_NewLongObj((int) (*((ZnItem *) valp))->id);
    }
    break;
  case ZN_CONFIG_WINDOW:
    if (*((Tk_Window *) valp) != NULL) {
      str = Tk_PathName(*((Tk_Window *) valp));
    }
    break;
  case ZN_CONFIG_CHAR:
    return Tcl_NewIntObj(*((char *) valp));
  case ZN_CONFIG_UCHAR:
  case ZN_CONFIG_ALPHA:
    return Tcl_NewIntObj(*((unsigned char *) valp));
  case ZN_CONFIG_USHORT:
  case ZN_CONFIG_PRI:
    return Tcl_NewIntObj(*((unsigned short *) valp));
  case ZN_CONFIG_SHORT:
     return Tcl_NewIntObj(*((short *) valp));
  case ZN_CONFIG_UINT:
    return Tcl_NewIntObj(*((unsigned int *) valp));
  case ZN_CONFIG_INT:
    return Tcl_NewIntObj(*((int *) valp));
  case ZN_CONFIG_ANGLE:
    return Tcl_NewDoubleObj(*((int *) valp));
  case ZN_CONFIG_DIM:
    return Tcl_NewDoubleObj(*((ZnDim *) valp));
  case ZN_CONFIG_ALIGNMENT:
    str = (char *) Tk_NameOfJustify(*((Tk_Justify *) valp));
    break;
  case ZN_CONFIG_ANCHOR:
    str = (char *) Tk_NameOfAnchor(*((Tk_Anchor *) valp));
    break;
  case ZN_CONFIG_LABEL_FORMAT:
    if (*((ZnLabelFormat *) valp)) {
      str = ZnLFGetString(*((ZnLabelFormat *) valp));
    }
    break;
  case ZN_CONFIG_AUTO_ALIGNMENT:
    str = buffer;
    ZnNameOfAutoAlign((ZnAutoAlign *) valp, buffer);
    break;
  case ZN_CONFIG_LEADER_ANCHORS:
    str = buffer;
    ZnNameOfLeaderAnchors(*((ZnLeaderAnchors *) valp), buffer);
    break;
  }
  return Tcl_NewStringObj(str, -1);
}


/*
 **********************************************************************************
 *
 * ZnQueryAttribute --
 *
 **********************************************************************************
 */
int
ZnQueryAttribute(Tcl_Interp     *interp,
                 void           *record,
                 ZnAttrConfig   *desc_table,
                 Tcl_Obj        *attr_name)
{
  ZnAttrConfig  *desc = GetAttrDesc(interp, attr_name, desc_table);
  
  if (!desc) {
    return TCL_ERROR;
  }
  Tcl_SetObjResult(interp, AttributeToObj(interp, record, desc));

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ZnItemClassList --
 *
 **********************************************************************************
 */
ZnList
ZnItemClassList()
{
  return item_classes;
}

/*
 **********************************************************************************
 *
 * ZnLookupItemClass --
 *
 **********************************************************************************
 */
ZnItemClass
ZnLookupItemClass(char  *class_name)
{
  ZnItemClass   *class;
  int           i, num_classes;

  class = (ZnItemClass *) ZnListArray(item_classes);
  num_classes = ZnListSize(item_classes);
  for (i = 0; i < num_classes; i++) {
    if (strcmp((class[i])->name, class_name) == 0) {
      return class[i];
    }
  }
  
  return NULL;
}

/*
 **********************************************************************************
 *
 * ZnAddItemClass --
 *
 **********************************************************************************
 */
void
ZnAddItemClass(ZnItemClass      class)
{
  if (!ZnLookupItemClass(class->name)) {
    ZnListAdd(item_classes, &class, ZnListTail);
    InitAttrDesc(class->attr_desc);
  }
}

/*
 **********************************************************************************
 *
 * ZnItemInit --
 *      Initialize classes static state.
 *
 **********************************************************************************
 */
void
ZnItemInit()
{
  /* First check if static part already inited */
  if (item_classes == NULL) {
    item_classes = ZnListNew(17, sizeof(ZnItemClass));
#ifdef ATC
    ZnAddItemClass(ZnTrack);
    ZnAddItemClass(ZnWayPoint);
    ZnAddItemClass(ZnMap);
    ZnAddItemClass(ZnReticle);
#endif
    ZnAddItemClass(ZnTabular);
    ZnAddItemClass(ZnRectangle);
    ZnAddItemClass(ZnArc);
    ZnAddItemClass(ZnCurve);
    ZnAddItemClass(ZnTriangles);
    ZnAddItemClass(ZnGroup);
    ZnAddItemClass(ZnIcon);
    ZnAddItemClass(ZnText);
    ZnAddItemClass(ZnWindow);
    ZnAddItemClass(ZnViewport);
    InitAttrDesc(ZnFIELD.attr_desc);
  }
}


/*
 **********************************************************************************
 *
 * UpdateItemDependency -- Method
 *      Update the group dependency list following a change in the
 *      connection of an item.
 *
 **********************************************************************************
 */
static void
UpdateItemDependency(ZnItem     item,
                     ZnItem     old_connection)
{
  if (old_connection == ZN_NO_ITEM) {
    /* Add a connection */
    ZnInsertDependentItem(item);
  }
  else if (item->connected_item == ZN_NO_ITEM) {
    /* Remove a connection */
    ZnExtractDependentItem(item);
  }
  else {
    /* Move at end to ensure that it will be updated after
     * the (new) item it depends upon.
     */
    ZnExtractDependentItem(item);
    ZnInsertDependentItem(item);
  }
}


/*
 **********************************************************************************
 *
 * ExtractItem --
 *      Extract an item from its context, includes updating graphic
 *      state flags.
 *
 **********************************************************************************
 */
static void
ExtractItem(ZnItem      item)
{
  ZnWInfo       *wi = item->wi;
  ZnItem        group = item->parent;

  /* damage bounding boxes */
  if (ISSET(item->flags, ZN_VISIBLE_BIT)) {
    ZnDamage(wi, &item->item_bounding_box);
  }
  
  /*
   * Tell that we need to repick
   */
  if (item->class != ZnGroup) {
    SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
  }

  if (group != ZN_NO_ITEM) {
    /* Remove me from dependency list. */
    ZnExtractDependentItem(item);
    
    /* Disconnect all dependents on me. */
    ZnDisconnectDependentItems(item);
    /*
     * Remove me as a clip item.
     */
    ZnGroupRemoveClip(group, item);
    /*
     * Remove me from item list.
     */
    ZnGroupExtractItem(item);
  }
}


/*
 **********************************************************************************
 *
 * InsertItem -- Method
 *
 *      Insert an item in the display list according to its priority.
 *      It is inserted in front of items of lower or same priority. If
 *      mark_item is not ZN_NO_ITEM the insertion is done relative
 *      to this item, before it if 'before' is True, after it otherwise.
 *      mark_item must be in the group 'group'.
 *
 **********************************************************************************
 */
static void
InsertItem(ZnItem       item,
           ZnItem       grp,
           ZnItem       mark_item,
           ZnBool       before)
{
  if (!grp) {
    grp = item->wi->top_group;
  }
  item->parent = grp;
  
  if (mark_item && (mark_item->parent != grp)) {
    mark_item = ZN_NO_ITEM;
  }
  
  ZnGroupInsertItem(grp, item, mark_item, before);
}


/*
 **********************************************************************************
 *
 * UpdateItemPriority -- Method
 *      Reorder a group's item list following a change in an
 *      item priority or a call to lower/raise.
 *
 **********************************************************************************
 */
static void
UpdateItemPriority(ZnItem       item,
                   ZnItem       mark_item,
                   ZnBool       before)
{
  ZnItem        parent = item->parent;
  
  ZnGroupExtractItem(item);
  InsertItem(item, parent, mark_item, before);
  Invalidate(item, ZN_DRAW_FLAG);
  SET(item->wi->flags, ZN_INTERNAL_NEED_REPICK);
}


/*
 **********************************************************************************
 *
 * SetId,
 * FreeId -- Method
 *      Get a fresh object id from the widget and enter the new
 *      object with this id in the object hash table. The id is
 *      incremented. FreeId on the other hand suppress the item
 *      from the hash table and set its object id to zero.
 *
 **********************************************************************************
 */
static void
SetId(ZnItem    item)
{
  ZnWInfo       *wi = item->wi;
  Tcl_HashEntry *entry;
  int           dummy;

  item->id = wi->obj_id;
  wi->obj_id++;
  entry = Tcl_CreateHashEntry(wi->id_table, (char *) item->id, &dummy);
  Tcl_SetHashValue(entry, item);  
}

static void
FreeId(ZnItem   item)
{
  Tcl_HashEntry *entry;
  
  if (item->id) {
    entry = Tcl_FindHashEntry(item->wi->id_table, (char *) item->id);
    if (entry) {
      Tcl_DeleteHashEntry(entry);
      item->id = 0;
    }
  }
}

/*
 **********************************************************************************
 *
 * AddTag -- Method
 *      Add a tag to the item. If the tag is already on the list it
 *      is not added. As a side effect the tag/item pair is added to
 *      the tag table of the widget.
 *      'tag' must be a Tk_Uid.
 *
 **********************************************************************************
 */
static void
AddTag(ZnItem   item,
       Tk_Uid   tag)
{
  int   num, i;
  char  **ptr;
  
  /*
   * No tags yet.
   */
  if (!item->tags) {
    item->tags = ZnListNew(1, sizeof(char *));
  }
  else {
    /*
     * If the tag is already there, that's done.
     */
    ptr = (char **) ZnListArray(item->tags);
    num = ZnListSize(item->tags);
    for (i = 0; i < num; i++) {
      if (ptr[i] == tag) {
        return;
      }
    }
  }
  /*
   * Add it.
   */
  ZnListAdd(item->tags, (void *) &tag, ZnListTail);
}

/*
 **********************************************************************************
 *
 * RemoveTag -- Method
 *
 **********************************************************************************
 */
static void
RemoveTag(ZnItem        item,
          Tk_Uid        tag)
{
  unsigned int  indx, num;
  char          **ptr;
  
  if (!item->tags) {
    return;
  }
  /*
   * look up the tag in the list.
   */
  ptr = (char **) ZnListArray(item->tags);
  num = ZnListSize(item->tags);
  for (indx = 0; indx < num; indx++) {
    if (ptr[indx] == tag) {
      /* The tag list is not freed when empty to avoid
       * overhead when using tags intensively. */
      ZnListDelete(item->tags, indx);
      return;
    }
  }
}

/*
 **********************************************************************************
 *
 * FreeTags -- Method
 *
 **********************************************************************************
 */
static void
FreeTags(ZnItem item)
{
  if (!item->tags) {
    return;
  }
  ZnListFree(item->tags);
  item->tags = NULL;
}


/*
 **********************************************************************************
 *
 * HasTag -- Method
 *
 **********************************************************************************
 */
static ZnBool
HasTag(ZnItem   item,
       Tk_Uid   tag)
{
  int           num;
  Tk_Uid        *tags;

  if (!item->tags || !ZnListSize(item->tags)) {
    return False;
  }
  else {
    num = ZnListSize(item->tags);
    tags = ZnListArray(item->tags);
    for (tags = ZnListArray(item->tags); num > 0; tags++, num--) {
      if (*tags == tag) {
        return True;
      }
    }
  }
  return False;
}


/*
 **********************************************************************************
 *
 * ZnCreateItem --
 *
 *      InsertItem and ConfigureItem must be called after CreateItem
 *      to finalize the setup of a new item. This is so even if
 *      there are no attributes to be changed after creation.
 *      ConfigureItem must be called in this case with the 'init'
 *      parameter set to True.
 *
 **********************************************************************************
 */
ZnItem
ZnCreateItem(ZnWInfo        *wi,
             ZnItemClass   item_class,
             int            *argc,
             Tcl_Obj *CONST *args[])
{
  ZnItem        item;

  item = ZnMalloc(item_class->size);
  
  /* Initialize common state */
  item->class = item_class;
  item->wi = wi;
  item->parent = NULL;
  item->previous = ZN_NO_ITEM;
  item->next = ZN_NO_ITEM;
  CLEAR(item->flags, ZN_UPDATE_DEPENDENT_BIT);
  item->inv_flags = 0;
  item->transfo = NULL;
  item->parent = NULL;
  item->connected_item = ZN_NO_ITEM;
#ifdef GL
#ifdef GL_LIST
  item->gl_list = 0;
#endif
#endif
  ZnResetBBox(&item->item_bounding_box);

  /* Init item specific attributes */
  if (item_class->Init(item, argc, args) == TCL_ERROR) {
    ZnFree(item);
    return ZN_NO_ITEM;
  }

  SetId(item);
  item->tags = NULL;
  
  SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
  wi->num_items++;

  return (item);
}


/*
 **********************************************************************************
 *
 * CloneItem -- Method
 *      Can't clone the top level group.
 *
 **********************************************************************************
 */
static ZnItem
CloneItem(ZnItem        model)
{
  ZnWInfo       *wi = model->wi;
  ZnItem        item;
  Tk_Uid        *tags;
  unsigned int  num_tags;
  int           i;
  
  if (!model->parent) {
    return ZN_NO_ITEM;
  }
  
  item = ZnMalloc(model->class->size);
  memcpy(item, model, model->class->size);

  item->previous = ZN_NO_ITEM;
  item->next = ZN_NO_ITEM;
  item->connected_item = ZN_NO_ITEM;
  CLEAR(item->flags, ZN_UPDATE_DEPENDENT_BIT);
  item->inv_flags = 0;
  SetId(item);

  if (model->tags) {
    item->tags = NULL;
    tags = (Tk_Uid *) ZnListArray(model->tags);
    num_tags = ZnListSize(model->tags);
    for (i = num_tags-1; i >= 0; i--, tags++) {
      AddTag(item, *tags);
    }
  }

  if (item->transfo) {
    item->transfo = ZnTransfoDuplicate(item->transfo);
  }
  
  /* Call item's clone to duplicate non shared resources */
  item->class->Clone(item);

  SET(wi->flags, ZN_INTERNAL_NEED_REPICK);
  wi->num_items++;

  Invalidate(item, ZN_COORDS_FLAG);

  return item;
}


/*
 **********************************************************************************
 *
 * ConfigureItem -- Method
 *
 **********************************************************************************
 */
static int
ConfigureItem(ZnItem            item,
              int               field,
              int               argc,
              Tcl_Obj   *CONST  argv[],
              ZnBool            init)
{
  ZnWInfo       *wi = item->wi;
  int           flags;
  ZnBool        previous_visible = init ? False : ISSET(item->flags, ZN_VISIBLE_BIT);

  flags = 0;
  ASSIGN(flags, ZN_COORDS_FLAG, init);
  if (argv) {
    if (field < 0){
      if (item->class->Configure(item, argc, argv, &flags) == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (item->class->GetFieldSet && ISSET(flags, ZN_CLFC_FLAG)) {
        ZnFIELD.ClearFieldCache(item->class->GetFieldSet(item), -1);
      }
    }
    else if (item->class->GetFieldSet) {
      if (ZnFIELD.ConfigureField(item->class->GetFieldSet(item),
                                 field, argc, argv, &flags) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    else {
      return TCL_ERROR;
    }
  }

  //
  // If visibility changed.
  if (previous_visible ^ ISSET(item->flags, ZN_VISIBLE_BIT)) {
    // First must force an update of the parent geometry (bbox).
    Invalidate(item, ZN_COORDS_FLAG);
    //
    // Special case when the item has its visibility
    // just turned out.
    if (ISCLEAR(item->flags, ZN_VISIBLE_BIT)) {
      ZnDamage(wi, &item->item_bounding_box);
    }
  }
  
  Invalidate(item, flags);
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * QueryItem -- Method
 *
 **********************************************************************************
 */
static int
QueryItem(ZnItem                item,
          int                   field,
          int                   argc,
          Tcl_Obj *CONST        argv[])
{
  if (field < 0) {
    return item->class->Query(item, argc, argv);
  }
  else if (item->class->GetFieldSet) {
    return ZnFIELD.QueryField(item->class->GetFieldSet(item),
                              field, argc, argv);
  }
  
  return TCL_ERROR;
}


/*
 **********************************************************************************
 *
 * ComposeTransform --
 *      Compose a transform transfo with current_t to new_t.
 *
 **********************************************************************************
 */
static void
ComposeTransform(ZnTransfo      *transfo,
                 ZnPoint        *pos,
                 ZnTransfo      *current_t,
                 ZnTransfo      *new_t,
                 ZnBool         compose_scale,
                 ZnBool         compose_rot)
{
  ZnBool        full;
  ZnTransfo     t, t2;

  full = compose_scale && compose_rot;
  
  if (!transfo && !pos && full) {
    *new_t = *current_t;
    return;
  }
  if (full) {
    /*
     * Full concatenation.
     */
    /*ZnPrintTransfo(transfo);*/
    if (pos) {
      if (!transfo) {
        ZnTransfoSetIdentity(&t);
      }
      else {
        t = *transfo;
      }
      ZnTranslate(&t, pos->x, pos->y, False);
      ZnTransfoCompose(new_t, &t, current_t);
    }
    else {
      ZnTransfoCompose(new_t, transfo, current_t);
    }
  }
  else {
    ZnPoint     scale, trans, local_scale, local_trans, p;
    ZnReal      local_rot, rot;
    
    ZnTransfoSetIdentity(new_t);
    ZnTransfoDecompose(transfo, &local_scale, &local_trans, &local_rot, NULL);
    ZnScale(new_t, local_scale.x, local_scale.y);
    ZnRotateRad(new_t, local_rot);

    ZnTransfoDecompose(current_t, &scale, &trans, &rot, NULL);

    if (pos) {
      ZnTransfoSetIdentity(&t);
      ZnTranslate(&t, pos->x, pos->y, False);
      ZnTransfoCompose(&t2, &t, current_t);
      ZnTransformPoint(&t2, &local_trans, &p);
    }
    else {
      ZnTransformPoint(current_t, &local_trans, &p);
    }

    if (compose_scale) {
      ZnScale(new_t, scale.x, scale.y);
    }
    if (compose_rot) {
      ZnRotateRad(new_t, rot);
    }
    ZnTranslate(new_t, p.x, p.y, False);
  }
}


/*
 **********************************************************************************
 *
 * GetItemTransform -- Method
 *      Compute the current transform for an item.
 *
 **********************************************************************************
 */
static void
GetItemTransform(ZnItem         item,
                 ZnTransfo      *t)
{
  ZnItem        *items;
  int           i;
  ZnTransfo     t_tmp, *t1, *t2, *swap;
  ZnPoint       *pos;

  if (item_stack == NULL) {
    item_stack = ZnListNew(16, sizeof(ZnItem));
  }
  else {
    ZnListEmpty(item_stack);
  }
  
  while (item != ZN_NO_ITEM) {
    ZnListAdd(item_stack, &item, ZnListTail);
    item = item->parent;
  }
  
  ZnTransfoSetIdentity(t);
  t1 = t;
  t2 = &t_tmp;
  items = (ZnItem *) ZnListArray(item_stack);
  for (i = ZnListSize(item_stack)-1; i >= 0; i--) {
    pos = NULL;
    if (items[i]->class->pos_offset >= 0) {
      pos = (ZnPoint *) (((char *) items[i]) + items[i]->class->pos_offset);
      if (pos->x == 0 && pos->y == 0) {
        pos = NULL;
      }
    }
    ComposeTransform(items[i]->transfo, pos, t1, t2,
                     ISSET(items[i]->flags, ZN_COMPOSE_SCALE_BIT),
                     ISSET(items[i]->flags, ZN_COMPOSE_ROTATION_BIT));
    swap = t2;
    t2 = t1;
    t1 = swap;
  }
  if (t1 != t) {
    *t = *t1;
  }
}



/*
 **********************************************************************************
 *
 * ZnResetTransformStack
 * ZnInitTransformStack
 * ZnFreeTransformStack
 * ZnPushTransform
 * ZnPopTransform --
 *
 **********************************************************************************
 */
void
ZnResetTransformStack(ZnWInfo   *wi)
{
  ZnListAssertSize(wi->transfo_stack, 1);
  wi->current_transfo = (ZnTransfo *) ZnListAt(wi->transfo_stack, 0);
  ZnTransfoSetIdentity(wi->current_transfo);
}

void
ZnInitTransformStack(ZnWInfo    *wi)
{
  wi->transfo_stack = ZnListNew(8, sizeof(ZnTransfo));
  ZnResetTransformStack(wi);
}

void
ZnFreeTransformStack(ZnWInfo    *wi)
{
  ZnListFree(wi->transfo_stack);
}

void
ZnPushTransform(ZnWInfo         *wi,
                ZnTransfo       *transfo,
                ZnPoint         *pos,
                ZnBool          compose_scale,
                ZnBool          compose_rot)
{
  ZnTransfo     *next_t;
  unsigned int  num_t;

  /*
   * Push the current transform and concatenate
   * the new transform taking into account the
   * combination flags.
   */
  num_t = ZnListSize(wi->transfo_stack);
  ZnListAssertSize(wi->transfo_stack, num_t+1);
  next_t = (ZnTransfo *) ZnListAt(wi->transfo_stack, num_t);
  ComposeTransform(transfo, pos, wi->current_transfo, next_t,
                   compose_scale, compose_rot);
  wi->current_transfo = next_t;
}

void
ZnPopTransform(ZnWInfo  *wi)
{
  /*
   * Restore the previous transform.
   */
  ZnListDelete(wi->transfo_stack, ZnListTail);
  wi->current_transfo = (ZnTransfo *) ZnListAt(wi->transfo_stack, ZnListTail);
}


/*
 **********************************************************************************
 *
 * ZnResetClipStack
 * ZnInitClipStack
 * ZnFreeClipStack
 * ZnCurrentClip
 * ZnPushClip
 * ZnPopClip --
 *
 **********************************************************************************
 */
/*
 * Describe the clipping at a given node
 * of the item hierarchy.
 */
typedef struct _ClipState {
  ZnBool        simple;         /* The clip is an aligned rectangle.    */
  TkRegion      region;         /* The region used to draw and to       */
                                /* probe for picking.                   */
  ZnBBox        clip_box;       /* The bounding box of the clip area.   */
} ClipState;

void
ZnResetClipStack(ZnWInfo        *wi)
{
  int           i;
  ClipState     *clips = (ClipState *) ZnListArray(wi->clip_stack);
  
  /*
   * Should not happen, clip stack should be
   * empty when this function is called.
   */
  for (i = ZnListSize(wi->clip_stack)-1; i >= 0; i--) {
    TkDestroyRegion(clips[i].region);
  }
  ZnListEmpty(wi->clip_stack);
  wi->current_clip = NULL;
}

void
ZnInitClipStack(ZnWInfo *wi)
{
  wi->clip_stack = ZnListNew(8, sizeof(ClipState));
  ZnResetClipStack(wi);  
}

void
ZnFreeClipStack(ZnWInfo *wi)
{
  ZnListFree(wi->clip_stack);
}

ZnBool
ZnCurrentClip(ZnWInfo   *wi,
              TkRegion  *reg,
              ZnBBox    **clip_box,
              ZnBool    *simple)
{
  if (wi->current_clip) {
    if (reg) {
      *reg = wi->current_clip->region;
    }
    if (clip_box) {
      *clip_box = &wi->current_clip->clip_box;
    }
    if (simple) {
      *simple = wi->current_clip->simple;
    }
    return True;
  }
  
  return False;
}

/*
 * If simple is True poly is a pointer to an
 * array of two points. In the other case it
 * is a regular pointer to a multi contour poly.
 */
void
ZnPushClip(ZnWInfo      *wi,
           ZnTriStrip   *tristrip,
           ZnBool       simple,
           ZnBool       set_gc)
{
  unsigned int  i, j, num_clips;
  unsigned int  num_pts, max_num_pts;
  ZnPoint       *p;
  ClipState     *previous_clip=NULL;
  TkRegion      reg, reg_op/*, reg_to*/;
  XRectangle    rect;
  XPoint        xpts[3];
  
  if (tristrip->num_strips == 0) {
    return;
  }
  max_num_pts = tristrip->strips[0].num_points;
  for (j = 0; j < tristrip->num_strips; j++) {
    num_pts = tristrip->strips[j].num_points;
    if (num_pts > max_num_pts) {
      num_pts = max_num_pts;
    }
  }
  if ((simple && (max_num_pts < 2)) ||
      (!simple && (max_num_pts < 3))) {
    return;
  }
  
  num_clips = ZnListSize(wi->clip_stack);
  /*  printf("PushClip: num clips %d\n", num_clips);fflush(stdout);*/
  if (num_clips != 0) {
    previous_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail);
  }
  ZnListAssertSize(wi->clip_stack, num_clips+1);
  wi->current_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail);
  wi->current_clip->simple = simple;

  /*
   * Compute the local region.
   */
  if (simple) {
    rect.x = (short) tristrip->strips[0].points[0].x;
    rect.y = (short) tristrip->strips[0].points[0].y;
    rect.width = ((unsigned short) (tristrip->strips[0].points[1].x -
                                    tristrip->strips[0].points[0].x));
    rect.height = ((unsigned short) (tristrip->strips[0].points[1].y -
                                     tristrip->strips[0].points[0].y));
    reg = TkCreateRegion();
    TkUnionRectWithRegion(&rect, reg, reg);
    /*printf("Adding a simple clip: %d, %d, %d, %d\n",
      rect.x, rect.y, rect.width, rect.height);*/
  }
  else {
    reg = TkCreateRegion();
    for (j = 0; j < tristrip->num_strips; j++) {
      num_pts = tristrip->strips[j].num_points;
      p = tristrip->strips[j].points;
      if (tristrip->strips[j].fan) {
        xpts[0].x = ZnNearestInt(p->x);
        xpts[0].y = ZnNearestInt(p->y);
        p++;
        xpts[1].x = ZnNearestInt(p->x);
        xpts[1].y = ZnNearestInt(p->y);
        p++;
        for (i = 2; i < num_pts; i++, p++) {
          xpts[2].x = ZnNearestInt(p->x);
          xpts[2].y = ZnNearestInt(p->y);
          reg_op = (TkRegion) ZnPolygonRegion(xpts, 3, EvenOddRule);
          //reg_to = TkCreateRegion();
          //ZnUnionRegion(reg, reg_op, reg_to);
          ZnUnionRegion(reg, reg_op, reg);
          //TkDestroyRegion(reg);
          TkDestroyRegion(reg_op);
          //reg = reg_to;
          xpts[1] = xpts[2];
        }
      }
      else {
        xpts[0].x = (short) p->x;
        xpts[0].y = (short) p->y;
        p++;
        xpts[1].x = (short) p->x;
        xpts[1].y = (short) p->y;
        p++;
        for (i = 2 ; i < num_pts; i++, p++) {
          xpts[2].x = (short) p->x;
          xpts[2].y = (short) p->y;     
          reg_op = (TkRegion) ZnPolygonRegion(xpts, 3, EvenOddRule);
          //reg_to = TkCreateRegion();
          //ZnUnionRegion(reg, reg_op, reg_to);
          ZnUnionRegion(reg, reg_op, reg);
          //TkDestroyRegion(reg);
          TkDestroyRegion(reg_op);
          //reg = reg_to;
          xpts[0] = xpts[1];
          xpts[1] = xpts[2];
        }
      }
    }
  }
  
  /*
   * Combine with previous region if any.
   */
  if (previous_clip) {
    wi->current_clip->region = TkCreateRegion();
    TkIntersectRegion(reg, previous_clip->region, wi->current_clip->region);
    TkDestroyRegion(reg);
    /*printf("Merging with previous clip\n");*/
  }
  else {
    wi->current_clip->region = reg;
  }
  TkClipBox(wi->current_clip->region, &rect);
  wi->current_clip->clip_box.orig.x = rect.x;
  wi->current_clip->clip_box.orig.y = rect.y;
  wi->current_clip->clip_box.corner.x = rect.x + rect.width;
  wi->current_clip->clip_box.corner.y = rect.y + rect.height;

  /*
   * Set the clipping in the GC. 
   */
  if (set_gc) {
    if (wi->render) {
#ifdef GL
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF);      
      glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
      if (simple) {
        /*      printf("Clip box is : %d, %d, %d, %d, num_clips : %d\n",
                rect.x, rect.y, rect.width, rect.height, num_clips);*/
        glBegin(GL_QUADS);
        glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.orig.y);
        glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.corner.y);
        glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.corner.y);
        glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.orig.y);
        glEnd();
      }
      else {
        for (j = 0; j < tristrip->num_strips; j++) {
          num_pts = tristrip->strips[j].num_points;
          p = tristrip->strips[j].points;
          if (tristrip->strips[j].fan) {
            glBegin(GL_TRIANGLE_FAN);
          }
          else {
            glBegin(GL_TRIANGLE_STRIP);
          }
          for (i = 0; i < num_pts; i++, p++) {
            glVertex2d(p->x, p->y);
          }
          glEnd();
        }
      }
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF);
      glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);   
#endif
    }
    else {
      TkSetRegion(wi->dpy, wi->gc, wi->current_clip->region);
    }
  }
}

void
ZnPopClip(ZnWInfo       *wi,
          ZnBool        set_gc)
{
  int   num_clips;
  
  if (wi->current_clip == NULL) {
    return;
  }
  
  TkDestroyRegion(wi->current_clip->region);
  ZnListDelete(wi->clip_stack, ZnListTail);
  num_clips = ZnListSize(wi->clip_stack);
  
  if (num_clips != 0) {
    wi->current_clip = (ClipState *) ZnListAt(wi->clip_stack, ZnListTail);
  }
  else {
    wi->current_clip = NULL;
  }

  /*
   * Set the clipping in the GC.
   */
  if (set_gc) {
    if (num_clips != 0) {
      if (wi->render) {
#ifdef GL
        glStencilFunc(GL_EQUAL, (GLint) (num_clips+1), 0xFF);
        glStencilOp(GL_KEEP, GL_DECR, GL_DECR);
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
#if 0
        if (wi->current_clip->simple) {
#endif
          glBegin(GL_QUADS);
          glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.orig.y);
          glVertex2d(wi->current_clip->clip_box.orig.x, wi->current_clip->clip_box.corner.y);
          glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.corner.y);
          glVertex2d(wi->current_clip->clip_box.corner.x, wi->current_clip->clip_box.orig.y);
          glEnd();
#if 0
        }
        else {
        }
#endif
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
        glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF);    
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 
#endif
      }
      else {
        TkSetRegion(wi->dpy, wi->gc, wi->current_clip->region);
      }
    }
    else {
      /*printf("resetting clip mask\n");*/
      if (wi->render) {
#ifdef GL
        glClear(GL_STENCIL_BUFFER_BIT);
        glDisable(GL_STENCIL_TEST);
#endif
      }
      else {
        XSetClipMask(wi->dpy, wi->gc, None);
      }
    }
  }
  /*printf("PopClip: num clips %d\n", ZnListSize(wi->clip_stack));fflush(stdout);*/
}


/*
 **********************************************************************************
 *
 * Invalidate -- Method
 *
 **********************************************************************************
 */
static void
Invalidate(ZnItem       item,
           int          reason)
{
  /* 
   * Why this test has to be so an abrupt shortcut ?
   * It precludes addition of meaningful reasons
   * by subsequent invalidations .
   *
     if (ISSET(item->inv_flags, ZN_TRANSFO_FLAG)) {
    return;
    }*/

  if (ISSET(reason, ZN_COORDS_FLAG) ||
      ISSET(reason, ZN_TRANSFO_FLAG)) {
    ZnItem parent = item->parent;
    while ((parent != NULL) &&
           ISCLEAR(parent->inv_flags, ZN_COORDS_FLAG) &&
           ISCLEAR(parent->inv_flags, ZN_TRANSFO_FLAG)) {
      SET(parent->inv_flags, ZN_COORDS_FLAG);
      /*printf("invalidate coords for parent %d\n", parent->id);*/
      parent = parent->parent;
    }
    /*
     * There is no need to set the DRAW flag to force the invalidation
     * of the current bounding box. This will be done by ComputeCoordinates
     * in Group.
     */
    item->inv_flags |= reason;
    /*printf("invalidate %s for item %d, flags %s\n",
           ISSET(reason, ZN_TRANSFO_FLAG)?"TRANSFO":"COORDS", item->id,
           ISSET(item->inv_flags, ZN_TRANSFO_FLAG)?"TRANSFO":"COORDS");*/
    ZnNeedRedisplay(item->wi);
  }
  else if (ISSET(reason, ZN_DRAW_FLAG)) {
    if (ISSET(item->flags, ZN_VISIBLE_BIT)) {
      /*printf("invalidate graphics for item %d\n", item->id);*/
      ZnDamage(item->wi, &item->item_bounding_box);
      ZnNeedRedisplay(item->wi);
#ifdef GL
#ifdef GL_LIST
      /*
       * Remove the item display list so that it will be recreated
       * to reflect the changes.
       */
      if (item->gl_list) {
        glDeleteLists(item->gl_list, 1);
        item->gl_list = 0;
      }
#endif
#endif
    }
  }
}

           
/*
 **********************************************************************************
 *
 * InvalidateItems -- Method
 *      Invalidate the geometric state of all items belonging
 *      to a given class. The search for items starts at group
 *      and proceed depth first.
 *
 **********************************************************************************
 */
static void
InvalidateItems(ZnItem          group,
                ZnItemClass     item_class)
{
  ZnItem        item;

  if (group->class != ZnGroup) {
    return;
  }
  item = ZnGroupHead(group);
  while (item != ZN_NO_ITEM) {
    if (item->class == item_class) {
      Invalidate(item, ZN_COORDS_FLAG);
    }
    else if (item->class == ZnGroup) {
      InvalidateItems(item, item_class);
    }
    item = item->next;
  }
}


/*
 **********************************************************************************
 *
 * ResetTransfo
 * SetTransfo
 * TranslateItem
 * ScaleItem
 * SkewItem
 * RotateItem -- Methods
 *      Set of functions that deal with item transform. They take care
 *      of all details including managing NULL transforms and invalidating
 *      the item hierarchy.
 *
 **********************************************************************************
 */
static void
ResetTransfo(ZnItem     item)
{
  if (item->transfo) {
    ZnFree(item->transfo);
    item->transfo = NULL;
  }
  Invalidate(item, ZN_TRANSFO_FLAG);
}


static void
SetTransfo(ZnItem       item,
           ZnTransfo    *t)
{
  if (item->transfo) {
    ZnFree(item->transfo);
  }
  if (!t || ZnTransfoIsIdentity(t)) {
    item->transfo = NULL;
  }
  else {
    item->transfo = ZnTransfoDuplicate(t);
  }
  Invalidate(item, ZN_TRANSFO_FLAG);
}


static void
TranslateItem(ZnItem    item,
              ZnReal    dx,
              ZnReal    dy,
              ZnBool    abs)
{
  if (!item->transfo) {
    item->transfo = ZnTransfoNew();
  }
  ZnTranslate(item->transfo, dx, dy, abs);
  Invalidate(item, ZN_TRANSFO_FLAG);
}


static void
ScaleItem(ZnItem        item,
          ZnReal        sx,
          ZnReal        sy,
          ZnPoint       *p)
{
  if (!item->transfo) {
    item->transfo = ZnTransfoNew();
  }
  if (p) {
    ZnTranslate(item->transfo, -p->x, -p->y, False);
  }
  ZnScale(item->transfo, sx, sy);
  if (p) {
    ZnTranslate(item->transfo, p->x, p->y, False);
  }
  Invalidate(item, ZN_TRANSFO_FLAG);
}


static void
SkewItem(ZnItem item,
         ZnReal x_skew,
         ZnReal y_skew)
{
  if (!item->transfo) {
    item->transfo = ZnTransfoNew();
  }
  ZnSkewRad(item->transfo, x_skew, y_skew);
  Invalidate(item, ZN_TRANSFO_FLAG);
}


static void
RotateItem(ZnItem       item,
           ZnReal       angle,
           ZnBool       deg,
           ZnPoint      *p)
{
  if (!item->transfo) {
    item->transfo = ZnTransfoNew();
  }
  if (p) {
    ZnTranslate(item->transfo, -p->x, -p->y, False);
  }
  if (deg) {
    ZnRotateDeg(item->transfo, angle);
  }
  else {
    ZnRotateRad(item->transfo, angle);
  }
  if (p) {
    ZnTranslate(item->transfo, p->x, p->y, False);
  }

  Invalidate(item, ZN_TRANSFO_FLAG);
}


/*
 **********************************************************************************
 *
 * DestroyItem -- Method
 *
 **********************************************************************************
 */
static void
DestroyItem(ZnItem      item)
{
  ZnWInfo       *wi = item->wi;
  ZnTextInfo    *ti = &wi->text_info;

  /*
   * Extract it from its group.
   */
  ExtractItem(item);
  
  /*
   * Update state variables to prevent dangling pointers.
   */
  if (wi->current_item == item) {
    wi->current_item = ZN_NO_ITEM;
    wi->current_part = ZN_NO_PART;
  }
  if (wi->new_item == item) {
    wi->new_item = ZN_NO_ITEM;
    wi->new_part = ZN_NO_PART;
  }
  if ((wi->hot_item == item) || (wi->hot_prev) == item) {
    wi->hot_item = ZN_NO_ITEM;
  }
  if (ti->sel_item == item) {
    ti->sel_item = ZN_NO_ITEM;
    ti->sel_field = ZN_NO_PART;
  }
  if (ti->anchor_item == item) {
    ti->anchor_item = ZN_NO_ITEM;
    ti->anchor_field = ZN_NO_PART;
  }
  if (wi->focus_item == item) {
    wi->focus_item = ZN_NO_ITEM;
    wi->focus_field = ZN_NO_PART;
  }

  /*
   * Call per class removal code.
   */
  (item->class->Destroy)(item);
  /*
   * Free the transform if any.
   */
  if (item->transfo) {
    ZnFree(item->transfo);
  }
  /*
   * Remove the item from the item table and free
   * all its tags.
   */
  FreeId(item);
  FreeTags(item);
  /*
   * Free the item own memory
   */
  ZnFree(item);
  wi->num_items--;
}


/*
 **********************************************************************************
 *
 * Generic methods on items --
 *
 **********************************************************************************
 */

struct _ZnITEM ZnITEM = {
  CloneItem,
  DestroyItem,
  ConfigureItem,
  QueryItem,
  InsertItem,
  UpdateItemPriority,
  UpdateItemDependency,
  ExtractItem,
  SetId,
  FreeId,
  AddTag,
  RemoveTag,
  FreeTags,
  HasTag,
  ResetTransfo,
  SetTransfo,
  TranslateItem,
  ScaleItem,
  SkewItem,
  RotateItem,
  Invalidate,
  InvalidateItems,
  GetItemTransform
};

Added jni/tkzinc/generic/Item.h.



























































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/*
 * Item.h -- Header to access items' common state and functions.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1996 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Item_h
#define _Item_h


#include "PostScript.h"
#include "Attrs.h"
#include "Types.h"
#include "List.h"
#include "Field.h"

#include <X11/Xlib.h>
#include <tkInt.h>


/*
 * Types and constants for attribute processing.
 */
typedef struct _ZnAttrConfig {
  int   type;
  char  *name;
  Tk_Uid uid;
  int   offset;
  int   bool_bit;
  int   flags;
  ZnBool read_only;
} ZnAttrConfig;

/*
 * When adding new type in the following enum
 * do not forget to update attribute_type_strings
 * in Item.c.
 */
#define ZN_CONFIG_END           0
#define ZN_CONFIG_BOOL          1
#define ZN_CONFIG_BITMAP        2
#define ZN_CONFIG_BITMAP_LIST   3
#define ZN_CONFIG_STRING        4
#define ZN_CONFIG_FONT          5
#define ZN_CONFIG_EDGE_LIST     6
#define ZN_CONFIG_RELIEF        7
#define ZN_CONFIG_DIM           8
#define ZN_CONFIG_PRI           9
#define ZN_CONFIG_ALIGNMENT     10
#define ZN_CONFIG_AUTO_ALIGNMENT 11
#define ZN_CONFIG_LINE_END      12
#define ZN_CONFIG_LABEL_FORMAT  13
#define ZN_CONFIG_LINE_STYLE    14
#define ZN_CONFIG_LINE_SHAPE    15
#define ZN_CONFIG_ITEM          16
#define ZN_CONFIG_ANGLE         17
#define ZN_CONFIG_INT           18
#define ZN_CONFIG_UINT          19
#define ZN_CONFIG_POINT         20
#define ZN_CONFIG_ANCHOR        21
#define ZN_CONFIG_TAG_LIST      22
#define ZN_CONFIG_MAP_INFO      23
#define ZN_CONFIG_IMAGE         24
#define ZN_CONFIG_LEADER_ANCHORS 25
#define ZN_CONFIG_JOIN_STYLE    26
#define ZN_CONFIG_CAP_STYLE     27
#define ZN_CONFIG_GRADIENT      28
#define ZN_CONFIG_GRADIENT_LIST 29
#define ZN_CONFIG_WINDOW        30
#define ZN_CONFIG_ALPHA         31
#define ZN_CONFIG_FILL_RULE     32
#define ZN_CONFIG_SHORT         33
#define ZN_CONFIG_USHORT        34
#define ZN_CONFIG_CHAR          35
#define ZN_CONFIG_UCHAR         36

#define ZN_DRAW_FLAG    1 << 0
#define ZN_COORDS_FLAG  1 << 1
#define ZN_TRANSFO_FLAG 1 << 2
#define ZN_REPICK_FLAG  1 << 3
#define ZN_BORDER_FLAG  1 << 4
#define ZN_CLFC_FLAG    1 << 5  /* Clear Label Format Cache. */
#define ZN_IMAGE_FLAG   1 << 6  /* Update image pointer. */
#define ZN_VIS_FLAG     1 << 7  /* Visibility has changed. */
#define ZN_MOVED_FLAG   1 << 8  /* Item has moved. */
#define ZN_ITEM_FLAG    1 << 9  /* Signal a change in an item type attribute. */
#define ZN_MAP_INFO_FLAG 1 << 10/* Update mapinfo pointer. */
#define ZN_LAYOUT_FLAG  1 << 11 /* A layout need update. */
#define ZN_POLAR_FLAG   1 << 12 /* Signal a cartesian to polar change. */
#define ZN_CARTESIAN_FLAG 1 << 13       /* Signal a polar to cartesian change. */
#define ZN_TILE_FLAG    1 << 14 /* Update tile pointer. */
#define ZN_WINDOW_FLAG  1 << 15 /* Signal a change in a window type attribute. */


/*
 * This constant marks a non existant item
*/
#define ZN_NO_ITEM              NULL

/*
 * Constants for item parts. The item indexable parts (named fields) are coded
 * as positive or null integers. The item specific parts (not indexable) are
 * coded as negatives beginning at -2 up to -9 which is the current limit. The
 * -1 value is reserved to indicate no part.
 */
#define ZnPartToBit(part)       (1 << (ABS(part)-2))
#define ZN_NO_PART              -1

/*
 * Some flags macros.
 */
#define ISSET(var, mask)        ((var) & (mask))
#define ISCLEAR(var, mask)      (((var) & (mask)) == 0)
#define SET(var,mask)           ((var) |= (mask))
#define CLEAR(var, mask)        ((var) &= ~(mask))
#define ASSIGN(var, mask, bool) ((bool) ? SET((var), (mask)) : CLEAR((var), (mask)))

/*
 * Item flags values.
 */
#define ZN_VISIBLE_BIT          (1<<0)
#define ZN_SENSITIVE_BIT        (1<<1)
#define ZN_CATCH_EVENT_BIT      (1<<2)
#define ZN_UPDATE_DEPENDENT_BIT (1<<3)
#define ZN_COMPOSE_SCALE_BIT    (1<<4)
#define ZN_COMPOSE_ROTATION_BIT (1<<5)
#define ZN_COMPOSE_ALPHA_BIT    (1<<6)
/*
 * Must be kept one greater than the last flag shift count.
 */
#define ZN_PRIVATE_FLAGS_OFFSET 7


/*
 * Operator constants for the coord method.
 */
#define ZN_COORDS_READ          0
#define ZN_COORDS_READ_ALL      1
#define ZN_COORDS_REPLACE       2
#define ZN_COORDS_REPLACE_ALL   3
#define ZN_COORDS_ADD           4
#define ZN_COORDS_ADD_LAST      5
#define ZN_COORDS_REMOVE        6
  

struct _ZnWInfo;
struct _ZnTransfo;

/*
 * Item record header --
 */
typedef struct _ZnItemStruct {
  /* Private data */
  unsigned int          id;
  ZnList                tags;
  struct _ZnWInfo       *wi;                    /* The widget this item is on   */
  struct _ZnItemClassStruct *class;             /* item class                   */
  struct _ZnItemStruct  *previous;              /* previous item in group list  */
  struct _ZnItemStruct  *next;                  /* next item in group list      */
  struct _ZnItemStruct  *parent;
  ZnBBox                item_bounding_box;      /* device item bounding box     */

  /* Common attributes */
  unsigned short        flags;                  
  unsigned short        part_sensitive;         /* Currently limited to 16 parts per item */
  unsigned short        inv_flags;
  unsigned short        priority;
  struct _ZnTransfo     *transfo;
  struct _ZnItemStruct  *connected_item;        /* Item this item is connected to       */
#ifdef GL
#ifdef GL_LIST
  GLuint                gl_list;                /* Display list storing the item graphics */
#endif
#endif
} ZnItemStruct, *ZnItem;

typedef struct _ZnToAreaStruct {
  Tk_Uid        tag_uid;
  ZnBool        enclosed;
  ZnItem        in_group;
  ZnBool        report;
  ZnBool        recursive;
  ZnBool        override_atomic;
  ZnBBox        *area;
} ZnToAreaStruct, *ZnToArea;

typedef struct _ZnPickStruct {
  int           aperture;
  ZnItem        in_group;
  ZnItem        start_item;
  ZnBool        recursive;
  ZnBool        override_atomic;
  ZnPoint       *point;
  ZnItem        a_item;
  int           a_part;
} ZnPickStruct, *ZnPick;


/*
 * Item class record --
 */
typedef int (*ZnItemInitMethod)(ZnItem item, int *argc, Tcl_Obj *CONST *args[]);
typedef int (*ZnItemConfigureMethod)(ZnItem item, int argc, Tcl_Obj *CONST args[],
                                     int *flags);
typedef int (*ZnItemQueryMethod)(ZnItem item, int argc, Tcl_Obj *CONST args[]);
typedef void (*ZnItemCloneMethod)(ZnItem item);
typedef void (*ZnItemDestroyMethod)(ZnItem item);
typedef void (*ZnItemDrawMethod)(ZnItem item);
typedef void (*ZnItemPreRenderMethod)(ZnItem item);
typedef void (*ZnItemRenderMethod)(ZnItem item);
typedef void (*ZnItemComputeCoordinatesMethod)(ZnItem item, ZnBool force);
typedef int (*ZnItemToAreaMethod)(ZnItem item, ZnToArea ta);
typedef ZnReal (*ZnItemPickMethod)(ZnItem item, ZnPick ps);
typedef ZnBool (*ZnItemIsSensitiveMethod)(ZnItem item, int part);
typedef struct _ZnFieldSetStruct* (*ZnItemGetFieldSetMethod)(ZnItem item);
typedef int (*ZnItemContourMethod)(ZnItem item, int cmd, int index, ZnPoly *poly);
typedef void (*ZnItemPickVertexMethod)(ZnItem item, ZnPoint *p, int *contour,
                                       int *vertex, int *o_vertex);
typedef void (*ZnItemGetAnchorMethod)(ZnItem item, Tk_Anchor anchor, ZnPoint *p);
typedef ZnBool (*ZnItemGetClipVerticesMethod)(ZnItem item, ZnTriStrip *tristrip);
typedef ZnBool (*ZnItemGetContoursMethod)(ZnItem item, ZnPoly *poly);
typedef int (*ZnItemCoordsMethod)(ZnItem item, int contour, int index, int cmd,
                                  ZnPoint **points, char **controls, unsigned int *num_points);
typedef void (*ZnItemInsertCharsMethod)(ZnItem item, int field, int *index,
                                        char *chars);
typedef void (*ZnItemDeleteCharsMethod)(ZnItem item, int field, int *first,
                                        int *last);
typedef void (*ZnItemCursorMethod)(ZnItem item, int field, int index);
typedef int (*ZnItemIndexMethod)(ZnItem item, int field, Tcl_Obj *index_spec,
                                 int *index);
typedef int (*ZnItemPartMethod)(ZnItem item, Tcl_Obj **part_spec, int *part);
typedef int (*ZnItemSelectionMethod)(ZnItem item, int field, int offset,
                                     char *chars, int max_chars);
typedef int (*ZnItemPostScriptMethod)(ZnItem item, ZnBool prepass, ZnBBox *area);


typedef void    *ZnItemClassId;

#define ZN_CLASS_HAS_ANCHORS    (1<<0)
#define ZN_CLASS_ONE_COORD      (1<<1)

typedef struct _ZnItemClassStruct {
  char                          *name;
  unsigned int                  size;
  ZnAttrConfig                  *attr_desc;
  unsigned int                  num_parts;      /* 0 if no special parts, else
                                                 * gives how many parts exist. */
  int                           flags;          /* HAS_ANCHORS, ONE_COORD */
  int                           pos_offset;     /* Offset of -position attrib, */
                                                /* if any, -1 otherwise. */
  ZnItemInitMethod              Init;
  ZnItemCloneMethod             Clone;
  ZnItemDestroyMethod           Destroy;
  ZnItemConfigureMethod         Configure;
  ZnItemQueryMethod             Query;
  ZnItemGetFieldSetMethod       GetFieldSet;
  ZnItemGetAnchorMethod         GetAnchor;
  ZnItemGetClipVerticesMethod   GetClipVertices;
  ZnItemGetContoursMethod       GetContours;
  ZnItemCoordsMethod            Coords;
  ZnItemInsertCharsMethod       InsertChars;
  ZnItemDeleteCharsMethod       DeleteChars;
  ZnItemCursorMethod            Cursor;
  ZnItemIndexMethod             Index;
  ZnItemPartMethod              Part;
  ZnItemSelectionMethod         Selection;
  ZnItemContourMethod           Contour;
  ZnItemComputeCoordinatesMethod ComputeCoordinates;
  ZnItemToAreaMethod            ToArea;
  ZnItemDrawMethod              Draw;
  ZnItemPreRenderMethod         PreRender;
  ZnItemRenderMethod            Render;
  ZnItemIsSensitiveMethod       IsSensitive;
  ZnItemPickMethod              Pick;
  ZnItemPickVertexMethod        PickVertex;
  ZnItemPostScriptMethod        PostScript;
} ZnItemClassStruct, *ZnItemClass;


/*
 **********************************************************************************
 *
 * Generic methods for all items.
 *
 **********************************************************************************
 */
extern struct _ZnITEM {
  ZnItem (*CloneItem)(ZnItem model);
  void (*DestroyItem)(ZnItem item);
  int (*ConfigureItem)(ZnItem item, int field, int argc, Tcl_Obj *CONST args[],
                       ZnBool init);
  int (*QueryItem)(ZnItem item, int field, int argc, Tcl_Obj *CONST args[]);
  void (*InsertItem)(ZnItem item, ZnItem group, ZnItem mark_item, ZnBool before);
  void (*UpdateItemPriority)(ZnItem item, ZnItem mark_item, ZnBool before);
  void (*UpdateItemDependency)(ZnItem item, ZnItem old_connection);
  void (*ExtractItem)(ZnItem item);
  void (*SetId)(ZnItem item);
  void (*FreeId)(ZnItem item);
  void (*AddTag)(ZnItem item, Tk_Uid tag);
  void (*RemoveTag)(ZnItem item, Tk_Uid tag);
  void (*FreeTags)(ZnItem item);
  ZnBool (*HasTag)(ZnItem item, Tk_Uid tag);
  void (*ResetTransfo)(ZnItem item);
  void (*SetTransfo)(ZnItem item, struct _ZnTransfo *t);
  void (*TranslateItem)(ZnItem item, ZnReal tx, ZnReal ty, ZnBool abs);
  void (*ScaleItem)(ZnItem item, ZnReal sx, ZnReal sy, ZnPoint *p);
  void (*SkewItem)(ZnItem item, ZnReal x_skew, ZnReal y_skew);
  void (*RotateItem)(ZnItem item, ZnReal angle, ZnBool deg, ZnPoint *p);
  void (*Invalidate)(ZnItem item, int reason);
  void (*InvalidateItems)(ZnItem group, ZnItemClass item_class);
  void (*GetItemTransform)(ZnItem item, struct _ZnTransfo *t);
} ZnITEM;


/*
 **********************************************************************************
 *
 * Methods defined in Item.c useful for writing items.
 *
 **********************************************************************************
 */
void ZnItemInit();
ZnItem ZnCreateItem(struct _ZnWInfo *wi, ZnItemClass item_class,
                  int *argc, Tcl_Obj *CONST *args[]);
void ZnAddItemClass(ZnItemClass class);
ZnItemClass ZnLookupItemClass(char *class_name);
ZnList ZnItemClassList();
int ZnConfigureAttributes(struct _ZnWInfo *wi, ZnItem item, void *record,
                          ZnAttrConfig *attr_desc, int argc, Tcl_Obj *CONST args[],
                          int *flags);
int ZnAttributesInfo(Tcl_Interp *interp, void *record,
                     ZnAttrConfig *attr_desc, int argc, Tcl_Obj *CONST args[]);
int ZnQueryAttribute(Tcl_Interp *interp, void *record, ZnAttrConfig *attr_desc,
                     Tcl_Obj *attr_name);
void ZnInitTransformStack(struct _ZnWInfo *wi);
void ZnFreeTransformStack(struct _ZnWInfo *wi);
void ZnResetTransformStack(struct _ZnWInfo *wi);
void ZnPushTransform(struct _ZnWInfo *wi, struct _ZnTransfo *transfo,
                     ZnPoint *pos, ZnBool compose_scale, ZnBool compose_rot);
void ZnPopTransform(struct _ZnWInfo *wi);
void ZnInitClipStack(struct _ZnWInfo *wi);
void ZnFreeClipStack(struct _ZnWInfo *wi);
void ZnResetClipStack(struct _ZnWInfo *wi);
void ZnPushClip(struct _ZnWInfo *wi, ZnTriStrip *tristrip, ZnBool simple,
                ZnBool set_gc);
void ZnPopClip(struct _ZnWInfo *wi, ZnBool set_gc);
ZnBool ZnCurrentClip(struct _ZnWInfo *wi, TkRegion *reg, ZnBBox **clip_box,
                     ZnBool *simple);
void ZnUpdateItemImage(void *client_data);


extern CONST ZnItemClassId    ZnArc;
extern CONST ZnItemClassId    ZnMap;
extern CONST ZnItemClassId    ZnTabular;
extern CONST ZnItemClassId    ZnCurve;
extern CONST ZnItemClassId    ZnBezier;
extern CONST ZnItemClassId    ZnTriangles;
extern CONST ZnItemClassId    ZnRectangle;
extern CONST ZnItemClassId    ZnReticle;
extern CONST ZnItemClassId    ZnTrack;
extern CONST ZnItemClassId    ZnWayPoint;
extern CONST ZnItemClassId    ZnGroup;
extern CONST ZnItemClassId    ZnIcon;
extern CONST ZnItemClassId    ZnText;
extern CONST ZnItemClassId    ZnWindow;
extern CONST ZnItemClassId    ZnViewport;


#endif  /* _Item_h */

Added jni/tkzinc/generic/List.c.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
/*
 * List.c -- Implementation of list module.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Tue Mar 15 17:18:17 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


/*
 **********************************************************************************
 * 
 * This modules exports the following functions:
 *      - ZnListNew
 *      - ZnListDuplicate
 *      - ZnListEmpty
 *      - ZnListFromArray
 *      - ZnListArray
 *      - ZnListFree
 *      - ZnListSize
 *      - ZnListAssertSize
 *      - ZnListAdd
 *      - ZnListAt
 *      - ZnListAtPut
 *      - ZnListDelete
 *      - ZnListTruncate
 *      - ZnListDetect
 *      - ZnListDo
 *
 * To appear soon:
 *      - ZnListCollect
 *      - ZnListReject
 *
 * And the following variables:
 *
 **********************************************************************************
 */

/*
 **********************************************************************************
 *
 * Included files
 *
 **********************************************************************************
 */

#include "Types.h"
#include "List.h"

#include <stddef.h>
#include <memory.h>
#include <stdlib.h>


/*
 **********************************************************************************
 *
 * Constants
 *
 **********************************************************************************
 */
static const char rcs_id[]="$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";

#define MAX_CHUNCK_SIZE         1024

#ifndef MAX
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif


/*
 **********************************************************************************
 *
 * New types
 *
 **********************************************************************************
 */

typedef struct {
  char          *list;
  unsigned long elem_size;
  unsigned long alloc_size;
  unsigned long used_size;
} _ZnList;


/*
 **********************************************************************************
 *
 * GrowIfNeeded --
 *      Enlarge a list so that it has min_size available. Take care of
 *      static storage.
 *
 **********************************************************************************
 */

static void
GrowIfNeeded(_ZnList      *list,
             unsigned int min_size)
{
  if (list->used_size+min_size <= list->alloc_size) {
    return;
  }
  
  if (list->alloc_size == 0) {
    if (list->list == NULL) {
      /* Normal case if we have created a zero sized list */
      list->alloc_size = min_size;
      list->list = ZnMalloc(list->alloc_size*list->elem_size);
    }
    else {
      /* Case of a list made by ZnListFromArray. If we try to make
         it grow we need to reallocate and copy. */
      char      *new_list;

      list->alloc_size = list->used_size+min_size;
      new_list = ZnMalloc(list->alloc_size*list->elem_size);
      memcpy(new_list,
             list->list,
             list->used_size*list->elem_size);
      list->list = new_list;
    }
  }
  else {
    list->alloc_size = MAX(MIN(list->alloc_size*2, MAX_CHUNCK_SIZE),
                           list->alloc_size+min_size);
    
    list->list = ZnRealloc(list->list,
                           list->alloc_size*list->elem_size);
  }
  
  memset(list->list+(list->used_size*list->elem_size),
         0,
         (list->alloc_size-list->used_size)*list->elem_size);
}


/*
 **********************************************************************************
 *
 * ZnListNew --
 *      Return a new empty list 'initial_size' large.
 *
 **********************************************************************************
 */

ZnList
ZnListNew(unsigned int  initial_size,
          unsigned int  element_size)
{
  _ZnList       *new_list;

  if (element_size == 0) {
    element_size = 1;
  }

  new_list = ZnMalloc(sizeof(_ZnList));

  new_list->alloc_size = initial_size;
  new_list->used_size = 0;
  new_list->elem_size = element_size;

  if (initial_size) {
    unsigned long size = new_list->alloc_size*new_list->elem_size;

    new_list->list = ZnMalloc(size);
    memset(new_list->list, 0, size);
  }
  else {
    new_list->list = NULL;
  }
  
  return (ZnList) new_list;
}


/*
 **********************************************************************************
 *
 * ZnListDuplicate --
 *      Return a copy of the list given as parameter.
 *
 **********************************************************************************
 */

ZnList
ZnListDuplicate(ZnList  list)
{
  _ZnList       *cur_list = (_ZnList *) list;
  _ZnList       *new_list;

  new_list = ZnMalloc(sizeof(_ZnList));

  new_list->alloc_size = cur_list->alloc_size == 0 ? cur_list->used_size :
                                                     cur_list->alloc_size;
  new_list->used_size = cur_list->used_size;
  new_list->elem_size = cur_list->elem_size;

  if (new_list->alloc_size) {
    unsigned long used_size = new_list->used_size*new_list->elem_size;
    unsigned long size = new_list->alloc_size*new_list->elem_size;

    new_list->list = ZnMalloc(size);

    if (used_size) {
      memcpy(new_list->list, cur_list->list, used_size);
    }

    memset(new_list->list + used_size, 0, size - used_size);
  }
  else {
    new_list->list = NULL;
  }
    
  return (ZnList) new_list;
}


/*
 **********************************************************************************
 *
 * ZnListEmpty --
 *      Clear out a list, kkeping its allocated size.
 *
 **********************************************************************************
 */

void
ZnListEmpty(ZnList      list)
{
  _ZnList       *cur_list = (_ZnList *) list;

  cur_list->used_size = 0;
}


/*
 **********************************************************************************
 *
 * ZnListFromArray --
 *      Return a list filled from the given array.
 *
 **********************************************************************************
 */

ZnList
ZnListFromArray(void            *array,
                unsigned int    array_size,
                unsigned int    element_size)
{
  _ZnList       *new_list;

  new_list = (_ZnList *) ZnListNew(0, element_size);
  new_list->list = array;
  new_list->used_size = array_size;
  return (ZnList) new_list;
}


/*
 **********************************************************************************
 *
 * ZnListArray --
 *      Return a pointer to the array containing the list.
 *
 **********************************************************************************
 */

void *
ZnListArray(ZnList      list)
{
  _ZnList       *cur_list = (_ZnList *) list;

  return (void *) cur_list->list;
}


/*
 **********************************************************************************
 *
 * ZnListFree --
 *      Delete a list and free its memory. The entries
 *      still in the list are lost but no further deallocation
 *      is attempted.
 *
 **********************************************************************************
 */

void
ZnListFree(ZnList       list)
{
  _ZnList       *cur_list = (_ZnList *) list;

  if (cur_list->list != NULL && cur_list->alloc_size != 0) {
    ZnFree(cur_list->list);
  }

  ZnFree(cur_list);
}


/*
 **********************************************************************************
 *
 * ZnListSize --
 *      Return the current number of entries kept in list.
 *
 **********************************************************************************
 */

unsigned int
ZnListSize(ZnList       list)
{
  return ((_ZnList *)list)->used_size;
}


/*
 **********************************************************************************
 *
 * ZnListAssertSize --
 *      Set the list length to size.
 *
 **********************************************************************************
 */

void
ZnListAssertSize(ZnList         list,
                 unsigned int   size)
{
  _ZnList       *cur_list = (_ZnList *) list;

  if (cur_list->used_size < size) {
    GrowIfNeeded(cur_list, size - cur_list->used_size);
  }
  cur_list->used_size = size;
}


/*
 **********************************************************************************
 *
 * ZnListCopy --
 *      Destructively copy 'from' into 'to' starting at the first
 *      position. It is the same as saying ZnListEmpty and then
 *      ZnListAppend.
 *
 **********************************************************************************
 */

void
ZnListCopy(ZnList       to,
           ZnList       from)
{
  _ZnList       *to_list = (_ZnList *) to;
  _ZnList       *from_list = (_ZnList *) from;

  if (from_list->elem_size != to_list->elem_size) {
    return;
  }

  to_list->used_size = 0;
  GrowIfNeeded(to_list, from_list->used_size);
  memcpy(to_list->list,
         from_list->list,
         from_list->used_size*from_list->elem_size);
  to_list->used_size = from_list->used_size;
}


/*
 **********************************************************************************
 *
 * ZnListAppend --
 *      Append 'from' at the end of 'to' which is enlarged as needed.
 *
 **********************************************************************************
 */

void
ZnListAppend(ZnList     to,
             ZnList     from)
{
  _ZnList       *to_list = (_ZnList *) to;
  _ZnList       *from_list = (_ZnList *) from;

  if (from_list->elem_size != to_list->elem_size) {
    return;
  }

  GrowIfNeeded(to_list, from_list->used_size);
  memcpy(to_list->list+(to_list->used_size*to_list->elem_size),
         from_list->list,
         from_list->used_size*from_list->elem_size);
  to_list->used_size += from_list->used_size;
}


/*
 **********************************************************************************
 *
 * ZnListAdd --
 *      Add a new entry 'value' in the list before
 *      'index'. 'index' can be the position of a
 *      previous entry or the special values ZnListHead,
 *      ZnListTail. The entries have positions
 *      starting at 0.
 *
 **********************************************************************************
 */

void
ZnListAdd(ZnList        list,
          void          *value,
          unsigned int  index)
{
  _ZnList *cur_list = (_ZnList *) list;
  int     i;

  GrowIfNeeded(cur_list, 1);

  if (index < cur_list->used_size) {
    for (i = cur_list->used_size-1; i >= (int) index; i--) {
      memcpy(cur_list->list+((i+1)*cur_list->elem_size),
             cur_list->list+(i*cur_list->elem_size),
             cur_list->elem_size);
    }
  }
  else if (index > cur_list->used_size) {
    index = cur_list->used_size;
  }
  
  memcpy(cur_list->list+(index*cur_list->elem_size),
         (char *) value,
         cur_list->elem_size);

  (cur_list->used_size)++;
}


/*
 **********************************************************************************
 *
 * ZnListAt --
 *      Return the entry at 'index'. Indices start at 0.
 *      Indices out of the current range are constrained
 *      to fit in the range.
 *
 **********************************************************************************
 */

void *
ZnListAt(ZnList         list,
         unsigned int   index)
{
  if (!((_ZnList *) list)->used_size) {
    return NULL;
  }
  if (index >= ((_ZnList *) list)->used_size) {
    index = ((_ZnList *) list)->used_size - 1;
  }
  
  return (void *) (((_ZnList *) list)->list+(index*((_ZnList *) list)->elem_size));
}


/*
 **********************************************************************************
 *
 * ZnListAtPut --
 *      Set the entry at 'index' to 'value'.
 *      Indices start at 0. Indices out of the current
 *      range are constrained to fit in the range.
 *
 **********************************************************************************
 */

void
ZnListAtPut(ZnList       list,
            void         *value,
            unsigned int index)
{
  if (!((_ZnList *) list)->used_size) {
    return;
  }
  if (index >= ((_ZnList *) list)->used_size) {
    index = ((_ZnList *) list)->used_size - 1;
  }
  
  memcpy(((_ZnList *) list)->list+(index*((_ZnList *) list)->elem_size),
         (char *) value,
         ((_ZnList *) list)->elem_size);
}


/*
 **********************************************************************************
 *
 * ZnListDelete --
 *      Suppress the entry matching value, searching from position 
 *      'index'. If value is NULL suppress entry at index.
 *
 **********************************************************************************
 */

void
ZnListDelete(ZnList             list,
             unsigned int       index)
{
  _ZnList       *cur_list = (_ZnList *) list;
  unsigned int  i;

  if (!((_ZnList *) list)->used_size) {
    return;
  }
  if (index >= ((_ZnList *) list)->used_size) {
    index = ((_ZnList *) list)->used_size - 1;
  }

  for (i = index; i < cur_list->used_size-1; i++) {
    memcpy(cur_list->list+(i*cur_list->elem_size),
           cur_list->list+((i+1)*cur_list->elem_size),
           cur_list->elem_size);
  }
  (cur_list->used_size)--;
}

/*
 **********************************************************************************
 *
 * ZnListTruncate --
 *      Suppress the entries from position 'index' inclusive to the end.
 *
 **********************************************************************************
 */

void
ZnListTruncate(ZnList           list,
               unsigned int     index)
{
  _ZnList       *cur_list = (_ZnList *) list;

  if (index >= ((_ZnList *) list)->used_size) {
    return;
  }

  cur_list->used_size = index;
}

Added jni/tkzinc/generic/List.h.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * List.h -- Header of list module.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Tue Mar 15 17:24:51 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _List_h
#define _List_h


#ifdef __CPLUSPLUS__
extern "C" {
#endif


#define ZnListHead      0
#define ZnListTail      (~(1 << ((8*sizeof(int)) - 1)))


typedef void    *ZnList;


ZnList  ZnListNew(unsigned int  /* initial_size */,
                  unsigned int  /* element_size */);
ZnList  ZnListDuplicate(ZnList  /* list */);
void    ZnListEmpty(ZnList      /* list */);
ZnList  ZnListFromArray(void    * /* array */,
                        unsigned int    /* array_size */,
                        unsigned int    /* element_size */);
void    *ZnListArray(ZnList     /* list */);
void    ZnListFree(ZnList       /* list */);
unsigned int ZnListSize(ZnList  /* list */);
void    ZnListAssertSize(ZnList /* list */,
                         unsigned int   /* size */);
void    ZnListCopy(ZnList       /* to */,
                   ZnList       /* from */);
void    ZnListAppend(ZnList     /* to */,
                     ZnList     /* from */);
void    ZnListAdd(ZnList        /* list */,
                  void          * /* value */,
                  unsigned int  /* index */);
void    *ZnListAt(ZnList        /* list */,
                  unsigned int  /* index */);
void    ZnListAtPut(ZnList              /* list */,
                    void       * /* value */,
                    unsigned int /* index */);
void    ZnListDelete(ZnList             /* list */,
                     unsigned int       /* index */);
void    ZnListTruncate(ZnList           /* list */,
                       unsigned int     /* index */);

#ifdef __CPLUSPLUS__
}
#endif

#endif /* _List_h */

Added jni/tkzinc/generic/Map.c.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
/*
 * Map.c -- Implementation of Map item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Types.h"
#include "MapInfo.h"
#include "Item.h"
#include "Geo.h"
#include "Draw.h"
#include "WidgetInfo.h"
#include "tkZinc.h"
#include "Image.h"

#include <memory.h>
#include <stdio.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 **********************************************************************************
 *
 * Specific Map item record
 *
 **********************************************************************************
 */

typedef struct _MapItemStruct {
  ZnItemStruct  header;
 
  /* Public data */
  ZnBool        filled;
  ZnImage       fill_pattern;
  ZnGradient    *color;
  Tk_Font       text_font;      /* null value -> use zn_map_text_font */
  char          *map_info_name;
  ZnList        symbol_patterns;
  
  /* Private data */
  ZnMapInfoId   map_info;
  ZnList        vectors;
  ZnList        dashed_vectors;
  ZnList        dotted_vectors;
  ZnList        mixed_vectors;
  ZnList        arcs;
  ZnList        dashed_arcs;
  ZnList        dotted_arcs;
  ZnList        mixed_arcs;
  ZnList        marks;
  ZnList        symbols;
  ZnList        texts;
#ifdef GL
  ZnTexFontInfo *tfi;
#endif
} MapItemStruct, *MapItem;


static ZnAttrConfig     map_attrs[] = {
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(MapItemStruct, header.flags), ZN_CATCH_EVENT_BIT, ZN_REPICK_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-color", NULL,
    Tk_Offset(MapItemStruct, color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(MapItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(MapItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(MapItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-filled", NULL,
    Tk_Offset(MapItemStruct, filled), 1, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
    Tk_Offset(MapItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_FONT, "-font", NULL,
    Tk_Offset(MapItemStruct, text_font), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_MAP_INFO, "-mapinfo", NULL,
    Tk_Offset(MapItemStruct, map_info_name), 0,
    ZN_COORDS_FLAG|ZN_MAP_INFO_FLAG, False },
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(MapItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(MapItemStruct, header.flags), ZN_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BITMAP_LIST, "-symbols", NULL,
    Tk_Offset(MapItemStruct, symbol_patterns), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(MapItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(MapItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
    
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


void
UpdateMapInfo(ClientData        client_data,
              ZnMapInfoId       map_info)
{
  ZnItem        item = (ZnItem) client_data;

  /*printf("updating a map 'cause of a change in mapinfo\n");*/
  ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
}


static void
FreeLists(MapItem       map)
{
  if (map->vectors) {
    ZnListFree(map->vectors);
  }
  map->vectors = NULL;
  if (map->dashed_vectors) {
    ZnListFree(map->dashed_vectors);
  }
  map->dashed_vectors = NULL;
  if (map->dotted_vectors) {
    ZnListFree(map->dotted_vectors);
  }
  map->dotted_vectors = NULL;
  if (map->mixed_vectors) {
    ZnListFree(map->mixed_vectors);
  }
  map->mixed_vectors = NULL;
  
  if (map->arcs) {
    ZnListFree(map->arcs);
  }
  map->arcs = NULL;
  if (map->dashed_arcs) {
    ZnListFree(map->dashed_arcs);
  }
  map->dashed_arcs = NULL;
  if (map->dotted_arcs) {
    ZnListFree(map->dotted_arcs);
  }
  map->dotted_arcs = NULL;
  if (map->mixed_arcs) {
    ZnListFree(map->mixed_arcs);
  }
  map->mixed_arcs = NULL;
  
  if (map->marks) {
    ZnListFree(map->marks);
  }
  map->marks = NULL;
  
  if (map->symbols) {
    ZnListFree(map->symbols);
  }
  map->symbols = NULL;
  
  if (map->texts) {
    ZnListFree(map->texts);
  }
  map->texts = NULL;
}


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  MapItem       map  = (MapItem) item;
  ZnWInfo       *wi = item->wi;

  SET(item->flags, ZN_VISIBLE_BIT);
  CLEAR(item->flags, ZN_SENSITIVE_BIT);
  CLEAR(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->part_sensitive = 0;
  item->priority = 0;
  map->filled = False;
  map->fill_pattern = ZnUnspecifiedImage; 
  map->symbol_patterns = NULL;
  map->color = ZnGetGradientByValue(wi->fore_color);
  map->text_font = Tk_GetFont(wi->interp, wi->win,
                              Tk_NameOfFont(wi->map_text_font));
#ifdef GL
  map->tfi = NULL;
#endif

  map->map_info_name = NULL;
  map->map_info = NULL;

  map->vectors = NULL;
  map->dashed_vectors = NULL;
  map->dotted_vectors = NULL;
  map->mixed_vectors = NULL;
  map->arcs = NULL;
  map->dashed_arcs = NULL;
  map->dotted_arcs = NULL;
  map->mixed_arcs = NULL;
  map->marks = NULL;
  map->symbols = NULL;
  map->texts = NULL;
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */

static void
Clone(ZnItem    item)
{
  MapItem       map  = (MapItem) item;
  ZnWInfo       *wi = item->wi;
  
  if (map->vectors) {
    map->vectors = ZnListDuplicate(map->vectors);
  }
  if (map->dashed_vectors) {
    map->dashed_vectors = ZnListDuplicate(map->dashed_vectors);
  }
  if (map->dotted_vectors) {
    map->dotted_vectors = ZnListDuplicate(map->dotted_vectors);
  }
  if (map->mixed_vectors) {
    map->mixed_vectors = ZnListDuplicate(map->mixed_vectors);
  }
  
  if (map->arcs) {
    map->arcs = ZnListDuplicate(map->arcs);
  }
  if (map->dashed_arcs) {
    map->dashed_arcs = ZnListDuplicate(map->dashed_arcs);
  }
  if (map->dotted_arcs) {
    map->dotted_arcs = ZnListDuplicate(map->dotted_arcs);
  }
  if (map->mixed_arcs) {
    map->mixed_arcs = ZnListDuplicate(map->mixed_arcs);
  }
  
  if (map->marks) {
    map->marks = ZnListDuplicate(map->marks);
  }
  
  if (map->symbols) {
    map->symbols = ZnListDuplicate(map->symbols);
  }
  
  if (map->texts) {
    map->texts = ZnListDuplicate(map->texts);
  }

  if (map->map_info_name) {
    char *text;
    text = ZnMalloc((strlen(map->map_info_name) + 1) * sizeof(char));
    strcpy(text, map->map_info_name);
    map->map_info_name = text;
    map->map_info = ZnGetMapInfo(wi->interp, map->map_info_name,
                                 UpdateMapInfo, (ClientData) map);
  }
  
  map->color = ZnGetGradientByValue(map->color);
  map->text_font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(map->text_font));
#ifdef GL
  map->tfi = NULL;
#endif
  if (map->fill_pattern != ZnUnspecifiedImage) {
    map->fill_pattern = ZnGetImageByValue(map->fill_pattern, NULL, NULL);
  }
  if (map->symbol_patterns) {
    ZnImage *pats, *new_pats;
    unsigned int i, num_pats;
    
    pats = ZnListArray(map->symbol_patterns);
    num_pats = ZnListSize(map->symbol_patterns);
    map->symbol_patterns = ZnListNew(num_pats, sizeof(ZnImage));
    new_pats = ZnListArray(map->symbol_patterns);
    for (i = 0; i < num_pats; i++) {
      new_pats[i] = ZnGetImageByValue(pats[i], NULL, NULL);
    }
  }
}


/*
 **********************************************************************************
 *
 * Destroy --
 *      Free the Map storage.
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  MapItem       map = (MapItem) item;

  FreeLists(map);
  ZnFreeGradient(map->color);
  Tk_FreeFont(map->text_font);
#ifdef GL
  if (map->tfi) {
    ZnFreeTexFont(map->tfi);
  }
#endif
  if (map->fill_pattern != ZnUnspecifiedImage) {
    ZnFreeImage(map->fill_pattern, NULL, NULL);
    map->fill_pattern = ZnUnspecifiedImage;
  }
  if (map->symbol_patterns) {
    ZnImage *pats;
    int     i, num_pats;

    pats = ZnListArray(map->symbol_patterns);
    num_pats = ZnListSize(map->symbol_patterns);
    for (i = 0; i < num_pats; i++) {
      if (pats[i] != ZnUnspecifiedImage) {
        ZnFreeImage(pats[i], NULL, NULL);
      }
    }
    ZnListFree(map->symbol_patterns);
  }
  if (map->map_info_name) {
    ZnFree(map->map_info_name);
  }
  if (map->map_info != NULL) {
    ZnFreeMapInfo(map->map_info, UpdateMapInfo, (ClientData) map);
  }
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  ZnWInfo       *wi = item->wi;
  MapItem       map = (MapItem) item;
#ifdef GL
  Tk_Font       old_font = map->text_font;
#endif

  if (ZnConfigureAttributes(wi, item, item, map_attrs, argc, argv, flags) == TCL_ERROR) {
    return TCL_ERROR;
  }

#ifdef GL
  if (old_font != map->text_font) {
    if (map->tfi) {
      ZnFreeTexFont(map->tfi);
      map->tfi = NULL;
    }
  }
#endif
  if (ISSET(*flags, ZN_MAP_INFO_FLAG)) {
    ZnMapInfoId map_info;
    ZnBool      error = False;
    
    if (map->map_info_name) {
      map_info = ZnGetMapInfo(wi->interp, map->map_info_name,
                              UpdateMapInfo, (ClientData) map);
      if (!map_info) {
        error = True;
      }
    }
    else {
      map_info = NULL;
    }
    if (!error) {
      if (map->map_info != NULL) {
        ZnFreeMapInfo(map->map_info, UpdateMapInfo, (ClientData) map);
      }
      map->map_info = map_info;
    }
    else {
      return TCL_ERROR;
    }
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, map_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }  

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */

static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo               *wi = item->wi;
  MapItem               map = (MapItem) item;
  ZnMapInfoId           map_info;
  ZnMapInfoLineStyle    line_style;
  ZnMapInfoTextStyle    text_style;
  char                  symbol;
  char                  *text;
  unsigned int          i, j, cnt;
  unsigned int          num_points;
  unsigned int          num_dashed_points;
  unsigned int          num_dotted_points;
  unsigned int          num_mixed_points;
  unsigned int          num_arcs;
  unsigned int          num_dashed_arcs;
  unsigned int          num_dotted_arcs;
  unsigned int          num_mixed_arcs;
  unsigned int          num_marks;
  ZnPoint               *vectors, *dashed_vectors, *dotted_vectors;
  ZnPoint               *mixed_vectors, *marks;
  XArc                  *arcs, *dashed_arcs, *dotted_arcs, *mixed_arcs;
  ZnPoint               *symbols, *texts;
  ZnPoint               from, to, center;
  ZnPoint               tmp_from, tmp_to;
  XArc                  arc;
  ZnBBox                bbox, bbox_inter, zn_bbox;
  ZnPos                 x_from_w, y_from_w, x_to_w, y_to_w;
  ZnPos                 start_angle, extend;
  ZnDim                 radius_w, line_width;
  int                   radius;
  ZnPoint               *new_marks;
  unsigned int          n_new_marks;
  Tk_Font               text_font;
  int                   sym_w2=0, sym_h2=0;
  
  ZnResetBBox(&item->item_bounding_box);

  if (map->map_info == NULL) {
    return;
  }

  zn_bbox.orig.x = zn_bbox.orig.y = 0;
  zn_bbox.corner.x = wi->width;
  zn_bbox.corner.y = wi->height;

  map_info = map->map_info;

  num_points            = 0;
  num_dashed_points     = 0;
  num_dotted_points     = 0;
  num_mixed_points      = 0;
  num_marks             = 0;
  num_arcs              = 0;
  num_dashed_arcs       = 0;
  num_dotted_arcs       = 0;
  num_mixed_arcs        = 0;  
  
  /*
   * Experimental code to help trap out of bounds
   * errors occuring as the result of improper use
   * of MapInfo/Map (i.e not doing a configure on
   * the MapInfo attribute after a reconfiguration
   * of the MapInfo. This version is more secure
   * but slower than the previous one.
   */
  /*
   * First discover how many component of each kind
   * there is in the MapInfo.
   */
  cnt = ZnMapInfoNumLines(map_info);
  for (i = 0; i < cnt; i++) {
    ZnMapInfoGetLine(map_info, i, NULL, &line_style, NULL, NULL, NULL, NULL, NULL);
    switch (line_style) {
    case ZnMapInfoLineSimple:
      num_points += 2;
      break;
    case ZnMapInfoLineDashed:
      num_dashed_points += 2;  
      break;
    case ZnMapInfoLineDotted:
      num_dotted_points += 2;  
      break;
    case ZnMapInfoLineMixed:
      num_mixed_points += 2;
      break;
    case ZnMapInfoLineMarked:
      num_points += 2;
      ZnMapInfoGetMarks(map_info, i, NULL, &n_new_marks);
      num_marks += n_new_marks;
      break;
    }
  }

  cnt = ZnMapInfoNumTexts(map_info);
  for (i = 0; i < cnt; i++) {
    ZnMapInfoGetText(map_info, i, NULL, &text_style, &line_style, NULL, NULL, NULL);
    if (text_style == ZnMapInfoUnderlinedText) {
      switch (line_style) {
      case ZnMapInfoLineSimple:
      case ZnMapInfoLineMarked:
        num_points += 2;
        break;
      case ZnMapInfoLineDotted:
        num_dotted_points += 2;
        break;
      case ZnMapInfoLineMixed:
        num_mixed_points += 2;
        break;
      case ZnMapInfoLineDashed:
        num_dashed_points += 2;  
        break;
      }
    }
  }

  cnt = ZnMapInfoNumArcs(map_info);
  for (i = 0; i < cnt; i++) {
    ZnMapInfoGetArc(map_info, i, NULL, &line_style, NULL, NULL, NULL, NULL, NULL, NULL);
    switch (line_style) {
    case ZnMapInfoLineSimple:
    case ZnMapInfoLineMarked:
      num_arcs += 2;
      break;
    case ZnMapInfoLineDotted:
      num_dotted_arcs += 2;
      break;
    case ZnMapInfoLineMixed:
      num_mixed_arcs += 2;
      break;
    case ZnMapInfoLineDashed:
      num_dashed_arcs += 2;
      break;
    }
  }
  
  /*
   * Make sure the various lists are large enough
   * to contain the computed amount of points.
   * Later we will cut them to take into account the
   * clipping and the filled attribute.
   */
  if (!map->vectors) {
    map->vectors = ZnListNew(num_points, sizeof(ZnPoint));
  }
  ZnListAssertSize(map->vectors, num_points);
  if (!map->dashed_vectors) {
    map->dashed_vectors = ZnListNew(num_dashed_points, sizeof(ZnPoint));
  }
  ZnListAssertSize(map->dashed_vectors, num_dashed_points);
  if (!map->dotted_vectors) {
    map->dotted_vectors = ZnListNew(num_dotted_points, sizeof(ZnPoint));
  }
  ZnListAssertSize(map->dotted_vectors, num_dotted_points);
  if (!map->mixed_vectors) {
    map->mixed_vectors = ZnListNew(num_mixed_points, sizeof(ZnPoint));
  }
  ZnListAssertSize(map->mixed_vectors, num_mixed_points);
  if (!map->arcs) {
    map->arcs = ZnListNew(num_arcs, sizeof(XArc));
  }
  ZnListAssertSize(map->arcs, num_arcs);
  if (!map->dashed_arcs) {
    map->dashed_arcs = ZnListNew(num_dashed_arcs, sizeof(XArc));
  }
  ZnListAssertSize(map->dashed_arcs, num_dashed_arcs);
  if (!map->dotted_arcs) {
    map->dotted_arcs = ZnListNew(num_dotted_arcs, sizeof(XArc));
  }
  ZnListAssertSize(map->dotted_arcs, num_dotted_arcs);
  if (!map->mixed_arcs) {
    map->mixed_arcs = ZnListNew(num_mixed_arcs, sizeof(XArc));
  }
  ZnListAssertSize(map->mixed_arcs, num_mixed_arcs);
  if (!map->marks) {
    map->marks = ZnListNew(num_marks, sizeof(ZnPoint));
  }
  ZnListAssertSize(map->marks, num_marks);
  if (!map->symbols) {
    map->symbols = ZnListNew(ZnMapInfoNumSymbols(map_info), sizeof(ZnPoint));
  }
  ZnListAssertSize(map->symbols, ZnMapInfoNumSymbols(map_info));
  if (!map->texts) {
    map->texts = ZnListNew(ZnMapInfoNumTexts(map_info), sizeof(ZnPoint));
  }
  ZnListAssertSize(map->texts, ZnMapInfoNumTexts(map_info));

  /*
   * Ask the pointers to the actual arrays.
   */
  vectors        = (ZnPoint *) ZnListArray(map->vectors);
  dashed_vectors = (ZnPoint *) ZnListArray(map->dashed_vectors);
  dotted_vectors = (ZnPoint *) ZnListArray(map->dotted_vectors);
  mixed_vectors  = (ZnPoint *) ZnListArray(map->mixed_vectors);
  arcs           = (XArc *) ZnListArray(map->arcs);
  dashed_arcs    = (XArc *) ZnListArray(map->dashed_arcs);
  dotted_arcs    = (XArc *) ZnListArray(map->dotted_arcs);
  mixed_arcs     = (XArc *) ZnListArray(map->mixed_arcs);
  marks          = (ZnPoint *) ZnListArray(map->marks);
  symbols        = (ZnPoint *) ZnListArray(map->symbols);
  texts          = (ZnPoint *) ZnListArray(map->texts);

  if (num_marks && (wi->map_distance_symbol != ZnUnspecifiedImage)) {
    ZnSizeOfImage(wi->map_distance_symbol, &sym_w2, &sym_h2);
    sym_w2 = (sym_w2+1)/2;
    sym_h2 = (sym_h2+1)/2;
  }
  /*printf("Map: %d %d %d %d %d, texts: %d, symbols: %d\n", num_points, num_dashed_points, num_dotted_points,
         num_mixed_points, num_marks, ZnMapInfoNumTexts(map_info), ZnMapInfoNumSymbols(map_info));*/
  /*
   * Reset the counts of points to compute the actual
   * counts taking into account the clipping and the
   * filled attribute.
   */
  num_points            = 0;
  num_dashed_points     = 0;
  num_dotted_points     = 0;
  num_mixed_points      = 0;
  num_marks             = 0;
  num_arcs              = 0;
  num_dashed_arcs       = 0;
  num_dotted_arcs       = 0;
  num_mixed_arcs        = 0;  

  cnt = ZnMapInfoNumLines(map_info);
  for (i = 0; i < cnt; i++) {
    ZnMapInfoGetLine(map_info, i, NULL, &line_style, &line_width,
                   &x_from_w, &y_from_w, &x_to_w, &y_to_w);

    tmp_from.x = x_from_w;
    tmp_from.y = y_from_w;
    tmp_to.x = x_to_w;
    tmp_to.y = y_to_w;
    ZnTransformPoint(wi->current_transfo, &tmp_from, &from);
    ZnTransformPoint(wi->current_transfo, &tmp_to, &to);

    /*
     * Skip zero length and outside segments.
     */
    if ((from.x == to.x) && (from.y == to.y)) {
      continue;
    }
    
    if (!map->filled) {
      if (ZnLineInBBox(&from, &to, &zn_bbox) < 0) {
        continue;
      }
    }

    switch (line_style) {
    case ZnMapInfoLineSimple:
      vectors[num_points] = from;
      num_points++;
      vectors[num_points] = to;
      num_points++;
      break;
    case ZnMapInfoLineDashed:
      if (!map->filled) {
        dashed_vectors[num_dashed_points] = from;
        num_dashed_points++;
        dashed_vectors[num_dashed_points] = to;
        num_dashed_points++;
      }
      break;
    case ZnMapInfoLineDotted:
      if (!map->filled) {
        dotted_vectors[num_dotted_points] = from;
        num_dotted_points++;
        dotted_vectors[num_dotted_points] = to;
        num_dotted_points++;
      }
      break;
    case ZnMapInfoLineMixed:
      if (!map->filled) {
        mixed_vectors[num_mixed_points] = from;
        num_mixed_points++;
        mixed_vectors[num_mixed_points] = to;
        num_mixed_points++;
      }
      break;
    case ZnMapInfoLineMarked:
      if (!map->filled) {
        vectors[num_points] = from;
        num_points++;
        vectors[num_points] = to;
        num_points++;
        if (wi->map_distance_symbol != ZnUnspecifiedImage) {
          ZnMapInfoGetMarks(map_info, i, &new_marks, &n_new_marks);
          for (j = 0; j < n_new_marks; j++) {
            /*
             * The transform can be put outside the loop when
             * MapInfo point type is modified to ZnPoint.
             * Will use then ZnTransformPoints.
             */
            tmp_from.x = new_marks[j].x;
            tmp_from.y = new_marks[j].y;
            ZnTransformPoint(wi->current_transfo, &tmp_from, &marks[num_marks]);
            ZnAddPointToBBox(&item->item_bounding_box,
                             marks[num_marks].x-sym_w2, marks[num_marks].y-sym_h2);
            ZnAddPointToBBox(&item->item_bounding_box,
                             marks[num_marks].x+sym_w2, marks[num_marks].x+sym_h2);  
            num_marks++;
          }
        }
      }
      break;
    }
  }
  
  cnt = ZnMapInfoNumArcs(map_info);
  for (i = 0; i < cnt; i++) {
    ZnPoint xp;
    
    ZnMapInfoGetArc(map_info, i, NULL, &line_style, &line_width, 
                  &x_from_w, &y_from_w, &radius_w, &start_angle, &extend);

    tmp_from.x = x_from_w;
    tmp_from.y = y_from_w;
    ZnTransformPoint(wi->current_transfo, &tmp_from, &center);
    tmp_from.x += radius_w;
    tmp_from.y = 0;
    ZnTransformPoint(wi->current_transfo, &tmp_from, &xp);
    radius = ((int) (xp.x - center.x));

    bbox.orig.x = center.x - radius;
    bbox.orig.y = center.y - radius;
    bbox.corner.x = bbox.orig.x + (2 * radius);
    bbox.corner.y = bbox.orig.y + (2 * radius);
    
    /*
     * Skip zero length and outside arcs.
     */
    if (!radius || !extend) {
      continue;
    }
    
    ZnIntersectBBox(&zn_bbox, &bbox, &bbox_inter);
    if (ZnIsEmptyBBox(&bbox_inter)) {
      continue;
    }
    
    arc.x       = (int) (center.x - radius);
    arc.y       = (int) (center.y - radius);
    arc.width   = 2 * radius;
    arc.height  = arc.width;
    arc.angle1  = ((unsigned short) start_angle) * 64;
    arc.angle2  = ((unsigned short) extend) * 64;
    
    switch (line_style) {
    case ZnMapInfoLineSimple:
    case ZnMapInfoLineMarked:
      arcs[num_arcs] = arc;
      num_arcs++;
      
      bbox.orig.x = arc.x;
      bbox.orig.y = arc.y;
      bbox.corner.x = bbox.orig.x + arc.width + 1;
      bbox.corner.y = bbox.orig.y + arc.height + 1;
      ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
      break;
    case ZnMapInfoLineDashed:
      if (!map->filled) {
        dashed_arcs[num_dashed_arcs] = arc;
        num_dashed_arcs++;
        
        bbox.orig.x = arc.x;
        bbox.orig.y = arc.y;
        bbox.corner.x = bbox.orig.x + arc.width + 1;
        bbox.corner.y = bbox.orig.y + arc.height + 1;
        ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
      }
      break;
    case ZnMapInfoLineDotted:
      if (!map->filled) {
        dotted_arcs[num_dotted_arcs] = arc;
        num_dotted_arcs++;
        
        bbox.orig.x = arc.x;
        bbox.orig.y = arc.y;
        bbox.corner.x = bbox.orig.x + arc.width + 1;
        bbox.corner.y = bbox.orig.y + arc.height + 1;
        ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
      }
      break;
    case ZnMapInfoLineMixed:
      if (!map->filled) {
        mixed_arcs[num_mixed_arcs] = arc;
        num_mixed_arcs++;
        
        bbox.orig.x = arc.x;
        bbox.orig.y = arc.y;
        bbox.corner.x = bbox.orig.x + arc.width + 1;
        bbox.corner.y = bbox.orig.y + arc.height + 1;
        ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
      }
      break;
    }
  }
  
  /*
   * Truncate arc lists to the real size.
   */
  ZnListAssertSize(map->arcs, num_arcs);
  ZnListAssertSize(map->dashed_arcs, num_dashed_arcs);
  ZnListAssertSize(map->dotted_arcs, num_dotted_arcs);
  ZnListAssertSize(map->mixed_arcs, num_mixed_arcs);
  
  /* If map is filled, only the vectors description is valid. */
  if (!map->filled) {
    if (map->symbol_patterns) {
      ZnImage sym, *syms = ZnListArray(map->symbol_patterns);
      int     num_syms = ZnListSize(map->symbol_patterns);    

      cnt = ZnMapInfoNumSymbols(map_info);
      for (i = 0; i < cnt; i++) {
        ZnMapInfoGetSymbol(map_info, i, NULL, &x_from_w, &y_from_w, &symbol);
        tmp_from.x = x_from_w;
        tmp_from.y = y_from_w;
        ZnTransformPoint(wi->current_transfo, &tmp_from, &symbols[i]);
        sym = syms[symbol%num_syms];
        if (sym != ZnUnspecifiedImage) {
          ZnSizeOfImage(sym, &sym_w2, &sym_h2);
          sym_w2 = (sym_w2+1)/2;
          sym_h2 = (sym_h2+1)/2;
          ZnAddPointToBBox(&item->item_bounding_box,
                           symbols[i].x-sym_w2, symbols[i].y-sym_h2);
          ZnAddPointToBBox(&item->item_bounding_box,
                           symbols[i].x+sym_w2, symbols[i].y+sym_h2);     
        }
      }
      ZnListAssertSize(map->symbols, cnt);
    }

    cnt = ZnMapInfoNumTexts(map_info);
    text_font = map->text_font ? map->text_font : wi->map_text_font;
    for (i = 0; i < cnt; i++) {
      ZnMapInfoGetText(map_info, i, NULL,
                     &text_style, &line_style, &x_from_w, &y_from_w, &text);
      tmp_from.x = x_from_w;
      tmp_from.y = y_from_w;
      ZnTransformPoint(wi->current_transfo, &tmp_from, &texts[i]);
      ZnAddStringToBBox(&item->item_bounding_box, text, text_font,
                        texts[i].x, texts[i].y);
      
      if (text_style == ZnMapInfoUnderlinedText) {
        ZnGetStringBBox(text, text_font, texts[i].x, texts[i].y, &bbox);
        
        from.x = bbox.orig.x;
        from.y = bbox.corner.y;
        to.x   = bbox.corner.x;
        to.y   = bbox.corner.y;
        
        switch (line_style) {
        case ZnMapInfoLineSimple:
        case ZnMapInfoLineMarked:
          vectors[num_points] = from;
          num_points++;
          vectors[num_points] = to;
          num_points++;
          break;
        case ZnMapInfoLineDashed:
          dashed_vectors[num_dashed_points] = from;
          num_dashed_points++;
          dashed_vectors[num_dashed_points] = to;
          num_dashed_points++;
          break;
        case ZnMapInfoLineDotted:
          dotted_vectors[num_dotted_points] = from;
          num_dotted_points++;
          dotted_vectors[num_dotted_points] = to;
          num_dotted_points++;
          break;
        case ZnMapInfoLineMixed:
          mixed_vectors[num_mixed_points] = from;
          num_mixed_points++;
          mixed_vectors[num_mixed_points] = to;
          num_mixed_points++;
          break;
        }
      }
    }
    ZnListAssertSize(map->texts, cnt);
  }
    
  /*
   * Truncate line lists to the real size.
   */
  ZnListAssertSize(map->vectors, num_points);
  ZnListAssertSize(map->dashed_vectors, num_dashed_points);
  ZnListAssertSize(map->dotted_vectors, num_dotted_points);
  ZnListAssertSize(map->mixed_vectors, num_mixed_points);
  ZnListAssertSize(map->marks, num_marks);
  
  ZnAddPointsToBBox(&item->item_bounding_box,
                    ZnListArray(map->vectors), ZnListSize(map->vectors));
  ZnAddPointsToBBox(&item->item_bounding_box,
                    ZnListArray(map->dashed_vectors), ZnListSize(map->dashed_vectors));
  ZnAddPointsToBBox(&item->item_bounding_box,
                    ZnListArray(map->dotted_vectors), ZnListSize(map->dotted_vectors));
  ZnAddPointsToBBox(&item->item_bounding_box,
                    ZnListArray(map->mixed_vectors), ZnListSize(map->mixed_vectors));
  item->item_bounding_box.orig.x -= 0.5;
  item->item_bounding_box.orig.y -= 0.5;
  item->item_bounding_box.corner.x += 0.5;
  item->item_bounding_box.corner.y += 0.5;
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */

static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  return -1;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */

static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  MapItem       map = (MapItem) item;
  ZnMapInfoId   map_info;
  ZnPoint       *points;
  XPoint        *xpoints;
  XArc          *arcs;
  char          *text;
  char          tmp_str[] = ".";
  XGCValues     values;
  unsigned int  i, cnt;
  ZnDim         line_width_w;
  int           line_width;

  if (map->map_info == NULL) {
    return;
  }

  map_info = map->map_info;

  values.foreground = ZnGetGradientPixel(map->color, 0.0);

  if (map->filled) {
    if (ZnListSize(map->vectors) || ZnListSize(map->arcs)) {
      if (map->fill_pattern == ZnUnspecifiedImage) { /* Fill solid */
        values.fill_style = FillSolid;
        XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values);
      }
      else { /* Fill stippled */
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(map->fill_pattern, wi->win);
        XChangeGC(wi->dpy, wi->gc,
                  GCFillStyle | GCStipple | GCForeground, &values);
      }
      
      cnt = ZnListSize(map->vectors);
      if (cnt) {
        ZnListAssertSize(ZnWorkXPoints, cnt);
        xpoints = (XPoint *) ZnListArray(ZnWorkXPoints);
        points = (ZnPoint *) ZnListArray(map->vectors);
        for (i = 0; i < cnt; i++) {
          xpoints[i].x = (int) points[i].x;
          xpoints[i].y = (int) points[i].y;
        }
        XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, (int) cnt,
                     Nonconvex, CoordModeOrigin);
      }
      
      if (ZnListSize(map->arcs)) {
        arcs = ZnListArray(map->arcs);
        cnt = ZnListSize(map->arcs);
        for (i = 0; i < cnt; i++, arcs++) {
          XFillArc(wi->dpy, wi->draw_buffer, wi->gc,
                   arcs->x, arcs->y, arcs->width, arcs->height,
                   arcs->angle1, arcs->angle2);
        }
      }
    }
  }
  else { /* Not filled */
    
    if (ZnListSize(map->vectors)) {
      ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc,
                GCFillStyle | GCLineWidth | GCForeground, &values);

      /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
         in releases R4 and older */
      /*      XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
                    (XSegment *) ZnListArray(map->vectors),
                    ZnListSize(map->vectors)/2);*/
      cnt = ZnListSize(map->vectors);
      points = (ZnPoint *) ZnListArray(map->vectors);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL,
                         NULL, NULL, NULL);
          line_width = (int) line_width_w;
          if (line_width != values.line_width) {
            values.line_width = line_width;
            XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
          }
          /*printf("Dessin d'une ligne de %d %d �%d %d\n",
                 (int)points[i].x, (int)points[i].y,
                 (int)points[i+1].x, (int)points[i+1].y);*/
          XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
                    (int) points[i].x,
                    (int) points[i].y,
                    (int) points[i+1].x,
                    (int) points[i+1].y);
        }
      }
    }

    if (ZnListSize(map->dashed_vectors)) {
      ZnSetLineStyle(wi, ZN_LINE_DASHED);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      
      /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
         in releases R4 and older */
/*      XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
                    (XSegment *) ZnListArray(map->dashed_vectors), ZnListSize(map->dashed_vectors)/2);*/
      cnt = ZnListSize(map->dashed_vectors);
      points = (ZnPoint *) ZnListArray(map->dashed_vectors);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL, NULL, NULL, NULL);
          line_width = (int) line_width_w;        
          if (line_width != values.line_width) {
            values.line_width = line_width;
            XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
          }
          XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
                    (int) points[i].x,
                    (int) points[i].y,
                    (int) points[i+1].x,
                    (int) points[i+1].y);
        }
      }
    }
    
    if (ZnListSize(map->dotted_vectors)) {
      ZnSetLineStyle(wi, ZN_LINE_DOTTED);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc,
                GCFillStyle | GCLineWidth | GCForeground, &values);
      
      /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
         in releases R4 and older */
/*      XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
                    (XSegment *) ZnListArray(map->dotted_vectors), ZnListSize(map->dotted_vectors)/2);*/
      cnt = ZnListSize(map->dotted_vectors);
      points = (ZnPoint *) ZnListArray(map->dotted_vectors);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL, NULL, NULL, NULL);
          line_width = (int) line_width_w;
          if (line_width != values.line_width) {
            values.line_width = line_width;
            XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
          }
          XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
                    (int) points[i].x,
                    (int) points[i].y,
                    (int) points[i+1].x,
                    (int) points[i+1].y);
        }
      }
    }
    
    if (ZnListSize(map->mixed_vectors)) {
      ZnSetLineStyle(wi, ZN_LINE_MIXED);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      
      /* !! WARNING !! XDrawSegments can't handle an unlimited number of segments
         in releases R4 and older */
      /*XDrawSegments(wi->dpy, wi->draw_buffer, wi->gc,
                    (XSegment *) ZnListArray(map->mixed_vectors), ZnListSize(map->mixed_vectors)/2);*/
      cnt = ZnListSize(map->mixed_vectors);
      points = (ZnPoint *) ZnListArray(map->mixed_vectors);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &line_width_w, NULL, NULL, NULL, NULL);
          line_width = (int) line_width_w;
          if (line_width != values.line_width) {
            values.line_width = line_width;
            XChangeGC(wi->dpy, wi->gc, GCLineWidth, &values);
          }
          XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
                    (int) points[i].x,
                    (int) points[i].y,
                    (int) points[i+1].x,
                    (int) points[i+1].y);
        }
      }
    }
    
    if (ZnListSize(map->arcs)) {
      
      ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      arcs = ZnListArray(map->arcs);
      cnt = ZnListSize(map->arcs);
      for (i = 0; i < cnt; i++, arcs++) {
        XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
                 arcs->x, arcs->y, arcs->width, arcs->height,
                 arcs->angle1, arcs->angle2);
      }
    }
    
    if (ZnListSize(map->dashed_arcs)) {
      
      ZnSetLineStyle(wi, ZN_LINE_DASHED);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      arcs = ZnListArray(map->arcs);
      cnt = ZnListSize(map->arcs);
      for (i = 0; i < cnt; i++, arcs++) {
        XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
                 arcs->x, arcs->y, arcs->width, arcs->height,
                 arcs->angle1, arcs->angle2);
      }
    }
    
    if (ZnListSize(map->dotted_arcs)) {
      
      ZnSetLineStyle(wi, ZN_LINE_DOTTED);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      arcs = ZnListArray(map->arcs);
      cnt = ZnListSize(map->arcs);
      for (i = 0; i < cnt; i++, arcs++) {
        XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
                 arcs->x, arcs->y, arcs->width, arcs->height,
                 arcs->angle1, arcs->angle2);
      }
    }
    
    if (ZnListSize(map->mixed_arcs)) {
      
      ZnSetLineStyle(wi, ZN_LINE_MIXED);
      values.fill_style = FillSolid;
      values.line_width = 1;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      arcs = ZnListArray(map->arcs);
      cnt = ZnListSize(map->arcs);
      for (i = 0; i < cnt; i++, arcs++) {
        XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
                 arcs->x, arcs->y, arcs->width, arcs->height,
                 arcs->angle1, arcs->angle2);
      }
    }
    
    if (ZnListSize(map->texts)) {
      /* For the Tk widget we don't have to bother with old
       * compatibility issues.
       */
      values.font = Tk_FontId(map->text_font);
      values.fill_style = FillSolid;
      XChangeGC(wi->dpy, wi->gc,
                GCFillStyle | GCFont | GCForeground, &values);
      
      cnt = ZnListSize(map->texts);
      points = (ZnPoint *) ZnListArray(map->texts);
      for (i = 0; i < cnt; i++) {
        ZnMapInfoGetText(map_info, i, NULL, NULL, NULL, NULL, NULL, &text);
        Tk_DrawChars(wi->dpy, wi->draw_buffer, wi->gc,
                     map->text_font, text, (int) strlen(text),
                     (int) points[i].x, (int) points[i].y); 
      }
    }
      
    if (ZnListSize(map->symbols) || ZnListSize(map->marks)) {
      int          ox, oy;
      unsigned int w, h;
      ZnImage sym;
      
      values.fill_style = FillStippled;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle, &values);
      
      if (map->symbol_patterns) {
        ZnImage *syms = ZnListArray(map->symbol_patterns);
        int     num_syms = ZnListSize(map->symbol_patterns);
        
        cnt = ZnListSize(map->symbols);
        points = ZnListArray(map->symbols);
        for (i = 0; i < cnt; i++) {
          ZnMapInfoGetSymbol(map_info, i, NULL, NULL, NULL, &(tmp_str[0]));
          sym = syms[tmp_str[0]%num_syms];
          if (sym != ZnUnspecifiedImage) {
            ZnSizeOfImage(sym, (int *) &w, (int *) &h);
            ox = ((int) points[i].x) - w/2;
            oy = ((int) points[i].y) - h/2;
            values.stipple = ZnImagePixmap(sym, wi->win);
            values.ts_x_origin = ox;
            values.ts_y_origin = oy;
            XChangeGC(wi->dpy, wi->gc,
                      GCStipple|GCTileStipXOrigin|GCTileStipYOrigin, &values);
            XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, ox, oy, w, h);
          }
        }
      }

      if (wi->map_distance_symbol != ZnUnspecifiedImage) {
        ZnSizeOfImage(wi->map_distance_symbol, (int *) &w, (int *) &h);
        cnt = ZnListSize(map->marks);
        points = ZnListArray(map->marks);
        values.stipple = ZnImagePixmap(wi->map_distance_symbol, wi->win);
        XChangeGC(wi->dpy, wi->gc, GCStipple, &values);
        for (i = 0; i < cnt; i++) {
          ox = ((int) points[i].x) - w/2;
          oy = ((int) points[i].y) - h/2;
          values.ts_x_origin = ox;
          values.ts_y_origin = oy;
          XChangeGC(wi->dpy, wi->gc, GCTileStipXOrigin|GCTileStipYOrigin, &values);
          XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, ox, oy, w, h);
        }
      }
    }
  }
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
MapRenderVectors(ZnTriStrip *tristrip)
{
  unsigned int  i, j, num_points;
  ZnPoint       *points;

  for (i = 0; i < tristrip->num_strips; i++) {
    num_points = tristrip->strips[i].num_points;
    points = tristrip->strips[i].points;
    if (tristrip->strips[i].fan) {
      glBegin(GL_TRIANGLE_FAN);
    }
    else {
      glBegin(GL_TRIANGLE_STRIP);
    }
    for (j = 0; j < num_points; j++, points++) {
      glVertex2d(points->x, points->y);
    }
    glEnd();
  }
}

static void
Render(ZnItem   item)
{
  ZnWInfo       *wi = item->wi;
  MapItem       map = (MapItem) item;
  ZnMapInfoId   map_info;
  ZnPoint       *points, p;
  char          *text;
  char          tmp_str[] = ".";
  unsigned int  i, cnt;
  int           w, h;
  XColor        *color;
  GLfloat       line_width;
  ZnDim         new_width;
  unsigned short alpha;

  if (!map->map_info) {
    return;
  }

  map_info = map->map_info;
  color = ZnGetGradientColor(map->color, 0.0, &alpha);
  alpha = ZnComposeAlpha(alpha, wi->alpha);
  glColor4us(color->red, color->green, color->blue, alpha);
  if (map->filled) {
    //
    // TODO: This code doesn't handle pattern/tile and filled
    // arcs are not supported. The tesselation data is not
    // cached for future reuse, it is redone for each render
    // pass.
    // Render only vectors
    if (ZnListSize(map->vectors)) {
      ZnTriStrip tristrip;
      GLdouble v[3];
      ZnCombineData *cdata, *cnext;

      line_width = 1.0;
      glLineWidth(line_width);
      ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
      cnt = ZnListSize(map->vectors);
      points = ZnListArray(map->vectors);      

      /* Init our TriStrip */
      tristrip.num_strips = 0;
      tristrip.strips = NULL;

      /* Start tessellation */
      gluTessProperty(ZnTesselator.tess, GLU_TESS_BOUNDARY_ONLY, (GLdouble) GL_FALSE);
      gluTessBeginPolygon(ZnTesselator.tess, &tristrip);
      gluTessBeginContour(ZnTesselator.tess);

      for (i =0; i < cnt; i += 2) {
        v[0] = points[i].x;
        v[1] = points[i].y;
        v[2] = 0;
        gluTessVertex(ZnTesselator.tess, v, &points[i]);
      }
	
      gluTessEndContour(ZnTesselator.tess);
      gluTessEndPolygon(ZnTesselator.tess);
	
      cdata = ZnTesselator.combine_list;
      while (cdata) {
        ZnTesselator.combine_length--;
        cnext = cdata->next;
        ZnFree(cdata);
        cdata = cnext;
      }
      ZnTesselator.combine_list = NULL;
        
      /* Render our vectors*/
      MapRenderVectors(&tristrip);
      ZnTriFree(&tristrip);
    }
  }
  else { /* Not filled */
    if (ZnListSize(map->vectors)) {
      line_width = 1.0;
      glLineWidth(line_width);
      ZnSetLineStyle(wi, ZN_LINE_SIMPLE);
      cnt = ZnListSize(map->vectors);
      points = ZnListArray(map->vectors);
      glBegin(GL_LINES);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
                         NULL, NULL, NULL);
          if (new_width != line_width) {
            line_width = (GLfloat)new_width;
            glLineWidth(line_width);
          }
          glVertex2d(points[i].x, points[i].y);
          glVertex2d(points[i+1].x, points[i+1].y);
        }
      }
      glEnd();
    }
    if (ZnListSize(map->dashed_vectors)) {
      line_width = 1.0;
      glLineWidth(line_width);
      ZnSetLineStyle(wi, ZN_LINE_DASHED);
      cnt = ZnListSize(map->dashed_vectors);
      points = ZnListArray(map->dashed_vectors);
      glBegin(GL_LINES);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
                         NULL, NULL, NULL);
          if (new_width != line_width) {
            line_width = (GLfloat)new_width;
            glLineWidth(line_width);
          }
          glVertex2d(points[i].x, points[i].y);
          glVertex2d(points[i+1].x, points[i+1].y);
        }
      }
      glEnd();
      glDisable(GL_LINE_STIPPLE);
    }
    if (ZnListSize(map->dotted_vectors)) {
      line_width = 1.0;
      glLineWidth(line_width);
      ZnSetLineStyle(wi, ZN_LINE_DOTTED);
      cnt = ZnListSize(map->dotted_vectors);
      points = ZnListArray(map->dotted_vectors);
      glBegin(GL_LINES);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
                         NULL, NULL, NULL);
          if (new_width != line_width) {
            line_width = (GLfloat)new_width;
            glLineWidth(line_width);
          }
          glVertex2d(points[i].x, points[i].y);
          glVertex2d(points[i+1].x, points[i+1].y);
        }
      }
      glEnd();
      glDisable(GL_LINE_STIPPLE);
    }
    if (ZnListSize(map->mixed_vectors)) {
      line_width = 1.0;
      glLineWidth(line_width);
      ZnSetLineStyle(wi, ZN_LINE_MIXED);
      cnt = ZnListSize(map->mixed_vectors);
      points = ZnListArray(map->mixed_vectors);
      glBegin(GL_LINES);
      for (i = 0; i < cnt; i += 2) {
        if (ZnLineInBBox(&points[i], &points[i+1], &wi->damaged_area) >= 0) {
          ZnMapInfoGetLine(map_info, i/2, NULL, NULL, &new_width, NULL,
                         NULL, NULL, NULL);
          if (new_width != line_width) {
            line_width = (GLfloat)new_width;
            glLineWidth(line_width);
          }
          glVertex2d(points[i].x, points[i].y);
          glVertex2d(points[i+1].x, points[i+1].y);
        }
      }
      glEnd();
      glDisable(GL_LINE_STIPPLE);
    }

    if (ZnListSize(map->arcs)) {
      line_width = 1.0;
      glLineWidth(line_width);
    }
    if (ZnListSize(map->dashed_arcs)) {
      line_width = 1.0;
      glLineWidth(line_width);
      glLineStipple(1, 0xF0F0);
      glEnable(GL_LINE_STIPPLE);
      glDisable(GL_LINE_STIPPLE);
    }
    if (ZnListSize(map->dotted_arcs)) {
      line_width = 1.0;
      glLineWidth(line_width);
      glLineStipple(1, 0x18C3);
      glEnable(GL_LINE_STIPPLE);
      glDisable(GL_LINE_STIPPLE);
    }
    if (ZnListSize(map->mixed_arcs)) {
      line_width = 1.0;
      glLineWidth(line_width);
      glLineStipple(1, 0x27FF);
      glEnable(GL_LINE_STIPPLE);
      glDisable(GL_LINE_STIPPLE);
    }

    if (! map->tfi) {
      map->tfi = ZnGetTexFont(wi, map->text_font);
    }
    if (ZnListSize(map->texts) && map->tfi) {
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      glEnable(GL_TEXTURE_2D);
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
      glBindTexture(GL_TEXTURE_2D, ZnTexFontTex(map->tfi));
      cnt = ZnListSize(map->texts);
      points = ZnListArray(map->texts);
      for (i = 0; i < cnt; i++, points++) {
        glPushMatrix();
        ZnMapInfoGetText(map_info, i, NULL, NULL, NULL, NULL, NULL, &text);
        glTranslated(points->x, points->y, 0.0);
        ZnRenderString(map->tfi, (unsigned char *) text, strlen(text));
        glPopMatrix();
      }
      glDisable(GL_TEXTURE_2D);
    }

    if (map->symbol_patterns) {
      ZnImage sym, *syms = ZnListArray(map->symbol_patterns);
      int     num_syms = ZnListSize(map->symbol_patterns);
      
      cnt = ZnListSize(map->symbols);
      points = ZnListArray(map->symbols);
      for (i = 0; i < cnt; i++) {
        ZnMapInfoGetSymbol(map_info, i, NULL, NULL, NULL, &(tmp_str[0]));
        sym = syms[tmp_str[0]%num_syms];
        if (sym != ZnUnspecifiedImage) {
          ZnSizeOfImage(sym, &w, &h);
          p.x = points[i].x-(w+1.0)/2.0;
          p.y = points[i].y-(h+1.0)/2.0;
          ZnRenderIcon(wi, sym, map->color, &p, True);
        }
      }
    }
    
    if (wi->map_distance_symbol != ZnUnspecifiedImage) {
      ZnSizeOfImage(wi->map_distance_symbol, &w, &h);
      cnt = ZnListSize(map->marks);
      points = ZnListArray(map->marks);
      for (i = 0; i < cnt; i++, points++) {
        p.x = points->x-(w+1)/2;
        p.y = points->y-(h+1)/2;
        ZnRenderIcon(wi, wi->map_distance_symbol, map->color, &p, True);
      }
    }
  }
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *      This is *NOT* correct but for now we will tell that we are
 *      transparent even if we are solid filled.
 *
 *      !!!! We need to say we are opaque at least if we are solid
 *      filled. !!!!
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  return 1e40;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */

static CONST ZnItemClassStruct MAP_ITEM_CLASS = {
  "map",
  sizeof(MapItemStruct),
  map_attrs,
  0,                    /* num_parts */
  0,                    /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  NULL,                 /* GetAnchor */
  NULL,                 /* GetClipVertices */
  NULL,                 /* GetContours */
  NULL,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnMap = (ZnItemClassId) &MAP_ITEM_CLASS;

Added jni/tkzinc/generic/MapInfo.c.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
/*
 * MapInfo.c -- MapInfo interface.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : 
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _WIN32
#include <sys/param.h>
#include <netinet/in.h>
#else
#include <winsock2.h>
#endif

#include "MapInfo.h"
#include "tkZinc.h"

#include <memory.h>
#include <math.h>



static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 *-----------------------------------------------------------------------
 *
 * New types
 *
 *-----------------------------------------------------------------------
 */
typedef struct {
  ZnPtr                 tag;
  ZnMapInfoLineStyle    style;
  int                   width;
  ZnPoint               center;
  unsigned int          radius;
  int                   start_angle;
  int                   extend;
} ZnMapInfoArcStruct, *ZnMapInfoArc;

typedef struct {
  ZnPtr                 tag;
  ZnMapInfoLineStyle    style;
  int                   width;
  ZnPoint               from;
  ZnPoint               to;
  unsigned int          num_marks;
  ZnPoint               *marks;
} ZnMapInfoLineStruct, *ZnMapInfoLine;

typedef struct {
  ZnPtr                 tag;
  ZnPoint               at;
  char                  symbol[2];
} ZnMapInfoSymbolStruct, *ZnMapInfoSymbol;

typedef struct {
  ZnPtr                 tag;
  ZnMapInfoTextStyle    text_style;
  ZnMapInfoLineStyle    line_style;
  ZnPoint               at;
  char                  *text;
} ZnMapInfoTextStruct, *ZnMapInfoText;

typedef struct {
  char          *name;
  ZnList        lines;
  ZnList        symbols;
  ZnList        texts;
  ZnList        arcs;
} ZnMapInfoStruct, *ZnMapInfo;


#define MARKERS_SPACING         80.0    /* 10 nautic miles in 1/8 of a mile */
#define BASE_ALLOC_SIZE         8


/*
 *-----------------------------------------------------------------------
 *
 * Macros.
 * 
 *-----------------------------------------------------------------------
 */
#define NOT_MARKED_STYLE(style)                                         \
((style) == ZnMapInfoLineMarked ? ZnMapInfoLineSimple : (style));


/*
 *-----------------------------------------------------------------------
 *
 * ComputeLineMarks --
 *      Add marks to a line in the marks substructure.
 *
 *-----------------------------------------------------------------------
 */

static void
ComputeLineMarks(ZnMapInfoLine  marked_line)
{
  ZnDim length;
  ZnPos x_from = marked_line->from.x;
  ZnPos y_from = marked_line->from.y;
  ZnPos x_to = marked_line->to.x;
  ZnPos y_to = marked_line->to.y;
  ZnPos delta_x = x_from - x_to;
  ZnPos delta_y = y_from - y_to;
  ZnPos step_x, step_y;
  unsigned int  j;

  length = sqrt(delta_x * delta_x + delta_y * delta_y);
  step_x = (x_to - x_from) * MARKERS_SPACING / length;
  step_y = (y_to - y_from) * MARKERS_SPACING / length;
  marked_line->num_marks = (int) (length / MARKERS_SPACING);

  /* We don't want markers at ends, so we get rid of the last one
     if it is at an end */
  if (fmod(length, MARKERS_SPACING) == 0.0) {
    (marked_line->num_marks)--;
  }

  if (marked_line->num_marks) {
    marked_line->marks = ZnMalloc(marked_line->num_marks * sizeof(ZnPoint));
  }
  
  for (j = 0; j < marked_line->num_marks; j++) {
    marked_line->marks[j].x = x_from + ((j + 1) * step_x);
    marked_line->marks[j].y = y_from + ((j + 1) * step_y);
  }
}


static ZnMapInfoId
ZnMapInfoCreate(char    *name)
{
  ZnMapInfo     new_map;

  new_map = ZnMalloc(sizeof(ZnMapInfoStruct));
  memset((char *) new_map, 0, sizeof(ZnMapInfoStruct));
  if (!name) {
    name = "";
  }
  new_map->name = (char *) ZnMalloc(strlen(name)+1);
  /*printf("Nouvelle MapInfo: %s\n", name);*/
  strcpy(new_map->name, name);
  
  return((ZnMapInfoId) new_map);
}


static char *
ZnMapInfoName(ZnMapInfoId       map_info)
{
  if (!map_info) {
    return "";
  }
  return ((ZnMapInfo) map_info)->name;
}


static ZnMapInfoId
ZnMapInfoDuplicate(ZnMapInfoId  map_info)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfo     new_map;
  unsigned int  i, num_lines, num_texts;
  ZnMapInfoText new_texts, cur_texts;
  ZnMapInfoLine new_lines, cur_lines;

  if (!cur_map) {
    return ((ZnMapInfoId) NULL);
  }
  
  new_map = ZnMapInfoCreate(cur_map->name);

  if (cur_map->lines) {
    new_map->lines = ZnListDuplicate(cur_map->lines);

    cur_lines = ZnListArray(cur_map->lines);
    new_lines = ZnListArray(new_map->lines);
    num_lines = ZnListSize(cur_map->lines);

    for (i = 0; i < num_lines; i++) {
      if (new_lines[i].style == ZnMapInfoLineMarked) {
        new_lines[i].marks = ZnMalloc(new_lines[i].num_marks * sizeof(ZnPoint));
        memcpy((char *) new_lines[i].marks,
               (char *) cur_lines[i].marks,
               new_lines[i].num_marks * sizeof(ZnPoint));
      }
    }
  }
  if (cur_map->symbols) {
    new_map->symbols = ZnListDuplicate(cur_map->symbols);
  }
  if (cur_map->texts) {
    new_map->texts = ZnListDuplicate(cur_map->texts);

    cur_texts = ZnListArray(cur_map->texts);
    new_texts = ZnListArray(new_map->texts);
    num_texts = ZnListSize(cur_map->texts);
    
    for (i = 0; i < num_texts; i++) {
      new_texts[i].text = ZnMalloc(strlen(cur_texts[i].text) + 1);
      strcpy(new_texts[i].text, cur_texts[i].text);
    }
  }
  if (cur_map->arcs) {
    new_map->arcs = ZnListDuplicate(cur_map->arcs);
  }

  return((ZnMapInfoId) new_map);
}


static void
ZnMapInfoDelete(ZnMapInfoId     map_info)
{
  ZnMapInfo     cur_map = map_info;
  unsigned int  i, num_texts, num_lines;
  ZnMapInfoText cur_texts;
  ZnMapInfoLine cur_lines;
  
  if (cur_map) {
    if (cur_map->texts) {
      num_texts = ZnListSize(cur_map->texts);
      cur_texts = ZnListArray(cur_map->texts);

      for (i = 0; i < num_texts; i++) {
        ZnFree(cur_texts[i].text);
      }
      
      ZnListFree(cur_map->texts);
    }

    if (cur_map->lines) {
      num_lines = ZnListSize(cur_map->lines);
      cur_lines = ZnListArray(cur_map->lines);

      for (i = 0; i < num_lines; i++) {
        if (cur_lines[i].style == ZnMapInfoLineMarked) {
          ZnFree(cur_lines[i].marks);
        }
      }

      ZnListFree(cur_map->lines);
    }

    if (cur_map->symbols) {
      ZnListFree(cur_map->symbols);
    }
    
    if (cur_map->arcs) {
      ZnListFree(cur_map->arcs);
    }
    
    ZnFree(cur_map->name);
    ZnFree(cur_map);
  }
}

static void
ZnMapInfoEmpty(ZnMapInfoId      map_info)
{
  ZnMapInfo cur_map = map_info;

  if (cur_map) {
    if (cur_map->texts) {
      ZnListEmpty(cur_map->texts);
    }
    if (cur_map->lines) {
      ZnListEmpty(cur_map->lines);
    }
    if (cur_map->symbols) {
      ZnListEmpty(cur_map->symbols);
    }
    if (cur_map->arcs) {
      ZnListEmpty(cur_map->arcs);
    }
  }
}


static void
ZnMapInfoAddLine(ZnMapInfoId    map_info,
                 unsigned int   index,
                 ZnPtr          tag,
                 ZnMapInfoLineStyle line_style,
                 ZnDim          line_width,
                 ZnPos          x_from,
                 ZnPos          y_from,
                 ZnPos          x_to,
                 ZnPos          y_to)
{
  ZnMapInfo             cur_map = map_info;
  ZnMapInfoLineStruct   line_struct;

  if (cur_map) {
    if (!cur_map->lines) {
      cur_map->lines = ZnListNew(16, sizeof(ZnMapInfoLineStruct));
    }

    line_struct.style = line_style;
    line_struct.width = (int) line_width;
    line_struct.tag = tag;
    line_struct.from.x = x_from;
    line_struct.from.y = y_from;
    line_struct.to.x = x_to;
    line_struct.to.y = y_to;
    /*printf("Ajout de la ligne: %d %d %d %d\n", x_from, y_from, x_to, y_to);*/
    if (line_style == ZnMapInfoLineMarked) {
      ComputeLineMarks(&line_struct);
    }
    ZnListAdd(cur_map->lines, &line_struct, index);
  }
}


static void
ZnMapInfoReplaceLine(ZnMapInfoId        map_info,
                     unsigned int       index,
                     ZnPtr              tag,
                     ZnMapInfoLineStyle line_style,
                     ZnDim              line_width,
                     ZnPos              x_from,
                     ZnPos              y_from,
                     ZnPos              x_to,
                     ZnPos              y_to)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoLine line_ptr;

  if (cur_map && cur_map->lines) {
    line_ptr = ZnListAt(cur_map->lines, index);
    if (line_ptr) {
      if (line_ptr->style == ZnMapInfoLineMarked) {
        ZnFree(line_ptr->marks);
      }

      line_ptr->style = line_style;
      line_ptr->width = (int) line_width;
      line_ptr->tag = tag;
      line_ptr->from.x = x_from;
      line_ptr->from.y = y_from;
      line_ptr->to.x = x_to;
      line_ptr->to.y = y_to;

      if (line_ptr->style == ZnMapInfoLineMarked) {
        ComputeLineMarks(line_ptr);
      }
    }
  }
}


static void
ZnMapInfoRemoveLine(ZnMapInfoId         map_info,
                    unsigned int        index)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoLine line_ptr;

  if (cur_map && cur_map->lines) {
    line_ptr = ZnListAt(cur_map->lines, index);
    if (line_ptr) {
      if (line_ptr->style == ZnMapInfoLineMarked) {
        ZnFree(line_ptr->marks);
      }

      ZnListDelete(cur_map->lines, index);
    }
  }
}


void
ZnMapInfoGetLine(ZnMapInfoId            map_info,
                 unsigned int           index,
                 ZnPtr                  *tag,
                 ZnMapInfoLineStyle     *line_style,
                 ZnDim                  *line_width,
                 ZnPos                  *x_from,
                 ZnPos                  *y_from,
                 ZnPos                  *x_to,
                 ZnPos                  *y_to)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoLine line_ptr;

  if (cur_map && cur_map->lines) {
    line_ptr = ZnListAt(cur_map->lines, index);
    if (line_ptr) {
      if (tag) {
        *tag = line_ptr->tag;
      }
      if (line_style) {
        *line_style = line_ptr->style;
      }
      if (line_width) {
        *line_width = (ZnDim) line_ptr->width;
      }
      if (x_from) {
        *x_from = line_ptr->from.x;
      }
      if (y_from) {
        *y_from = line_ptr->from.y;
      }
      if (x_to) {
        *x_to = line_ptr->to.x;
      }
      if (y_to) {
        *y_to = line_ptr->to.y;
      }
    }
  }
}


void
ZnMapInfoGetMarks(ZnMapInfoId   map_info,
                  unsigned int  index,
                  ZnPoint       **marks,
                  unsigned int  *num_marks)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoLine line_ptr;

  if (cur_map && cur_map->lines) {
    line_ptr = ZnListAt(cur_map->lines, index);
    if (line_ptr && line_ptr->style == ZnMapInfoLineMarked) {
      if (marks) {
        *marks = line_ptr->marks;
      }
      if (num_marks) {
        *num_marks = line_ptr->num_marks;
      }
    }
  }
}


unsigned int
ZnMapInfoNumLines(ZnMapInfoId   map_info)
{
  ZnMapInfo     cur_map = map_info;

  if (cur_map && cur_map->lines) {
    return ZnListSize(cur_map->lines);
  }
  else {
    return 0;
  }
}
 
  
static void
ZnMapInfoAddSymbol(ZnMapInfoId  map_info,
                   unsigned int index,
                   ZnPtr        tag,
                   ZnPos        x,
                   ZnPos        y,
                   int          symbol)
{
  ZnMapInfo             cur_map = map_info;
  ZnMapInfoSymbolStruct symbol_struct;

  if (cur_map) {
    if (!cur_map->symbols) {
      cur_map->symbols = ZnListNew(16, sizeof(ZnMapInfoSymbolStruct));
    }
    
    symbol_struct.tag = tag;
    symbol_struct.at.x = x;
    symbol_struct.at.y = y;
    symbol_struct.symbol[0] = symbol;
    symbol_struct.symbol[1] = '\0';
    
    ZnListAdd(cur_map->symbols, &symbol_struct, index);
  }
}


static void
ZnMapInfoReplaceSymbol(ZnMapInfoId      map_info,
                       unsigned int     index,
                       ZnPtr            tag,
                       ZnPos            x,
                       ZnPos            y,
                       int              symbol)
{
  ZnMapInfo             cur_map = map_info;
  ZnMapInfoSymbolStruct symbol_struct;

  if (cur_map && cur_map->symbols) {
    symbol_struct.tag = tag;
    symbol_struct.at.x = x;
    symbol_struct.at.y = y;
    symbol_struct.symbol[0] = symbol;
    symbol_struct.symbol[1] = '\0';

    ZnListAtPut(cur_map->symbols, &symbol_struct, index);
  }
}


static void
ZnMapInfoRemoveSymbol(ZnMapInfoId       map_info,
                      unsigned int      index)
{
  ZnMapInfo     cur_map = map_info;

  if (cur_map && cur_map->symbols) {
    ZnListDelete(cur_map->symbols, index);
  }
}


void
ZnMapInfoGetSymbol(ZnMapInfoId  map_info,
                   unsigned int index,
                   ZnPtr        *tag,
                   ZnPos        *x,
                   ZnPos        *y,
                   char         *symbol)
{
  ZnMapInfo       cur_map = map_info;
  ZnMapInfoSymbol symbol_ptr;

  if (cur_map && cur_map->symbols) {
    symbol_ptr = ZnListAt(cur_map->symbols, index);
    if (symbol_ptr) {
      if (tag) {
        *tag = symbol_ptr->tag;
      }
      if (x) {
        *x = symbol_ptr->at.x;
      }
      if (y) {
        *y = symbol_ptr->at.y;
      }
      if (symbol) {
        *symbol = symbol_ptr->symbol[0];
      }
    }
  }
}


unsigned int
ZnMapInfoNumSymbols(ZnMapInfoId map_info)
{
  ZnMapInfo cur_map = map_info;

  if (cur_map && cur_map->symbols) {
    return ZnListSize(cur_map->symbols);
  }
  else {
    return 0;
  }
}
 
  
static void
ZnMapInfoAddText(ZnMapInfoId    map_info,
                 unsigned int   index,
                 ZnPtr          tag,
                 ZnMapInfoTextStyle text_style,
                 ZnMapInfoLineStyle line_style,
                 ZnPos          x,
                 ZnPos          y,
                 char           *text)
{
  ZnMapInfo             cur_map = map_info;
  ZnMapInfoTextStruct   text_struct;

  if (cur_map) {
    if (!cur_map->texts) {
      cur_map->texts = ZnListNew(16, sizeof(ZnMapInfoTextStruct));
    }

    text_struct.tag        = tag;
    text_struct.text_style = text_style;
    text_struct.line_style = NOT_MARKED_STYLE(line_style);
    text_struct.at.x       = x;
    text_struct.at.y       = y;
    text_struct.text       = ZnMalloc(strlen(text) + 1);
    strcpy(text_struct.text, text);
    
    ZnListAdd(cur_map->texts, &text_struct, index);
  }
}


static void
ZnMapInfoReplaceText(ZnMapInfoId        map_info,
                     unsigned int       index,
                     ZnPtr              tag,
                     ZnMapInfoTextStyle text_style,
                     ZnMapInfoLineStyle line_style,
                     ZnPos              x,
                     ZnPos              y,
                     char               *text)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoText text_ptr;

  if (cur_map && cur_map->texts) {
    text_ptr = ZnListAt(cur_map->texts, index);
    if (text_ptr) {
      ZnFree(text_ptr->text);

      text_ptr->tag        = tag;
      text_ptr->text_style = text_style;
      text_ptr->line_style = NOT_MARKED_STYLE(line_style);
      text_ptr->at.x       = x;
      text_ptr->at.y       = y;
      text_ptr->text       = ZnMalloc(strlen(text) + 1);
      strcpy(text_ptr->text, text);
    }
  }
}


static void
ZnMapInfoRemoveText(ZnMapInfoId         map_info,
                    unsigned int        index)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoText text_ptr;

  if (cur_map && cur_map->texts) {
    text_ptr = ZnListAt(cur_map->texts, index);
    if (text_ptr) {
      ZnFree(text_ptr->text);

      ZnListDelete(cur_map->texts, index);
    }
  }
}


void
ZnMapInfoGetText(ZnMapInfoId    map_info,
                 unsigned int   index,
                 ZnPtr          *tag,
                 ZnMapInfoTextStyle *text_style,
                 ZnMapInfoLineStyle *line_style,
                 ZnPos          *x,
                 ZnPos          *y,
                 char           **text)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoText text_ptr;

  if (cur_map && cur_map->texts) {
    text_ptr = ZnListAt(cur_map->texts, index);
    if (text_ptr) {
      if (tag) {
        *tag = text_ptr->tag;
      }
      if (text_style) {
        *text_style = text_ptr->text_style;
      }
      if (line_style) {
        *line_style = text_ptr->line_style;
      }
      if (x) {
        *x = text_ptr->at.x;
      }
      if (y) {
        *y = text_ptr->at.y;
      }
      if (text) {
        *text = text_ptr->text;
      }
    }
  }
}


unsigned int
ZnMapInfoNumTexts(ZnMapInfoId   map_info)
{
  ZnMapInfo cur_map = map_info;

  if (cur_map && cur_map->texts) {
    return ZnListSize(cur_map->texts);
  }
  else {
    return 0;
  }
}


static void
ZnMapInfoAddArc(ZnMapInfoId     map_info,
                unsigned int    index,
                ZnPtr           tag,
                ZnMapInfoLineStyle line_style,
                ZnDim           line_width,
                ZnPos           center_x,
                ZnPos           center_y,
                ZnDim           radius,
                ZnReal          start_angle,
                ZnReal          extend)
{
  ZnMapInfo             cur_map = map_info;
  ZnMapInfoArcStruct    arc_struct;
  
  if (cur_map) {
    if (!cur_map->arcs) {
      cur_map->arcs = ZnListNew(16, sizeof(ZnMapInfoArcStruct));
    }

    arc_struct.style = NOT_MARKED_STYLE(line_style);
    arc_struct.width = (int) line_width;
    arc_struct.tag = tag;
    arc_struct.center.x = center_x;
    arc_struct.center.y = center_y;
    arc_struct.radius = (int) radius;
    arc_struct.start_angle = (int) start_angle;
    arc_struct.extend = (int) extend;
    
    ZnListAdd(cur_map->arcs, &arc_struct, index);
  }
}


static void
ZnMapInfoReplaceArc(ZnMapInfoId         map_info,
                    unsigned int        index,
                    ZnPtr               tag,
                    ZnMapInfoLineStyle  line_style,
                    ZnDim               line_width,
                    ZnPos               center_x,
                    ZnPos               center_y,
                    ZnDim               radius,
                    ZnReal              start_angle,
                    ZnReal              extend)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoArc  arc_ptr;
  
  if (cur_map && cur_map->arcs) {
    arc_ptr = ZnListAt(cur_map->arcs, index);
    if (arc_ptr) {
      arc_ptr->style = NOT_MARKED_STYLE(line_style);
      arc_ptr->width = (int) line_width;
      arc_ptr->tag = tag;
      arc_ptr->center.x = center_x;
      arc_ptr->center.y = center_y;
      arc_ptr->radius = (int) radius;
      arc_ptr->start_angle = (int) start_angle;
      arc_ptr->extend = (int) extend;
    }
  }
}


static void
ZnMapInfoRemoveArc(ZnMapInfoId  map_info,
                   unsigned int index)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoArc  arc_ptr;

  if (cur_map && cur_map->arcs) {
    arc_ptr = ZnListAt(cur_map->arcs, index);
    if (arc_ptr) {
      ZnListDelete(cur_map->arcs, index);
    }
  }
}


void
ZnMapInfoGetArc(ZnMapInfoId     map_info,
                unsigned int    index,
                ZnPtr           *tag,
                ZnMapInfoLineStyle *line_style,
                ZnDim           *line_width,
                ZnPos           *center_x,
                ZnPos           *center_y,
                ZnDim           *radius,
                ZnReal          *start_angle,
                ZnReal          *extend)
{
  ZnMapInfo     cur_map = map_info;
  ZnMapInfoArc  arc_ptr;

  if (cur_map && cur_map->arcs) {
    arc_ptr = ZnListAt(cur_map->arcs, index);
    if (arc_ptr) {
      if (tag) {
        *tag = arc_ptr->tag;
      }
      if (line_style) {
        *line_style = arc_ptr->style;
      }
      if (line_width) {
        *line_width = arc_ptr->width;
      }
      if (center_x) {
        *center_x = arc_ptr->center.x;
      }
      if (center_y) {
        *center_y = arc_ptr->center.y;
      }
      if (radius) {
        *radius = arc_ptr->radius;
      }
      if (start_angle) {
        *start_angle = arc_ptr->start_angle;
      }
      if (extend) {
        *extend = arc_ptr->extend;
      }
    }
  }
}

unsigned int
ZnMapInfoNumArcs(ZnMapInfoId    map_info)
{
  ZnMapInfo cur_map = map_info;

  if (cur_map && cur_map->arcs) {
    return ZnListSize(cur_map->arcs);
  }
  else {
    return 0;
  }
}

static void
ZnMapInfoScale(ZnMapInfoId      map_info,
               ZnReal           factor)
{
  ZnMapInfo     mp = map_info;
  int           i, num;
  ZnMapInfoLine line_ptr;
  ZnMapInfoSymbol sym_ptr;
  ZnMapInfoText text_ptr;
  ZnMapInfoArc  arc_ptr;

  if (mp && mp->lines) {
    num = ZnListSize(mp->lines);
    line_ptr = ZnListArray(mp->lines);
    for (i = 0; i < num; i++, line_ptr++) {
      line_ptr->from.x *= factor;
      line_ptr->from.y *= factor;
      line_ptr->to.x *= factor;
      line_ptr->to.y *= factor;
    }
  }
  if (mp && mp->symbols) {
    num = ZnListSize(mp->symbols);
    sym_ptr = ZnListArray(mp->symbols);
    for (i = 0; i < num; i++, sym_ptr++) {
      sym_ptr->at.x *= factor;
      sym_ptr->at.y *= factor;
    }
  }
  if (mp && mp->texts) {
    num = ZnListSize(mp->texts);
    text_ptr = ZnListArray(mp->texts);
    for (i = 0; i < num; i++, text_ptr++) {
      text_ptr->at.x *= factor;
      text_ptr->at.y *= factor;
    }
  }
  if (mp && mp->arcs) {
    num = ZnListSize(mp->arcs);
    arc_ptr = ZnListArray(mp->arcs);
    for (i = 0; i < num; i++, arc_ptr++) {
      arc_ptr->center.x *= factor;
      arc_ptr->center.y *= factor;
      arc_ptr->radius = (unsigned int) (arc_ptr->radius * factor);
    }
  }
}

static void
ZnMapInfoTranslate(ZnMapInfoId  map_info,
                   ZnPos        x,
                   ZnPos        y)
{
  ZnMapInfo     mp = map_info;
  int           i, num;
  ZnMapInfoLine line_ptr;
  ZnMapInfoSymbol sym_ptr;
  ZnMapInfoText text_ptr;
  ZnMapInfoArc  arc_ptr;

  if (mp && mp->lines) {
    num = ZnListSize(mp->lines);
    line_ptr = ZnListArray(mp->lines);
    for (i = 0; i < num; i++, line_ptr++) {
      line_ptr->from.x += x;
      line_ptr->from.y += y;
      line_ptr->to.x += x;
      line_ptr->to.y += y;
    }
  }
  if (mp && mp->symbols) {
    num = ZnListSize(mp->symbols);
    sym_ptr = ZnListArray(mp->symbols);
    for (i = 0; i < num; i++, sym_ptr++) {
      sym_ptr->at.x += x;
      sym_ptr->at.y += y;
    }
  }
  if (mp && mp->texts) {
    num = ZnListSize(mp->texts);
    text_ptr = ZnListArray(mp->texts);
    for (i = 0; i < num; i++, text_ptr++) {
      text_ptr->at.x += x;
      text_ptr->at.y += y;
    }
  }
  if (mp && mp->arcs) {
    num = ZnListSize(mp->arcs);
    arc_ptr = ZnListArray(mp->arcs);
    for (i = 0; i < num; i++, arc_ptr++) {
      arc_ptr->center.x += x;
      arc_ptr->center.y += y;
    }
  }
}



#define TEXT_SIZE               256
#define ntohi(n) ntohl((n))

/*
 *-----------------------------------------------------------------------
 *
 * Videomap record definition. Ints are assumed to be 4 bytes.
 *
 *-----------------------------------------------------------------------
 */

typedef struct {
  int   id;             /* Map id (internal) */
  int   dashed;         /* Tell if vectors are dashed (exclusive with marked) */
  int   expanded;       /* Device coordinates or world coordinates (ignored now) */
  int   marked;         /* Tell if vectors are marked (exclusive with dashed) */
  int   color;          /* drawing color (ignored now) */
  int   elements[50];   /* Element type ('P', 'V', 'T') */
  int   x[50];          /* Coordinates if 'P' or 'V' */
  int   y[50];
  int   symbol[50];     /* Filled if 'P' or 'V' */
  int   text[50];       /* Low order byte is ascii char if 'T' */
  int   num_elements;   /* Number of elements */
} VideoMap;

/*
 *-----------------------------------------------------------------------
 *
 * ReorderVidomap - reorder integers according to the endianess
 *
 *-----------------------------------------------------------------------
 */

static void
ReorderVidomap(VideoMap *vm)
{
  int   loop;
  
  vm->id = ntohi((unsigned int) vm->id);
  vm->dashed = ntohi((unsigned int) vm->dashed);
  vm->expanded = ntohi((unsigned int) vm->expanded);
  vm->marked = ntohi((unsigned int) vm->marked);
  vm->color = ntohi((unsigned int) vm->color);
  for (loop = 0; loop < 50; loop++) {
    vm->elements[loop] = ntohi((unsigned int) vm->elements[loop]);
    vm->x[loop] = ntohi((unsigned int) vm->x[loop]);
    vm->y[loop] = ntohi((unsigned int) vm->y[loop]);
    vm->symbol[loop] = ntohi((unsigned int) vm->symbol[loop]);
    vm->text[loop] = ntohi((unsigned int) vm->text[loop]);
  }
  vm->num_elements = ntohi((unsigned int) vm->num_elements);
}

/*
 *-----------------------------------------------------------------------
 *
 * FillMap - Fill map with data in Videomap record vm.
 *
 *-----------------------------------------------------------------------
 */

static void
FillMap(ZnMapInfoId     map,
        VideoMap        *vm)
{
  int           i;
  ZnBool        has_start_pos = False;
  ZnPos         x_cur=0, y_cur=0;
  char          ch;
  ZnPos         text_x=0, text_y=0;
  char          text[TEXT_SIZE];
  ZnBool        in_text = False;
  ZnBool        in_mod_text = False;
  unsigned int  text_size=0;

  for (i = 0; i < vm->num_elements; i++) {
    switch(vm->elements[i] & 0xFF) {
    case 'p':
    case 'P':
      if (in_text) {
        in_text = in_mod_text = False;
        while (text[text_size - 1] == ' ') {
          text_size--;
        }
        text[text_size] = (char) 0;
        ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
                         ZnMapInfoLineSimple, text_x, text_y, text);
      }

      x_cur = (int) (short) vm->x[i];
      y_cur = (int) (short) vm->y[i];
      has_start_pos = True;
        
      if (vm->symbol[i]) {
        ZnMapInfoAddSymbol(map, ZnMapInfoNumSymbols(map), NULL, x_cur, y_cur,
                           (char) vm->symbol[i]);
      }
      break;

      /* We gather consecutive 'T' elements in a text. We skip
         leading and trailing spaces and mod texts (between '@'
         and now obsolete) */

    case 't':
    case 'T':
      if (!has_start_pos) {
        ZnWarning("Bogus map block, it has been discarded\n");
        return;
      }

      if (in_text == False) {
        ch = (char) vm->text[i] & 0xFF;
        if (ch == '@') {
          if (in_mod_text == True) {
            in_mod_text = False;
          }
          else {
            in_mod_text = True;
          }
        }
        else if (in_mod_text == False) {
          in_text = True;
          text_size = 0;
          text_x = x_cur;
          text_y = y_cur;
          text[0] = (char) 0;
        }
      }
      if (in_text) {
        text[text_size] = (char) vm->text[i] & 0xFF;
        text_size++;
      }
      break;

    case 'v':
    case 'V':
      if (!has_start_pos) {
        ZnWarning("Bogus map block, it has been discarded\n");
        return;
      }

      if (in_text) {
        in_text = in_mod_text = False;
        while (text[text_size - 1] == ' ') {
          text_size--;
        }
        text[text_size] = (char) 0;
        ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
                         ZnMapInfoLineSimple, text_x, text_y, text);
      }

      if (vm->dashed)   {
        ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineDashed,
                         1, x_cur, y_cur,
                         (int) (short) vm->x[i], (int) (short) vm->y[i]);
      }
      else if (vm->marked) {
        ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineMarked,
                         1, x_cur, y_cur,
                         (int) (short) vm->x[i], (int) (short) vm->y[i]);
      }
      else {
        ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineSimple,
                         1, x_cur, y_cur,
                         (int) (short) vm->x[i], (int) (short) vm->y[i]);
      }

      x_cur = (int) (short) vm->x[i];
      y_cur = (int) (short) vm->y[i];

      if (vm->symbol[i]) {
        ZnMapInfoAddSymbol(map, ZnMapInfoNumSymbols(map), NULL, x_cur, y_cur,
                           (char) vm->symbol[i]);
      }
      break;
    }
  }

  if (in_text) {
    in_text = in_mod_text = False;
    while (text[text_size - 1] == ' ') {
      text_size--;
    }
    text[text_size] = (char) 0;
    ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
                     ZnMapInfoLineSimple, text_x, text_y, text);
  }
}

/*
 *-----------------------------------------------------------------------
 *
 * ZnMapInfoGetVideomap - Load a mapinfo with the content of a videomap
 *      file named 'filename'. Only the sub map 'index' will be loaded.
 *      If successful a new mapinfo is returned, NULL otherwise. The
 *      index is zero based.
 *
 *-----------------------------------------------------------------------
 */
static int
ZnMapInfoGetVideomap(ZnMapInfoId        map,
                     char               *filename,
                     unsigned int       index)
{
  VideoMap      current_vm;
  Tcl_Channel   chan;
  unsigned int  cur_index, cur_id;

  /* Open the specified map file. */
  chan = Tcl_OpenFileChannel(NULL, filename, "r", 0);
  if (chan == NULL) {
    return TCL_ERROR;
  }
  if (Tcl_SetChannelOption(NULL, chan,
                           "-translation", "binary") == TCL_ERROR) {
    return TCL_ERROR;
  }

  /* Load the map */

  /* First skip the leading maps up to index. */
  cur_index = 0;
  if (Tcl_Read(chan, (char *) &current_vm,
               sizeof(VideoMap)) != sizeof(VideoMap)) {
    goto error;
  }
  cur_id = ntohi((unsigned int) current_vm.id);
  while (cur_index != index) {
    if (Tcl_Read(chan, (char *) &current_vm,
                 sizeof(VideoMap)) != sizeof(VideoMap)) {
      goto error;
    }
    if (cur_id != ntohi((unsigned int) current_vm.id)) {
      cur_index++;
      cur_id = ntohi((unsigned int) current_vm.id);
    }
  };

  /* Then load all the map modules. */
  do {
    ReorderVidomap(&current_vm);
    FillMap(map, &current_vm);
    if ((Tcl_Read(chan, (char *) &current_vm,
                  sizeof(VideoMap)) != sizeof(VideoMap)) &&
        !Tcl_Eof(chan)) {
      goto error;
    }
  }
  while ((cur_id == ntohi((unsigned int) current_vm.id)) &&
         !Tcl_Eof(chan));

  Tcl_Close(NULL, chan);
  return TCL_OK;

 error:
  Tcl_Close(NULL, chan);
  return TCL_ERROR;
}

/*
 *-----------------------------------------------------------------------
 *
 * ZnMapInfoVideomapIds - Return the list of sub map ids contained in a
 *      videomap file. This makes it possible to iterate through such
 *      a file without stumbling on an error, to know how much maps
 *      are there and to sort them according to their ids.
 *
 *-----------------------------------------------------------------------
 */ 

static ZnList
ZnMapInfoVideomapIds(char       *filename)
{
  Tcl_Channel   chan;
  VideoMap      current_vm;
  unsigned int  cur_id;
  ZnList        ids;
  
  /* Open the specified map file. */
  chan = Tcl_OpenFileChannel(NULL, filename, "r", 0);
  if (chan == NULL) {
    return NULL;
  }
  if (Tcl_SetChannelOption(NULL, chan,
                           "-translation", "binary") == TCL_ERROR) {
    return NULL;
  }

  if (Tcl_Read(chan, (char *) &current_vm,
               sizeof(VideoMap)) != sizeof(VideoMap)) {
  error:
    Tcl_Close(NULL, chan);
    return NULL;
  }
  cur_id = ntohi((unsigned int) current_vm.id);
  ids = ZnListNew(16, sizeof(int));
  /*printf("id %d\n", cur_id);*/
  ZnListAdd(ids, &cur_id, ZnListTail);
  
  do {
    if (Tcl_Read(chan, (char *) &current_vm,
                 sizeof(VideoMap)) != sizeof(VideoMap)) {
      ZnListFree(ids);
      goto error;
    }
    if (cur_id != ntohi((unsigned int) current_vm.id)) {
      cur_id = ntohi((unsigned int) current_vm.id);
      /*printf("id %d\n", cur_id);*/
      ZnListAdd(ids, &cur_id, ZnListTail);
    }
  }
  while (!Tcl_Eof(chan));

  Tcl_Close(NULL, chan);
  return ids;
}


/*
 *--------------------------------------------------------------------------
 *
 * ZnMapInfo and Videomapstuff that should go eventually in its own file.
 *
 *--------------------------------------------------------------------------
 */

static Tcl_HashTable    mapInfoTable;
static ZnBool           map_info_inited = False;

typedef struct {
  ClientData            client_data;
  ZnMapInfoChangeProc   proc;
} ZnMapInfoClient;

typedef struct {
  ZnMapInfoId   map_info;
  ZnBool        deleted;
  ZnList        clients;
} ZnMapInfoMaster;

static void
ZnMapInfoInit()
{
  Tcl_InitHashTable(&mapInfoTable, TCL_ONE_WORD_KEYS);

  map_info_inited = True;
}

static void
UpdateMapInfoClients(ZnMapInfoMaster    *master)
{
  int             i, num;
  ZnMapInfoClient *client;

  num = ZnListSize(master->clients);
  client = ZnListArray(master->clients);
  for (i = 0; i < num; i++, client++) {
    (*client->proc)(client->client_data, master->map_info);
  }
}

static int
ZnCreateMapInfo(Tcl_Interp      *interp,
                char            *name,
                ZnMapInfoId     *map_info)
{
  Tk_Uid          uid = Tk_GetUid(name);
  Tcl_HashEntry   *entry;
  int             new;
  ZnMapInfoMaster *master;
  
  if (!map_info_inited) {
    ZnMapInfoInit();
  }
  
  entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new);
  if (!new) {
    /*
     * Empty the map info if it is not.
     */
    master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
    if (master->deleted) {
      master->deleted = False;
    }
    else {
      ZnMapInfoEmpty(master->map_info);
      UpdateMapInfoClients(master);
    }
  }
  else {
    master = (ZnMapInfoMaster *) ZnMalloc(sizeof(ZnMapInfoMaster));
    master->map_info = ZnMapInfoCreate(name);
    master->deleted = False;
    master->clients = ZnListNew(1, sizeof(ZnMapInfoClient));
    Tcl_SetHashValue(entry, master);
  }
  if (map_info) {
    *map_info = master->map_info;
  }
  return TCL_OK;
}

static int
ZnDuplicateZnMapInfo(Tcl_Interp *interp,
                     char               *name,
                     ZnMapInfoId        map_info)
{
  Tk_Uid          uid = Tk_GetUid(name);
  Tcl_HashEntry   *entry;
  int             new;
  ZnMapInfoMaster *master;
  
  if (!map_info_inited) {
    ZnMapInfoInit();
  }
  
  entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new);
  if (!new) {
    Tcl_AppendResult(interp, "duplicate mapinfo \"", name, "\" already exists", NULL);
    return TCL_ERROR;
  }
  master = (ZnMapInfoMaster *) ZnMalloc(sizeof(ZnMapInfoMaster));
  master->map_info = ZnMapInfoDuplicate(map_info);
  master->deleted = False;
  master->clients = ZnListNew(1, sizeof(ZnMapInfoClient));
  Tcl_SetHashValue(entry, master);

  return TCL_OK;
}

static ZnMapInfoMaster *
LookupMapInfoMaster(Tcl_Interp  *interp,
                    char        *name)
{
  Tk_Uid          uid = Tk_GetUid(name);
  Tcl_HashEntry   *entry;
  ZnMapInfoMaster *master;
  
  if (!map_info_inited) {
    ZnMapInfoInit();
  }
  
  entry = Tcl_FindHashEntry(&mapInfoTable, uid);
  if (entry == NULL) {
  mp_error:
    Tcl_AppendResult(interp, "mapinfo \"", name, "\" doesn't exist", NULL);
    return NULL;
  }
  master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
  if (master->deleted) {
    goto mp_error;
  }
  return master;
}

static int
ZnDeleteMapInfo(Tcl_Interp      *interp,
                char            *name)
{
  ZnMapInfoMaster *master;
  Tk_Uid          uid = Tk_GetUid(name);
  Tcl_HashEntry   *entry;
  
  if (!map_info_inited) {
    ZnMapInfoInit();
  }
  
  entry = Tcl_FindHashEntry(&mapInfoTable, uid);
  if (entry == NULL) {
    return TCL_ERROR;
  }
  
  master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
  if (ZnListSize(master->clients) != 0) {
    master->deleted = True;
    ZnMapInfoEmpty(master->map_info);
    UpdateMapInfoClients(master);
  }
  else {
    ZnMapInfoDelete(master->map_info);
    ZnListFree(master->clients);
    Tcl_DeleteHashEntry(entry);
    ZnFree(master);
  }

  return TCL_OK;
}

ZnMapInfoId
ZnGetMapInfo(Tcl_Interp         *interp,
             char               *name,
             ZnMapInfoChangeProc proc,
             ClientData         client_data)
{
  ZnMapInfoMaster       *master;
  ZnMapInfoClient       client;
  
  master = LookupMapInfoMaster(interp, name);
  if (master == NULL) {
    return NULL;
  }
  client.proc = proc;
  client.client_data = client_data;
  ZnListAdd(master->clients, &client, ZnListTail);

  return master->map_info;
}

void
ZnFreeMapInfo(ZnMapInfoId       map_info,
              ZnMapInfoChangeProc proc,
              ClientData        client_data)
{
  Tk_Uid        uid = Tk_GetUid(ZnMapInfoName(map_info));
  Tcl_HashEntry *entry;
  ZnMapInfoMaster *master;
  ZnMapInfoClient *client;
  unsigned int  num, i;
  
  if (!map_info_inited) {
    ZnMapInfoInit();
  }
  
  entry = Tcl_FindHashEntry(&mapInfoTable, uid);
  if (entry == NULL) {
    return;
  }
  master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
  client = ZnListArray(master->clients);
  num = ZnListSize(master->clients);
  for (i = 0; i < num; i++, client++) {
    if ((client->client_data == client_data) &&
        (client->proc == proc)) {
      ZnListDelete(master->clients, i);
      return;
    }
  }
}

static void
ZnUpdateMapInfoClients(ZnMapInfoId      map_info)
{
  Tk_Uid          uid = Tk_GetUid(ZnMapInfoName(map_info));
  Tcl_HashEntry   *entry;
  ZnMapInfoMaster *master;

  if (!map_info_inited) {
    ZnMapInfoInit();
  }
  
  entry = Tcl_FindHashEntry(&mapInfoTable, uid);
  if (entry == NULL) {
    return;
  }
  master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
  UpdateMapInfoClients(master);
}


/*
 * These arrays must be kept in sync with the ZnMapInfoLineStyle
 * and ZnMapInfoTextStyle enums.
 */
static char *line_style_strings[] = {
  "simple",
  "dashed",
  "dotted",
  "mixed",
  "marked",
};

static char *text_style_strings[] = {
  "normal",
  "underlined"
};

static char *
ZnMapInfoLineStyleToString(ZnMapInfoLineStyle   line_style)
{
  return line_style_strings[line_style];
}

static int
ZnMapInfoLineStyleFromString(Tcl_Interp         *interp,
                             char               *str,
                             ZnMapInfoLineStyle *line_style)
{
  int   i, num = sizeof(line_style_strings)/sizeof(char *);

  for (i = 0; i < num; i++) {
    if (strcmp(str, line_style_strings[i]) == 0) {
      *line_style = i;
      return TCL_OK;
    }
  }
  Tcl_AppendResult(interp, " incorrect mapinfo line style \"",
                   str,"\"", NULL);
  return TCL_ERROR;
}

static char *
ZnMapInfoTextStyleToString(ZnMapInfoTextStyle   text_style)
{
  return text_style_strings[text_style];
}

static int
ZnMapInfoTextStyleFromString(Tcl_Interp         *interp,
                             char                       *str,
                             ZnMapInfoTextStyle *text_style)
{
  int   i, num = sizeof(text_style_strings)/sizeof(char *);

  for (i = 0; i < num; i++) {
    if (strcmp(str, text_style_strings[i]) == 0) {
      *text_style = i;
      return TCL_OK;
    }
  }
  Tcl_AppendResult(interp, " incorrect mapinfo text style \"",
                   str,"\"", NULL);
  return TCL_ERROR;
}

int
ZnMapInfoObjCmd(ClientData      client_data,
                Tcl_Interp      *interp,        /* Current interpreter. */
                int             argc,           /* Number of arguments. */
                Tcl_Obj *CONST  args[])
{
  ZnPos           x, y;
  int             index, index2, result;
  ZnMapInfoMaster *master;
  Tcl_Obj         *l;
#ifdef PTK_800
  static char *sub_cmd_strings[] =
#else
  static CONST char *sub_cmd_strings[] =
#endif
  {
    "add", "count", "create", "delete", "duplicate",
    "get", "remove", "replace", "scale", "translate", NULL
  };
#ifdef PTK_800
  static char *e_type_strings[] =
#else
  static CONST char *e_type_strings[] =
#endif
  {
    "arc", "line", "symbol", "text", NULL
  };
  enum          sub_cmds {
    ZN_MI_ADD, ZN_MI_COUNT, ZN_MI_CREATE, ZN_MI_DELETE, ZN_MI_DUPLICATE,
    ZN_MI_GET, ZN_MI_REMOVE, ZN_MI_REPLACE, ZN_MI_SCALE, ZN_MI_TRANSLATE
  };
  enum          e_types {
    ZN_E_ARC, ZN_E_LINE, ZN_E_SYMBOL, ZN_E_TEXT
  };
  

  if (argc < 3) {
    Tcl_WrongNumArgs(interp, 1, args, "mapInfo/name subCmd ?args?");
    return TCL_ERROR;
  }

  if (Tcl_GetIndexFromObj(interp, args[2], sub_cmd_strings,
                          "subCmd", 0, &index) != TCL_OK) {
    return TCL_ERROR;
  }
  result = TCL_OK;
  /*printf("mapinfo command \"%s\", argc=%d\n",
    Tcl_GetString(args[2]), argc);*/

  switch((enum sub_cmds) index) {
    /*
     * create
     */
  case ZN_MI_CREATE:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "name create");
        return TCL_ERROR;
      }
      if (ZnCreateMapInfo(interp, Tcl_GetString(args[1]), NULL) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    break;
    /*
     * delete
     */
  case ZN_MI_DELETE:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "mapInfo delete");
        return TCL_ERROR;
      }
      if (ZnDeleteMapInfo(interp, Tcl_GetString(args[1])) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    break;
    /*
     * duplicate
     */
  case ZN_MI_DUPLICATE:
    {
      if (argc != 4) {
        Tcl_WrongNumArgs(interp, 1, args, "mapInfo duplicate name");
        return TCL_ERROR;
      }
      master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
      if (master == NULL) {
        return TCL_ERROR;
      }
      if (ZnDuplicateZnMapInfo(interp, Tcl_GetString(args[3]),
                               master->map_info) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    break;
    /*
     * add/replace
     */
  case ZN_MI_ADD:
  case ZN_MI_REPLACE:
    {
      ZnMapInfoLineStyle line_style;
      ZnMapInfoTextStyle text_style;
      int                i, insert, val;
      ZnPos              coords[6];
      ZnBool             add_cmd = (enum sub_cmds) index == ZN_MI_ADD;
      int                num_param = add_cmd ? 4 : 5;
      
      if (argc < num_param) {
        Tcl_WrongNumArgs(interp, 3, args,
                         add_cmd ? "elementType ?args?" : "elementType index ?args?");
        return TCL_ERROR;
      }
      master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
      if (master == NULL) {
        return TCL_ERROR;
      }
      if (!add_cmd) {
        if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
          return TCL_ERROR;
        }
      }
      if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
                              "elementType", 0, &index2) != TCL_OK) {
        return TCL_ERROR;
      }
      switch ((enum e_types) index2) {
      case ZN_E_LINE:
        {
          if (argc != (num_param+6)) {
            Tcl_WrongNumArgs(interp, 4, args,
                             add_cmd ? "style width x1 y1 x2 y2" : "index style width x1 y1 x2 y2");
            return TCL_ERROR;
          }
          if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]),
                                           &line_style) == TCL_ERROR) {
            return TCL_ERROR;
          }
          for (i = 0; i < 5; i++) {
            if (Tcl_GetDoubleFromObj(interp, args[num_param+i+1], &coords[i]) == TCL_ERROR) {
              return TCL_ERROR;
            }
          }
          if (coords[0] < 0) {
            coords[0] = 0;
          }
          if (add_cmd) {
            ZnMapInfoAddLine(master->map_info, ZnListTail, NULL, line_style,
                             coords[0], coords[1], coords[2], coords[3], coords[4]);
          }
          else {
            ZnMapInfoReplaceLine(master->map_info, insert, NULL, line_style,
                                 coords[0], coords[1], coords[2], coords[3], coords[4]);
          }
        }
        break;
      case ZN_E_SYMBOL:
        {
          if (argc != (num_param+3)) {
            Tcl_WrongNumArgs(interp, 4, args,
                             add_cmd ? "x y intVal" : "index x y intVal");
            return TCL_ERROR;
          }
          for (i = 0; i < 2; i++) {
            if (Tcl_GetDoubleFromObj(interp, args[num_param+i], &coords[i]) == TCL_ERROR) {
              return TCL_ERROR;
            }
          }
          if (Tcl_GetIntFromObj(interp, args[num_param+2], &val) == TCL_ERROR) {
            return TCL_ERROR;
          }
          if (val < 0) {
            val = 0;
          }
          if (add_cmd) {
            ZnMapInfoAddSymbol(master->map_info, ZnListTail, NULL, coords[0],
                               coords[1], (char) val);
          }
          else {
            ZnMapInfoReplaceSymbol(master->map_info, insert, NULL, coords[0],
                                   coords[1], (char) val);
          }
        }
        break;
      case ZN_E_TEXT:
        {
          if (argc != (num_param+5)) {
            Tcl_WrongNumArgs(interp, 4, args,
                             add_cmd ? "textStyle lineStyle x y string" : "index textStyle lineStyle x y string");
            return TCL_ERROR;
          }
          if (ZnMapInfoTextStyleFromString(interp, Tcl_GetString(args[num_param]),
                                           &text_style) == TCL_ERROR) {
            return TCL_ERROR;
          }
          if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param+1]),
                                           &line_style) == TCL_ERROR) {
            return TCL_ERROR;
          }
          for (i = 0; i < 2; i++) {
            if (Tcl_GetDoubleFromObj(interp, args[num_param+i+2], &coords[i]) == TCL_ERROR) {
              return TCL_ERROR;
            }
          }
          if (add_cmd) {
            ZnMapInfoAddText(master->map_info, ZnListTail, NULL, text_style,
                             line_style, coords[0], coords[1],
                             Tcl_GetString(args[num_param+4]));
          }
          else {
            /*printf("replace text ts %d ls %d %g %g %s\n", text_style,
              line_style, coords[0], coords[1], Tcl_GetString(args[num_param+4]));*/
            ZnMapInfoReplaceText(master->map_info, insert, NULL, text_style,
                                 line_style, coords[0], coords[1],
                                 Tcl_GetString(args[num_param+4]));
          }
        }
        break;
      case ZN_E_ARC:
        {
          if (argc != (num_param+7)) {
            Tcl_WrongNumArgs(interp, 4, args,
                             add_cmd ? "style width cx cy radius start extent" : "index style width cx cy radius start extent");
            return TCL_ERROR;
          }
          if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]),
                                           &line_style) == TCL_ERROR) {
            return TCL_ERROR;
          }
          for (i = 0; i < 6; i++) {
            if (Tcl_GetDoubleFromObj(interp, args[num_param+i+1], &coords[i]) == TCL_ERROR) {
              return TCL_ERROR;
            }
          }
          if (coords[0] < 0) {
            coords[0] = 0;
          }
          if (coords[3] < 0) {
            coords[3] = 0;
          }
          if (add_cmd) {
            ZnMapInfoAddArc(master->map_info, ZnListTail, NULL, line_style, coords[0],
                            coords[1], coords[2], coords[3], coords[4], coords[5]);
          }
          else {
            ZnMapInfoReplaceArc(master->map_info, insert, NULL, line_style, coords[0],
                                coords[1], coords[2], coords[3], coords[4], coords[5]);
          }
        }
        break;
      }
      UpdateMapInfoClients(master);
    }
    break;
    /*
     * count
     */
  case ZN_MI_COUNT:
    {
      int       count = 0;
      if (argc != 4) {
        Tcl_WrongNumArgs(interp, 1, args, "mapInfo count type");
        return TCL_ERROR;
      }
      master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
      if (master == NULL) {
        return TCL_ERROR;
      }
      if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
                              "elementType", 0, &index2) != TCL_OK) {
        return TCL_ERROR;
      }
      switch ((enum e_types) index2) {
      case ZN_E_LINE:
        count = ZnMapInfoNumLines(master->map_info);
        break;
      case ZN_E_SYMBOL:
        count = ZnMapInfoNumSymbols(master->map_info);
        break;
      case ZN_E_TEXT:
        count = ZnMapInfoNumTexts(master->map_info);
        break;
      case ZN_E_ARC:
        count = ZnMapInfoNumArcs(master->map_info);
        break;
      }
      l = Tcl_NewIntObj(count);
      Tcl_SetObjResult(interp, l);
    }
    break;
    /*
     * get
     */
  case ZN_MI_GET:
    {
      int   insert;

      if (argc != 5) {
        Tcl_WrongNumArgs(interp, 1, args, "mapInfo get type index");
        return TCL_ERROR;
      }
      master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
      if (master == NULL) {
        return TCL_ERROR;
      }
      if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (insert < 0) {
        insert = 0;
      }
      if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
                              "elementType", 0, &index2) != TCL_OK) {
        return TCL_ERROR;
      }
      switch ((enum e_types) index2) {
      case ZN_E_LINE:
        {
          ZnMapInfoLineStyle line_style;
          ZnDim line_width;
          ZnPos x_to, y_to;
          ZnMapInfoGetLine(master->map_info, insert, NULL, &line_style,
                           &line_width, &x, &y, &x_to, &y_to);
          l = Tcl_GetObjResult(interp);
          Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(line_width));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x_to));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y_to));
        }
        break;
      case ZN_E_SYMBOL:
        {
          char  symbol;
          ZnMapInfoGetSymbol(master->map_info, insert, NULL, &x, &y, &symbol);
          l = Tcl_GetObjResult(interp);
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(symbol));
        }
        break;
      case ZN_E_TEXT:
        {
          char *text;
          ZnMapInfoTextStyle text_style;
          ZnMapInfoLineStyle line_style;
          ZnMapInfoGetText(master->map_info, insert, NULL, &text_style, &line_style,
                           &x, &y, &text);
          l = Tcl_GetObjResult(interp);
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoTextStyleToString(text_style), -1));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(text, -1));
        }
        break;
      case ZN_E_ARC:
        {
          ZnMapInfoLineStyle    line_style;
          ZnDim line_width, radius;
          ZnPos start, extent;
          ZnMapInfoGetArc(master->map_info, insert, NULL, &line_style, &line_width,
                          &x, &y, &radius, &start, &extent);
          l = Tcl_GetObjResult(interp);
          Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(line_width));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(radius));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(start));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(extent));
        }
        break;
      }
    }
    break;
    /*
     * remove
     */
  case ZN_MI_REMOVE:
    {
      int insert;
      if (argc != 5) {
        Tcl_WrongNumArgs(interp, 1, args, "mapInfo remove type index");
        return TCL_ERROR;
      }
      master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
      if (master == NULL) {
        return TCL_ERROR;
      }
      if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (insert < 0) {
        insert = 0;
      }
      if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
                              "elementType", 0, &index2) != TCL_OK) {
        return TCL_ERROR;
      }
      switch ((enum e_types) index2) {
      case ZN_E_LINE:
        ZnMapInfoRemoveLine(master->map_info, insert);
        break;
      case ZN_E_SYMBOL:
        ZnMapInfoRemoveSymbol(master->map_info, insert);
        break;
      case ZN_E_TEXT:
        ZnMapInfoRemoveText(master->map_info, insert);
        break;
      case ZN_E_ARC:
        ZnMapInfoRemoveArc(master->map_info, insert);
        break;
      }
      UpdateMapInfoClients(master);
    }
    break;
    /*
     * scale
     */
  case ZN_MI_SCALE:
    {
      double factor;
      
      if (argc != 4) {
        Tcl_WrongNumArgs(interp, 1, args, "mapInfo scale factor");
        return TCL_ERROR;
      }
      master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
      if (master == NULL) {
        return TCL_ERROR;
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &factor) == TCL_ERROR) {
        return TCL_ERROR;
      }
      ZnMapInfoScale(master->map_info, factor);
      UpdateMapInfoClients(master);
    }
    break;
    /*
     * translate
     */
  case ZN_MI_TRANSLATE:
    {
      if (argc != 5) {
        Tcl_WrongNumArgs(interp, 1, args, "mapInfo translate xAmount yAmount");
        return TCL_ERROR;
      }
      master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
      if (master == NULL) {
        return TCL_ERROR;
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &x) == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (Tcl_GetDoubleFromObj(interp, args[4], &y) == TCL_ERROR) {
        return TCL_ERROR;
      }
      ZnMapInfoTranslate(master->map_info, x, y);
      UpdateMapInfoClients(master);
    }
    break;
  }

  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * VideomapObjCmd --
 *
 *
 *----------------------------------------------------------------------
 */
int
ZnVideomapObjCmd(ClientData     client_data,
                 Tcl_Interp     *interp,        /* Current interpreter. */
                 int            argc,           /* Number of arguments. */
                 Tcl_Obj        *CONST  args[])
{
  ZnList        ids;
  int           index;
  int           *id_array, id_num, i;
  Tcl_Obj       *l;
#ifdef PTK_800
  static char *sub_cmd_strings[] =
#else
  static CONST char *sub_cmd_strings[] =
#endif
  {
    "ids", "load", NULL
  };
  enum          sub_cmds {
    ZN_V_IDS, ZN_V_LOAD
  };
  

  if (argc < 2) {
    Tcl_WrongNumArgs(interp, 1, args, "?subCmd? filename $args?");
    return TCL_ERROR;
  }

  if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings,
                          "subCmd", 0, &index) != TCL_OK) {
    return TCL_ERROR;
  }

  switch((enum sub_cmds) index) {
    /*
     * ids
     */
  case ZN_V_IDS:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args,"ids filename");
        return TCL_ERROR;
      }
      ids = ZnMapInfoVideomapIds(Tcl_GetString(args[2]));
      if (ids == NULL) {
        Tcl_AppendResult(interp, "unable to look at videomap file \"",
                         Tcl_GetString(args[2]), "\"", NULL);
        return TCL_ERROR;
      }
      id_array = ZnListArray(ids);
      id_num = ZnListSize(ids);
      l = Tcl_GetObjResult(interp);
      for (i = 0; i < id_num; i++) {
        Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(id_array[i]));
      }
      ZnListFree(ids);
    }
    break;
    /*
     * load
     */
  case ZN_V_LOAD:
    {
      ZnMapInfoId          map_info;
      int insert;
      
      if (argc != 5) {
        Tcl_WrongNumArgs(interp, 1, args, "load filename index mapInfo");
        return TCL_ERROR;
      }
      if (Tcl_GetIntFromObj(interp, args[3], &insert) == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (insert < 0) {
        insert = 0;
      }
      if (ZnCreateMapInfo(interp, Tcl_GetString(args[4]), &map_info) == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (ZnMapInfoGetVideomap(map_info, Tcl_GetString(args[2]), insert) == TCL_ERROR) {
        Tcl_AppendResult(interp, "unable to load videomap file \"",
                         Tcl_GetString(args[2]), ":",
                         Tcl_GetString(args[3]), "\"", NULL);
        return TCL_ERROR;
      }
      ZnUpdateMapInfoClients(map_info);
    }
    break;
  }
  
  return TCL_OK;
}

Added jni/tkzinc/generic/MapInfo.h.































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
 * MapInfo.h -- Public include file for MapInfo interface.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : 
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _MapInfo_h
#define _MapInfo_h

#ifdef __CPLUSPLUS__
extern "C" {
#endif


#include "Types.h"
#include "List.h"
#include "Geo.h"
  

/*
 *-----------------------------------------------------------------------
 *
 * New types
 *
 *-----------------------------------------------------------------------
 */

typedef void    *ZnMapInfoId;

typedef enum {
  ZnMapInfoLineSimple,
  ZnMapInfoLineDashed,
  ZnMapInfoLineDotted,
  ZnMapInfoLineMixed,
  ZnMapInfoLineMarked
} ZnMapInfoLineStyle;

typedef enum {
  ZnMapInfoNormalText,
  ZnMapInfoUnderlinedText
} ZnMapInfoTextStyle;

  
void ZnMapInfoGetLine(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
                      ZnMapInfoLineStyle *line_style, ZnDim *line_width,
                      ZnPos *x_from, ZnPos *y_from,
                      ZnPos *x_to, ZnPos *y_to);
unsigned int ZnMapInfoNumLines(ZnMapInfoId map_info);
void ZnMapInfoGetMarks(ZnMapInfoId map_info, unsigned int index,
                       ZnPoint **marks, unsigned int *num_marks);
void ZnMapInfoGetSymbol(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
                        ZnPos *x, ZnPos *y, char *symbol);
unsigned int ZnMapInfoNumSymbols(ZnMapInfoId map_info);
void ZnMapInfoGetText(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
                      ZnMapInfoTextStyle *text_style,
                      ZnMapInfoLineStyle *line_style,
                      ZnPos *x, ZnPos *y, char **text);
unsigned int ZnMapInfoNumTexts(ZnMapInfoId map_info);
void ZnMapInfoGetArc(ZnMapInfoId map_info, unsigned int index, ZnPtr *tag,
                     ZnMapInfoLineStyle *line_style, ZnDim *line_width,
                     ZnPos *center_x, ZnPos *center_y, ZnDim *radius,
                     ZnReal *start_angle, ZnReal *extend);
unsigned int ZnMapInfoNumArcs(ZnMapInfoId map_info);


typedef void (*ZnMapInfoChangeProc)(ClientData client_data, ZnMapInfoId map_info);

ZnMapInfoId ZnGetMapInfo(Tcl_Interp *interp, char *name,
                         ZnMapInfoChangeProc proc, ClientData client_data);
void ZnFreeMapInfo(ZnMapInfoId map_info, ZnMapInfoChangeProc proc,
                   ClientData client_data);

int ZnMapInfoObjCmd(ClientData client_data, Tcl_Interp *interp,
                    int argc, Tcl_Obj *CONST args[]);
int ZnVideomapObjCmd(ClientData client_data, Tcl_Interp *interp,
                     int argc, Tcl_Obj *CONST args[]);
  

#ifdef __CPLUSPLUS__
}
#endif

#endif  /* _MapInfo_h */

Added jni/tkzinc/generic/OverlapMan.c.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
/*
 * OverlapMan.c -- Track label overlap avoidance manager implementation.
 *
 * Authors              :
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
 * TODO:
 *
 *   The tracks should be identified by their ids not their
 *   structure pointer. This would enable an easy interface
 *   between the overlap manager and the applications when
 *   dealing with tracks.
 */

static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";

#include "Types.h"
#include "OverlapMan.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#ifdef _WIN32
#  ifndef __GNUC__
#    pragma warning(disable : 4996)
#  endif
#endif

#define signe(a) ((a) < (0) ? (-1) : (1))
#define abs(a)   ((a) < (0) ? -(a) : (a))
#ifndef M_PI
#define M_PI            3.14159265358979323846264338327
#endif
#ifndef M_PI_2
#define M_PI_2          1.57079632679489661923
#endif
#ifndef M_PI_4
#define M_PI_4          0.78539816339744830962
#endif
#define DegreesToRadian(angle) \
  (M_PI * (double) (angle) / 180.0)
#define RadianToDegrees(angle) \
  (fmod((angle) * 180.0 / M_PI, 360.0))
#define RadianToDegrees360(angle) \
  (fmod(RadianToDegrees(angle)+360.0,360.0))


#define NB_ALLOC 20
#define COEF1  0.5      /* coef of second repulsion point */
#define COEF2  0.1      /* coef of second repulsion point */

#define DELTA_T 0.1     /* integration step for Euler method */
#define FALSE   0
#define TRUE    1

#ifndef _WIN32
typedef int BOOLEAN;
#endif

typedef struct _INFOS {
  void*  id;
  int     x;
  int     y;
  int     vv_dx;
  int     vv_dy;
  /* Fri Oct 13 15:15:31 2000  int     label_x;
  int     label_y;
  int     label_width;
  int     label_height;*/
  int     rho;
  int     theta;
  int     visibility;
  BOOLEAN New_Track;
  int     dx;
  int     dy;
  double  alpha;
  double  alpha_point;
  BOOLEAN Refresh;
} INFOS;

typedef struct _ZINCS {
  void  *rw;
  void  *(*_next_track)();
  void  (*_set_label_angle)();
  INFOS *infos;
  int   NBinfos;
  int   NBalloc_infos;
} ZINCS;

/*
 * Definition of tunable parameters
 */


/*
 * real parameters adresse
 */
static  double K0 = 2100.0;     /* Repulsion factor */
static  double K0min = 500.0;
static  double K0max = 3000.0;

static  double n0 = 2.10;       /* Repulsion exponent */
static  double n0min = 2.0;
static  double n0max = 3.0;

static  double K1 = 6.0;         /* Friction factor */
static  double K1min = 1.0;
static  double K1max = 10.0;

static  double K2 = 6.0;         /* Drawback forces factor */
static  double K2min = 1.0;
static  double K2max = 10.0;

static  double K3 = 4.0;         /* Keep in view forces factor */
static  double K3min = 1.0;
static  double K3max = 10.0;

/*
 * accessor structure need for generic set/get method
 */
typedef struct _OMPARAM {
  int      type;
  int      size;
  char    *name;
  void    *data;
  BOOLEAN  rw;           /* 1 means readwrite, 0 means read only */
} OMPARAM, *pOMPARAM;

/*
 * Global vars.
 *
 */
static OMPARAM OmParamAccess[] = {
  { OM_PARAM_DOUBLE, sizeof(double), "repulsion",                    &K0,    1 },
  { OM_PARAM_DOUBLE, sizeof(double), "repulsion_bearing",            &n0,    1 },
  { OM_PARAM_DOUBLE, sizeof(double), "friction",                     &K1,    1 },
  { OM_PARAM_DOUBLE, sizeof(double), "best_position_attraction",     &K2,    1 },
  { OM_PARAM_DOUBLE, sizeof(double), "screen_edge_repulsion",        &K3,    1 },
  { OM_PARAM_DOUBLE, sizeof(double), "min_repulsion",                &K0min, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "min_repulsion_bearing",        &n0min, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "min_friction",                 &K1min, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "min_best_position_attraction", &K2min, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "min_screen_edge_repulsion",    &K3min, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "max_repulsion",                &K0max, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "max_repulsion_bearing",        &n0max, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "max_friction",                 &K1max, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "max_best_position_attraction", &K2max, 0 },
  { OM_PARAM_DOUBLE, sizeof(double), "max_screen_edge_repulsion",    &K3max, 0 },
  { OM_PARAM_END,  0, "", NULL, 0 }
};

static int NbParam = sizeof(OmParamAccess) / sizeof(OMPARAM) - 1;
static  ZINCS   *wr = NULL;
static  int     NBzincs=0;
static  int     NBalloc_zincs=0;
static  INFOS   info1;


/*
 * Square of the distance (between two label centers) below which
 * the repulsion is not computed.
 */
static  double limit_distance = 6.0; 

/*
 * Square of the minimum distance (between two label centers)
 * considered during initialisation of the leaders.
 */
static  double placing_min_dist = 11000.0;

/*
 * Angle step between two placement trials.
 */
static  double placing_step = M_PI/6.0;


/*
 ****************************************************************************
 *
 * FindPosW --
 *      Find the zinc position in the database,
 *      if not found, gets the positon to insert in.
 *
 ****************************************************************************
 */
static BOOLEAN
FindPosW(void   *w,
         int    *mid)
{ 
  int   left=0;
  int   right=NBzincs-1;
 
  if (w < wr[0].rw) {
    *mid = 0;
    return FALSE;
  }
  if (w > wr[right].rw) {
    *mid = right+1;
    return FALSE;
  }
  if (w == wr[right].rw) {
    *mid = right;
    return TRUE;
  }

  *mid = (right + left) / 2;
  while ((right > left+1) && (wr[*mid].rw != w)) {
    if (w > wr[*mid].rw) {
      left = *mid;
    }
    else {
      right = *mid;
    }
    *mid = (right + left) / 2;
  }
  if (wr[*mid].rw == w) {
    return TRUE;
  }
  else { 
    (*mid)++;
    return FALSE;
  }
}


/*
 ****************************************************************************
 *
 * AllocW --
 *      Allocate cells in database for the specified zinc.
 *
 ****************************************************************************
 */
static void
AllocW(void     *w,
       int      pos)
{
  int   i;
  
  if (NBzincs == NBalloc_zincs) {
    NBalloc_zincs += NB_ALLOC;
    wr = ZnRealloc(wr, sizeof(ZINCS) * NBalloc_zincs);
  }

  for (i = NBzincs-1; i >= pos; i--) {
    memcpy((char *) &wr[i+1], (char *) &wr[i], sizeof(ZINCS));
  }  
  /*memcpy((char *)&wr[pos+1], (char *)&wr[pos], (NBzincs-pos) * sizeof(ZINCS) );*/

  NBzincs++;
  wr[pos].rw = w;
  wr[pos].infos = NULL;
  wr[pos].NBinfos = 0;
  wr[pos].NBalloc_infos = 0;                             
}


/*
 ***************************************************************************
 *
 * ProjToAngle --
 *      Compute an angle from dx and dy projections.
 *
 ***************************************************************************
 */
static double
ProjToAngle(int dx,
            int dy)
{
  if (dx == 0) {     
    if (dy < 0) {
      return -M_PI_2;
    }
    else {
      if (dy > 0) {
        return M_PI_2;
      }
      else {
        return 0;
      }
    }
  }
  if (dx > 0) {
    return atan((double) (dy) / (double) (dx));
  }
  if (dx < 0) {
    return atan((double) (dy) / (double) (dx)) + M_PI;
  }

  return 0.0;
}


/*
 ****************************************************************************
 *
 * OmInit --
 *      Called only once to initialize some internal data.
 *
 ****************************************************************************
 */
void
OmInit()
{
  /*  printf("OmInit\n");*/
}        


/*
 ****************************************************************************
 *
 * OmRegister --
 *      Create a database entry for the specified zinc.
 *
 ****************************************************************************
 */
void
OmRegister(void *w,
           void *(*_fnext_track)(void *, void *,
                                 int *, int *,
                                 int *, int *,
                                 int *, int *,
                                 int *, int *,
                                 int *, int *),
           void (*_fset_label_angle)(void *, void *, int, int, char *),
           void (*_fquery_label_pos)(void *, void *, int,
                                     int *, int *, int *, int *))
{
  int           iw=0;
  BOOLEAN       found=FALSE;

  if (NBzincs > 0) {
    found = FindPosW(w, &iw);
  }
  if (found == FALSE) {
    AllocW(w, iw);
  }
  wr[iw]._next_track= _fnext_track;
  wr[iw]._set_label_angle= _fset_label_angle;
}


/*
 ****************************************************************************
 *
 * OmUnregister --
 *      Cancel database information about the specified zinc.
 *
 ****************************************************************************
 */
void
OmUnregister(void       *w)
{ 
  int   i;

  if (FindPosW(w, &i) == TRUE) { 
    ZnFree(wr[i].infos);
    memcpy((char *) &wr[i], (char *) &wr[i+1], (NBzincs-i-1)*sizeof(ZINCS));
    NBzincs--;
  }
}


/*
 ***************************************************************************
 *
 * FindPosId --
 *      Find track position in the database,
 *      if not found gets the positon to insert in.
 *
 ***************************************************************************
 */
static BOOLEAN
FindPosId(int   iw,
          void  *id,
          int   *mid)
{ 
  int   left=0;
  int   right= wr[iw].NBinfos-1;

  if (id < wr[iw].infos[0].id) {
    *mid = 0;
    return FALSE;
  }
  if (id > wr[iw].infos[right].id) {
    *mid = right+1;
    return FALSE;
  }
  if (id == wr[iw].infos[right].id) {
    *mid = right;
    return TRUE;
  }
 
  *mid = (right + left) / 2;
  while ((right > left+1) && (wr[iw].infos[*mid].id != id)) { 
    if (id > wr[iw].infos[*mid].id) {
      left = *mid;
    }
    else {
      right = *mid;
    }
    *mid = (right + left) / 2;
  }
  if (wr[iw].infos[*mid].id == id) {
    return TRUE;
  }
  else { 
    (*mid)++;
    return FALSE;
  }
}


/*
 ***************************************************************************
 *
 * SetTrackInitValues --
 *      Set initial label values for a track.
 *
 ***************************************************************************
 */
static void
SetTrackInitValues()
{
  info1.alpha       = ProjToAngle(info1.vv_dx, info1.vv_dy) - 3.0 * M_PI_4;
  info1.dx          = (int) (info1.rho * cos(info1.alpha));
  info1.dy          = (int) (info1.rho * sin(info1.alpha));
  info1.alpha_point = 0.0;
}


/*
 ***************************************************************************
 * SetTrackCurrentValues --
 *      Update label values for a track.
 *
 ***************************************************************************
 */
static void
SetTrackCurrentValues(int       iw,
                      int       pos)
{
  info1.New_Track   = FALSE;
  info1.alpha_point = wr[iw].infos[pos].alpha_point;
}


/*
 ***************************************************************************
 *
 * PutTrackLoaded --
 *      Put track labels information into database.
 *
 ***************************************************************************
 */
static void
PutTrackLoaded(int      iw)
{
  int           pos = 0, i;
  BOOLEAN       found = FALSE;

  if (wr[iw].NBinfos > 0) {
    found = FindPosId(iw, info1.id, &pos);
  }
  if (found == FALSE) {
    /*
     * New track.
     */ 
    if (wr[iw].NBinfos == wr[iw].NBalloc_infos) {
      wr[iw].NBalloc_infos += NB_ALLOC;
      wr[iw].infos = ZnRealloc((void *) wr[iw].infos,
                               sizeof(INFOS)*wr[iw].NBalloc_infos);
    }
    
    if (pos < wr[iw].NBinfos) {
      for(i = wr[iw].NBinfos-1; i >= pos; i--) {
        memcpy((char *) &(wr[iw].infos[i+1]), (char *) &(wr[iw].infos[i]),
               sizeof(INFOS));
      }
      /* memcpy((char *) &(wr[iw].infos[pos+1]), (char *) &(wr[iw].infos[pos]),
                (wr[iw].NBinfos-pos)*sizeof(INFOS) );*/
    }
    
    info1.New_Track = TRUE;
    SetTrackInitValues(iw, pos);

    wr[iw].NBinfos++;
  }
  else {
    if (info1.visibility == FALSE) {  
      SetTrackInitValues( iw, pos);
    }
    else {
      SetTrackCurrentValues(iw, pos);
    }
  }

  memcpy((char *) &(wr[iw].infos[pos]), (char *) &info1, sizeof(INFOS)); 
}


/*
 ***************************************************************************
 *
 * ReadTracks --
 *      Get track labels information from zinc.
 *
 ***************************************************************************
 */
static void
ReadTracks(int  iw)
{
  int   i=0;
  int   trash1; /* dummy variable : received unused data */

  for (i = 0; i < wr[iw].NBinfos; i++) { 
    wr[iw].infos[i].Refresh = FALSE;
  }
  
  info1.id = NULL; 
  while ((info1.id = (*wr[iw]._next_track)(wr[iw].rw, info1.id,   
                                           &info1.x, &info1.y,
                                           &info1.vv_dx, &info1.vv_dy,
                                           /* Fri Oct 13 15:15:48 2000
                                            * &info1.label_x, &info1.label_y,            
                                            * &info1.label_width, &info1.label_height,
                                            */
                                           &info1.rho, &info1.theta,
                                           &info1.visibility,
                                           &trash1,&trash1,&trash1))) {
    info1.alpha = (ProjToAngle(info1.vv_dx, info1.vv_dy ) - M_PI_2 -
                   DegreesToRadian(info1.theta));
    info1.dx = (int) (info1.rho * cos(info1.alpha));
    info1.dy = (int) (info1.rho * sin(info1.alpha));
    info1.Refresh = TRUE;
    /* printf("OverlapMan(Om): ReadTracks  id[%-10d], x[%4.4i], y[%4.4i], \
       vv_dx[%4.4i], vv_dy[%4.4i], rho[%-3.3d], theta[%-3.3d], visi[%d]\n",
       (int)info1.id,info1.x, info1.y, info1.vv_dx,info1.vv_dy,
       info1.rho,info1.theta,info1.visibility); */
    PutTrackLoaded(iw);
  }
  
  i = 0;
  while (i < wr[iw].NBinfos) {
    /*
     * Delete non refreshed tracks from database.
     */
    if (wr[iw].infos[i].Refresh == FALSE) {
      memcpy((char *) &(wr[iw].infos[i]), (char *) &(wr[iw].infos[i+1]),
             (wr[iw].NBinfos-i-1)*sizeof(INFOS));
      wr[iw].NBinfos--;
    }
    else {
      i++;
    }
  }
}

/*
 ***************************************************************************
 *
 * OmSetNParam --
 *      Return 1 if ok, anything else if nok (non existing parameters,
 * wrong type).
 *
 ***************************************************************************
 */
int
OmSetNParam(char *name, /* parameter's name */
                        void *value)
{
  int accessid = 0;
  int status = 0;
  
  while (OmParamAccess[accessid].type !=  OM_PARAM_END) {
        if (!strcmp(name, OmParamAccess[accessid].name)) {
          /* a parameter named name has been found */
          if (OmParamAccess[accessid].rw) {
                memcpy(OmParamAccess[accessid].data, value,
                       (unsigned int) OmParamAccess[accessid].size);
                status = 1;
                break;
          }
          else {
                status = -1 ; /* data is readonly */
          };
        };
        ++accessid;
  };
  return(status);
}

/*
 ***************************************************************************
 *
 * OmGetNParam --
 *      Return 1 if ok, anything else if nok (non existing parameters,
 * wrong type).
 *
 ***************************************************************************
 */
int
OmGetNParam(char *name, /* parameter's name */
                        void *ptvalue)
{
  int accessid = 0;
  int status = 0;
  
  while (OmParamAccess[accessid].type !=  OM_PARAM_END) {
        if (!strcmp(name, OmParamAccess[accessid].name)) {
          /* a parameter named "name" has been found */
                memcpy(ptvalue,  OmParamAccess[accessid].data, 
                       (unsigned int) OmParamAccess[accessid].size);
                status = 1;
                break;
          };
        ++accessid;
  };
  return(status);
}

/*
 ***************************************************************************
 *
 * OmGetNParamList --
 *      Return 1 and next index if remains to read, the current param
 * being written in current_param. Return 0 if end of list.
 *
 ***************************************************************************
 */
int 
OmGetNParamList(OmParam *current_param, int *idx_next)
{
  int status = 0 ;
  pOMPARAM cparam ; 
  if (*idx_next < NbParam) {
        cparam = &OmParamAccess[*idx_next];
        current_param->type = cparam->type ;
        strcpy(current_param->name, cparam->name);
        /* printf("value of parameter is %f \n", *((double *)(cparam->data)));
           printf("adresse de K0 %x \n", (int)&K0); */
        ++(*idx_next) ;
        status = 1;
  };
  return(status);
}  

void
OmSetParam(double OmKrepulsion, 
           double OmKrepulsionBearing, 
           double OmKfriction, 
           double OmKbestPositionAttraction, 
           double OmKscreenEdgeRepulsion)
{
  K0 = OmKrepulsion;
  n0 = OmKrepulsionBearing;
  K1 = OmKfriction;
  K2 = OmKbestPositionAttraction;
  K3 = OmKscreenEdgeRepulsion;
}

void
OmGetParam(double *OmKrepulsion, 
           double *OmKrepulsionBearing, 
           double *OmKfriction, 
           double *OmKbestPositionAttraction, 
           double *OmKscreenEdgeRepulsion)
{
  *OmKrepulsion = K0;
  *OmKrepulsionBearing = n0;
  *OmKfriction = K1;
  *OmKbestPositionAttraction = K2;
  *OmKscreenEdgeRepulsion = K3;
}

void
OmGetMinParam(double *OmKminRepulsion, 
              double *OmKminRepulsionBearing, 
              double *OmKminFriction, 
              double *OmKminBestPositionAttraction, 
              double *OmKminScreenEdgeRepulsion)
{
  *OmKminRepulsion = K0min;
  *OmKminRepulsionBearing = n0min;
  *OmKminFriction = K1min;
  *OmKminBestPositionAttraction = K2min;
  *OmKminScreenEdgeRepulsion = K3min;
}

void
OmGetMaxParam(double *OmKmaxRepulsion, 
              double *OmKmaxRepulsionBearing, 
              double *OmKmaxFriction, 
              double *OmKmaxBestPositionAttraction, 
              double *OmKmaxScreenEdgeRepulsion)
{
  *OmKmaxRepulsion = K0max;
  *OmKmaxRepulsionBearing = n0max;
  *OmKmaxFriction = K1max;
  *OmKmaxBestPositionAttraction = K2max;
  *OmKmaxScreenEdgeRepulsion = K3max;
}


/*
 ***************************************************************************
 *
 * SetupLeaderPosition --
 *      Setup leader position for new tracks.
 *
 ***************************************************************************
 */
static void
SetupLeaderPosition(int iw,
                    int ip)
{
  double        X10, Y10, X20, Y20;
  double        D, k, Fx0, Fy0;
  int           jp;
  double        alpha;
  BOOLEAN       ok = FALSE;
  double        dx = 0, dy = 0;
  
  Fx0 = 0.0;
  Fy0 = 0.0;
  
  for (jp = 0; jp < wr[iw].NBinfos; jp++) {
    if  (wr[iw].infos[jp].New_Track == FALSE) {
      X10 = (double) (wr[iw].infos[ip].x - wr[iw].infos[jp].x - wr[iw].infos[jp].dx);
      Y10 = (double) (wr[iw].infos[ip].y - wr[iw].infos[jp].y - wr[iw].infos[jp].dy);
      X20 = ((double) (wr[iw].infos[ip].x - wr[iw].infos[jp].x) -
             (double) (wr[iw].infos[jp].dx) * COEF1 +
             (double) (wr[iw].infos[jp].dy) * COEF2);
      Y20 = ((double) (wr[iw].infos[ip].y - wr[iw].infos[jp].y) -
             (double) (wr[iw].infos[jp].dy) * COEF1 -
             (double) (wr[iw].infos[jp].dx) * COEF2);
      
      D = X10 * X10 + Y10 * Y10;
      if (D > limit_distance) {
        k = K0 / (sqrt(D) * pow(D, n0 - 1.0));
        Fx0 += X10 * k;
        Fy0 += Y10 * k;
      }
      D = X20 * X20 + Y20 * Y20;
      if (D > limit_distance) {
        k = K0 / (sqrt(D) * pow(D, n0 - 1.0));
        Fx0 += X20 * k;
        Fy0 += Y20 * k;
      }
    }
  } 
  if ((Fx0 == 0) && (Fy0 == 0)) {
    Fx0 = 1;
  }
  
  k = (double) (wr[iw].infos[ip].rho) / sqrt(Fx0*Fx0 + Fy0*Fy0);
  
  wr[iw].infos[ip].dx = (int) (Fx0 * k);
  wr[iw].infos[ip].dy = (int) (Fy0 * k);
  wr[iw].infos[ip].alpha = ProjToAngle((int) (Fx0*k), (int) (Fy0*k));
  
  alpha = wr[iw].infos[ip].alpha;
  while ((alpha < wr[iw].infos[ip].alpha + 2.0*M_PI) && (ok == FALSE)) {
    dx = (double) (wr[iw].infos[ip].rho) * cos(alpha);
    dy = (double) (wr[iw].infos[ip].rho) * sin(alpha);
    ok = TRUE;
    
    for (jp = 0; jp < wr[iw].NBinfos; jp++) {
      if  (wr[iw].infos[jp].New_Track == FALSE) {
        X10 = (double) (wr[iw].infos[ip].x + (int) dx -
                        wr[iw].infos[jp].x - wr[iw].infos[jp].dx);
        Y10 = (double) (wr[iw].infos[ip].y + (int) dy -
                        wr[iw].infos[jp].y - wr[iw].infos[jp].dy);
        D = X10 * X10 + Y10 * Y10;
        if (D < placing_min_dist) {
          ok = FALSE;
        }
      }
    }
    alpha += placing_step;
  }
  if (ok) {
    wr[iw].infos[ip].dx = (int) dx;
    wr[iw].infos[ip].dy = (int) dy;
    wr[iw].infos[ip].alpha = ProjToAngle((int) dx, (int) dy);
  }
}


/*
 ***************************************************************************
 *
 * ComputeRepulsion --
 *      Compute the moment of the repulsion forces of all the other
 *      tracks.
 *
 ***************************************************************************
 */
static double
ComputeRepulsion(int    iw,
                 int    ip)
{
  double        X10, Y10, X00, Y00, X11, Y11, X01, Y01;
  double        D0, D1, k, Fx0, Fy0, Fx1, Fy1;
  int           jp;
  
  X00 = (double) (wr[iw].infos[ip].x + wr[iw].infos[ip].dx);
  Y00 = (double) (wr[iw].infos[ip].y + wr[iw].infos[ip].dy);
  X01 = ((double) (wr[iw].infos[ip].x) +
         (double) (wr[iw].infos[ip].dx) * COEF1 -
         (double) (wr[iw].infos[ip].dy) * COEF2);
  Y01 = ((double) (wr[iw].infos[ip].y) +
         (double) (wr[iw].infos[ip].dy) * COEF1 +
         (double) (wr[iw].infos[ip].dx) * COEF2);
  Fx0 = 0.0;
  Fy0 = 0.0;
  Fx1 = 0.0;
  Fy1 = 0.0;
  
  for (jp = 0; jp < wr[iw].NBinfos; jp++) {
    if  ( ip != jp ) {
      X10 = (double) (wr[iw].infos[jp].x + wr[iw].infos[jp].dx);
      Y10 = (double) (wr[iw].infos[jp].y + wr[iw].infos[jp].dy);
      X11 = ((double) (wr[iw].infos[jp].x) +
             (double) (wr[iw].infos[jp].dx) * COEF1 -
             (double) (wr[iw].infos[jp].dy) * COEF2);
      Y11 = ((double) (wr[iw].infos[jp].y) +
             (double) (wr[iw].infos[jp].dy) * COEF1 +
             (double) (wr[iw].infos[jp].dx) * COEF2);

      D0 = (X10 - X00) * (X10 - X00) + (Y10 - Y00) * (Y10 - Y00);
      if (D0 > limit_distance) {
        k = K0 / (sqrt(D0) * pow(D0, n0 - 1.0));
        Fx0 += (X10 - X00) * k;
        Fy0 += (Y10 - Y00) * k;
      }
      D1 = (X11 - X01) * (X11 - X01) + (Y11 - Y01) * (Y11 - Y01);
      if (D1 > limit_distance) {
        k = K0 / (sqrt(D1) * pow(D1, n0 - 1.0));
        Fx1 += (X11 - X01) * k;
        Fy1 += (Y11 - Y01) * k;
      }
    }
  }
  
  return  -((double) (wr[iw].infos[ip].dx) * Fy0 -
            (double) (wr[iw].infos[ip].dy) * Fx0 +
            (double) (wr[iw].infos[ip].dx) * COEF1 * Fy1 -
            (double) (wr[iw].infos[ip].dy) * COEF2 * Fy1 - 
            (double) (wr[iw].infos[ip].dy) * COEF1 * Fx1 -
            (double) (wr[iw].infos[ip].dx) * COEF2 * Fx1);
}


/*
 ***************************************************************************
 *
 * ComputeFriction --
 *      Compute the moment of the friction force.
 *
 ***************************************************************************
 */
static double
ComputeFriction(int     iw,
                int     ip)
{
  return (double) (-K1 * wr[iw].infos[ip].alpha_point);      
}


/*
 ***************************************************************************
 *                                                                           
 * ComputeDrawback --
 *      Compute the moment of the best positions drawback forces.
 *
 ***************************************************************************
 */
static double
ComputeDrawback(int     iw,
                int     ip)
{
  int           vx, vy, dx, dy;
  double        m = 0;
  double        nd = 1.0, nv = 1.0;
  double        vi;
  
  vx = wr[iw].infos[ip].vv_dx;
  vy = wr[iw].infos[ip].vv_dy;
  dx = wr[iw].infos[ip].dx;
  dy = wr[iw].infos[ip].dy;
  
  if ((vx != 0) || (vy != 0)) {
    nv = sqrt((double)(vx * vx + vy * vy));
  }
  if ((dx != 0) || (dy != 0)) {
    nd = sqrt((double)(dx * dx + dy * dy));
  }
  
  vi = (double) (vx * dx + vy * dy)/(nd * nv);
  vi = vi <= -1.0 ? -1.0 : vi;
  vi = vi >=  1.0 ?  1.0 : vi;
  vi = 3 * M_PI_4 - acos(vi);
  
  if (vy * dx - vx * dy < 0) {
    m = -vi;
  }
  else {
    m = vi;
  }
  
  return (double) (-K2 * m);
}


/*
 ***************************************************************************
 *
 * ComputeDrawbackInView --
 *      Compute the moment of the keep in view forces.
 *
 ***************************************************************************
 */
static double
DrawbackDirection(int   vx,
                  int   vy,
                  int   dx,
                  int   dy)
{
  double        m=0;
  double        nd=1.0, nv=1.0;
  double        vi;
  
  if ((vx != 0) || (vy != 0)) {
    nv = sqrt((double)(vx * vx + vy * vy));
  }
  if ((dx != 0) || (dy != 0)) {
    nd = sqrt((double)(dx * dx + dy * dy));
  }
  
  vi = (double) (vx * dx + vy * dy)/(nd * nv);
  vi = vi <= -1.0 ? -1.0 : vi;
  vi = vi >=  1.0 ? 1.0 : vi;
  vi = acos(vi);
  
  if (vy * dx - vx * dy < 0) {
    m = vi;
  }
  else {
    m = - vi;
  }
  
  return (double) (-K3 * m);
}


static double
ComputeDrawbackInView(int       iw,
                      int       ip,
                      int       width,
                      int       height)
{
  int           r=50;
  int           dx, dy;
  double        Gamma=0;
  
  r = wr[iw].infos[ip].rho; 
  dx = wr[iw].infos[ip].dx;
  dy = wr[iw].infos[ip].dy;
  
  if (abs(wr[iw].infos[ip].x) < r) {
    Gamma += DrawbackDirection(53, 0, dx, dy);
  }
  if (abs(wr[iw].infos[ip].x - width) < r) {
    Gamma += DrawbackDirection(-53, 0, dx, dy);
  }
  if (abs(wr[iw].infos[ip].y ) < r) {
    Gamma += DrawbackDirection(0, 53, dx, dy);
  }
  if (abs(wr[iw].infos[ip].y - height) < r) {
    Gamma += DrawbackDirection(0,- 53, dx, dy);
  }

  return (double) Gamma; 
}

/*
 ***************************************************************************
 *
 * RefineSetup --
 *      Refine setup for far spaced tracks.
 *
 ***************************************************************************
 */
static void
RefineSetup(int iw,
            int ip)
{
  double        acceleration;
  int           i;

  for (i = 0; i <= 10; i++) {
    acceleration = ComputeRepulsion(iw, ip) + ComputeDrawback(iw, ip);
          
    if (acceleration > 100) {
      acceleration = 100;
    }
    if (acceleration < -100) {
      acceleration = -100;
    }
    
    wr[iw].infos[ip].alpha_point = acceleration * DELTA_T + wr[iw].infos[ip].alpha_point;
    wr[iw].infos[ip].alpha_point += ComputeFriction(iw, ip) * DELTA_T; 
    
    if (wr[iw].infos[ip].alpha_point >  30) {
      wr[iw].infos[ip].alpha_point =  30;
    }
    if (wr[iw].infos[ip].alpha_point < -30) {
      wr[iw].infos[ip].alpha_point = -30;
    }
    
    wr[iw].infos[ip].alpha = wr[iw].infos[ip].alpha_point * DELTA_T + wr[iw].infos[ip].alpha;
  }
}


/*
 ***************************************************************************
 *
 * OmProcessOverlap --
 *      Overlap Manager main function.
 *
 ***************************************************************************
 */
void
OmProcessOverlap(void   *zinc,
                 int    width,
                 int    height,
                 double scale)
{
  double        acceleration = 0.0;
  int           ip, iw;

  if (NBzincs != 0 && FindPosW(zinc, &iw) == TRUE) {
    ReadTracks(iw);

    for (ip = 0; ip < wr[iw].NBinfos; ip++) { 
      if  (wr[iw].infos[ip].New_Track == TRUE) {
        SetupLeaderPosition(iw, ip); 
        RefineSetup(iw, ip); 
        wr[iw].infos[ip].New_Track = FALSE;
      }
    }
    
    for (ip = 0; ip < wr[iw].NBinfos; ip++) {
      acceleration = (ComputeRepulsion(iw, ip) + ComputeDrawback(iw, ip) +
                      ComputeDrawbackInView(iw, ip, width, height));
      
      if (acceleration > 100) {
        acceleration = 100;
      }
      if (acceleration < -100) {
        acceleration = -100;
      }
        
      wr[iw].infos[ip].alpha_point += acceleration * DELTA_T ;
      wr[iw].infos[ip].alpha_point += ComputeFriction(iw, ip) * DELTA_T ; 
      
      if (wr[iw].infos[ip].alpha_point > 30) {
        wr[iw].infos[ip].alpha_point =  30;
      }
      if (wr[iw].infos[ip].alpha_point < -30) {
        wr[iw].infos[ip].alpha_point = -30;
      }
      
      wr[iw].infos[ip].alpha += wr[iw].infos[ip].alpha_point * DELTA_T ;
      wr[iw].infos[ip].theta = (int) RadianToDegrees360(-wr[iw].infos[ip].alpha +   
                                                        ProjToAngle(wr[iw].infos[ip].vv_dx,
                                                                    wr[iw].infos[ip].vv_dy)
                                                        - M_PI_2);
      
      /*
      if (wr[iw].infos[ip].theta > 75 && wr[iw].infos[ip].theta < 105) {
        if (wr[iw].infos[ip].alpha_point > 0) {
          wr[iw].infos[ip].theta = 105;
        }
        else {
          wr[iw].infos[ip].theta = 75;
        }
      }
      
      if (wr[iw].infos[ip].theta > 255 && wr[iw].infos[ip].theta < 285) { 
        if (wr[iw].infos[ip].alpha_point > 0) {
          wr[iw].infos[ip].theta = 285;
        }
        else {
          wr[iw].infos[ip].theta = 255;
        }
      }
      */

      (*wr[iw]._set_label_angle) (wr[iw].rw, wr[iw].infos[ip].id,
                                  120, wr[iw].infos[ip].theta, NULL);
      /* wr[iw].infos[ip].rho*/      
    }
  }
}

Added jni/tkzinc/generic/OverlapMan.h.



























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * OverlapMan.h -- Track label overlap avoidance manager header file
 *
 * Authors              :
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _OverlapMan_h
#define _OverlapMan_h


#include <string.h>
#include <math.h>

/*
 * Init code.
 */
void
OmInit();

/*
 * This is the interface with the zinc widget. To substitute
 * a different overlap manager, it is necessary to conform to
 * this API.
 */
void
OmRegister(void *w,
           void *(*_fnext_track)(void *ptr,
                                 void *item,
                                 int *x, int *y,
                                 int *sv_dx, int *sv_dy,
                                 /* Fri Oct 13 15:16:13 2000
                                 int *label_x, int *label_y,
                                 int *label_width, int *label_height,
                                 */
                                 int *rho, int *theta,
                                 int *visibility,
                                 int *locked ,
                                 int *preferred_angle  ,
                                 int *convergence_style),
           void (*_fset_label_angle)(void *ptr, void *item, int rho, int theta, char *reason),
           void (*_fquery_label_pos)(void *ptr, void *item, int theta,
                                     int *x, int *y, int *w, int *h));
void
OmUnregister(void       *w);
void
OmProcessOverlap(void   *zinc,
                 int    width,
                 int    height,
                 double scale);


/* 
 * Parameter data type which ease exchange of parameters between
 * Radar Image toolkit and Om library
 */
#define OM_PARAM_END       0
#define OM_PARAM_INT       1
#define OM_PARAM_FLOAT     2
#define OM_PARAM_DOUBLE    3
#define OM_PARAM_STRING    4


typedef struct {
  int  type     ;  /* should be among OM_PARAM_ */
  char name[50] ;
} OmParam ;


/*
 * These are the generic overlap manager public functions used
 * to set/get any parameters that the Om library allow to modify
 * dynamically (tunable parameters)
 */

/* OmSetNParam
   return 1 if ok , anythingelse if nok (non existing parameters ,
   wrong type) */
int
OmSetNParam(char *name, /* parameter's name */
                        void *value);
/* OmGetNParam
   return 1 if ok , anythingelse if nok (non existing parameters ,
   wrong type)
 */
int
OmGetNParam(char *name, /* parameter's name */
                        void *ptvalue);

/* OmGetNParamList
   return 1 and next index if remains to read, the current param
   being written in current_param
   return 0 if end of list and no param */
int 
OmGetNParamList(OmParam *current_param, int *idx_next);


#endif  /* _OverlapMan_h */

Added jni/tkzinc/generic/PostScript.c.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
/*
 * PostScript.c -- Implementation of PostScript driver.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Tue Jan 3 13:17:17 1995
 *
 * $Id$
 */

/*
 *  Copyright (c) 1995 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
 * This code is based on tkCanvPs.c which is copyright:
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 */

/*
 **********************************************************************************
 *
 * Included files
 *
 **********************************************************************************
 */

#ifndef _WIN32
#include <unistd.h>
#include <pwd.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>

#include "Types.h"
#include "Item.h"
#include "Group.h"
#include "PostScript.h"
#include "WidgetInfo.h"
#include "Geo.h"


/*
 **********************************************************************************
 *
 * Constants.
 * 
 **********************************************************************************
 */

static  const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 * One of the following structures is created to keep track of Postscript
 * output being generated.  It consists mostly of information provided on
 * the widget command line.
 * WATCH! This structure must be kept in sync with the structure in
 * tkCanvPs.c, we share most of the code for emitting postscript and
 * this rely on sharing the structure.
 */
typedef struct TkPostscriptInfo {
  int           x, y, width, height; /* Area to print, in canvas pixel
                                      * coordinates. */
  int           x2, y2;              /* x+width and y+height. */
  char          *pageXString;        /* String value of "-pagex" option or NULL. */
  char          *pageYString;        /* String value of "-pagey" option or NULL. */
  double        pageX, pageY;        /* Postscript coordinates (in points)
                                      * corresponding to pageXString and
                                      * pageYString. Don't forget that y-values
                                      * grow upwards for Postscript! */
  char          *pageWidthString;    /* Printed width of output. */
  char          *pageHeightString;   /* Printed height of output. */
  double        scale;               /* Scale factor for conversion: each pixel
                                      * maps into this many points. */
  Tk_Anchor     pageAnchor;          /* How to anchor bbox on Postscript page. */
  int           rotate;              /* Non-zero means output should be rotated
                                      * on page (landscape mode). */
  char          *fontVar;            /* If non-NULL, gives name of global variable
                                      * containing font mapping information.
                                      * Malloc'ed. */
  char          *colorVar;           /* If non-NULL, give name of global variable
                                      * containing color mapping information.
                                      * Malloc'ed. */
  char          *colorMode;          /* Mode for handling colors:  "monochrome",
                                      * "gray", or "color".  Malloc'ed. */
  int           colorLevel;          /* Numeric value corresponding to colorMode:
                                      * 0 for mono, 1 for gray, 2 for color. */
  char          *fileName;           /* Name of file in which to write Postscript;
                                      * NULL means return Postscript info as
                                      * result. Malloc'ed. */
  char          *channelName;        /* If -channel is specified, the name of
                                      * the channel to use. */
  Tcl_Channel   chan;                /* Open channel corresponding to fileName. */
  Tcl_HashTable fontTable;           /* Hash table containing names of all font
                                      * families used in output.  The hash table
                                      * values are not used. */
  int           prepass;             /* Non-zero means that we're currently in
                                      * the pre-pass that collects font information,
                                      * so the Postscript generated isn't
                                      * relevant. */
  int           prolog;              /* Non-zero means output should contain
                                      * the file prolog.ps in the header. */
  /*
   * Below are extensions for Tkzinc.
   */
   ZnBBox       bbox;
} TkPostscriptInfo;

/*
 * The table below provides a template that's used to process arguments
 * to the "postscript" command and fill in TkPostscriptInfo structures.
 */
static Tk_ConfigSpec config_specs[] = {
  {TK_CONFIG_STRING, "-colormap", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, colorVar), 0, NULL},
  {TK_CONFIG_STRING, "-colormode", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, colorMode), 0, NULL},
  {TK_CONFIG_STRING, "-file", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, fileName), 0, NULL},
  {TK_CONFIG_STRING, "-channel", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, channelName), 0, NULL},
  {TK_CONFIG_STRING, "-fontmap", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, fontVar), 0, NULL},
  {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, height), 0, NULL},
  {TK_CONFIG_ANCHOR, "-pageanchor", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, pageAnchor), 0, NULL},
  {TK_CONFIG_STRING, "-pageheight", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, pageHeightString), 0, NULL},
  {TK_CONFIG_STRING, "-pagewidth", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, pageWidthString), 0, NULL},
  {TK_CONFIG_STRING, "-pagex", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, pageXString), 0, NULL},
  {TK_CONFIG_STRING, "-pagey", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, pageYString), 0, NULL},
  {TK_CONFIG_BOOLEAN, "-prolog", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, prolog), 0, NULL},
  {TK_CONFIG_BOOLEAN, "-rotate", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, rotate), 0, NULL},
  {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, width), 0, NULL},
  {TK_CONFIG_PIXELS, "-x", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, x), 0, NULL},
  {TK_CONFIG_PIXELS, "-y", (char *) NULL, (char *) NULL,
   "", Tk_Offset(TkPostscriptInfo, y), 0, NULL},
  {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
   (char *) NULL, 0, 0, NULL}
};

/*
 *--------------------------------------------------------------
 *
 * GetPostscriptPoints --
 *
 *  Given a string, returns the number of Postscript points
 *  corresponding to that string.
 *
 * Results:
 *  The return value is a standard Tcl return result.  If
 *  TCL_OK is returned, then everything went well and the
 *  screen distance is stored at *doublePtr;  otherwise
 *  TCL_ERROR is returned and an error message is left in
 *  the interp's result.
 *
 * Side effects:
 *  None.
 *
 *--------------------------------------------------------------
 */
static int
GetPostscriptPoints(Tcl_Interp *interp,
                    char       *string,
                    double     *double_ptr)
{
  char *end;
  double d;

  d = strtod(string, &end);
  if (end == string) {
  error:
    Tcl_AppendResult(interp, "bad distance \"", string, "\"", (char *) NULL);
    return TCL_ERROR;
  }
  while ((*end != '\0') && isspace(UCHAR(*end))) {
    end++;
  }
  switch (*end) {
  case 'c':
    d *= 72.0/2.54;
    end++;
    break;
  case 'i':
    d *= 72.0;
    end++;
    break;
  case 'm':
    d *= 72.0/25.4;
    end++;
    break;
  case 0:
    break;
  case 'p':
    end++;
    break;
  default:
    goto error;
  }
  while ((*end != '\0') && isspace(UCHAR(*end))) {
    end++;
  }
  if (*end != 0) {
    goto error;
  }
  *double_ptr = d;
  return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ZnPostScriptCmd --
 *
 *  This procedure is invoked to process the "postscript" options
 *  of the widget command for zinc widgets. See the user
 *  documentation for details on what it does.
 *
 * Results:
 *  A standard Tcl result.
 *
 * Side effects:
 *  See the user documentation.
 *
 *--------------------------------------------------------------
 */
int
ZnPostScriptCmd(ZnWInfo        *wi,
                int            argc,
                Tcl_Obj *CONST argv[])
{
  TkPostscriptInfo  ps_info;
  Tk_PostscriptInfo old_info;
  int               result;
#define STRING_LENGTH 400
  char              string[STRING_LENGTH+1];
  CONST char        *p;
  time_t            now;
  size_t            length;
  Tk_Window         tkwin = wi->win;
  /*
   *  Offset of lower-left corner of area to be marked up, measured
   * in canvas units from the positioning point on the page (reflects
   * anchor position).  Initial values needed only to stop compiler
   * warnings. 
   */
  int               delta_x = 0, delta_y = 0;
  Tcl_HashSearch    search;
  Tcl_HashEntry     *entry;
  Tcl_DString       buffer;
  char              psenccmd[] = "::tk::ensure_psenc_is_loaded";

  /*
   *----------------------------------------------------------------
   * Initialize the data structure describing Postscript generation,
   * then process all the arguments to fill the data structure in.
   *----------------------------------------------------------------
   */
#ifndef PTK
  result = Tcl_EvalEx(wi->interp, psenccmd, -1, TCL_EVAL_GLOBAL);
#endif
  if (result != TCL_OK) {
    return result;
  }
  old_info = wi->ps_info;
  wi->ps_info = (Tk_PostscriptInfo) &ps_info;
  ps_info.x = (int) wi->origin.x;
  ps_info.y = (int) wi->origin.y;
  ps_info.width = -1;
  ps_info.height = -1;
  ps_info.pageXString = NULL;
  ps_info.pageYString = NULL;
  ps_info.pageX = 72*4.25;
  ps_info.pageY = 72*5.5;
  ps_info.pageWidthString = NULL;
  ps_info.pageHeightString = NULL;
  ps_info.scale = 1.0;
  ps_info.pageAnchor = TK_ANCHOR_CENTER;
  ps_info.rotate = 0;
  ps_info.fontVar = NULL;
  ps_info.colorVar = NULL;
  ps_info.colorMode = NULL;
  ps_info.colorLevel = 0;
  ps_info.fileName = NULL;
  ps_info.channelName = NULL;
  ps_info.chan = NULL;
  ps_info.prepass = 0;
  ps_info.prolog = 1;
  Tcl_InitHashTable(&ps_info.fontTable, TCL_STRING_KEYS);
  result = Tk_ConfigureWidget(wi->interp, wi->win, config_specs,
                              argc-2, (CONST char **) argv+2,
                              (char *) &ps_info,
                              TK_CONFIG_ARGV_ONLY|TK_CONFIG_OBJS);
  if (result != TCL_OK) {
    goto cleanup;
  }

  if (ps_info.width == -1) {
    ps_info.width = Tk_Width(tkwin);
  }
  if (ps_info.height == -1) {
    ps_info.height = Tk_Height(tkwin);
  }
  ps_info.x2 = ps_info.x + ps_info.width;
  ps_info.y2 = ps_info.y + ps_info.height;
  ps_info.bbox.orig.x = ps_info.x;
  ps_info.bbox.orig.y = ps_info.y;
  ps_info.bbox.corner.x = ps_info.x2;
  ps_info.bbox.corner.y = ps_info.y2;

  if (ps_info.pageXString != NULL) {
    if (GetPostscriptPoints(wi->interp, ps_info.pageXString, &ps_info.pageX) != TCL_OK) {
      goto cleanup;
    }
  }
  if (ps_info.pageYString != NULL) {
    if (GetPostscriptPoints(wi->interp, ps_info.pageYString, &ps_info.pageY) != TCL_OK) {
      goto cleanup;
    }
  }
  if (ps_info.pageWidthString != NULL) {
    if (GetPostscriptPoints(wi->interp, ps_info.pageWidthString, &ps_info.scale) != TCL_OK) {
      goto cleanup;
    }
    ps_info.scale /= ps_info.width;
  }
  else if (ps_info.pageHeightString != NULL) {
    if (GetPostscriptPoints(wi->interp, ps_info.pageHeightString, &ps_info.scale) != TCL_OK) {
      goto cleanup;
    }
    ps_info.scale /= ps_info.height;
  }
  else {
    ps_info.scale = (72.0/25.4)*WidthMMOfScreen(Tk_Screen(tkwin));
    ps_info.scale /= WidthOfScreen(Tk_Screen(tkwin));
  }
  switch (ps_info.pageAnchor) {
  case TK_ANCHOR_NW:
  case TK_ANCHOR_W:
  case TK_ANCHOR_SW:
    delta_x = 0;
    break;
  case TK_ANCHOR_N:
  case TK_ANCHOR_CENTER:
  case TK_ANCHOR_S:
    delta_x = -ps_info.width/2;
    break;
  case TK_ANCHOR_NE:
  case TK_ANCHOR_E:
  case TK_ANCHOR_SE:
    delta_x = -ps_info.width;
    break;
  }
  switch (ps_info.pageAnchor) {
  case TK_ANCHOR_NW:
  case TK_ANCHOR_N:
  case TK_ANCHOR_NE:
    delta_y = - ps_info.height;
    break;
  case TK_ANCHOR_W:
  case TK_ANCHOR_CENTER:
  case TK_ANCHOR_E:
    delta_y = -ps_info.height/2;
    break;
  case TK_ANCHOR_SW:
  case TK_ANCHOR_S:
  case TK_ANCHOR_SE:
    delta_y = 0;
    break;
  }

  if (ps_info.colorMode == NULL) {
    ps_info.colorLevel = 2;
  }
  else {
    length = strlen(ps_info.colorMode);
    if (strncmp(ps_info.colorMode, "monochrome", length) == 0) {
      ps_info.colorLevel = 0;
    }
    else if (strncmp(ps_info.colorMode, "gray", length) == 0) {
      ps_info.colorLevel = 1;
    }
    else if (strncmp(ps_info.colorMode, "color", length) == 0) {
      ps_info.colorLevel = 2;
    }
    else {
      Tcl_AppendResult(wi->interp, "bad color mode \"", ps_info.colorMode,
                       "\": must be monochrome, ", "gray, or color",
                       (char *) NULL);
      goto cleanup;
    }
  }

  if (ps_info.fileName != NULL) {
    /*
     * Check that -file and -channel are not both specified.
     */
    if (ps_info.channelName != NULL) {
      Tcl_AppendResult(wi->interp, "can't specify both -file", " and -channel",
                       (char *) NULL);
      result = TCL_ERROR;
      goto cleanup;
    }
    /*
     * Check that we are not in a safe interpreter. If we are, disallow
     * the -file specification.
     */
    if (Tcl_IsSafe(wi->interp)) {
      Tcl_AppendResult(wi->interp, "can't specify -file in a", " safe interpreter",
                       (char *) NULL);
      result = TCL_ERROR;
      goto cleanup;
    }
        
    p = Tcl_TranslateFileName(wi->interp, ps_info.fileName, &buffer);
    if (p == NULL) {
      goto cleanup;
    }
    ps_info.chan = Tcl_OpenFileChannel(wi->interp, p, "w", 0666);
    Tcl_DStringFree(&buffer);
    if (ps_info.chan == NULL) {
      goto cleanup;
    }
  }

  if (ps_info.channelName != NULL) {
    int mode;
        
    /*
     * Check that the channel is found in this interpreter and that it
     * is open for writing.
     */
    ps_info.chan = Tcl_GetChannel(wi->interp, ps_info.channelName, &mode);
    if (ps_info.chan == (Tcl_Channel) NULL) {
      result = TCL_ERROR;
      goto cleanup;
    }
    if ((mode & TCL_WRITABLE) == 0) {
      Tcl_AppendResult(wi->interp, "channel \"", ps_info.channelName,
                       "\" wasn't opened for writing", (char *) NULL);
      result = TCL_ERROR;
      goto cleanup;
    }
  }

  /*
   *--------------------------------------------------------
   * Make a pre-pass over all of the items, generating Postscript
   * and then throwing it away.  The purpose of this pass is just
   * to collect information about all the fonts in use, so that
   * we can output font information in the proper form required
   * by the Document Structuring Conventions.
   *--------------------------------------------------------
   */
  ps_info.prepass = 1;
  result = wi->top_group->class->PostScript(wi->top_group, True, &ps_info.bbox);
  Tcl_ResetResult(wi->interp);
  /*
   * If an error occurred, just proceed with the main pass.
   * There's no need to report the error now;  it can be
   * reported later (errors can happen later that don't
   * happen now, so we still have to check for errors later
   * anyway).
   */
  ps_info.prepass = 0;

  /*
   *--------------------------------------------------------
   * Generate the header and prolog for the Postscript.
   *--------------------------------------------------------
   */
  if (ps_info.prolog) {
    Tcl_AppendResult(wi->interp, "%!PS-Adobe-3.0 EPSF-3.0\n",
                     "%%Creator: Tk Zinc Widget\n", (char *) NULL);
#ifdef HAVE_PW_GECOS
    if (!Tcl_IsSafe(wi->interp)) {
      struct passwd *pwPtr = getpwuid(getuid());  /* INTL: Native. */
      Tcl_AppendResult(wi->interp, "%%For: ",
                       (pwPtr != NULL) ? pwPtr->pw_gecos : "Unknown", "\n",
                       (char *) NULL);
      endpwent();
    }
#endif /* HAVE_PW_GECOS */
    Tcl_AppendResult(wi->interp, "%%Title: Window ", Tk_PathName(tkwin), "\n",
                     (char *) NULL);
    time(&now);
    /* INTL: Native. */
    Tcl_AppendResult(wi->interp, "%%CreationDate: ", ctime(&now), (char *) NULL);
    if (!ps_info.rotate) {
      sprintf(string, "%d %d %d %d", (int) (ps_info.pageX + ps_info.scale*delta_x),
              (int) (ps_info.pageY + ps_info.scale*delta_y),
              (int) (ps_info.pageX + ps_info.scale*(delta_x + ps_info.width) + 1.0),
              (int) (ps_info.pageY + ps_info.scale*(delta_y + ps_info.height) + 1.0));
    }
    else {
      sprintf(string, "%d %d %d %d",
              (int) (ps_info.pageX - ps_info.scale*(delta_y + ps_info.height)),
              (int) (ps_info.pageY + ps_info.scale*delta_x),
              (int) (ps_info.pageX - ps_info.scale*delta_y + 1.0),
              (int) (ps_info.pageY + ps_info.scale*(delta_x + ps_info.width) + 1.0));
    }
    Tcl_AppendResult(wi->interp, "%%BoundingBox: ", string, "\n", (char *) NULL);
    Tcl_AppendResult(wi->interp, "%%Pages: 1\n", "%%DocumentData: Clean7Bit\n",
                     (char *) NULL);
    Tcl_AppendResult(wi->interp, "%%Orientation: ",
                     ps_info.rotate ? "Landscape\n" : "Portrait\n", (char *) NULL);
    p = "%%DocumentNeededResources: font ";
    for (entry = Tcl_FirstHashEntry(&ps_info.fontTable, &search); entry != NULL;
         entry = Tcl_NextHashEntry(&search)) {
      Tcl_AppendResult(wi->interp, p, Tcl_GetHashKey(&ps_info.fontTable, entry),
                       "\n", (char *) NULL);
      p = "%%+ font ";
    }
    Tcl_AppendResult(wi->interp, "%%EndComments\n\n", (char *) NULL);

    /*
     * Insert the prolog
     */
    Tcl_AppendResult(wi->interp, Tcl_GetVar(wi->interp,"::tk::ps_preamable",
                     TCL_GLOBAL_ONLY), (char *) NULL);

    if (ps_info.chan != NULL) {
      Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
      Tcl_ResetResult(wi->interp);
    }

    /*
     *-----------------------------------------------------------
     * Document setup:  set the color level and include fonts.
     *-----------------------------------------------------------
     */
    sprintf(string, "/CL %d def\n", ps_info.colorLevel);
    Tcl_AppendResult(wi->interp, "%%BeginSetup\n", string, (char *) NULL);
    for (entry = Tcl_FirstHashEntry(&ps_info.fontTable, &search); entry != NULL;
         entry = Tcl_NextHashEntry(&search)) {
      Tcl_AppendResult(wi->interp, "%%IncludeResource: font ",
      Tcl_GetHashKey(&ps_info.fontTable, entry), "\n", (char *) NULL);
    }
    Tcl_AppendResult(wi->interp, "%%EndSetup\n\n", (char *) NULL);

    /*
     *-----------------------------------------------------------
     * Page setup:  move to page positioning point, rotate if
     * needed, set scale factor, offset for proper anchor position,
     * and set clip region.
     *-----------------------------------------------------------
     */
    Tcl_AppendResult(wi->interp, "%%Page: 1 1\n", "save\n", (char *) NULL);
    sprintf(string, "%.1f %.1f translate\n", ps_info.pageX, ps_info.pageY);
    Tcl_AppendResult(wi->interp, string, (char *) NULL);
    if (ps_info.rotate) {
      Tcl_AppendResult(wi->interp, "90 rotate\n", (char *) NULL);
    }
    sprintf(string, "%.4g %.4g scale\n", ps_info.scale, -ps_info.scale);
    Tcl_AppendResult(wi->interp, string, (char *) NULL);
    sprintf(string, "%d %d translate\n", delta_x - ps_info.x, delta_y);
    Tcl_AppendResult(wi->interp, string, (char *) NULL);
    /*
     * Save the base matrix for further reference.
     */
    Tcl_AppendResult(wi->interp, "/InitialTransform matrix currentmatrix def\n", NULL);

    sprintf(string, "%d %.15g moveto %d %.15g lineto %d %.15g lineto %d %.15g",
            ps_info.x, Tk_PostscriptY((double) ps_info.y, (Tk_PostscriptInfo) &ps_info),
            ps_info.x2, Tk_PostscriptY((double) ps_info.y, (Tk_PostscriptInfo) &ps_info),
            ps_info.x2, Tk_PostscriptY((double) ps_info.y2, (Tk_PostscriptInfo) &ps_info),
            ps_info.x, Tk_PostscriptY((double) ps_info.y2, (Tk_PostscriptInfo) &ps_info));
    Tcl_AppendResult(wi->interp, string, " lineto closepath clip newpath\n", (char *) NULL);
  }
  if (ps_info.chan != NULL) {
    Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
    Tcl_ResetResult(wi->interp);
  }

  /*
   *---------------------------------------------------------------------
   * Iterate through all the items, having each relevant one draw itself.
   * Quit if any of the items returns an error.
   *---------------------------------------------------------------------
   */
  result = wi->top_group->class->PostScript(wi->top_group, False, &ps_info.bbox);
  if (result == TCL_ERROR) {
    goto cleanup;
  }

  /*
   *---------------------------------------------------------------------
   * Output page-end information, such as commands to print the page
   * and document trailer stuff.
   *---------------------------------------------------------------------
   */
  if (ps_info.prolog) {
    Tcl_AppendResult(wi->interp, "restore showpage\n\n", "%%Trailer\nend\n%%EOF\n",
                     (char *) NULL);
  }
  if (ps_info.chan != NULL) {
    Tcl_Write(ps_info.chan, Tcl_GetStringResult(wi->interp), -1);
    Tcl_ResetResult(wi->interp);
  }

  /*
   * Clean up ps_info to release malloc'ed stuff.
   */
  cleanup:
  if (ps_info.pageXString != NULL) {
    ckfree(ps_info.pageXString);
  }
  if (ps_info.pageYString != NULL) {
    ckfree(ps_info.pageYString);
  }
  if (ps_info.pageWidthString != NULL) {
    ckfree(ps_info.pageWidthString);
  }
  if (ps_info.pageHeightString != NULL) {
    ckfree(ps_info.pageHeightString);
  }
  if (ps_info.fontVar != NULL) {
    ckfree(ps_info.fontVar);
  }
  if (ps_info.colorVar != NULL) {
    ckfree(ps_info.colorVar);
  }
  if (ps_info.colorMode != NULL) {
    ckfree(ps_info.colorMode);
  }
  if (ps_info.fileName != NULL) {
    ckfree(ps_info.fileName);
  }
  if ((ps_info.chan != NULL) && (ps_info.channelName == NULL)) {
  Tcl_Close(wi->interp, ps_info.chan);
  }
  if (ps_info.channelName != NULL) {
    ckfree(ps_info.channelName);
  }
  Tcl_DeleteHashTable(&ps_info.fontTable);
  wi->ps_info = (Tk_PostscriptInfo) old_info;
  return result;
}

void
ZnFlushPsChan(Tcl_Interp        *interp,
              Tk_PostscriptInfo ps_info) {
  TkPostscriptInfo  *psi = (TkPostscriptInfo *) ps_info;
  if (psi->chan != NULL) {
    Tcl_Write(psi->chan, Tcl_GetStringResult(interp), -1);
    Tcl_ResetResult(interp);
  }
}

int
ZnPostscriptOutline(Tcl_Interp        *interp,
                    Tk_PostscriptInfo ps_info,
                    Tk_Window         tkwin,
                    ZnDim             line_width,
                    ZnLineStyle       line_style,
                    ZnGradient        *line_color,
                    ZnImage           line_pattern)
{
  char string[41];
  char dashed[] = { 8 };
  char dotted[] = { 2, 5 };
  char mixed[] = { 8, 5, 2, 5 };
  char *pattern = NULL;
  int patlen = 0;

  sprintf(string, "%.15g setlinewidth\n", (double) line_width);
  Tcl_AppendResult(interp, string, NULL);
  /*
   * Setup the line style. It is dependent on the line
   * width.
   */
  switch (line_style) {
    case ZN_LINE_DOTTED:
      pattern = dotted;
      patlen = sizeof(dotted)/sizeof(char);
      break;
    case ZN_LINE_DASHED:
      pattern = dashed;
      patlen = sizeof(dashed)/sizeof(char);
      break;
    case ZN_LINE_MIXED:
      pattern = mixed;
      patlen = sizeof(mixed)/sizeof(char);
      break;
  }
  if (pattern) {
    sprintf(string, "[%d", ((*pattern++) * (int) line_width) & 0xff);
    while (--patlen) {
      sprintf(string+strlen(string), " %d", ((*pattern++) * (int) line_width) & 0xff);
    }
    Tcl_AppendResult(interp, string, NULL);
    sprintf(string, "] %d setdash\n", 0 /* dash offset */);
    Tcl_AppendResult(interp, string, NULL);
  }
  if (Tk_PostscriptColor(interp, ps_info,
                         ZnGetGradientColor(line_color, 0.0, NULL)) != TCL_OK) {
    return TCL_ERROR;
  }
  if (line_pattern != ZnUnspecifiedImage) {
    Tcl_AppendResult(interp, "StrokeClip ", NULL);
    if (Tk_PostscriptStipple(interp, tkwin, ps_info,
                             ZnImagePixmap(line_pattern, tkwin)) != TCL_OK) {
      return TCL_ERROR;
    }
  }
  else {
    Tcl_AppendResult(interp, "stroke\n", NULL);
  }
  
  return TCL_OK;
}

/*
 * Emit PostScript to describe a bitmap as a string possibly
 * spliting it in parts due to the limited length of PostScript
 * strings.
 * This function emit the common code for ZnPostscriptBitmap and
 * ZnPostscriptStipple.
 */
#if 0
static int
EmitPSBitmap()
{
  return TCL_OK;
}
#endif

int
ZnPostscriptStipple(Tcl_Interp          *interp,
                    Tk_Window           tkwin,
                    Tk_PostscriptInfo   ps_info,
                    ZnImage             bitmap)
{
  return TCL_OK;
}

int
ZnPostscriptBitmap(Tcl_Interp        *interp,
                   Tk_Window         tkwin,
                   Tk_PostscriptInfo ps_info,
                   ZnImage           bitmap,
                   ZnReal            x,
                   ZnReal            y,
                   int               width,
                   int               height)
{
  char buffer[100 + TCL_DOUBLE_SPACE * 2 + TCL_INTEGER_SPACE * 4];
  int rows_at_once, rows_this_time, cur_row;

  if (width > 60000) {
    Tcl_ResetResult(interp);
    Tcl_AppendResult(interp, "can't generate Postscript",
                     " for bitmaps more than 60000 pixels wide", NULL);
    return TCL_ERROR;
  }
  rows_at_once = 60000/width;
  if (rows_at_once < 1) {
    rows_at_once = 1;
  }
  sprintf(buffer, "%.15g %.15g translate\n", x, y + height);
  Tcl_AppendResult(interp, buffer, NULL);
  for (cur_row = 0; cur_row < height; cur_row += rows_at_once) {
    rows_this_time = rows_at_once;
    if (rows_this_time > (height - cur_row)) {
      rows_this_time = height - cur_row;
    }
    sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n",
            (double) rows_this_time, width, rows_this_time);
    Tcl_AppendResult(interp, buffer, NULL);
    if (Tk_PostscriptBitmap(interp, tkwin, ps_info,  ZnImagePixmap(bitmap, tkwin),
                            0, cur_row, width, rows_this_time) != TCL_OK) {
      return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "\n} imagemask\n", (char *) NULL);
  }

  return TCL_OK;
}

void
ZnPostscriptString(Tcl_Interp   *interp,
                   char         *str,
                   int          num_bytes)
{
#ifndef PTK_800

  int         used, len, clen;
  int         c, bytecount = 0;
  CONST char  *p, *last_p, *glyphname;
  Tcl_UniChar ch;
  char        charbuf[5];
#define MAXUSE 500
  char        buf[MAXUSE+30];

	used = 0;
	buf[used++] = '[';
	buf[used++] = '(';
  len = num_bytes;
  p = str;
  while (len) {
    clen = Tcl_UtfToUniChar(p, &ch);
    last_p = p;
    p += clen;
    len -= clen;
    /*
     * INTL: For now we just treat the characters as binary
     * data and display the lower byte.  Eventually this should
     * be revised to handle international postscript fonts.
     */
    Tcl_UtfToExternal(interp, NULL, last_p, clen, 0, NULL,
                      charbuf, 4, NULL, &bytecount, NULL);
    if (bytecount == 1) {
      c = UCHAR(charbuf[0]);
      if ((c == '(') || (c == ')') || (c == '\\') ||
          (c < 0x20) || (c >= UCHAR(0x7f))) {
        /*
         * Tricky point:  the "03" is necessary in the sprintf
         * below, so that a full three digits of octal are
         * always generated.  Without the "03", a number
         * following this sequence could be interpreted by
         * Postscript as part of this sequence.
         */
        sprintf(buf + used, "\\%03o", c);
        used += 4;
      }
      else {
        buf[used++] = c;
      }
    }
    else {
      /* This character doesn't belong to system character set.
       * So, we must use full glyph name */
      sprintf(charbuf, "%04X", ch); /* endianness? */
      if ((glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", charbuf, 0))) {
        if ((used > 0) && (buf[used-1] == '(')) {
          --used;
        }
        else {
          buf[used++] = ')';
        }
        if ((used + strlen(glyphname)) >= MAXUSE) {
          buf[used] = '\0';
          Tcl_AppendResult(interp, buf, NULL);
          used = 0;
        }
        buf[used++] = '/';
        while(*glyphname) {
          buf[used++] = *glyphname++ ;
        }
        buf[used++] = '(';
      }
    }
    if (used >= MAXUSE) {
      buf[used] = '\0';
      Tcl_AppendResult(interp, buf, NULL);
      used = 0;
    }
  }
  buf[used++] = ')';
  buf[used++] = ']';
  buf[used++] = '\n';
  buf[used] = '\0';
  Tcl_AppendResult(interp, buf, NULL);

#endif
}

int
ZnPostscriptTile(Tcl_Interp        *interp,
                 Tk_Window         win,
                 Tk_PostscriptInfo ps_info,
                 ZnImage           image)
{
  char path[150];
  int  w, h;

  ZnSizeOfImage(image, &w, &h);
  Tcl_AppendResult(interp, "<< /PatternType 1 /PaintType 1 /TilingType 1\n", NULL);
  sprintf(path, "  /BBox [%.15g %.15g %.15g %.15g] /XStep %.15g /YStep %.15g\n",
          0.0, (double) h, (double) w, 0.0, (double) w, (double) h);
  Tcl_AppendResult(interp, path, "  /PaintProc { begin\n", NULL);

  /*
   * On ne peut pas reprendre le code de Tk_PostscriptImage,
   * il génère une image inline impropre à l'inclusion dans
   * une procedure de tuilage. C'est d'ailleurs un problème :
   * Une string postscript ne doit pas dépasser 65K.
   */
  if (Tk_PostscriptImage(ZnImageTkImage(image), interp, win, ps_info, 0, 0, w, h, 0) != TCL_OK) {
    return TCL_ERROR;
  }

  Tcl_AppendResult(interp, "end } bind >> matrix makepattern setpattern fill\n", NULL);

  return TCL_OK;
}

void
ZnPostscriptTrace(ZnItem item,
                  ZnBool enter)
{
  ZnWInfo *wi = item->wi;
  char    buf[100];

  if (wi->debug) {
    sprintf(buf, "%%%%%%%% %s for %s %d %%%%%%%%\n",
            enter ? "Code" : "End of code", item->class->name, item->id);
    Tcl_AppendResult(wi->interp, buf, NULL);
  }
}

int
ZnPostscriptGradient(Tcl_Interp        *interp,
                     Tk_PostscriptInfo ps_info,
                     ZnGradient        *gradient,
                     ZnPoint           *quad,
                     ZnPoly            *poly)
{
  unsigned int    i;
  char            path[150];
  ZnPoint         p, center, extent;
  ZnGradientColor *gc1, *gc2;

  if (gradient->type == ZN_CONICAL_GRADIENT || gradient->type == ZN_PATH_GRADIENT) {
    return TCL_OK;
  }

  Tcl_AppendResult(interp, "<< /PatternType 2 /Shading\n", NULL);

  switch (gradient->type) {
    case ZN_AXIAL_GRADIENT:
      /*
       * Fill the rectangle defined by quad with
       * the axial gradient.
       */
      switch (gradient->angle) {
        case 0:
          center = quad[0];
          extent = quad[1];
        case 90:
          center = quad[0];
          extent = quad[3];
          break;
        case 180:
          center = quad[1];
          extent = quad[0];
          break;
        case 270:
          center = quad[3];
          extent = quad[0];
          break;
      }
      Tcl_AppendResult(interp,
                       "  << /ShadingType 2 /ColorSpace /DeviceRGB /Extend [true true] ",
                       NULL); 
      sprintf(path, "/Coords [%.15g %.15g %.15g %.15g]\n",
              quad[0].x, quad[0].y, quad[1].x, quad[1].y);
      Tcl_AppendResult(interp, path, NULL);
      break;
    case ZN_RADIAL_GRADIENT:
      /*
       * On ne peut pas représenter un dégradé radial ou conique
       * anamorphique si on n'inclu pas la transformation dans le
       * PostScript résultant. PostScript ne peut décrire que des
       * dégradés circulaires. La seule solution rapide est d'utiliser
       * comme dans l'item Triangles une trame de triangles (Shading
       * type 4).
       */
      p.x = p.y = 0;
      ZnTransformPoint((ZnTransfo *) quad, &p, &center);
      p.x = 1.0;
      ZnTransformPoint((ZnTransfo *) quad, &p, &extent);
      Tcl_AppendResult(interp,
                       "  << /ShadingType 3 /ColorSpace /DeviceRGB /Extend [true true] ",
                       NULL); 
      sprintf(path, "/Coords [%.15g %.15g %.15g %.15g %.15g %.15g]\n",
              center.x, center.y, 0.0, center.x, center.y, ABS(center.x-extent.x));
      printf("center %g %g, radius %g\n", center.x, center.y, ABS(center.x-extent.x));
      Tcl_AppendResult(interp, path, NULL);
      break;
    case ZN_CONICAL_GRADIENT:
      break;
    case ZN_PATH_GRADIENT:
      break;
  }

  Tcl_AppendResult(interp, "    /Function << ", NULL);
  Tcl_AppendResult(interp, "/FunctionType 3\n", NULL);
  Tcl_AppendResult(interp, "      /Domain [0 1] /Bounds [", NULL);
  for (i = 1; i < gradient->num_actual_colors-1; i++) {
    sprintf(path, "%.4g ", gradient->actual_colors[i].position/100.0);
    Tcl_AppendResult(interp, path, NULL);
  }
  Tcl_AppendResult(interp, "] /Encode [", NULL);
  for (i = 0; i < gradient->num_actual_colors-1; i++) {
    Tcl_AppendResult(interp, "0 1 ", NULL);
  }
  Tcl_AppendResult(interp, "]\n      /Functions [\n", NULL);
  for (i = 0, gc1 = gradient->actual_colors; i < gradient->num_actual_colors-1; i++) {
    gc2 = gc1 + 1;
    Tcl_AppendResult(interp, "      << /FunctionType 2 /Domain [0 1] /N 1 ", NULL);
    sprintf(path, "/C0 [%.8g %.8g %.8g] /C1 [%.8g %.8g %.8g] >>\n",
            gc1->rgb->red/65535.0, gc1->rgb->green/65535.0, gc1->rgb->blue/65535.0,
            gc2->rgb->red/65535.0, gc2->rgb->green/65535.0, gc2->rgb->blue/65535.0);
    Tcl_AppendResult(interp, path, NULL);
    gc1 = gc2;
  }
  Tcl_AppendResult(interp, "      ] >>\n", NULL);
  Tcl_AppendResult(interp, "  >> >>\n", NULL);
  Tcl_AppendResult(interp, "matrix makepattern setpattern fill\n", NULL);

  return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * TkImageGetColor --
 *
 *	This procedure converts a pixel value to three floating
 *      point numbers, representing the amount of red, green, and 
 *      blue in that pixel on the screen.  It makes use of colormap
 *      data passed as an argument, and should work for all Visual
 *      types.
 *
 *	This implementation is bogus on Windows because the colormap
 *	data is never filled in.  Instead all postscript generated
 *	data coming through here is expected to be RGB color data.
 *	To handle lower bit-depth images properly, XQueryColors
 *	must be implemented for Windows.
 *
 * Results:
 *	Returns red, green, and blue color values in the range 
 *      0 to 1.  There are no error returns.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */
/*
 * The following definition is used in generating postscript for images
 * and windows.
 */
typedef struct TkColormapData {	/* Hold color information for a window */
    int separated;		/* Whether to use separate color bands */
    int color;			/* Whether window is color or black/white */
    int ncolors;		/* Number of color values stored */
    XColor *colors;		/* Pixel value -> RGB mappings */
    int red_mask, green_mask, blue_mask;	/* Masks and shifts for each */
    int red_shift, green_shift, blue_shift;	/* color band */
} TkColormapData;

#ifdef WIN32
#include <windows.h>

/*
 * We could just define these instead of pulling in windows.h.
 #define GetRValue(rgb)	((BYTE)(rgb))
 #define GetGValue(rgb)	((BYTE)(((WORD)(rgb)) >> 8))
 #define GetBValue(rgb)	((BYTE)((rgb)>>16))
*/
#else
#define GetRValue(rgb)	((rgb & cdata->red_mask) >> cdata->red_shift)
#define GetGValue(rgb)	((rgb & cdata->green_mask) >> cdata->green_shift)
#define GetBValue(rgb)	((rgb & cdata->blue_mask) >> cdata->blue_shift)
#endif

#if defined(WIN32) || defined(MAC_OSX_TK)
static void
TkImageGetColor(cdata, pixel, red, green, blue)
    TkColormapData *cdata;              /* Colormap data */
    unsigned long pixel;                /* Pixel value to look up */
    double *red, *green, *blue;         /* Color data to return */
{
    *red   = (double) GetRValue(pixel) / 255.0;
    *green = (double) GetGValue(pixel) / 255.0;
    *blue  = (double) GetBValue(pixel) / 255.0;
}
#else
static void
TkImageGetColor(cdata, pixel, red, green, blue)
    TkColormapData *cdata;              /* Colormap data */
    unsigned long pixel;                /* Pixel value to look up */
    double *red, *green, *blue;         /* Color data to return */
{
    if (cdata->separated) {
	int r = GetRValue(pixel);
	int g = GetGValue(pixel);
	int b = GetBValue(pixel);
	*red   = cdata->colors[r].red / 65535.0;
	*green = cdata->colors[g].green / 65535.0;
	*blue  = cdata->colors[b].blue / 65535.0;
    } else {
	*red   = cdata->colors[pixel].red / 65535.0;
	*green = cdata->colors[pixel].green / 65535.0;
	*blue  = cdata->colors[pixel].blue / 65535.0;
    }
}
#endif

/*
 *--------------------------------------------------------------
 *
 * ZnPostscriptXImage --
 *
 *	This procedure is called to output the contents of an
 *	XImage in Postscript, using a format appropriate for the 
 *      current color mode (i.e. one bit per pixel in monochrome, 
 *      one byte per pixel in gray, and three bytes per pixel in
 *      color).
 *
 * Results:
 *	Returns a standard Tcl return value.  If an error occurs
 *	then an error message will be left in interp->result.
 *	If no error occurs, then additional Postscript will be
 *	appended to interp->result.
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------
 */
/* TODO beaucoup de code à partager avec photo ci dessous
 * sans compter qu'il faut une autre fonction pour emettre
 * du code pour les tiling patterns.
 * Il faudrait un operateur central qui emette dans une
 * string postscript des bandes d'image afin de respecter
 * la taille max des strings (on peut aussi mettre les
 * bandes dans un tableau au préalable). Cet opérateur
 * gére le niveau de couleur (0, 1, ...) et sait gérer les
 * bits de transparence Postscript 3 en option.
 */
int
ZnPostscriptXImage(Tcl_Interp        *interp,
                   Tk_Window         tkwin,
                   Tk_PostscriptInfo psInfo,
                   XImage            *ximage,
                   int               x,
                   int               y,
                   int               width,
                   int               height)
{
  TkPostscriptInfo *psi = (TkPostscriptInfo *) psInfo;
  char             buffer[256];
  int              xx, yy, band, maxRows;
  double           red, green, blue;
  int              bytesPerLine=0, maxWidth=0;
  int              level = psi->colorLevel;
  Colormap         cmap;
  int              i, ncolors;
  Visual           *visual;
  TkColormapData   cdata;

  if (psi->prepass) {
    return TCL_OK;
  }

  Tcl_AppendResult(interp, "%%%%%% Start of ZnPostscriptXImage\n", NULL);

  cmap = Tk_Colormap(tkwin);
  visual = Tk_Visual(tkwin);

  /*
   * Obtain information about the colormap, ie the mapping between
   * pixel values and RGB values.  The code below should work
   * for all Visual types.
   */
  ncolors = visual->map_entries;
  cdata.colors = (XColor *) ckalloc(sizeof(XColor) * ncolors);
  cdata.ncolors = ncolors;

  if ((visual->class == DirectColor) || (visual->class == TrueColor)) {
    cdata.separated = 1;
    cdata.red_mask = visual->red_mask;
    cdata.green_mask = visual->green_mask;
    cdata.blue_mask = visual->blue_mask;
    cdata.red_shift = 0;
    cdata.green_shift = 0;
    cdata.blue_shift = 0;
    while ((0x0001 & (cdata.red_mask >> cdata.red_shift)) == 0) {
      cdata.red_shift ++;
    }
    while ((0x0001 & (cdata.green_mask >> cdata.green_shift)) == 0) {
      cdata.green_shift ++;
    }
    while ((0x0001 & (cdata.blue_mask >> cdata.blue_shift)) == 0) {
      cdata.blue_shift ++;
    }
    for (i = 0; i < ncolors; i ++) {
      cdata.colors[i].pixel = ((i << cdata.red_shift) & cdata.red_mask) |
        ((i << cdata.green_shift) & cdata.green_mask) |
        ((i << cdata.blue_shift) & cdata.blue_mask);
    }
  }
  else {
    cdata.separated=0;
    for (i = 0; i < ncolors; i ++) {
      cdata.colors[i].pixel = i;
    }
  }
  if ((visual->class == StaticGray) || (visual->class == GrayScale)) {
    cdata.color = 0;
  }
  else {
    cdata.color = 1;
  }

  XQueryColors(Tk_Display(tkwin), cmap, cdata.colors, ncolors);

  /*
   * Figure out which color level to use (possibly lower than the 
   * one specified by the user).  For example, if the user specifies
   * color with monochrome screen, use gray or monochrome mode instead. 
   */

  if (!cdata.color && level == 2) {
    level = 1;
  }
  if (!cdata.color && cdata.ncolors == 2) {
    level = 0;
  }

  /*
   * Check that at least one row of the image can be represented
   * with a string less than 64 KB long (this is a limit in the 
   * Postscript interpreter).
   */
  switch (level) {
    case 0: bytesPerLine = (width + 7) / 8;  maxWidth = 240000;  break;
    case 1: bytesPerLine = width;  maxWidth = 60000;  break;
    case 2: bytesPerLine = 3 * width;  maxWidth = 20000;  break;
  }

  if (bytesPerLine > 60000) {
    Tcl_ResetResult(interp);
    sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide", maxWidth);
    Tcl_AppendResult(interp, buffer, (char *) NULL);
    ckfree((char *) cdata.colors);
    return TCL_ERROR;
  }

  maxRows = 60000 / bytesPerLine;

  for (band = height-1; band >= 0; band -= maxRows) {
    int rows = (band >= maxRows) ? maxRows : band + 1;
    int lineLen = 0;
    switch (level) {
      case 0:
        sprintf(buffer, "%d %d 1 matrix {\n<", width, rows);
        Tcl_AppendResult(interp, buffer, (char *) NULL);
        break;
      case 1:
        sprintf(buffer, "%d %d 8 matrix {\n<", width, rows);
        Tcl_AppendResult(interp, buffer, (char *) NULL);
        break;
      case 2:
        sprintf(buffer, "%d %d 8 matrix {\n<", width, rows);
        Tcl_AppendResult(interp, buffer, (char *) NULL);
        break;
    }
    for (yy = band; yy > band - rows; yy--) {
      switch (level) {
        case 0:
          {
            /*
             * Generate data for image in monochrome mode.
             * No attempt at dithering is made--instead, just
             * set a threshold.
             */
            unsigned char mask=0x80;
            unsigned char data=0x00;
            for (xx = x; xx< x+width; xx++) {
              TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
                              &red, &green, &blue);
              if (0.30 * red + 0.59 * green + 0.11 * blue > 0.5)
                data |= mask;
              mask >>= 1;
              if (mask == 0) {
                sprintf(buffer, "%02X", data);
                Tcl_AppendResult(interp, buffer, (char *) NULL);
                lineLen += 2;
                if (lineLen > 60) {
                  lineLen = 0;
                  Tcl_AppendResult(interp, "\n", (char *) NULL);
                }
                mask=0x80;
                data=0x00;
              }
            }
            if ((width % 8) != 0) {
              sprintf(buffer, "%02X", data);
              Tcl_AppendResult(interp, buffer, (char *) NULL);
              mask=0x80;
              data=0x00;
            }
            break;
          }
        case 1:
          {
            /*
             * Generate data in gray mode--in this case, take a 
             * weighted sum of the red, green, and blue values.
             */
            for (xx = x; xx < x+width; xx ++) {
              TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
                              &red, &green, &blue);
              sprintf(buffer, "%02X", (int) floor(0.5 + 255.0 *
                                                  (0.30 * red + 0.59 * green + 0.11 * blue)));
              Tcl_AppendResult(interp, buffer, (char *) NULL);
              lineLen += 2;
              if (lineLen > 60) {
                lineLen = 0;
                Tcl_AppendResult(interp, "\n", (char *) NULL);
              }
            }
            break;
          }
        case 2:
          {
            /*
             * Finally, color mode.  Here, just output the red, green,
             * and blue values directly.
             */
            for (xx = x; xx < x+width; xx++) {
              TkImageGetColor(&cdata, XGetPixel(ximage, xx, yy),
                              &red, &green, &blue);
              sprintf(buffer, "%02X%02X%02X",
                      (int) floor(0.5 + 255.0 * red),
                      (int) floor(0.5 + 255.0 * green),
                      (int) floor(0.5 + 255.0 * blue));
              Tcl_AppendResult(interp, buffer, (char *) NULL);
              lineLen += 6;
              if (lineLen > 60) {
                lineLen = 0;
                Tcl_AppendResult(interp, "\n", (char *) NULL);
              }
            }
            break;
          }
      }
    }
    switch (level) {
      case 0: sprintf(buffer, ">\n} image\n"); break;
      case 1: sprintf(buffer, ">\n} image\n"); break;
      case 2: sprintf(buffer, ">\n} false 3 colorimage\n"); break;
    }
    Tcl_AppendResult(interp, buffer, (char *) NULL);
    sprintf(buffer, "0 %d translate\n", rows);
    Tcl_AppendResult(interp, buffer, (char *) NULL);
  }
  ckfree((char *) cdata.colors);

  Tcl_AppendResult(interp, "%%%%%% End of ZnPostscriptXImage\n", NULL);

  return TCL_OK;
}

/*
 *--------------------------------------------------------------
 *
 * ZnPostscriptPhoto --
 *
 *  This procedure is called to output the contents of a
 *  photo image in Postscript, using a format appropriate for
 *  the requested postscript color mode (i.e. one byte per pixel
 *  in gray, and three bytes per pixel in color).
 *
 * Results:
 *  Returns a standard Tcl return value.  If an error occurs
 *  then an error message will be left in interp->result.
 *  If no error occurs, then additional Postscript will be
 *  appended to the interpreter's result.
 *
 * Side effects:
 *  None.
 *
 *--------------------------------------------------------------
 */
int
ZnPostscriptPhoto(Tcl_Interp         *interp,
                  Tk_PhotoImageBlock *blockPtr,
                  Tk_PostscriptInfo  ps_info,
                  int                width,
                  int                height)
{
  TkPostscriptInfo *psi = (TkPostscriptInfo *) ps_info;
  static int       codeIncluded = 0;
  unsigned char    *pixelPtr;
  char             buffer[256], cspace[40], decode[40];
  int              bpc;
  int              xx, yy, lineLen;
  float            red, green, blue;
  int              alpha;
  int              bytesPerLine=0, maxWidth=0;
  unsigned char    opaque = 255;
  unsigned char    *alphaPtr;
  int              alphaOffset, alphaPitch, alphaIncr;

  if (psi->prepass) {
    codeIncluded = 0;
    return TCL_OK;
  }

  /*
   * Define the "TkPhoto" function, which is a modified version
   * of the original "transparentimage" function posted
   * by ian@five-d.com (Ian Kemmish) to comp.lang.postscript.
   * For a monochrome colorLevel this is a slightly different
   * version that uses the imagemask command instead of image.
   */
  if( !codeIncluded && (psi->colorLevel != 0) ) {
    /*
     * Color and gray-scale code.
     */
    codeIncluded = !0;
    Tcl_AppendResult(interp,
                     "/TkPhoto { \n",
                     "  gsave \n",
                     "  32 dict begin \n",
                     "  /tinteger exch def \n",
                     "  /transparent 1 string def \n",
                     "  transparent 0 tinteger put \n",
                     "  /olddict exch def \n",
                     "  olddict /DataSource get dup type /filetype ne { \n",
                     "    olddict /DataSource 3 -1 roll \n",
                     "    0 () /SubFileDecode filter put \n",
                     "  } { \n",
                     "    pop \n",
                     "  } ifelse \n",
                     "  /newdict olddict maxlength dict def \n",
                     "  olddict newdict copy pop \n",
                     "  /w newdict /Width get def \n",
                     "  /crpp newdict /Decode get length 2 idiv def \n",
                     "  /str w string def \n",
                     "  /pix w crpp mul string def \n",
                     "  /substrlen 2 w log 2 log div floor exp cvi def \n",
                     "  /substrs [ \n",
                     "  { \n",
                     "     substrlen string \n",
                     "     0 1 substrlen 1 sub { \n",
                     "       1 index exch tinteger put \n",
                     "     } for \n",
                     "     /substrlen substrlen 2 idiv def \n",
                     "     substrlen 0 eq {exit} if \n",
                     "  } loop \n",
                     "  ] def \n",
                     "  /h newdict /Height get def \n",
                     "  1 w div 1 h div matrix scale \n",
                     "  olddict /ImageMatrix get exch matrix concatmatrix \n",
                     "  matrix invertmatrix concat \n",
                     "  newdict /Height 1 put \n",
                     "  newdict /DataSource pix put \n",
                     "  /mat [w 0 0 h 0 0] def \n",
                     "  newdict /ImageMatrix mat put \n",
                     "  0 1 h 1 sub { \n",
                     "    mat 5 3 -1 roll neg put \n",
                     "    olddict /DataSource get str readstring pop pop \n",
                     "    /tail str def \n",
                     "    /x 0 def \n",
                     "    olddict /DataSource get pix readstring pop pop \n",
                     "    { \n",
                     "      tail transparent search dup /done exch not def \n",
                     "      {exch pop exch pop} if \n",
                     "      /w1 exch length def \n",
                     "      w1 0 ne { \n",
                     "        newdict /DataSource ",
                     " pix x crpp mul w1 crpp mul getinterval put \n",
                     "        newdict /Width w1 put \n",
                     "        mat 4 x neg put \n",
                     "        /x x w1 add def \n",
                     "        newdict image \n",
                     "        /tail tail w1 tail length w1 sub getinterval def \n",
                     "      } if \n",
                     "      done {exit} if \n",
                     "      tail substrs { \n",
                     "        anchorsearch {pop} if \n",
                     "      } forall \n",
                     "      /tail exch def \n",
                     "      tail length 0 eq {exit} if \n",
                     "      /x w tail length sub def \n",
                     "    } loop \n",
                     "  } for \n",
                     "  end \n",
                     "  grestore \n",
                     "} bind def \n\n\n", (char *) NULL);
  }
  else if (!codeIncluded && (psi->colorLevel == 0)) {
    /*
     * Monochrome-only code
     */
    codeIncluded = !0;
    Tcl_AppendResult(interp,
                     "/TkPhoto { \n",
                     "  gsave \n",
                     "  32 dict begin \n",
                     "  /dummyInteger exch def \n",
                     "  /olddict exch def \n",
                     "  olddict /DataSource get dup type /filetype ne { \n",
                     "    olddict /DataSource 3 -1 roll \n",
                     "    0 () /SubFileDecode filter put \n",
                     "  } { \n",
                     "    pop \n",
                     "  } ifelse \n",
                     "  /newdict olddict maxlength dict def \n",
                     "  olddict newdict copy pop \n",
                     "  /w newdict /Width get def \n",
                     "  /pix w 7 add 8 idiv string def \n",
                     "  /h newdict /Height get def \n",
                     "  1 w div 1 h div matrix scale \n",
                     "  olddict /ImageMatrix get exch matrix concatmatrix \n",
                     "  matrix invertmatrix concat \n",
                     "  newdict /Height 1 put \n",
                     "  newdict /DataSource pix put \n",
                     "  /mat [w 0 0 h 0 0] def \n",
                     "  newdict /ImageMatrix mat put \n",
                     "  0 1 h 1 sub { \n",
                     "    mat 5 3 -1 roll neg put \n",
                     "    0.000 0.000 0.000 setrgbcolor \n",
                     "    olddict /DataSource get pix readstring pop pop \n",
                     "    newdict /DataSource pix put \n",
                     "    newdict imagemask \n",
                     "    1.000 1.000 1.000 setrgbcolor \n",
                     "    olddict /DataSource get pix readstring pop pop \n",
                     "    newdict /DataSource pix put \n",
                     "    newdict imagemask \n",
                     "  } for \n",
                     "  end \n",
                     "  grestore \n",
                     "} bind def \n\n\n", (char *) NULL);
  }

  /*
   * Check that at least one row of the image can be represented
   * with a string less than 64 KB long (this is a limit in the
   * Postscript interpreter).
   */
  switch (psi->colorLevel)
  {
    case 0: bytesPerLine = (width + 7) / 8;  maxWidth = 240000;  break;
    case 1: bytesPerLine = width;  maxWidth = 60000;  break;
    case 2: bytesPerLine = 3 * width;  maxWidth = 20000;  break;
  }
  if (bytesPerLine > 60000) {
    Tcl_ResetResult(interp);
    sprintf(buffer, "Can't generate Postscript for images more than %d pixels wide",
            maxWidth);
    Tcl_AppendResult(interp, buffer, (char *) NULL);
    return TCL_ERROR;
  }

  /*
   * Set up the postscript code except for the image-data stream.
   */
  switch (psi->colorLevel) {
    case 0: 
      strcpy( cspace, "/DeviceGray");
      strcpy( decode, "[1 0]");
      bpc = 1;
      break;
    case 1: 
      strcpy( cspace, "/DeviceGray");
      strcpy( decode, "[0 1]");
      bpc = 8;
      break;
    default:
      strcpy( cspace, "/DeviceRGB");
      strcpy( decode, "[0 1 0 1 0 1]");
      bpc = 8;
      break;
  }

  Tcl_AppendResult(interp, cspace, " setcolorspace\n\n", (char *) NULL);
  sprintf(buffer, "  /Width %d\n  /Height %d\n  /BitsPerComponent %d\n",
          width, height, bpc);
  Tcl_AppendResult(interp,
                   "<<\n  /ImageType 1\n", buffer,
                   "  /DataSource currentfile /ASCIIHexDecode filter\n", (char *) NULL);
  sprintf(buffer, "  /ImageMatrix [1 0 0 -1 0 %d]\n", height);
  Tcl_AppendResult(interp, buffer, "  /Decode ", decode, "\n>>\n1 TkPhoto\n", (char *) NULL);

  /*
   * Check the PhotoImageBlock information.
   * We assume that:
   *     if pixelSize is 1,2 or 4, the image is R,G,B,A;
   *     if pixelSize is 3, the image is R,G,B and offset[3] is bogus.
   */
  if (blockPtr->pixelSize == 3) {
    /*
     * No alpha information: the whole image is opaque.
     */
    alphaPtr = &opaque;
    alphaPitch = alphaIncr = alphaOffset = 0;
  }
  else {
    /*
     * Set up alpha handling.
     */
    alphaPtr = blockPtr->pixelPtr;
    alphaPitch = blockPtr->pitch;
    alphaIncr = blockPtr->pixelSize;
    alphaOffset = blockPtr->offset[3];
  }

  for (yy = 0, lineLen=0; yy < height; yy++) {
    switch (psi->colorLevel) {
      case 0:
        {
          /*
           * Generate data for image in monochrome mode.
           * No attempt at dithering is made--instead, just
           * set a threshold.
           * To handle transparencies we need to output two lines:
           * one for the black pixels, one for the white ones.
           */
          unsigned char mask=0x80;
          unsigned char data=0x00;
          for (xx = 0; xx< width; xx ++) {
            pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);

            red = pixelPtr[blockPtr->offset[0]];
            green = pixelPtr[blockPtr->offset[1]];
            blue = pixelPtr[blockPtr->offset[2]];

            alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);

            /*
             * If pixel is less than threshold, then it is black.
             */
            if ((alpha != 0) && (0.3086 * red + 0.6094 * green + 0.082 * blue < 128)) {
              data |= mask;
            }
            mask >>= 1;
            if (mask == 0) {
              sprintf(buffer, "%02X", data);
              Tcl_AppendResult(interp, buffer, (char *) NULL);
              lineLen += 2;
              if (lineLen >= 60) {
                lineLen = 0;
                Tcl_AppendResult(interp, "\n", (char *) NULL);
              }
              mask=0x80;
              data=0x00;
            }
          }
          if ((width % 8) != 0) {
            sprintf(buffer, "%02X", data);
            Tcl_AppendResult(interp, buffer, (char *) NULL);
            mask=0x80;
            data=0x00;
          }

          mask=0x80;
          data=0x00;
          for (xx = 0; xx< width; xx ++) {
            pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);

            red = pixelPtr[blockPtr->offset[0]];
            green = pixelPtr[blockPtr->offset[1]];
            blue = pixelPtr[blockPtr->offset[2]];

            alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);

            /*
             * If pixel is greater than threshold, then it is white.
             */
            if ((alpha != 0) && (0.3086 * red + 0.6094 * green + 0.082 * blue >= 128)) {
              data |= mask;
            }
            mask >>= 1;
            if (mask == 0) {
              sprintf(buffer, "%02X", data);
              Tcl_AppendResult(interp, buffer, (char *) NULL);
              lineLen += 2;
              if (lineLen >= 60) {
                lineLen = 0;
                Tcl_AppendResult(interp, "\n", (char *) NULL);
              }
              mask=0x80;
              data=0x00;
            }
          }
          if ((width % 8) != 0) {
            sprintf(buffer, "%02X", data);
            Tcl_AppendResult(interp, buffer, (char *) NULL);
            mask=0x80;
            data=0x00;
          }
          break;
        }
      case 1:
        {
          /*
           * Generate transparency data.
           * We must prevent a transparent value of 0
           * because of a bug in some HP printers.
           */
          for (xx = 0; xx < width; xx ++) {
            alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
            sprintf(buffer, "%02X", alpha | 0x01);
            Tcl_AppendResult(interp, buffer, (char *) NULL);
            lineLen += 2;
            if (lineLen >= 60) {
              lineLen = 0;
              Tcl_AppendResult(interp, "\n", (char *) NULL);
            }
          }

          /*
           * Generate data in gray mode--in this case, take a 
           * weighted sum of the red, green, and blue values.
           */
          for (xx = 0; xx < width; xx ++) {
            pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);

            red = pixelPtr[blockPtr->offset[0]];
            green = pixelPtr[blockPtr->offset[1]];
            blue = pixelPtr[blockPtr->offset[2]];

            sprintf(buffer, "%02X",
                    (int) floor(0.5 + ( 0.3086 * red + 0.6094 * green + 0.0820 * blue)));
            Tcl_AppendResult(interp, buffer, (char *) NULL);
            lineLen += 2;
            if (lineLen >= 60) {
              lineLen = 0;
              Tcl_AppendResult(interp, "\n", (char *) NULL);
            }
          }
          break;
        }
      default:
        {
          /*
           * Generate transparency data.
           * We must prevent a transparent value of 0
           * because of a bug in some HP printers.
           */
          for (xx = 0; xx < width; xx ++) {
            alpha = *(alphaPtr + (yy * alphaPitch) + (xx * alphaIncr) + alphaOffset);
            sprintf(buffer, "%02X", alpha | 0x01);
            Tcl_AppendResult(interp, buffer, (char *) NULL);
            lineLen += 2;
            if (lineLen >= 60) {
              lineLen = 0;
              Tcl_AppendResult(interp, "\n", (char *) NULL);
            }
          }

          /*
           * Finally, color mode.  Here, just output the red, green,
           * and blue values directly.
           */
          for (xx = 0; xx < width; xx ++) {
            pixelPtr = blockPtr->pixelPtr + (yy * blockPtr->pitch) + (xx *blockPtr->pixelSize);

            sprintf(buffer, "%02X%02X%02X", pixelPtr[blockPtr->offset[0]],
                    pixelPtr[blockPtr->offset[1]], pixelPtr[blockPtr->offset[2]]);
            Tcl_AppendResult(interp, buffer, (char *) NULL);
            lineLen += 6;
            if (lineLen >= 60) {
              lineLen = 0;
              Tcl_AppendResult(interp, "\n", (char *) NULL);
            }
          }
          break;
        }
    }
  }

  Tcl_AppendResult(interp, ">\n", (char *) NULL);
  return TCL_OK;
}

int
ZnPostscriptImage(Tcl_Interp        *interp,
                  Tk_Window         tkwin,
                  Tk_PostscriptInfo ps_info,
                  ZnImage           image,
                  int               x,
                  int               y,
                  int               w,
                  int               h)
{
  int              result;
  XImage           *ximage = NULL;
  Tk_PhotoHandle   tkphoto;
  
  if (((TkPostscriptInfo *) ps_info)->prepass) {
    return TCL_OK;
  }

  tkphoto = ZnImageTkPhoto(image);
  if (tkphoto != NULL) {
    Tk_PhotoImageBlock block;

    Tk_PhotoGetImage(tkphoto, &block);
    block.pixelPtr += y * block.pitch + x * block.pixelSize;

    return ZnPostscriptPhoto(interp, &block, ps_info, w, h);
  }
  else {
    Pixmap    pix = ZnImagePixmap(image, tkwin);
    XGCValues values;
    GC        gc;

    if (pix == None) {
      /*
       * Pixmap not cached (probably working under GL).
       * Create a temporary pixmap.
       */
      pix = Tk_GetPixmap(Tk_Display(tkwin), Tk_WindowId(tkwin), w, h, Tk_Depth(tkwin));
      values.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
      gc = Tk_GetGC(tkwin, GCForeground, &values);
      if (gc != None) {
        XFillRectangle(Tk_Display(tkwin), pix, gc, 0, 0, (unsigned int) w, (unsigned int) h);
        Tk_FreeGC(Tk_Display(tkwin), gc);
      }
      Tk_RedrawImage(image, x, y, w, h, pix, 0, 0);
      Tk_FreePixmap(Tk_Display(tkwin), pix);
    }
    else {
      ximage = XGetImage(Tk_Display(tkwin), pix, 0, 0,
                         (unsigned int) w, (unsigned int) h, AllPlanes, ZPixmap);
    }
    if (ximage == NULL) {
      /* The XGetImage() function is apparently not
       * implemented on this system. Just ignore it.
       */
      return TCL_OK;
    }
    result = ZnPostscriptXImage(interp, tkwin, ps_info, ximage, x, y, w, h);
    XDestroyImage(ximage);
  }

  return result;
}

void
EmitPhotoImageData()
{
}


/*
 * TODO gradients, tuiles, reliefs, flêches, clipping.
 * TODO la fonction DrawText est buggée dans un environnement rotation
 *      l'erreur passe par un max autour de modulo 45°
 * TODO Bugs de placement sur le texte et les bordures des fields
 * TODO Problème : Si on utilise les transformations PostScript on
 *      génère un code plus concis et le rendu est potentiellement
 *      plus beau (on utilise les arcs et les beziers natifs) et on
 *      peut générer des dégradés identiques à ceux de zinc mais le
 *      tuilage/stencil, les flêches, l'épaisseur des lignes suivent
 *      la transformation.
 * TODO Le code gérant les images ne sait pas traiter le canal alpha.
 * TODO Inclure ici le code de gestion des stipples.
 * TODO Pour images et stipples le code doit prendre en compte le contexte
 *      X et/ou OpenGL.
 */ 

Added jni/tkzinc/generic/PostScript.h.



















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*
 * PostScript.h -- Header to access PostScript driver.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Wed Jan  4 11:30:00 1995
 *
 * $Id$
 */

/*
 *  Copyright (c) 1995 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _PostScript_h
#define _PostScript_h


#include "List.h"
#include "Types.h"
#include "Geo.h"
#include "Color.h"
#include "Image.h"

#include <stdio.h>
#include <X11/Xlib.h>


struct _ZnWInfo;
struct _ZnItemStruct;


int ZnPostScriptCmd(struct _ZnWInfo *wi, int argc, Tcl_Obj *CONST *args);
void ZnFlushPsChan(Tcl_Interp *interp, Tk_PostscriptInfo ps_info);
int ZnPostscriptOutline(Tcl_Interp *interp, Tk_PostscriptInfo ps_info,
                        Tk_Window tkwin, ZnDim line_width, ZnLineStyle line_style,
                        ZnGradient *line_color, ZnImage line_pattern);
int ZnPostscriptBitmap(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
                       ZnImage bitmap, ZnReal x, ZnReal y, int width, int height);
void ZnPostscriptString(Tcl_Interp *interp, char *str, int num_bytes);
void ZnPostscriptTrace(struct _ZnItemStruct *item, ZnBool enter);
int ZnPostscriptGradient(Tcl_Interp *interp, Tk_PostscriptInfo ps_info,
                         ZnGradient *gradient, ZnPoint *quad, ZnPoly *poly);
int ZnPostscriptXImage(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo psInfo,
                       XImage *ximage, int x, int y, int width, int height);
int ZnPostscriptStipple(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
                        ZnImage bitmap);
int ZnPostscriptTile(Tcl_Interp *interp, Tk_Window win, Tk_PostscriptInfo ps_info,
                     ZnImage image);
int ZnPostscriptImage(Tcl_Interp *interp, Tk_Window tkwin, Tk_PostscriptInfo ps_info,
                      ZnImage image, int x, int y, int width, int height);

#endif	/* _PostScript_h */

Added jni/tkzinc/generic/Rectangle.c.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
/*
 * Rectangle.c -- Implementation of rectangle item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Fri Dec  2 14:47:42 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1994 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Item.h"
#include "Geo.h"
#include "Draw.h"
#include "Types.h"
#include "Image.h"
#include "Color.h"
#include "WidgetInfo.h"
#include "tkZinc.h"


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";

/*
 * Bit offset of flags.
 */
#define FILLED_BIT      1       /* If the rectangle is filled with color/pattern */
#define ALIGNED_BIT     2


/*
 **********************************************************************************
 *
 * Specific Rectangle item record
 *
 **********************************************************************************
 */

typedef struct _RectangleItemStruct {
  ZnItemStruct  header;

  /* Public data */
  ZnPoint       coords[2];
  unsigned short flags;
  ZnReliefStyle relief;
  ZnLineStyle   line_style;
  ZnDim         line_width;
  ZnGradient    *line_color;
  ZnImage       line_pattern;
  ZnGradient    *fill_color;
  ZnImage       tile;
  
  /* Private data */
  ZnPoint       dev[4];
  ZnGradient    *gradient;
  ZnPoint       *grad_geo;
} RectangleItemStruct, *RectangleItem;


static ZnAttrConfig     rect_attrs[] = {
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(RectangleItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(RectangleItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(RectangleItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(RectangleItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-fillcolor", NULL,
    Tk_Offset(RectangleItemStruct, fill_color), 0,
    ZN_COORDS_FLAG|ZN_BORDER_FLAG, False },
  { ZN_CONFIG_BOOL, "-filled", NULL,
    Tk_Offset(RectangleItemStruct, flags), FILLED_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
    Tk_Offset(RectangleItemStruct, tile), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
    Tk_Offset(RectangleItemStruct, line_color), 0,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BITMAP, "-linepattern", NULL,
    Tk_Offset(RectangleItemStruct, line_pattern), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
    Tk_Offset(RectangleItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-linewidth", NULL,
    Tk_Offset(RectangleItemStruct, line_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(RectangleItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_RELIEF, "-relief", NULL, Tk_Offset(RectangleItemStruct, relief), 0,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(RectangleItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(RectangleItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_IMAGE, "-tile", NULL,
    Tk_Offset(RectangleItemStruct, tile), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(RectangleItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};



/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  ZnWInfo       *wi = item->wi;
  RectangleItem rect = (RectangleItem) item;
  unsigned int  num_points;
  ZnPoint       *points;

  rect->gradient = NULL;
  rect->grad_geo = NULL;

  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 1;
  
  if (*argc < 1) {
    Tcl_AppendResult(wi->interp, " rectangle coords expected", NULL);
    return TCL_ERROR;
  }
  if (ZnParseCoordList(wi, (*args)[0], &points,
                       NULL, &num_points, NULL) == TCL_ERROR) {
    return TCL_ERROR;
  }
  if (num_points != 2) {
    Tcl_AppendResult(wi->interp, " malformed rectangle coords", NULL);
    return TCL_ERROR;
  };
  rect->coords[0] = points[0];
  rect->coords[1] = points[1];
  (*args)++;
  (*argc)--;
  
  CLEAR(rect->flags, FILLED_BIT);
  rect->relief = ZN_RELIEF_FLAT;
  rect->line_style = ZN_LINE_SIMPLE;
  rect->line_width = 1;
  rect->line_pattern = ZnUnspecifiedImage;
  rect->tile = ZnUnspecifiedImage;
  rect->line_color = ZnGetGradientByValue(wi->fore_color);
  rect->fill_color = ZnGetGradientByValue(wi->fore_color);
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  RectangleItem rect = (RectangleItem) item;

  if (rect->gradient) {
    rect->gradient = ZnGetGradientByValue(rect->gradient);
  }
  if (rect->tile != ZnUnspecifiedImage) {
    rect->tile = ZnGetImageByValue(rect->tile, ZnUpdateItemImage, item);
  }
  if (rect->line_pattern != ZnUnspecifiedImage) {
    rect->line_pattern = ZnGetImageByValue(rect->line_pattern, NULL, NULL);
  }
  rect->line_color = ZnGetGradientByValue(rect->line_color);
  rect->fill_color = ZnGetGradientByValue(rect->fill_color);
  rect->grad_geo = NULL;
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  RectangleItem rect = (RectangleItem) item;

  if (rect->tile != ZnUnspecifiedImage) {
    ZnFreeImage(rect->tile, ZnUpdateItemImage, item);
    rect->tile = ZnUnspecifiedImage;
  }
  if (rect->gradient) {
    ZnFreeGradient(rect->gradient);
  }
  if (rect->line_pattern != ZnUnspecifiedImage) {
    ZnFreeImage(rect->line_pattern, NULL, NULL);
    rect->line_pattern = ZnUnspecifiedImage;
  }
  if (rect->grad_geo) {
    ZnFree(rect->grad_geo);
  }
  ZnFreeGradient(rect->fill_color);
  ZnFreeGradient(rect->line_color);
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  ZnWInfo       *wi = item->wi;
  RectangleItem rect = (RectangleItem) item;
  int           status = TCL_OK;
  XColor        *color;
  unsigned short alpha;
  
  status = ZnConfigureAttributes(wi, item, item, rect_attrs, argc, argv, flags);
  
  if (rect->gradient &&
      (ISSET(*flags, ZN_BORDER_FLAG) || (rect->relief == ZN_RELIEF_FLAT))) {
    ZnFreeGradient(rect->gradient);
    rect->gradient = NULL;
  }
  if ((rect->relief != ZN_RELIEF_FLAT) && !rect->gradient) {
    color = ZnGetGradientColor(rect->line_color, 51.0, &alpha);
    rect->gradient = ZnGetReliefGradient(wi->interp, wi->win,
                                         Tk_NameOfColor(color), alpha);
    if (rect->gradient == NULL) {
      status = TCL_ERROR;
    }
  }

  return status;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, rect_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  RectangleItem rect = (RectangleItem) item;
  ZnPoint       p[4];
  int           i;
  ZnBool        aligned;
  ZnDim         delta, lw2;
  
  ZnResetBBox(&item->item_bounding_box);
  if (!rect->line_width && ISCLEAR(rect->flags, FILLED_BIT)) {
    return;
  }

  p[0] = rect->coords[0];
  p[2] = rect->coords[1];
  p[1].x = p[2].x;
  p[1].y = p[0].y;
  p[3].x = p[0].x;
  p[3].y = p[2].y;
  ZnTransformPoints(wi->current_transfo, p, rect->dev, 4);
  for (i = 0; i < 4; i++) {
    rect->dev[i].x = ZnNearestInt(rect->dev[i].x);
    rect->dev[i].y = ZnNearestInt(rect->dev[i].y);
  }

  /*
   * Add all points to the bounding box. Then expand by the line
   * width to account for mitered corners. This is an overestimate.
   */
  ZnAddPointsToBBox(&item->item_bounding_box, rect->dev, 4);
  if (rect->line_width > 0) {
    lw2 = rect->line_width/2.0;
    item->item_bounding_box.orig.x -= lw2;
    item->item_bounding_box.orig.y -= lw2;
    item->item_bounding_box.corner.x += lw2;
    item->item_bounding_box.corner.y += lw2;
  }
  item->item_bounding_box.orig.x -= 0.5;
  item->item_bounding_box.orig.y -= 0.5;
  item->item_bounding_box.corner.x += 0.5;
  item->item_bounding_box.corner.y += 0.5;
  
  delta = rect->dev[0].y - rect->dev[1].y;
  delta = ABS(delta);
  aligned = delta < X_PRECISION_LIMIT;
  delta = rect->dev[0].x - rect->dev[3].x;
  delta = ABS(delta);
  aligned &= delta < X_PRECISION_LIMIT;
  ASSIGN(rect->flags, ALIGNED_BIT, aligned);
  
#ifdef GL
  /*
   * Compute the gradient geometry
   */
  if (!ZnGradientFlat(rect->fill_color)) {
    ZnPoly      shape;
    
    if (rect->fill_color->type == ZN_AXIAL_GRADIENT) {
      int       angle = rect->fill_color->angle;
      
      if ((angle != 0) && (angle != 90) && (angle != 180) && (angle != 270)) {
        if (!rect->grad_geo) {
          rect->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
        }
        ZnPolyContour1(&shape, p, 4, False);
        ZnComputeGradient(rect->fill_color, wi, &shape, rect->grad_geo);
      }
      else {
        goto free_ggeo;
      }
    }
    else {
      if (!rect->grad_geo) {
        rect->grad_geo = ZnMalloc(6*sizeof(ZnPoint));
      }
      if (rect->fill_color->type == ZN_PATH_GRADIENT) {
        ZnPolyContour1(&shape, rect->coords, 2, False);
      }
      else {
        ZnPolyContour1(&shape, p, 4, False);
      }
      ZnComputeGradient(rect->fill_color, wi, &shape, rect->grad_geo);
    }
  }
  else {
  free_ggeo:
    if (rect->grad_geo) {
      ZnFree(rect->grad_geo);
      rect->grad_geo = NULL;
    }
  }
#endif
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  RectangleItem rect = (RectangleItem) item;
  int           result, result2;
  ZnBBox        *area = ta->area;

  result = -1;

  if (ISSET(rect->flags, FILLED_BIT)) {
    result = ZnPolygonInBBox(rect->dev, 4, area, NULL);
    if (result == 0) {
      return 0;
    }
  }
  if (rect->line_width > 0) {
    int         i;
    ZnPoint     pts[5];

    for (i = 0; i < 4; i++) {
      pts[i] = rect->dev[i];
    }
    pts[4] = pts[0];
    result2 = ZnPolylineInBBox(pts, 5, rect->line_width,
                               CapProjecting, JoinMiter, area);
    if (ISCLEAR(rect->flags, FILLED_BIT)) {
      if (result2 == 0) {
        return 0;
      }
      result = result2;
    }
    else if (result2 != result) {
      return 0;
    }
  }

  return result;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi  = item->wi;
  RectangleItem rect = (RectangleItem) item;
  XGCValues     values;
  unsigned int  i, gc_mask;
  XRectangle    r;
  XPoint        xp[5];
  
  if (ISSET(rect->flags, ALIGNED_BIT)) {
    if (rect->dev[0].x < rect->dev[2].x) {
      r.x = (int) rect->dev[0].x;
      r.width = ((int) rect->dev[2].x) - r.x;
    }
    else {
      r.x = (int) rect->dev[2].x;
      r.width = ((int) rect->dev[0].x) - r.x;
    }
    if (rect->dev[0].y < rect->dev[2].y) {
      r.y = (int) rect->dev[0].y;
      r.height = ((int) rect->dev[2].y) - r.y;
    }
    else {
      r.y = (int) rect->dev[2].y;
      r.height = ((int) rect->dev[0].y) - r.y;
    }
  }
  else {
    for (i = 0; i < 4; i++) {
      xp[i].x = (int) rect->dev[i].x;
      xp[i].y = (int) rect->dev[i].y;
    }
    xp[i] = xp[0];
  }
  
  /*
   * Fill if requested.
   */
  if (ISSET(rect->flags, FILLED_BIT)) {
    values.foreground = ZnGetGradientPixel(rect->fill_color, 0.0);
    if (rect->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(rect->tile)) { /* Fill tiled */
        values.fill_style = FillTiled;
        values.tile = ZnImagePixmap(rect->tile, wi->win);
        if (ISSET(rect->flags, ALIGNED_BIT)) {
          values.ts_x_origin = (int) r.x;
          values.ts_y_origin = (int) r.y;
        }
        else {
          values.ts_x_origin = (int) item->item_bounding_box.orig.x;
          values.ts_y_origin = (int) item->item_bounding_box.orig.y;
        }
        XChangeGC(wi->dpy, wi->gc,
                  GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCTile, &values);
      }
      else {
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(rect->tile, wi->win);
        if (ISSET(rect->flags, ALIGNED_BIT)) {
          values.ts_x_origin = (int) r.x;
          values.ts_y_origin = (int) r.y;
        }
        else {
          values.ts_x_origin = (int) item->item_bounding_box.orig.x;
          values.ts_y_origin = (int) item->item_bounding_box.orig.y;
        }
        XChangeGC(wi->dpy, wi->gc,
                  GCTileStipXOrigin|GCTileStipYOrigin|GCFillStyle|GCStipple|GCForeground,
                  &values);
      }
    }
    else { /* Fill solid */
      values.fill_style = FillSolid;
      XChangeGC(wi->dpy, wi->gc, GCForeground | GCFillStyle, &values);
    }
    if (ISSET(rect->flags, ALIGNED_BIT)) {
      XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
                     r.width, r.height);
    }
    else {
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
    }
  }

  /* Draw the outline */
  if (rect->line_width) {
    if (rect->relief != ZN_RELIEF_FLAT) {
      if (ISSET(rect->flags, ALIGNED_BIT)) {
        ZnDrawRectangleRelief(wi, rect->relief, rect->gradient,
                              &r, rect->line_width);
      }
      else {
        ZnPoint p[5];
        for (i = 0; i < 4; i++) {
          p[4-i].x = rect->dev[i].x;
          p[4-i].y = rect->dev[i].y;
        }
        p[0] = p[4];
        ZnDrawPolygonRelief(wi, rect->relief, rect->gradient,
                            p, 5, rect->line_width);
      }
    }
    else {
      ZnSetLineStyle(wi, rect->line_style);
      gc_mask = GCFillStyle|GCLineWidth|GCForeground|GCJoinStyle;
      values.foreground = ZnGetGradientPixel(rect->line_color, 0.0);
      values.line_width = (int) rect->line_width;
      values.join_style = JoinMiter;
      if (ISCLEAR(rect->flags, ALIGNED_BIT)) {
        gc_mask |= GCCapStyle;
        values.cap_style = CapProjecting;
      }
      if (rect->line_pattern == ZnUnspecifiedImage) {
        values.fill_style = FillSolid;
        XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
      }
      else {
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(rect->line_pattern, wi->win);
        gc_mask |= GCStipple;
        XChangeGC(wi->dpy, wi->gc, gc_mask, &values);
      }
      if (ISSET(rect->flags, ALIGNED_BIT)) {
        XDrawRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y,
                       r.width, r.height);
      }
      else {
        XDrawLines(wi->dpy, wi->draw_buffer, wi->gc, xp, 5, CoordModeOrigin);
      }
    }
  }
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
RectRenderCB(void *closure)
{
  RectangleItem rect = (RectangleItem) closure;

  glBegin(GL_TRIANGLE_STRIP);
  glVertex2d(rect->dev[0].x, rect->dev[0].y);
  glVertex2d(rect->dev[3].x, rect->dev[3].y);
  glVertex2d(rect->dev[1].x, rect->dev[1].y);
  glVertex2d(rect->dev[2].x, rect->dev[2].y);
  glEnd();
}
#endif

#ifdef GL
static void
Render(ZnItem   item)
{
  ZnWInfo       *wi  = item->wi;
  RectangleItem rect = (RectangleItem) item;
  int           i;

#ifdef GL_LIST
  if (!item->gl_list) {
    item->gl_list = glGenLists(1);
    glNewList(item->gl_list, GL_COMPILE);
#endif
    if (ISSET(rect->flags, FILLED_BIT)) {
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      
      if (!ZnGradientFlat(rect->fill_color)) {
        ZnBool  fast = (rect->fill_color->type == ZN_AXIAL_GRADIENT) && !rect->grad_geo;
        ZnPoly  poly;
        
        ZnPolyContour1(&poly, rect->dev, 4, False);
        ZnRenderGradient(wi, rect->fill_color,
                         fast ? NULL: RectRenderCB, rect,
                         fast ? rect->dev : rect->grad_geo, &poly);
      }
      else if (rect->tile != ZnUnspecifiedImage) { /* Fill tiled/patterned */
        if (ISSET(rect->flags, ALIGNED_BIT)) {
          ZnBBox bbox;

          bbox.orig = rect->dev[0];
          bbox.corner = rect->dev[2];
          ZnRenderTile(wi, rect->tile, rect->fill_color, NULL, NULL, (ZnPoint *) &bbox);
        }
        else {
          ZnRenderTile(wi, rect->tile, rect->fill_color, RectRenderCB,
                       rect, (ZnPoint *) &item->item_bounding_box);
        }
      }
      else {
        unsigned short alpha;
        XColor *color = ZnGetGradientColor(rect->fill_color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
        RectRenderCB(rect);
      }
    }
    
    if (rect->line_width) {
      ZnPoint p[5];
      for (i = 0; i < 4; i++) {
        p[4-i].x = rect->dev[i].x;
        p[4-i].y = rect->dev[i].y;
      }
      p[0] = p[4];
      if (rect->relief != ZN_RELIEF_FLAT) {
        ZnRenderPolygonRelief(wi, rect->relief, rect->gradient, False,
                              p, 5, rect->line_width);
      }
      else {
        ZnRenderPolyline(wi, p, 5, rect->line_width,
                         rect->line_style, CapRound, JoinMiter,
                         NULL, NULL, rect->line_color);
      }
    }
#ifdef GL_LIST    
    glEndList();
  }
  
  glCallList(item->gl_list);
#endif
}
#else
static void
Render(ZnItem   item)
{
}
#endif
 

/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  RectangleItem rect = (RectangleItem) item;
  double        best_dist;
  ZnPoint       *p = ps->point;

  best_dist = ZnPolygonToPointDist(rect->dev, 4, p);

  if (ISSET(rect->flags, FILLED_BIT)) {
    if (best_dist <= 0.0) {
      return 0.0;
    }
  }
  best_dist = ABS(best_dist);
  
  if (rect->line_width > 1) {
    double      dist;
    int         i;
    ZnPoint     pts[5];

    for (i = 0; i < 4; i++) {
      pts[i] = rect->dev[i];
    }
    pts[4] = pts[0];
    dist = ZnPolylineToPointDist(pts, 5, rect->line_width,
                                 CapProjecting, JoinMiter, p);
    if (dist <= 0.0) {
      return 0.0;
    }
    best_dist = MIN(dist, best_dist);
  }

  return best_dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ZnWInfo       *wi = item->wi;
  RectangleItem rect = (RectangleItem) item;
  char          path[500];

  if (ISCLEAR(rect->flags, FILLED_BIT) && (rect->line_width == 0)) {
    return TCL_OK;
  }

  /*
   * Create the rectangle path.
   */
  sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto %.15g %.15g lineto %.15g %.15g lineto closepath\n",
          rect->dev[0].x, rect->dev[0].y, rect->dev[1].x, rect->dev[1].y,
          rect->dev[2].x, rect->dev[2].y, rect->dev[3].x, rect->dev[3].y);
  Tcl_AppendResult(wi->interp, path, NULL);

  /*
   * Emit code to draw the filled area.
   */
  if (ISSET(rect->flags, FILLED_BIT)) {
    if (rect->line_width) {
      Tcl_AppendResult(wi->interp, "gsave\n", NULL);
    }
    if (!ZnGradientFlat(rect->fill_color)) {
      if (ZnPostscriptGradient(wi->interp, wi->ps_info, rect->fill_color,
                               rect->grad_geo ? rect->grad_geo : rect->dev, NULL) != TCL_OK) {
        return TCL_ERROR;
      }
    }
    else if (rect->tile != ZnUnspecifiedImage) {
      if (!ZnImageIsBitmap(rect->tile)) { /* Fill tiled */
        if (ZnPostscriptTile(wi->interp, wi->win, wi->ps_info, rect->tile) != TCL_OK) {
          return TCL_ERROR;
        }
      }
      else { /* Fill stippled */
        if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                               ZnGetGradientColor(rect->fill_color, 0.0, NULL)) != TCL_OK) {
          return TCL_ERROR;
        }
        Tcl_AppendResult(wi->interp, "clip ", NULL);
        if (ZnPostscriptStipple(wi->interp, wi->win, wi->ps_info, rect->tile) != TCL_OK) {
          return TCL_ERROR;
        }
      }
    }
    else { /* Fill solid */
      if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                             ZnGetGradientColor(rect->fill_color, 0.0, NULL)) != TCL_OK) {
        return TCL_ERROR;
      }
      Tcl_AppendResult(wi->interp, "fill\n", NULL);
    }
    if (rect->line_width) {
      Tcl_AppendResult(wi->interp, "grestore\n", NULL);
    }
  }

  /*
   * Then emit code code to stroke the outline.
   */
  if (rect->line_width) {
    if (rect->relief != ZN_RELIEF_FLAT) {
      /* TODO No support yet */
    }
    else {
      Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
      if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
                              rect->line_width, rect->line_style,
                              rect->line_color, rect->line_pattern) != TCL_OK) {
        return TCL_ERROR;
      }
    }
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  RectangleItem rect = (RectangleItem) item;
  ZnPoint       *points;

  if (ISSET(rect->flags, ALIGNED_BIT)) {
    ZnListAssertSize(ZnWorkPoints, 2);
    points = ZnListArray(ZnWorkPoints);
    ZnTriStrip1(tristrip, points, 2, False);
    tristrip->strips[0].fan = False;
  
    if (rect->dev[0].x < rect->dev[2].x) {
      points[0].x = rect->dev[0].x;
      points[1].x = rect->dev[2].x+1.0;
    }
    else {
      points[0].x = rect->dev[2].x;
      points[1].x = rect->dev[0].x+1.0;
    }
    if (rect->dev[0].y < rect->dev[2].y) {
      points[0].y = rect->dev[0].y;
      points[1].y = rect->dev[2].y+1.0;
    }
    else {
      points[0].y = rect->dev[2].y;
      points[1].y = rect->dev[0].y+1.0;
    }
  }
  else {
    ZnListAssertSize(ZnWorkPoints, 4);
    points = ZnListArray(ZnWorkPoints);
    points[0] = rect->dev[1];
    points[1] = rect->dev[2];
    points[2] = rect->dev[0];
    points[3] = rect->dev[3];
    ZnTriStrip1(tristrip, points, 4, False);
  }

  return ISSET(rect->flags, ALIGNED_BIT);
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item vertices.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  RectangleItem rect = (RectangleItem) item;

  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " rectangles can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if (cmd == ZN_COORDS_REPLACE_ALL) {
    if (*num_pts != 2) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 2 points on rectangles", NULL);
      return TCL_ERROR;
    }
    rect->coords[0] = (*pts)[0];
    rect->coords[1] = (*pts)[1];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if (cmd == ZN_COORDS_REPLACE) {
    if (*num_pts < 1) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need at least 1 point", NULL);
      return TCL_ERROR;
    }
    if (index < 0) {
      index += 2;
    }
    if ((index < 0) || (index > 1)) {
    range_err:
      Tcl_AppendResult(item->wi->interp,
                       " incorrect coord index, should be between -2 and 1", NULL);
      return TCL_ERROR;
    }
    rect->coords[index] = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if (cmd == ZN_COORDS_READ_ALL) {
    *num_pts = 2;
    *pts = rect->coords;
  }
  else if (cmd == ZN_COORDS_READ) {
    if (index < 0) {
      index += 2;
    }
    if ((index < 0) || (index > 1)) {
      goto range_err;
    }
    *num_pts = 1;
    *pts = &rect->coords[index];
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  ZnBBox *bbox = &item->item_bounding_box;

  ZnOrigin2Anchor(&bbox->orig,
                  bbox->corner.x - bbox->orig.x,
                  bbox->corner.y - bbox->orig.y,
                  anchor, p);
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */ 
static CONST ZnItemClassStruct RECTANGLE_ITEM_CLASS = {
  "rectangle",
  sizeof(RectangleItemStruct),
  rect_attrs,
  0,                    /* num_parts */
  0,                    /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  GetClipVertices,
  NULL,                 /* GetContours */
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnRectangle = (ZnItemClassId) &RECTANGLE_ITEM_CLASS;

Added jni/tkzinc/generic/Reticle.c.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
/*
 * Reticle.c -- Implementation of Reticle item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Mon Feb  1 12:13:24 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Types.h"
#include "WidgetInfo.h"
#include "Item.h"
#include "Geo.h"
#include "Draw.h"

#include <math.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 * Draw as many circles as visible.
 */
#define ANY_CIRCLES     -1

/*
 * Some default values.
 */
#define DEFAULT_RETICLE_STEP_SIZE       80
#define DEFAULT_RETICLE_PERIOD          5

/*
 **********************************************************************************
 *
 * Specific Reticle item record
 *
 **********************************************************************************
 */

typedef struct _ReticleItemStruct {
  ZnItemStruct  header;
 
  /* Public data */
  ZnPoint       pos;                    /* Origin world coordinates     */
  ZnGradient    *line_color;            /* circle color           */
  ZnGradient    *bright_line_color;     /* intermediate circle color */
  ZnDim         first_radius;           /* first world radius             */
  ZnDim         step_size;              /* step world size                */
  int           period;                 /* bright circle period           */
  int           num_circles;            /* num cercles max                */
  ZnLineStyle   line_style;             /* circles lines styles           */
  ZnLineStyle   bright_line_style;

  /* Private data */
  ZnPoint       dev;                    /* item device coordinate         */
  ZnDim         first_radius_dev;       /* first device radius            */
  ZnDim         step_size_dev;          /* steps device size              */
} ReticleItemStruct, *ReticleItem;


static ZnAttrConfig     reticle_attrs[] = {
  { ZN_CONFIG_GRADIENT, "-brightlinecolor", NULL,
    Tk_Offset(ReticleItemStruct, bright_line_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-brightlinestyle", NULL,
    Tk_Offset(ReticleItemStruct, bright_line_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(ReticleItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(ReticleItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(ReticleItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(ReticleItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_DIM, "-stepsize", NULL,
    Tk_Offset(ReticleItemStruct, step_size), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_DIM, "-firstradius", NULL,
    Tk_Offset(ReticleItemStruct, first_radius), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-linecolor", NULL,
    Tk_Offset(ReticleItemStruct, line_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-linestyle", NULL,
    Tk_Offset(ReticleItemStruct, line_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_UINT, "-numcircles", NULL,
    Tk_Offset(ReticleItemStruct, num_circles), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_UINT, "-period", NULL,
    Tk_Offset(ReticleItemStruct, period), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_POINT, "-position", NULL,
    Tk_Offset(ReticleItemStruct, pos), 0,
    ZN_COORDS_FLAG, False},
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(ReticleItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(ReticleItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(ReticleItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(ReticleItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])     
{
  ReticleItem   reticle = (ReticleItem) item;
  ZnWInfo       *wi = item->wi;
  
  SET(item->flags, ZN_VISIBLE_BIT);
  CLEAR(item->flags, ZN_SENSITIVE_BIT);
  CLEAR(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 0;
  item->part_sensitive = 0;
  reticle->line_color = ZnGetGradientByValue(wi->fore_color);
  reticle->bright_line_color = ZnGetGradientByValue(wi->fore_color);
  reticle->first_radius = DEFAULT_RETICLE_STEP_SIZE;
  reticle->step_size = DEFAULT_RETICLE_STEP_SIZE;
  reticle->period = DEFAULT_RETICLE_PERIOD;
  reticle->num_circles = ANY_CIRCLES;
  reticle->line_style = ZN_LINE_SIMPLE;
  reticle->bright_line_style = ZN_LINE_SIMPLE;
  reticle->pos.x = 0;
  reticle->pos.y = 0;
  reticle->dev.x = 0;
  reticle->dev.y = 0;
  reticle->first_radius_dev = 0;
  reticle->step_size_dev = 0;

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  ReticleItem   reticle = (ReticleItem) item;
  
  reticle->line_color = ZnGetGradientByValue(reticle->line_color);
  reticle->bright_line_color = ZnGetGradientByValue(reticle->bright_line_color);  
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  ReticleItem   reticle = (ReticleItem) item;
    
  ZnFreeGradient(reticle->line_color);
  ZnFreeGradient(reticle->bright_line_color);
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  if (ZnConfigureAttributes(item->wi, item, item, reticle_attrs,
                            argc, argv, flags) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, reticle_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }  

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  ReticleItem   reticle  = (ReticleItem) item;
  ZnDim         half_width;
  ZnPoint       p, xp;
  
  /* Compute center device coordinates */
  p.x = p.y = 0;
  ZnTransformPoint(wi->current_transfo, &p, &reticle->dev);
  p.x = reticle->step_size;
  ZnTransformPoint(wi->current_transfo, &p, &xp);
  reticle->step_size_dev = hypot(xp.x - reticle->dev.x, xp.y - reticle->dev.y);
  p.x = reticle->first_radius;
  ZnTransformPoint(wi->current_transfo, &p, &xp);
  reticle->first_radius_dev = hypot(xp.x - reticle->dev.x, xp.y - reticle->dev.y);
  if (reticle->first_radius_dev < 1.0) {
    reticle->first_radius_dev = 1.0;
  }
  if (reticle->step_size_dev < 1.0) {
    reticle->step_size_dev = 1.0;
  }
  
  /* Reticle bounding box is zn bounding box or depends on num_circles */
  if (reticle->num_circles == ANY_CIRCLES) {
    item->item_bounding_box.orig.x = 0;
    item->item_bounding_box.orig.y = 0;
    item->item_bounding_box.corner.x = wi->width;
    item->item_bounding_box.corner.y = wi->height;
  }
  else {
    half_width = reticle->first_radius_dev +
                 (reticle->num_circles - 1) * reticle->step_size_dev;
    item->item_bounding_box.orig.x = reticle->dev.x - half_width;
    item->item_bounding_box.orig.y = reticle->dev.y - half_width;
    item->item_bounding_box.corner.x = item->item_bounding_box.orig.x + (2 * half_width);
    item->item_bounding_box.corner.y = item->item_bounding_box.orig.y + (2 * half_width);
  }
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  return -1;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  ReticleItem   reticle = (ReticleItem) item;
  ZnDim         radius  = reticle->first_radius_dev;
  ZnDim         radius_max_dev;
  XGCValues     values;
  int           i;
  ZnDim         l1, l2, l3, l4;
/*  int         count = 0;*/

  /* Compute radius max */
  l1 = (ZnDim) hypot(wi->damaged_area.orig.x - reticle->dev.x,
                     wi->damaged_area.orig.y - reticle->dev.y);
  l2 = (ZnDim) hypot(wi->damaged_area.corner.x - reticle->dev.x,
                     wi->damaged_area.orig.y - reticle->dev.y);
  l3 = (ZnDim) hypot(wi->damaged_area.orig.x - reticle->dev.x,
                     wi->damaged_area.corner.y - reticle->dev.y);
  l4 = (ZnDim) hypot(wi->damaged_area.corner.x - reticle->dev.x,
                     wi->damaged_area.corner.y - reticle->dev.y);
  radius_max_dev = MAX(MAX(l1,l2), MAX(l3, l4));

  if (reticle->num_circles > 0) {
    radius_max_dev = MIN(radius_max_dev, reticle->first_radius_dev +
                         (reticle->num_circles - 1) * reticle->step_size_dev);
  }
  
  while (radius <= radius_max_dev) {
    ZnSetLineStyle(wi, reticle->line_style);
    values.foreground = ZnGetGradientPixel(reticle->line_color, 0.0);
    values.line_width = 1;
    values.fill_style = FillSolid;
    XChangeGC(wi->dpy, wi->gc, GCForeground | GCLineWidth | GCFillStyle, &values);
    for (i = 1; ((radius <= radius_max_dev) && (i < reticle->period)); i++) {
      if ((reticle->dev.x >= wi->damaged_area.orig.x - radius) &&
          (reticle->dev.x <= wi->damaged_area.corner.x + radius) &&
          (reticle->dev.y >= wi->damaged_area.orig.y - radius) &&
          (reticle->dev.y <= wi->damaged_area.corner.y + radius)) {
        XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
                 (int) (reticle->dev.x - radius),
                 (int) (reticle->dev.y - radius),
                 (unsigned int) (radius * 2 - 1),
                 (unsigned int) (radius * 2 - 1),
                 0, 360 * 64);
/*      count++;*/
      }
      radius += (reticle->step_size_dev);
    }
    if ((radius <= radius_max_dev) &&
        (reticle->dev.x >= wi->damaged_area.orig.x - radius) &&
        (reticle->dev.x <= wi->damaged_area.corner.x + radius) &&
        (reticle->dev.y >= wi->damaged_area.orig.y - radius) &&
        (reticle->dev.y <= wi->damaged_area.corner.y + radius)) {
      ZnSetLineStyle(wi, reticle->bright_line_style);
      values.foreground = ZnGetGradientPixel(reticle->bright_line_color, 0.0);
      values.line_width = 1;
      values.fill_style = FillSolid;
      XChangeGC(wi->dpy, wi->gc, GCForeground | GCLineWidth | GCFillStyle, &values);
      XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
               (int) (reticle->dev.x - radius),
               (int) (reticle->dev.y - radius),
               (unsigned int) (radius * 2 - 1),
               (unsigned int) (radius * 2 - 1),
               0, 360 * 64);
      /*count++;*/
    }
    radius += (reticle->step_size_dev);
  }
/*printf("# circles drawn: %d\n", count);*/
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
Render(ZnItem   item)
{
  ZnWInfo       *wi = item->wi;
  ReticleItem   reticle = (ReticleItem) item;
  ZnDim         radius  = reticle->first_radius_dev;
  ZnDim         radius_max_dev, new, x, y, xo, yo;
  int           i, j;
  ZnPoint       *genarc;
  unsigned int  num_p;
  unsigned short alpha;
  XColor        *color;

  xo = reticle->dev.x;
  yo = reticle->dev.y;
  /* Compute radius max */
  radius_max_dev = 0;
  x = wi->damaged_area.orig.x - xo;
  y = wi->damaged_area.orig.y - yo;
  new = x*x + y*y;
  if (new > radius_max_dev) {
    radius_max_dev = new;
  }
  x = wi->damaged_area.corner.x - xo;
  y = wi->damaged_area.orig.y - yo;
  new = x*x + y*y;
  if (new > radius_max_dev) {
    radius_max_dev = new;
  }
  x = wi->damaged_area.orig.x - xo;
  y = wi->damaged_area.corner.y - yo;
  new = x*x + y*y;
  if (new > radius_max_dev) {
    radius_max_dev = new;
  }
  x = wi->damaged_area.corner.x - xo;
  y = wi->damaged_area.corner.y - yo;
  new = x*x + y*y;
  if (new > radius_max_dev) {
    radius_max_dev = new;
  }
  radius_max_dev = sqrt(radius_max_dev);

  if (reticle->num_circles > 0) {
    radius_max_dev = MIN(radius_max_dev, reticle->first_radius_dev +
                         (reticle->num_circles - 1) * reticle->step_size_dev);
  }

  genarc = ZnGetCirclePoints(3, ZN_CIRCLE_FINER, 0.0, 2*M_PI, &num_p, NULL);
  glLineWidth(1.0);
  while (radius <= radius_max_dev) {
    ZnSetLineStyle(wi, reticle->line_style);
    color = ZnGetGradientColor(reticle->line_color, 0.0, &alpha);
    alpha = ZnComposeAlpha(alpha, wi->alpha);
    glColor4us(color->red, color->green, color->blue, alpha);
    for (i = 1; ((radius <= radius_max_dev) && (i < reticle->period)); i++) {
      if ((xo >= wi->damaged_area.orig.x - radius) &&
          (xo <= wi->damaged_area.corner.x + radius) &&
          (yo >= wi->damaged_area.orig.y - radius) &&
          (yo <= wi->damaged_area.corner.y + radius)) {
        glBegin(GL_LINE_LOOP);
        for (j = 0; j < num_p; j++) {
          x = xo + genarc[j].x * radius;
          y = yo + genarc[j].y * radius;
          glVertex2d(x, y);
        }
        glEnd();
      }
      radius += (reticle->step_size_dev);
    }
    if ((radius <= radius_max_dev) &&
        (xo >= wi->damaged_area.orig.x - radius) &&
        (xo <= wi->damaged_area.corner.x + radius) &&
        (yo >= wi->damaged_area.orig.y - radius) &&
        (yo <= wi->damaged_area.corner.y + radius)) {
      ZnSetLineStyle(wi, reticle->bright_line_style);
      color = ZnGetGradientColor(reticle->bright_line_color, 0.0, &alpha);
      alpha = ZnComposeAlpha(alpha, wi->alpha);
      glColor4us(color->red, color->green, color->blue, alpha);
      glBegin(GL_LINE_LOOP);
      for (j = 0; j < num_p; j++) {
        x = xo + genarc[j].x * radius;
        y = yo + genarc[j].y * radius;
        glVertex2d(x, y);
      }
      glEnd();
    }
    radius += (reticle->step_size_dev);
  }
  glDisable(GL_LINE_STIPPLE);
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *      Nothing to pick, we are almost transparent.
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  return 1e40;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item center.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  ReticleItem   reticle = (ReticleItem) item;
  
  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " reticles can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (*num_pts == 0) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 1 point on reticles", NULL);
      return TCL_ERROR;
    }
    reticle->pos = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    *num_pts = 1;
    *pts = &reticle->pos;
  }
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct RETICLE_ITEM_CLASS = {
  "reticle",
  sizeof(ReticleItemStruct),
  reticle_attrs,
  0,                    /* num_parts */
  ZN_CLASS_ONE_COORD,   /* flags */
  Tk_Offset(ReticleItemStruct, pos),
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  NULL,                 /* GetAnchor */
  NULL,                 /* GetClipVertices */
  NULL,                 /* GetContours */
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnReticle = (ZnItemClassId) &RETICLE_ITEM_CLASS;

Added jni/tkzinc/generic/Tabular.c.

















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
/*
 * Tabular.c -- Implementation of Tabular item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Types.h"
#include "WidgetInfo.h"
#include "Item.h"
#include "Geo.h"
#include "tkZinc.h"

#include <ctype.h>
#include <stdlib.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 **********************************************************************************
 *
 * Specific Tabular item record
 *
 **********************************************************************************
 */
typedef struct _TabularItemStruct {
  ZnItemStruct          header;

  /* Public data */
  ZnPoint               pos;
  Tk_Anchor             anchor;
  Tk_Anchor             connection_anchor;

  /* Private data */
  ZnFieldSetStruct      field_set;
} TabularItemStruct, *TabularItem;


static ZnAttrConfig     tabular_attrs[] = {
  { ZN_CONFIG_ANCHOR, "-anchor", NULL,
    Tk_Offset(TabularItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(TabularItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(TabularItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(TabularItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(TabularItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ITEM, "-connecteditem", NULL,
    Tk_Offset(TabularItemStruct, header.connected_item), 0,
    ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
  { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
    Tk_Offset(TabularItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LABEL_FORMAT, "-labelformat", NULL,
    Tk_Offset(TabularItemStruct, field_set.label_format), 0,
    ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
  { ZN_CONFIG_UINT, "-numfields", NULL,
    Tk_Offset(TabularItemStruct, field_set.num_fields), 0, 0, True },
  { ZN_CONFIG_POINT, "-position", NULL,
    Tk_Offset(TabularItemStruct, pos), 0, ZN_COORDS_FLAG, False},
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(TabularItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(TabularItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(TabularItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(TabularItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  ZnWInfo       *wi = item->wi;
  TabularItem   tab = (TabularItem) item;
  ZnFieldSet    field_set = &tab->field_set;
  int           num_fields;

  item->priority = 1;

  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);

  tab->anchor = TK_ANCHOR_NW;
  tab->connection_anchor = TK_ANCHOR_SW;
  tab->pos.x = tab->pos.y = 0.0;

  field_set->item = item;
  field_set->label_format = NULL;
  
  /*
   * Then try to see if some fields are needed.
   */
  if ((*argc > 0) && (Tcl_GetString((*args)[0])[0] != '-') &&
      (Tcl_GetIntFromObj(wi->interp, (*args)[0], &num_fields) != TCL_ERROR)) {
    field_set->num_fields = num_fields;
    *args += 1;
    *argc -= 1;
    ZnFIELD.InitFields(field_set);
  }
  else {
    Tcl_AppendResult(wi->interp, " number of fields expected", NULL);
    return TCL_ERROR;
  }    
  
  item->part_sensitive = 0;

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  ZnFieldSet    fs = &((TabularItem) item)->field_set;

  ZnFIELD.CloneFields(fs);
  fs->item = item;
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  ZnFIELD.FreeFields(&((TabularItem) item)->field_set);
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  ZnItem        old_connected;

  old_connected = item->connected_item;
  if (ZnConfigureAttributes(item->wi, item, item, tabular_attrs,
                            argc, argv, flags) == TCL_ERROR) {
    item->connected_item = old_connected;
    return TCL_ERROR;
  }
  if (ISSET(*flags, ZN_ITEM_FLAG)) {
    /*
     * If the new connected item is not appropriate back up
     * to the old one.
     */
    if ((item->connected_item == ZN_NO_ITEM) ||
        (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
         (item->parent == item->connected_item->parent))) {
      ZnITEM.UpdateItemDependency(item, old_connected);
    }
    else {
      item->connected_item = old_connected;
    }
  }  

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, tabular_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  TabularItem   tab = (TabularItem) item;
  ZnWInfo       *wi = item->wi;
  ZnFieldSet    field_set = &tab->field_set;
  ZnDim         width, height;
  
  ZnResetBBox(&item->item_bounding_box);
  if (field_set->label_format && field_set->num_fields) {
    ZnFIELD.GetLabelBBox(field_set, &width, &height);

    /*
     * The connected item support anchors, this is checked by
     * configure.
     */
    if (item->connected_item != ZN_NO_ITEM) {
      item->connected_item->class->GetAnchor(item->connected_item,
                                             tab->connection_anchor,
                                             &field_set->label_pos);
    }
    else {
      ZnPoint pos;
      pos.x = pos.y = 0;
      ZnTransformPoint(wi->current_transfo, &pos,
                          &field_set->label_pos);
    }

    ZnAnchor2Origin(&field_set->label_pos, width, height, tab->anchor,
                    &field_set->label_pos);

    /*
     * Setup the item bounding box.
     */
    item->item_bounding_box.orig = field_set->label_pos;
    item->item_bounding_box.corner.x = field_set->label_pos.x + width;
    item->item_bounding_box.corner.y = field_set->label_pos.y + height;
    /*
     * Need to slightly increase the bbox for GL thick lines
     */
#ifdef GL
    item->item_bounding_box.orig.x -= 1;
    item->item_bounding_box.orig.y -= 1;
    item->item_bounding_box.corner.x += 1;
    item->item_bounding_box.corner.y += 1;
#endif

    /*
     * Update connected items.
     */
    SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
  }
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  return ZnFIELD.FieldsToArea(&((TabularItem) item)->field_set, ta->area);
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnFIELD.DrawFields(&((TabularItem) item)->field_set);
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
static void
Render(ZnItem   item)
{
  ZnFIELD.RenderFields(&((TabularItem) item)->field_set);
}


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  if (ISCLEAR(item->flags, ZN_SENSITIVE_BIT) ||
      !item->parent->class->IsSensitive(item->parent, ZN_NO_PART)) {
    return False;
  }
  if (item_part == ZN_NO_PART) {
    return ISSET(item->flags, ZN_SENSITIVE_BIT);
  }
  else {    
    return ZnFIELD.IsFieldSensitive(&((TabularItem) item)->field_set, item_part);
  }
}


/*
 **********************************************************************************
 *
 * Pick --
 *      We tell what our label tells.
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  int best_part;
  double dist;
  
  dist = ZnFIELD.FieldsPick(&((TabularItem) item)->field_set, ps->point, &best_part);
  /*printf("tabular %d reporting part %d, distance %lf\n",
    item->id, best_part, dist);*/
  if (dist <= 0.0) {
    dist = 0.0;
  }
  
  ps->a_part = best_part;
  return dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  return ZnFIELD.PostScriptFields(&((TabularItem) item)->field_set, prepass, area);
}


/*
 **********************************************************************************
 *
 * GetFieldSet --
 *
 **********************************************************************************
 */
static ZnFieldSet
GetFieldSet(ZnItem      item)
{
  return &((TabularItem) item)->field_set;
}


/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  ZnFieldSet    field_set = &((TabularItem) item)->field_set;
  ZnDim width, height;
  
  if (field_set->label_format) {
    ZnFIELD.GetLabelBBox(field_set, &width, &height);
    ZnOrigin2Anchor(&field_set->label_pos, width, height, anchor, p);
  }
  else {
    p->x = p->y = 0.0;
  }
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  ZnFieldSet    field_set = &((TabularItem) item)->field_set;
  ZnDim         width, height;
  ZnPoint       *points;
  
  if (field_set->label_format) {
    ZnFIELD.GetLabelBBox(field_set, &width, &height);
    ZnListAssertSize(ZnWorkPoints, 2);
    points = (ZnPoint *) ZnListArray(ZnWorkPoints);
    ZnTriStrip1(tristrip, points, 2, False);
    points[0] = field_set->label_pos;
    points[1].x = points[0].x + width;
    points[1].y = points[0].y + height;
  }

  return True;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item origin. This doesn't take care of
 *      the possible attachment. The change will be effective at the
 *      end of the attachment.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  TabularItem   tabular = (TabularItem) item;
  
  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " tabulars can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (*num_pts == 0) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 1 point on tabulars", NULL);
      return TCL_ERROR;
    }
    tabular->pos = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    *num_pts = 1;
    *pts = &tabular->pos;
  }
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Part --
 *      Convert a private part from/to symbolic representation.
 *
 **********************************************************************************
 */
static int
Part(ZnItem     item,
     Tcl_Obj    **part_spec,
     int        *part)
{
  char  *part_str;
  char  *end;
  
  if (*part_spec) {
    part_str = Tcl_GetString(*part_spec);
    if (strlen(part_str) == 0) {
      *part = ZN_NO_PART;
    }
    else if (isdigit(part_str[0])) {
      *part = strtol(part_str, &end, 0);
      if ((*end != 0) || (*part < 0) ||
          ((unsigned int) *part >= ((TabularItem) item)->field_set.num_fields)) {
        goto part_error;
      }
    }
    else {
    part_error:
      Tcl_AppendResult(item->wi->interp, " invalid item part specification", NULL);
      return TCL_ERROR; 
    }
  }
  else {
    if (*part >= 0) {
      *part_spec = Tcl_NewIntObj(*part);
    }
    else {
      *part_spec = Tcl_NewStringObj("", -1);
    }
  }
  return TCL_OK;  
}


/*
 **********************************************************************************
 *
 * Index --
 *      Parse a text index and return its value and aa
 *      error status (standard Tcl result).
 *
 **********************************************************************************
 */
static int
Index(ZnItem    item,
      int       field,
      Tcl_Obj   *index_spec,
      int       *index)
{
  return ZnFIELD.FieldIndex(&((TabularItem) item)->field_set, field,
                          index_spec, index);
}


/*
 **********************************************************************************
 *
 * InsertChars --
 *
 **********************************************************************************
 */
static void
InsertChars(ZnItem      item,
            int         field,
            int         *index,
            char        *chars)
{
  if (ZnFIELD.FieldInsertChars(&((TabularItem) item)->field_set,
                             field, index, chars)) {
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
}


/*
 **********************************************************************************
 *
 * DeleteChars --
 *
 **********************************************************************************
 */
static void
DeleteChars(ZnItem      item,
            int         field,
            int         *first,
            int         *last)
{
  if (ZnFIELD.FieldDeleteChars(&((TabularItem) item)->field_set,
                             field, first, last)) {
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
}


/*
 **********************************************************************************
 *
 * Cursor --
 *
 **********************************************************************************
 */
static void
TabularCursor(ZnItem    item,
              int       field,
              int       index)
{
  ZnFIELD.FieldCursor(&((TabularItem) item)->field_set, field, index);
}


/*
 **********************************************************************************
 *
 * Selection --
 *
 **********************************************************************************
 */
static int
Selection(ZnItem        item,
          int           field,
          int           offset,
          char          *chars,
          int           max_chars)
{
  return ZnFIELD.FieldSelection(&((TabularItem) item)->field_set, field,
                              offset, chars, max_chars);
}


/*
 **********************************************************************************
 *
 * Exported functions structs --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct TABULAR_ITEM_CLASS = {
  "tabular",
  sizeof(TabularItemStruct),
  tabular_attrs,
  0,
  ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
  Tk_Offset(TabularItemStruct, pos),
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  GetFieldSet,
  GetAnchor,
  GetClipVertices,
  NULL,                 /* GetContours */
  Coords,
  InsertChars,
  DeleteChars,
  TabularCursor,
  Index,
  Part,
  Selection,
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnTabular = (ZnItemClassId) &TABULAR_ITEM_CLASS;

Added jni/tkzinc/generic/Text.c.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
/*
 * Text.c -- Implementation of Text item.
 *
 * Authors              : Patrick LECOANET
 * Creation date        : Sat Mar 25 13:58:39 1995
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
 * Some functions in this file are derived from tkCanvText.c and thus
 * copyrighted:
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
 *
 */

#include <math.h>
#include <ctype.h>
#include <X11/Xatom.h>
#include <string.h>
#include <stdlib.h>

#include "Item.h"
#include "Geo.h"
#include "Draw.h"
#include "Types.h"
#include "WidgetInfo.h"
#include "tkZinc.h"
#include "Image.h"


static const char rcsid[] = "$Imagine: Text.c,v 1.13 1997/05/15 11:35:46 lecoanet Exp $";
static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 * Bit offset of flags.
 */
#define UNDERLINED      1
#define OVERSTRIKED     2


/*
 **********************************************************************************
 *
 * Specific Text item record
 *
 **********************************************************************************
 */
typedef struct _TextLineInfo 
{
  char           *start;         /* Index of first char in line */
  unsigned short num_bytes;    /* Number of displayed bytes in line (NOT chars)*/
  unsigned short width;         /* Line width in pixels */
  unsigned short origin_x;      /* X pos for drawing the line */
  unsigned short origin_y;
} TextLineInfoStruct, *TextLineInfo;

typedef struct _TextItemStruct {
  ZnItemStruct  header;

  /* Public data */
  ZnPoint       pos;            /* Position at anchor */
  ZnGradient    *color;
  char          *text;
  ZnImage       fill_pattern;
  Tk_Font       font;
  unsigned short width;
  short         spacing;
  unsigned short flags;
  Tk_Anchor     anchor;
  Tk_Anchor     connection_anchor;
  Tk_Justify    alignment;

  /* Private data */
  unsigned short num_chars;
  unsigned short insert_index;
  ZnList        text_info;
  unsigned short max_width;
  unsigned short height;
  ZnPoint       poly[4];
#ifdef GL
  ZnTexFontInfo *tfi;
#endif
} TextItemStruct, *TextItem;


static ZnAttrConfig     text_attrs[] = {
  { ZN_CONFIG_ALIGNMENT, "-alignment", NULL,
    Tk_Offset(TextItemStruct, alignment), 0,
    ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
  { ZN_CONFIG_ANCHOR, "-anchor", NULL,
    Tk_Offset(TextItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(TextItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-color", NULL,
    Tk_Offset(TextItemStruct, color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(TextItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(TextItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(TextItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ITEM, "-connecteditem", NULL,
    Tk_Offset(TextItemStruct, header.connected_item), 0,
    ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
  { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
    Tk_Offset(TextItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-fillpattern", NULL,
    Tk_Offset(TextItemStruct, fill_pattern), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_FONT, "-font", NULL,
    Tk_Offset(TextItemStruct, font), 0,
    ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
  { ZN_CONFIG_BOOL, "-overstriked", NULL,
    Tk_Offset(TextItemStruct, flags), OVERSTRIKED, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(TextItemStruct, pos), 0,
    ZN_COORDS_FLAG, False},
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(TextItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(TextItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_SHORT, "-spacing", NULL,
    Tk_Offset(TextItemStruct, spacing), 0,
    ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(TextItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_STRING, "-text", NULL,
    Tk_Offset(TextItemStruct, text), 0,
    ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
  { ZN_CONFIG_BOOL, "-underlined", NULL,
    Tk_Offset(TextItemStruct, flags), UNDERLINED, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(TextItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  { ZN_CONFIG_USHORT, "-width", NULL,
    Tk_Offset(TextItemStruct, width), 0,
    ZN_COORDS_FLAG|ZN_LAYOUT_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  ZnWInfo       *wi = item->wi;
  TextItem      text = (TextItem) item;

  /*printf("size of a text(header) = %d(%d) %d\n",
    sizeof(TextItemStruct), sizeof(ZnItemStruct), sizeof(TextLineInfoStruct));*/
 
  text->text_info = NULL;
  
  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  CLEAR(item->flags, ZN_COMPOSE_ROTATION_BIT);
  CLEAR(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 1;

  text->pos.x = text->pos.y = 0.0;
  text->text = NULL;
  text->num_chars = 0;
  text->fill_pattern = ZnUnspecifiedImage;
  text->anchor = TK_ANCHOR_NW;
  text->connection_anchor = TK_ANCHOR_SW;
  text->color = ZnGetGradientByValue(wi->fore_color);
  text->alignment = TK_JUSTIFY_LEFT;
  text->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(wi->font));
#ifdef GL
  text->tfi = ZnGetTexFont(wi, text->font);
#endif
  text->width = 0;
  text->spacing = 0;
  text->insert_index = 0;
  CLEAR(text->flags, UNDERLINED);
  CLEAR(text->flags, OVERSTRIKED);

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  TextItem      text = (TextItem) item;
  ZnWInfo       *wi = item->wi;
  char          *str;

  if (text->text) {
    str = ZnMalloc((strlen(text->text) + 1) * sizeof(char));
    strcpy(str, text->text);
    text->text = str;
  }
  if (text->fill_pattern != ZnUnspecifiedImage) {
    text->fill_pattern = ZnGetImageByValue(text->fill_pattern, NULL, NULL);
  }
  text->color = ZnGetGradientByValue(text->color);
  text->font = Tk_GetFont(wi->interp, wi->win, Tk_NameOfFont(text->font));
#ifdef GL
  text->tfi = ZnGetTexFont(wi, text->font);
#endif

  /*
   * We always need to invalidate, either because the model
   * has not done its layout (text_info == NULL) or because
   * we must unshare the pointers to the text that are in
   * text_info.
   */
  text->text_info = NULL;
  ZnITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  TextItem      text = (TextItem) item;

  if (text->text) {
    ZnFree(text->text);
  }
  if (text->fill_pattern != ZnUnspecifiedImage) {
    ZnFreeImage(text->fill_pattern, NULL, NULL);
    text->fill_pattern = ZnUnspecifiedImage;
  }
  ZnFreeGradient(text->color);
  Tk_FreeFont(text->font);
#ifdef GL
  if (text->tfi) {
    ZnFreeTexFont(text->tfi);
  }
#endif
  
  if (text->text_info) {
    ZnListFree(text->text_info);
  }
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  TextItem      text = (TextItem) item;
  ZnItem        old_connected = item->connected_item;
  unsigned int  num_chars;
#ifdef GL
  Tk_Font       old_font = text->font;
#endif

  if (ZnConfigureAttributes(item->wi, item, item, text_attrs,
                            argc, argv, flags) == TCL_ERROR) {
    item->connected_item = old_connected;
    return TCL_ERROR;
  }

#ifdef GL
  if (old_font != text->font) {
    if (text->tfi) {
      ZnFreeTexFont(text->tfi);
      text->tfi = ZnGetTexFont(item->wi, text->font);
    }
  }
#endif
  num_chars = 0;
  if (text->text) {
    num_chars = Tcl_NumUtfChars(text->text, (int) strlen(text->text));
  }
  if (text->num_chars != num_chars) {
    ZnTextInfo *ti = &item->wi->text_info;
    /*
     * The text has changed, update the selection and
     * insertion pos to keep them valid.
     */
    if (item == ti->sel_item) {
      if (ti->sel_last > (int) num_chars) {
        ti->sel_last = num_chars;
      }
      if (ti->sel_first >= ti->sel_last) {
        ti->sel_item = ZN_NO_ITEM;
        ti->sel_field = ZN_NO_PART;
      }
      if ((ti->anchor_item == item) && (ti->sel_anchor > (int) num_chars)) {
        ti->sel_anchor = num_chars;
      }
    }
    if (text->insert_index > num_chars) {
      text->insert_index = num_chars;
    }
    text->num_chars = num_chars;
  }

  if (ISSET(*flags, ZN_ITEM_FLAG)) {
    /*
     * If the new connected item is not appropriate back up
     * to the old one.
     */
    if ((item->connected_item == ZN_NO_ITEM) ||
        (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
         (item->parent == item->connected_item->parent))) {
      ZnITEM.UpdateItemDependency(item, old_connected);
    }
    else {
      item->connected_item = old_connected;
    }
  }
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, text_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }  

  return TCL_OK;
}


/*
 * Compute the transformation to be used and the origin
 * of the text (upper left point in item coordinates).
 */
static ZnTransfo *
ComputeTransfoAndOrigin(ZnItem    item,
                        ZnPoint   *origin)
{
  TextItem text = (TextItem) item;

  /*
   * The connected item support anchors, this is checked by configure.
   */
  if (item->connected_item != ZN_NO_ITEM) {
    ZnTransfo inv;

    item->connected_item->class->GetAnchor(item->connected_item,
                                           text->connection_anchor,
                                           origin);

    /* GetAnchor return a position in device coordinates not in
     * the item coordinate space. To compute the text origin
     * (upper left corner), we must apply the inverse transform
     * to the ref point before calling anchor2origin.
     */
    ZnTransfoInvert(item->transfo, &inv);
    ZnTransformPoint(&inv, origin, origin);
    ZnAnchor2Origin(origin, (ZnReal) text->max_width,
                    (ZnReal) text->height, text->anchor, origin);
    origin->x = ZnNearestInt(origin->x);
    origin->y = ZnNearestInt(origin->y);
    /*
     * The relevant transform in case of an attachment is the item
     * transform alone. This is case of local coordinate space where
     * only the translation is a function of the whole transform
     * stack, scale and rotation are reset.
     */
    return item->transfo;
  }
  else {
    ZnPoint p;
    p.x = p.y = 0;
    ZnAnchor2Origin(&p, (ZnReal) text->max_width,
                    (ZnReal) text->height, text->anchor, origin);
    origin->x = ZnNearestInt(origin->x);
    origin->y = ZnNearestInt(origin->y);

    return item->wi->current_transfo;
  }
}


/*
 * Compute the selection and the cursor geometry.
 */
void
ComputeCursor(ZnItem       item,
              int          *cursor_line,
              unsigned int *cursor_offset)
{
  TextItem      text = (TextItem) item;
  ZnWInfo       *wi = item->wi;
  ZnTextInfo    *ti = &wi->text_info;
  TextLineInfo  lines, lines_ptr;
  unsigned int  i, line_index, insert_index, num_lines;

  if ((wi->focus_item != item) || ISCLEAR(wi->flags, ZN_GOT_FOCUS) || !ti->cursor_on) {
    return;
  }
  num_lines = ZnListSize(text->text_info);
  if (num_lines == 0) {
    *cursor_line = 0;
    *cursor_offset = 0;
    return;
  }

  lines = ZnListArray(text->text_info);
  insert_index = Tcl_UtfAtIndex(text->text, (int) text->insert_index) - text->text;
  for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
    /*
     * Mark the line with the cursor and compute its
     * position along the X axis.
     */
    line_index = lines_ptr->start - text->text;
    if ((insert_index >= line_index) && (insert_index <= line_index + lines_ptr->num_bytes)) {
      *cursor_line = i;
      *cursor_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start, insert_index - line_index);
    }
  }
}

static void
ComputeSelection(ZnItem       item,
                 int          *sel_first_line,
                 int          *sel_last_line,
                 unsigned int *sel_start_offset,
                 unsigned int *sel_stop_offset)
{  
  TextItem      text = (TextItem) item;
  ZnWInfo       *wi = item->wi;
  ZnTextInfo    *ti = &wi->text_info;
  TextLineInfo  lines_ptr, lines;
  int           i, num_lines, byte_index;
  unsigned int  line_index;
  unsigned int  sel_first, sel_last;

  num_lines = ZnListSize(text->text_info);

  if ((ti->sel_item != item) || !num_lines) {
    return;
  }

  lines = ZnListArray(text->text_info);

  sel_first = Tcl_UtfAtIndex(text->text, ti->sel_first)-text->text;
  sel_last = Tcl_UtfAtIndex(text->text, ti->sel_last)-text->text;
  for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
    /*
     * Compute the selection first and last line as well as
     * the positions along the X axis.
     */
    line_index = lines_ptr->start - text->text;
    if ((sel_last >= line_index) &&
        (sel_first <= (line_index + lines_ptr->num_bytes))) {
      if (*sel_first_line < 0) {
        byte_index = sel_first - line_index;
        if (byte_index <= 0) {
          *sel_first_line = i;
          *sel_start_offset = 0;
          /*printf("sel_start_offset 1 : %d\n", *sel_start_offset);*/
        }
        else if (byte_index <= lines_ptr->num_bytes) {
          *sel_first_line = i;
          *sel_start_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
                                           byte_index);
          /*printf("sel_start_offset 2 : %d\n", *sel_start_offset);*/
        }
      }
      byte_index = ti->sel_last - line_index;
      *sel_last_line = i;
      if (byte_index == lines_ptr->num_bytes+1)
        *sel_stop_offset = lines_ptr->width;
      else if (byte_index <= lines_ptr->num_bytes)
        *sel_stop_offset = Tk_TextWidth(text->font, (char *) lines_ptr->start,
                                        byte_index);
    }
  }
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  TextItem      text = (TextItem) item;
  TextLineInfo  infos;
  Tk_FontMetrics fm;
  ZnTransfo     *transfo;
  int           i, num_lines, cur_dy, font_height;
  
  ZnResetBBox(&item->item_bounding_box);
  
  Tk_GetFontMetrics(text->font, &fm);
  font_height = fm.ascent+fm.descent;
  
  /*
   * The layout need not be done each time the item is moved, scaled
   * or rotated.
   */
  if (ISSET(item->inv_flags, ZN_LAYOUT_FLAG)) {
    char *scan;
    int  wrap, prev_num_lines;

    text->max_width = 0;
    if (text->text_info != NULL) {
      prev_num_lines = ZnListSize(text->text_info);
      ZnListEmpty(text->text_info);
    }
    else {
      prev_num_lines = 0;
      text->text_info = ZnListNew(1, sizeof(TextLineInfoStruct));
    }
    
    if (text->width > 0) {
      wrap = text->width;
    }
    else {
      wrap = 100000;
    }
    
    if ((scan = text->text) != NULL) {
      TextLineInfoStruct info;

      while (*scan) {
        char    *special;
        int     num, w;

        /*
         * Limit the excursion of Tk_MeasureChars to the end
         * of the line. Do not include \n in the measure done.
         */
        num = strcspn(scan, "\r\n");
        special = scan + num;
        info.num_bytes = Tk_MeasureChars(text->font, scan, num, wrap,
                                         TK_WHOLE_WORDS|TK_AT_LEAST_ONE, &w);
        
        info.width = w;
        info.start = scan;
        text->max_width = MAX(info.width, text->max_width);
        
        scan += info.num_bytes;

        /*
         * Skip the newline line character.
         */
        if ((*scan == '\r') || (*scan == '\n')) {
          scan++;
        }
        else {
          /*
           * Skip white spaces occuring after an
           * automatic line break.
           */
          while (*scan == ' ') {
            scan++;
          }
        }
        
        ZnListAdd(text->text_info, &info, ZnListTail);
        /*printf("adding a text info : %s, num_bytes :  %d, width : %d\n",
          info.start, info.num_bytes, info.width);*/
      }
      if (*text->text && ((scan[-1] == '\r') || (scan[-1] == '\n'))) {
        /* Build a text info even for an empty line
         * at the end of text or for an empty text.
         * It is needed to enable selection and cursor
         * insertion to behave correctly.
         */
        info.num_bytes = 0;
        info.width = 0;
        info.start = scan;
        ZnListAdd(text->text_info, &info, ZnListTail);
      }
    }
  
    /*
     * Compute x & y positions for all lines in text_info. The coordinates are
     * in text natural units NOT transformed units.
     */
    cur_dy = fm.ascent;
    num_lines = ZnListSize(text->text_info);
    infos = (TextLineInfo) ZnListArray(text->text_info);
    
    for (i = 0; i < num_lines; i++) {
      switch (text->alignment) {
      case TK_JUSTIFY_LEFT:
        infos[i].origin_x = 0;
        break;
      case TK_JUSTIFY_CENTER:
        infos[i].origin_x = (text->max_width + 1 - infos[i].width)/2;
        break;
      case TK_JUSTIFY_RIGHT:
        infos[i].origin_x = text->max_width + 1 - infos[i].width;
        break;
      }
      infos[i].origin_y = cur_dy;
      cur_dy += font_height + text->spacing;
      /*printf("fixing line %d x : %d, y : %d\n", i, infos[i].origin_x,
        infos[i].origin_y);*/
    }
  } /* ISSET(item->inv_flags, INV_TEXT_LAYOUT) */
    
  text->height = font_height;
  if (text->text_info) {
    unsigned int h, cursor_offset;
    int          cursor_line;
    ZnPoint      origin, box[4];

    num_lines = ZnListSize(text->text_info);
    infos = ZnListArray(text->text_info);
    h = num_lines * font_height + (num_lines-1) * text->spacing;
    text->height = MAX(text->height, h);

    transfo = ComputeTransfoAndOrigin(item, &origin);
    
    text->poly[0].x = origin.x;
    text->poly[0].y = origin.y;
    text->poly[3].x = text->poly[0].x + text->max_width;
    text->poly[3].y = text->poly[0].y + text->height;
    text->poly[1].x = text->poly[0].x;
    text->poly[1].y = text->poly[3].y;
    text->poly[2].x = text->poly[3].x;
    text->poly[2].y = text->poly[0].y;
    ZnTransformPoints(transfo, text->poly, text->poly, 4);       

    /*
     * Add to the bounding box.
     */
    ZnAddPointsToBBox(&item->item_bounding_box, text->poly, 4);

    /*
     * Add the cursor shape to the bbox.
     */
    cursor_line = -1;
    ComputeCursor(item, &cursor_line, &cursor_offset);
    if (cursor_line >= 0) {
      if (num_lines) {
        box[0].x = origin.x + infos[cursor_line].origin_x + cursor_offset -
          wi->text_info.insert_width/2;
        box[0].y = origin.y + infos[cursor_line].origin_y - fm.ascent + 1;
      }
      else {
        box[0].x = origin.x;
        box[0].y = origin.y;
      }
      box[2].x = box[0].x + wi->text_info.insert_width;
      box[2].y = box[0].y + font_height - 1;
      box[1].x = box[2].x;
      box[1].y = box[0].y;
      box[3].x = box[0].x;
      box[3].y = box[2].y;
      ZnTransformPoints(transfo, box, box, 4);
      ZnAddPointsToBBox(&item->item_bounding_box, box, 4);
    }
  }

  /*printf("bbox origin: %g %g corner %g %g\n",
         item->item_bounding_box.orig.x, item->item_bounding_box.orig.y,
         item->item_bounding_box.corner.x, item->item_bounding_box.corner.y);*/
  /*
   * Update connected items.
   */
  SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  TextItem      text = (TextItem) item;
  int           inside = -1;
  ZnBool        first_done = False;
  int           num_lines, i;
  TextLineInfo  lines, lines_ptr;
  Tk_FontMetrics fm;
  int           font_height;
  ZnBBox        line_bbox, *area = ta->area;
  ZnPoint       box[4], p, origin;
  ZnTransfo     inv, *transfo;

  if (!text->text_info || !text->text) {
    return -1;
  }
  
  transfo = ComputeTransfoAndOrigin(item, &origin);
  box[0] = area->orig;
  box[2] = area->corner;
  box[1].x = box[2].x;
  box[1].y = box[0].y;
  box[3].x = box[0].x;
  box[3].y = box[2].y;
  ZnTransfoInvert(transfo, &inv);
  ZnTransformPoints(&inv, box, box, 4);

  lines = (TextLineInfo) ZnListArray(text->text_info);
  num_lines = ZnListSize(text->text_info);
  Tk_GetFontMetrics(text->font, &fm);
  font_height = fm.descent + fm.ascent;
  if (text->spacing > 0) {
    font_height += text->spacing;
  }

  /*printf("text %d, num lines=%d\n", item->id, num_lines);*/
  for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
    ZnResetBBox(&line_bbox);
    p.x = origin.x + lines_ptr->origin_x;
    p.y = origin.y + lines_ptr->origin_y - fm.ascent;
    ZnAddPointToBBox(&line_bbox, p.x, p.y);
    ZnAddPointToBBox(&line_bbox, p.x + lines_ptr->width, p.y + font_height);
    if (!first_done) {
      first_done = True;
      inside = ZnPolygonInBBox(box, 4, &line_bbox, NULL);
      if (inside == 0) {
        return 0;
      }
    }
    else {
      if (ZnPolygonInBBox(box, 4, &line_bbox, NULL) == 0) {
        return 0;
      }
    }
  }

  return inside;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  TextItem      text = (TextItem) item;
  XGCValues     values;
  ZnPoint       pos, box[4], origin;
  ZnTransfo     *transfo;
  Drawable      drw;
  GC            gc;
  XImage        *src_im, *dest_im=NULL;
  unsigned int  dest_im_width=0, dest_im_height=0;
  unsigned int  gc_mask = 0;
  Tk_FontMetrics fm;
  unsigned int  font_height;  
  int           num_lines, i;
  TextLineInfo  lines, lines_ptr;
  ZnTextInfo    *ti = &wi->text_info;
  unsigned int  underline_thickness, underline_pos=0, overstrike_pos=0;
  int           sel_first_line=-1, sel_last_line=-1, cursor_line=-1;
  unsigned int  sel_start_offset=0, sel_stop_offset=0, cursor_offset=0;

  if (!text->text_info/* || !text->text*/) {
    return;
  }

  lines = (TextLineInfo) ZnListArray(text->text_info);
  num_lines = ZnListSize(text->text_info);
  Tk_GetFontMetrics(text->font, &fm);
  font_height = fm.ascent+fm.descent;

  transfo = ComputeTransfoAndOrigin(item, &origin);

  /*
   * Compute the selection and the cursor geometry.
   */
  ComputeCursor(item, &cursor_line, &cursor_offset);
  ComputeSelection(item, &sel_first_line, &sel_last_line,
                   &sel_start_offset, &sel_stop_offset);


  ZnTransformPoint(transfo, &origin, &pos);

  /*printf("sel 1st : %d offset : %d, sel last : %d offset : %d\n",
    sel_first_line, sel_start_offset, sel_last_line, sel_stop_offset);*/
  /*
   * Setup the gc for the selection and fill the selection.
   */
  if ((ti->sel_item == item) && (sel_first_line >= 0)) {
    XPoint xp[4];

    values.foreground = ZnGetGradientPixel(ti->sel_color, 0.0);
    values.fill_style = FillSolid;
    XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCForeground, &values);
    
    if (sel_first_line == sel_last_line) {
      box[0].x = origin.x + 
        lines[sel_first_line].origin_x + sel_start_offset;
      box[0].y = origin.y +
        lines[sel_first_line].origin_y - fm.ascent;
      box[2].x = box[0].x + sel_stop_offset - sel_start_offset;
      box[2].y = box[0].y + font_height;
      box[1].x = box[2].x;
      box[1].y = box[0].y;
      box[3].x = box[0].x;
      box[3].y = box[2].y;
      ZnTransformPoints(transfo, box, box, 4);
      for (i = 0; i < 4; i++) {
        xp[i].x = (short) box[i].x;
        xp[i].y = (short) box[i].y;
      }
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
    }
    else {
      box[0].x = origin.x + 
        lines[sel_first_line].origin_x + sel_start_offset;
      box[0].y = origin.y +
        lines[sel_first_line].origin_y - fm.ascent;
      box[2].x = box[0].x +
        text->max_width-lines[sel_first_line].origin_x-sel_start_offset;
      box[2].y = box[0].y + font_height;
      box[1].x = box[2].x;
      box[1].y = box[0].y;
      box[3].x = box[0].x;
      box[3].y = box[2].y;
      ZnTransformPoints(transfo, box, box, 4);
      for (i = 0; i < 4; i++) {
        xp[i].x = (short) box[i].x;
        xp[i].y = (short) box[i].y;
      }
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
      for (i = sel_first_line+1, lines_ptr = &lines[sel_first_line+1];
           i < sel_last_line; i++, lines_ptr++) {
        box[0].x = origin.x;
        box[0].y = origin.y + lines_ptr->origin_y - fm.ascent;
        box[2].x = box[0].x + text->max_width;
        box[2].y = box[0].y + font_height;
        box[1].x = box[2].x;
        box[1].y = box[0].y;
        box[3].x = box[0].x;
        box[3].y = box[2].y;
        ZnTransformPoints(transfo, box, box, 4);
        for (i = 0; i < 4; i++) {
          xp[i].x = (short) box[i].x;
          xp[i].y = (short) box[i].y;
        }
        XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
      }
      box[0].x = origin.x;
      box[0].y = origin.y + lines[sel_last_line].origin_y - fm.ascent;
      box[2].x = box[0].x + lines[sel_last_line].origin_x + sel_stop_offset;
      box[2].y = box[0].y + font_height;
      box[1].x = box[2].x;
      box[1].y = box[0].y;
      box[3].x = box[0].x;
      box[3].y = box[2].y;
      ZnTransformPoints(transfo, box, box, 4);
      for (i = 0; i < 4; i++) {
        xp[i].x = (short) box[i].x;
        xp[i].y = (short) box[i].y;
      }
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xp, 4, Convex, CoordModeOrigin);
    }
  }

  /*printf("cursor line : %d, cursor offset : %d\n", cursor_line, cursor_offset);*/
  /*
   * Setup the gc for the cursor and draw it.
   */
  if (cursor_line >= 0) {
    values.fill_style = FillSolid;
    values.line_width = ti->insert_width;
    values.foreground = ZnGetGradientPixel(ti->insert_color, 0.0);
    XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle|GCLineWidth, &values);

    box[0].x = origin.x + lines[cursor_line].origin_x + cursor_offset;
    box[0].y = origin.y + lines[cursor_line].origin_y - fm.ascent + 1;
    box[1].x = box[0].x;
    box[1].y = box[0].y + font_height - 1;
    ZnTransformPoints(transfo, box, box, 2);
    XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
              (int) box[0].x, (int) box[0].y, (int) box[1].x, (int) box[1].y);
  }


  /*
   * If the current transform is a pure translation, it is
   * possible to optimize by directly drawing to the X back
   * buffer. Else, we draw in a temporary buffer, get
   * its content as an image, transform the image into another
   * one and use this last image as a mask to draw in the X
   * back buffer.
   */
  if (ZnTransfoIsTranslation(transfo)) {
    drw = wi->draw_buffer;

    gc = wi->gc;
    values.foreground = ZnGetGradientPixel(text->color, 0.0);    
  }
  else {
    dest_im_width = (unsigned int) (item->item_bounding_box.corner.x -
                                    item->item_bounding_box.orig.x + 1);
    dest_im_height = (unsigned int) (item->item_bounding_box.corner.y -
                                     item->item_bounding_box.orig.y + 1);

    drw = Tk_GetPixmap(wi->dpy, wi->draw_buffer,
                       MAX(dest_im_width, text->max_width),
                       MAX(dest_im_height, text->height), 1);
    gc = XCreateGC(wi->dpy, drw, 0, NULL);
    XSetForeground(wi->dpy, gc, 0);
    XFillRectangle(wi->dpy, drw, gc, 0, 0,
                   MAX(dest_im_width, text->max_width),
                   MAX(dest_im_height, text->height));
    dest_im = XGetImage(wi->dpy, drw, 0, 0,
                        MAX(dest_im_width, text->max_width),
                        MAX(dest_im_height, text->height),
                        1, ZPixmap);

    values.foreground = 1;
 
    pos.x = 0;
    pos.y = 0;
  }

  /*
   * Setup the gc to render the text and draw it.
   */
  values.font = Tk_FontId(text->font);
  gc_mask = GCFont | GCForeground;
  if (text->fill_pattern != ZnUnspecifiedImage) {
    values.fill_style = FillStippled;
    values.stipple = ZnImagePixmap(text->fill_pattern, wi->win);
    gc_mask |= GCFillStyle | GCStipple;
  }
  else {
    values.fill_style = FillSolid;
    gc_mask |= GCFillStyle;
  }
  if (ISSET(text->flags, UNDERLINED) || ISSET(text->flags, OVERSTRIKED)) {
    /*
     * These 3 values should be fetched from the font.
     * Currently I don't know how without diving into
     * Tk internals.
     */
    underline_thickness = 2;
    underline_pos = fm.descent/2;
    overstrike_pos = fm.ascent*3/10;
    values.line_style = LineSolid;
    values.line_width = underline_thickness;
    gc_mask |= GCLineStyle | GCLineWidth;
  }
  XChangeGC(wi->dpy, gc, gc_mask, &values);
  for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
    int tmp_x, tmp_y;
    
    tmp_x = (int)(pos.x + lines_ptr->origin_x);
    tmp_y = (int)(pos.y + lines_ptr->origin_y);
    Tk_DrawChars(wi->dpy, drw, gc,
                 text->font, (char *) lines_ptr->start,
                 (int) lines_ptr->num_bytes, tmp_x, tmp_y);
    if (ISSET(text->flags, UNDERLINED)) {
      int y_under = tmp_y + underline_pos;
      
      XDrawLine(wi->dpy, drw, gc,
                tmp_x, y_under, tmp_x + (int) lines_ptr->width, y_under);
    }
    if (ISSET(text->flags, OVERSTRIKED)) {
      int y_over = tmp_y-overstrike_pos;
      
      XDrawLine(wi->dpy, drw, gc,
                tmp_x, y_over, tmp_x + (int) lines_ptr->width, y_over);
    }
  }

  if (dest_im != NULL) {
    src_im = XGetImage(wi->dpy, drw, 0, 0, text->max_width, text->height,
                       1, ZPixmap);

    box[0].x = origin.x;
    box[0].y = origin.y;
    box[3].x = box[0].x + text->max_width;
    box[3].y = box[0].y + text->height;
    box[1].x = box[0].x;
    box[1].y = box[3].y;
    box[2].x = box[3].x;
    box[2].y = box[0].y;
    ZnTransformPoints(transfo, box, box, 4);
    for (i = 0; i < 4; i++) {
      box[i].x -= item->item_bounding_box.orig.x;
      box[i].y -= item->item_bounding_box.orig.y;
      box[i].x = ZnNearestInt(box[i].x);
      box[i].y = ZnNearestInt(box[i].y);
    }

    ZnMapImage(src_im, dest_im, box);

#ifdef PLATFORM_SDL
    XPutImage(wi->dpy, drw, gc, dest_im,
              0, 0, 0, 0, dest_im_width, dest_im_height);
#else
    TkPutImage(NULL, 0, wi->dpy, drw, gc, dest_im,
               0, 0, 0, 0, dest_im_width, dest_im_height);
#endif

    values.foreground = ZnGetGradientPixel(text->color, 0.0);
    values.stipple = drw;
    values.ts_x_origin = (int) item->item_bounding_box.orig.x;
    values.ts_y_origin = (int) item->item_bounding_box.orig.y;
    values.fill_style = FillStippled;
    XChangeGC(wi->dpy, wi->gc,
              GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin|GCForeground,
              &values);
    XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,
                   (int) item->item_bounding_box.orig.x,
                   (int) item->item_bounding_box.orig.y,
                   dest_im_width, dest_im_height);

    XFreeGC(wi->dpy, gc);
    Tk_FreePixmap(wi->dpy, drw);
    XDestroyImage(src_im);
    XDestroyImage(dest_im);
  }
}
  

/*
**********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
Render(ZnItem   item)
{
  ZnWInfo       *wi = item->wi;
  TextItem      text = (TextItem) item;
  TextLineInfo  lines, lines_ptr;
  ZnTextInfo    *ti = &wi->text_info;
  ZnPoint       o, c, origin;
  ZnTransfo     *transfo;
  GLdouble      m[16];
  int           i, num_lines;
  XColor        *color;
  unsigned short alpha;
  Tk_FontMetrics fm;
  int           font_height;  
  int           underline_thickness, underline_pos=0, overstrike_pos=0;
  int           sel_first_line=-1, sel_last_line=-1, cursor_line=-1;
  unsigned int  sel_start_offset=0, sel_stop_offset=0, cursor_offset=0;

  if (!text->text_info) {
    return;
  }
  
#ifdef GL_LIST
  if (!item->gl_list) {
    item->gl_list = glGenLists(1);
    glNewList(item->gl_list, GL_COMPILE);
#endif
    lines = (TextLineInfo) ZnListArray(text->text_info);
    num_lines = ZnListSize(text->text_info);
    Tk_GetFontMetrics(text->font, &fm);
    font_height = fm.ascent+fm.descent;
    
    /*
     * These 3 values should be fetched from the font.
     * Currently I don't know how without diving into
     * Tk internals.
     */
    underline_thickness = 2;
    underline_pos = fm.descent/2;
    overstrike_pos = fm.ascent*3/10;
    
    transfo = ComputeTransfoAndOrigin(item, &origin);
  
    /*
     * Compute the selection and the cursor geometry.
     */
    ComputeCursor(item, &cursor_line, &cursor_offset);
    ComputeSelection(item, &sel_first_line, &sel_last_line,
                     &sel_start_offset, &sel_stop_offset);
  
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glPushMatrix();
    memset(m, 0, sizeof(m));
    m[0] = m[5] = m[15] = 1.0;
    if (transfo) {
      m[0] = transfo->_[0][0]; m[1] = transfo->_[0][1];
      m[4] = transfo->_[1][0]; m[5] = transfo->_[1][1];
      m[12] = ZnNearestInt(transfo->_[2][0]);
      m[13] = ZnNearestInt(transfo->_[2][1]);
    }
    glLoadMatrixd(m);
    glTranslated(origin.x, origin.y, 0.0);
    glPushMatrix();    

    /*
     * Render the selection.
     */
    if ((ti->sel_item == item) && (sel_first_line >= 0)) {
      color = ZnGetGradientColor(ti->sel_color, 0.0, &alpha);
      alpha = ZnComposeAlpha(alpha, wi->alpha);
      glColor4us(color->red, color->green, color->blue, alpha);
      o.x = lines[sel_first_line].origin_x + sel_start_offset;
      o.y = lines[sel_first_line].origin_y - fm.ascent;
      glBegin(GL_QUADS);
      if (sel_first_line == sel_last_line) {
        c.x = o.x + sel_stop_offset - sel_start_offset;
        c.y = o.y + font_height;
        glVertex2d(o.x, o.y);
        glVertex2d(o.x, c.y);
        glVertex2d(c.x, c.y);
        glVertex2d(c.x, o.y);
      }
      else {
        c.x = o.x + (text->max_width - 
                     lines[sel_first_line].origin_x - sel_start_offset);
        c.y = o.y + font_height;
        glVertex2d(o.x, o.y);
        glVertex2d(o.x, c.y);
        glVertex2d(c.x, c.y);
        glVertex2d(c.x, o.y);
        for (i = sel_first_line+1, lines_ptr = &lines[sel_first_line+1];
             i < sel_last_line; i++, lines_ptr++) {
          o.x = 0;
          o.y = lines_ptr->origin_y - fm.ascent;
          c.x = o.x + text->max_width;
          c.y = o.y + font_height;
          glVertex2d(o.x, o.y);
          glVertex2d(o.x, c.y);
          glVertex2d(c.x, c.y);
          glVertex2d(c.x, o.y);
        }
        o.x = 0;
        o.y = lines[sel_last_line].origin_y - fm.ascent;
        c.x = o.x + lines[sel_last_line].origin_x + sel_stop_offset;
        c.y = o.y + font_height;
        glVertex2d(o.x, o.y);
        glVertex2d(o.x, c.y);
        glVertex2d(c.x, c.y);
        glVertex2d(c.x, o.y);
      }
      glEnd();
    }

    /*
     * Render the cursor.
     */
    if (cursor_line >= 0) {
      color = ZnGetGradientColor(ti->insert_color, 0.0, &alpha);
      alpha = ZnComposeAlpha(alpha, wi->alpha);
      glColor4us(color->red, color->green, color->blue, alpha);
      glLineWidth((GLfloat) ti->insert_width);
      
      o.x = lines[cursor_line].origin_x + cursor_offset;
      o.y = lines[cursor_line].origin_y - fm.ascent + 1;
      c.x = o.x;
      c.y = o.y + font_height - 1;

      glBegin(GL_LINES);
      glVertex2d(o.x, o.y);
      glVertex2d(c.x, c.y);
      glEnd();
    }

    /*
     * Render the text.
     */
    glEnable(GL_TEXTURE_2D);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glBindTexture(GL_TEXTURE_2D, ZnTexFontTex(text->tfi));
    color = ZnGetGradientColor(text->color, 0.0, &alpha);
    alpha = ZnComposeAlpha(alpha, wi->alpha);
    glColor4us(color->red, color->green, color->blue, alpha);
    
    for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
      glTranslated(lines_ptr->origin_x, lines_ptr->origin_y, 0.0);

      if (ISSET(text->flags, UNDERLINED) || ISSET(text->flags, OVERSTRIKED)) {
        glLineWidth((GLfloat) underline_thickness);
        glDisable(GL_TEXTURE_2D);
        if (ISSET(text->flags, UNDERLINED)) {
          glBegin(GL_LINES);
          glVertex2d(0, underline_pos);
          glVertex2d(lines_ptr->width, underline_pos);
          glEnd();
        }
        if (ISSET(text->flags, OVERSTRIKED)) {
          glBegin(GL_LINES);
          glVertex2d(0, -overstrike_pos);
          glVertex2d(lines_ptr->width, -overstrike_pos);
          glEnd();
        }
        glEnable(GL_TEXTURE_2D);
      }

      ZnRenderString(text->tfi, (unsigned char *) lines_ptr->start,
                     lines_ptr->num_bytes);
      glPopMatrix();
      glPushMatrix();
    }

    glPopMatrix();
    glPopMatrix();
      
    glDisable(GL_TEXTURE_2D);
#ifdef GL_LIST    
    glEndList();
  }
  
  glCallList(item->gl_list);
#endif
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  TextItem      text = (TextItem) item;
  double        dist = 1.0e40, new_dist;
  int           num_lines, i;
  TextLineInfo  lines, lines_ptr;
  Tk_FontMetrics fm;
  int           font_height;
  ZnPoint       box[4], origin, *p = ps->point;
  ZnTransfo     *transfo;

  if (!text->text_info || !text->text) {
    return dist;
  }
  
  transfo = ComputeTransfoAndOrigin(item, &origin);
  
  lines = ZnListArray(text->text_info);
  num_lines = ZnListSize(text->text_info);
  Tk_GetFontMetrics(text->font, &fm);
  font_height = fm.descent + fm.ascent;
  if (text->spacing > 0) {
    font_height += text->spacing;
  }  

  for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
    box[0].x = origin.x + lines_ptr->origin_x;
    box[0].y = origin.y + lines_ptr->origin_y - fm.ascent;
    box[2].x = box[0].x + lines_ptr->width;
    box[2].y = box[0].y + font_height;
    box[1].x = box[2].x;
    box[1].y = box[0].y;
    box[3].x = box[0].x;
    box[3].y = box[2].y;
    ZnTransformPoints(transfo, box, box, 4);
    new_dist = ZnPolygonToPointDist(box, 4, p);
    dist = MIN(dist, new_dist);
    if (dist <= 0.0) {
      dist = 0.0;
      break;
    }
  }

  return dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ZnWInfo        *wi = item->wi;
  TextItem       text = (TextItem) item;
  Tk_FontMetrics fm;
  TextLineInfo   lines, lines_ptr;
  ZnPoint        origin;
  ZnReal         alignment;
  int            i, num_lines;
  char           path[150];

  lines = (TextLineInfo) ZnListArray(text->text_info);
  num_lines = ZnListSize(text->text_info);

  if (Tk_PostscriptFont(wi->interp, wi->ps_info, text->font) != TCL_OK) {
    return TCL_ERROR;
  }
  if (Tk_PostscriptColor(wi->interp, wi->ps_info,
                         ZnGetGradientColor(text->color, 0.0, NULL)) != TCL_OK) {
    return TCL_ERROR;
  }
  if (text->fill_pattern != ZnUnspecifiedImage) {
    Tcl_AppendResult(wi->interp, "/StippleText {\n    ", NULL);
    Tk_PostscriptStipple(wi->interp, wi->win, wi->ps_info,
                         ZnImagePixmap(text->fill_pattern, wi->win));
    Tcl_AppendResult(wi->interp, "} bind def\n", NULL);
  }

  ComputeTransfoAndOrigin(item, &origin);

  sprintf(path, "/InitialTransform load setmatrix\n"
          "[%.15g %.15g %.15g %.15g %.15g %.15g] concat\n"
          "1 -1 scale\n",
          wi->current_transfo->_[0][0], wi->current_transfo->_[0][1], 
          wi->current_transfo->_[1][0], wi->current_transfo->_[1][1], 
          wi->current_transfo->_[2][0], wi->current_transfo->_[2][1]);
  Tcl_AppendResult(wi->interp, path, NULL);

  sprintf(path, "%.15g %.15g [\n", origin.x, origin.y);
  Tcl_AppendResult(wi->interp, path, NULL);

  /*
   * Emit code to draw the lines.
   */
  for (i = 0, lines_ptr = lines; i < num_lines; i++, lines_ptr++) {
    ZnPostscriptString(wi->interp, lines_ptr->start, lines_ptr->num_bytes);
  }

  switch (text->alignment) {
    default:
    case TK_JUSTIFY_LEFT:
      alignment = 0;
      break;
    case TK_JUSTIFY_CENTER:
      alignment = 0.5;
      break;
    case TK_JUSTIFY_RIGHT:
      alignment = 1;
      break;
  }
  Tk_GetFontMetrics(text->font, &fm);
  /* DrawText should not mess with anchors, they are already accounted for */
  sprintf(path, "] %d %g %g %g %s DrawText\n", fm.linespace, 0.0, 0.0, 
          alignment, (text->fill_pattern == ZnUnspecifiedImage) ? "false" : "true");
  Tcl_AppendResult(wi->interp, path, NULL);

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  TextItem      text = (TextItem) item;

  if (text->num_chars != 0) {
    ZnRectOrigin2Anchor(text->poly, anchor, p);
  }
  else {
    *p = *text->poly;
  }
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  TextItem      text = (TextItem) item;

  ZnTriStrip1(tristrip, text->poly, 4, False);

  return False;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item origin. This doesn't take care of
 *      the possible attachment. The change will be effective at the
 *      end of the attachment.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  TextItem      text = (TextItem) item;
  
  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " texts can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (*num_pts == 0) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 1 point on texts", NULL);
      return TCL_ERROR;
    }
    text->pos = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    *num_pts = 1;
    *pts = &text->pos;
  }
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Index --
 *      Parse a text index and return its value and a
 *      error status (standard Tcl result).
 *
 **********************************************************************************
 */
static int
PointToChar(TextItem    text,
            int         x,
            int         y)
{
  int           i, n, num_lines, dummy, byte_index;
  ZnPoint       p;
  TextLineInfo  ti;
  Tk_FontMetrics fm;
  ZnReal        a, b;

  byte_index = 0;
  if (!text->text_info) {
    return 0;
  }
  
  p.x = x;
  p.y = y;
  a = ZnLineToPointDist(&text->poly[0], &text->poly[2], &p, NULL);
  b = ZnLineToPointDist(&text->poly[0], &text->poly[1], &p, NULL);
  p.x = (text->max_width * b /
         hypot(text->poly[2].x - text->poly[0].x, text->poly[2].y - text->poly[0].y));
  p.y = (text->height * a /
         hypot(text->poly[1].x - text->poly[0].x, text->poly[1].y - text->poly[0].y));
  p.x = ZnNearestInt(p.x);
  p.y = ZnNearestInt(p.y);

  /*
   * Find the text line under point.
   */
  num_lines = ZnListSize(text->text_info);
  ti = ZnListArray(text->text_info);
  Tk_GetFontMetrics(text->font, &fm);
  for (i = 0; i < num_lines; i++, ti++) {
    if (p.y < ti->origin_y + fm.descent) {
      if (p.x < ti->origin_x) {
        /*
         * Point to the left of the current line, returns
         * index of first char.
         */
        byte_index = ti->start - text->text;
        break;
      }
      if (p.x >= (ti->origin_x + ti->width)) {
        /*
         * Point to the right of the current line, returns
         * index past the last char.
         */
        byte_index = ti->start + ti->num_bytes - text->text;
        break;
      }
      n = Tk_MeasureChars(text->font, ti->start, (int) ti->num_bytes,
                          (int) (p.x + 2 - ti->origin_x), TK_PARTIAL_OK,
                          &dummy);
#ifdef PTK_800
      byte_index = (ti->start + n - 1) - text->text;
#else
      byte_index = Tcl_UtfPrev(ti->start + n, ti->start) - text->text;
#endif
      break;
    }
  }
  if (i == num_lines) {
    /*
     * Point below all lines, return the index after
     * the last char in text.
     */
    ti--;
    byte_index = ti->start + ti->num_bytes - text->text;
  }

  return Tcl_NumUtfChars(text->text, byte_index);
}

/*
 * Return a new index from a current index and a
 * move command.
 *
 * 0 end of index line
 * 1 beginning of index line
 * 2 next word or end of word from index
 * 3 previous word or beginning of word from index
 * 4 previous line from index line
 * 5 next line from index line
 *
 */
static int
MoveFromIndex(TextItem     text,
              unsigned int char_index,
              int          move)
{
  unsigned int  num_lines, byte_index, num_bytes=0;
  unsigned int  line_index, line_start=0;
  TextLineInfo  lines, p;
  char          *strp;

  if (!text->text_info || !text->text) {
    return char_index;
  }
  byte_index = Tcl_UtfAtIndex(text->text, (int) char_index)-text->text;
  num_lines = ZnListSize(text->text_info);
  lines = p = ZnListArray(text->text_info);
  for (line_index = 0; line_index < num_lines; line_index++, p++) {
    line_start = p->start - text->text;
    num_bytes = p->num_bytes;
    if (line_start + num_bytes >= byte_index) {
      break;
    }
  }
  if (line_index == num_lines) {
    line_index--;
    p--;
  }

  switch (move) {
  case 0:
    byte_index = line_start + num_bytes;
    goto convert_it;
  case 1:
    byte_index = line_start;
    goto convert_it;
  case 2:
    strp = &text->text[byte_index];
    while ((strp[1] == ' ') || (strp[1] == '\n')) {
      strp++;
    }
    while ((strp[1] != ' ') && (strp[1] != '\n') && strp[1]) {
      strp++;
    }
    byte_index = strp + 1 - text->text;
    goto convert_it;
  case 3:
    strp = &text->text[byte_index];
    while ((strp != text->text) && ((strp[-1] == ' ') || (strp[-1] == '\n'))) {
      strp--;
    }
    while ((strp != text->text) && (strp[-1] != ' ') && (strp[-1] != '\n')) {
      strp--;
    }
    byte_index = strp - text->text;
    goto convert_it;
  case 4:
    if (line_index > 0) {
      byte_index -= line_start;
      p = &lines[line_index-1];
      byte_index = MIN(byte_index, p->num_bytes);
      line_start = p->start - text->text;
      byte_index += line_start;
    }
    goto convert_it;
  case 5:
    if (line_index < num_lines-1) {
      byte_index -= line_start;
      p = &lines[line_index+1];
      byte_index = MIN(byte_index, p->num_bytes);
      line_start = p->start - text->text;
      byte_index += line_start;
    }
  convert_it:
    char_index = Tcl_NumUtfChars(text->text, (int) byte_index);
  default:
    return char_index;
  }
}

static int
Index(ZnItem    item,
      int       field,
      Tcl_Obj   *index_spec,
      int       *index)
{
  TextItem      text = (TextItem) item;
  ZnWInfo       *wi = item->wi;
  ZnTextInfo    *ti = &wi->text_info;
  unsigned int  length;
  int           c, x, y;
  double        tmp;
  char          *end, *p;

  p = Tcl_GetString(index_spec);
  c = p[0];
  length = strlen(p);
  
  if ((c == 'e') && (length > 1) && (strncmp(p, "end", length) == 0)) {
    *index = text->num_chars;
  }
  else if ((c == 'e') && (length > 1) && (strncmp(p, "eol", length) == 0)) {
    *index = MoveFromIndex(text, text->insert_index, 0);
  }
  else if ((c == 'b') && (length > 1) && (strncmp(p, "bol", length) == 0)) {
    *index = MoveFromIndex(text, text->insert_index, 1);
  }
  else if ((c == 'e') && (length > 1) && (strncmp(p, "eow", length) == 0)) {
    *index = MoveFromIndex(text, text->insert_index, 2);
  }
  else if ((c == 'b') && (length > 1) && (strncmp(p, "bow", length) == 0)) {
    *index = MoveFromIndex(text, text->insert_index, 3);
  }
  else if ((c == 'u') && (strncmp(p, "up", length) == 0)) {
    *index = MoveFromIndex(text, text->insert_index, 4);
  }
  else if ((c == 'd') && (strncmp(p, "down", length) == 0)) {
    *index = MoveFromIndex(text, text->insert_index, 5);
  }
  else if ((c == 'i') && (strncmp(p, "insert", length) == 0)) {
    *index = text->insert_index;
  }
  else if ((c == 's') && (strncmp(p, "sel.first", length) == 0) &&
           (length >= 5)) {
    if (ti->sel_item != item) {
      Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
      return TCL_ERROR;
    }
    *index = ti->sel_first;
  }
  else if ((c == 's') && (strncmp(p, "sel.last", length) == 0) &&
           (length >= 5)) {
    if (ti->sel_item != item) {
      Tcl_AppendResult(wi->interp, "selection isn't in item", (char *) NULL);
      return TCL_ERROR;
    }
    /*
     * We return a modified selection end so that it reflect
     * the text index of the last character _not_ the insertion
     * point between the last and the next.
     */
    *index = ti->sel_last-1;
  }
  else if (c == '@') {
    p++;
    tmp = strtod(p, &end);
    if ((end == p) || (*end != ',')) {
      goto badIndex;
    }
    /*x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);*/
    x = (int) tmp;
    p = end+1;
    tmp = strtod(p, &end);
    if ((end == p) || (*end != 0)) {
      goto badIndex;
    }
    /*y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);*/
    y = (int) tmp;
    
    *index = PointToChar(text, x, y);
  }
  else if (Tcl_GetIntFromObj(wi->interp, index_spec, index) == TCL_OK) {
    if (*index < 0){
      *index = 0;
    }
    else if ((unsigned int) *index > text->num_chars) {
      *index = text->num_chars;
    }
  }
  else {
  badIndex:
    Tcl_AppendResult(wi->interp, "bad index \"", p, "\"", (char *) NULL);
    return TCL_ERROR;
  }

  return TCL_OK;  
}


/*
 **********************************************************************************
 *
 * InsertChars --
 *
 **********************************************************************************
 */
static void
InsertChars(ZnItem      item,
            int         field,
            int         *index,
            char        *chars)
{
  TextItem      text = (TextItem) item;
  ZnTextInfo    *ti = &item->wi->text_info;
  unsigned int  num_chars, byte_index, num_bytes = strlen(chars);
  char          *new;

  if (num_bytes == 0) {
    return;
  }
  if (*index < 0) {
    *index = 0;
  }
  if ((unsigned int) *index > text->num_chars) {
    *index = text->num_chars;
  }
  num_chars = Tcl_NumUtfChars(chars, (int) num_bytes);

  if (text->text) {
    byte_index = Tcl_UtfAtIndex(text->text, *index)-text->text;
    new = ZnMalloc(strlen(text->text) + num_bytes + 1);
    memcpy(new, text->text, (size_t) byte_index);
    strcpy(new + byte_index + num_bytes, text->text + byte_index);
    ZnFree(text->text);
  }
  else {
    byte_index = 0;
    new = ZnMalloc(num_bytes + 1);
    new[num_bytes] = 0;
  }
  memcpy(new + byte_index, chars, num_bytes);
  text->text = new;
  text->num_chars += num_chars;
  
  if (text->insert_index >= (unsigned int) *index) {
    text->insert_index += num_chars;
  }
  if (ti->sel_item == item) {
    if (ti->sel_first >= *index) {
      ti->sel_first += num_chars;
    }
    if (ti->sel_last >= *index) {
      ti->sel_last += num_chars;
    }
    if ((ti->anchor_item == item) && (ti->sel_anchor >= *index)) {
      ti->sel_anchor += num_chars;
    }
  }
  
  ZnITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
}


/*
 **********************************************************************************
 *
 * DeleteChars --
 *
 **********************************************************************************
 */
static void
DeleteChars(ZnItem      item,
            int         field,
            int         *first,
            int         *last)
{
  TextItem      text = (TextItem) item;
  int           byte_count, first_offset;
  int           char_count, num_bytes;
  ZnTextInfo    *ti = &item->wi->text_info;
  char          *new;
  
  if (!text->text) {
    return;
  }
  if (*first < 0) {
    *first = 0;
  }
  if (*last >= (int) text->num_chars) {
    *last = text->num_chars-1;
  }
  if (*first > *last) {
    return;
  }
  char_count = *last + 1 - *first;
  first_offset = Tcl_UtfAtIndex(text->text, *first)-text->text;
  byte_count = Tcl_UtfAtIndex(text->text + first_offset, char_count)-
    (text->text+first_offset);
  num_bytes = strlen(text->text);

  if (num_bytes - byte_count) {
    new = (char *) ZnMalloc((unsigned) (num_bytes + 1 - byte_count));
    memcpy(new, text->text, (size_t) first_offset);
    strcpy(new + first_offset, text->text + first_offset + byte_count);
    ZnFree(text->text);
    text->text = new;
    text->num_chars -= char_count;
  }
  else {
    ZnFree(text->text);
    text->text = NULL;
    text->num_chars = 0;
  }

  if (text->insert_index > (unsigned int) *first) {
    text->insert_index -= char_count;
    if (text->insert_index < (unsigned int) *first) {
      text->insert_index = *first;
    }
    else if (*first == 0) {
      text->insert_index = 0;
    }
  }
  if (ti->sel_item == item) {
    if (ti->sel_first > *first) {
      ti->sel_first -= char_count;
      if (ti->sel_first < *first) {
        ti->sel_first = *first;
      }
    }
    if (ti->sel_last >= *first) {
      ti->sel_last -= char_count;
      if (ti->sel_last < *first - 1) {
        ti->sel_last = *first - 1;
      }
    }
    if (ti->sel_first > ti->sel_last) {
      ti->sel_item = ZN_NO_ITEM;
    }
    if ((ti->anchor_item == item) && (ti->sel_anchor > *first)) {
      ti->sel_anchor -= char_count;
      if (ti->sel_anchor < *first) {
        ti->sel_anchor = *first;
      }
    }
  }

  ZnITEM.Invalidate(item, ZN_COORDS_FLAG|ZN_LAYOUT_FLAG);
}


/*
 **********************************************************************************
 *
 * Cursor --
 *
 **********************************************************************************
 */
static void
TextCursor(ZnItem       item,
           int          field,
           int          index)
{
  TextItem      text = (TextItem) item;

  if (index < 0) {
    text->insert_index = 0;
  }
  else if ((unsigned int) index > text->num_chars) {
    text->insert_index = text->num_chars;
  }
  else {
    text->insert_index = index;
  }
}


/*
 **********************************************************************************
 *
 * Selection --
 *
 **********************************************************************************
 */
static int
Selection(ZnItem        item,
          int           field,
          int           offset,
          char          *chars,
          int           max_bytes)
{
  TextItem      text = (TextItem) item;
  ZnWInfo       *wi = item->wi;
  ZnTextInfo    *ti = &wi->text_info;
  int           count;
  char  const   *sel_first, *sel_last;

  if (!text->text) {
    return 0;
  }
  if ((ti->sel_first < 0) ||
      (ti->sel_first > ti->sel_last)) {
    return 0;
  }
  sel_first = Tcl_UtfAtIndex(text->text, ti->sel_first);
  sel_last = Tcl_UtfAtIndex(sel_first, ti->sel_last + 1 - ti->sel_first);
  count = sel_last - sel_first - offset;
  if (count <= 0) {
    return 0;
  }
  if (count > max_bytes) {
    count = max_bytes;
  }
  memcpy(chars, sel_first + offset, (size_t) count);
  chars[count] = 0;
  
  return count;
}


/*
 **********************************************************************************
 *
 * Exported functions struct
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct TEXT_ITEM_CLASS = {
  "text",
  sizeof(TextItemStruct),
  text_attrs,
  0,                    /* num_parts */
  ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
  Tk_Offset(TextItemStruct, pos),
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  GetClipVertices,
  NULL,                 /* GetContours */
  Coords,
  InsertChars,
  DeleteChars,
  TextCursor,
  Index,
  NULL,                 /* Part */
  Selection,
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnText = (ZnItemClassId) &TEXT_ITEM_CLASS;

Added jni/tkzinc/generic/Track.c.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
/*
 * Track.c -- Implementation of Track and WayPoint items.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Types.h"
#include "Track.h"
#include "Draw.h"
#include "Geo.h"
#include "Item.h"
#include "Group.h"
#include "WidgetInfo.h"
#include "Image.h"
#include "tkZinc.h"

#include <ctype.h>
#include <stdlib.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";

/*
 * Define this to enable overlap manager setting
 * the label distance rho.
 */
#undef DP

/*
 * Some default values
*/
#define DEFAULT_MARKER_SIZE             0
#define DEFAULT_LABEL_ANGLE             20
#define DEFAULT_LABEL_DISTANCE          50
#define DEFAULT_LINE_WIDTH              1
#define DEFAULT_LABEL_PREFERRED_ANGLE   0
#define DEFAULT_CONVERGENCE_STYLE       0

#ifdef OM_TECH
#define OMTECHSTUFFLEN 256              /* length of technical buffer for OM purpose */
#endif

#define SPEED_VECTOR_PICKING_THRESHOLD  5       /* In pixels    */

/*
 * Sets a threshold for calculating distance from label_dx, label_dy.
 * Above this threshold value, the module is discarded, label_distance
 * is preferred.
 */
#define LABEL_DISTANCE_THRESHOLD 5 

#define MARKER_FILLED_BIT               1 << 0
#define FILLED_HISTORY_BIT              1 << 1
#define DOT_MIXED_HISTORY_BIT           1 << 2
#define CIRCLE_HISTORY_BIT              1 << 3
#define SV_MARK_BIT                     1 << 4
#define SV_TICKS_BIT                    1 << 5
#define POLAR_BIT                       1 << 6
#define FROZEN_LABEL_BIT                1 << 7
#define LAST_AS_FIRST_BIT               1 << 8
#define HISTORY_VISIBLE_BIT             1 << 9

#define CURRENT_POSITION        -2
#define LEADER                  -3
#define CONNECTION              -4
#define SPEED_VECTOR            -5


/*
**********************************************************************************
*
* Specific Track item record
*
**********************************************************************************
*/
typedef struct {
  ZnPoint       world;  /* world coord of pos    */
  ZnPoint       dev;    /* dev coord of pos      */
  ZnBool        visible;
} HistoryStruct, *History;
  
typedef struct _TrackItemStruct {
  ZnItemStruct  header;
  
  /* Public data */
  unsigned short flags;
  ZnImage       symbol;                 /* item symbol                  */
  ZnGradient    *symbol_color;
  int           label_angle;            /* Label angle from track (degree). */
  ZnDim         label_distance;         /* Label distance from track. */
  ZnDim         label_dx;               /* Label dx/dy from track.      */
  ZnDim         label_dy;
  int           label_preferred_angle;
  int           label_convergence_style;
  Tk_Anchor     label_anchor;
  ZnLeaderAnchors leader_anchors;       /* Spec of the leader attachment */
  ZnGradient    *leader_color;          /* leader color                 */
  ZnLineStyle   leader_style;
  ZnLineShape   leader_shape;
  ZnLineEnd     leader_first_end;
  ZnLineEnd     leader_last_end;
  ZnDim         leader_width;
  ZnDim         marker_size;            /* world size of error circle   */
  ZnGradient    *marker_color;          /* error circle color           */
  ZnLineStyle   marker_style;           /* error circle style           */
  ZnImage       marker_fill_pattern;    /* error circle fill pattern    */
  ZnGradient    *connection_color;      /* connection color             */
  ZnLineStyle   connection_style;
  ZnDim         connection_width;
  ZnGradient    *speed_vector_color;    /* s. v. color                  */
  ZnPoint       pos;                    /* item world coordinates       */
  ZnPoint       speed_vector;           /* s. v. slope in world coord   */
  ZnDim         speed_vector_width;
  ZnGradient    *history_color;
  ZnDim         history_width;
#ifdef OM_TECH
  char          *omtechstuff;
#endif

  /* Private data */
  ZnFieldSetStruct field_set;
  ZnPoint       dev;                    /* device coords of current pos */
  ZnPoint       speed_vector_dev;       /* s. v. end in device coord    */
  ZnDim         marker_size_dev;        /* dev size of error circle     */
  ZnList        history;                /* pos list                     */
  ZnList        leader_points;
} TrackItemStruct, *TrackItem;


static ZnAttrConfig     track_attrs[] = {
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_CATCH_EVENT_BIT, ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-circlehistory", NULL,
    Tk_Offset(TrackItemStruct, flags), CIRCLE_HISTORY_BIT, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ITEM, "-connecteditem", NULL,
    Tk_Offset(TrackItemStruct, header.connected_item), 0,
    ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-connectioncolor", NULL,
    Tk_Offset(TrackItemStruct, connection_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-connectionsensitive", NULL,
    Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CONNECTION),
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-connectionstyle", NULL,
    Tk_Offset(TrackItemStruct, connection_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-connectionwidth", NULL,
    Tk_Offset(TrackItemStruct, connection_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-filledhistory", NULL,
    Tk_Offset(TrackItemStruct, flags), FILLED_HISTORY_BIT, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-filledmarker", NULL,
    Tk_Offset(TrackItemStruct, flags), MARKER_FILLED_BIT, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-frozenlabel", NULL,
    Tk_Offset(TrackItemStruct, flags), FROZEN_LABEL_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-historycolor", NULL,
    Tk_Offset(TrackItemStruct, history_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-historywidth", NULL,
    Tk_Offset(TrackItemStruct, history_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ANCHOR, "-labelanchor", NULL,
    Tk_Offset(TrackItemStruct, label_anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ANGLE, "-labelangle", NULL,
    Tk_Offset(TrackItemStruct, label_angle), 0,
    ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
  { ZN_CONFIG_UINT, "-labelconvergencestyle", NULL,
    Tk_Offset(TrackItemStruct, label_convergence_style), 0, 0, False },
  { ZN_CONFIG_DIM, "-labeldistance", NULL,
    Tk_Offset(TrackItemStruct, label_distance), 0,
    ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
  { ZN_CONFIG_DIM, "-labeldx", NULL,
    Tk_Offset(TrackItemStruct, label_dx), 0,
    ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
  { ZN_CONFIG_DIM, "-labeldy", NULL,
    Tk_Offset(TrackItemStruct, label_dy), 0,
    ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
  { ZN_CONFIG_LABEL_FORMAT, "-labelformat", NULL,
    Tk_Offset(TrackItemStruct, field_set.label_format), 0,
    ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
  { ZN_CONFIG_ANGLE, "-labelpreferredangle", NULL,
    Tk_Offset(TrackItemStruct, label_preferred_angle), 0, 0, False },
  { ZN_CONFIG_BOOL, "-lastasfirst", NULL,
    Tk_Offset(TrackItemStruct, flags), LAST_AS_FIRST_BIT, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LEADER_ANCHORS, "-leaderanchors", NULL,
    Tk_Offset(TrackItemStruct, leader_anchors), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-leadercolor", NULL,
    Tk_Offset(TrackItemStruct, leader_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_END, "-leaderfirstend", NULL,
    Tk_Offset(TrackItemStruct, leader_first_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_END, "-leaderlastend", NULL,
    Tk_Offset(TrackItemStruct, leader_last_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-leadersensitive", NULL,
    Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(LEADER),
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-leaderstyle", NULL,
    Tk_Offset(TrackItemStruct, leader_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_SHAPE, "-leadershape", NULL,
    Tk_Offset(TrackItemStruct, leader_shape), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_DIM, "-leaderwidth", NULL,
    Tk_Offset(TrackItemStruct, leader_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-markercolor", NULL,
    Tk_Offset(TrackItemStruct, marker_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BITMAP, "-markerfillpattern", NULL,
    Tk_Offset(TrackItemStruct, marker_fill_pattern), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-markersize", NULL,
    Tk_Offset(TrackItemStruct, marker_size), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-markerstyle", NULL,
    Tk_Offset(TrackItemStruct, marker_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-mixedhistory", NULL,
    Tk_Offset(TrackItemStruct, flags), DOT_MIXED_HISTORY_BIT, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_UINT, "-numfields", NULL,
    Tk_Offset(TrackItemStruct, field_set.num_fields), 0, 0, True },
  { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(TrackItemStruct, pos), 0,
    ZN_COORDS_FLAG|ZN_MOVED_FLAG, False},
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(TrackItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
  { ZN_CONFIG_POINT, "-speedvector", NULL, Tk_Offset(TrackItemStruct, speed_vector), 0,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-speedvectorcolor", NULL,
    Tk_Offset(TrackItemStruct, speed_vector_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-speedvectormark", NULL,
    Tk_Offset(TrackItemStruct, flags), SV_MARK_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-speedvectorsensitive", NULL,
    Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(SPEED_VECTOR),
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-speedvectorticks", NULL,
    Tk_Offset(TrackItemStruct, flags), SV_TICKS_BIT, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-speedvectorwidth", NULL,
    Tk_Offset(TrackItemStruct, speed_vector_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BITMAP, "-symbol", NULL,
    Tk_Offset(TrackItemStruct, symbol), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-symbolcolor", NULL,
    Tk_Offset(TrackItemStruct, symbol_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-symbolsensitive", NULL,
    Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CURRENT_POSITION),
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(TrackItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  { ZN_CONFIG_BOOL, "-historyvisible", NULL,
    Tk_Offset(TrackItemStruct, flags), HISTORY_VISIBLE_BIT, ZN_COORDS_FLAG, False },
#ifdef OM_TECH
  /* This read only attribut receives reason value transmitted by
     ZnSetLabelAngleFromOm; it can be read by application to
     understand OM internal strategy */ 
  { ZN_CONFIG_STRING, "-omtechstuff", NULL, Tk_Offset(TrackItemStruct, omtechstuff), 0, 0, True }, 
#endif  
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};

static ZnAttrConfig     wp_attrs[] = {
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_CATCH_EVENT_BIT, ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ITEM, "-connecteditem", NULL,
    Tk_Offset(TrackItemStruct, header.connected_item), 0,
    ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-connectioncolor", NULL,
    Tk_Offset(TrackItemStruct, connection_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-connectionsensitive", NULL,
    Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CONNECTION),
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-connectionstyle", NULL,
    Tk_Offset(TrackItemStruct, connection_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-connectionwidth", NULL,
    Tk_Offset(TrackItemStruct, connection_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-filledmarker", NULL,
    Tk_Offset(TrackItemStruct, flags), MARKER_FILLED_BIT, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_ANCHOR, "-labelanchor", NULL,
    Tk_Offset(TrackItemStruct, label_anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ANGLE, "-labelangle", NULL,
    Tk_Offset(TrackItemStruct, label_angle), 0,
    ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
  { ZN_CONFIG_DIM, "-labeldistance", NULL,
    Tk_Offset(TrackItemStruct, label_distance), 0,
    ZN_COORDS_FLAG|ZN_POLAR_FLAG, False },
  { ZN_CONFIG_DIM, "-labeldx", NULL,
    Tk_Offset(TrackItemStruct, label_dx), 0,
    ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
  { ZN_CONFIG_DIM, "-labeldy", NULL,
    Tk_Offset(TrackItemStruct, label_dy), 0,
    ZN_COORDS_FLAG|ZN_CARTESIAN_FLAG, False },
  { ZN_CONFIG_LABEL_FORMAT, "-labelformat", NULL,
    Tk_Offset(TrackItemStruct, field_set.label_format), 0,
    ZN_COORDS_FLAG|ZN_CLFC_FLAG, False },
  { ZN_CONFIG_LEADER_ANCHORS, "-leaderanchors", NULL,
    Tk_Offset(TrackItemStruct, leader_anchors), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-leadercolor", NULL,
    Tk_Offset(TrackItemStruct, leader_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_LINE_END, "-leaderfirstend", NULL,
    Tk_Offset(TrackItemStruct, leader_first_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_END, "-leaderlastend", NULL,
    Tk_Offset(TrackItemStruct, leader_last_end), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-leadersensitive", NULL,
    Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(LEADER),
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_LINE_SHAPE, "-leadershape", NULL,
    Tk_Offset(TrackItemStruct, leader_shape), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-leaderstyle", NULL,
    Tk_Offset(TrackItemStruct, leader_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-leaderwidth", NULL,
    Tk_Offset(TrackItemStruct, leader_width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-markercolor", NULL,
    Tk_Offset(TrackItemStruct, marker_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BITMAP, "-markerfillpattern", NULL,
    Tk_Offset(TrackItemStruct, marker_fill_pattern), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_DIM, "-markersize", NULL,
    Tk_Offset(TrackItemStruct, marker_size), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_LINE_STYLE, "-markerstyle", NULL,
    Tk_Offset(TrackItemStruct, marker_style), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_UINT, "-numfields", NULL,
    Tk_Offset(TrackItemStruct, field_set.num_fields), 0, 0, True },
  { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(TrackItemStruct, pos), 0,
    ZN_COORDS_FLAG, False},
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(TrackItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_SENSITIVE_BIT, ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BITMAP, "-symbol", NULL,
    Tk_Offset(TrackItemStruct, symbol), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_GRADIENT, "-symbolcolor", NULL,
    Tk_Offset(TrackItemStruct, symbol_color), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-symbolsensitive", NULL,
    Tk_Offset(TrackItemStruct, header.part_sensitive), ZnPartToBit(CURRENT_POSITION),
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(TrackItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(TrackItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};



/*
**********************************************************************************
*
* Init --
*
**********************************************************************************
*/
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  TrackItem     track = (TrackItem) item;
  ZnFieldSet    field_set = &track->field_set;
  ZnWInfo       *wi = item->wi;
  int           num_fields;

  /*printf("size of a track = %d\n", sizeof(TrackItemStruct));*/
   
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  SET(item->part_sensitive, ZnPartToBit(CURRENT_POSITION));
  SET(item->part_sensitive, ZnPartToBit(LEADER));
  SET(item->part_sensitive, ZnPartToBit(CONNECTION));
  SET(item->part_sensitive, ZnPartToBit(SPEED_VECTOR));
  track->symbol_color = ZnGetGradientByValue(wi->fore_color);
  track->symbol = ZnGetImageByValue(wi->track_symbol, NULL, NULL);
  track->label_anchor = TK_ANCHOR_CENTER;
  track->label_angle = DEFAULT_LABEL_ANGLE;
  track->label_distance = DEFAULT_LABEL_DISTANCE;
  SET(track->flags, POLAR_BIT);
  CLEAR(track->flags, FROZEN_LABEL_BIT);
#ifdef OM_TECH
  track->omtechstuff = NULL; 
#endif

  track->label_preferred_angle   = DEFAULT_LABEL_PREFERRED_ANGLE;
  track->label_convergence_style = DEFAULT_CONVERGENCE_STYLE ;
 
  track->leader_anchors = NULL;
  track->leader_color = ZnGetGradientByValue(wi->fore_color);
  track->leader_style = ZN_LINE_SIMPLE;
  track->leader_shape = ZN_LINE_STRAIGHT;
  track->leader_width = DEFAULT_LINE_WIDTH;
  track->connection_color = ZnGetGradientByValue(wi->fore_color);
  track->connection_style = ZN_LINE_SIMPLE;
  track->connection_width = DEFAULT_LINE_WIDTH;
  track->marker_color = ZnGetGradientByValue(wi->fore_color);
  track->marker_style = ZN_LINE_SIMPLE;
  track->marker_fill_pattern = ZnUnspecifiedImage;
  track->speed_vector_color = ZnGetGradientByValue(wi->fore_color);
  track->history_color = ZnGetGradientByValue(wi->fore_color);
        track->history_width = 8;
  CLEAR(track->flags, MARKER_FILLED_BIT);
  SET(track->flags, FILLED_HISTORY_BIT);
  CLEAR(track->flags, DOT_MIXED_HISTORY_BIT);
  CLEAR(track->flags, CIRCLE_HISTORY_BIT);
  CLEAR(track->flags, LAST_AS_FIRST_BIT);
  CLEAR(track->flags, SV_MARK_BIT);
  CLEAR(track->flags, SV_TICKS_BIT);
  
  if (item->class == ZnTrack) {
    item->priority = 1;
    SET(track->flags, HISTORY_VISIBLE_BIT);
    track->marker_size = DEFAULT_MARKER_SIZE;
    track->speed_vector.x = 0;
    track->speed_vector.y = 0;
    track->speed_vector_width = DEFAULT_LINE_WIDTH;
  }
  else {
    item->priority = 1;
    CLEAR(track->flags, HISTORY_VISIBLE_BIT);
    track->marker_size = 0;
    track->speed_vector.x = 0.0;
    track->speed_vector.y = 10.0;
  }
  field_set->item = item;
  field_set->label_format = NULL;
  /*
   * Then try to see if some fields are needed.
   */
  if ((*argc > 0) && (Tcl_GetString((*args)[0])[0] != '-') &&
      (Tcl_GetIntFromObj(wi->interp, (*args)[0], &num_fields) != TCL_ERROR)) {
    field_set->num_fields = num_fields;
    *args += 1;
    *argc -= 1;
    ZnFIELD.InitFields(field_set);
  }
  else {
    Tcl_AppendResult(wi->interp, " number of fields expected", NULL);
    return TCL_ERROR;
  }
  
  track->pos.x = 0;
  track->pos.y = 0;
  track->field_set.label_pos.x = 0;
  track->field_set.label_pos.y = 0;
  track->leader_first_end = NULL;
  track->leader_last_end = NULL;

  track->history = NULL;
  track->dev.x = 0;
  track->dev.y = 0;
  track->speed_vector_dev.x = 0;
  track->speed_vector_dev.y = 0;
  track->marker_size_dev = 0;
  track->leader_points = NULL;

  return TCL_OK;
}


/*
**********************************************************************************
*
* Clone --
*
**********************************************************************************
*/
static void
Clone(ZnItem    item)
{
  TrackItem     track = (TrackItem) item;
#ifdef OM_TECH
  char          *omtechstuffclone;
#endif

  if (track->history) {
    track->history = ZnListDuplicate(track->history);
  }
  track->dev.x = 0;
  track->dev.y = 0;
  track->speed_vector_dev.x = 0;
  track->speed_vector_dev.y = 0;
  track->marker_size_dev = 0;
  if (track->leader_points) {
    track->leader_points = ZnListDuplicate(track->leader_points);
  }
  if (track->leader_first_end) {
    ZnLineEndDuplicate(track->leader_first_end);
  }
  if (track->leader_last_end) {
    ZnLineEndDuplicate(track->leader_last_end);
  }
  
  ZnFIELD.CloneFields(&track->field_set);
  track->field_set.item = item;

#ifdef OM_TECH
  if (track->omtechstuff) {
    omtechstuffclone = ZnMalloc( (OMTECHSTUFFLEN + 1) * sizeof(char));
    strcpy(omtechstuffclone, track->omtechstuff);
    track->omtechstuff = omtechstuffclone;
  }
#endif

  /*
   * We get all shared resources, colors bitmaps.
   */
  track->symbol_color = ZnGetGradientByValue(track->symbol_color);
  track->leader_color = ZnGetGradientByValue(track->leader_color);
  track->connection_color = ZnGetGradientByValue(track->connection_color);
  track->marker_color = ZnGetGradientByValue(track->marker_color);
  track->speed_vector_color = ZnGetGradientByValue(track->speed_vector_color);
  track->history_color = ZnGetGradientByValue(track->history_color);
  if (track->symbol != ZnUnspecifiedImage) {
    track->symbol = ZnGetImageByValue(track->symbol, NULL, NULL);
  }
  if (track->marker_fill_pattern != ZnUnspecifiedImage) {
    track->marker_fill_pattern = ZnGetImageByValue(track->marker_fill_pattern, NULL, NULL);
  }
}


/*
**********************************************************************************
*
* Destroy --
*
**********************************************************************************
*/
static void
Destroy(ZnItem  item)
{
  TrackItem     track   = (TrackItem) item;

  if (track->leader_points) {
    ZnListFree(track->leader_points);
  }
  if (track->leader_first_end) {
    ZnLineEndDelete(track->leader_first_end);
  }
  if (track->leader_last_end) {
    ZnLineEndDelete(track->leader_last_end);
  }

  if (track->history) {
    ZnListFree(track->history);
  }

#ifdef OM_TECH
  if (track->omtechstuff) {
    ZnFree(track->omtechstuff);
  }
#endif
  
  /*
   * Release shared resources.
   */
  ZnFreeGradient(track->symbol_color);
  ZnFreeGradient(track->leader_color);
  ZnFreeGradient(track->connection_color);
  ZnFreeGradient(track->marker_color);
  ZnFreeGradient(track->speed_vector_color);
  ZnFreeGradient(track->history_color);
  if (track->symbol != ZnUnspecifiedImage) {
    ZnFreeImage(track->symbol, NULL, NULL);
    track->symbol = ZnUnspecifiedImage;
  }
  if (track->marker_fill_pattern != ZnUnspecifiedImage) {
    ZnFreeImage(track->marker_fill_pattern, NULL, NULL);
    track->marker_fill_pattern = ZnUnspecifiedImage;
  }

  ZnFIELD.FreeFields(&track->field_set);
}


/*
**********************************************************************************
*
* Configure --
*
**********************************************************************************
*/
static void
AddToHistory(TrackItem  track,
             ZnPoint    old_pos)
{
  ZnWInfo       *wi = ((ZnItem) track)->wi;
  
  if (track->history) {
    HistoryStruct       hist;
    
    hist.world = old_pos;
    hist.dev = track->dev;
    hist.visible = True;
    ZnListAdd(track->history, &hist, ZnListHead);
    ZnListTruncate(track->history, wi->track_managed_history_size);
  }
  else {
    /* We do not shift the first time we move as the preceding position
     * is not valid. */
    /*printf("creating history\n");*/
    track->history = ZnListNew(wi->track_managed_history_size+1,
                               sizeof(HistoryStruct));
  }
}

static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  TrackItem     track = (TrackItem) item;
  ZnWInfo       *wi = item->wi;
  ZnItem        old_connected;
  ZnPoint       old_pos;
  
  old_pos = track->pos;
  old_connected = item->connected_item;
  
  if (ZnConfigureAttributes(wi, item, item, track_attrs, argc, argv, flags) == TCL_ERROR) {
    item->connected_item = old_connected;
    return TCL_ERROR;
  }
  
  if (track->label_angle < 0) {
    track->label_angle = 360 + track->label_angle;
  }

  /*
   * Adapt to the new label locating system.
   */
  if (ISSET(*flags, ZN_POLAR_FLAG)) {
    SET(track->flags, POLAR_BIT);
    ZnGroupSetCallOm(item->parent, True);
  }
  else if (ISSET(*flags, ZN_CARTESIAN_FLAG)) {
    CLEAR(track->flags, POLAR_BIT);
    ZnGroupSetCallOm(item->parent, True);
  }
  
  if (ISSET(*flags, ZN_ITEM_FLAG)) {
    /*
     * If the new connected item is not appropriate back up
     * to the old one.
     */
    if ((item->connected_item == ZN_NO_ITEM) ||
        (((item->connected_item->class == ZnTrack) ||
          (item->connected_item->class == ZnWayPoint)) &&
         (item->parent == item->connected_item->parent))) {
      ZnITEM.UpdateItemDependency(item, old_connected);
    }
    else {
      item->connected_item = old_connected;
    }
  }
  
  if (ISSET(*flags, ZN_VIS_FLAG)) {
    /* Record the change to trigger the overlap manager latter */
    if ((item->class == ZnTrack) && ISSET(item->flags, ZN_VISIBLE_BIT)) {
      ZnGroupSetCallOm(item->parent, True);
    }
  }
  
  /* If the current position has changed, shift the past pos. */
  if (ISSET(*flags, ZN_MOVED_FLAG)) {
    if (item->class == ZnTrack) {
      AddToHistory(track, old_pos);
      ZnGroupSetCallOm(item->parent, True);
    }
  }

  return TCL_OK;
}
  
  
/*
**********************************************************************************
*
* Query --
*
**********************************************************************************
*/
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, track_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}


static void
AdjustLabelDistance(TrackItem  track,
                    ZnTransfo  *current_t,
                    ZnReal     theta,      // Angle to adjust for
                    ZnDim      bb_width,
                    ZnDim      bb_height,
                    ZnPoint    *label_pos,
                    ZnReal     *label_dx,
                    ZnReal     *label_dy) 
{
  ZnReal  rho, rotation, dist;
  int     it;
  ZnBBox  bbox;

  rho = track->label_distance;
  /*
   * Compute heading after applying the transform.
   */
  ZnTransfoDecompose(current_t, NULL, NULL, &rotation, NULL);
  /*printf("rotation=%g, heading=%g, angle=%d\n", rotation,
    ZnProjectionToAngle(track->speed_vector.x, track->speed_vector.y),
    track->label_angle);*/
  rotation = ZnProjectionToAngle(track->speed_vector.x, track->speed_vector.y)-rotation;
  /*
   * Adjust the distance to match the requested label_distance
   * whatever the label angle.
   */
  it = 0;
  while (1) {
    ZnPointPolarToCartesian(rotation, rho, theta, label_dx, label_dy);
    label_pos->x = track->dev.x + *label_dx;
    label_pos->y = track->dev.y - *label_dy;
    ZnAnchor2Origin(label_pos, bb_width, bb_height, track->label_anchor, label_pos);
    ZnResetBBox(&bbox);
    ZnAddPointToBBox(&bbox, label_pos->x, label_pos->y);
    ZnAddPointToBBox(&bbox, label_pos->x + bb_width, label_pos->y + bb_height);
    dist = ZnRectangleToPointDist(&bbox, &track->dev);
    dist = track->label_distance - dist;
    if (ABS(dist) < 1.0 || it > 5) {
      break;
    }
    it++;
    rho += dist;
  }
}

/*
**********************************************************************************
*
* ComputeCoordinates --
*
**********************************************************************************
*/
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  TrackItem     track = (TrackItem) item;
  ZnFieldSet    field_set = &track->field_set;
  ZnItem        c_item;
  History       hist;
  ZnPoint       old_label_pos, old_pos, p, xp;
  ZnDim         old_label_width, old_label_height;
  ZnReal        rotation;
  ZnBBox        bbox;
  ZnPoint       *points;
  unsigned int  num_points, num_acc_pos, i;
  int           alignment, w_int, h_int;
  ZnReal        w2=0.0, h2=0.0, w=0.0;
  
  ZnResetBBox(&item->item_bounding_box);
  old_label_pos = field_set->label_pos;
  old_label_width = field_set->label_width;
  old_label_height = field_set->label_height;

  old_pos = track->dev;

  ZnTransformPoint(wi->current_transfo, &track->pos, &track->dev);
  track->dev.x = ZnNearestInt(track->dev.x);
  track->dev.y = ZnNearestInt(track->dev.y);
  /*printf("track pos %g %g --> %g %g\n", track->pos.x, track->pos.y, track->dev.x, track->dev.y);*/
  if (track->symbol != ZnUnspecifiedImage) {
    ZnSizeOfImage(track->symbol, &w_int, &h_int);
    /*printf("taille symbole %d %d\n", w, h);*/
    w2 = (w_int+1.0)/2.0;
    h2 = (h_int+1.0)/2.0;
    bbox.orig.x = track->dev.x - w2;
    bbox.orig.y = track->dev.y - h2;
    bbox.corner.x = track->dev.x + w2;
    bbox.corner.y = track->dev.y + h2;
    
    ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
  }
  
  /* Here we approximate the past position sizes to the size
     of the current position. They are actually smaller but who
     care :-). In fact it is even worse as we use the overall
     information from the symbol font.
  */
  if ((item->class == ZnTrack) && track->history) {
    unsigned int visible_history_size;
    /*
     * Trunc the visible history to the managed size.
     */
    ZnListTruncate(track->history, wi->track_managed_history_size);
    visible_history_size = (ISSET(track->flags, HISTORY_VISIBLE_BIT) ?
                            wi->track_visible_history_size : 0);

    ZnResetBBox(&bbox);
    w2 = (track->history_width+1.0)/2.0;
    num_acc_pos = ZnListSize(track->history);
    hist = ZnListArray(track->history);
    for (i = 0; i < num_acc_pos; i++) {
      ZnTransformPoint(wi->current_transfo, &hist[i].world, &hist[i].dev);
      if ((i < visible_history_size) && (hist[i].visible)) {
        bbox.orig.x = hist[i].dev.x - w2;
        bbox.orig.y = hist[i].dev.y - w2;
        bbox.corner.x = hist[i].dev.x + w2;
        bbox.corner.y = hist[i].dev.y + w2;
        ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
      }
    }
  }

  /*
   * Compute the speed vector end.
   */
  if (item->class == ZnTrack) {
    p.x = track->pos.x + track->speed_vector.x * wi->speed_vector_length;
    p.y = track->pos.y + track->speed_vector.y * wi->speed_vector_length;
    ZnTransformPoint(wi->current_transfo, &p, &track->speed_vector_dev);
    track->speed_vector_dev.x = ZnNearestInt(track->speed_vector_dev.x);
    track->speed_vector_dev.y = ZnNearestInt(track->speed_vector_dev.y);
    if (ISSET(track->flags, SV_MARK_BIT)) {
      w = track->speed_vector_width + 1.0;
      ZnAddPointToBBox(&item->item_bounding_box,
                       track->speed_vector_dev.x - w,
                       track->speed_vector_dev.y - w);
      ZnAddPointToBBox(&item->item_bounding_box,
                       track->speed_vector_dev.x + w,
                       track->speed_vector_dev.y + w);      
    }
    else {
      ZnAddPointToBBox(&item->item_bounding_box, track->speed_vector_dev.x,
                       track->speed_vector_dev.y);
    }
  }
  
  /*
   * Take care of the connection between items.
   */
  c_item = item->connected_item;
  if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0.0)) {
    w2 = track->connection_width/2.0;
    //printf("%d connected to %d, %g %g and %g %g\n", c_item->id, item->id,
    //       ((TrackItem)c_item)->dev.x, ((TrackItem)c_item)->dev.y,
    //       track->dev.x, track->dev.y);
    ZnAddPointToBBox(&item->item_bounding_box, track->dev.x-w2, track->dev.y-w2);
    ZnAddPointToBBox(&item->item_bounding_box, ((TrackItem)c_item)->dev.x+w2,
                     ((TrackItem)c_item)->dev.y+w2);
  }

  /*
   * Compute the size of the circular marker.
   */
  p.x = track->pos.x + track->marker_size;
  p.y = track->pos.y;
  ZnTransformPoint(wi->current_transfo, &p, &xp);
  xp.x = xp.x - track->dev.x;
  xp.y = xp.y - track->dev.y;
  track->marker_size_dev = sqrt(xp.x*xp.x + xp.y*xp.y);
  track->marker_size_dev = ZnNearestInt(track->marker_size_dev);
  if (track->marker_size_dev > PRECISION_LIMIT) {
    ZnAddPointToBBox(&item->item_bounding_box,
                     track->dev.x - (ZnPos) track->marker_size_dev,
                     track->dev.y - (ZnPos) track->marker_size_dev);
    ZnAddPointToBBox(&item->item_bounding_box,
                     track->dev.x + (ZnPos) track->marker_size_dev,
                     track->dev.y + (ZnPos) track->marker_size_dev);
  } 
 
  /* Compute the new label bounding box. */
  if (field_set->label_format && field_set->num_fields) {
    ZnDim   bb_width, bb_height;
    ZnReal  theta, dist;
    ZnPoint leader_end;

    ZnFIELD.GetLabelBBox(field_set, &bb_width, &bb_height);
    /*
     * Compute the label position.
     */
    if (ISSET(track->flags, POLAR_BIT)) {
      /*
       * Update label_dx, label_dy from label_distance, label_angle
       */
      AdjustLabelDistance(track, wi->current_transfo, track->label_angle,
                          bb_width, bb_height, &field_set->label_pos,
                          &track->label_dx, &track->label_dy);
    }
    else {
      /*
       * Update label_angle following the change in label_dx, label_dy.
       * label_distance is not updated.
       */
      ZnTransfoDecompose(wi->current_transfo, NULL, NULL, &rotation, NULL);
      rotation = ZnProjectionToAngle(track->speed_vector.x, track->speed_vector.y) - rotation;
      ZnPointCartesianToPolar(rotation, &dist, &theta, track->label_dx, track->label_dy); 
      track->label_angle = (int) theta;  
    
      field_set->label_pos.x = track->dev.x + track->label_dx;
      field_set->label_pos.y = track->dev.y - track->label_dy;
      ZnAnchor2Origin(&field_set->label_pos, bb_width, bb_height,
                      track->label_anchor, &field_set->label_pos);
    }
    field_set->label_pos.x = ZnNearestInt(field_set->label_pos.x);
    field_set->label_pos.y = ZnNearestInt(field_set->label_pos.y);

    /*
     * Need to compensate for GL thick lines
     */
#ifdef GL
#define CORR 1
#else
#define CORR 0
#endif
    ZnAddPointToBBox(&item->item_bounding_box, field_set->label_pos.x - CORR, field_set->label_pos.y - CORR);
    ZnAddPointToBBox(&item->item_bounding_box,
                     field_set->label_pos.x + (ZnPos) bb_width + CORR,
                     field_set->label_pos.y + (ZnPos) bb_height + CORR);
#undef CORR

    /*
     * Process the leader.
     */
    if (track->leader_width > 0) {
      int       left_x, left_y, right_x, right_y;
      ZnPoint   end_points[ZN_LINE_END_POINTS];
      
      /*
       * Compute the actual leader end in the label.
       */
      if (track->leader_anchors) {
        left_x = track->leader_anchors->left_x;
        right_x = track->leader_anchors->right_x;
        left_y = track->leader_anchors->left_y;
        right_y = track->leader_anchors->right_y;
      }
      else {
        left_x = right_x = left_y = right_y = 50;
      }
      if (track->label_angle >= 270 || track->label_angle < 90) {
        if (track->leader_anchors && (left_y < 0)) {
          ZnFIELD.GetFieldBBox(field_set, (unsigned int) left_x, &bbox);
          leader_end.x = bbox.orig.x;
          leader_end.y = bbox.corner.y;
        }
        else {
          leader_end.x = field_set->label_pos.x + left_x*bb_width/100;
          leader_end.y = field_set->label_pos.y + left_y*bb_height/100;
        }
        alignment = ZN_AA_LEFT;
      }
      else {
        if (track->leader_anchors && (right_y < 0)) {
          ZnFIELD.GetFieldBBox(field_set, (unsigned int) right_x, &bbox);
          leader_end.x = bbox.corner.x;
          leader_end.y = bbox.corner.y;
        }
        else {
          leader_end.x = field_set->label_pos.x + right_x*bb_width/100;
          leader_end.y = field_set->label_pos.y + right_y*bb_height/100;
        }
        alignment = ZN_AA_RIGHT;
      }
      
      ZnFIELD.SetFieldsAutoAlign(field_set, alignment);
      
      /* Clip the leader on the label's fields */
      ZnFIELD.LeaderToLabel(field_set, &track->dev, &leader_end);
      
      /* Setup leader shape points */
      if (!track->leader_points) {
        track->leader_points = ZnListNew(ZN_LINE_SHAPE_POINTS, sizeof(ZnPoint));
      }
      ZnLineShapePoints(&track->dev, &leader_end, track->leader_width,
                        track->leader_shape, &bbox, track->leader_points);
      ZnAddBBoxToBBox(&item->item_bounding_box, &bbox);
      points = (ZnPoint *) ZnListArray(track->leader_points);
      num_points = ZnListSize(track->leader_points);
      
      /* Setup leader ends */
      if (track->leader_first_end != NULL) {
        ZnGetLineEnd(&points[0], &points[1], track->leader_width,
                     CapRound, track->leader_first_end, end_points);
        ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
      }
      if (track->leader_last_end != NULL) {
        ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
                     CapRound, track->leader_last_end, end_points);
        ZnAddPointsToBBox(&item->item_bounding_box, end_points, ZN_LINE_END_POINTS);
      }
    }
  }
  
  /* Update connected items. */
  if ((old_label_pos.x != field_set->label_pos.x) ||
      (old_label_pos.y != field_set->label_pos.y) ||
      (old_label_width != field_set->label_width) ||
      (old_label_height != field_set->label_height) ||
      (old_pos.x != track->dev.x) ||
      (old_pos.y != track->dev.y)) {
    /* Update connected items */
    SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
  }
}


/*
**********************************************************************************
*
* ToArea --
*       Tell if the object is entirely outside (-1),
*       entirely inside (1) or in between (0).
*
**********************************************************************************
*/
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  TrackItem     track = (TrackItem) item;
  int           inside;
  int           width, height;
  ZnDim         lwidth, lheight;
  ZnBBox        bbox, *area = ta->area;
  ZnPoint       pts[2];

  /*
   * Try the current position.
   */
  ZnResetBBox(&bbox);
  if (track->symbol != ZnUnspecifiedImage) {
    ZnSizeOfImage(track->symbol, &width, &height);
    bbox.orig.x = track->dev.x-(width+1)/2;
    bbox.orig.y = track->dev.y-(height+1)/2;
    bbox.corner.x = bbox.orig.x + width;
    bbox.corner.y = bbox.orig.y + height;
  }
  inside = ZnBBoxInBBox(&bbox, area);
  if (inside == 0) {
    /*printf("track pos\n");*/    
    return 0;
  }
  
  /*
   * Try the fields.
   */
  ZnFIELD.GetLabelBBox(&track->field_set, &lwidth, &lheight);
  if ((lwidth > 0.0) && (lheight > 0.0)) {
    if (ZnFIELD.FieldsToArea(&track->field_set, area) != inside) {
      return 0;
    }
  }
  
  /*
   * Try the leader.
   */
  if (track->field_set.label_format && (track->leader_width > 0)) {
    ZnPoint       end_points[ZN_LINE_END_POINTS];
    ZnPoint       *points;
    unsigned int  num_points;

    points = (ZnPoint *) ZnListArray(track->leader_points);
    num_points = ZnListSize(track->leader_points);
    lwidth = track->leader_width > 1 ? track->leader_width : 0;
    if (ZnPolylineInBBox(points, num_points, lwidth,
                         CapRound, JoinRound, area) != inside) {
      /*printf("track leader\n");*/
      return 0;
    }
    if (track->leader_first_end != NULL) {
      ZnGetLineEnd(&points[0], &points[1], track->leader_width,
                   CapRound, track->leader_first_end, end_points);
      if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != inside) {
        /*printf("track leader\n");*/
        return 0;
      }
    }
    if (track->leader_last_end != NULL) {
      ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
                   CapRound, track->leader_last_end, end_points);
      if (ZnPolygonInBBox(end_points, ZN_LINE_END_POINTS, area, NULL) != inside) {
        /*printf("track leader\n");*/
        return 0;
      }
    }
  }

  /*
   * Try the speed vector.
   */
  if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
    pts[0] = track->dev;
    pts[1] = track->speed_vector_dev;
    lwidth = track->speed_vector_width > 1 ? track->speed_vector_width : 0;
    if (ZnPolylineInBBox(pts, 2, lwidth, CapRound, JoinRound, area) != inside) {
      /*printf("track speed vector\n");*/
      return 0;
    }
  }

  /*
   * Try the connection.
   */
  if ((item->connected_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
    pts[0] = track->dev;
    pts[1] = ((TrackItem) item->connected_item)->dev;
    lwidth = track->connection_width > 1 ? track->connection_width : 0;
    if (ZnPolylineInBBox(pts, 2, lwidth, CapRound, JoinRound, area) != inside) {
      /*printf("track connection\n");*/
      return 0;
    }
  }

  return inside;
}


/*
**********************************************************************************
*
* Draw --
*
**********************************************************************************
*/
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  TrackItem     track = (TrackItem) item;
  ZnItem        c_item;
  XGCValues     values;
  History       hist;
  unsigned int  h_side_size, side_size, width=0, height=0;
  unsigned int  i, nb_hist, num_acc_pos;
  int           x, y;

  /* Draw the marker */
  if (track->marker_size_dev != 0) {
    ZnSetLineStyle(wi, track->marker_style);
    values.foreground = ZnGetGradientPixel(track->marker_color, 0.0);
    values.line_width = 1;
    if (ISSET(track->flags, MARKER_FILLED_BIT)) {
      if (track->marker_fill_pattern == ZnUnspecifiedImage) {
        /* Fill solid */
        values.fill_style = FillSolid;
        XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      }
      else {
        /* Fill stippled */
        values.fill_style = FillStippled;
        values.stipple = ZnImagePixmap(track->marker_fill_pattern, wi->win);
        XChangeGC(wi->dpy, wi->gc,
                  GCFillStyle | GCStipple | GCLineWidth | GCForeground, &values);
      }
      XFillArc(wi->dpy, wi->draw_buffer, wi->gc,
               (int) (track->dev.x - (ZnPos) track->marker_size_dev),
               (int) (track->dev.y - (ZnPos) track->marker_size_dev),
               (unsigned int) track->marker_size_dev * 2,
               (unsigned int) track->marker_size_dev * 2,
               0, 360 * 64);
    }
    else {
      values.fill_style = FillSolid;
      XChangeGC(wi->dpy, wi->gc, GCFillStyle | GCLineWidth | GCForeground, &values);
      XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,
               (int) (track->dev.x - (ZnPos) track->marker_size_dev),
               (int) (track->dev.y - (ZnPos) track->marker_size_dev),
               (unsigned int) (track->marker_size_dev * 2),
               (unsigned int) (track->marker_size_dev * 2),
               0, 360 * 64);
    }
  }
  
  /*
   * Draw the connection.
   */
  c_item = item->connected_item;
  if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
    ZnPoint     pts[2];
    
    pts[0] = track->dev;
    pts[1] = ((TrackItem) item->connected_item)->dev;
    ZnDrawLineShape(wi, pts, 2, track->connection_style,
                    ZnGetGradientPixel(track->connection_color, 0.0),
                    track->connection_width, ZN_LINE_STRAIGHT);
  }

  /*
   * Draw the speed vector.
   */
  if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
    values.foreground = ZnGetGradientPixel(track->speed_vector_color, 0.0);
    values.line_width = (int) track->speed_vector_width;
    values.line_style = LineSolid;
    values.fill_style = FillSolid;
    XChangeGC(wi->dpy, wi->gc,
              GCForeground | GCLineWidth | GCLineStyle | GCFillStyle, &values);
    XDrawLine(wi->dpy, wi->draw_buffer, wi->gc,
              (int) track->dev.x,
              (int) track->dev.y,
              (int) track->speed_vector_dev.x,
              (int) track->speed_vector_dev.y);
  }
  
  /*
   * Draw the leader.
   */
  if (track->field_set.label_format && (track->leader_width > 0)) {
    ZnPoint      end_points[ZN_LINE_END_POINTS];
    XPoint       xpoints[ZN_LINE_END_POINTS];
    ZnPoint      *points;
    unsigned int num_points;

    points = (ZnPoint *) ZnListArray(track->leader_points);
    num_points = ZnListSize(track->leader_points);
    ZnDrawLineShape(wi, points, num_points, track->leader_style,
                    ZnGetGradientPixel(track->leader_color, 0.0),
                    track->leader_width, track->leader_shape);
    if (track->leader_first_end != NULL) {
      ZnGetLineEnd(&points[0], &points[1], track->leader_width,
                   CapRound, track->leader_first_end, end_points);
      for (i = 0; i < ZN_LINE_END_POINTS; i++) {
        xpoints[i].x = (short) end_points[i].x;
        xpoints[i].y = (short) end_points[i].y;
      }
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, ZN_LINE_END_POINTS,
                   Nonconvex, CoordModeOrigin);
    }
    if (track->leader_last_end != NULL) {
      ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
                   CapRound, track->leader_last_end, end_points);
      for (i = 0; i < ZN_LINE_END_POINTS; i++) {
        xpoints[i].x = (short) end_points[i].x;
        xpoints[i].y = (short) end_points[i].y;
      }
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, ZN_LINE_END_POINTS,
                   Nonconvex, CoordModeOrigin);
    }
  }
  
  if (track->symbol != ZnUnspecifiedImage) {
    ZnSizeOfImage(track->symbol, (int *) &width, (int *) &height);
  }
  
  /*
   * Draw the history, current pos excepted.
   */
  if ((item->class == ZnTrack) && track->history) {
    unsigned int visible_history_size;

    visible_history_size = (ISSET(track->flags, HISTORY_VISIBLE_BIT) ?
                            wi->track_visible_history_size : 0);

    values.foreground = ZnGetGradientPixel(track->history_color, 0.0);
    values.fill_style = FillSolid;
    XChangeGC(wi->dpy, wi->gc, GCForeground|GCFillStyle, &values);  
    if (ISCLEAR(track->flags, FILLED_HISTORY_BIT)) {
      values.line_width = 1;
      values.line_style = LineSolid;
      XChangeGC(wi->dpy, wi->gc, GCLineWidth | GCLineStyle, &values);
    }
    num_acc_pos = MIN(visible_history_size, ZnListSize(track->history));
    hist = ZnListArray(track->history);
    side_size = (int) track->history_width;

    for (i = 0, nb_hist = 0; i < num_acc_pos; i++) {
      if (ISSET(track->flags, LAST_AS_FIRST_BIT) &&
          (i == visible_history_size-1)) {
        values.foreground = ZnGetGradientPixel(track->symbol_color, 0.0);
        XChangeGC(wi->dpy, wi->gc, GCForeground, &values);
      }
      side_size--;
      side_size = MAX(1, side_size);
      h_side_size = (side_size+1)/2;
      if (hist[i].visible) {
        if (ISSET(track->flags, DOT_MIXED_HISTORY_BIT) && !(nb_hist++ % 2)) {
          x = (int) hist[i].dev.x;
          y = (int) hist[i].dev.y;
          /* Draw a point (portability layer doesn't define a XDrawPoint) */
          XDrawLine(wi->dpy, wi->draw_buffer, wi->gc, x, y, x, y);
        }
        else {
          x = ((int) hist[i].dev.x) - h_side_size;
          y = ((int) hist[i].dev.y) - h_side_size;
          if (ISSET(track->flags, CIRCLE_HISTORY_BIT)) {
            if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
              XFillArc(wi->dpy, wi->draw_buffer, wi->gc,  
                       x, y, side_size, side_size, 0, 360*64);
            }
            else {
              XDrawArc(wi->dpy, wi->draw_buffer, wi->gc,  
                       x, y, side_size - 1, side_size - 1, 0, 360*64);
            }
          }
          else {
            if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
              XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc,  
                             x, y, side_size, side_size);
            }
            else {
              XDrawRectangle(wi->dpy, wi->draw_buffer, wi->gc,  
                             x, y, side_size - 1, side_size - 1);
            }
          }
        }
      }
    }
  }

  /*
   * Draw the current position using a pattern for Tk.
   */
  if (track->symbol != ZnUnspecifiedImage) {
    x = ((int) track->dev.x) - (width+1)/2;
    y = ((int) track->dev.y) - (height+1)/2;
    values.foreground = ZnGetGradientPixel(track->symbol_color, 0.0);
    values.fill_style = FillStippled;
    values.stipple = ZnImagePixmap(track->symbol, wi->win);
    values.ts_x_origin = x;
    values.ts_y_origin = y;
    XChangeGC(wi->dpy, wi->gc,
              GCForeground|GCFillStyle|GCStipple|GCTileStipXOrigin|GCTileStipYOrigin,
              &values);
    XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, x, y, width, height);
  }

  /*
   * Draw the label.
   */
  ZnFIELD.DrawFields(&track->field_set);
}


/*
**********************************************************************************
*
* Render --
*
**********************************************************************************
*/
#ifdef GL
struct MarkerCBData {
  ZnPoint *p;
  int     num;
  ZnReal  size;
  ZnPoint center;
};

static void
MarkerRenderCB(void *closure)
{
  struct MarkerCBData *cbd = (struct MarkerCBData *) closure;
  int                 i;

  glBegin(GL_TRIANGLE_FAN);
  glVertex2d(cbd->center.x, cbd->center.y);  
  for (i = 0; i < cbd->num; i++) {
    glVertex2d(cbd->center.x + cbd->p[i].x*cbd->size,
               cbd->center.y + cbd->p[i].y*cbd->size);
  }
  glEnd();
}

static void
Render(ZnItem   item)
{
  ZnWInfo       *wi = item->wi;
  TrackItem     track = (TrackItem) item;
  TrackItem     c_item;
  History       hist;
  unsigned int  h_side_size, side_size, width=0, height=0;
  unsigned int  i, j, nb_hist, num_acc_pos;
  unsigned short alpha;
  XColor        *color;
  ZnPoint       *points;
  unsigned int  num_points;
  ZnReal        x0, y0, size;

  /* Draw the marker */
  if (track->marker_size_dev != 0) {
    points = ZnGetCirclePoints(3, ZN_CIRCLE_MEDIUM, 0.0, 2*M_PI, &num_points, NULL);
    x0 = track->dev.x;
    y0 = track->dev.y;
    size = track->marker_size_dev;
    if (ISSET(track->flags, MARKER_FILLED_BIT)) {
      ZnBBox              bbox;
      struct MarkerCBData cbd;

      cbd.center.x = x0;
      cbd.center.y = y0;
      cbd.num = num_points;
      cbd.size = size;
      cbd.p = points;
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
      if (track->marker_fill_pattern != ZnUnspecifiedImage) { /* Fill stippled */
        ZnResetBBox(&bbox);
        ZnAddPointToBBox(&bbox, track->dev.x-size, track->dev.y-size);
        ZnAddPointToBBox(&bbox, track->dev.x+size, track->dev.y+size);
        ZnRenderTile(wi, track->marker_fill_pattern, track->marker_color,
                     MarkerRenderCB, &cbd, (ZnPoint *) &bbox);
      }
      else {
        color = ZnGetGradientColor(track->marker_color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
        MarkerRenderCB(&cbd);
      }
    }
    else {
      glLineWidth(1.0);
      ZnSetLineStyle(wi, track->marker_style);
      glBegin(GL_LINE_LOOP);
      for (i = 0; i < num_points; i++) {
        glVertex2d(x0 + points[i].x*size, y0 + points[i].y*size);
      }
      glEnd();
    }
  }

  /*
   * Draw the connection.
   */
  c_item = (TrackItem) item->connected_item;
  if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
    color = ZnGetGradientColor(track->connection_color, 0.0, &alpha);
    alpha = ZnComposeAlpha(alpha, wi->alpha);
    glColor4us(color->red, color->green, color->blue, alpha);
    glLineWidth((GLfloat)track->connection_width);
    glBegin(GL_LINES);
    glVertex2d(track->dev.x, track->dev.y);
    glVertex2d(c_item->dev.x, c_item->dev.y);
    glEnd();
  }

  /*
   * Draw the speed vector.
   */
  if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
    unsigned int num_clips=0, svlength=0;
    ZnReal       svxstep=0, svystep=0;
    GLfloat      ticksize=0;

    color = ZnGetGradientColor(track->speed_vector_color, 0.0, &alpha);
    alpha = ZnComposeAlpha(alpha, wi->alpha);
    glColor4us(color->red, color->green, color->blue, alpha);
    glLineWidth((GLfloat)track->speed_vector_width);

    /*
     * Turn off AA to obtain a square point precisely defined
     */
    if (ISSET(track->flags, SV_TICKS_BIT) ||
        ISSET(track->flags, SV_MARK_BIT)) {
      glDisable(GL_POINT_SMOOTH);
      
      if (ISSET(track->flags, SV_TICKS_BIT)) {
        num_clips = ZnListSize(wi->clip_stack);
        ticksize = 3;
        svlength = (int) wi->speed_vector_length;
        svxstep = (track->speed_vector_dev.x-track->dev.x)/svlength;    
        svystep = (track->speed_vector_dev.y-track->dev.y)/svlength;    
        glPointSize(ticksize);
        ZnGlStartClip(num_clips, False);
        glBegin(GL_POINTS);
        for (i = 1; i < svlength; i++) {
          glVertex2d(track->dev.x + i*svxstep, track->dev.y + i*svystep);
        }
        glEnd();
        ZnGlRenderClipped();
      }
    }

    glBegin(GL_LINES);
    glVertex2d(track->dev.x, track->dev.y);
    glVertex2d(track->speed_vector_dev.x, track->speed_vector_dev.y);
    glEnd();

    if (ISSET(track->flags, SV_MARK_BIT)) {
      glPointSize((GLfloat) (track->speed_vector_width + 2.0));
      glBegin(GL_POINTS);
      glVertex2d(track->speed_vector_dev.x, track->speed_vector_dev.y);
      glEnd();
    }

    if (ISSET(track->flags, SV_TICKS_BIT) ||
        ISSET(track->flags, SV_MARK_BIT)) {
      glEnable(GL_POINT_SMOOTH);

      if (ISSET(track->flags, SV_TICKS_BIT)) {
        glPointSize(ticksize);
        ZnGlRestoreStencil(num_clips, False);
        glBegin(GL_POINTS);
        for (i = 1; i < svlength; i++) {
          glVertex2d(track->dev.x + i*svxstep, track->dev.y + i*svystep);
        }
        glEnd();
        ZnGlEndClip(num_clips);
      }
    }
  }

  /*
   * Draw the leader.
   */
  if (track->field_set.label_format && (track->leader_width > 0)) {
    points = ZnListArray(track->leader_points);
    num_points = ZnListSize(track->leader_points);
    ZnRenderPolyline(wi,
                     points, num_points, track->leader_width,
                     track->leader_style, CapRound, JoinRound,
                     track->leader_first_end, track->leader_last_end,
                     track->leader_color);
  }
  
  if (track->symbol != ZnUnspecifiedImage) {
    ZnSizeOfImage(track->symbol, (int *) &width, (int *) &height);
  }
  
  /*
   * Draw the history, current pos excepted.
   */
  if ((item->class == ZnTrack) && track->history) {
    unsigned int visible_history_size;

    visible_history_size = (ISSET(track->flags, HISTORY_VISIBLE_BIT) ?
                            wi->track_visible_history_size : 0);

    points = ZnGetCirclePoints(3, ZN_CIRCLE_COARSE, 0.0, 2*M_PI, &num_points, NULL);
    color = ZnGetGradientColor(track->history_color, 0.0, &alpha);
    alpha = ZnComposeAlpha(alpha, wi->alpha);
    glColor4us(color->red, color->green, color->blue, alpha);
    glLineWidth(1.0);    
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    num_acc_pos = MIN(visible_history_size, ZnListSize(track->history));
    hist = ZnListArray(track->history);
    side_size = (int) track->history_width;
    /*
     * Turning off line and point smoothing
     * to enhance ;-) history drawing.
     */
    glDisable(GL_LINE_SMOOTH);
    glDisable(GL_POINT_SMOOTH);
    for (i = 0, nb_hist = 0; i < num_acc_pos; i++) {
      if (ISSET(track->flags, LAST_AS_FIRST_BIT) &&
          (i == visible_history_size-1)) {
        color = ZnGetGradientColor(track->symbol_color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, wi->alpha);
        glColor4us(color->red, color->green, color->blue, alpha);
      }
      side_size--;
      side_size = MAX(1, side_size);
      h_side_size = (side_size+1)/2;
      if (hist[i].visible) {
        x0 = hist[i].dev.x;
        y0 = hist[i].dev.y;
        if ((ISSET(track->flags, DOT_MIXED_HISTORY_BIT) && !(nb_hist++ % 2)) ||
            (side_size == 1)) {
          glPointSize(1.0);    
          glBegin(GL_POINTS);
          glVertex2d(x0, y0);
          glEnd();
        }
        else {
          if (ISSET(track->flags, CIRCLE_HISTORY_BIT)) {
            if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
              glPointSize((GLfloat) side_size);
              glBegin(GL_POINTS);
              glVertex2d(x0, y0);
              glEnd();
            }
            else {
#if 1
              glBegin(GL_LINE_LOOP);
              for (j = 0; j < num_points; j++) {
                glVertex2d(x0 + points[j].x*h_side_size,
                           y0 + points[j].y*h_side_size);
              }
              glEnd();
#else
              RenderHollowDot(wi, &hist[i].dev, side_size+1);
#endif
            }
          }
          else {
            if (ISSET(track->flags, FILLED_HISTORY_BIT)) {
              glBegin(GL_QUADS);
              glVertex2d(x0 - h_side_size, y0 - h_side_size);
              glVertex2d(x0 - h_side_size, y0 + h_side_size);
              glVertex2d(x0 + h_side_size, y0 + h_side_size);
              glVertex2d(x0 + h_side_size, y0 - h_side_size);
              glEnd();
            }
            else {
              glBegin(GL_LINE_LOOP);
              glVertex2d(x0 - h_side_size, y0 - h_side_size);
              glVertex2d(x0 - h_side_size, y0 + h_side_size);
              glVertex2d(x0 + h_side_size, y0 + h_side_size);
              glVertex2d(x0 + h_side_size, y0 - h_side_size);
              glEnd();
            }
          }
        }
      }
    }
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_POINT_SMOOTH);
  }

  /*
   * Draw the current position using a pattern.
   */
  if (track->symbol != ZnUnspecifiedImage) {
    ZnPoint p;

    p.x = track->dev.x - (width+1)/2;
    p.y = track->dev.y - (height+1)/2;
    ZnRenderIcon(wi, track->symbol, track->symbol_color, &p, True);
  }

  /*
   * Render the label.
   */
  ZnFIELD.RenderFields(&track->field_set);
} 
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
**********************************************************************************
*
* IsSensitive --
*
**********************************************************************************
*/
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  if (ISCLEAR(item->flags, ZN_SENSITIVE_BIT) ||
      !item->parent->class->IsSensitive(item->parent, ZN_NO_PART)) {
    return False;
  }
  
  if (item_part < ZN_NO_PART) {
    return ISSET(item->part_sensitive, ZnPartToBit(item_part));
  }
  else if (item_part >= 0) {
    return ZnFIELD.IsFieldSensitive(&((TrackItem) item)->field_set, item_part);
  }
  else if (item_part == ZN_NO_PART) {
    return ISSET(item->flags, ZN_SENSITIVE_BIT);
  }
  return True;
}


/*
**********************************************************************************
*
* Pick --
*
**********************************************************************************
*/
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  TrackItem     track = (TrackItem) item;
  ZnItem        c_item;
  ZnBBox        bbox;
  double        dist=0, new_dist;
  ZnPoint       *points, *p = ps->point;
  int           num_points, i;
  int           width=0, height=0;
  double        width_2;
  int           best_part;
  ZnPoint       pts[2];
                     
  /*
   * Try one of the fields.
   */
  dist = ZnFIELD.FieldsPick(&track->field_set, p, &best_part);
  if (dist <= 0.0) {
    goto report0;
  }

  /*
   * Try the current position symbol.
   */
  ZnResetBBox(&bbox);
  if (track->symbol != ZnUnspecifiedImage) {
    ZnSizeOfImage(track->symbol, &width, &height);
    bbox.orig.x = track->dev.x-(width+1)/2;
    bbox.orig.y = track->dev.y-(height+1)/2;
    bbox.corner.x = bbox.orig.x + width;
    bbox.corner.y = bbox.orig.y + height;
  }

  new_dist = ZnRectangleToPointDist(&bbox, p);
  if (new_dist < dist) {
    best_part = CURRENT_POSITION;
    dist = new_dist;
  }
  if (dist <= 0.0) {
    goto report0;
  }
  
  /*
   * Try the leader.
   */
  if (track->field_set.label_format && (track->leader_width > 0) &&
      track->leader_points) {
    ZnPoint end_points[ZN_LINE_END_POINTS];

    width_2 = (track->leader_width>1) ? ((double) track->leader_width)/2.0 : 0;
    points = (ZnPoint *) ZnListArray(track->leader_points);
    num_points = ZnListSize(track->leader_points)-1;
    for (i = 0; i < num_points; i++) {
      new_dist = ZnLineToPointDist(&points[i], &points[i+1], p, NULL);
      new_dist -= width_2;
      if (new_dist < dist) {
        best_part = LEADER;
        dist = new_dist;
      }
      if (dist <= 0.0) {
        goto report0;
      }
    }
    if (track->leader_first_end != NULL) {
      ZnGetLineEnd(&points[0], &points[1], track->leader_width,
                   CapRound, track->leader_first_end, end_points);
      new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
      if (new_dist < dist) {
        best_part = LEADER;
        dist = new_dist;        
      }
      if (dist <= 0.0) {
        goto report0;
      }
    }
    if (track->leader_last_end != NULL) {
      ZnGetLineEnd(&points[num_points-1], &points[num_points-2], track->leader_width,
                   CapRound, track->leader_last_end, end_points);
      new_dist = ZnPolygonToPointDist(end_points, ZN_LINE_END_POINTS, p);
      if (new_dist < dist) {
        best_part = LEADER;
        dist = new_dist;        
      }
      if (dist <= 0.0) {
        goto report0;
      }
    }
  }

  /*
   * Try the speed vector.
   */
  if ((item->class == ZnTrack) && (track->speed_vector_width > 0)) {
    pts[0] = track->dev;
    pts[1] = track->speed_vector_dev;
    new_dist = ZnPolylineToPointDist(pts, 2, track->speed_vector_width,
                                     CapRound, JoinRound, p);
    if (new_dist < dist) {
      best_part = SPEED_VECTOR;
      dist = new_dist;
    }
    if (dist <= 0.0) {
      goto report0;
    }
  }

  /*
   * Try the connection.
   */
  c_item = item->connected_item;
  if ((c_item != ZN_NO_ITEM) && (track->connection_width > 0)) {
    pts[0] = track->dev;
    pts[1] = ((TrackItem) item->connected_item)->dev;
    new_dist = ZnPolylineToPointDist(pts, 2, track->connection_width,
                                     CapRound, JoinRound, p);
    if (new_dist < dist) {
      dist = new_dist;
      best_part = CONNECTION;
    }
    if (dist <= 0.0) {
    report0:
      dist = 0.0;
    }
  }

  //printf("track %d reporting part %d, distance %lf\n", item->id, best_part, dist);
  ps->a_part = best_part;
  return dist;
}


/*
**********************************************************************************
*
* PostScript --
*
**********************************************************************************
*/
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
	return TCL_OK;
}


#ifdef ATC
/*
**********************************************************************************
*
* ZnSendTrackToOm --
*
**********************************************************************************
*/
/*
 * TODO:
 *
 *   The tracks should be identified by their ids not their
 *   structure pointer. This would enable an easy interface
 *   between the overlap manager and the applications when
 *   dealing with tracks.
 */
void *
ZnSendTrackToOm(void    *ptr,
                void    *item,
                int     *x,
                int     *y,
                int     *sv_dx,
                int     *sv_dy,
                /*int   *label_x,
                  int   *label_y,
                  int   *label_width,
                  int   *label_height,*/
                int     *rho,
                int     *theta,
                int     *visibility,
                int     *locked,
                int     *preferred_angle,
                int     *convergence_style)
{
  ZnWInfo       *wi = (ZnWInfo *) ptr;
  ZnItem        current_item = (ZnItem) item;
  TrackItem     track;
  ZnBBox        zn_bbox, bbox;
  ZnBool        to_be_sent;

  int rho_derived ;

  zn_bbox.orig.x = zn_bbox.orig.y = 0;
  zn_bbox.corner.x = wi->width;
  zn_bbox.corner.y = wi->height;

  if (current_item == ZN_NO_ITEM) {
    current_item = ZnGroupHead(wi->om_group);
  }
  else {
    current_item = current_item->next;
  }

  while (current_item != ZN_NO_ITEM) {
    to_be_sent = current_item->class == ZnTrack;

    /* We send invisibles items because the current algorithm
       take care of the age of the tracks.
       to_be_sent &= ISSET(current_item->flags, ZN_VISIBLE_BIT);*/

    ZnIntersectBBox(&zn_bbox, &current_item->item_bounding_box, &bbox);
    to_be_sent &= !ZnIsEmptyBBox(&bbox);
    
    if (to_be_sent) {
      track = (TrackItem) current_item;
      
      *x = (int) track->dev.x;
      *y = wi->height - ((int) track->dev.y);

      /*
       * We must send world values for speed vector deltas as device
       * equivalents can be null. But then if the image is rotated this
       * is nonsense.
       */
      *sv_dx = (int) track->speed_vector.x;
      *sv_dy = (int) track->speed_vector.y;

      /* Fri Oct 13 15:16:38 2000
       *label_x = track->field_set.label_pos.x;
       *label_y = wi->height - track->field_set.label_pos.y;
       if (track->field_set.label_format) {
       ZnDim    bb_width, bb_height;

       ZnFIELD.GetLabelBBox(&track->field_set, &bb_width, &bb_height);
       *label_width = bb_width;
       *label_height = bb_height;
       }
       else {
       *label_width = 0;
       *label_height = 0;
       }
      */

      /*
       * Trial to fix rho drift due to ZnPointPolarToCartesian
       * roundoff error.
       */
      rho_derived = (int) sqrt(track->label_dx*track->label_dx +
                               track->label_dy*track->label_dy);
#ifdef DP
      if (ABS(rho_derived - track->label_distance) < LABEL_DISTANCE_THRESHOLD) {
        /* The error is narrow so value discarded */
        *rho =  track->label_distance ;
      }
      else {
        /* Means a user change has been performed on label_dx label_dy */
        *rho = rho_derived ;
      }
#else
      *rho = rho_derived;
#endif
      *theta = track->label_angle;
      *visibility = (ISSET(current_item->flags, ZN_VISIBLE_BIT) ? 1 : 0 );
      *locked = (ISSET(track->flags, FROZEN_LABEL_BIT) ? 1 : 0);
      *preferred_angle = track->label_preferred_angle;
      *convergence_style = track->label_convergence_style;
      break;
    }
    
    current_item = current_item->next;
  }
  
  return (void *) current_item;
}


/*
**********************************************************************************
*
* ZnSetLabelAngleFromOm --
*
**********************************************************************************
*/
void
ZnSetLabelAngleFromOm(void *ptr,   /* No longer in use. */
                      void *item,
                      int  rho,
                      int  theta,
                      char *reason) /* Technical data explaining algorithm processing */
{
  TrackItem track = (TrackItem) item;

  theta %= 360;
  if (theta < 0) {
    theta += 360;
  }
  if (ISCLEAR(track->flags, FROZEN_LABEL_BIT) && (track->label_angle != theta)) {
    track->label_angle = theta;
#ifdef DP
    track->label_distance = rho;
#endif
    SET(track->flags, POLAR_BIT);
    ZnITEM.Invalidate((ZnItem) item, ZN_COORDS_FLAG);
    /*    ZnGroupSetCallOm(((ZnItem)item)->parent, True);*/
  }
#ifdef OM_TECH
  /* Setup reason regardless of redrawing options. */
  if (reason) {
    if (!track->omtechstuff) {
      track->omtechstuff = ZnMalloc(  (OMTECHSTUFFLEN + 1) * sizeof(char));
    }
    strncpy(track->omtechstuff, reason, OMTECHSTUFFLEN); 
  }
#endif 
}


/*
**********************************************************************************
*
* ZnQueryLabelPosition -- OverlapMan query the widget about what would be the
*                         label position if label_angle is theta
*
**********************************************************************************
*/
void
ZnQueryLabelPosition(void *ptr,   /* No longer in use. */
                     void *item,
                     int  theta,
                     int  *x,
                     int  *y,
                     int  *w,
                     int  *h)
{
  ZnItem    it = (ZnItem) item;
  TrackItem track = (TrackItem) it;
  
  if (track->field_set.label_format) {
    ZnDim     bb_width, bb_height;
    ZnPoint   pos;
    ZnReal    dx, dy;
    ZnTransfo t;
    
    ZnFIELD.GetLabelBBox(&track->field_set, &bb_width, &bb_height);
    ZnITEM.GetItemTransform(item, &t);
    AdjustLabelDistance(track, &t, theta, bb_width, bb_height, &pos, &dx, &dy);
    *x = (int) pos.x;
    *y = (int) (it->wi->height - pos.y);
    *w = (int) bb_width;
    *h = (int) bb_height;
  }
  else {
    *x = *y = *w = *h = 0;
  }
}
#endif


/*
**********************************************************************************
*
* ZnSetHistoryVisibility -- PLC - not yet implemented
*
**********************************************************************************
*/
void
ZnSetHistoryVisibility(ZnItem   item,
                       int      index,
                       ZnBool   visible)
{
}


/*
**********************************************************************************
*
* ZnTruncHistory -- PLC - not yet interfaced
*
**********************************************************************************
*/
void
ZnTruncHistory(ZnItem   item)
{
  TrackItem     track = (TrackItem) item;

  if (track->history) {
    int size = ZnListSize (track->history);
    History hist_tbl = ZnListArray (track->history);
    while (size--) {
      hist_tbl[size].visible = False;
    }
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
}


/*
**********************************************************************************
*
* GetFieldSet --
*
**********************************************************************************
*/
static ZnFieldSet
GetFieldSet(ZnItem      item)
{
  return &((TrackItem) item)->field_set;
}


/*
**********************************************************************************
*
* GetAnchor --
*
**********************************************************************************
*/
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  ZnFieldSet    field_set = &((TrackItem) item)->field_set;
  ZnDim         width, height;
  
  if (field_set->label_format) {
    ZnFIELD.GetLabelBBox(field_set, &width, &height);
    ZnOrigin2Anchor(&field_set->label_pos, width, height, anchor, p);
  }
  else {
    p->x = p->y = 0.0;
  }
}


/*
**********************************************************************************
*
* Coords --
*       Return or edit the item position.
*
**********************************************************************************
*/
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  TrackItem     track = (TrackItem) item;
  
  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp, " ",
                     item->class->name, "s can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (*num_pts == 0) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 1 point on ",
                       item->class->name, "s", NULL);
      return TCL_ERROR;
    }
    if (item->class == ZnTrack) {
      AddToHistory(track, track->pos);
    }
    track->pos = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    *num_pts = 1;
    *pts = &track->pos;
  }
  return TCL_OK;
}


/*
**********************************************************************************
*
* Part --
*       Convert a private part from/to symbolic representation.
*
**********************************************************************************
*/
static int
Part(ZnItem     item,
     Tcl_Obj    **part_spec,
     int        *part)
{
  char  *part_str="";
  int   c;
  char  *end;
  
  if (*part_spec) {
    part_str = Tcl_GetString(*part_spec);
    if (strlen(part_str) == 0) {
      *part = ZN_NO_PART;
    }
    else if (isdigit(part_str[0])) {
      *part = strtol(part_str, &end, 0);
      if ((*end != 0) || (*part < 0) ||
          ((unsigned int) *part >= ((TrackItem) item)->field_set.num_fields)) {
        goto part_error;
      }
    }
    else {
      c = part_str[0];
      if ((c == 'c') && (strcmp(part_str, "connection") == 0)) {
        *part = CONNECTION;
      }
      else if ((c == 'l') && (strcmp(part_str, "leader") == 0)) {
        *part = LEADER;
      }
      else if ((c == 'p') && (strcmp(part_str, "position") == 0)) {
        *part = CURRENT_POSITION;
      }
      else if ((c == 's') && (strcmp(part_str, "speedvector") == 0)) {
        if (item->class != ZnTrack) {
          goto part_error;
        }
        *part = SPEED_VECTOR;
      }
      else {
      part_error:
        Tcl_AppendResult(item->wi->interp, " invalid item part specification", NULL);
        return TCL_ERROR;       
      }
    }
  }
  else {
    if (*part >= 0) {
      *part_spec = Tcl_NewIntObj(*part);
    }
    else {
      part_str = "";
      switch (*part) {
      default:
      case ZN_NO_PART:
        break;
      case CURRENT_POSITION:
        part_str = "position";
        break;
      case LEADER:
        part_str = "leader";
        break;
      case CONNECTION:
        part_str = "connection";
        break;
      case SPEED_VECTOR:
        if (item->class == ZnTrack) {
          part_str = "speedvector";
          break;
        }
      }
      if (part_str[0]) {
        *part_spec = Tcl_NewStringObj(part_str, -1);
      }
    }
  }
  return TCL_OK;  
}


/*
**********************************************************************************
*
* Index --
*       Parse a text index and return its value and aa
*       error status (standard Tcl result).
*
**********************************************************************************
*/
static int
Index(ZnItem    item,
      int       field,
      Tcl_Obj   *index_spec,
      int       *index)
{
  return ZnFIELD.FieldIndex(&((TrackItem) item)->field_set, field,
                            index_spec, index);
}


/*
**********************************************************************************
*
* InsertChars --
*
**********************************************************************************
*/
static void
InsertChars(ZnItem      item,
            int         field,
            int         *index,
            char        *chars)
{
  if (ZnFIELD.FieldInsertChars(&((TrackItem) item)->field_set,
                               field, index, chars)) {
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
}


/*
**********************************************************************************
*
* DeleteChars --
*
**********************************************************************************
*/
static void
DeleteChars(ZnItem      item,
            int         field,
            int         *first,
            int         *last)
{
  if (ZnFIELD.FieldDeleteChars(&((TrackItem) item)->field_set,
                               field, first, last)) {
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
}


/*
**********************************************************************************
*
* Cursor --
*
**********************************************************************************
*/
static void
TrackCursor(ZnItem      item,
            int         field,
            int         index)
{
  ZnFIELD.FieldCursor(&((TrackItem) item)->field_set, field, index);
}


/*
**********************************************************************************
*
* Selection --
*
**********************************************************************************
*/
static int
Selection(ZnItem        item,
          int           field,
          int           offset,
          char          *chars,
          int           max_chars)
{
  return ZnFIELD.FieldSelection(&((TrackItem) item)->field_set, field,
                                offset, chars, max_chars);
}


/*
**********************************************************************************
*
* Exported functions struct --
*
**********************************************************************************
*/
/*
 * Track -position attribute is not handled the same way as other
 * interface items like texts, icons and such, as it make little sense
 * to change the local transform of a track. It is always processed as
 * a point in the coordinate system of the track's parent. It is the same
 * for the points in the history and the speed vector end.
 */
static CONST ZnItemClassStruct TRACK_ITEM_CLASS = {
  "track",
  sizeof(TrackItemStruct),
  track_attrs,
  4,                    /* num_parts */
  ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  GetFieldSet,
  GetAnchor,
  NULL,                 /* GetClipVertices */
  NULL,                 /* GetContours */
  Coords,
  InsertChars,
  DeleteChars,
  TrackCursor,
  Index,
  Part,
  Selection,
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

static CONST ZnItemClassStruct WAY_POINT_ITEM_CLASS = {
  "waypoint",
  sizeof(TrackItemStruct),
  wp_attrs,
  3,                    /* num_parts */
  ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  GetFieldSet,
  GetAnchor,
  NULL,                 /* GetClipVertices */
  NULL,                 /* GetContours */
  Coords,
  InsertChars,
  DeleteChars,
  TrackCursor,
  Index,
  Part,
  Selection,
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnTrack = (ZnItemClassId) &TRACK_ITEM_CLASS;
CONST ZnItemClassId ZnWayPoint = (ZnItemClassId) &WAY_POINT_ITEM_CLASS;

Added jni/tkzinc/generic/Track.h.



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*
 * Track.h -- 
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Tue Jan 19 16:03:53 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Track_h
#define _Track_h


#include "Item.h"


/*
 **********************************************************************************
 *
 * Functions defined in Track.c for internal use.
 *
 **********************************************************************************
 */

void *ZnSendTrackToOm(void *ptr, void *item, int *x, int *y,
                      int *sv_dx, int *sv_dy,
                      /* Fri Oct 13 15:18:11 2000
                         int *label_x, int *label_y,
                         int *label_width, int *label_height,*/
                      int *rho, int *theta, int *visibility, int *locked,
                      int *preferred_angle, int *convergence_style);
void ZnSetLabelAngleFromOm(void *ptr, void *item, int rho, int theta,
                           char *reason); /* Technical data explaining algorithm processing */
void ZnQueryLabelPosition(void *ptr, void *item, int theta,
                          int *x, int *y, int *w, int *h);  
void ZnSetHistoryVisibility(ZnItem item, int index, ZnBool visibility);
void ZnTruncHistory(ZnItem item);


#endif /* _Track_h */

Added jni/tkzinc/generic/Transfo.c.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
/*
 * Transfo.c -- Implementation of transformation routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : 
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
 * This package deals with *AFFINE* 3x3 matrices.
 * This means that you should not try to feed it with matrices
 * containing perspective changes. It is assumed that the third
 * column is always [0 0 1] as this is the case for affine matrices.
 * Furthermore affine matrices are known to be invertible (non singular).
 * Despite this, various tests are done to test the invertibility because
 * of numerical precision or limit.
 * Any of the operations in this module yield an affine matrix. Composition
 * of two affine matrices and inversion of an affine matrix result in an
 * affine matrix (Affine matrices Group property). Rotation, translation
 * anamorphic scaling, xy skew and yx skew also preserve the property.
 *
 */


#include "Item.h"
#include "Geo.h"
#include "Transfo.h"
#include "Types.h"

#include <stdlib.h>


static const char rcsid[] = "$Imagine: Transfo.c,v 1.7 1997/01/24 14:33:37 lecoanet Exp $";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";



/*
 *************************************************************************
 *
 * The transformation primitives are based on affines matrices retricted
 * to the following pattern:
 *
 *      x x 0
 *      x x 0
 *      x x 1
 *
 * It is necessary to feed only those matrices to the Transfo primitives
 * as they do optimizations based on the properties of affine matrices.
 * Furthermore the package stores only the first two columns, the third
 * is constant. There is no way to describe perspective transformation
 * with these transformation matrices.
 *
 *************************************************************************
 */

/*
 *************************************************************************
 *
 * ZnTransfoNew --
 *      Create a new transformation and return it initialized to
 *      identity.
 * 
 *************************************************************************
 */
ZnTransfo *
ZnTransfoNew()
{
  ZnTransfo     *t;

  t = (ZnTransfo *) ZnMalloc(sizeof(ZnTransfo));
  ZnTransfoSetIdentity(t);
  
  return t;
}


/*
 *************************************************************************
 *
 * ZnTransfoDuplicate --
 *      Create a new transformation identical to the model t.
 * 
 *************************************************************************
 */
ZnTransfo *
ZnTransfoDuplicate(ZnTransfo *t)
{
  ZnTransfo     *nt;

  nt = (ZnTransfo *) ZnMalloc(sizeof(ZnTransfo));
  if (t) {
    *nt = *t;
  }
  else {
    ZnTransfoSetIdentity(nt);
  }
  
  return nt;
}


/*
 *************************************************************************
 *
 * ZnTransfoFree --
 *      Delete a transformation and free its memory.
 * 
 *************************************************************************
 */
void
ZnTransfoFree(ZnTransfo *t)
{
  ZnFree(t);
}


/*
 *************************************************************************
 *
 * ZnPrintTransfo --
 *      Print the transfo matrix on stdout.
 * 
 *************************************************************************
 */
void
ZnPrintTransfo(ZnTransfo        *t)
{
  /*
   * sx 0       cos(rot)  sin(rot)      1          tan(skewy)   1  0
   * 0  sy      -sin(rot) cos(rot)      tan(skewx) 1            0  1
   * 0  0       0         0             0          0            tx ty
   */
  if (t) {
    printf("(%5g %5g\n %5g %5g\n %5g %5g)\n",
           t->_[0][0], t->_[0][1],
           t->_[1][0], t->_[1][1],
           t->_[2][0], t->_[2][1]);
  }
  else {
    printf("(%5g %5g\n %5g %5g\n %5g %5g)\n",
           1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
  }
}


/*
 *************************************************************************
 *
 * ZnTransfoIsIdentity --
 *      Tell if the given transfo is (close to) identity.
 * 
 *************************************************************************
 */
ZnBool
ZnTransfoIsIdentity(ZnTransfo   *t)
{
  ZnReal        tmp;
  ZnBool        res = False;

  tmp = t->_[0][0] - 1.0;
  res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
  tmp = t->_[1][1] - 1.0;
  res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
  tmp = t->_[0][1];
  res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
  tmp = t->_[1][0];
  res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
  tmp = t->_[2][0];
  res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
  tmp = t->_[2][1];
  res = res & ((tmp < PRECISION_LIMIT) && (tmp > -PRECISION_LIMIT));
  return res;
}


/*
 *************************************************************************
 *
 * ZnTransfoSetIdentity --
 *      Initialize the given transfo to identity.
 * 
 *************************************************************************
 */
void
ZnTransfoSetIdentity(ZnTransfo  *t)
{
  t->_[0][0] = 1;
  t->_[0][1] = 0;
  t->_[1][0] = 0;
  t->_[1][1] = 1;
  t->_[2][0] = 0;
  t->_[2][1] = 0;
}


/*
 *************************************************************************
 *
 * ZnTransfoCompose --
 *      Combine two transformations t1 and t2 by post-concatenation.
 *      Returns the resulting transformation.
 *      t2 can be NULL, meaning identity transform. This is used in
 *      the toolkit to optimize some cases.
 *
 *      All the parameters must be distincts transforms.
 *
 *************************************************************************
 */
ZnTransfo *
ZnTransfoCompose(ZnTransfo      *res,
                 ZnTransfo      *t1,
                 ZnTransfo      *t2)
{
  if ((t1 != NULL) && (t2 != NULL)) {
    register float      tmp;

    tmp = t1->_[0][0];
    res->_[0][0] = tmp*t2->_[0][0] + t1->_[0][1]*t2->_[1][0];
    res->_[0][1] = tmp*t2->_[0][1] + t1->_[0][1]*t2->_[1][1];
    tmp = t1->_[1][0];
    res->_[1][0] = tmp*t2->_[0][0] + t1->_[1][1]*t2->_[1][0];
    res->_[1][1] = tmp*t2->_[0][1] + t1->_[1][1]*t2->_[1][1];
    tmp = t1->_[2][0];
    res->_[2][0] = tmp*t2->_[0][0] + t1->_[2][1]*t2->_[1][0] + t2->_[2][0];
    res->_[2][1] = tmp*t2->_[0][1] + t1->_[2][1]*t2->_[1][1] + t2->_[2][1];
  }
  else if (t1 == NULL) {
    if (res != t2) {
      *res = *t2;
    }
  }
  else if (t2 == NULL) {
    if (res != t1) {
      *res = *t1;
    }
  }
  else {
    ZnTransfoSetIdentity(res);
  }
  
  return res;
}


/*
 *************************************************************************
 *
 * ZnTransfoInvert --
 *      Compute the inverse of the given matrix and return it. This
 *      function makes the assumption that the matrix is affine to
 *      optimize the job. Do not give it a general matrix, this will
 *      fail. This code is from Graphics Gems II. Anyway an affine
 *      matrix is always invertible for affine matrices form a sub
 *      group of the non-singular matrices.
 *
 *************************************************************************
 */
ZnTransfo *
ZnTransfoInvert(ZnTransfo       *t,
                ZnTransfo       *inv)
{
  float pos, neg, temp, det_l;

  if (t == NULL) {
    ZnTransfoSetIdentity(inv);
    return inv;
  }

  /*
   * Compute the determinant of the upper left 2x2 sub matrix to see
   * if it is singular.
   */
  pos = neg = 0.0;
  temp = t->_[0][0] * t->_[1][1];
  if (temp >= 0.0) {
    pos += temp;
  }
  else {
    neg += temp;
  }
  temp = - t->_[0][1] * t->_[1][0];
  if (temp >= 0.0) {
    pos += temp;
  }
  else {
    neg += temp;
  }
  det_l = pos + neg;
  temp = det_l / (pos - neg); /* Why divide by (pos - neg) ?? */
  
  if (ABS(temp) < PRECISION_LIMIT) {
    ZnWarning("ZnTransfoInvert : singular matrix\n");
    return NULL;
  }
  
  det_l = 1 / det_l;
  inv->_[0][0] = t->_[1][1] * det_l;
  inv->_[0][1] = - t->_[0][1] * det_l;
  inv->_[1][0] = - t->_[1][0] * det_l;
  inv->_[1][1] = t->_[0][0] * det_l;
  /*
   * The code below is equivalent to:
   *   inv->_[2][0] = (t->_[1][0] * t->_[2][1] - t->_[1][1] * t->_[2][0]) * det_l;
   *   inv->_[2][1] = - (t->_[0][0] * t->_[2][1] - t->_[0][1] * t->_[2][0]) * det_l;
   *
   * with some operations factored (already computed) to increase speed.
   */
  inv->_[2][0] = - (inv->_[0][0] * t->_[2][0] + inv->_[1][0] * t->_[2][1]);
  inv->_[2][1] = - (inv->_[0][1] * t->_[2][0] + inv->_[1][1] * t->_[2][1]);

  return inv;
}


/*
 *************************************************************************
 *
 * ZnTransfoDecompose --
 *      Decompose an affine matrix into translation, scale, skew and
 *      rotation. The different values are stored in the locations
 *      pointed to by the pointer parameters. If some values are not
 *      needed a NULL pointer can be given instead. The resulting skew
 *      shews x coordinate when y change.
 *      This code is taken from Graphics Gems II.
 *
 *************************************************************************
 */
void
ZnTransfoDecompose(ZnTransfo    *t,
                   ZnPoint      *scale,
                   ZnPoint      *trans,
                   ZnReal       *rotation,
                   ZnReal       *skewxy)
{
  ZnTransfo     local;
  float         skew, len, rot, det;
  
  if (t == NULL) {
    /* Identity transform */
    if (scale) {
      scale->x = 1.0;
      scale->y = 1.0;
    }
    if (trans) {
      trans->x = 0.0;
      trans->y = 0.0;
    }
    if (rotation) {
      *rotation = 0.0;
    }
    if (skewxy) {
      *skewxy = 0.0;
    }
    //printf("Transfo is identity\n");
    return;
  }

  det = (t->_[0][0]*t->_[1][1] - t->_[0][1]*t->_[1][0]);
  if (ABS(det) < PRECISION_LIMIT) {
    ZnWarning("ZnTransfoDecompose : singular matrix\n");
    return;
  }
  
  local = *t;
  //ZnPrintTransfo(&local);
  /* Get translation part if needed */
  if (trans) {
    trans->x = ABS(local._[2][0]) < PRECISION_LIMIT ? 0 : local._[2][0];
    trans->y = ABS(local._[2][1]) < PRECISION_LIMIT ? 0 : local._[2][1];
  }
  if (!scale && !skewxy && !rotation) {
    return;
  }

  /* Get scale and skew */
  len = (float) sqrt(local._[0][0]*local._[0][0] +
                     local._[0][1]*local._[0][1]); /* Get x scale from 1st row */
  if (scale) {
    scale->x = len < PRECISION_LIMIT ? 0.0 : len;
  }
  local._[0][0] /= len;                  /* Normalize 1st row */
  local._[0][1] /= len;
  skew = (local._[0][0]*local._[1][0] +
          local._[0][1]*local._[1][1]); /* Skew is dot product of 1st row & 2nd row */
  /* Make the 2nd row orthogonal to the 1st row
   * by linear combinaison:
   * row1.x = row1.x + row0.x*-skew &
   * row1.y = row1.y + row0.y*-skew
   */
  local._[1][0] -= local._[0][0]*skew;
  local._[1][1] -= local._[0][1]*skew;
  len = (float) sqrt(local._[1][0]*local._[1][0] +
                     local._[1][1]*local._[1][1]); /* Get y scale from 2nd row */
  if (scale) {
    scale->y = len < PRECISION_LIMIT ? 0.0 : len;
  }

  if (!skewxy && !rotation) {
    return;
  }

  local._[1][0] /= len;                  /* Normalize 2nd row */
  local._[1][1] /= len;
  skew /= len;
  if (skewxy) {
    *skewxy = ABS(skew) < PRECISION_LIMIT ? 0.0 : skew;
    //printf("skew %f\n", *skewxy);
  }

  if (!rotation) {
    return;
  }

  //printf("Matrix after scale & skew extracted\n");
  //ZnPrintTransfo(&local);
  /* Get rotation */
  /* Check for a coordinate system flip. If det of upper-left 2x2
   * is -1, there is a reflection. If the rotation is < 180° negate
   * the y scale. If the rotation is > 180° then negate the x scale
   * and report a rotation between 0 and 180°. This dissymetry is
   * the result of computing (z) rotation from the first row (x component
   * of the axis system basis).
   */
  det = (local._[0][0]*local._[1][1]- local._[0][1]*local._[1][0]);
  
  rot = (float) atan2(local._[0][1], local._[0][0]);
  if (rot < 0) {
    rot = (2 * (float) M_PI) + rot;
  }
  rot = rot < PRECISION_LIMIT ? 0 : rot;
  if (rot >= M_PI) {
    /*rot -= M_PI;  Why that, I'll have to check Graphic Gems ??? */
    if (scale && det < 0) {
      scale->x *= -1;
    }
  }
  else if (scale && det < 0) {
    scale->y *= -1;
  }
  
  //printf("scalex %f\n", scale->x);
  //printf("scaley %f\n", scale->y);
  //printf("rotation %f\n", rot*180.0/3.1415);

  if (rotation) {
    *rotation = rot;
  }
}


/*
 *************************************************************************
 *
 * ZnTransfoEqual --
 *      Return True if t1 and t2 are equal (i.e they have the same
 *      rotation, skew scales and translations). If include_translation
 *      is True the translations are considered in the test.
 *
 *************************************************************************
 */
ZnBool
ZnTransfoEqual(ZnTransfo        *t1,
               ZnTransfo        *t2,
               ZnBool           include_translation)
{
  if (include_translation) {
    return (t1->_[0][0] == t2->_[0][0] &&
            t1->_[0][1] == t2->_[0][1] &&
            t1->_[1][0] == t2->_[1][0] &&
            t1->_[1][1] == t2->_[1][1] &&
            t1->_[2][0] == t2->_[2][0] &&
            t1->_[2][1] == t2->_[2][1]);
  }
  else {
    return (t1->_[0][0] == t2->_[0][0] &&
            t1->_[0][1] == t2->_[0][1] &&
            t1->_[1][0] == t2->_[1][0] &&
            t1->_[1][1] == t2->_[1][1]);
  }
}


/*
 *************************************************************************
 *
 * ZnTransfoHasSkew --
 *      Return True if t has a skew factor in x or y or describe a
 *      rotation or both.
 *
 *************************************************************************
 */
ZnBool
ZnTransfoHasSkew(ZnTransfo      *t)
{
  return t->_[0][1] != 0.0 || t->_[1][0] != 0.0;
}


/*
 *************************************************************************
 *
 * ZnTransfoIsTranslation --
 *      Return True if t is a pure translation.
 *
 *************************************************************************
 */
ZnBool
ZnTransfoIsTranslation(ZnTransfo        *t)
{
  if (!t) {
    return True;
  }
  return (t->_[0][0] == 1.0 &&
          t->_[0][1] == 0.0 &&
          t->_[1][0] == 0.0 &&
          t->_[1][1] == 1.0);
}


/*
 *************************************************************************
 *
 * ZnTransformPoint --
 *      Apply the transformation to the point. The point is
 *      modified and returned as the value of the function.
 *      It is safe for p and xp to be the same point (structure).
 *      A NULL transformation means identity. This is only used
 *      in the toolkit to optimize some cases. It should never
 *      happen in user code.
 *
 *************************************************************************
 */
ZnPoint *
ZnTransformPoint(ZnTransfo              *t,
                 register ZnPoint       *p,
                 ZnPoint                *xp)
{
  if (t == NULL) {
    xp->x = p->x;
    xp->y = p->y;
  }
  else {
    ZnReal a;
    a = t->_[0][0]*p->x + t->_[1][0]*p->y + t->_[2][0];
    xp->y = t->_[0][1]*p->x + t->_[1][1]*p->y + t->_[2][1];
    xp->x = a;
  }
  return xp;
}


/*
 *************************************************************************
 *
 * ZnTransformPoints --
 *      Apply the transformation to the points in p returning points in xp.
 *      It is safe for p and xp to be the same array of ponits.
 *      The number of points is in num.
 *      A NULL transformation means identity. This is only used
 *      in the toolkit to optimize some cases. It should never
 *      happen in user code.
 *
 *************************************************************************
 */
void
ZnTransformPoints(ZnTransfo     *t,
                  ZnPoint       *p,
                  ZnPoint       *xp,
                  unsigned int  num)
{
  if (t == NULL) {
    memcpy(xp, p, sizeof(ZnPoint)*num);
  }
  else {
    unsigned int i;

    for (i = 0; i < num; i++) {
      ZnReal a;
      a = t->_[0][0]*p[i].x + t->_[1][0]*p[i].y + t->_[2][0];
      xp[i].y = t->_[0][1]*p[i].x + t->_[1][1]*p[i].y + t->_[2][1];
      xp[i].x = a;
    }
  }
}


/*
 *************************************************************************
 *
 * ZnTranslate --
 *      Translate the given transformation by delta_x, delta_y. Returns
 *      the resulting transformation. If abs is true, delta_x and
 *      delta_y are used to set the translation instead of adding deltas.
 *
 *************************************************************************
 */
ZnTransfo *
ZnTranslate(ZnTransfo   *t,
            ZnReal      delta_x,
            ZnReal      delta_y,
            ZnBool      abs)
{
  if (abs) {
    t->_[2][0] = (float) delta_x;
    t->_[2][1] = (float) delta_y;
  }
  else {
    t->_[2][0] = t->_[2][0] + (float) delta_x;
    t->_[2][1] = t->_[2][1] + (float) delta_y;
  }

  return t;
}

/*
 *************************************************************************
 *
 * ZnScale --
 *      Scale the given transformation by scale_x, scale_y. Returns the
 *      resulting transformation.
 *
 *************************************************************************
 */
ZnTransfo *
ZnScale(ZnTransfo       *t,
        ZnReal          scale_x,
        ZnReal          scale_y)
{
  t->_[0][0] = t->_[0][0] * (float) scale_x;
  t->_[0][1] = t->_[0][1] * (float) scale_y;
  t->_[1][0] = t->_[1][0] * (float) scale_x;
  t->_[1][1] = t->_[1][1] * (float) scale_y;
  t->_[2][0] = t->_[2][0] * (float) scale_x;
  t->_[2][1] = t->_[2][1] * (float) scale_y;
  
  return t;
}


/*
 *************************************************************************
 *
 * ZnRotateRad --
 *      Rotate the given transformation by angle radians
 *      counter-clockwise around the origin. Returns the resulting
 *      transformation.
 *
 *************************************************************************
 */
ZnTransfo *
ZnRotateRad(ZnTransfo   *t,
            ZnReal      angle)
{
  float c = (float) cos(angle);
  float s = (float) sin(angle);
  float tmp;
  
  tmp = t->_[0][0];
  t->_[0][0] = tmp*c - t->_[0][1]*s;
  t->_[0][1] = tmp*s + t->_[0][1]*c;
  tmp = t->_[1][0];
  t->_[1][0] = tmp*c - t->_[1][1]*s;
  t->_[1][1] = tmp*s + t->_[1][1]*c;
  tmp = t->_[2][0];
  t->_[2][0] = tmp*c - t->_[2][1]*s;
  t->_[2][1] = tmp*s + t->_[2][1]*c;
  
  return t;
}


/*
 *************************************************************************
 *
 * ZnRotateDeg --
 *      Rotate the given transformation by angle degrees
 *      counter-clockwise around the origin. Returns the resulting
 *      transformation.
 *
 *************************************************************************
 */
ZnTransfo *
ZnRotateDeg(ZnTransfo   *t,
            ZnReal      angle)
{
  return ZnRotateRad(t, ZnDegRad(angle));
}


/*
 *************************************************************************
 *
 * ZnSkewRad --
 *      Skew the given transformation by x_angle and y_angle radians
 *      counter-clockwise around the origin. Returns the resulting
 *      transformation.
 *
 *************************************************************************
 */
ZnTransfo *
ZnSkewRad(ZnTransfo     *t,
          ZnReal        skew_x,
          ZnReal        skew_y)
{
  float sx = (float) tan(skew_x);
  float sy = (float) tan(skew_y);
  float tmp;

  tmp = t->_[0][0];
  t->_[0][0] = tmp + t->_[0][1]*sx;
  t->_[0][1] = tmp*sy + t->_[0][1];
  tmp = t->_[1][0];
  t->_[1][0] = tmp + t->_[1][1]*sx;
  t->_[1][1] = tmp*sy + t->_[1][1];
  tmp = t->_[2][0];
  t->_[2][0] = tmp + t->_[2][1]*sx;
  t->_[2][1] = tmp*sy + t->_[2][1];

  return t;
}


/*
 *************************************************************************
 *
 * ZnSkewDeg --
 *      Skew the given transformation by x_angle and y_angle degrees
 *      counter-clockwise around the origin. Returns the resulting
 *      transformation.
 *
 *************************************************************************
 */
ZnTransfo *
ZnSkewDeg(ZnTransfo     *t,
          ZnReal        skew_x,
          ZnReal        skew_y)
{
  return ZnSkewRad(t, ZnDegRad(skew_x), ZnDegRad(skew_y));
}

  
#undef PRECISION_LIMIT


Added jni/tkzinc/generic/Transfo.h.



















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
 * Transfo.h -- Header for common geometric routines.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Transfo_h
#define _Transfo_h


#include "Types.h"

#include <math.h>
#include <limits.h>


/*
 * First subscript is matrix row, second is matrix column.
 * So a[0][1] is upper right corner of matrix a and a[2][0]
 * is lower left corner.
 */
typedef struct  _ZnTransfo {
  float _[3][2];
} ZnTransfo;


ZnTransfo *
ZnTransfoNew(void);
ZnTransfo *
ZnTransfoDuplicate(ZnTransfo *t);
void
ZnTransfoFree(ZnTransfo *t);
void
ZnPrintTransfo(ZnTransfo        *t);
void
ZnTransfoSetIdentity(ZnTransfo  *t);
ZnBool
ZnTransfoIsIdentity(ZnTransfo   *t);
ZnTransfo *
ZnTransfoCompose(ZnTransfo      *res,
                 ZnTransfo      *t1,
                 ZnTransfo      *t2);
ZnTransfo *
ZnTransfoInvert(ZnTransfo       *t,
                ZnTransfo       *inv);
void
ZnTransfoDecompose(ZnTransfo    *t,
                   ZnPoint      *scale,
                   ZnPoint      *trans,
                   ZnReal       *rotation,
                   ZnReal       *skewxy);
ZnBool
ZnTransfoEqual(ZnTransfo        *t1,
               ZnTransfo        *t2,
               ZnBool           include_translation);
ZnBool
ZnTransfoHasSkew(ZnTransfo      *t);
ZnBool
ZnTransfoIsTranslation(ZnTransfo        *t);
ZnPoint *
ZnTransformPoint(ZnTransfo      *t,
                 ZnPoint        *p,
                 ZnPoint        *xp);
void
ZnTransformPoints(ZnTransfo     *t,
                  ZnPoint       *p,
                  ZnPoint       *xp,
                  unsigned int  num);
ZnTransfo *
ZnTranslate(ZnTransfo   *t,
            ZnReal      delta_x,
            ZnReal      delta_y,
            ZnBool      abs);
ZnTransfo *
ZnScale(ZnTransfo       *t,
        ZnReal          scale_x,
        ZnReal          scale_y);
ZnTransfo *
ZnRotateRad(ZnTransfo   *t,
            ZnReal      angle);
ZnTransfo *
ZnRotateDeg(ZnTransfo   *t,
            ZnReal      angle);
ZnTransfo *
ZnSkewRad(ZnTransfo     *t,
          ZnReal        skew_x,
          ZnReal        skew_y);
ZnTransfo *
ZnSkewDeg(ZnTransfo     *t,
          ZnReal        skew_x,
          ZnReal        skew_y);

#endif  /* _Transfo_h */

Added jni/tkzinc/generic/Triangles.c.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
/*
 * Triangles.c -- Implementation of Triangle fan/strips  item.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Tue Dec 11 10:52:01 2001
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Draw.h"
#include "Item.h"
#include "Geo.h"
#include "Types.h"
#include "WidgetInfo.h"
#include "tkZinc.h"
#include "Image.h"
#include "Color.h"

#include <ctype.h>


static const char rcsid[] = "$Id";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


/*
 * Bit offset of flags.
 */
#define FAN_BIT         1<<0    /* Tell if the triangles are arranged in fan or strips. */


/*
 **********************************************************************************
 *
 * Specific Triangles item record
 *
 **********************************************************************************
 */
typedef struct _TrianglesItemStruct {
  ZnItemStruct  header;

  /* Public data */
  ZnList        points;
  unsigned short flags;
  ZnList        colors;
  
  /* Private data */
  ZnTriStrip    dev_points;
} TrianglesItemStruct, *TrianglesItem;


static ZnAttrConfig     tr_attrs[] = {
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(TrianglesItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_GRADIENT_LIST, "-colors", NULL,
    Tk_Offset(TrianglesItemStruct, colors), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(TrianglesItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(TrianglesItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(TrianglesItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-fan", NULL,
    Tk_Offset(TrianglesItemStruct, flags), FAN_BIT, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(TrianglesItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(TrianglesItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(TrianglesItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(TrianglesItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  ZnWInfo       *wi = item->wi;
  TrianglesItem tr = (TrianglesItem) item;
  unsigned int  num_points;
  ZnPoint       *points;
  ZnList        l;
  ZnGradient    **grads;
  
  tr->dev_points.num_strips = 0;

  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 1;
  tr->points = NULL;

  if (*argc < 1) {
    Tcl_AppendResult(wi->interp, " triangles coords expected", NULL);
    return TCL_ERROR;
  }
  if (ZnParseCoordList(wi, (*args)[0], &points,
                       NULL, &num_points, NULL) == TCL_ERROR) {
    return TCL_ERROR;
  }
  if (num_points < 3) {
    Tcl_AppendResult(wi->interp, " malformed triangles coords, need at least 3 points", NULL);
    return TCL_ERROR;
  }

  tr->points = ZnListNew(num_points, sizeof(ZnPoint));
  l = ZnListFromArray(points, num_points, sizeof(ZnPoint));
  ZnListAppend(tr->points, l);
  ZnListFree(l);
  (*args)++;
  (*argc)--;
 
  CLEAR(tr->flags, FAN_BIT);
  tr->colors = ZnListNew(1, sizeof(ZnGradient *));
  ZnListAssertSize(tr->colors, 1);
  grads = ZnListArray(tr->colors);
  *grads = ZnGetGradientByValue(wi->fore_color);
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  TrianglesItem tr = (TrianglesItem) item;

  if (tr->colors) {
    int         i, num_grads;
    ZnGradient  **grads;

    tr->colors = ZnListDuplicate(tr->colors);
    num_grads = ZnListSize(tr->colors);
    grads = ZnListArray(tr->colors);
    for (i = 0; i < num_grads; i++, grads++) {
      *grads = ZnGetGradientByValue(*grads);
    }
  }

  tr->dev_points.num_strips = 0;
  tr->points = ZnListDuplicate(tr->points);
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  TrianglesItem tr = (TrianglesItem) item;

  ZnListFree(tr->points);
  if (tr->dev_points.num_strips) {
    ZnFree(tr->dev_points.strips->points);
  }
  if (tr->colors) {
    int         i, num_grads;
    ZnGradient  **grads;

    num_grads = ZnListSize(tr->colors);
    grads = ZnListArray(tr->colors);
    for (i = 0; i < num_grads; i++, grads++) {
      ZnFreeGradient(*grads);
    }
    ZnListFree(tr->colors);
  }
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  int           status = TCL_OK;
  
  status = ZnConfigureAttributes(item->wi, item, item, tr_attrs, argc, argv, flags);

  return status;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, tr_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  TrianglesItem tr = (TrianglesItem) item;
  ZnPoint       *points;
  ZnPoint       *dev_points;
  unsigned int  num_points;
  
  ZnResetBBox(&item->item_bounding_box);

  points = (ZnPoint *) ZnListArray(tr->points);
  num_points = ZnListSize(tr->points);

  /*
   * Allocate space for devices coordinates
   */
  if (tr->dev_points.num_strips == 0) {
    dev_points = ZnMalloc(num_points * sizeof(ZnPoint));
  }
  else {
    dev_points = tr->dev_points.strips->points;
    if (tr->dev_points.strips->num_points < num_points) {
      dev_points = ZnRealloc(dev_points, num_points * sizeof(ZnPoint));
    }
  }
  ZnTriStrip1(&tr->dev_points, dev_points, num_points,
              ISSET(tr->flags, FAN_BIT));

  /*
   * Compute device coordinates.
   */
  ZnTransformPoints(wi->current_transfo, points, dev_points, num_points);

  /*
   * Compute the bounding box. 
   */
  ZnAddPointsToBBox(&item->item_bounding_box, dev_points, num_points);
  
  /*
   * Expand the bounding box by one pixel in all
   * directions to take care of rounding errors.
   */
  item->item_bounding_box.orig.x -= 1;
  item->item_bounding_box.orig.y -= 1;
  item->item_bounding_box.corner.x += 1;
  item->item_bounding_box.corner.y += 1;
}



/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  TrianglesItem tr = (TrianglesItem) item;
  ZnPoint       *points;
  unsigned int  i, num_points;
  int            result=-1, result2;
  ZnBBox        *area = ta->area;

  if (tr->dev_points.num_strips == 0) {
    return -1;
  }

  points = tr->dev_points.strips->points;
  num_points = tr->dev_points.strips->num_points;

  if (ISCLEAR(tr->flags, FAN_BIT)) {
    result = ZnPolygonInBBox(points, 3, area, NULL);
    if (result == 0) {
      return 0;
    }
    points++;
    for (i = 0; i < num_points-3; i++, points++) {
      result2 = ZnPolygonInBBox(points, 3, area, NULL);
      if (result2 != result) {
        return 0;
      }
    }
  }
  else {
    ZnPoint     tri[3];

    tri[0] = points[0];
    tri[1] = points[1];
    tri[2] = points[2];
    result = ZnPolygonInBBox(points, num_points, area, NULL);
    if (result == 0) {
      return 0;
    }
    points += 3;
    for (i = 0; i < num_points-3; i++, points++) {
      tri[1] = tri[2];
      tri[2] = *points;
      result2 = ZnPolygonInBBox(points, num_points, area, NULL);
      if (result2 != result) {
        return 0;
      }   
    }
  }

  return result;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  TrianglesItem tr = (TrianglesItem) item;
  unsigned int  i, num_points, last_color_index;
  ZnPoint       *points;
  ZnGradient    **grads;
  
  if (tr->dev_points.num_strips == 0) {
    return;
  }

  points = tr->dev_points.strips->points;
  num_points = tr->dev_points.strips->num_points;

  grads = ZnListArray(tr->colors);
  last_color_index = ZnListSize(tr->colors)-1;
  XSetFillStyle(wi->dpy, wi->gc, FillSolid);  
  
  if (ISCLEAR(tr->flags, FAN_BIT)) {
    XPoint      *xpoints;
    ZnListAssertSize(ZnWorkXPoints, num_points);
    xpoints = ZnListArray(ZnWorkXPoints);
    for (i = 0; i < num_points; i++) {
      xpoints[i].x = ZnNearestInt(points[i].x);
      xpoints[i].y = ZnNearestInt(points[i].y);
    }
    for (i = 0; i < num_points-2; i++, xpoints++) {
      if (i <= last_color_index) {
        XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(grads[i], 0.0));
      }
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, xpoints, 3,
#ifdef ConvexNoAA
                   ConvexNoAA,
#else
                   Convex,
#endif
                   CoordModeOrigin);
    }
  }
  else {
    XPoint      tri[3];

    tri[0].x = ZnNearestInt(points[0].x);
    tri[0].y = ZnNearestInt(points[0].y);
    tri[1].x = ZnNearestInt(points[1].x);
    tri[1].y = ZnNearestInt(points[1].y);
    tri[2].x = ZnNearestInt(points[2].x);
    tri[2].y = ZnNearestInt(points[2].y);
    points += 3;
    for (i = 0; i < num_points-2; i++, points++) {
      if (i <= last_color_index) {
        XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(grads[i], 0.0));
      }
      XFillPolygon(wi->dpy, wi->draw_buffer, wi->gc, tri, 3,
#ifdef ConvexNoAA
                   ConvexNoAA,
#else
                   Convex,
#endif
                   CoordModeOrigin);
      tri[1] = tri[2];
      tri[2].x = ZnNearestInt(points->x);
      tri[2].y = ZnNearestInt(points->y);
    }
  }
}


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
Render(ZnItem   item)
{
  ZnWInfo       *wi = item->wi;
  TrianglesItem tr = (TrianglesItem) item;
  int           i, num_points, last_color_index;
  ZnPoint       *points;
  ZnGradient    **grads;
  unsigned short alpha;
  XColor        *color;

  if (tr->dev_points.num_strips == 0) {
    return;
  }

  points = tr->dev_points.strips->points;
  num_points = tr->dev_points.strips->num_points;

  grads = ZnListArray(tr->colors);
  last_color_index = ZnListSize(tr->colors)-1;

  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  if (ISCLEAR(tr->flags, FAN_BIT)) {
    glBegin(GL_TRIANGLE_STRIP);
  }
  else {
    glBegin(GL_TRIANGLE_FAN);
  }

  for (i = 0; i < num_points; i++, points++) {
    if (i <= last_color_index) {
      color = ZnGetGradientColor(grads[i], 0.0, &alpha);
      alpha = ZnComposeAlpha(alpha, wi->alpha);
      glColor4us(color->red, color->green, color->blue, alpha);
    }
    glVertex2d(points->x, points->y);
  }
  glEnd();
}
#else
static void
Render(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  TrianglesItem tr = (TrianglesItem) item;
  double        dist=1.0e40, new_dist;
  ZnPoint       *points, *p = ps->point;
  int           i, num_points;

  if (tr->dev_points.num_strips == 0) {
    return dist;
  }
  
  points = tr->dev_points.strips->points;
  num_points = tr->dev_points.strips->num_points;

  if (ISCLEAR(tr->flags, FAN_BIT)) {
    for (i = 0; i < num_points-2; i++, points++) {
      new_dist = ZnPolygonToPointDist(points, 3, p);
      if (new_dist <= 0.0) {
        return 0.0;
      }
      if (new_dist < dist) {
        dist = new_dist;
      }
    }
  }
  else {
    ZnPoint     tri[3];

    tri[0] = points[0];
    tri[1] = points[1];
    tri[2] = points[2];
    for (i = 0; i < num_points-2; i++, points++) {
      new_dist = ZnPolygonToPointDist(tri, 3, p);
      if (new_dist <= 0.0) {
        return 0.0;
      }
      if (new_dist < dist) {
        dist = new_dist;
      }
      tri[1] = tri[2];
      tri[2] = *points;
    }
  }

  return dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ZnWInfo       *wi = item->wi;
  TrianglesItem tr = (TrianglesItem) item;
  ZnPoint       *points;
  int           i, num_points, last_color_index;
  int           edge;
  ZnGradient    **grads;
  XColor        *color = NULL;
  double        red, green, blue;
  ZnBBox        bbox;
  char          path[150];

  points = tr->dev_points.strips->points;
  num_points = tr->dev_points.strips->num_points;
  ZnResetBBox(&bbox);
  ZnAddPointsToBBox(&bbox, points, num_points);
  
  grads = ZnListArray(tr->colors);
  last_color_index = ZnListSize(tr->colors)-1;

  Tcl_AppendResult(wi->interp,
                   "/ShadingDict <<\n  /ShadingType 4\n  /ColorSpace /DeviceRGB\n",
                   "  /DataSource [", NULL);
  for (i = 0; i < num_points; i++) {
    if (i <= last_color_index) {
      color = ZnGetGradientColor(grads[i], 0.0, NULL);
    }
    if (i < 3) {
      edge = 0;
    }
    else if (ISCLEAR(tr->flags, FAN_BIT)) {
      edge = 1;
    }
    else {
      edge = 2;
    }
    red = ((double) (color->red >> 8)) / 255.0;
    green = ((double) (color->green >> 8)) / 255.0;
    blue = ((double) (color->blue >> 8)) / 255.0;

    sprintf(path, "%d %.15g %.15g %.4g %.4g %.4g ",
            edge, points[i].x, points[i].y, red, green, blue);
    Tcl_AppendResult(wi->interp, path, NULL);
  }
  Tcl_AppendResult(wi->interp, "]\n>> def\n", NULL);
  Tcl_AppendResult(wi->interp, "<<\n  /PatternType 2\n  /Shading ShadingDict\n>>\n", NULL);
  Tcl_AppendResult(wi->interp, "matrix identmatrix makepattern setpattern\n", NULL);
  sprintf(path, "%.15g %.15g %.15g %.15g rectfill\n", bbox.orig.x, bbox.orig.y,
          bbox.corner.x - bbox.orig.x, bbox.corner.y - bbox.orig.y);
  Tcl_AppendResult(wi->interp, path, NULL);

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  TrianglesItem tr = (TrianglesItem) item;

  if (tr->dev_points.num_strips == 0) {
    tristrip->num_strips = 0;
    return True;
  }

  ZnTriStrip1(tristrip, tr->dev_points.strips->points,
              tr->dev_points.strips->num_points,
              tr->dev_points.strips[0].fan);
  return False;
}


/*
 **********************************************************************************
 *
 * GetContours --
 *      Get the external contour(s).
 *      Never ever call ZnPolyFree on the poly returned by GetContours.
 *
 **********************************************************************************
 */
static ZnBool
GetContours(ZnItem      item,
           ZnPoly       *poly)
{
  TrianglesItem tr = (TrianglesItem) item;
  ZnPoint       *points;
  unsigned int  k, j, num_points;
  int           i;

  if (tr->dev_points.num_strips == 0) {
    poly->num_contours = 0;
    return True;
  }

  num_points = tr->dev_points.strips->num_points;

  if (ISCLEAR(tr->flags, FAN_BIT)) {
    ZnListAssertSize(ZnWorkPoints, num_points);
    points = ZnListArray(ZnWorkPoints);
    
    for (k = 1, j = 0; k < num_points; k += 2, j++) {
      points[j] = tr->dev_points.strips->points[k];
    }
    i = num_points - 1;
    if (num_points % 2 == 0) {
      i--;
    }
    for ( ; i >= 0; i -= 2, j++) {
      points[j] = tr->dev_points.strips->points[i];
    }
    ZnPolyContour1(poly, points, num_points, False);
  }
  else {
    ZnPolyContour1(poly, tr->dev_points.strips->points, num_points, False);
  }
  poly->contours[0].cw = !ZnTestCCW(poly->contours[0].points, poly->contours[0].num_points);
  poly->contours[0].controls = NULL;
  return False;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item vertices.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  TrianglesItem tr = (TrianglesItem) item;
  unsigned int  num_points, i;
  ZnPoint       *points;

  if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (cmd == ZN_COORDS_REPLACE_ALL) {
      ZnList    tmp;
      if (*num_pts == 0) {
        Tcl_AppendResult(item->wi->interp,
                         " coords command need at least 3 points on triangles", NULL);
        return TCL_ERROR;
      }
      tmp = ZnListFromArray(*pts, *num_pts, sizeof(ZnPoint));
      ZnListEmpty(tr->points);
      ZnListAppend(tr->points, tmp);
      ZnListFree(tmp);
    }
    else {
      if (*num_pts == 0) {
        Tcl_AppendResult(item->wi->interp,
                         " coords command need at least 1 point on triangles", NULL);
        return TCL_ERROR;
      }
      points = ZnListArray(tr->points);
      num_points = ZnListSize(tr->points);
      if (index < 0) {
        index += num_points;
      }
      if ((index < 0) || ((unsigned int) index >= num_points)) {
      range_err:
        Tcl_AppendResult(item->wi->interp, " coord index out of range", NULL);
        return TCL_ERROR;
      }
      points[index] = (*pts)[0];
    }
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    points = ZnListArray(tr->points);
    num_points = ZnListSize(tr->points);
    if (cmd == ZN_COORDS_READ_ALL) {
      *num_pts = num_points;
      *pts = points;
    }
    else {
      if (index < 0) {
        index += num_points;
      }
      if ((index < 0) || ((unsigned int)index >= num_points)) {
        goto range_err;
      }
      *num_pts = 1;
      *pts = &points[index];
    }
  }
  else if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST)) {
    if (cmd == ZN_COORDS_ADD) {
      num_points = ZnListSize(tr->points);
      if (index < 0) {
        index += num_points;
      }
      if ((index < 0) || ((unsigned int)index >= num_points)) {
        goto range_err;
      }
      for (i = 0; i < *num_pts; i++, index++) {
        ZnListAdd(tr->points, &(*pts)[i], (unsigned int) index);
      }
    }
    else {
      ZnList    tmp;
      tmp = ZnListFromArray(*pts, *num_pts, sizeof(ZnPoint));
      ZnListAppend(tr->points, tmp);
      ZnListFree(tmp);
    }
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if (cmd == ZN_COORDS_REMOVE) {
    if (ZnListSize(tr->points) < 4) {
      Tcl_AppendResult(item->wi->interp,
                       " triangles should keep at least 3 points", NULL);
      return TCL_ERROR;
    }
    points = ZnListArray(tr->points);
    num_points = ZnListSize(tr->points);
    if (index < 0) {
      index += num_points;
    }
    if ((index < 0) || ((unsigned int)index >= num_points)) {
      goto range_err;
    }
    ZnListDelete(tr->points, (unsigned int) index);
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * PickVertex --
 *      Return in 'vertex' the vertex closest to p and in 'o_vertex' the
 *      opposite vertex on the closest edge, if such an edge exists or -1
 *      in the other case.
 *
 **********************************************************************************
 */
static void
PickVertex(ZnItem       item,
           ZnPoint      *p,
           int          *contour,
           int          *vertex,
           int          *o_vertex)
{
  TrianglesItem tr = (TrianglesItem) item;
  int           i, k, num_points;
  ZnPoint       *points;
  ZnReal        dist=1.0e40, new_dist, dist2;

  *contour = *vertex = *o_vertex = -1;
  
  points = tr->dev_points.strips->points;
  num_points = tr->dev_points.strips->num_points;
  for (i = 0; i < num_points; i++) {
    new_dist = hypot(points[i].x - p->x, points[i].y - p->y);
    if (new_dist < dist) {
      dist = new_dist;
      *contour = 0;
      *vertex = i;
    }
  }
  /*
   * Update the opposite vertex.
   */
  i = (*vertex+1) % num_points;
  new_dist = ZnLineToPointDist(&points[*vertex], &points[i], p, NULL);
  k = ((unsigned)(*vertex-1)) % num_points;
  dist2 = ZnLineToPointDist(&points[*vertex], &points[k], p, NULL);
  if (dist2 < new_dist) {
    *o_vertex = k;
  }
  else {
    *o_vertex = i;
  }
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct TRIANGLES_ITEM_CLASS = {
  "triangles",
  sizeof(TrianglesItemStruct),
  tr_attrs,
  0,                    /* num_parts */
  0,                    /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,
  NULL,
  GetClipVertices,
  GetContours,
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  PickVertex,           /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnTriangles = (ZnItemClassId) &TRIANGLES_ITEM_CLASS;

Added jni/tkzinc/generic/Types.h.

























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
 * Types.h -- Some types and macros used by the Zinc widget.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Mon Feb  1 12:13:24 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _Types_h
#define _Types_h


#ifdef _WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h>
#  undef WIN32_LEAN_AND_MEAN
#  if defined(_MSC_VER)
#    define DllEntryPoint DllMain
#  endif
// Suppress complaints about deprecated standard C functions
// like strcpy and strcat
#  ifndef __GNUC__
#    pragma warning(disable : 4996)
#  endif
#endif

#ifdef GL
#  ifdef PLATFORM_SDL
#    ifdef __APPLE__
#     include <OpenGL/gl.h>
#    else
#     include <GL/gl.h>
#    endif
#  else
#    ifdef _WIN32
#      include <GL/gl.h>
#    else
#      ifdef MAC_OSX_TK
#        include <AGL/agl.h>
#        include <AGL/glu.h>
#      else
#        include <GL/glx.h>
#      endif
#    endif
#  endif
#endif

#define NEED_REAL_STDIO

#include <tk.h>
#include <tkInt.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef PTK
#  include <tkPort.h>
#  include <tkImgPhoto.h>
#  include <tkVMacro.h>
#  ifndef PTK_800
#    define Arg Tcl_Obj *
#  endif
#else
#  include <tkDecls.h>
#  include <tkIntDecls.h>
#endif
#include <stdio.h>


/* This EXTERN declaration is needed for Tcl < 8.0.3 */
#ifndef EXTERN
# ifdef __cplusplus
#  define EXTERN extern "C" TCL_STORAGE_CLASS
# else
#  define EXTERN extern TCL_STORAGE_CLASS
# endif
#endif


#ifdef __CPLUSPLUS__
extern "C" {
#endif


typedef double  ZnReal; /* Keep it a double for GL and Tcl. */
typedef int     ZnBool; /* Keep it an int to keep Tk happy */
typedef ZnReal  ZnPos;
typedef ZnReal  ZnDim;
typedef void    *ZnPtr;


#define ZnPixel(color)          ((color)->pixel)
#define ZnMalloc(size)          ((void *)ckalloc(size))
#define ZnFree(ptr)             (ckfree((char *)(ptr)))
#define ZnRealloc(ptr, size)    ((void *)ckrealloc((void *)(ptr), size))
#define ZnWarning(msg)          (fprintf(stderr, "%s", (msg)))
  
#define ZnUnspecifiedImage      None
#define ZnUnspecifiedColor      NULL

#ifndef TCL_INTEGER_SPACE
#  define TCL_INTEGER_SPACE     24
#endif

#ifdef PTK_800
/*
 * Macros for Tk8.4/perl/Tk utf compatibility
 */
#define Tcl_NumUtfChars(str, len) (((len)<0)?((int)strlen(str)):(len))
#define Tcl_UtfAtIndex(str, index) (&(str)[(index)])
#define Tcl_GetString(str) (Tcl_GetStringFromObj(str, NULL))

#define Tk_GetScrollInfoObj(interp, argc, args, fract, count) \
Tk_GetScrollInfo(interp, argc, (Tcl_Obj **) args, fract, count)
#endif

/*
 * Macros for Windows compatibility
 */
#if defined(_WIN32) && !defined(PLATFORM_SDL)
#  include <tkWinInt.h>
#  ifdef TCL_STORAGE_CLASS
#    undef TCL_STORAGE_CLASS
#  endif
#  ifdef BUILD_Tkzinc
#    define TCL_STORAGE_CLASS DLLEXPORT
#  else
#    define TCL_STORAGE_CLASS DLLIMPORT
#  endif

#  ifndef __GNUC__
// Okay, Those Xlib functions will bring inconsistancy errors
// as they are already provided by Tk portability layer, shut them up.
#  pragma warning(disable : 4273)
#  endif

#undef XFillRectangle
#define XFillRectangle ZnXFillRectangle
void XFillRectangle(Display *display, Drawable d, GC gc, int x, int y,
                    unsigned int width, unsigned int height);
#  undef XFillRectangles
#define XFillRectangles ZnXFillRectangles
void XFillRectangles(Display *display, Drawable d, GC gc,
                     XRectangle* rectangles, int nrectangles);
#  undef XFillArc
#define XFillArc ZnXFillArc
void XFillArc(Display *display, Drawable d, GC gc, int x, int y, unsigned int width,
              unsigned int height, int start, int extent);
#  undef XFillPolygon
#define XFillPolygon ZnXFillPolygon
void XFillPolygon(Display *display, Drawable d, GC gc, XPoint *points, int npoints,
                  int shape, int mode);
#  undef XDrawRectangle
#define XDrawRectangle ZnXDrawRectangle
void XDrawRectangle(Display *display, Drawable d, GC gc, int x, int y,
                    unsigned int width, unsigned int height);
#  undef XDrawArc
#define XDrawArc ZnXDrawArc
void XDrawArc(Display *display, Drawable d, GC gc, int x, int y,
              unsigned int width, unsigned int height, int start, int extent);
#  undef XDrawLine
#define XDrawLine ZnXDrawLine
void XDrawLine(Display *display, Drawable d, GC gc, int x1, int y1, int x2, int y2);
#  undef XDrawLines
#define XDrawLines ZnXDrawLines
void XDrawLines(Display *display, Drawable d, GC gc, XPoint* points,
                int npoints, int mode);

ZnBool ZnPointInRegion(TkRegion reg, int x, int y);
void ZnUnionRegion(TkRegion sra, TkRegion srb, 
                   TkRegion dr_return);
void ZnOffsetRegion(TkRegion reg, int dx, int dy);
TkRegion ZnPolygonRegion(XPoint *points, int n,
                         int fill_rule);
#  ifdef GL
#    define ZnGLContext HGLRC
#    define ZnGLWaitX()
#    define ZnGLWaitGL()
#    define ZN_GL_LINE_WIDTH_RANGE GL_LINE_WIDTH_RANGE
#    define ZN_GL_POINT_SIZE_RANGE GL_POINT_SIZE_RANGE
#  endif

#elif defined(MAC_OSX_TK)

ZnBool ZnPointInRegion(TkRegion reg, int x, int y);
void ZnUnionRegion(TkRegion sra, TkRegion srb, 
                   TkRegion dr_return);
void ZnOffsetRegion(TkRegion reg, int dx, int dy);
TkRegion ZnPolygonRegion(XPoint *points, int n,
                         int fill_rule);
#  ifdef GL
#    define ZnGLContext AGLContext
#    define ZnGLWaitX()
#    define ZnGLWaitGL()
#    define ZN_GL_LINE_WIDTH_RANGE GL_SMOOTH_LINE_WIDTH_RANGE
#    define ZN_GL_POINT_SIZE_RANGE GL_SMOOTH_POINT_SIZE_RANGE
#  endif

#else /* Other unices and X11 */

# ifdef _WIN32
#  ifdef TCL_STORAGE_CLASS
#    undef TCL_STORAGE_CLASS
#  endif
#  ifdef BUILD_Tkzinc
#    define TCL_STORAGE_CLASS DLLEXPORT
#  else
#    define TCL_STORAGE_CLASS DLLIMPORT
#  endif
# endif

#  define ZnPointInRegion(reg, x, y) \
  XPointInRegion((Region) reg, x, y)
#  define ZnPolygonRegion(points, npoints, fillrule) \
  ((TkRegion) XPolygonRegion(points, npoints, fillrule))
#  define ZnUnionRegion(sra, srb, rreturn) \
  XUnionRegion((Region) sra, (Region) srb, (Region) rreturn)
#  define ZnOffsetRegion(reg, dx, dy) \
  XOffsetRegion((Region) reg, dx, dy)
#  ifdef GL
#   ifdef PLATFORM_SDL
#    define ZnGLContext void *
#    define ZnGLWaitX()
#    define ZnGLWaitGL()
#   else
#    define ZnGLContext GLXContext
#    define ZnGLWaitX() glXWaitX()
#    define ZnGLWaitGL() glXWaitGL()
#   endif
#   ifdef _WIN32
#    define ZN_GL_LINE_WIDTH_RANGE GL_LINE_WIDTH_RANGE
#    define ZN_GL_POINT_SIZE_RANGE GL_POINT_SIZE_RANGE
#   else
#    define ZN_GL_LINE_WIDTH_RANGE GL_SMOOTH_LINE_WIDTH_RANGE
#    define ZN_GL_POINT_SIZE_RANGE GL_SMOOTH_POINT_SIZE_RANGE
#   endif
#  endif
#endif

#ifdef __CPLUSPLUS__
}
#endif

#endif /* _Types_h */

Added jni/tkzinc/generic/Viewport.c.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
/*
 * Viewport.c -- Implementation of viewport item.
 *
 * Authors              : Roland Tomczak.
 * Creation date        : Fri Dec  2 14:47:42 1994
 *
 * $Id$
 */

/*
 *  Copyright (c) 1994 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Doc : A Viewport item is an item, which rendering is performed by a Third-Party API.
 * The third-Party Library must respect the API defined by the RendererApi.h file, and
 * export the corresponding functions.
 * 
 * A Viewport item may be rendered in two way :
 *  - DirectAccess rendering : In this case, the Third-Party rendering function is directly 
 *    called during the "Rendering" process of the tree. This is the most efficient way, but
 *    has some limitation :
 *      - As OpenGl viewport can't be others than "straight" rectangle, the item will be rendered
 *        in its bounding box rect, and clipped so as it appears to its right position, inclucling
 *        possible transforms. So, if the Viewport is rotated, its content WONT be rotated, but will
 *        appear in the "clipped rotated" position defined.
 *
 *      - Rotations aren't taken in accound for the item count, so as Alpha value
 
 *      - The API MUST be very careful when manipulating stencil buffer, otherwhise its display may
 *        overlap its container, or affect the rendering of the following tree items. The current clipping 
 *        level is passed as an argument : When entering the API Rendering, if this clipping level is > 0, 
 *        the clipping test is configured as glStencilFunc(GL_EQUAL, (GLint) num_clips, 0xFF); You must 
 *        add/remove clipping levels with glStencilOp(GL_KEEP, GL_INCR, GL_INCR) and glStencilOp(GL_KEEP, 
 *        GL_DECR, GL_DECR); If the incoming clipping level is = 0, then GL_STENCIL_TEST is disabled.
 *      - The API process MUST be very careful when changing glViewport ! It is set so that the item appears
 *        to its right position onto TkZinc rendering.
 *    If the displayed item is bellow all the others, especially when its cover the entire background, the two last 
 *    limitations aren't to be take in account. So, DirectAccess is specially dedicated to background items.
 *  - Non DirectAccess rendering : Viewport is rendered onto a texture during a Pre-rendering phase, and then,
 *    is copied onto screen. It's less efficient, but don't have any constraint.
  */


#include "Item.h"
#include "Geo.h"
#include "Draw.h"
#include "Types.h"
#include "Image.h"
#include "Color.h"
#include "WidgetInfo.h"
#include "tkZinc.h"


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";

// Function prototypes definitions
typedef void    (*API_INITIALIZE_SIGNATURE)(int nID);
typedef void    (*API_RENDER_SIGNATURE)(int nID, int nClipLevel);
typedef char *  (*API_COMMAND_SIGNATURE)(int nID, const char * pchCommand );
typedef void    (*API_FINALIZE_SIGNATURE)(int nID);

/*
 * Bit offset of flags.
 */
#define ALIGNED_BIT     1

static int nNextViewportId = 0; 

/*
 **********************************************************************************
 *
 * Specific Viewport item record
 *
 **********************************************************************************
 */

typedef struct _ViewportItemStruct {
  ZnItemStruct  header;

  /* Public data */
  ZnPoint         coords[2];
  unsigned short  flags;

  char          * module_name;            // Viewport module name ( DLL or .so to be loaded )
  char          * command;                // Command to be send to module
  char          * command_result;         // Command result ( string )
    
  unsigned short  refresh;          // Set it to force display refresh
  unsigned short  directaccess;     // Direct Access or Memory access
  unsigned short  texture_width;    // Non direct Access texture Width
  unsigned short  texture_height;   // Non direct Access texture Height
  unsigned short  texture_opacity;  // Non direct Access texture opacity( 0..100 )


  /* Private data */
  ZnPoint       dev[4];
  char          cInitialized;     // 1 when initialized
  int           nViewportId;      // Our viewport ID
  unsigned int  nTextureId;       // Texture ID for non-direct Access
  int           nPrevTextureWidth;  // Non direct Access texture Width
  int           nPrevTextureHeight; // Non direct Access texture Height

  // External functions
  API_INITIALIZE_SIGNATURE  pApiInitializeFunc;
  API_RENDER_SIGNATURE      pApiRenderFunc;
  API_COMMAND_SIGNATURE     pApiCommandFunc;
  API_FINALIZE_SIGNATURE    pApiFinalizeFunc;

} ViewportItemStruct, *ViewportItem;


static ZnAttrConfig     viewport_attrs[] = {
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(ViewportItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(ViewportItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(ViewportItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(ViewportItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(ViewportItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(ViewportItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(ViewportItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(ViewportItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },

  { ZN_CONFIG_BOOL, "-refresh", NULL,
    Tk_Offset(ViewportItemStruct, refresh), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_SHORT, "-directaccess", NULL,
    Tk_Offset(ViewportItemStruct, directaccess), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_SHORT, "-texturewidth", NULL,
    Tk_Offset(ViewportItemStruct, texture_width), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_SHORT, "-textureheight", NULL,
    Tk_Offset(ViewportItemStruct, texture_height), 0, ZN_DRAW_FLAG, False }, 
  { ZN_CONFIG_SHORT, "-textureopacity", NULL,
    Tk_Offset(ViewportItemStruct, texture_opacity), 0, ZN_DRAW_FLAG, False },
  
  { ZN_CONFIG_STRING, "-modulename", NULL,
    Tk_Offset(ViewportItemStruct, module_name), 0, ZN_DRAW_FLAG, False },
  { ZN_CONFIG_STRING, "-command", NULL,
    Tk_Offset(ViewportItemStruct, command), 0, 0, False },
  { ZN_CONFIG_STRING, "-commandresult", NULL,
    Tk_Offset(ViewportItemStruct, command_result), 0, 0, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};



/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  ZnWInfo       *wi = item->wi;
  ViewportItem  rect = (ViewportItem) item;
  unsigned int  num_points;
  ZnPoint       *points;

  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT);
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 1;
  
  if (*argc < 1) {
    Tcl_AppendResult(wi->interp, " viewport coords expected", NULL);
    return TCL_ERROR;
  }
  if (ZnParseCoordList(wi, (*args)[0], &points,
                       NULL, &num_points, NULL) == TCL_ERROR) {
    return TCL_ERROR;
  }
  if (num_points != 2) {
    Tcl_AppendResult(wi->interp, " malformed viewport coords", NULL);
    return TCL_ERROR;
  };
  rect->coords[0] = points[0];
  rect->coords[1] = points[1];
  (*args)++;
  (*argc)--;

  rect->module_name     = NULL;
  rect->command         = NULL;
  rect->command_result  = NULL;

  rect->directaccess        = 0;

  
  rect->texture_width       = 128;
  rect->texture_height      = 128;
  rect->texture_opacity     = 100;

  // Initialize our internal attributes
  rect->cInitialized        = 0;
  rect->nViewportId         = nNextViewportId ++;
  rect->nTextureId          = 0;
  rect->nPrevTextureWidth   = 128;
  rect->nPrevTextureHeight  = 128;

  // API callbacks functions
  rect->pApiInitializeFunc  = NULL;
  rect->pApiRenderFunc      = NULL;
  rect->pApiCommandFunc     = NULL;
  rect->pApiFinalizeFunc    = NULL;
  
  // Increase number of viewport item
  wi->nb_of_viewport_items++;

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  ViewportItem  rect = (ViewportItem) item;
  ZnWInfo       *wi = item->wi;
  char        * str;

  // Set a new Id..
  rect->nViewportId = nNextViewportId ++;
  // .. and reset internal texture
  rect->nTextureId  = 0; 
  
  // Increase number of viewport item
  wi->nb_of_viewport_items++;

  // Copy our strings attributs
  if (rect->module_name) {
    str = ZnMalloc((strlen(rect->module_name) + 1) * sizeof(char));
    strcpy(str, rect->module_name);
    rect->module_name = str;
  }
  if (rect->command) {
    str = ZnMalloc((strlen(rect->command) + 1) * sizeof(char));
    strcpy(str, rect->command);
    rect->command = str;
  }
  if (rect->command_result) {
    str = ZnMalloc((strlen(rect->command_result) + 1) * sizeof(char));
    strcpy(str, rect->command_result);
    rect->command_result = str;
  }

  // .. Finally, initialize the viewport to the library
  if ( rect->pApiInitializeFunc != NULL )
  {
    rect->pApiInitializeFunc ( rect->nViewportId );
  }
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  ViewportItem rect = (ViewportItem) item;
  ZnWInfo       *wi = item->wi;

  // Decrease number of viewport item
  wi->nb_of_viewport_items--;

  rect->cInitialized = 0;

  if ( rect->nTextureId != 0 )
  {
    glDeleteTextures(1, &rect->nTextureId);
    rect->nTextureId = 0;
  }

  if (rect->module_name) 
  {
    ZnFree(rect->module_name);
  }
  if (rect->command) 
  {
    ZnFree(rect->command);
  }
  if (rect->command_result) 
  {
    ZnFree(rect->command_result);
  }
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  ZnWInfo       * wi = item->wi;
  ViewportItem    rect = (ViewportItem) item;
  int             status = TCL_OK;
  char *          pOldModuleName = rect->module_name;

  status = ZnConfigureAttributes(wi, item, item, viewport_attrs, argc, argv, flags);

  // If library name has changed, load callback functions or realease them
  if ( rect->module_name != pOldModuleName )
  {
    // Finalize our viewport for current module
    if ( rect->pApiFinalizeFunc != NULL )
    {
      rect->pApiFinalizeFunc ( rect->nViewportId );
    }

    // Release existing callbacks
    rect->pApiInitializeFunc  = NULL;
    rect->pApiRenderFunc      = NULL;
    rect->pApiCommandFunc     = NULL;
    rect->pApiFinalizeFunc    = NULL;  

    if ( rect->module_name )
    {

#ifdef _WIN32
      // There's a module name, let's load the librairie and recover function name
      char *  pchLibraryName [ 1024 ];
      HMODULE handle = NULL;

      strcpy ( pchLibraryName, rect->module_name );
      strcat ( pchLibraryName, ".dll" );

      handle = LoadLibrary (pchLibraryName);

      if (handle != NULL)
      {
        // printf ( "\nLibrary Loaded !");

        // The Librarie has been loaded : let's recover callback functions
        rect->pApiInitializeFunc  = ( API_INITIALIZE_SIGNATURE ) (GetProcAddress (handle, "apiInitialize" ));
        rect->pApiRenderFunc      = ( API_RENDER_SIGNATURE ) (GetProcAddress (handle, "apiRender" ));
        rect->pApiCommandFunc     = ( API_COMMAND_SIGNATURE ) (GetProcAddress (handle, "apiCommand" ));
        rect->pApiFinalizeFunc    = ( API_FINALIZE_SIGNATURE ) (GetProcAddress (handle, "apiFinalize" ));
      }
      else
      {
        // printf ( "\nLibrary Loading failed !!");
      }
#endif /* ifdef _WIN32 */

    }
  }

  // If a command needs to be executed, let's do it
  if ( rect->pApiCommandFunc != NULL )
  {
    if ( rect->command )
    {
      char * pchCommandResult = rect->pApiCommandFunc ( rect->nViewportId, rect->command );

      // Free requested command...
      ZnFree(rect->command);
      rect->command = NULL;

      // ..Clean the result..
      if (rect->command_result) 
      {
        ZnFree(rect->command_result);
        rect->command_result = NULL;
      }

      // ..And, eventually, retrieve the new result
      if ( pchCommandResult != NULL )
      {
        rect->command_result = ZnMalloc ( strlen ( pchCommandResult ) + 1 );
        strcpy(rect->command_result, pchCommandResult);
      }
    }
  }

  return status;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, viewport_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo       *wi = item->wi;
  ViewportItem  rect = (ViewportItem) item;
  ZnPoint       p[4];
  int           i;
  ZnBool        aligned;
  ZnDim         delta;
  
  ZnResetBBox(&item->item_bounding_box);

  p[0] = rect->coords[0];
  p[2] = rect->coords[1];
  p[1].x = p[2].x;
  p[1].y = p[0].y;
  p[3].x = p[0].x;
  p[3].y = p[2].y;
  ZnTransformPoints(wi->current_transfo, p, rect->dev, 4);
  for (i = 0; i < 4; i++) {
    rect->dev[i].x = ZnNearestInt(rect->dev[i].x);
    rect->dev[i].y = ZnNearestInt(rect->dev[i].y);
  }

  /*
   * Add all points to the bounding box. Then expand by the line
   * width to account for mitered corners. This is an overestimate.
   */
  ZnAddPointsToBBox(&item->item_bounding_box, rect->dev, 4);

  item->item_bounding_box.orig.x -= 0.5;
  item->item_bounding_box.orig.y -= 0.5;
  item->item_bounding_box.corner.x += 0.5;
  item->item_bounding_box.corner.y += 0.5;
  
  delta = rect->dev[0].y - rect->dev[1].y;
  delta = ABS(delta);
  aligned = delta < X_PRECISION_LIMIT;
  delta = rect->dev[0].x - rect->dev[3].x;
  delta = ABS(delta);
  aligned &= delta < X_PRECISION_LIMIT;
  ASSIGN(rect->flags, ALIGNED_BIT, aligned);
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  ViewportItem  rect = (ViewportItem) item;
  int           result;
  ZnBBox        *area = ta->area;

  result = -1;

  result = ZnPolygonInBBox(rect->dev, 4, area, NULL);
  if (result == 0) {
    return 0;
  }

  return result;
}


/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ViewportItem  rect = (ViewportItem) item;
  unsigned int  i;
  XRectangle    r;
  XPoint        xp[5];
  
  if (ISSET(rect->flags, ALIGNED_BIT)) {
    if (rect->dev[0].x < rect->dev[2].x) {
      r.x = (int) rect->dev[0].x;
      r.width = ((int) rect->dev[2].x) - r.x;
    }
    else {
      r.x = (int) rect->dev[2].x;
      r.width = ((int) rect->dev[0].x) - r.x;
    }
    if (rect->dev[0].y < rect->dev[2].y) {
      r.y = (int) rect->dev[0].y;
      r.height = ((int) rect->dev[2].y) - r.y;
    }
    else {
      r.y = (int) rect->dev[2].y;
      r.height = ((int) rect->dev[0].y) - r.y;
    }
  }
  else {
    for (i = 0; i < 4; i++) {
      xp[i].x = (int) rect->dev[i].x;
      xp[i].y = (int) rect->dev[i].y;
    }
    xp[i] = xp[0];
  }
  
  /* XDraw method have to be implemented */
}


/*
 **********************************************************************************
 *
 * PreRender --
 *
 **********************************************************************************
 */
 
#ifdef GL
static void
PreRender(ZnItem   item)
{
  ViewportItem    rect = (ViewportItem) item;

  // Initialize the Viewport when accessing for the first time
  if ( rect->cInitialized == 0 )
  {
    // Initialize our viewport
    if (  rect->pApiInitializeFunc != NULL )
    {
      rect->pApiInitializeFunc ( rect->nViewportId );
    }

    rect->cInitialized = 1;
  }

  // We only proceed if a Rendering function is defined
  if ( rect->pApiRenderFunc != NULL )
  {
    if ( rect->directaccess == 0 )
    {
      // Our texture is "non DirectAccess"

      // Clean up our texture if dimensions have changed
      if (  ( rect->texture_width != rect->nPrevTextureWidth )
        || ( rect->texture_height != rect->nPrevTextureHeight ) )
      {
        if ( rect->nTextureId != 0 )
        {
          glDeleteTextures(1, &rect->nTextureId);
          rect->nTextureId = 0;
        }
      }

      // If no texture is associated with our viewport ( or if we'd just destroy the current one ), let's create one
      // ( Thanks to http://www.cppfrance.com/codes/RENDU-SUR-TEXTURE-OPENGL-VCPLUSPLUS_11278.aspx )
      if ( rect->nTextureId == 0 )
      {
        // Create a new empty RGBA texture buffer
        unsigned int *pTextureBuffer = NULL;
   
        pTextureBuffer = ckalloc ( sizeof ( unsigned int ) * rect->texture_width * rect->texture_height * 4 );
        memset(pTextureBuffer, 0, rect->texture_width * rect->texture_height * 4 * sizeof(unsigned int));
   
        glGenTextures(1, &(rect->nTextureId));		  // Genere un nom de texture
        glBindTexture(GL_TEXTURE_2D, rect->nTextureId);	  // Active la texture que nous venons de generer
   
        // Definition of our 2D RGBA texture
        glTexImage2D(GL_TEXTURE_2D, 0, 4, rect->texture_width, rect->texture_height, 0, GL_RGBA, GL_UNSIGNED_INT, pTextureBuffer);
   
        // Texture processing parameters
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
      	
	// As the texture is stored onto OpenGL, no need to keep it in memory
        ckfree ( ( void * ) pTextureBuffer );

        // Let's save its dimension, if an user decide to change them ( in this case, it'll be regenerated )
        rect->nPrevTextureWidth = rect->texture_width;
        rect->nPrevTextureHeight = rect->texture_height;
      }

      // Now, render the Viewport onto this texture
      // Set our viewport on texture size
      if ( rect->nTextureId != 0 )
      {
        glViewport (  0, 0, rect->texture_width, rect->texture_height );

        rect->pApiRenderFunc ( rect->nViewportId,  0 );

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,rect->nTextureId);
		  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, rect->texture_width, rect->texture_height, 0);
        glDisable(GL_TEXTURE_2D);
      }
    }
    else
    {
      // Clean up our texture if any
      if ( rect->nTextureId != 0 )
      {
        glDeleteTextures(1, &rect->nTextureId);
        rect->nTextureId = 0;
      }
    }
  }
}

#else
static void
PreRender(ZnItem   item)
{
}
#endif


/*
 **********************************************************************************
 *
 * Render --
 *
 **********************************************************************************
 */
#ifdef GL
static void
ViewportRenderCB(void *closure)
{
  ViewportItem  rect = (ViewportItem) closure;
  ZnItem        item = (ZnItem) closure;

  // Proceed only if an rendering function has been found
  if ( rect->pApiRenderFunc != NULL )
  {
    if ( rect->directaccess == 1 )
    {
      // Window info. Needed because we've to retrieve its height, when changing
      // our viewport to set it on our object bounding box
      ZnWInfo *     wi  = item->wi;
      // Window height.
      int           int_height = Tk_Height(wi->win);
      // This point array will contain our viewport mask coordinates
      ZnPoint       *points;
      // This triangle strip will contain our specific viewport clipping zone.
      ZnTriStrip    tristrip;

      // Clip the region, so that only the viewport rect will be displayed
      // First of all, build our clipping triangle point list 
      ZnListAssertSize(ZnWorkPoints, 4);
      points = ZnListArray(ZnWorkPoints);
      points[0] = rect->dev[1];
      points[1] = rect->dev[2];
      points[2] = rect->dev[0];
      points[3] = rect->dev[3];
      ZnTriStrip1(&tristrip, points, 4, False);
      // Then, push this clipping level
      ZnPushClip(wi, &tristrip, False, True);

      // Store our global state : Push all rendering attributes...
      glPushAttrib (  GL_ACCUM_BUFFER_BIT
                    | GL_COLOR_BUFFER_BIT
                    | GL_CURRENT_BIT
                    | GL_DEPTH_BUFFER_BIT 
                    | GL_ENABLE_BIT
                    | GL_EVAL_BIT 
                    | GL_FOG_BIT 
                    | GL_HINT_BIT
                    | GL_LIGHTING_BIT
                    | GL_LINE_BIT
                    | GL_LIST_BIT
                    | GL_PIXEL_MODE_BIT
                    | GL_POINT_BIT
                    | GL_POLYGON_BIT
                    | GL_POLYGON_STIPPLE_BIT
                    | GL_SCISSOR_BIT
                    | GL_STENCIL_BUFFER_BIT
                    | GL_TEXTURE_BIT
                    | GL_TRANSFORM_BIT
                    | GL_VIEWPORT_BIT );

      // ... And the model transform matrix
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();

      // ... And the projection transform matrix
      glMatrixMode(GL_PROJECTION);
      glPushMatrix( );

      // Set our viewport on the whole object bounding box.
      glViewport ( ( GLint ) ( item->item_bounding_box.orig.x ),
                  ( GLint ) ( int_height - item->item_bounding_box.corner.y ),
                  ( GLsizei ) ( item->item_bounding_box.corner.x - item->item_bounding_box.orig.x ),
                  ( GLsizei ) ( item->item_bounding_box.corner.y - item->item_bounding_box.orig.y )
                );
   
      // ... And invoke our rendering function !
      rect->pApiRenderFunc ( rect->nViewportId,  ZnListSize(wi->clip_stack) );
      
      // ... Restore tje projection matrix
      glMatrixMode(GL_PROJECTION);
      glPopMatrix();

      // ... And the model transform matrix
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix();

      // ... Our attributs
      glPopAttrib ();
      
      // ... And stop clipping !
      ZnPopClip(wi, True);
    }
    else
    {
      // If Viewport is Non-DirectAccess, we just have to display prerendered
      // texture onto screen

      // Retrieve window information ( for alpha value )
      ZnWInfo *     wi  = item->wi;
      
      // Item is displayed only if our texture is available
      if ( rect->nTextureId != 0 )
      {
        unsigned short  alpha;

        alpha = ( float ) rect->texture_opacity;     
        alpha = ZnComposeAlpha(alpha, wi->alpha);

        // .. Prepare OGL for texture drawing...
        glEnable(GL_TEXTURE_2D);  
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, rect->nTextureId );
      
        glColor4us(65535, 65535, 65535, alpha);

        // ... and display our quad !!!
        glBegin(GL_QUADS);
  		  glTexCoord2f(  0, 1);
			  glVertex2d(rect->dev[0].x, rect->dev[0].y);
        glTexCoord2f(  1,  1);
			  glVertex2d(rect->dev[1].x, rect->dev[1].y);
        glTexCoord2f( 1,   0);
			  glVertex2d(rect->dev[2].x, rect->dev[2].y);
        glTexCoord2f( 0, 0);
        glVertex2d(rect->dev[3].x, rect->dev[3].y);
        glEnd();
        glDisable(GL_TEXTURE_2D);  
      }
    }
  }
}
#endif



#ifdef GL
static void
Render(ZnItem   item)
{
  ViewportItem    rect = (ViewportItem) item;

#ifdef GL_LIST
  if (!item->gl_list) {
    item->gl_list = glGenLists(1);
    glNewList(item->gl_list, GL_COMPILE);
#endif
    
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    
    // Viewport Item rendering callback
    ViewportRenderCB(rect);
    
#ifdef GL_LIST    
    glEndList();
  }
  
  glCallList(item->gl_list);
#endif
}
#else
static void
Render(ZnItem   item)
{
}
#endif
 

/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  return (ISSET(item->flags, ZN_SENSITIVE_BIT) &&
          item->parent->class->IsSensitive(item->parent, ZN_NO_PART));
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  ViewportItem rect = (ViewportItem) item;
  double        best_dist;
  ZnPoint       *p = ps->point;

  best_dist = ZnPolygonToPointDist(rect->dev, 4, p);

  if (best_dist <= 0.0) {
    return 0.0;
  }
    
  best_dist = ABS(best_dist);
  
  return best_dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ZnWInfo       *wi = item->wi;
  ViewportItem  rect = (ViewportItem) item;
  char          path[500];

  /*
   * Create the viewport rectangle path...
   */
  sprintf(path, "%.15g %.15g moveto %.15g %.15g lineto %.15g %.15g lineto %.15g %.15g lineto closepath\n",
          rect->dev[0].x, rect->dev[0].y, rect->dev[1].x, rect->dev[1].y,
          rect->dev[2].x, rect->dev[2].y, rect->dev[3].x, rect->dev[3].y);
  Tcl_AppendResult(wi->interp, path, NULL);

  /*
   * And emit code code to stroke the outline... Viewport content won't be displayed, only the rectangle area
   */
  /*
  Tcl_AppendResult(wi->interp, "0 setlinejoin 2 setlinecap\n", NULL);
  if (ZnPostscriptOutline(wi->interp, wi->ps_info, wi->win,
                          rect->line_width, rect->line_style,
                          rect->line_color, rect->line_pattern) != TCL_OK) {
    return TCL_ERROR;
  }
  */
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *      Never ever call ZnTriFree on the tristrip returned by GetClipVertices.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  ViewportItem  rect = (ViewportItem) item;
  ZnPoint       *points;

  if (ISSET(rect->flags, ALIGNED_BIT)) {
    ZnListAssertSize(ZnWorkPoints, 2);
    points = ZnListArray(ZnWorkPoints);
    ZnTriStrip1(tristrip, points, 2, False);
    tristrip->strips[0].fan = False;
  
    if (rect->dev[0].x < rect->dev[2].x) {
      points[0].x = rect->dev[0].x;
      points[1].x = rect->dev[2].x+1.0;
    }
    else {
      points[0].x = rect->dev[2].x;
      points[1].x = rect->dev[0].x+1.0;
    }
    if (rect->dev[0].y < rect->dev[2].y) {
      points[0].y = rect->dev[0].y;
      points[1].y = rect->dev[2].y+1.0;
    }
    else {
      points[0].y = rect->dev[2].y;
      points[1].y = rect->dev[0].y+1.0;
    }
  }
  else {
    ZnListAssertSize(ZnWorkPoints, 4);
    points = ZnListArray(ZnWorkPoints);
    points[0] = rect->dev[1];
    points[1] = rect->dev[2];
    points[2] = rect->dev[0];
    points[3] = rect->dev[3];
    ZnTriStrip1(tristrip, points, 4, False);
  }

  return ISSET(rect->flags, ALIGNED_BIT);
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item vertices.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  ViewportItem rect = (ViewportItem) item;

  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp, " viewports can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if (cmd == ZN_COORDS_REPLACE_ALL) {
    if (*num_pts != 2) {
      Tcl_AppendResult(item->wi->interp, " coords command need 2 points on viewports", NULL);
      return TCL_ERROR;
    }
    rect->coords[0] = (*pts)[0];
    rect->coords[1] = (*pts)[1];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if (cmd == ZN_COORDS_REPLACE) {
    if (*num_pts < 1) {
      Tcl_AppendResult(item->wi->interp, " coords command need at least 1 point", NULL);
      return TCL_ERROR;
    }
    if (index < 0) {
      index += 2;
    }
    if ((index < 0) || (index > 1)) {
    range_err:
      Tcl_AppendResult(item->wi->interp," incorrect coord index, should be between -2 and 1", NULL);
      return TCL_ERROR;
    }
    rect->coords[index] = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if (cmd == ZN_COORDS_READ_ALL) {
    *num_pts = 2;
    *pts = rect->coords;
  }
  else if (cmd == ZN_COORDS_READ) {
    if (index < 0) {
      index += 2;
    }
    if ((index < 0) || (index > 1)) {
      goto range_err;
    }
    *num_pts = 1;
    *pts = &rect->coords[index];
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  ZnBBox *bbox = &item->item_bounding_box;

  ZnOrigin2Anchor(&bbox->orig,
                  bbox->corner.x - bbox->orig.x,
                  bbox->corner.y - bbox->orig.y,
                  anchor, p);
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */ 
static CONST ZnItemClassStruct VIEWPORT_ITEM_CLASS = {
  "viewport",
  sizeof(ViewportItemStruct),
  viewport_attrs,
  0,                    /* num_parts */
  0,                    /* flags */
  -1,
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  GetClipVertices,
  NULL,                 /* GetContours */
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  PreRender,            /* Pre-render */
  Render,
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnViewport = (ZnItemClassId) &VIEWPORT_ITEM_CLASS;

Added jni/tkzinc/generic/WidgetInfo.h.







































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/*
 * WidgetInfo.h -- Zinc Widget record.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Mon Feb  1 12:13:24 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _WidgetInfo_h
#define _WidgetInfo_h


#include "Item.h"
#include "Transfo.h"
#include "Types.h"
#ifndef _WIN32
#include "perfos.h"
#endif
#include "Color.h"


#define ZN_NUM_ALPHA_STEPS      16

/*
 * Constants for flags
 */
#define ZN_REPICK_IN_PROGRESS   (1<<0)
#define ZN_GRABBED_ITEM         (1<<1)
#define ZN_GRABBED_PART         (1<<2)
#define ZN_REALIZED             (1<<3)
#define ZN_INTERNAL_NEED_REPICK (1<<4)
#define ZN_UPDATE_SCROLLBARS    (1<<5)  /* If set, the scrollbars must be updated. */
#define ZN_GOT_FOCUS            (1<<6)  /* Set means that the widget has the input focus. */
#define ZN_UPDATE_PENDING       (1<<7)  /* Set means there is a pending graphic update. */
#define ZN_HAS_GL               (1<<8)  /* Tell if openGL can be used. */
#define ZN_HAS_X_SHAPE          (1<<9)  /* Tell if the X shape extension is available. */
#define ZN_MONITORING           (1<<10) /* Set if performance monitoring is on. */
#define ZN_PRINT_CONFIG         (1<<11) /* If set the openGL hardware configuration
                                         * is printed on startup. */
#define ZN_CONFIGURE_EVENT      (1<<12)
#define ZN_UPDATE_CANVASTEX     (1<<13)

#ifdef __CPLUSPLUS__
extern "C" {
#endif


/*
 * The following structure provides information about the selection and
 * the insertion cursor.  It is needed by only a few items, such as
 * those that display text.  It is shared by the generic canvas code
 * and the item-specific code, but most of the fields should be written
 * only by the canvas generic code.
 */
typedef struct _ZnTextInfo {
  ZnGradient    *sel_color;     /* Background color for selected text.
                                 * Read-only to items.*/
  ZnItem        sel_item;       /* Pointer to selected item. ZN_NO_ITEM
                                 * means that the widget doesn't own the
                                 * selection. Writable by items. */
  int           sel_field;
  int           sel_first;      /* Index of first selected character. 
                                 * Writable by items. */
  int           sel_last;       /* Index of last selected character. 
                                 * Writable by items. */
  ZnItem        anchor_item;    /* Item corresponding to sel_anchor: not
                                 * necessarily sel_item. Read-only to items. */
  int           anchor_field;
  int           sel_anchor;     /* Fixed end of selection (i.e. "select to"
                                 * operation will use this as one end of the
                                 * selection).  Writable by items. */
  ZnGradient    *insert_color;  /* Used to draw vertical bar for insertion
                                 * cursor.  Read-only to items. */
  unsigned int  insert_width;   /* Total width of insertion cursor.  Read-only
                                 * to items. */
  ZnBool        cursor_on;      /* True means that an insertion cursor should
                                 * be displayed in focus_item. Read-only to
                                 * items.*/
} ZnTextInfo;

typedef struct _ZnWInfo {
  Tcl_Interp            *interp;        /* Interpreter associated with widget.  */
  Tcl_Command           cmd;            /* Token for zinc widget command.       */
  Tcl_HashTable         *id_table;      /* Hash table for object ids.           */
  Tcl_HashTable         *t_table;       /* Hash table for transformations.      */
  unsigned long         obj_id;         /* Id for the next new object.          */
  int                   flags;
  Tk_BindingTable       binding_table;  /* Table of all bindings currently defined
                                         * for this widget.  NULL means that no
                                         * bindings exist, so the table hasn't been
                                         * created.  Each "object" used for this
                                         * table is either a Tk_Uid for a tag or
                                         * the address of an item named by id.  */
  int                   state;          /* Last known modifier state.  Used to
                                         * defer picking a new current object
                                         * while buttons are down. */
  ZnItem                current_item;   /* Item picked from previous pick sequence */
  ZnItem                new_item;       /* Item picked from current pick sequence */
  int                   current_part;
  int                   new_part;
  ZnItem                hot_item;
  ZnItem                hot_prev;
  ZnItem                focus_item;     /* Item that currently has the input focus,
                                         * or ZN_NO_ITEM if no such item.  Read-only to
                                         * items.  */
  int                   focus_field;
  XEvent                pick_event;     /* Event used to forge fake events and to do
                                         * repicks. */
  ZnBBox                exposed_area;   /* Window area that need to be rexposed.
                                         * It is distinct from redraw_area which
                                         * is updated when items are changed. */
  Pixmap                alpha_stipples[ZN_NUM_ALPHA_STEPS];
  int                   border_width;
#if defined(GL) && defined(ROTATION)
  double                screen_rotation;
  unsigned int          enable_rotation;
  ZnTransfo             rotation_transfo;
#endif
  int                   opt_width;      /* Window size as stated/reported by the option. */
  int                   opt_height;     /* They are equal to the width/height fields after
                                         * the actual resize. They may to be equal if
                                         * the resize is not acknowledged by the geo
                                         * manager. */
  ZnGradient            *relief_grad;   /* The gradient describing the border relief
                                         * colors. */
  ZnReliefStyle         relief;         /* The border relief. */
  
  /* Tracks global resources    */
#ifdef ATC
  unsigned int          track_managed_history_size;     /* Size of history for tracks   */
  unsigned int          track_visible_history_size;     /* Size of displayed history    */
  ZnReal                speed_vector_length; /* How long (in time) are speedvectors*/
  int                   om_group_id;    /* Tell which group contains tracks to be       */
  ZnItem                om_group;       /* processed for anti label overlap.            */

  /* Maps global resources */
  Tk_Font               map_text_font;          /* Font for texts in Map items          */
#ifdef GL
  ZnTexFontInfo         map_font_tfi;           /* Used to preserve the default font from
                                                 * being freed again and again */
#endif
  Tcl_Obj               *map_symbol_obj;
  ZnImage               map_distance_symbol;    /* Distance marks displayed along Map   */
                                                /* lines.                               */
  Tcl_Obj               *track_symbol_obj;
  ZnImage               track_symbol;           /* Symbol displayed at track/wp current */
                                                /* position.                            */
#endif
  /* Transformer */
  ZnTransfo             *current_transfo;
  ZnList                transfo_stack;
  struct _ClipState     *current_clip;
  ZnList                clip_stack;
  
  /* Others */
  ZnGradient            *fore_color;            /* Default gradient used in new items   */
  ZnGradient            *back_color;            /* Color of the widget background.      */
  ZnGradient            *bbox_color;            /* Color used to draw bboxes (debug).   */
  Tk_Cursor             cursor;                 /* Cursor displayed in zinc window.     */
  ZnBool                draw_bboxes;            /* Draw item's bboxes (debug).          */
  ZnBool                follow_pointer;         /* Process pointer motion events to     */
                                                /* emit enter/leave events.             */
  int                   light_angle;
  
  int                   pick_aperture;          /* size of pick aperture in pixels      */
  Tk_Font               font;                   /* Default font used in new items */
#ifdef GL
  ZnTexFontInfo         font_tfi;               /* Used to preserve the default font from
                                                 * being freed again and again */
#endif

#if defined(GL) && defined(PLATFORM_SDL)
  struct _ZnGLContextEntry *ce;
#endif

  Tcl_Obj               *tile_obj;
  ZnImage               tile;
  
  /* Zinc private resources */
  int                   width;                  /* Actual window dimension. */
  int                   height;
  int                   inset;                  /* Border and highlight width */
#if defined(GL) && defined(ROTATION)
  int                   canvastex;              /* The intermediate canvas texture */
  int                   fbo;
  int                   depthstencil;
  ZnPoint               texcoords[4];
#endif

  /* Graphic variables */
  Display               *dpy;                   /* The display of the widget window.    */
  Screen                *screen;
  Tk_Window             win;                    /* The window of the widget. */
  Pixmap                draw_buffer;            /* Pixmap for double buffering          */
  ZnBBox                damaged_area;           /* The current damaged rectangle        */
  GC                    gc;
  ZnBool                reshape;                /* Use the Shape Extension on the window.*/
  ZnBool                full_reshape;           /* Use it on the top level window.      */
  Window                real_top;
  int                   render;
  int                usedamage;              /* Use GL damage (only works if render is to 1 ie if we use GL) */ 
  unsigned char         alpha;                  /* Current composite group alpha. */
  ZnItem                top_group;
#ifndef PTK_800
  Tk_OptionTable        opt_table;
#endif

  /* Text management */
  ZnTextInfo            text_info;
  int                   insert_on_time;
  int                   insert_off_time;
  Tcl_TimerToken        blink_handler;
  char                  *take_focus;
  int                   highlight_width;        /* Width in pixels of highlight to draw
                                                 * around widget when it has the focus.
                                                 * = 0 means don't draw a highlight. */
  ZnGradient            *highlight_bg_color;    /* Color for drawing traversal highlight
                                                 * area when highlight is off. */
  ZnGradient            *highlight_color;       /* Color for drawing traversal highlight.*/
  
  /* viewport item management */
  int                   nb_of_viewport_items;   /* Number of viewport items in our tree */
  
  /* Scrollbar management */
  ZnPoint               origin;                 /* Coordinate mapped to the upper left corner
                                                 * of the zinc window. */
#ifdef PTK
  LangCallback          *x_scroll_cmd;
  LangCallback          *y_scroll_cmd;
#else
  Tcl_Obj               *x_scroll_cmd;          /* Command prefixes for communicating with */
  Tcl_Obj               *y_scroll_cmd;          /* scrollbars.  NULL means no scrollbar.
                                                 * Malloc'ed */
#endif
  int                   x_scroll_incr;          /* If >0, defines a grid for horiz/vert */
  int                   y_scroll_incr;          /* scrolling.  This is the size of the "unit",
                                                 * and the left edge of the screen will always
                                                 * lie on an even unit boundary. */
  int                   scroll_xo;              /* This bbox define the region that is the */
  int                   scroll_yo;              /* 100% area for scrolling (i.e. it determines */
  int                   scroll_xc;              /* the size and location of the sliders on */
  int                   scroll_yc;              /* scrollbars). */
  ZnBool                confine;                /* When true, it is not possible to scroll the
                                                 * viewing area past the scroll region. */
  Tcl_Obj               *region;                /* Scroll region option string source of the
                                                 * scroll_region above. */
  Tk_PostscriptInfo     ps_info;

  /* Perf measurement variables. */
#ifndef _WIN32
  ZnChrono              this_draw_chrono;
  ZnChrono              total_draw_chrono;
#endif
  int                   num_items;
  int                   damaged_area_w;
  int                   damaged_area_h;
  int                   debug;
} ZnWInfo;

  
#ifdef __CPLUSPLUS__
}
#endif

#endif /* _WidgetInfo_h */

Added jni/tkzinc/generic/Window.c.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
/*
 * Window.c -- Implementation of Window item.
 *
 * Authors              : Patrick LECOANET
 * Creation date        : Fri May 12 11:25:53 2000
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#include "Item.h"
#include "Geo.h"
#include "Types.h"
#include "WidgetInfo.h"
#include "tkZinc.h"

#include <stdio.h>
#include "WindowUtils.h"

/* We need to include tkPlatDecls to use Tk_GetHWND */
#if defined(_WIN32) && defined(PTK) && !defined(PTK_800)
#include <tkPlatDecls.m>
#endif


static const char rcsid[] = "$Id$";
static const char compile_id[] = "$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";

/*
 **********************************************************************************
 *
 * Specific Window item record
 *
 **********************************************************************************
 */
typedef struct _WindowItemStruct {
  ZnItemStruct  header;

  /* Public data */
  ZnPoint       pos;
  Tk_Anchor     anchor;
  Tk_Anchor     connection_anchor;
  Tk_Window     win;
  int           width;
  int           height;
  char         *windowtitle;
  
  /* Private data */
  ZnPoint       pos_dev;
  int           real_width;
  int           real_height;
  
#ifdef _WIN32
   HWND        externalwindow;
   LONG        externalwindowstyle;
#else
   Window      externalwindow;
#endif /* ifdef _WIN32 */
  
} WindowItemStruct, *WindowItem;


static ZnAttrConfig     wind_attrs[] = {
  { ZN_CONFIG_ANCHOR, "-anchor", NULL,
    Tk_Offset(WindowItemStruct, anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-catchevent", NULL,
    Tk_Offset(WindowItemStruct, header.flags), ZN_CATCH_EVENT_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-composealpha", NULL,
    Tk_Offset(WindowItemStruct, header.flags), ZN_COMPOSE_ALPHA_BIT,
    ZN_DRAW_FLAG, False },
  { ZN_CONFIG_BOOL, "-composerotation", NULL,
    Tk_Offset(WindowItemStruct, header.flags), ZN_COMPOSE_ROTATION_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_BOOL, "-composescale", NULL,
    Tk_Offset(WindowItemStruct, header.flags), ZN_COMPOSE_SCALE_BIT,
    ZN_COORDS_FLAG, False },
  { ZN_CONFIG_ITEM, "-connecteditem", NULL,
    Tk_Offset(WindowItemStruct, header.connected_item), 0,
    ZN_COORDS_FLAG|ZN_ITEM_FLAG, False },
  { ZN_CONFIG_ANCHOR, "-connectionanchor", NULL,
    Tk_Offset(WindowItemStruct, connection_anchor), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_INT, "-height", NULL,
    Tk_Offset(WindowItemStruct, height), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_POINT, "-position", NULL, Tk_Offset(WindowItemStruct, pos), 0,
    ZN_COORDS_FLAG, False},
  { ZN_CONFIG_PRI, "-priority", NULL,
    Tk_Offset(WindowItemStruct, header.priority), 0,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG, False },
  { ZN_CONFIG_BOOL, "-sensitive", NULL,
    Tk_Offset(WindowItemStruct, header.flags), ZN_SENSITIVE_BIT,
    ZN_REPICK_FLAG, False },
  { ZN_CONFIG_TAG_LIST, "-tags", NULL,
    Tk_Offset(WindowItemStruct, header.tags), 0, 0, False },
  { ZN_CONFIG_BOOL, "-visible", NULL,
    Tk_Offset(WindowItemStruct, header.flags), ZN_VISIBLE_BIT,
    ZN_DRAW_FLAG|ZN_REPICK_FLAG|ZN_VIS_FLAG, False },
  { ZN_CONFIG_INT, "-width", NULL,
    Tk_Offset(WindowItemStruct, width), 0, ZN_COORDS_FLAG, False },
  { ZN_CONFIG_WINDOW, "-window", NULL,
    Tk_Offset(WindowItemStruct, win), 0,
    ZN_COORDS_FLAG|ZN_WINDOW_FLAG, False },
  { ZN_CONFIG_STRING, "-windowtitle", NULL,
    Tk_Offset(WindowItemStruct, windowtitle), 0,
    ZN_COORDS_FLAG|ZN_WINDOW_FLAG, False },
  
  { ZN_CONFIG_END, NULL, NULL, 0, 0, 0, False }
};


/*
 **********************************************************************************
 *
 * WindowDeleted --
 *
 *      Do the bookeeping after a managed window deletion.
 *
 **********************************************************************************
 */
static void
WindowDeleted(ClientData        client_data,
              XEvent            *event)
{
  WindowItem wind = (WindowItem) client_data;

  if (event->type == DestroyNotify) {
    wind->win = NULL;
  }
}


/*
 **********************************************************************************
 *
 * Window item geometry manager --
 *
 **********************************************************************************
 */


/*
 * A managed window changes requested dimensions.
 */
static void
WindowItemRequest(ClientData    client_data,
                  Tk_Window     win)
{
  WindowItem wind = (WindowItem) client_data;

  ZnITEM.Invalidate((ZnItem) wind, ZN_COORDS_FLAG);
}

/*
 * A managed window turns control over
 * to another geometry manager.
 */
static void
WindowItemLostSlave(ClientData  client_data,
                    Tk_Window   win)
{
  WindowItem wind = (WindowItem) client_data;
  ZnWInfo *wi = ((ZnItem) wind)->wi;
  
  Tk_DeleteEventHandler(wi->win, StructureNotifyMask, WindowDeleted,
                        (ClientData) wind);
  if (wi->win != Tk_Parent(wind->win)) {
    Tk_UnmaintainGeometry(wind->win, wi->win);
  }
  Tk_UnmapWindow(wind->win);
  wind->win = NULL;
}

static Tk_GeomMgr wind_geom_type = {
    "zincwindow",               /* name */
    WindowItemRequest,          /* requestProc */
    WindowItemLostSlave,        /* lostSlaveProc */
};



/*
 **********************************************************************************
 *
 * Manage external Window -- Reparent, Unparent, Resize
 *
 **********************************************************************************
 */

#ifndef PLATFORM_SDL
/*
 * Create a Tk_Window
 */
static int WINDOW_PRIVATE_TK_WINDOW_COUNTER = 0;
 
static void
WindowCreateTkWindow(ZnItem item)
{
    ZnWInfo    *wi = item->wi;
    WindowItem wind = (WindowItem) item;
    char buffer[32];
     
    if (wind->win == 0) {
      /* create a unique name */
      sprintf(buffer, "_private_tkwindow_%d", WINDOW_PRIVATE_TK_WINDOW_COUNTER);
      WINDOW_PRIVATE_TK_WINDOW_COUNTER++;
     
      /* create a new Tk_Window */
      wind->win = Tk_CreateWindow(wi->interp, wi->win, buffer, NULL);
    }
}
#endif
 
 /*
 * Resize an external window
 */
static void
WindowResizeExternalWindow(ZnItem item, int width, int height)
{
    ZnWInfo    *wi = item->wi;
    WindowItem wind = (WindowItem) item;
    
    /* Our window (wi->win) must exists before doing anything */
    Tk_MakeWindowExist(wi->win);
    Tk_MakeWindowExist(wind->win);
    
#ifdef _WIN32
    /* Resize our external window if needed */
    if (wind->externalwindow != 0) {
      MoveWindow(wind->externalwindow, 0, 0, width, height, TRUE);
    }

#else
    /* Resize our external window if needed */
    if (wind->externalwindow != 0) {
      XResizeWindow(wi->dpy, wind->externalwindow, width, height);
      XFlush(wi->dpy); 
    }

#endif /* ifdef _WIN32 */
}


/*
 * Reparent/capture an external window
 */
static void
WindowCaptureExternalWindow(ZnItem item)
{
#if defined(_WIN32) && !defined(PLATFORM_SDL)

    ZnWInfo    *wi = item->wi;
    WindowItem wind = (WindowItem) item;

   /* Try to find a window matching windowtitle */
   HWND externalWindow = SearchWindowByTitle(wind->windowtitle, wi->dpy, NULL, 0);
   
   /* Test if we can reparent our window */
   if ((externalWindow != 0) && (wi->win != 0)) {
      /* Save external window */
      wind->externalwindow = externalWindow;
      
      /* Test if we must create a window */
      if (wind->win == NULL) {
         /* Create a new window */
         WindowCreateTkWindow(item);
      }
      
      /* Our window must exists before we try to reparent an external window */
      Tk_MakeWindowExist(wi->win);
      Tk_MakeWindowExist(wind->win);
      
      /* remove window decoration */
      wind->externalwindowstyle = removeWindowDecoration(externalWindow);
      ShowWindow(externalWindow, SW_SHOW);
            
      /* Reparent our external window */
      SetParent(externalWindow, Tk_GetHWND(Tk_WindowId(wind->win)));
      ShowWindow(externalWindow, SW_SHOW);
      
      /* Windows only: we must resize our external window */
      WindowResizeExternalWindow(item, wind->real_width, wind->real_height);
   }

#elif !defined(PLATFORM_SDL)
   /* Try to find a window matching windowtitle */
   Window externalWindow = SearchWindowByTitle(wind->windowtitle, wi->dpy, RootWindowOfScreen(wi->screen), 0);

   /* Test if we can reparent our window */
   if ((externalWindow != 0) && (wi->win != 0)) {
      /* Save external window */
      wind->externalwindow = externalWindow;
   
      /* Test if we must create a window */
      if (wind->win == NULL) {
         /* Create a new window */
         WindowCreateTkWindow(item);
      }
      
      /* Our window must exists before we try to reparent an external window */
      Tk_MakeWindowExist(wi->win);
      Tk_MakeWindowExist(wind->win);
   
      /* Withdraw our external window from desktop */
      withdrawWindowFromDesktop (wi->dpy, externalWindow, Tk_ScreenNumber(wi->win));
      
      /* Reparent our external window */
      XAddToSaveSet (wi->dpy, externalWindow);
      XReparentWindow(wi->dpy, externalWindow, Tk_WindowId(wind->win), 0, 0);
      XMapWindow(wi->dpy, externalWindow);
      XFlush(wi->dpy);
   }

#endif /* ifdef _WIN32 */
}


/*
 * Unparent/release an external window
 */
static void
WindowReleaseExternalWindow(ZnItem item)
{
    WindowItem wind = (WindowItem) item;
    
#ifdef _WIN32
   /* Test if we must release an external window */
   if (wind->externalwindow != 0) {   
       /* restore window style */
       restoreWindowStyle(wind->externalwindow, wind->externalwindowstyle);	   
	   wind->externalwindowstyle = 0;
       
       /* Reparent our external window (new parent is the main root window) */
       SetParent(wind->externalwindow, NULL);
   }

#elif !defined(PLATFORM_SDL)
   /* Test if we must release an external window */
   if (wind->externalwindow != 0) {
       /* Reparent our external window (new parent is the main root window) */
       XReparentWindow(wi->dpy, wind->externalwindow, XRootWindow(wi->dpy, Tk_ScreenNumber(wi->win)), 0, 0);
       XMapWindow(wi->dpy, wind->externalwindow);
       XFlush(wi->dpy);
       XRemoveFromSaveSet(wi->dpy, wind->externalwindow);
   }
#endif /* ifdef _WIN32 */

   /* Reset externalwindow */
   wind->externalwindow = 0;
}



/*
 **********************************************************************************
 *
 * Init --
 *
 **********************************************************************************
 */
static int
Init(ZnItem             item,
     int                *argc,
     Tcl_Obj *CONST     *args[])
{
  WindowItem    wind = (WindowItem) item;

  /* Init attributes */
  SET(item->flags, ZN_VISIBLE_BIT);
  SET(item->flags, ZN_SENSITIVE_BIT);
  SET(item->flags, ZN_CATCH_EVENT_BIT);
  SET(item->flags, ZN_COMPOSE_ALPHA_BIT); /* N.A */
  SET(item->flags, ZN_COMPOSE_ROTATION_BIT);
  SET(item->flags, ZN_COMPOSE_SCALE_BIT);
  item->priority = 0;

  wind->pos.x = wind->pos.y = 0.0;
  wind->width = wind->height = 0;
  wind->anchor = TK_ANCHOR_NW;
  wind->connection_anchor = TK_ANCHOR_SW;
  wind->win = NULL;
  wind->windowtitle = NULL;
  wind->externalwindow = 0;
  
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Clone --
 *
 **********************************************************************************
 */
static void
Clone(ZnItem    item)
{
  WindowItem    wind = (WindowItem) item;

  /*
   * The same Tk widget can't be shared by to Window items.
   */
  wind->win = NULL;
  wind->windowtitle = NULL;
  wind->externalwindow = 0;
}


/*
 **********************************************************************************
 *
 * Destroy --
 *
 **********************************************************************************
 */
static void
Destroy(ZnItem  item)
{
  ZnWInfo       *wi = item->wi;
  WindowItem    wind = (WindowItem) item;


  /*
   * Unmanage external window if needed
   */
  if (wind->externalwindow != 0) {
    WindowReleaseExternalWindow(item);
  }
  if (wind->windowtitle) {
    ZnFree(wind->windowtitle);
  }

  /*
   * Unmanage the widget.
   */
  if (wind->win) {
    Tk_DeleteEventHandler(wind->win, StructureNotifyMask, WindowDeleted,
                          (ClientData) item);
    Tk_ManageGeometry(wind->win, (Tk_GeomMgr *) NULL, (ClientData) NULL);
    if (wi->win != Tk_Parent(wind->win)) {
      Tk_UnmaintainGeometry(wind->win, wi->win);
    }
    Tk_UnmapWindow(wind->win);
  }
}


/*
 **********************************************************************************
 *
 * Configure --
 *
 **********************************************************************************
 */
static int
Configure(ZnItem        item,
          int           argc,
          Tcl_Obj *CONST argv[],
          int           *flags)
{
  WindowItem    wind = (WindowItem) item;
  ZnWInfo       *wi = item->wi;
  ZnItem        old_connected;
  Tk_Window     old_win;
  const char   *old_windowtitle = wind->windowtitle;
  
  old_connected = item->connected_item;
  old_win = wind->win;
  
  if (ZnConfigureAttributes(wi, item, item, wind_attrs, argc, argv, flags) == TCL_ERROR) {
    item->connected_item = old_connected;
    return TCL_ERROR;
  }  

  if (ISSET(*flags, ZN_ITEM_FLAG)) {
    /*
     * If the new connected item is not appropriate back up
     * to the old one.
     */
    if ((item->connected_item == ZN_NO_ITEM) ||
        (ISSET(item->connected_item->class->flags, ZN_CLASS_HAS_ANCHORS) &&
         (item->parent == item->connected_item->parent))) {
      ZnITEM.UpdateItemDependency(item, old_connected);
    }
    else {
      item->connected_item = old_connected;
    }
  }

  if (ISSET(*flags, ZN_WINDOW_FLAG)) {
    if (old_win != NULL) {
      Tk_DeleteEventHandler(old_win, StructureNotifyMask,
                            WindowDeleted, (ClientData) item);
      Tk_ManageGeometry(old_win, (Tk_GeomMgr *) NULL, (ClientData) NULL);
      Tk_UnmaintainGeometry(old_win, wi->win);
      Tk_UnmapWindow(old_win);
    }

    if (wind->windowtitle != NULL) {      
      if (old_windowtitle == 0) {
         /* It's a new capture */
         WindowCaptureExternalWindow(item);
      
      } else {
         /* Test if we must capture a new window */
         if (strcmp(old_windowtitle, (const char *)(wind->windowtitle)) != 0) {
            /* release previous external window */
            WindowReleaseExternalWindow(item);
            
            /* Capture a new window */
            WindowCaptureExternalWindow(item);
         }
      }
    }
    
    if (wind->win != NULL) {
      Tk_CreateEventHandler(wind->win, StructureNotifyMask,
                            WindowDeleted, (ClientData) item);
      Tk_ManageGeometry(wind->win, &wind_geom_type, (ClientData) item);
    }
  }
  
  if ((wind->win != NULL) &&
      ISSET(*flags, ZN_VIS_FLAG) &&
      ISCLEAR(item->flags, ZN_VISIBLE_BIT)) {
      Tk_UnmapWindow(wind->win);
  }

  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Query --
 *
 **********************************************************************************
 */
static int
Query(ZnItem            item,
      int               argc,
      Tcl_Obj *CONST    argv[])
{
  if (ZnQueryAttribute(item->wi->interp, item, wind_attrs, argv[0]) == TCL_ERROR) {
    return TCL_ERROR;
  }  

  return TCL_OK;
}

/*
 * Compute the transformation to be used and the origin
 * of the window (upper left point in item coordinates).
 */
static ZnTransfo *
ComputeTransfoAndOrigin(ZnItem    item,
                        ZnPoint   *origin)
{
  WindowItem wind = (WindowItem) item;
  ZnTransfo  *t;

  /*
   * The connected item support anchors, this is checked by configure.
   */
  if (item->connected_item != ZN_NO_ITEM) {
    ZnTransfo inv;

    item->connected_item->class->GetAnchor(item->connected_item,
                                           wind->connection_anchor,
                                           origin);

    /* GetAnchor return a position in device coordinates not in
     * the item coordinate space. To compute the icon origin
     * (upper left corner), we must apply the inverse transform
     * to the ref point before calling anchor2origin.
     */
    ZnTransfoInvert(item->transfo, &inv);
    ZnTransformPoint(&inv, origin, origin);
    /*
     * The relevant transform in case of an attachment is the item
     * transform alone. This is case of local coordinate space where
     * only the translation is a function of the whole transform
     * stack, scale and rotation are reset.
     */
    t = item->transfo;
  }
  else {
    origin->x = origin->y = 0;
    t = item->wi->current_transfo;
  }

  ZnAnchor2Origin(origin, (ZnReal) wind->real_width, (ZnReal) wind->real_height,
                  wind->anchor, origin);
  //origin->x = ZnNearestInt(origin->x);
  //origin->y = ZnNearestInt(origin->y);

  return t;
}

/*
 **********************************************************************************
 *
 * ComputeCoordinates --
 *
 **********************************************************************************
 */
static void
ComputeCoordinates(ZnItem       item,
                   ZnBool       force)
{
  ZnWInfo    *wi = item->wi;
  WindowItem wind = (WindowItem) item;
  ZnPoint    origin;
  ZnTransfo  *t;

  ZnResetBBox(&item->item_bounding_box);

  if (wind->win == NULL) {
    return;
  }

  wind->real_width = wind->width;
  if (wind->real_width <= 0) {
    wind->real_width = Tk_ReqWidth(wind->win);
    if (wind->real_width <= 0) {
      wind->real_width = 1;
    }
  }
  wind->real_height = wind->height;
  if (wind->real_height <= 0) {
    wind->real_height = Tk_ReqHeight(wind->win);
    if (wind->real_height <= 0) {
      wind->real_height = 1;
    }
  }

  t = ComputeTransfoAndOrigin(item, &origin);
  ZnTransformPoint(wi->current_transfo, &origin, &wind->pos_dev);
  wind->pos_dev.x = ZnNearestInt(wind->pos_dev.x);
  wind->pos_dev.y = ZnNearestInt(wind->pos_dev.y);

  /*
   * Compute the bounding box.
   */
  ZnAddPointToBBox(&item->item_bounding_box, wind->pos_dev.x, wind->pos_dev.y);
  ZnAddPointToBBox(&item->item_bounding_box, wind->pos_dev.x+wind->real_width,
                   wind->pos_dev.y+wind->real_height);
  item->item_bounding_box.orig.x -= 1.0;
  item->item_bounding_box.orig.y -= 1.0;
  item->item_bounding_box.corner.x += 1.0;
  item->item_bounding_box.corner.y += 1.0;

  /*
   * Update connected items.
   */
  SET(item->flags, ZN_UPDATE_DEPENDENT_BIT);
}


/*
 **********************************************************************************
 *
 * ToArea --
 *      Tell if the object is entirely outside (-1),
 *      entirely inside (1) or in between (0).
 *
 **********************************************************************************
 */
static int
ToArea(ZnItem   item,
       ZnToArea ta)
{
  WindowItem    wind = (WindowItem) item;
  ZnBBox        box;
  int           w=0, h=0;
  
  box.orig = wind->pos_dev;
  if (wind->win != NULL) {
    w = wind->real_width;
    h = wind->real_height;
  }
  box.corner.x = box.orig.x + w;
  box.corner.y = box.orig.y + h;
  
  return ZnBBoxInBBox(&box, ta->area);
}

/*
 **********************************************************************************
 *
 * Draw --
 *
 **********************************************************************************
 */
static void
Draw(ZnItem     item)
{
  ZnWInfo       *wi = item->wi;
  WindowItem    wind = (WindowItem) item;

  if (wind->win == NULL) {
    return;
  }

  /*
   * If the window is outside the visible area, unmap it.
   */
  if ((item->item_bounding_box.corner.x <= 0) ||
      (item->item_bounding_box.corner.y <= 0) ||
      (item->item_bounding_box.orig.x >= wi->width) ||
      (item->item_bounding_box.orig.y >= wi->height)) {
    if (wi->win == Tk_Parent(wind->win)) {
      Tk_UnmapWindow(wind->win);
    }
    else {
      Tk_UnmaintainGeometry(wind->win, wi->win);
    }
    return;
  }

  /*
   * Position and map the window.
   */
  if (wi->win == Tk_Parent(wind->win)) {
    if ((wind->pos_dev.x != Tk_X(wind->win)) ||
        (wind->pos_dev.y != Tk_Y(wind->win)) ||
        (wind->real_width != Tk_Width(wind->win)) ||
        (wind->real_height != Tk_Height(wind->win))) {
      Tk_MoveResizeWindow(wind->win,
                          (int) wind->pos_dev.x, (int) wind->pos_dev.y,
                          wind->real_width, wind->real_height);
    }
    Tk_MapWindow(wind->win);
  }
  else {
    Tk_MaintainGeometry(wind->win, wi->win,
                        (int) wind->pos_dev.x, (int) wind->pos_dev.y,
                        wind->real_width, wind->real_height);
  }
  
  WindowResizeExternalWindow(item, wind->real_width, wind->real_height);
}


/*
 **********************************************************************************
 *
 * IsSensitive --
 *
 **********************************************************************************
 */
static ZnBool
IsSensitive(ZnItem      item,
            int         item_part)
{
  /*
   * Sensitivity can't be controlled.
   */
  return True;
}


/*
 **********************************************************************************
 *
 * Pick --
 *
 **********************************************************************************
 */
static double
Pick(ZnItem     item,
     ZnPick     ps)
{
  WindowItem    wind = (WindowItem) item;
  ZnBBox        box;
  ZnReal        dist = 1e40;
  ZnPoint       *p = ps->point;

  box.orig = wind->pos_dev;
  if (wind->win != NULL) {
    box.corner.x = box.orig.x + wind->real_width;
    box.corner.y = box.orig.y + wind->real_height;
    dist = ZnRectangleToPointDist(&box, p);
    if (dist <= 0.0) {
      dist = 0.0;
    }
  }
  return dist;
}


/*
 **********************************************************************************
 *
 * PostScript --
 *
 **********************************************************************************
 */
#ifdef X_GetImage
static int
xerrorhandler(ClientData  client_data,
              XErrorEvent *e)
{
	return 0;
}
#endif

static int
PostScript(ZnItem item,
           ZnBool prepass,
           ZnBBox *area)
{
  ZnWInfo         *wi = item->wi;
  WindowItem      wind = (WindowItem) item;
  char            path[256];
  XImage          *ximage;
  int             result;
  ZnPoint         origin;
  Tcl_DString     buffer1, buffer2;
#ifdef X_GetImage
  Tk_ErrorHandler	handle;
#endif

  sprintf(path, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n",
          Tk_Class(wind->win), Tk_PathName(wind->win), wind->real_width, wind->real_height,
          wind->pos_dev.x, wind->pos_dev.y);
  Tcl_AppendResult(wi->interp, path, NULL);

  ComputeTransfoAndOrigin(item, &origin);
  
  sprintf(path, "/InitialTransform load setmatrix\n"
          "%.15g %.15g translate\n"
          "1 -1 scale\n",
          wind->pos_dev.x, wind->pos_dev.y + wind->real_height);
  Tcl_AppendResult(wi->interp, path, NULL);

  /* first try if the widget has its own "postscript" command. If it
   * exists, this will produce much better postscript than
   * when a pixmap is used.
   */
#ifndef PTK
  Tcl_DStringInit(&buffer1);
  Tcl_DStringInit(&buffer2);
  Tcl_DStringGetResult(wi->interp, &buffer2);
  sprintf(path, "%s postscript -prolog 0\n", Tk_PathName(wind->win));
  result = Tcl_Eval(wi->interp, path);
  Tcl_DStringGetResult(wi->interp, &buffer1);
  Tcl_DStringResult(wi->interp, &buffer2);
  Tcl_DStringFree(&buffer2);

  if (result == TCL_OK) {
    Tcl_AppendResult(wi->interp, "50 dict begin\nsave\ngsave\n", NULL);
    sprintf (path, "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d",
             wind->real_height, wind->real_width, wind->real_height, wind->real_width);
    Tcl_AppendResult(wi->interp, path, NULL);
    Tcl_AppendResult(wi->interp, " 0 rlineto closepath\n",
                     "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n",
                     Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n", NULL);
    Tcl_DStringFree(&buffer1);

    return result;
  }
  Tcl_DStringFree(&buffer1);
#endif

  /*
   * If the window is off the screen it will generate an BadMatch/XError
   * We catch any BadMatch errors here
   */
#ifdef X_GetImage
  handle = Tk_CreateErrorHandler(wi->dpy, BadMatch, X_GetImage, -1,
                                 xerrorhandler, (ClientData) wind->win);
#endif

  /*
   * Generate an XImage from the window.  We can then read pixel 
   * values out of the XImage.
   */
  ximage = XGetImage(wi->dpy, Tk_WindowId(wind->win), 0, 0, (unsigned int) wind->real_width,
                     (unsigned int) wind->real_height, AllPlanes, ZPixmap);

#ifdef X_GetImage
  Tk_DeleteErrorHandler(handle);
#endif

  if (ximage == NULL) { 
    return TCL_OK;
  }

  result = ZnPostscriptXImage(wi->interp, wind->win, wi->ps_info, ximage,
                              0, 0, wind->real_width, wind->real_height);
  XDestroyImage(ximage);

  return result;
}


/*
 **********************************************************************************
 *
 * GetAnchor --
 *
 **********************************************************************************
 */
static void
GetAnchor(ZnItem        item,
          Tk_Anchor     anchor,
          ZnPoint       *p)
{
  WindowItem    wind = (WindowItem) item;
  
  if (wind->win != NULL) {
    ZnOrigin2Anchor(&wind->pos_dev, (ZnReal) wind->real_width,
                    (ZnReal) wind->real_height, anchor, p);
  }
  else {
    p->x = p->y = 0.0;
  }
}


/*
 **********************************************************************************
 *
 * GetClipVertices --
 *      Get the clipping shape.
 *
 **********************************************************************************
 */
static ZnBool
GetClipVertices(ZnItem          item,
                ZnTriStrip      *tristrip)
{
  WindowItem    wind = (WindowItem) item;
  int           w=0, h=0;
  ZnPoint       *points;
  
  ZnListAssertSize(ZnWorkPoints, 2);
  if (wind->win != NULL) {
    w = wind->real_width;
    h = wind->real_height;    
  }
  points = ZnListArray(ZnWorkPoints);
  ZnTriStrip1(tristrip, points, 2, False);
  points[0] = wind->pos_dev;
  points[1].x = points[0].x + w;
  points[1].y = points[0].y + h;

  return True;
}


/*
 **********************************************************************************
 *
 * Coords --
 *      Return or edit the item origin. This doesn't take care of
 *      the possible attachment. The change will be effective at the
 *      end of the attachment.
 *
 **********************************************************************************
 */
static int
Coords(ZnItem           item,
       int              contour,
       int              index,
       int              cmd,
       ZnPoint          **pts,
       char             **controls,
       unsigned int     *num_pts)
{
  WindowItem    wind = (WindowItem) item;
  
  if ((cmd == ZN_COORDS_ADD) || (cmd == ZN_COORDS_ADD_LAST) || (cmd == ZN_COORDS_REMOVE)) {
    Tcl_AppendResult(item->wi->interp,
                     " windows can't add or remove vertices", NULL);
    return TCL_ERROR;
  }
  else if ((cmd == ZN_COORDS_REPLACE) || (cmd == ZN_COORDS_REPLACE_ALL)) {
    if (*num_pts == 0) {
      Tcl_AppendResult(item->wi->interp,
                       " coords command need 1 point on windows", NULL);
      return TCL_ERROR;
    }
    wind->pos = (*pts)[0];
    ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
  }
  else if ((cmd == ZN_COORDS_READ) || (cmd == ZN_COORDS_READ_ALL)) {
    *num_pts = 1;
    *pts = &wind->pos;
  }
  return TCL_OK;
}


/*
 **********************************************************************************
 *
 * Exported functions struct --
 *
 **********************************************************************************
 */
static CONST ZnItemClassStruct WINDOW_ITEM_CLASS = {
  "window",
  sizeof(WindowItemStruct),
  wind_attrs,
  0,                    /* num_parts */
  ZN_CLASS_HAS_ANCHORS|ZN_CLASS_ONE_COORD, /* flags */
  Tk_Offset(WindowItemStruct, pos),
  Init,
  Clone,
  Destroy,
  Configure,
  Query,
  NULL,                 /* GetFieldSet */
  GetAnchor,
  GetClipVertices,
  NULL,                 /* GetContours */
  Coords,
  NULL,                 /* InsertChars */
  NULL,                 /* DeleteChars */
  NULL,                 /* Cursor */
  NULL,                 /* Index */
  NULL,                 /* Part */
  NULL,                 /* Selection */
  NULL,                 /* Contour */
  ComputeCoordinates,
  ToArea,
  Draw,
  NULL,                 /* Pre-render */
  Draw,                 /* Render use the same code as Draw. */
  IsSensitive,
  Pick,
  NULL,                 /* PickVertex */
  PostScript
};

CONST ZnItemClassId ZnWindow = (ZnItemClassId) &WINDOW_ITEM_CLASS;

Added jni/tkzinc/generic/WindowUtils.c.



































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/*
 * WindowUtils.c -- Implementation of routines to manipulate windows
 *
 * Authors              : Christophe Berthuet, Alexandre Lemort
 * Creation date        : Fri oct 12 14:47:42 2007
 *
 */


#include "WindowUtils.h"



/*
*************************************
 *
 * Platform specific functions 
 *
 *************************************
 */ 
#ifdef _WIN32

/*
 *-----------------------------------
 *
 * Win32
 *
 *-----------------------------------
 */ 

/*
 * Enumwindows callback struct
 */
typedef struct {
   HWND window;
   char *windowtitle;
} EnumWindowsCallbackStruct;


/*
 * EnumWindows Callback
 */
BOOL CALLBACK SearchWindowCallback(HWND window, LPARAM userData)
{
   char windowTitle[1024];
   EnumWindowsCallbackStruct *myStruct = (EnumWindowsCallbackStruct *)userData;

   /* Get title of our window */
   GetWindowText(window, (LPSTR)windowTitle, 1024);
   
   /* Test if we have found our window */
   if (Tcl_StringMatch((const char*)windowTitle, myStruct->windowtitle)) {
      /* we have found our window */
      myStruct->window = window;
      
      /* Exit EnumWindows */
      return FALSE;
   }

   return TRUE;
}


/*
 * Retrieves the window handler of a window identified by its title
 */
HWND SearchWindowByTitle_simple(char *title, Display *display, HWND root, int depth)
{
   return FindWindow(NULL, (LPCTSTR)title);
}

HWND SearchWindowByTitle(char *title, Display *display, HWND root, int depth)
{
   EnumWindowsCallbackStruct myStruct;
   myStruct.window = NULL;
   myStruct.windowtitle = title;

   /* Try to find our window */
   EnumWindows(SearchWindowCallback, (LPARAM)&myStruct);

   /* Return result */
   return myStruct.window;
}


/*
 * Remove window decoration
 */
LONG removeWindowDecoration(HWND window)
{
   /* Get style of our window */
   LONG previousWindowStyle = GetWindowLong(window, GWL_STYLE);
   LONG windowStyle = previousWindowStyle;
  
   /* Change style */
   windowStyle &= WS_DLGFRAME;
   windowStyle &= WS_CAPTION;
   windowStyle &= WS_POPUP;
   windowStyle |= WS_CHILD;
   
   SetWindowLong(window, GWL_STYLE, windowStyle);//windowStyle);
   
   /* Apply change */
   /* NB: SetWindowPos parameters (HWND_BOTTOM, 0, 0, 100, 100) will not be applied */
   /* SWP_NOZORDER inhibits HWND_BOTTOM */
   /* SWP_NOMOVE inhibits 0, 0 */
   /* SWP_NOSIZE inhibits 100, 100 */
   /* SWP_FRAMECHANGED applies our new style */
   SetWindowPos(window, HWND_BOTTOM, 0, 0, 100, 100, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
   
   /* return previous style */
   return previousWindowStyle;
}


/*
 * Restore window style
 */
void restoreWindowStyle(HWND window, LONG windowStyle) 
{
   /* Restore style */
   SetWindowLong(window, GWL_STYLE, windowStyle);
   
   /* Apply change */
   /* NB: SetWindowPos parameters (HWND_BOTTOM, 0, 0, 100, 100) will not be applied */
   /* SWP_NOZORDER inhibits HWND_BOTTOM */
   /* SWP_NOMOVE inhibits 0, 0 */
   /* SWP_NOSIZE inhibits 100, 100 */
   /* SWP_FRAMECHANGED applies our new style */
   SetWindowPos(window, HWND_BOTTOM, 0, 0, 100, 100, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
}




#else 


/*
 *-----------------------------------
 *
 * Linux
 *
 *-----------------------------------
 */ 


/*
 * Retrieves the window handler of a window identified by its title
 */
Window SearchWindowByTitle(char* wndTitle, Display *dpy, Window wndRoot, int depth)
{
   Window wndFound = 0;

#ifndef PLATFORM_SDL

   // Variables used in the search
   Window root_return; 
   Window parent_return; 
   Window *children_return = 0 ;
   unsigned int nchildren_return = 0;
   
   char msg[255]; 
   int j = 0;

   if( XQueryTree( dpy, wndRoot, &root_return, &parent_return, &children_return, &nchildren_return) != 0 )
   {
      XTextProperty text_prop_return;
      for( j = 0; j < nchildren_return; j++ )
      {
         if( XGetWMName(dpy, children_return[j], &text_prop_return) != 0 )
         {
            if (Tcl_StringMatch(((const char *)(text_prop_return.value)), wndTitle)) 
            { 
               // Window found !!
               wndFound = children_return[j];
               break;
            }
            else
            {
               wndFound = SearchWindowByTitle(wndTitle, dpy, children_return[j], depth +  1 );
               if( wndFound != 0) 
               {
                  break;
               }
            }
         }
         else
         {
            wndFound = SearchWindowByTitle(wndTitle, dpy, children_return[j], depth +  1);
            if( wndFound != 0) 
            {
               break;
            }
         }
      }  
      XFree( children_return );
   }

#endif

   return wndFound;
}


/*
 * Get WM_STATE value of a window
 */
static int 
getWM_STATE (Display *display, Window window)
{
 int status = 0;
 long state = 0;
 static Atom aWM_STATE = 0;
 Atom actual_type = 0;
 int actual_format = 0;
 unsigned long num_ret = 0, num_left = 0;
 unsigned char *data = NULL;

 if (!aWM_STATE) {
  aWM_STATE = XInternAtom(display, "WM_STATE", False);
 }

 status = XGetWindowProperty (display, window, aWM_STATE, 0L, sizeof (long), False, aWM_STATE, &actual_type, &actual_format, &num_ret, &num_left, &data);

 /*I should point out that Success is defined as 0 in X11*/
 if ((status == Success) && (NULL != data)) {
   state = *(long *)data;
 } else {
   state = -1;
 }

 if (data) {
   XFree (data);
 }
 return state;
}


/*
 * Withdraw a window from desktop
 */
void withdrawWindowFromDesktop (Display *display, Window window, int screenNum) {
 int wm_state;

 /* Try to withdraw window */
 XWithdrawWindow (display, window, screenNum);
 XSync (display, 0);
 
 /* Test if we succeed. Otherwise, try until it works */
 while ((wm_state = getWM_STATE (display, window)) != 0 && wm_state != -1) {
  XSync (display, 0);
  XWithdrawWindow (display, window, screenNum);
 }
}




#endif /* ifdef _WIN32 */




/*
 ************************************
 *
 * Common functions
 *
 ************************************
 */


Added jni/tkzinc/generic/WindowUtils.h.





































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
 * WindowUtils.h -- routines to manipulate windows
 *
 * Authors              : Christophe Berthuet, Alexandre Lemort
 * Creation date        : Fri oct 12 14:47:42 2007
 *
 */


#include "tkZinc.h"


#ifdef _WIN32
/* Windows */
#include <windows.h>

#else
/* Linux */
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#endif /* ifdef _WIN32 */







/*
*************************************
 *
 * Platform specific functions 
 *
 *************************************
 */ 
#ifdef _WIN32

/*
 *-----------------------------------
 *
 * Win32
 *
 *-----------------------------------
 */ 

/*
 * Retrieves the window handler of a window identified by its title
 */
HWND SearchWindowByTitle(char *title, Display *display, HWND root, int depth);


/*
 * Add/remove window decoration 
 */
void restoreWindowStyle(HWND window, LONG windowStyle);
LONG removeWindowDecoration(HWND window);



#else 


/*
 *-----------------------------------
 *
 * Linux
 *
 *-----------------------------------
 */ 


/*
 * Retrieves the window handler of a window identified by its title
 */
Window SearchWindowByTitle(char *title, Display *display, Window root, int depth);


/*
 * Withdraw a window from desktop
 */
void withdrawWindowFromDesktop (Display *display, Window window, int screenNum);


#endif /* ifdef _WIN32 */




/*
 ************************************
 *
 * Common functions
 *
 ************************************
 */


Added jni/tkzinc/generic/perfos.c.





























































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/*
 * perfos.c -- Perfos modules.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : 
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

#ifndef _WIN32

#include "perfos.h"
#include "List.h"

#include <X11/Xutil.h>

#include <stdio.h>
#include <math.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>


static const char rcsid[] = "$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";


static ZnList   Chronos = NULL;


/*
 **********************************************************************************
 *
 * HardwareSynchronize - Synchronise Xwindow.
 *
 **********************************************************************************
 */
static void
HardwareSynchronize(Display     *test_display,
                    Drawable    test_window)
{
  /*XImage   *image;*/

  /* Synchronize yourself with the drawing engine by sending a
     XGetImage one pixel square. */
  /*
  image = XGetImage(test_display, test_window, 0, 0, 1, 1, ~0, ZPixmap);
  XDestroyImage(image);
  */
}


/*
 **********************************************************************************
 *
 * GetUCTime - Return machine time. This is the sum of user and system
 *      times for the process so far.
 *
 **********************************************************************************
 */
static long
GetUCTime(void)
{
  struct tms    time;

  times(&time);
  return time.tms_utime + time.tms_stime;
}


/*
 **********************************************************************************
 *
 * GetCurrentTime - Return current time.
 *
 **********************************************************************************
 */
static long
GetCurrentTime(void)
{
  struct timeval start;

  gettimeofday(&start, NULL);
  return((start.tv_sec * 100) + (start.tv_usec / 10000));
}


/*
 **********************************************************************************
 *
 * XGetCurrentTime - return current time after Xwindow synchronize.
 *
 **********************************************************************************
 */
static long
XGetCurrentTime(Display *display, Drawable window)
{
  HardwareSynchronize(display, window);
  return(GetCurrentTime());
}


/*
 **********************************************************************************
 *
 * XCorrectionValue - Evaluate the correction value to apply
 *                    to counter the client-server round trip
 *                    time.
 *
 **********************************************************************************
 */
static long
XCorrectionValue(Display *display, Drawable window)
{ 
  int               i;
  long              start, stop;

  start = GetCurrentTime();
  for (i = 0; i < 5; i++) {
    HardwareSynchronize(display, window);
  }
  stop = GetCurrentTime();
  return((stop - start) / 5);
}

/*
 **********************************************************************************
 *
 * ZnXStartChrono - Start a perf chrono with X synchronize.
 *
 **********************************************************************************
 */
void
ZnXStartChrono(ZnChrono chrono, Display *display, Drawable window)
{
  chrono->current_correction = XCorrectionValue(display, window);
  chrono->current_delay = XGetCurrentTime(display, window);
}


/*
 **********************************************************************************
 *
 * ZnXStopChrono - Stop a perf chrono with X synchronize.
 *
 **********************************************************************************
 */
void
ZnXStopChrono(ZnChrono chrono, Display *display, Drawable window)
{
  chrono->total_delay = chrono->total_delay +
    (XGetCurrentTime(display, window) - 
     chrono->current_delay - chrono->current_correction);
  chrono->actions++;
}


/*
 **********************************************************************************
 *
 * ZnStartChrono - Start a perf chrono in user time.
 *
 **********************************************************************************
 */
void
ZnStartChrono(ZnChrono chrono)
{
  chrono->current_delay = GetCurrentTime();
}


/*
 **********************************************************************************
 *
 * ZnStopChrono - Stop a perf chrono in user time.
 *
 **********************************************************************************
 */
void
ZnStopChrono(ZnChrono chrono)
{
  chrono->total_delay = chrono->total_delay + (GetCurrentTime() - chrono->current_delay);
  chrono->actions++;
}


/*
 **********************************************************************************
 *
 * ZnStartUCChrono - Start a perf chrono in uc time.
 *
 **********************************************************************************
 */
void
ZnStartUCChrono(ZnChrono chrono)
{
  chrono->current_delay = GetUCTime();
}


/*
 **********************************************************************************
 *
 * ZnStopUCChrono - Stop a perf chrono in uc time.
 *
 **********************************************************************************
 */
void
ZnStopUCChrono(ZnChrono chrono)
{
  chrono->total_delay = chrono->total_delay + (GetUCTime() - chrono->current_delay);
  chrono->actions++;
}


/*
 **********************************************************************************
 *
 * ZnPrintChronos - Print the currently available stats on all
 *                chronos registered so far.
 *
 **********************************************************************************
 */
void
ZnPrintChronos(void)
{
  int           i, cnt;
  ZnChrono      *chrs;
  
  cnt = ZnListSize(Chronos);
  chrs = (ZnChrono *) ZnListArray(Chronos);
  for (i = 0; i < cnt; i++) {
    if (chrs[i]->actions != 0) {
      printf("%s : %ld ms on %d times\n",
             chrs[i]->message,
             chrs[i]->total_delay * 10 / chrs[i]->actions,
             chrs[i]->actions);
    }
  }
}


/*
 **********************************************************************************
 *
 * ZnGetChrono - Return the number of runs and the total time of the Chrono.
 *
 **********************************************************************************
 */
void
ZnGetChrono(ZnChrono    chrono,
            long        *time,
            int         *actions)
{
  if (time) {
    *time = chrono->total_delay*10;
  }
  if (actions) {
    *actions = chrono->actions;
  }
}


/*
 **********************************************************************************
 *
 * ZnResetChronos - Reset all chronos or only the specified.
 *
 **********************************************************************************
 */
void
ZnResetChronos(ZnChrono chrono)
{
  int           i, cnt;
  ZnChrono      *chrs;

  if (chrono) {
    chrono->actions = 0;
    chrono->total_delay = 0;    
  }
  else {
    cnt = ZnListSize(Chronos);
    chrs = (ZnChrono *) ZnListArray(Chronos);
    for (i = 0; i < cnt; i++) {
      chrs[i]->actions = 0;
      chrs[i]->total_delay = 0;
    }
  }
}


/*
 **********************************************************************************
 *
 * ZnNewChrono - Return a new initialized chrono associated with
 *             message.
 *
 **********************************************************************************
 */
ZnChrono
ZnNewChrono(char *message)
{
  ZnChrono      new;

  if (!Chronos) {
    Chronos = ZnListNew(8, sizeof(ZnChrono));
  }

  new = (ZnChrono) ZnMalloc(sizeof(ZnChronoRec));
  new->actions = 0;
  new->total_delay = 0;
  new->message = message;

  ZnListAdd(Chronos, &new, ZnListTail);

  return new;
}

/*
 **********************************************************************************
 *
 * ZnFreeChrono - Free the resources of a chrono.
 *
 **********************************************************************************
 */
void
ZnFreeChrono(ZnChrono   chrono)
{
  int      i;
  ZnChrono *chrs = ZnListArray(Chronos);
  
  ZnFree(chrono);

  for (i = ZnListSize(Chronos)-1; i >= 0; i--) {
    if (chrs[i] == chrono) {
      ZnListDelete(Chronos, i);
      break;
    }
  }
}

#endif /* _WIN32 */

Added jni/tkzinc/generic/perfos.h.























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * perfos.h -- Header for perf module.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        :
 *
 * $Id$
 */

/*
 *  Copyright (c) 1996 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _perfos_h
#define _perfos_h

#ifdef __CPLUSPLUS__
extern "C" {
#endif

#ifndef _WIN32

#include "Types.h"


  typedef struct
  {
    long   current_correction;
    long   current_delay;
    long   total_delay;
    int    actions;
    char   *message;
  } ZnChronoRec, *ZnChrono;
  
  
  void ZnXStartChrono(ZnChrono /*chrono*/, Display */*dpy*/, Drawable /*win*/);
  void ZnXStopChrono(ZnChrono /*chrono*/, Display */*dpy*/, Drawable /*win*/);
  void ZnStartChrono(ZnChrono /*chrono*/);
  void ZnStopChrono(ZnChrono /*chrono*/);
  void ZnStartUCChrono(ZnChrono /*chrono*/);
  void ZnStopUCChrono(ZnChrono /*chrono*/);
  ZnChrono ZnNewChrono(char */*message*/);
  void ZnFreeChrono(ZnChrono /*chrono*/);
  void ZnPrintChronos(void);
  void ZnGetChrono(ZnChrono /*chrono*/, long */*time*/, int */*actions*/);
  void ZnResetChronos(ZnChrono /*chrono*/);

#endif /* _WIN32 */

#ifdef __CPLUSPLUS__
}
#endif

#endif  /* _perfos_h */

Added jni/tkzinc/generic/tkZinc.c.









































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
8435
8436
8437
8438
8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
8550
8551
8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641
8642
8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
8718
8719
8720
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824
8825
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
9016
9017
9018
9019
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038
9039
9040
9041
9042
9043
9044
9045
9046
9047
9048
9049
9050
9051
9052
9053
9054
9055
9056
9057
9058
9059
9060
9061
9062
9063
9064
9065
9066
9067
9068
9069
9070
9071
9072
9073
9074
9075
9076
9077
9078
9079
9080
9081
9082
9083
9084
9085
9086
9087
9088
9089
9090
9091
9092
9093
9094
9095
9096
9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
9119
9120
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
9147
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
9212
9213
9214
9215
9216
9217
9218
9219
9220
9221
9222
9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236
9237
9238
9239
9240
9241
9242
9243
9244
9245
9246
9247
9248
9249
9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
9265
9266
9267
9268
9269
9270
9271
9272
9273
9274
9275
9276
9277
9278
9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
9300
9301
9302
9303
9304
9305
9306
9307
9308
9309
9310
9311
9312
9313
9314
9315
9316
9317
9318
9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359
9360
9361
9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
9513
9514
9515
9516
9517
9518
9519
9520
9521
9522
9523
9524
9525
9526
9527
9528
9529
9530
9531
9532
9533
9534
9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
9552
9553
9554
9555
9556
9557
9558
9559
9560
9561
9562
9563
9564
9565
9566
9567
9568
9569
9570
9571
9572
9573
9574
9575
9576
9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
/*
 * tkZinc.c -- Zinc widget for the Tk Toolkit. Main module.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Mon Feb  1 12:13:24 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

/*
 * Some functions and code excerpts in this file are from tkCanvas.c
 * and thus copyrighted:
 *
 * Copyright (c) 1991-1994 The Regents of the University of California.
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 *
 */

static const char rcs_id[]="$Id$";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
static const char * const zinc_version = "zinc-version-" PACKAGE_VERSION;

#include <string.h>
#include <stdio.h>

#ifdef PLATFORM_SDL
# ifdef _WIN32
#  include <windows.h>
# endif
# include "tkInt.h"
# include "SdlTk.h"
#endif

#include "Types.h"
#include "Geo.h"
#include "Item.h"
#include "Group.h"
#include "WidgetInfo.h"
#include "tkZinc.h"
#include "MapInfo.h"
#ifdef ATC
#include "OverlapMan.h"
#include "Track.h"
#endif
#include "Transfo.h"
#include "Image.h"
#include "Draw.h"
#include "Color.h"
#ifndef _WIN32
#include "perfos.h"
#endif

#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <X11/Xatom.h>
#if defined(_WIN32) && defined(PTK) && !defined(PTK_800)
#include <tkPlatDecls.m>
#endif
#if defined(MAC_OSX_TK) && defined(GL)
#include <tkMacOSX.h>
#include <tkMacOSXInt.h>
#endif

#if defined(__APPLE__) && defined(PLATFORM_SDL)
#define _GLUfuncptr void (*)()
#endif
#if defined(_WIN32)
#define _GLUfuncptr void (CALLBACK *)()
#endif


typedef struct _TagSearchExpr {
  struct _TagSearchExpr *next; /* for linked lists of expressions - used in bindings */
  Tk_Uid                uid;    /* the uid of the whole expression */
  Tk_Uid                *uids;  /* expresion compiled to an array of uids */
  int                   allocated; /* available space for array of uids */
  int                   length; /* length of expression */
  int                   index;  /* current position in expression evaluation */
  int                   match;  /* this expression matches event's item's tags*/
} TagSearchExpr;


#define SYMBOL_WIDTH 8
#define SYMBOL_HEIGHT 8
static unsigned char SYMBOLS_BITS[][SYMBOL_WIDTH*SYMBOL_HEIGHT/8] = {
  { 0x18, 0x18, 0x24, 0x24, 0x5a, 0x5a, 0x81, 0xff },
  { 0xff, 0x81, 0x99, 0xbd, 0xbd, 0x99, 0x81, 0xff },
  { 0x18, 0x24, 0x42, 0x99, 0x99, 0x42, 0x24, 0x18 },
  { 0x18, 0x3c, 0x5a, 0xff, 0xff, 0x5a, 0x3c, 0x18 },
  { 0x18, 0x24, 0x42, 0x81, 0x81, 0x42, 0x24, 0x18 },
  { 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c },
  { 0x18, 0x18, 0x24, 0x24, 0x42, 0x42, 0x81, 0xff },
  { 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff },
  { 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xff, 0xff },
  { 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff },
  { 0x18, 0x3c, 0x7e, 0xe7, 0xe7, 0x7e, 0x3c, 0x18 },
  { 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x18 },
  { 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18 },
  { 0x3c, 0x7e, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x3c },
  { 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0xff, 0xff },
  { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
  { 0x18, 0x7e, 0x7e, 0xff, 0xff, 0x7e, 0x7e, 0x18 },
  { 0x18, 0x66, 0x42, 0x81, 0x81, 0x42, 0x66, 0x18 },
  { 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00 },
  { 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00 },
  { 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18 },
  { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 },
};

static unsigned char dither4x4[4][4] = {
  { 0, 8, 2, 10 },
  { 12, 4, 14, 6 },
  { 3, 11, 1, 9 },
  { 15, 7, 13, 5 }
};

static unsigned char bitmaps[ZN_NUM_ALPHA_STEPS][32][4];

static  Tk_Uid  all_uid;
static  Tk_Uid  current_uid;
static  Tk_Uid  and_uid;
static  Tk_Uid  or_uid;
static  Tk_Uid  xor_uid;
static  Tk_Uid  paren_uid;
static  Tk_Uid  end_paren_uid;
static  Tk_Uid  neg_paren_uid;
static  Tk_Uid  tag_val_uid;
static  Tk_Uid  neg_tag_val_uid;
static  Tk_Uid  dot_uid;
static  Tk_Uid  star_uid;

#ifdef GL
static  ZnGLContextEntry *gl_contexts = NULL;
#if defined(MAC_OSX_TK)
static GLint    ZnGLAttribs[] = {
  AGL_RGBA,
  AGL_DOUBLEBUFFER,
  AGL_RED_SIZE, 8,
  AGL_GREEN_SIZE, 8,
  AGL_BLUE_SIZE, 8,
  AGL_STENCIL_SIZE, 8,
  AGL_NONE
};
#elif !defined(_WIN32) && !defined(PLATFORM_SDL)
static  int             ZnMajorGlx, ZnMinorGlx;
static  int             ZnGLAttribs[] = {
  GLX_RGBA,
  GLX_DOUBLEBUFFER,
  GLX_RED_SIZE, 8,
  GLX_GREEN_SIZE, 8,
  GLX_BLUE_SIZE, 8,
  GLX_STENCIL_SIZE, 8,
  /*GLX_ALPHA_SIZE, 8,*/
  None
};
#endif
#endif
  
/*
 * Temporary object lists
 */
        ZnList          ZnWorkPoints;
        ZnList          ZnWorkXPoints;
        ZnList          ZnWorkStrings;
  
/*
 * Tesselator
 */
        ZnTess          ZnTesselator;


#if defined(GL) && defined(ROTATION)
static void TransformEvent _ANSI_ARGS_((ZnWInfo *wi, XEvent  *event));
#endif
static  void PickCurrentItem _ANSI_ARGS_((ZnWInfo *wi, XEvent *event));
#ifdef PTK_800
static  int ZnReliefParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
                                       Tk_Window tkwin, Tcl_Obj *ovalue,
                                       char *widget_rec, int offset));
static  Tcl_Obj *ZnReliefPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
                                            char *widget_rec, int offset,
                                            Tcl_FreeProc **free_proc));
static  int ZnGradientParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
                                         Tk_Window tkwin, Tcl_Obj *ovalue,
                                         char *widget_rec, int offset));
static  Tcl_Obj *ZnGradientPrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
                                              char *widget_rec, int offset,
                                              Tcl_FreeProc **free_proc));
static  int ZnImageParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
                                      Tk_Window tkwin, Tcl_Obj *ovalue,
                                      char *widget_rec, int offset));
static  int ZnBitmapParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
                                       Tk_Window tkwin, Tcl_Obj *ovalue,
                                       char *widget_rec, int offset));
static  Tcl_Obj *ZnImagePrint _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
                                           char *widget_rec, int offset,
                                           Tcl_FreeProc **free_proc));
static  Tk_CustomOption reliefOption = {
  (Tk_OptionParseProc *) ZnReliefParse,
  (Tk_OptionPrintProc *) ZnReliefPrint,
  NULL
};
static  Tk_CustomOption gradientOption = {
  (Tk_OptionParseProc *) ZnGradientParse,
  (Tk_OptionPrintProc *) ZnGradientPrint,
  NULL
};
static  Tk_CustomOption imageOption = {
  (Tk_OptionParseProc *) ZnImageParse,
  (Tk_OptionPrintProc *) ZnImagePrint,
  NULL
};
static  Tk_CustomOption bitmapOption = {
  (Tk_OptionParseProc *) ZnBitmapParse,
  (Tk_OptionPrintProc *) ZnImagePrint,
  NULL
};
#else
static  int ZnSetReliefOpt _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
                                        Tk_Window tkwin, Tcl_Obj **ovalue,
                                        char *widget_rec, int offset, char *old_val_ptr, int flags));
static  Tcl_Obj *ZnGetReliefOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
                                             char *widget_rec, int offset));
static void ZnRestoreReliefOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
                                            char *val_ptr, char *old_val_ptr));
static  int ZnSetGradientOpt _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp,
                                          Tk_Window tkwin, Tcl_Obj **ovalue,
                                          char *widget_rec, int offset, char *old_val_ptr, int flags));
static  Tcl_Obj *ZnGetGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
                                               char *widget_rec, int offset));
static  void ZnRestoreGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin,
                                               char *val_ptr, char *old_val_ptr));
static  void ZnFreeGradientOpt _ANSI_ARGS_((ClientData client_data, Tk_Window tkwin, char *val_ptr));

static  Tk_ObjCustomOption reliefOption = {
  "znrelief",
  ZnSetReliefOpt,
  ZnGetReliefOpt,
  ZnRestoreReliefOpt,
  NULL,
  0
};
static  Tk_ObjCustomOption gradientOption = {
  "zngradient",
  ZnSetGradientOpt,
  ZnGetGradientOpt,
  ZnRestoreGradientOpt,
  ZnFreeGradientOpt,
  NULL
};
#endif

#ifdef PTK_800
#define BORDER_WIDTH_SPEC               0
#define BACK_COLOR_SPEC                 (BORDER_WIDTH_SPEC + 1)
#define CONFINE_SPEC                    (BACK_COLOR_SPEC + 1)
#define CURSOR_SPEC                     (CONFINE_SPEC + 1)
#define FONT_SPEC                       (CURSOR_SPEC + 1)
#define FORE_COLOR_SPEC                 (FONT_SPEC + 1)
#define FULL_RESHAPE_SPEC               (FORE_COLOR_SPEC + 1)
#define HEIGHT_SPEC                     (FULL_RESHAPE_SPEC + 1)
#define HIGHLIGHT_BACK_COLOR_SPEC       (HEIGHT_SPEC + 1)
#define HIGHLIGHT_COLOR_SPEC            (HIGHLIGHT_BACK_COLOR_SPEC + 1)
#define HIGHLIGHT_THICKNESS_SPEC        (HIGHLIGHT_COLOR_SPEC + 1)
#define INSERT_COLOR_SPEC               (HIGHLIGHT_THICKNESS_SPEC + 1)
#define INSERT_OFF_TIME_SPEC            (INSERT_COLOR_SPEC + 1)
#define INSERT_ON_TIME_SPEC             (INSERT_OFF_TIME_SPEC + 1)
#define INSERT_WIDTH_SPEC               (INSERT_ON_TIME_SPEC + 1)
#define PICK_APERTURE_SPEC              (INSERT_WIDTH_SPEC + 1)
#define RELIEF_SPEC                     (PICK_APERTURE_SPEC + 1)
#define RENDER_SPEC                     (RELIEF_SPEC + 1)
#define RESHAPE_SPEC                    (RENDER_SPEC + 1)
#define SCROLL_REGION_SPEC              (RESHAPE_SPEC + 1)
#define SELECT_COLOR_SPEC               (SCROLL_REGION_SPEC + 1)
#define TAKE_FOCUS_SPEC                 (SELECT_COLOR_SPEC + 1)
#define TILE_SPEC                       (TAKE_FOCUS_SPEC + 1)
#define WIDTH_SPEC                      (TILE_SPEC + 1)
#define X_SCROLL_CMD_SPEC               (WIDTH_SPEC + 1)
#define X_SCROLL_INCREMENT_SPEC         (X_SCROLL_CMD_SPEC + 1)
#define Y_SCROLL_CMD_SPEC               (X_SCROLL_INCREMENT_SPEC + 1)
#define Y_SCROLL_INCREMENT_SPEC         (Y_SCROLL_CMD_SPEC + 1)
#define BBOXES_SPEC                     (Y_SCROLL_INCREMENT_SPEC + 1)
#define BBOXES_COLOR_SPEC               (BBOXES_SPEC + 1)
#define LIGHT_ANGLE_SPEC                (BBOXES_COLOR_SPEC + 1)
#define FOLLOW_POINTER_SPEC             (LIGHT_ANGLE_SPEC + 1)
#ifdef ATC
#define MAP_DISTANCE_SYMBOL_SPEC        (FOLLOW_POINTER_SPEC + 1)
#define MAP_TEXT_FONT_SPEC              (MAP_DISTANCE_SYMBOL_SPEC + 1)
#define OVERLAP_MANAGER_SPEC            (MAP_TEXT_FONT_SPEC + 1)
#define SPEED_VECTOR_LENGTH_SPEC        (OVERLAP_MANAGER_SPEC + 1)
#define VISIBLE_HISTORY_SIZE_SPEC       (SPEED_VECTOR_LENGTH_SPEC + 1)
#define MANAGED_HISTORY_SIZE_SPEC       (VISIBLE_HISTORY_SIZE_SPEC + 1)
#define TRACK_SYMBOL_SPEC               (MANAGED_HISTORY_SIZE_SPEC + 1)
#endif
#if defined(GL) && defined(ROTATION)
#ifdef ATC
#define SCREEN_ROTATION_SPEC            (TRACK_SYMBOL_SPEC + 1)
#else
#define SCREEN_ROTATION_SPEC            (FOLLOW_POINTER_SPEC + 1)
#endif
#define ENABLE_ROTATION_SPEC            (SCREEN_ROTATION_SPEC + 1)
#endif
#else
#define CONFIG_FONT                     1<<0
#define CONFIG_MAP_FONT                 1<<1
#define CONFIG_BACK_COLOR               1<<2
#define CONFIG_REDISPLAY                1<<3
#define CONFIG_DAMAGE_ALL               1<<4
#define CONFIG_INVALIDATE_TRACKS        1<<5
#define CONFIG_INVALIDATE_WPS           1<<6
#define CONFIG_INVALIDATE_MAPS          1<<7
#define CONFIG_REQUEST_GEOM             1<<8
#define CONFIG_OM                       1<<9
#define CONFIG_FOCUS                    1<<10
#define CONFIG_FOCUS_ITEM               1<<11
#define CONFIG_SCROLL_REGION            1<<12
#define CONFIG_SET_ORIGIN               1<<13
#define CONFIG_FOLLOW_POINTER           1<<14
#define CONFIG_MAP_SYMBOL               1<<15
#define CONFIG_TRACK_SYMBOL             1<<16
#define CONFIG_TILE                     1<<17
#define CONFIG_DEBUG                    1<<18
#if defined(GL) && defined(ROTATION)
#define CONFIG_ROTATION                 1<<19
#define CONFIG_ENABLE_ROTATION          1<<20
#endif
#endif

/*
 * Information used for argv parsing.
 */
#ifdef PTK_800
static Tk_ConfigSpec config_specs[] = {
  {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
   "2", Tk_Offset(ZnWInfo, border_width), 0, NULL},
  {TK_CONFIG_CUSTOM, "-backcolor", "backColor", "BackColor",
   "#c3c3c3", Tk_Offset(ZnWInfo, back_color), 0, &gradientOption},
  {TK_CONFIG_BOOLEAN, "-confine", "confine", "Confine",
   "1", Tk_Offset(ZnWInfo, confine), 0, NULL},
  {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
   "arrow", Tk_Offset(ZnWInfo, cursor), TK_CONFIG_NULL_OK, NULL},
  {TK_CONFIG_FONT, "-font", "font", "Font",
   "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
   Tk_Offset(ZnWInfo, font), 0, NULL},
  {TK_CONFIG_CUSTOM, "-forecolor", "foreColor", "Foreground",
   "Black", Tk_Offset(ZnWInfo, fore_color), 0, &gradientOption},
  {TK_CONFIG_BOOLEAN, "-fullreshape", "fullReshape", "FullReshape",
   "1", Tk_Offset(ZnWInfo, full_reshape), 0, NULL},
  {TK_CONFIG_PIXELS, "-height", "height", "Height",
   "7c", Tk_Offset(ZnWInfo, opt_height), 0, NULL},
  {TK_CONFIG_CUSTOM, "-highlightbackground", "highlightBackground", "HighlightBackground",
   "#c3c3c3", Tk_Offset(ZnWInfo, highlight_bg_color), 0, &gradientOption},
  {TK_CONFIG_CUSTOM, "-highlightcolor", "highlightColor", "HighlightColor",
   "Black", Tk_Offset(ZnWInfo, highlight_color), 0, &gradientOption},
  {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness",
   "2", Tk_Offset(ZnWInfo, highlight_width), 0, NULL},
  {TK_CONFIG_CUSTOM, "-insertbackground", "insertBackground", "Foreground",
   "Black", Tk_Offset(ZnWInfo, text_info.insert_color), 0, &gradientOption},
  {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
   "300", Tk_Offset(ZnWInfo, insert_off_time), 0, NULL},
  {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
   "600", Tk_Offset(ZnWInfo, insert_on_time), 0, NULL},
  {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
   "2", Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL},
  {TK_CONFIG_INT, "-pickaperture", "pickAperture", "PickAperture",
   "1", Tk_Offset(ZnWInfo, pick_aperture), 0, NULL},
  {TK_CONFIG_CUSTOM, "-relief", "relief", "Relief",
   "flat", Tk_Offset(ZnWInfo, relief), 0, &reliefOption},
  {TK_CONFIG_INT, "-render", "render", "Render",
   "0", Tk_Offset(ZnWInfo, render), 0, NULL},
  {TK_CONFIG_BOOLEAN, "-reshape", "reshape", "Reshape",
   "1", Tk_Offset(ZnWInfo, reshape), 0, NULL},  
  {TK_CONFIG_LANGARG, "-scrollregion", "scrollRegion", "ScrollRegion",
   "", Tk_Offset(ZnWInfo, region), TK_CONFIG_NULL_OK, NULL},
  {TK_CONFIG_CUSTOM, "-selectbackground", "selectBackground", "Foreground",
   "#a0a0a0", Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption},
  {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
   NULL, Tk_Offset(ZnWInfo, take_focus), TK_CONFIG_NULL_OK, NULL},
  {TK_CONFIG_CUSTOM, "-tile", "tile", "Tile",
   "", Tk_Offset(ZnWInfo, tile), 0, &imageOption},
  {TK_CONFIG_PIXELS, "-width", "width", "Width",
   "10c", Tk_Offset(ZnWInfo, opt_width), 0, NULL},
  {TK_CONFIG_CALLBACK, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
   "", Tk_Offset(ZnWInfo, x_scroll_cmd), TK_CONFIG_NULL_OK, NULL},
  {TK_CONFIG_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement",
   "0", Tk_Offset(ZnWInfo, x_scroll_incr), 0, NULL},
  {TK_CONFIG_CALLBACK, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
   "", Tk_Offset(ZnWInfo, y_scroll_cmd), TK_CONFIG_NULL_OK, NULL},
  {TK_CONFIG_PIXELS, "-yscrollincrement", "yScrollIncrement",  "ScrollIncrement",
   "0", Tk_Offset(ZnWInfo, y_scroll_incr), 0, NULL},
  /*
   * Debug options.
   */
  {TK_CONFIG_BOOLEAN, "-drawbboxes", "drawBBoxes",
   "DrawBBoxes", "0", Tk_Offset(ZnWInfo, draw_bboxes), 0, NULL},
  {TK_CONFIG_CUSTOM, "-bboxcolor", "bboxColor", "BBoxColor",
   "Pink", Tk_Offset(ZnWInfo, bbox_color), 0, &gradientOption},
  {TK_CONFIG_INT, "-lightangle", "lightAngle", "LightAngle",
   "120", Tk_Offset(ZnWInfo, light_angle), 0, NULL},
  {TK_CONFIG_BOOLEAN, "-followpointer", "followPointer",
   "FollowPointer", "1", Tk_Offset(ZnWInfo, follow_pointer), 0, NULL},
#ifdef ATC
  {TK_CONFIG_CUSTOM, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol",
   "AtcSymbol19", Tk_Offset(ZnWInfo, map_distance_symbol),
   TK_CONFIG_NULL_OK, &bitmapOption},
  {TK_CONFIG_FONT, "-maptextfont", "mapTextFont", "MapTextFont",
   "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
   Tk_Offset(ZnWInfo, map_text_font), 0, NULL},
  {TK_CONFIG_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1",
   Tk_Offset(ZnWInfo, om_group_id), 0, NULL},
  {TK_CONFIG_DOUBLE, "-speedvectorlength", "speedVectorLength",
   "SpeedVectorLength", "3", Tk_Offset(ZnWInfo, speed_vector_length), 0, NULL},
  {TK_CONFIG_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize",
   "6", Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL},
  {TK_CONFIG_INT, "-trackmanagedhistorysize", "trackManagedHistorySize",
   "TrackManagedHistorySize", "6", Tk_Offset(ZnWInfo, track_managed_history_size), 0, NULL},
  {TK_CONFIG_CUSTOM, "-tracksymbol", "trackSymbol", "TrackSymbol",
   "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol), TK_CONFIG_NULL_OK, &bitmapOption},
#endif
#if defined(GL) && defined(ROTATION)
  {TK_CONFIG_BOOLEAN, "-enablerotation", "enableRotation", "EnableRotation",
   "0", Tk_Offset(ZnWInfo, enable_rotation), 0, NULL},
  {TK_CONFIG_DOUBLE, "-screenrotation", "screenRotation", "ScreenRotation",
   "0", Tk_Offset(ZnWInfo, screen_rotation), 0, NULL},
#endif
  /* Use damage option (only used if -render is set to 1 ie if we use GL */
  {TK_CONFIG_INT, "-usedamage", "useDamage", "UseDamage",
   "0", Tk_Offset(ZnWInfo, usedamage), 0, NULL},
  {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL}
};
#else
static Tk_OptionSpec option_specs[] = {
  {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
     "2", -1, Tk_Offset(ZnWInfo, border_width), 0, NULL, CONFIG_DAMAGE_ALL|CONFIG_REQUEST_GEOM},
  {TK_OPTION_CUSTOM, "-backcolor", "backColor", "BackColor",
     "#c3c3c3", -1, Tk_Offset(ZnWInfo, back_color), 0, &gradientOption,
     CONFIG_BACK_COLOR|CONFIG_DAMAGE_ALL},
  {TK_OPTION_BOOLEAN, "-confine", "confine", "Confine",
     "1", -1, Tk_Offset(ZnWInfo, confine), 0, NULL, CONFIG_SET_ORIGIN},
  {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
     "", -1, Tk_Offset(ZnWInfo, cursor), TK_OPTION_NULL_OK, NULL, 0},
  {TK_OPTION_INT, "-debug", "debug", "Debug",
     "0", -1, Tk_Offset(ZnWInfo, debug), 0, NULL, 0},
  {TK_OPTION_FONT, "-font", "font", "Font",
     "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
     -1, Tk_Offset(ZnWInfo, font), 0, NULL, CONFIG_FONT},
  {TK_OPTION_CUSTOM, "-forecolor", "foreColor", "Foreground",
     "Black", -1, Tk_Offset(ZnWInfo, fore_color), 0, &gradientOption, 0},
  {TK_OPTION_BOOLEAN, "-fullreshape", "fullReshape", "FullReshape",
     "1", -1, Tk_Offset(ZnWInfo, full_reshape), 0, NULL, 0},
  {TK_OPTION_PIXELS, "-height", "height", "Height",
     "7c", -1, Tk_Offset(ZnWInfo, opt_height), 0, NULL, CONFIG_REQUEST_GEOM},
  {TK_OPTION_CUSTOM, "-highlightbackground", "highlightBackground", "HighlightBackground",
     "#c3c3c3", -1,  Tk_Offset(ZnWInfo, highlight_bg_color), 0, &gradientOption,
     CONFIG_REDISPLAY},
  {TK_OPTION_CUSTOM, "-highlightcolor", "highlightColor", "HighlightColor",
     "Black", -1, Tk_Offset(ZnWInfo, highlight_color), 0, &gradientOption, CONFIG_REDISPLAY},
  {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness",
     "2", -1, Tk_Offset(ZnWInfo, highlight_width), 0, NULL, CONFIG_REQUEST_GEOM|CONFIG_DAMAGE_ALL},
  {TK_OPTION_CUSTOM, "-insertbackground", "insertBackground", "Foreground",
     "Black", -1, Tk_Offset(ZnWInfo, text_info.insert_color), 0, &gradientOption, 0},
  {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
     "300", -1, Tk_Offset(ZnWInfo, insert_off_time), 0, NULL, CONFIG_FOCUS},
  {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
     "600", -1, Tk_Offset(ZnWInfo, insert_on_time), 0, NULL, CONFIG_FOCUS},
  {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
     "2", -1, Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL, CONFIG_FOCUS_ITEM},
  {TK_OPTION_INT, "-pickaperture", "pickAperture", "PickAperture",
     "1", -1, Tk_Offset(ZnWInfo, pick_aperture), 0, NULL, 0},
  {TK_OPTION_CUSTOM, "-relief", "relief", "Relief",
     "flat", -1, Tk_Offset(ZnWInfo, relief), 0, &reliefOption, CONFIG_REDISPLAY},
  {TK_OPTION_INT, "-render", "render", "Render",
     "-1", -1, Tk_Offset(ZnWInfo, render), 0, NULL, 0},
  {TK_OPTION_BOOLEAN, "-reshape", "reshape", "Reshape",
     "1", -1, Tk_Offset(ZnWInfo, reshape), 0, NULL, 0},
  {TK_OPTION_STRING, "-scrollregion", "scrollRegion", "ScrollRegion",
     "", Tk_Offset(ZnWInfo, region), -1,
     TK_OPTION_NULL_OK, NULL, CONFIG_SET_ORIGIN|CONFIG_SCROLL_REGION},
  {TK_OPTION_CUSTOM, "-selectbackground", "selectBackground", "Foreground",
     "#a0a0a0", -1, Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption, 0},
  {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
     NULL, Tk_Offset(ZnWInfo, take_focus), -1, TK_OPTION_NULL_OK, NULL, 0},
  {TK_OPTION_STRING, "-tile", "tile", "Tile",
     "", Tk_Offset(ZnWInfo, tile_obj), -1, TK_OPTION_NULL_OK, NULL, CONFIG_TILE|CONFIG_DAMAGE_ALL},
  {TK_OPTION_PIXELS, "-width", "width", "Width",
     "10c", -1, Tk_Offset(ZnWInfo, opt_width), 0, NULL, CONFIG_DAMAGE_ALL|CONFIG_REQUEST_GEOM},
#ifdef PTK
  {TK_OPTION_CALLBACK, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
     "", -1, Tk_Offset(ZnWInfo, x_scroll_cmd), TK_OPTION_NULL_OK, NULL, 0},
#else
  {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
     "", Tk_Offset(ZnWInfo, x_scroll_cmd), -1, TK_OPTION_NULL_OK, NULL, 0},
#endif
  {TK_OPTION_PIXELS, "-xscrollincrement", "xScrollIncrement", "ScrollIncrement",
     "0", -1, Tk_Offset(ZnWInfo, x_scroll_incr), 0, NULL, 0},
#ifdef PTK
  {TK_OPTION_CALLBACK, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
     "", -1, Tk_Offset(ZnWInfo, y_scroll_cmd), TK_OPTION_NULL_OK, NULL, 0},
#else
  {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
     "", Tk_Offset(ZnWInfo, y_scroll_cmd), -1, TK_OPTION_NULL_OK, NULL, 0},
#endif
  {TK_OPTION_PIXELS, "-yscrollincrement", "yScrollIncrement",  "ScrollIncrement",
     "0", -1, Tk_Offset(ZnWInfo, y_scroll_incr), 0, NULL, 0},
  /*
   * Debug options.
   */
  {TK_OPTION_BOOLEAN, "-drawbboxes", "drawBBoxes",
     "DrawBBoxes", "0", -1, Tk_Offset(ZnWInfo, draw_bboxes), 0, NULL, 0},
  {TK_OPTION_CUSTOM, "-bboxcolor", "bboxColor", "BBoxColor",
     "Pink", -1, Tk_Offset(ZnWInfo, bbox_color), 0, &gradientOption, 0},
  {TK_OPTION_INT, "-lightangle", "lightAngle", "LightAngle",
     "120", -1, Tk_Offset(ZnWInfo, light_angle), 0, NULL, CONFIG_DAMAGE_ALL},
  {TK_OPTION_BOOLEAN, "-followpointer", "followPointer",
   "FollowPointer", "1", -1, Tk_Offset(ZnWInfo, follow_pointer), 0, NULL, CONFIG_FOLLOW_POINTER},
#ifdef ATC
  {TK_OPTION_STRING, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol",
     "AtcSymbol19", Tk_Offset(ZnWInfo, map_symbol_obj), -1,
     TK_OPTION_NULL_OK, NULL, CONFIG_MAP_SYMBOL|CONFIG_INVALIDATE_MAPS},
  {TK_OPTION_FONT, "-maptextfont", "mapTextFont", "MapTextFont",
     "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*",
     -1, Tk_Offset(ZnWInfo, map_text_font), 0, NULL, CONFIG_MAP_FONT},
  {TK_OPTION_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1",
     -1, Tk_Offset(ZnWInfo, om_group_id), 0, NULL, CONFIG_OM},
  {TK_OPTION_DOUBLE, "-speedvectorlength", "speedVectorLength",
     "SpeedVectorLength", "3", -1, Tk_Offset(ZnWInfo, speed_vector_length),
     0, NULL, CONFIG_INVALIDATE_TRACKS},
  {TK_OPTION_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize",
     "6", -1, Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL, CONFIG_INVALIDATE_TRACKS},
  {TK_OPTION_INT, "-trackmanagedhistorysize", "trackManagedHistorySize",
     "TrackManagedHistorySize", "6", -1, Tk_Offset(ZnWInfo, track_managed_history_size),
     0, NULL, CONFIG_INVALIDATE_TRACKS},
  {TK_OPTION_STRING, "-tracksymbol", "trackSymbol", "TrackSymbol",
     "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol_obj), -1,
     0, NULL, CONFIG_TRACK_SYMBOL|CONFIG_INVALIDATE_TRACKS|CONFIG_INVALIDATE_WPS},
#endif
#if defined(GL) && defined(ROTATION)
  {TK_OPTION_BOOLEAN, "-enablerotation", "enableRotation", "EnableRotation",
     "0", -1, Tk_Offset(ZnWInfo, enable_rotation), 0, NULL, CONFIG_ENABLE_ROTATION},
  {TK_OPTION_DOUBLE, "-screenrotation", "screenRotation", "ScreenRotation",
     "0", -1, Tk_Offset(ZnWInfo, screen_rotation), 0, NULL, CONFIG_ROTATION},
#endif
  /* Use damage option (only used if -render is set to 1 ie if we use GL */
  {TK_OPTION_INT, "-usedamage", "useDamage", "UseDamage",
     "0", -1, Tk_Offset(ZnWInfo, usedamage), 0, NULL, 0},
  {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
};
#endif

static void     CmdDeleted _ANSI_ARGS_((ClientData client_data));
static void     Event _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr));
static void     Bind _ANSI_ARGS_((ClientData client_data, XEvent *eventPtr));
static int      FetchSelection _ANSI_ARGS_((ClientData clientData, int offset,
                                            char *buffer, int maxBytes));
static void     SelectTo _ANSI_ARGS_((ZnItem item, int field, int index));
static int      WidgetObjCmd _ANSI_ARGS_((ClientData client_data,
                                          Tcl_Interp *, int argc, Tcl_Obj *CONST args[]));
#ifdef PTK_800
static int      Configure _ANSI_ARGS_((Tcl_Interp *interp, ZnWInfo *wi,
                                       int argc, Tcl_Obj *CONST args[], int flags));
#else
static int      Configure _ANSI_ARGS_((Tcl_Interp *interp, ZnWInfo *wi,
                                       int argc, Tcl_Obj *CONST args[]));
#endif
static void     Redisplay _ANSI_ARGS_((ClientData client_data));
static void     Destroy _ANSI_ARGS_((ZnWInfo *wi));
static void     InitZinc _ANSI_ARGS_((Tcl_Interp *interp));
static void     Focus _ANSI_ARGS_((ZnWInfo *wi, ZnBool got_focus));
static void     Update _ANSI_ARGS_((ZnWInfo     *wi));
static void     Repair _ANSI_ARGS_((ZnWInfo     *wi));


#ifdef PTK_800
/*
 *----------------------------------------------------------------------
 *
 * ZnReliefParse
 * ZnReliefPrint --
 *      Converter for the -relief option.
 *
 *----------------------------------------------------------------------
 */
static int
ZnReliefParse(ClientData        client_data,
              Tcl_Interp        *interp,
              Tk_Window         tkwin,
              Tcl_Obj           *ovalue,
              char              *widget_rec,
              int               offset)
{
  ZnReliefStyle *relief_ptr = (ZnReliefStyle *) (widget_rec + offset);
  ZnReliefStyle relief;
  char        *value = Tcl_GetString(ovalue);
  int         result = TCL_OK;

  if (value != NULL) {
    result = ZnGetRelief((ZnWInfo *) widget_rec, value, &relief);
    if (result == TCL_OK) {
      *relief_ptr = relief;
    }
  }
  return result;
}

static Tcl_Obj *
ZnReliefPrint(ClientData        client_data,
              Tk_Window         tkwin,
              char              *widget_rec,
              int               offset,
              Tcl_FreeProc      **free_proc)
{
  ZnReliefStyle relief = *(ZnReliefStyle *) (widget_rec + offset);
  return Tcl_NewStringObj(ZnNameOfRelief(relief), -1);
}


/*
 *----------------------------------------------------------------------
 *
 * ZnGradientParse
 * ZnGradientPrint --
 *      Converter for the -*color* options.
 *
 *----------------------------------------------------------------------
 */
static int
ZnGradientParse(ClientData      client_data,
                Tcl_Interp      *interp,
                Tk_Window       tkwin,
                Tcl_Obj         *ovalue,
                char            *widget_rec,
                int             offset)
{
  ZnGradient    **grad_ptr = (ZnGradient **) (widget_rec + offset);
  ZnGradient    *grad, *prev_grad;
  char          *value = Tcl_GetString(ovalue);

  prev_grad = *grad_ptr;
  if ((value != NULL) && (*value != '\0')) {
    grad = ZnGetGradient(interp, tkwin, value);
    if (grad == NULL) {
      return TCL_ERROR;
    }
    if (prev_grad != NULL) {
      ZnFreeGradient(prev_grad);
    }
    *grad_ptr = grad;
  }
  return TCL_OK;
}

static Tcl_Obj *
ZnGradientPrint(ClientData      client_data,
                Tk_Window       tkwin,
                char            *widget_rec,
                int             offset,
                Tcl_FreeProc    **free_proc)
{
  ZnGradient *gradient = *(ZnGradient **) (widget_rec + offset);
  return Tcl_NewStringObj(ZnNameOfGradient(gradient), -1);
}


/*
 *----------------------------------------------------------------------
 *
 * ZnBitmapParse
 * ZnImageParse
 * ZnImagePrint --
 *      Converter for the -*image* options.
 *
 *----------------------------------------------------------------------
 */
static int
ZnBitmapParse(ClientData        client_data,
              Tcl_Interp        *interp,
              Tk_Window         tkwin,
              Tcl_Obj           *ovalue,
              char              *widget_rec,
              int               offset)
{
  ZnImage       *image_ptr = (ZnImage *) (widget_rec + offset);
  ZnImage       image, prev_image;
  char          *value = Tcl_GetString(ovalue);
  ZnWInfo       *wi = (ZnWInfo*) widget_rec;
  ZnBool        is_bmap = True;

  prev_image = *image_ptr;
  if ((value != NULL) && (*value != '\0')) {
    image = ZnGetImage(wi, value, NULL, NULL);
    if ((image == ZnUnspecifiedImage) ||
        ! (is_bmap = ZnImageIsBitmap(image))) {
      if (!is_bmap) {
        ZnFreeImage(image, NULL, NULL);
      }
      return TCL_ERROR;
    }
    if (prev_image != NULL) {
      ZnFreeImage(prev_image, NULL, NULL);
    }
    *image_ptr = image;
  }
  else if (prev_image != NULL) {
    ZnFreeImage(prev_image, NULL, NULL);
    *image_ptr = NULL;
  }

  return TCL_OK;
}

static void
ZnImageUpdate(void *client_data)
{
  ZnWInfo *wi = (ZnWInfo*) client_data;

  ZnDamageAll(wi);
}

static int
ZnImageParse(ClientData client_data,
             Tcl_Interp *interp,
             Tk_Window  tkwin,
             Tcl_Obj    *ovalue,
             char       *widget_rec,
             int        offset)
{
  ZnImage       *image_ptr = (ZnImage *) (widget_rec + offset);
  ZnImage       image, prev_image;
  char          *value = Tcl_GetString(ovalue);
  ZnWInfo       *wi = (ZnWInfo*) widget_rec;

  prev_image = *image_ptr;
  if ((value != NULL) && (*value != '\0')) {
    image = ZnGetImage(wi, value, ZnImageUpdate, wi);
    if (image == NULL) {
      return TCL_ERROR;
    }
    if (prev_image != NULL) {
      ZnFreeImage(prev_image, ZnImageUpdate, wi);
    }
    *image_ptr = image;
  }
  else if (prev_image != NULL) {
    ZnFreeImage(prev_image, ZnImageUpdate, wi);
    *image_ptr = NULL;
  }
  return TCL_OK;
}

static Tcl_Obj *
ZnImagePrint(ClientData         client_data,
             Tk_Window          tkwin,
             char               *widget_rec,
             int                offset,
             Tcl_FreeProc       **free_proc)
{
  ZnImage image = *(ZnImage *) (widget_rec + offset);
  return Tcl_NewStringObj(image?ZnNameOfImage(image):"", -1);
}
#else
/*
 *----------------------------------------------------------------------
 *
 * ZnSetReliefOpt
 * ZnGetReliefOpt
 * ZnRestoreReliefOpt --
 *      Converter for the -relief option.
 *
 *----------------------------------------------------------------------
 */
static int
ZnSetReliefOpt(ClientData       client_data,
               Tcl_Interp       *interp,
               Tk_Window        tkwin,
               Tcl_Obj          **ovalue,
               char             *widget_rec,
               int              offset,
               char             *old_val_ptr,
               int              flags)
{
  ZnReliefStyle *relief_ptr;
  ZnReliefStyle relief;
  char          *value = Tcl_GetString(*ovalue);
  
  if (ZnGetRelief((ZnWInfo *) widget_rec, value, &relief) == TCL_ERROR) {
    return TCL_ERROR;
  }
  if (offset >= 0) {
    relief_ptr = (ZnReliefStyle *) (widget_rec + offset);
    *((ZnReliefStyle *) old_val_ptr) = *relief_ptr;
    *relief_ptr = relief;
  }
  return TCL_OK;
}

static Tcl_Obj *
ZnGetReliefOpt(ClientData       client_data,
               Tk_Window        tkwin,
               char             *widget_rec,
               int              offset)
{
  ZnReliefStyle relief = *(ZnReliefStyle *) (widget_rec + offset);
  return Tcl_NewStringObj(ZnNameOfRelief(relief), -1);
}

static void
ZnRestoreReliefOpt(ClientData   client_data,
                   Tk_Window    tkwin,
                   char         *val_ptr,
                   char         *old_val_ptr)
{
  *(ZnReliefStyle *) val_ptr = *(ZnReliefStyle *) old_val_ptr;
}

/*
 *----------------------------------------------------------------------
 *
 * ZnSetGradientOpt
 * ZnGetGradientOpt
 * ZnRestoreGradientOpt --
 *      Converter for the -*color* options.
 *
 *----------------------------------------------------------------------
 */
static int
ZnSetGradientOpt(ClientData     client_data,
                 Tcl_Interp     *interp,
                 Tk_Window      tkwin,
                 Tcl_Obj        **ovalue,
                 char           *widget_rec,
                 int            offset,
                 char           *old_val_ptr,
                 int            flags)
{
  ZnGradient    **grad_ptr;
  ZnGradient    *grad;
  char          *value = Tcl_GetString(*ovalue);

  if (offset >= 0) {
    if (*value == '\0') {
      grad = NULL;
    }
    else {
      grad = ZnGetGradient(interp, tkwin, value);
      if (grad == NULL) {
        return TCL_ERROR;
      }
    }
    grad_ptr = (ZnGradient **) (widget_rec + offset);
    *(ZnGradient **) old_val_ptr = *grad_ptr;
    *grad_ptr = grad;
  }
  return TCL_OK;
}

static Tcl_Obj *
ZnGetGradientOpt(ClientData     client_data,
                 Tk_Window      tkwin,
                 char           *widget_rec,
                 int            offset)
{
  ZnGradient *gradient = *(ZnGradient **) (widget_rec + offset);
  return Tcl_NewStringObj(ZnNameOfGradient(gradient), -1);
}

static void
ZnRestoreGradientOpt(ClientData client_data,
                     Tk_Window  tkwin,
                     char       *val_ptr,
                     char       *old_val_ptr)
{
  if (*(ZnGradient **) val_ptr != NULL) {
    ZnFreeGradient(*(ZnGradient **) val_ptr);
  }
  *(ZnGradient **) val_ptr = *(ZnGradient **) old_val_ptr;
}

static void
ZnFreeGradientOpt(ClientData    client_data,
                  Tk_Window     tkwin,
                  char          *val_ptr)
{
  if (*(ZnGradient **) val_ptr != NULL) {
    ZnFreeGradient(*(ZnGradient **) val_ptr);
  }
}
#endif


/*
 *----------------------------------------------------------------------
 *
 * ZnGetAlphaStipple --
 *      Need to be handled per screen/dpy toolkit wide, not on a
 *      widget basis.
 *
 *----------------------------------------------------------------------
 */
static Pixmap
ZnGetAlphaStipple(ZnWInfo       *wi,
                  unsigned int  val)
{
  if (val >= 255)
    return None;
  else
    return wi->alpha_stipples[(int) (val / 16)];
}

/*
 *----------------------------------------------------------------------
 *
 * ZnGetInactiveStipple --
 *
 *----------------------------------------------------------------------
 */
Pixmap
ZnGetInactiveStipple(ZnWInfo    *wi)
{
  return ZnGetAlphaStipple(wi, 128);
}


/*
 *----------------------------------------------------------------------
 *
 * ZnNeedRedisplay --
 *
 *----------------------------------------------------------------------
 */
void
ZnNeedRedisplay(ZnWInfo *wi)
{
  if (ISCLEAR(wi->flags, ZN_UPDATE_PENDING) && ISSET(wi->flags, ZN_REALIZED)) {
    /*printf("scheduling an update\n");*/
    Tcl_DoWhenIdle(Redisplay, (ClientData) wi);
    SET(wi->flags, ZN_UPDATE_PENDING);
  }
}

/*
 *----------------------------------------------------------------------
 *
 * ZnGetGlContext --
 *
 *  On AGL there is one context per window/widget. The Oldest context
 *  is used to share the resources until it is destroyed, this task is
 *  then transferred to the next older and so on.
 *  On the other platforms a single context is created and shared
 *  amongst all the windows for a sinlge display.
 *
 *----------------------------------------------------------------------
 */
#ifdef GL
ZnGLContextEntry *
ZnGetGLContext(Display *dpy)
{
  ZnGLContextEntry *cur, *last;
  
  //
  // Find the first context matching.
  for (cur = gl_contexts; cur && cur->dpy != dpy; cur = cur->next);

  if (!cur) {
    return cur;
  }

  //
  // Now proceed to the oldest.
  for (last = cur; cur->next; cur = cur->next) {
    if (cur->dpy == dpy) {
      last = cur;
    }
  }

  return last;
}

ZnGLContextEntry *
ZnGLMakeCurrent(Display *dpy,
                ZnWInfo *wi)
{
  ZnGLContextEntry *ce;

  ce = ZnGetGLContext(dpy);

#ifdef PLATFORM_SDL
  if (!ce && !wi) {
    return NULL;
  }
#endif

  if (!wi) {
    /* Get a zinc widget from the context struct
     * for this display. If no more are left,
     * returns, nothing can be done. This can
     * happen only when freeing images or fonts
     * after the last zinc on a given display has
     * been deleted. In this case the context should
     * be deleted, freeing all resources including
     * textures.
     */
    ZnWInfo **wip = ZnListArray(ce->widgets);
    int     i, num = ZnListSize(ce->widgets);

    for (i = 0; i <num; i++, wip++) {
      if ((*wip)->win != NULL) {
        wi = *wip;
        break;
      }
    }
    if (!wi) {
      return NULL;
    }
  }
#ifdef PLATFORM_SDL
  ce = wi->ce;
  if (ce) {
    SdlTkGLXMakeCurrent(dpy, Tk_WindowId(wi->win), ce->context);
  }
#else
#ifdef _WIN32
  ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
  ce->hdc = GetDC(ce->hwnd);
  SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd);

  if (!wglMakeCurrent(ce->hdc, ce->context)) {
    fprintf(stderr, "Can't make the GL context current: %d\n", GetLastError());
  }
#elif defined(MAC_OSX_TK)
  if (aglSetCurrentContext(ce->context) == GL_FALSE) {
    fprintf(stderr, "Can't make the GL context current\n");
  }
#else
  glXMakeCurrent(dpy, Tk_WindowId(wi->win), ce->context);
#endif
#endif
  return ce;
}

void
ZnGLReleaseContext(ZnWInfo *wi, ZnGLContextEntry *ce)
{
  if (ce) {
#ifdef PLATFORM_SDL
    if (wi) {
      SdlTkGLXReleaseCurrent(wi->dpy,
                             Tk_WindowId(wi->win),
                             wi->ce->context);
    }
    else {
      ZnWInfo **wip = ZnListArray(ce->widgets);
      int num = ZnListSize(ce->widgets);

      if (num > 0) {
        wi = wip[0];
        SdlTkGLXReleaseCurrent(wi->dpy,
                               Tk_WindowId(wi->win),
                               ce->context);
      }
    }
#else
#ifdef _WIN32
    wglMakeCurrent(NULL, NULL);
    ReleaseDC(ce->hwnd, ce->hdc);
#else
    /*glXMakeCurrent(ce->dpy, None, NULL);*/
#endif
#endif
  }
}

static void
ZnGLSwapBuffers(ZnGLContextEntry *ce,
                ZnWInfo          *wi)
{
  if (ce) {
#ifdef PLATFORM_SDL
    SdlTkGLXSwapBuffers(wi->dpy, Tk_WindowId(wi->win));
#else
#ifdef _WIN32
    SwapBuffers(ce->hdc);
#elif defined(MAC_OSX_TK)
    aglSwapBuffers(ce->context);
#else
    glXSwapBuffers(ce->dpy, Tk_WindowId(wi->win));
#endif
#endif
  }
}
#endif


#ifdef GL
static void
InitRendering1(ZnWInfo  *wi)
{

  if (wi->render) {
#ifdef PLATFORM_SDL
    ZnGLContextEntry *ce;
    ZnGLContext gl_context;

    if (wi->ce == NULL) {
      Tk_MakeWindowExist(wi->win); 
      gl_context = SdlTkGLXCreateContext(wi->dpy,  Tk_WindowId(wi->win),
                                         wi->win);
      if (gl_context) {
        ce = ZnMalloc(sizeof(ZnGLContextEntry));
        ce->context = gl_context;
        ce->dpy = wi->dpy;
        ce->max_tex_size = 64; /* Minimum value is always valid */
        ce->max_line_width = 1;
        ce->max_point_width = 1;
        ce->next = gl_contexts;
        gl_contexts = ce;
        wi->ce = ce;
        ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
        ZnListAdd(ce->widgets, &wi, ZnListTail);
      }
    }
#else
#  if !defined(_WIN32) && !defined(MAC_OSX_TK)
    ZnGLContextEntry *ce;
    ZnGLContext gl_context;
    XVisualInfo *gl_visual = NULL;
    Colormap    colormap = 0;

    ASSIGN(wi->flags, ZN_PRINT_CONFIG, (getenv("ZINC_GLX_INFO") != NULL));

    if (ISSET(wi->flags, ZN_PRINT_CONFIG)) {
      fprintf(stderr, "GLX version %d.%d\n", ZnMajorGlx, ZnMinorGlx);
    }
    
    /*
     * Look for a matching context already available.
     */
    ce = ZnGetGLContext(wi->dpy);
    if (ce) {
      gl_context = ce->context;
      gl_visual = ce->visual;
      colormap = ce->colormap;
      ZnListAdd(ce->widgets, &wi, ZnListTail);
    }
    else {
      int val;
      
      gl_visual = glXChooseVisual(wi->dpy,
                                  XScreenNumberOfScreen(wi->screen),
                                  ZnGLAttribs);
      if (!gl_visual) {
        fprintf(stderr, "No glx visual\n");
      }
      else {
        gl_context = glXCreateContext(wi->dpy, gl_visual,
                                      NULL, wi->render==1);
        if (!gl_context) {
          fprintf(stderr, "No glx context\n");
        }
        else {
          colormap = XCreateColormap(wi->dpy, RootWindowOfScreen(wi->screen),
                                     gl_visual->visual, AllocNone);
          ce = ZnMalloc(sizeof(ZnGLContextEntry));
          ce->context = gl_context;
          ce->visual = gl_visual;
          ce->colormap = colormap;
          ce->dpy = wi->dpy;
          ce->max_tex_size = 64; /* Minimum value is always valid */
          ce->max_line_width = 1;
          ce->max_point_width = 1;
          ce->next = gl_contexts;
          gl_contexts = ce;
          ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
          ZnListAdd(ce->widgets, &wi, ZnListTail);
          
          if (ISSET(wi->flags, ZN_PRINT_CONFIG)) {
            fprintf(stderr, "  Visual : 0x%x, ",
                    (int) gl_visual->visualid);
            glXGetConfig(wi->dpy, gl_visual, GLX_RGBA, &val);
            fprintf(stderr, "RGBA : %d, ", val);
            glXGetConfig(wi->dpy, gl_visual, GLX_DOUBLEBUFFER, &val);
            fprintf(stderr, "Double Buffer : %d, ", val);
            glXGetConfig(wi->dpy, gl_visual, GLX_STENCIL_SIZE, &val);
            fprintf(stderr, "Stencil : %d, ", val);
            glXGetConfig(wi->dpy, gl_visual, GLX_BUFFER_SIZE, &val);
            fprintf(stderr, "depth : %d, ", val);
            glXGetConfig(wi->dpy, gl_visual, GLX_RED_SIZE, &val);
            fprintf(stderr, "red : %d, ", val);
            glXGetConfig(wi->dpy, gl_visual, GLX_GREEN_SIZE, &val);
            fprintf(stderr, "green : %d, ", val);
            glXGetConfig(wi->dpy, gl_visual, GLX_BLUE_SIZE, &val);
            fprintf(stderr, "blue : %d, ", val);
            glXGetConfig(wi->dpy, gl_visual, GLX_ALPHA_SIZE, &val);
            fprintf(stderr, "alpha : %d\n", val);
            fprintf(stderr, "  Direct Rendering: %d\n",
                    glXIsDirect(wi->dpy, gl_context));
          }
        }
      }
    }
    if (gl_visual && colormap) {
      Tk_SetWindowVisual(wi->win, gl_visual->visual, 24, colormap);
    }
#  endif
#endif
  }
}

#if defined(MAC_OSX_TK)
static void
UpdateBufferRect(ZnGLContextEntry *ce,
                 Tk_Window        win)
{
  GLint rect[4];
  Rect  bounds;

  TkMacOSXWinBounds((TkWindow *) win, &bounds);
  rect[0] = bounds.left;
  rect[1] = Tk_Height(ce->top_win) - bounds.bottom;
  rect[2] = bounds.right - bounds.left;
  rect[3] = bounds.bottom - bounds.top;;
  //printf("BUFFER_RECT: %d %d %d %d\n", rect[0], rect[1], rect[2], rect[3]);
  aglSetInteger(ce->context, AGL_BUFFER_RECT, rect);
  aglEnable(ce->context, AGL_BUFFER_RECT);
}
#endif

static void
InitRendering2(ZnWInfo   *wi,
               Tk_Window top_level)
{
  ZnGLContextEntry *ce;
#ifndef PLATFORM_SDL
  ZnGLContext      gl_context;
#endif
  GLfloat          r[2]; /* Min, Max */
  GLint            i[1];

  if (wi->render) {
    /*
     * Look for a matching context already available.
     */
#ifdef PLATFORM_SDL
    ce = wi->ce;
#else
    ce = ZnGetGLContext(wi->dpy);
#endif

#if defined(_WIN32) && !defined(PLATFORM_SDL)
    if (ce) {
      gl_context = ce->context;
      ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
      ce->hdc = GetDC(ce->hwnd);
      ZnListAdd(ce->widgets, &wi, ZnListTail);
      SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd);
    }
    else {
      ce = ZnMalloc(sizeof(ZnGLContextEntry));
      ce->hwnd = Tk_GetHWND(Tk_WindowId(wi->win));
      ce->hdc = GetDC(ce->hwnd);
      ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
      ZnListAdd(ce->widgets, &wi, ZnListTail);

      memset(&ce->pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
      ce->pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
      ce->pfd.nVersion = 1;
      ce->pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
      ce->pfd.iPixelType = PFD_TYPE_RGBA;
      ce->pfd.cRedBits = 8;
      ce->pfd.cGreenBits = 8;
      ce->pfd.cBlueBits = 8;
      ce->pfd.cAlphaBits = 8;
      ce->pfd.cStencilBits = 8;
      ce->pfd.iLayerType = PFD_MAIN_PLANE;
      ce->ipixel = ChoosePixelFormat(ce->hdc, &ce->pfd);
      /*printf("ipixel=%d dwFlags=0x%x req=0x%x iPixelType=%d hdc=%d\n",
        ce->ipixel,     ce->pfd.dwFlags,
        PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,       
        ce->pfd.iPixelType==PFD_TYPE_RGBA,
        ce->hdc);*/
      if (!ce->ipixel ||
          (ce->pfd.cRedBits != 8) || (ce->pfd.cGreenBits != 8) || (ce->pfd.cBlueBits != 8) ||
          (ce->pfd.cStencilBits != 8)) {
        fprintf(stderr, "ChoosePixelFormat failed\n");
      }
      
      if (SetPixelFormat(ce->hdc, ce->ipixel, &ce->pfd) == TRUE) {
        gl_context = wglCreateContext(ce->hdc);
        if (gl_context) {
          ce->context = gl_context;
          ce->dpy = wi->dpy;
          ce->max_tex_size = 64; /* Minimum value is always valid */
          ce->max_line_width = 1;
          ce->max_point_width = 1;
          ce->next = gl_contexts;
          gl_contexts = ce;
        }
        else {
          fprintf(stderr, "wglCreateContext failed\n");
          ZnFree(ce);
        }
      }
      else {
        ZnFree(ce);
      }
    }
    ReleaseDC(ce->hwnd, ce->hdc);
    
#elif defined(MAC_OSX_TK)

    {
      AGLPixelFormat pix_fmt;
      GLenum         err;
  
      pix_fmt = aglChoosePixelFormat(NULL, 0, ZnGLAttribs);
      err = aglGetError();
      if (pix_fmt && (err == AGL_NO_ERROR)) {
        gl_context = aglCreateContext(pix_fmt, ce ? ce->context : NULL);
        err = aglGetError();
      }
      else {
        fprintf(stderr, "error when selecting a pixel format 0x%x %d\n", pix_fmt, err);
        return;
      }
      if ((err != AGL_NO_ERROR) || (gl_context == NULL)) {
        fprintf(stderr, "No GL context\n");
        return;
      }
      else {
        ce = ZnMalloc(sizeof(ZnGLContextEntry));
        ce->widgets = ZnListNew(1, sizeof(ZnWInfo *));
        ZnListAdd(ce->widgets, &wi, ZnListTail);

        ce->context = gl_context;
        ce->dpy = wi->dpy;
        ce->max_tex_size = 64; /* Minimum value is always valid */
        ce->max_line_width = 1;
        ce->max_point_width = 1;
        ce->next = gl_contexts;
        gl_contexts = ce;
        ce->pix_fmt = pix_fmt;
        ce->gworld = TkMacOSXGetDrawablePort(Tk_WindowId(wi->win));
        ce->top_win = top_level;
        if (aglSetDrawable(ce->context, ce->gworld) == GL_FALSE) {
          fprintf(stderr, "Can't attach the window to the GL context\n");
        }
      }
    }
    
#endif

    ce = ZnGLMakeCurrent(wi->dpy, wi);
    glGetFloatv(ZN_GL_LINE_WIDTH_RANGE, r);
    ce->max_line_width = r[1];
    glGetFloatv(ZN_GL_POINT_SIZE_RANGE, r);
    ce->max_point_width = r[1];
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, i);
    ce->max_tex_size = (unsigned int) i[0];
    
    if (ISSET(wi->flags, ZN_PRINT_CONFIG)) {
      fprintf(stderr, "OpenGL version %s\n",
              (char *) glGetString(GL_VERSION));
      fprintf(stderr, "  Rendering engine: %s, ",
              (char *) glGetString(GL_RENDERER));
      fprintf(stderr, "  Vendor: %s\n",
              (char *) glGetString(GL_VENDOR));
      fprintf(stderr, "  Available extensions: %s\n",
              (char *) glGetString(GL_EXTENSIONS));
      fprintf(stderr, "Max antialiased line width: %g\n",
              ce->max_line_width);
      fprintf(stderr, "Max antialiased point size: %g\n",
              ce->max_point_width);
      fprintf(stderr, "Max texture size: %d\n",
              ce->max_tex_size);
    }

#if defined(MAC_OSX_TK)
    UpdateBufferRect(ce, wi->win);
#endif
    ZnGLReleaseContext(wi, ce);
  }
}
#endif /* GL */


/*
 *----------------------------------------------------------------------
 *
 * ZincObjCmd --
 *
 *      This procedure is invoked to process the "zinc" Tcl
 *      command.  It creates a new "zinc" widget.
 *
 *----------------------------------------------------------------------
 */
EXTERN int
ZincObjCmd(ClientData           client_data,    /* Main window associated with
                                                 * interpreter. */
           Tcl_Interp           *interp,        /* Current interpreter. */
           int                  argc,           /* Number of arguments. */
           Tcl_Obj      *CONST  args[])         /* Argument strings. */
{
  Tk_Window     top_w = (Tk_Window) client_data;
  ZnWInfo       *wi;
  Tk_Window     tkwin;
#ifndef PTK_800
  Tk_OptionTable opt_table;
#endif
  unsigned int  num;
  ZnBool        has_gl = False;
#ifndef PLATFORM_SDL
# if !defined(_WIN32) && !defined(MAC_OSX_TK)
#  if defined(GL) || defined(SHAPE)
  int           major_op, first_err, first_evt;
#  endif
#  ifdef GL
  Display       *dpy = Tk_Display(top_w);
  Screen        *screen = Tk_Screen(top_w);
#  endif
# endif
#endif

  InitZinc(interp);

#ifdef GL
#  if defined(_WIN32) || defined(MAC_OSX_TK)
  has_gl = True;
#  elif defined(PLATFORM_SDL)
  has_gl = SdlTkGLXAvailable(Tk_Display(top_w));
#  else
  if (XQueryExtension(dpy, "GLX", &major_op, &first_evt, &first_err)) {
    if (glXQueryExtension(dpy, &first_err, &first_evt)) {
      if (glXQueryVersion(dpy, &ZnMajorGlx, &ZnMinorGlx)) {
        if ((ZnMajorGlx == 1) && (ZnMinorGlx >= 1)) {
          has_gl = True;
        }
      }
    }
  }
  if (has_gl) {
    XVisualInfo *visual = glXChooseVisual(dpy,
                                          XScreenNumberOfScreen(screen),
                                          ZnGLAttribs);
    if (visual) {
      XFree(visual);
    }
    else {
      has_gl = False;
    }
  }
#  endif
#endif

  if (argc == 1) {
    Tcl_AppendResult(interp, PACKAGE_VERSION, NULL);
    Tcl_AppendResult(interp, " X11", NULL);
#ifdef GL
#  ifdef _WIN32
    Tcl_AppendResult(interp, " GL", NULL);
#  else
    if (has_gl) {
      Tcl_AppendResult(interp, " GL", NULL);
    }
#  endif
#endif
    return TCL_OK;
  }

  tkwin = Tk_CreateWindowFromPath(interp, top_w, Tcl_GetString(args[1]), NULL);
  if (tkwin == NULL) {
    return TCL_ERROR;
  }

#ifndef PTK_800
  opt_table = Tk_CreateOptionTable(interp, option_specs);
 #endif

  Tk_SetClass(tkwin, "Zinc");
  
  /*
   * Allocate and initialize the widget record.
   */  
  wi = (ZnWInfo *) ZnMalloc(sizeof(ZnWInfo));
  wi->win = tkwin;
  wi->interp = interp;
  wi->dpy = Tk_Display(tkwin);
  wi->screen = Tk_Screen(tkwin);
  wi->flags = 0;
  wi->render = -1;
  wi->real_top = None;
#if defined(GL) && defined(ROTATION)
  wi->screen_rotation = 0;
  wi->enable_rotation = 0;
#endif

  ASSIGN(wi->flags, ZN_HAS_GL, has_gl);
#if defined(SHAPE)
  ASSIGN(wi->flags, ZN_HAS_X_SHAPE,
         XQueryExtension(wi->dpy, "SHAPE", &major_op, &first_evt, &first_err));
  wi->reshape = wi->full_reshape = True;
#else
  CLEAR(wi->flags, ZN_HAS_X_SHAPE);
  wi->reshape = wi->full_reshape = False;
#endif

#ifdef PTK
#ifdef PTK_800
  wi->cmd = Lang_CreateWidget(interp, tkwin, (Tcl_CmdProc *) WidgetObjCmd,
                              (ClientData) wi, CmdDeleted);
#else
  wi->cmd = Lang_CreateWidget(interp, tkwin, WidgetObjCmd, (ClientData) wi, CmdDeleted);
#endif
#else
  wi->cmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin), WidgetObjCmd,
                                 (ClientData) wi, CmdDeleted);
#endif
#ifndef PTK_800
  wi->opt_table = opt_table;
#endif
  wi->binding_table = 0;
  wi->fore_color = NULL;
  wi->back_color = NULL;
  wi->relief_grad = NULL;
  wi->bbox_color = NULL;
  wi->draw_bboxes = 0;
  wi->light_angle = 120;
  wi->follow_pointer = 0;
  wi->border_width = 0;
  wi->relief = ZN_RELIEF_FLAT;
  wi->opt_width = None;
  wi->opt_height = None;
#ifdef GL
  wi->font_tfi = NULL;
#endif
  wi->font = 0;
#ifdef ATC
  wi->track_visible_history_size = 0;
  wi->track_managed_history_size = 0;
  wi->speed_vector_length = 0;
  wi->map_text_font = 0;
#  ifdef GL
  wi->map_font_tfi = NULL;
#  ifdef PLATFORM_SDL
  wi->ce = NULL;
#  endif
#  endif
  wi->map_distance_symbol = ZnUnspecifiedImage;
  wi->track_symbol = ZnUnspecifiedImage;
#  ifndef PTK_800
  wi->map_symbol_obj = NULL;
  wi->track_symbol_obj = NULL;
#  endif
#endif
  wi->tile = ZnUnspecifiedImage;
#ifndef PTK_800
  wi->tile_obj = NULL;
#endif
  wi->cursor = None;
  wi->hot_item = ZN_NO_ITEM;
  wi->hot_prev = ZN_NO_ITEM;
  wi->confine = 0;
  wi->origin.x = wi->origin.y = 0;
  wi->scroll_xo = wi->scroll_yo = 0;
  wi->scroll_xc = wi->scroll_yc = 0;
  wi->x_scroll_incr = wi->y_scroll_incr = 0;
  wi->x_scroll_cmd = wi->y_scroll_cmd = NULL;
  wi->region = NULL;

  wi->id_table = (Tcl_HashTable *) ZnMalloc(sizeof(Tcl_HashTable));
  Tcl_InitHashTable(wi->id_table, TCL_ONE_WORD_KEYS);
  wi->t_table = (Tcl_HashTable *) ZnMalloc(sizeof(Tcl_HashTable));
  Tcl_InitHashTable(wi->t_table, TCL_STRING_KEYS);

  wi->obj_id = 1;
  wi->num_items = 0;

  wi->top_group = ZnCreateItem(wi, ZnGroup, 0, NULL);

#ifdef ATC
  wi->om_group_id = 0;
  wi->om_group = wi->top_group;
  OmRegister((void *) wi, ZnSendTrackToOm, ZnSetLabelAngleFromOm, ZnQueryLabelPosition);
#endif
  wi->gc = 0;
  wi->draw_buffer = 0;
  wi->pick_aperture = 0;
  wi->state = 0;
  memset(&wi->pick_event, 0, sizeof(XEvent));
  wi->new_item = wi->current_item = ZN_NO_ITEM;
  wi->new_part = wi->current_part = ZN_NO_PART;
  wi->focus_item = ZN_NO_ITEM;
  wi->focus_field = ZN_NO_PART;

  CLEAR(wi->flags, ZN_MONITORING);
#ifndef _WIN32
  wi->total_draw_chrono = ZnNewChrono("Total draw time");
  wi->this_draw_chrono = ZnNewChrono("Last draw time");
#endif
  wi->damaged_area_w = wi->damaged_area_h = 0;
  
  /*
   * Viewport item management init
   */
  wi->nb_of_viewport_items = 0;
  
  
  /*
   * Text management init.
   */
  wi->text_info.sel_color = NULL;
  wi->text_info.sel_item = ZN_NO_ITEM;
  wi->text_info.sel_field = ZN_NO_PART;
  wi->text_info.sel_first = -1;
  wi->text_info.sel_last = -1;
  wi->text_info.anchor_item = ZN_NO_ITEM;
  wi->text_info.anchor_field = ZN_NO_PART;
  wi->text_info.sel_anchor = 0;
  wi->text_info.insert_color = NULL;
  wi->text_info.insert_width = 0;
  wi->text_info.cursor_on = False;
  wi->insert_on_time = 0;
  wi->insert_off_time = 0;
  wi->blink_handler = NULL;
  wi->take_focus = NULL;
  wi->highlight_width = 0;
  wi->highlight_color = NULL;
  wi->highlight_bg_color = NULL;
  ZnResetBBox(&wi->exposed_area);
  ZnResetBBox(&wi->damaged_area);
  
  ZnInitClipStack(wi);  
  ZnInitTransformStack(wi);

  for (num = 0; num < ZN_NUM_ALPHA_STEPS; num++) {
    char        name[TCL_INTEGER_SPACE+12];

    sprintf(name, "AlphaStipple%d", num);
    wi->alpha_stipples[num] = Tk_GetBitmap(interp, tkwin, Tk_GetUid(name));
  }

  Tk_CreateEventHandler(tkwin,
                        ExposureMask|StructureNotifyMask|FocusChangeMask,
                        Event, (ClientData) wi);
  Tk_CreateEventHandler(tkwin, KeyPressMask|KeyReleaseMask|
                        ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
                        LeaveWindowMask|PointerMotionMask|VirtualEventMask|
                        MouseWheelMask,
                        Bind, (ClientData) wi);
  Tk_CreateSelHandler(tkwin, XA_PRIMARY, XA_STRING,
                      FetchSelection, (ClientData) wi, XA_STRING);

#ifdef PTK_800
  if (Configure(interp, wi, argc-2, args+2, 0) != TCL_OK) {
    Tk_DestroyWindow(tkwin);
    return TCL_ERROR;
  }  
#else
  if (Tk_InitOptions(interp, (char *) wi, opt_table, tkwin) != TCL_OK) {
    Tk_DestroyWindow(tkwin);
    return TCL_ERROR;
  }

  if (Configure(interp, wi, argc-2, args+2) != TCL_OK) {
    Tk_DestroyWindow(tkwin);
    return TCL_ERROR;
  }  
#endif

  wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0;
  wi->damaged_area.corner.x = wi->width = wi->opt_width;
  wi->damaged_area.corner.y = wi->height = wi->opt_height;

  if (!wi->render) {
  /*
   * Allocate double buffer pixmap/image.
   */
    wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
                                   wi->opt_width, wi->opt_height, Tk_Depth(wi->win));
  }

#ifdef GL
  else {
    InitRendering1(wi);
#ifdef ROTATION
    wi->canvastex = 0;
    wi->fbo = 0;
    wi->depthstencil = 0;
    SET(wi->flags, ZN_UPDATE_CANVASTEX);
#endif
  }
#endif

#ifdef PTK
  Tcl_SetObjResult(interp, LangWidgetObj(interp, tkwin));
#else
  Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tkwin), -1));
#endif
  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * EncodeItemPart --
 *
 *      Form a ClientData value from an item/part that is suitable
 *      as a key in a binding table.
 *
 *----------------------------------------------------------------------
 */
ClientData
EncodeItemPart(ZnItem   item,
               int      part)
{
  if (part >= 0) {
    ZnFieldSet fs;
    if (!item->class->GetFieldSet) {
      return item;
    }
    fs = item->class->GetFieldSet(item);
    return (ClientData) (ZnFIELD.GetFieldStruct(fs, part % (int) ZnFIELD.NumFields(fs)));
  }
  else if (part == ZN_NO_PART) {
    return item;
  }
  return (ClientData) (((char *) item)-part);
}


/*
 *--------------------------------------------------------------
 *
 * All tag search procs below are lifted from tkCanvas.c, then
 * modified to match our needs.
 *
 *--------------------------------------------------------------
 */

/*
 *--------------------------------------------------------------
 *
 * TagSearchExprInit --
 *
 *      This procedure allocates and initializes one
 *      TagSearchExpr struct.
 *
 *--------------------------------------------------------------
 */
static void
TagSearchExprInit(TagSearchExpr **expr_var)
{
  TagSearchExpr* expr = *expr_var;

  if (! expr) {
    expr = (TagSearchExpr *) ZnMalloc(sizeof(TagSearchExpr));
    expr->allocated = 0;
    expr->uids = NULL;
    expr->next = NULL;
  }
  expr->uid = NULL;
  expr->index = 0;
  expr->length = 0;
  *expr_var = expr;
}


/*
 *--------------------------------------------------------------
 *
 * TagSearchExprDestroy --
 *
 *      This procedure destroys one TagSearchExpr structure.
 *
 *--------------------------------------------------------------
 */
static void
TagSearchExprDestroy(TagSearchExpr      *expr)
{
  if (expr) {
    if (expr->uids) {
      ZnFree(expr->uids);
    }
    ZnFree(expr);
  }
}


/*
 *--------------------------------------------------------------
 *
 * TagSearchScanExpr --
 *
 *      This recursive procedure is called to scan a tag expression
 *      and compile it into an array of Tk_Uids.
 *
 * Results:
 *      The return value indicates if the tagOrId expression
 *      was successfully scanned (syntax).
 *      The information at *search is initialized
 *      such that a call to ZnTagSearchFirst, followed by
 *      successive calls to ZnTagSearchNext will return items
 *      that match tag.
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */
static int
TagSearchScanExpr(Tcl_Interp    *interp,        /* Current interpreter. */
                  ZnTagSearch   *search,        /* Search data */
                  TagSearchExpr *expr)          /* Compiled expression result */
{
  int   looking_for_tag; /* When true, scanner expects next char(s)
                          * to be a tag, else operand expected */
  int   found_tag;      /* One or more tags found */
  int   found_endquote; /* For quoted tag string parsing */
  int   negate_result;  /* Pending negation of next tag value */
  char  *tag;           /* tag from tag expression string */
  char  c;

  negate_result = 0;
  found_tag = 0;
  looking_for_tag = 1;
  while (search->tag_index < search->tag_len) {
    c = search->tag[search->tag_index++];
    
    if (expr->allocated == expr->index) {
      expr->allocated += 15;
      if (expr->uids) {
        expr->uids = (Tk_Uid *) ZnRealloc((char *) expr->uids,
                                          expr->allocated * sizeof(Tk_Uid));
      }
      else {
        expr->uids = (Tk_Uid *) ZnMalloc(expr->allocated * sizeof(Tk_Uid));
      }
    }
    
    if (looking_for_tag) {
      switch (c) {
      case ' ': /* ignore unquoted whitespace */
      case '\t':
      case '\n':
      case '\r':
        break;
      case '!': /* negate next tag or subexpr */
        if (looking_for_tag > 1) {
          Tcl_AppendResult(interp, "Too many '!' in tag search expression",
                           (char *) NULL);
          return TCL_ERROR;
        }
        looking_for_tag++;
        negate_result = 1;
        break;
      case '(': /* scan (negated) subexpr recursively */
        if (negate_result) {
          expr->uids[expr->index++] = neg_paren_uid;
          negate_result = 0;
        }
        else {
          expr->uids[expr->index++] = paren_uid;
        }
        if (TagSearchScanExpr(interp, search, expr) != TCL_OK) {
          /* Result string should be already set
           * by nested call to tag_expr_scan() */
          return TCL_ERROR;
        }
        looking_for_tag = 0;
        found_tag = 1;
        break;
      case '"': /* quoted tag string */
        if (negate_result) {
          expr->uids[expr->index++] = neg_tag_val_uid;
          negate_result = 0;
        }
        else {
          expr->uids[expr->index++] = tag_val_uid;
        }
        tag = search->rewrite_buf;
        found_endquote = 0;
        while (search->tag_index < search->tag_len) {
          c = search->tag[search->tag_index++];
          if (c == '\\') {
            c = search->tag[search->tag_index++];
          }
          if (c == '"') {
            found_endquote = 1;
            break;
          }
          *tag++ = c;
        }
        if (! found_endquote) {
          Tcl_AppendResult(interp, "Missing endquote in tag search expression",
                           (char *) NULL);
          return TCL_ERROR;
        }
        if (! (tag - search->rewrite_buf)) {
          Tcl_AppendResult(interp,
                           "Null quoted tag string in tag search expression",
                           (char *) NULL);
          return TCL_ERROR;
        }
        *tag++ = '\0';
        expr->uids[expr->index++] = Tk_GetUid(search->rewrite_buf);
        looking_for_tag = 0;
        found_tag = 1;
        break;
      case '&': /* illegal chars when looking for tag */
      case '|':
      case '^':
      case ')':
        Tcl_AppendResult(interp, "Unexpected operator in tag search expression",
                         (char *) NULL);
        return TCL_ERROR;
      default:  /* unquoted tag string */
        if (negate_result) {
          expr->uids[expr->index++] = neg_tag_val_uid;
          negate_result = 0;
        }
        else {
          expr->uids[expr->index++] = tag_val_uid;
        }
        tag = search->rewrite_buf;
        *tag++ = c;
        /* copy rest of tag, including any embedded whitespace */
        while (search->tag_index < search->tag_len) {
          c = search->tag[search->tag_index];
          if ((c == '!') || (c == '&') || (c == '|') || (c == '^') ||
              (c == '(') || (c == ')') || (c == '"')) {
            break;
          }
          *tag++ = c;
          search->tag_index++;
        }
        /* remove trailing whitespace */
        while (1) {
          c = *--tag;
          /* there must have been one non-whitespace char,
           *  so this will terminate */
          if ((c != ' ') && (c != '\t') && (c != '\n') && (c != '\r')) {
            break;
          }
        }
        *++tag = '\0';
        expr->uids[expr->index++] = Tk_GetUid(search->rewrite_buf);
        looking_for_tag = 0;
        found_tag = 1;
      }
      
    }
    else {    /* ! looking_for_tag */  
      switch (c) {
      case ' '  :       /* ignore whitespace */
      case '\t' :
      case '\n' :
      case '\r' :
        break;
      case '&'  :       /* AND operator */
        c = search->tag[search->tag_index++];
        if (c != '&') {
          Tcl_AppendResult(interp, "Singleton '&' in tag search expression",
                           (char *) NULL);
          return TCL_ERROR;
        }
        expr->uids[expr->index++] = and_uid;
        looking_for_tag = 1;
        break;
      case '|'  :       /* OR operator */
        c = search->tag[search->tag_index++];
        if (c != '|') {
          Tcl_AppendResult(interp, "Singleton '|' in tag search expression",
                           (char *) NULL);
          return TCL_ERROR;
        }
        expr->uids[expr->index++] = or_uid;
        looking_for_tag = 1;
        break;
      case '^'  :       /* XOR operator */
        expr->uids[expr->index++] = xor_uid;
        looking_for_tag = 1;
        break;
      case ')'  :       /* end subexpression */
        expr->uids[expr->index++] = end_paren_uid;
        goto breakwhile;
      default   :       /* syntax error */
        Tcl_AppendResult(interp,
                         "Invalid boolean operator in tag search expression",
                         (char *) NULL);
        return TCL_ERROR;
      }
    }
  }
 breakwhile:
  if (found_tag && ! looking_for_tag) {
    return TCL_OK;
  }
  Tcl_AppendResult(interp, "Missing tag in tag search expression",
                   (char *) NULL);
  return TCL_ERROR;
}


/*
 *--------------------------------------------------------------
 *
 * TagSearchEvalExpr --
 *
 *      This recursive procedure is called to eval a tag expression.
 *
 * Results:
 *      The return value indicates if the tagOrId expression
 *      successfully matched the tags of the current item.
 *
 * Side effects:
 *
 *--------------------------------------------------------------
 */
static int
TagSearchEvalExpr(TagSearchExpr *expr,  /* Search expression */
                  ZnItem        item)   /* Item being test for match */
{
  int           looking_for_tag; /* When true, scanner expects next char(s)
                                  * to be a tag, else operand expected */
  int           negate_result;  /* Pending negation of next tag value */
  Tk_Uid        uid;
  int           result=0;       /* Value of expr so far */
  int           paren_depth;
  
  negate_result = 0;
  looking_for_tag = 1;
  while (expr->index < expr->length) {
    uid = expr->uids[expr->index++];
    if (looking_for_tag) {
      if (uid == tag_val_uid) {
        /*
         * assert(expr->index < expr->length);
         */
        uid = expr->uids[expr->index++];
        /*
         * set result 1 if tag is found in item's tags
         */
        result = ZnITEM.HasTag(item, uid) ? 1 : 0;
      }
      else if (uid == neg_tag_val_uid) {
        negate_result = ! negate_result;
        /*
         * assert(expr->index < expr->length);
         */
        uid = expr->uids[expr->index++];
        /*
         * set result 1 if tag is found in item's tags
         */
        result = ZnITEM.HasTag(item, uid) ? 1 : 0;
      }
      else if (uid == paren_uid) {
        /*
         * evaluate subexpressions with recursion
         */
        result = TagSearchEvalExpr(expr, item);
      }
      else if (uid == neg_paren_uid) {
        negate_result = ! negate_result;
        /*
         * evaluate subexpressions with recursion
         */
        result = TagSearchEvalExpr(expr, item);
        /*
         * } else {
         *  assert(0);
         */
      }
      if (negate_result) {
        result = ! result;
        negate_result = 0;
      }
      looking_for_tag = 0;
    }
    else {    /* ! looking_for_tag */
      if (((uid == and_uid) && (!result)) || ((uid == or_uid) && result)) {
        /*
         * short circuit expression evaluation
         *
         * if result before && is 0, or result before || is 1, then
         * the expression is decided and no further evaluation is needed.
         */
        paren_depth = 0;
        while (expr->index < expr->length) {
          uid = expr->uids[expr->index++];
          if ((uid == tag_val_uid) || (uid == neg_tag_val_uid)) {
            expr->index++;
            continue;
          }
          if ((uid == paren_uid) || (uid == neg_paren_uid)) {
            paren_depth++;
            continue;
          } 
          if (uid == end_paren_uid) {
            paren_depth--;
            if (paren_depth < 0) {
              break;
            }
          }
        }
        return result;
        
      }
      else if (uid == xor_uid) {
        /*
         * if the previous result was 1 then negate the next result.
         */
        negate_result = result;
      }
      else if (uid == end_paren_uid) {
        return result;
        /*
         * } else {
         *  assert(0);
         */
      }
      looking_for_tag = 1;
    }
  }
  /*
   * assert(! looking_for_tag);
   */
  return result;
}


static ZnItem
LookupGroupFromPath(ZnItem       start,
                    Tk_Uid       *names,
                    unsigned int num_names)
{
  Tk_Uid        name, *tags;
  unsigned int  count;
  ZnBool        recursive;
  ZnItem        result, current = ZnGroupHead(start);

  if (num_names == 0) {
    return start;
  }

  name = names[1];
  recursive = (names[0] == star_uid);
  /*  printf("LookupGroupFromPath; group: %d, nom: %s, recursive: %s\n",
      start->id, name, names[0]);*/
  while (current != ZN_NO_ITEM) {
    if ((current->class == ZnGroup) && (current->tags)) {
      tags = ZnListArray(current->tags);
      count = ZnListSize(current->tags);
      for (; count > 0; tags++, count--) {
        if (name == *tags) {
          if (num_names > 2) {
            result = LookupGroupFromPath(current, names+2, num_names-2);
            return result;
          }
          else {
            return current;
          }
        }
      }
      /*
       * This group doesn't match try to search depth first.
       */
      if (recursive) {
        result = LookupGroupFromPath(current, names, num_names);
        if (result != ZN_NO_ITEM) {
          return result;
        }
      }
    }
    current = current->next;
  }

  return ZN_NO_ITEM;
}


/*
 *--------------------------------------------------------------
 *
 * ZnTagSearchScan --
 *
 *      This procedure is called to initiate an enumeration of
 *      all items in a given zinc that contain a tag that matches
 *      the tagOrId expression.
 *
 * Results:
 *      The return value indicates if the tagOrId expression
 *      was successfully scanned (syntax).
 *      The information at *search is initialized such that a
 *      call to ZnTagSearchFirst, followed by successive calls
 *      to ZnTagSearchNext will return items that match tag.
 *
 * Side effects:
 *      search is linked into a list of searches in progress
 *      in zinc, so that elements can safely be deleted while
 *      the search is in progress.
 *
 *--------------------------------------------------------------
 */
static int
ZnTagSearchScan(ZnWInfo   *wi,
                Tcl_Obj   *tag_obj,       /* Object giving tag value, NULL
                                           * is the same as 'all'. */
                ZnTagSearch **search_var) /* Record describing tag search;
                                           * will be initialized here. */
{
  Tk_Uid        tag;
  int           i;
  ZnTagSearch   *search;
  ZnItem        group = wi->top_group;
  ZnBool        recursive = True;

  if (tag_obj) {
    tag = Tcl_GetString(tag_obj);
  }
  else {
    tag = all_uid;
  }
  
  /*
   * Initialize the search.
   */
  if (*search_var) {
    search = *search_var;
  }
  else {
    /* Allocate primary search struct on first call */
    *search_var = search = (ZnTagSearch *) ZnMalloc(sizeof(ZnTagSearch));
    search->expr = NULL;
    
    /* Allocate buffer for rewritten tags (after de-escaping) */
    search->rewrite_buf_alloc = 100;
    search->rewrite_buf = ZnMalloc(search->rewrite_buf_alloc);
    search->item_stack = ZnListNew(16, sizeof(ZnItem));
  }
  TagSearchExprInit(&(search->expr));
  
  /* How long is the tagOrId ? */
  search->tag_len = strlen(tag);
  
  /*
   * Short-circuit impossible searches for null tags and
   * mark the search as 'over' for ZnTagSearchFirst and
   * ZnTagSearchNext. This test must not be migrated before
   * allocating search structures or special care must be
   * taken in ZnTagSearchDestroy to avoid deallocating unallocated
   * memory.
   */
  if (search->tag_len == 0) {
    search->over = True;
    return TCL_OK;
  }
  
  /*
   * If a path specification exists in the tag, strip it from the
   * tag and search for a matching group.
   */
  if (strpbrk(tag, ".*")) {
    Tk_Uid path;
    char         c, *next;
    unsigned int id;
    Tcl_HashEntry *entry;

    ZnListEmpty(ZnWorkStrings);
    recursive = False;
    if ((*tag == '.') || (*tag == '*')) {
      recursive = (*tag == '*');
      tag++;
    }
    path = tag;
    while ((next = strpbrk(path, ".*"))) {
      if (isdigit(*path)) {
        if (path == tag) { /* Group id is ok only in first section. */
          c = *next;
          *next = '\0';
          id = strtoul(path, NULL, 10);
          *next = c;
          group = wi->hot_item;
          if ((group == ZN_NO_ITEM) || (group->id != id)) {
            entry = Tcl_FindHashEntry(wi->id_table, (char *) id);
            if (entry != NULL) {
              group = (ZnItem) Tcl_GetHashValue(entry);
            }
            else {
              Tcl_AppendResult(wi->interp, "unknown group in path \"",
                               tag, "\"", NULL);
              return TCL_ERROR;
            }
          }
          if (group->class != ZnGroup) {
            Tcl_AppendResult(wi->interp, "item is not a group in path \"",
                             tag, "\"", NULL);
            return TCL_ERROR;
          }
        }
        else {
          Tcl_AppendResult(wi->interp, "misplaced group id in path \"",
                           tag, "\"", NULL);
          return TCL_ERROR;
        }
      }
      else {
        ZnListAdd(ZnWorkStrings,
                  (void *) (recursive ? &star_uid : &dot_uid),
                  ZnListTail);
        c = *next;
        *next = '\0';
        path = Tk_GetUid(path);
        *next = c;
        ZnListAdd(ZnWorkStrings, (void *) &path, ZnListTail);
      }
      recursive = (*next == '*');
      path = next+1;
    }

    group = LookupGroupFromPath(group,
                                ZnListArray(ZnWorkStrings),
                                ZnListSize(ZnWorkStrings));
    if (group == ZN_NO_ITEM) {
      Tcl_AppendResult(wi->interp, "path does not lead to a valid group\"",
                       tag, "\"", NULL);
      return TCL_ERROR;
    }

    /*
     * Adjust tag to strip the path.
     */
    tag = path;
    search->tag_len = strlen(tag);
    /*
     * If the tag consist only in a path description
     * assume that the tag all is implied.
     */
    if (search->tag_len == 0) {
      tag = all_uid;
      search->tag_len = strlen(tag);
    }
  }
  
  /*
   * Make sure there is enough buffer to hold rewritten tags (30%).
   */
  if ((unsigned int)(search->tag_len*1.3) >= search->rewrite_buf_alloc) {
    search->rewrite_buf_alloc = (unsigned int) (search->tag_len*1.3);
    search->rewrite_buf = ZnRealloc(search->rewrite_buf,
                                    search->rewrite_buf_alloc);
  }
  
  /* Initialize search */
  search->wi = wi;
  search->over = False;
  search->type = 0;
  search->group = group;
  search->recursive = recursive;
  ZnListEmpty(search->item_stack);
  
  /*
   * Find the first matching item in one of several ways. If the tag
   * is a number then it selects the single item with the matching
   * identifier.
   */
  if (isdigit(*tag)) {
    char *end;
    
    search->id = strtoul(tag, &end, 0);
    if (*end == 0) {
      search->type = 1;
      return TCL_OK;
    }
  }
  
  /*
   * Pre-scan tag for at least one unquoted "&&" "||" "^" "!"
   *   if not found then use string as simple tag
   */
  for (i = 0; i < search->tag_len; i++) {
    if (tag[i] == '"') {
      i++;
      for ( ; i < search->tag_len; i++) {
        if (tag[i] == '\\') {
          i++;
          continue;
        }
        if (tag[i] == '"') {
          break;
        }
      }
    }
    else {
      if (((tag[i] == '&') && (tag[i+1] == '&')) ||
          ((tag[i] == '|') && (tag[i+1] == '|')) ||
          (tag[i] == '^') || (tag[i] == '!')) {
        search->type = 4;
        break;
      }
    }
  }

  search->tag = tag;
  search->tag_index = 0;
  if (search->type == 4) {
    /*
     * an operator was found in the prescan, so
     * now compile the tag expression into array of Tk_Uid
     * flagging any syntax errors found
     */
    if (TagSearchScanExpr(wi->interp, search, search->expr) != TCL_OK) {
      /* Syntax error in tag expression */
      /* Result message set by TagSearchScanExpr */
      return TCL_ERROR;
    }
    search->expr->length = search->expr->index;
  }
  else {
    /*
     * For all other tags convert to a UID.
     */
    search->expr->uid = Tk_GetUid(tag);

    if (search->expr->uid == all_uid) {
      /*
       * All items match.
       */
      search->type = 2;
    }
    else {
      /*
       * Optimized single-tag search
       */
      search->type = 3;
    }
  }
  return TCL_OK;
}


/*
 *--------------------------------------------------------------
 *
 * ZnTagSearchFirst --
 *
 *      This procedure is called to get the first item
 *      item that matches a preestablished search predicate
 *      that was set by TagSearchScan.
 *
 * Results:
 *      The return value is a pointer to the first item, or NULL
 *      if there is no such item.  The information at *search
 *      is updated such that successive calls to ZnTagSearchNext
 *      will return successive items.
 *
 * Side effects:
 *      *search is linked into a list of searches in progress
 *      in zinc, so that elements can safely be deleted while
 *      the search is in progress.
 *
 *--------------------------------------------------------------
 */
static ZnItem
ZnTagSearchFirst(ZnTagSearch    *search)        /* Record describing tag search */
{
  ZnItem item, previous;

  /* short circuit impossible searches for null tags */
  if (search->over == True) {
    return ZN_NO_ITEM;
  }

  /*
   * Find the first matching item in one of several ways. If the tag
   * is a number then it selects the single item with the matching
   * identifier.  In this case see if the item being requested is the
   * hot item, in which case the search can be skipped.
   */
  if (search->type == 1) {
    Tcl_HashEntry *entry;
  
    item = search->wi->hot_item;
    previous = search->wi->hot_prev;
    if ((item == ZN_NO_ITEM) || (item->id != search->id) ||
        (previous == ZN_NO_ITEM) || (previous->next != item)) {
      entry = Tcl_FindHashEntry(search->wi->id_table, (char *) search->id);
      if (entry != NULL) {
        item = (ZnItem) Tcl_GetHashValue(entry);
        previous = item->previous;
      }
      else {
        previous = item = ZN_NO_ITEM;
      }
    }
    search->previous = previous;
    search->over = True;
    search->wi->hot_item = item;
    search->wi->hot_prev = previous;
    return item;
  }
  
  if (search->type == 2) {
    /*
     * All items match.
     */
    search->previous = ZN_NO_ITEM;
    search->current = ZnGroupHead(search->group);
    return search->current;
  }
  
  item = ZnGroupHead(search->group);
  previous = ZN_NO_ITEM;
  do {
    while (item != ZN_NO_ITEM) {
      if (search->type == 3) {
        /*
         * Optimized single-tag search
         */
        if (ZnITEM.HasTag(item, search->expr->uid)) {
          search->previous = previous;
          search->current = item;
          return item;
        }
      }
      else {
        /*
         * Type = 4.  Search for an item matching
         * the tag expression.
         */
        search->expr->index = 0;
        if (TagSearchEvalExpr(search->expr, item)) {
          search->previous = previous;
          search->current = item;
          return item;
        }
      }
      if ((item->class == ZnGroup) && (search->recursive)) {
        ZnItem prev_group = (ZnItem) search->group;
        /*
         * Explore the hierarchy depth first using the item stack
         * to save the current node.
         */
        /*printf("ZnTagSearchFirst diving for tag '%s', detph %d\n",
               search->tag, ZnListSize(search->item_stack)/2);*/
        search->group = item;
        previous = item;
        if (item == prev_group) {
          item = ZN_NO_ITEM;
        }
        else {
          item = item->next;
        }
        ZnListAdd(search->item_stack, &previous, ZnListTail);
        ZnListAdd(search->item_stack, &item, ZnListTail);
        previous = ZN_NO_ITEM;
        item = ZnGroupHead(search->group);
      }
      else {
        previous = item;
        item = item->next;
      }
    }
    /*
     * Continue search on higher group level.
     */
    /*printf("ZnTagSearchFirst backup for tag, detph %d\n",
      ZnListSize(search->item_stack)/2);*/    
    while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
      item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
      ZnListDelete(search->item_stack, ZnListTail);
      previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
      ZnListDelete(search->item_stack, ZnListTail);
    }
    if (item != ZN_NO_ITEM) {
      search->group = item->parent;
    }
  } while (item != ZN_NO_ITEM);

  search->previous = previous;
  search->over = True;
  
  return ZN_NO_ITEM;
}


/*
 *--------------------------------------------------------------
 *
 * ZnTagSearchNext --
 *
 *      This procedure returns successive items that match a given
 *      tag;  it should be called only after ZnTagSearchFirst has
 *      been used to begin a search.
 *
 * Results:
 *      The return value is a pointer to the next item that matches
 *      the tag expr specified to TagSearchScan, or NULL if no such
 *      item exists.  *search is updated so that the next call
 *      to this procedure will return the next item.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
static ZnItem
ZnTagSearchNext(ZnTagSearch     *search) /* Record describing search in progress. */
{
  ZnItem item, previous;

  if (search->over) {
    return ZN_NO_ITEM;
  }
  /*
   * Find next item in list (this may not actually be a suitable
   * one to return), and return if there are no items left.
   */
  previous = search->previous;
  if (previous == ZN_NO_ITEM) {
    item = ZnGroupHead(search->group);
  }
  else {
    item = previous->next;
  }

  if (item != search->current) {
    /*
     * The structure of the list has changed.  Probably the
     * previously-returned item was removed from the list.
     * In this case, don't advance previous;  just return
     * its new successor (i.e. do nothing here).
     */
  }
  else if ((item->class == ZnGroup) && (search->recursive)) {
    /*
     * Explore the hierarchy depth first using the item stack
     * to save the current node.
     */
    search->group = item;
    previous = item;
    item = item->next;
    /*printf("ZnTagSearchNext diving for all, pushing %d\n",
      item?item->id:0);*/
    ZnListAdd(search->item_stack, &previous, ZnListTail);
    ZnListAdd(search->item_stack, &item, ZnListTail);
    previous = ZN_NO_ITEM;
    item = ZnGroupHead(search->group);
  }
  else {
    previous = item;
    item = previous->next;
  }
  
  if (item == ZN_NO_ITEM) {
    while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
      /*
       * End of list at this level, back up one level.
       */
      item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
      ZnListDelete(search->item_stack, ZnListTail);
      previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
      ZnListDelete(search->item_stack, ZnListTail);
    }
    if (item != ZN_NO_ITEM) {
      search->group = item->parent;
      /*printf("ZnTagSearchNext popping %d, previous %d, next %d\n",
             item->id, (item->previous)?item->previous->id:0,
             (item->next)?item->next->id:0);*/
    }
    else {
      /*
       * Or finish the search if at top.
       */
      search->over = True;
      return ZN_NO_ITEM;
    }
  }

  if (search->type == 2) {
    /*
     * All items match.
     */
    search->previous = previous;
    search->current = item;
    return item;
  }
  
  do {
    while (item != ZN_NO_ITEM) {
      if (search->type == 3) { 
        /*
         * Optimized single-tag search
         */
        if (ZnITEM.HasTag(item, search->expr->uid)) {
          search->previous = previous;
          search->current = item;
          return item;
        }
      }
      else {
        /*
         * Else.... evaluate tag expression
         */
        search->expr->index = 0;
        if (TagSearchEvalExpr(search->expr, item)) {
          search->previous = previous;
          search->current = item;
          return item;
        }
      }
      if ((item->class == ZnGroup) && (search->recursive)) {
        /*
         * Explore the hierarchy depth first using the item stack
         * to save the current node.
         */
        /*printf("ZnTagSearchNext diving for tag, depth %d\n",
          ZnListSize(search->item_stack)/2);*/
        search->group = item;
        previous = item;
        item = item->next;
        ZnListAdd(search->item_stack, &previous, ZnListTail);
        ZnListAdd(search->item_stack, &item, ZnListTail);
        previous = ZN_NO_ITEM;
        item = ZnGroupHead(search->group);
      }
      else {
        previous = item;
        item = item->next;
      }
    }
    /*printf("ZnTagSearchNext backup for tag, depth %d\n",
      ZnListSize(search->item_stack)/2);*/
    while ((item == ZN_NO_ITEM) && ZnListSize(search->item_stack)) {
      item = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
      ZnListDelete(search->item_stack, ZnListTail);
      previous = *(ZnItem *) ZnListAt(search->item_stack, ZnListTail);
      ZnListDelete(search->item_stack, ZnListTail);
    }
    if (item != ZN_NO_ITEM) {
      search->group = item->parent;
    }
  } while (item != ZN_NO_ITEM);

  /*
   * Out of fuel.
   */
  search->previous = previous;
  search->over = True;
  
  return ZN_NO_ITEM;
}


/*
 *--------------------------------------------------------------
 *
 * ZnTagSearchDestroy --
 *
 *      This procedure destroys any dynamic structures that
 *      may have been allocated by TagSearchScan.
 *
 *--------------------------------------------------------------
 */
void
ZnTagSearchDestroy(ZnTagSearch  *search) /* Record describing tag search */
{
  if (search) {
    TagSearchExprDestroy(search->expr);
    ZnListFree(search->item_stack);
    ZnFree(search->rewrite_buf);
    ZnFree(search);
  }
}


/*
 *----------------------------------------------------------------------
 *
 * ZnItemWithTagOrId --
 *
 *      Return the first item matching the given tag or id. The
 *      function returns the item in 'item' and the operation
 *      status as the function's value.
 *
 *----------------------------------------------------------------------
 */
int
ZnItemWithTagOrId(ZnWInfo       *wi,
                  Tcl_Obj       *tag_or_id,
                  ZnItem        *item,
                  ZnTagSearch   **search_var)
{
  if (ZnTagSearchScan(wi, tag_or_id, search_var) != TCL_OK) {
    return TCL_ERROR;
  }
  *item = ZnTagSearchFirst(*search_var);
  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * LayoutItems --
 *
 *      Perform layouts on items. It can position items horizontally,
 *      vertically, along a path or with respect to a reference item.
 *      It can also align on a grid, evenly space items and resize
 *      items to a common reference.
 *
 *----------------------------------------------------------------------
 */
static int
LayoutItems(ZnWInfo     *wi,
            int         argc,
            Tcl_Obj     *CONST args[])
{
  int           index/*, result*/;
  /*ZnItem              item;*/
#ifdef PTK_800
  static char *layout_cmd_strings[] =
  #else
  static CONST char *layout_cmd_strings[] =
#endif
  {
    "align", "grid", "position", "scale", "space", NULL
  };
  enum          layout_cmds {
    ZN_L_ALIGN, ZN_L_GRID, ZN_L_POSITION, ZN_L_SCALE, ZN_L_SPACE
  };
  
  if (Tcl_GetIndexFromObj(wi->interp, args[0], layout_cmd_strings,
                          "layout command", 0, &index) != TCL_OK) {
    return TCL_ERROR;
  }
  switch((enum layout_cmds) index) {
    /*
     * align
     */
  case ZN_L_ALIGN:
    break;
    /*
     * grid
     */
  case ZN_L_GRID:
    break;
    /*
     * position
     */
  case ZN_L_POSITION:
    break;
    /*
     * scale
     */
  case ZN_L_SCALE:
    break;
    /*
     * space
     */
  case ZN_L_SPACE:
    break;
  }

  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * ZnSetOrigin --
 *
 *      This procedure is invoked to translate the viewed area so
 *      that the given point is displayed in the top left corner.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Zinc will be redisplayed to reflect the change in ciew.
 *      The scrollbars will be updated if there are any.
 *      The top group transform is modified to achieve the effect,
 *      it is not a good idea to mix view control and application
 *      control of the top group transform.
 *
 *----------------------------------------------------------------------
 */
static void
ZnSetOrigin(ZnWInfo *wi,
            ZnReal  x_origin,
            ZnReal  y_origin)
{
  int   left, right, top, bottom, delta;

   /*
    * If scroll increments have been set, round the window origin
    * to the nearest multiple of the increments.
    */
  if (wi->x_scroll_incr > 0) {
    if (x_origin >= 0) {
      x_origin += wi->x_scroll_incr/2;
    }
    else {
      x_origin = (-x_origin) + wi->x_scroll_incr/2;
    }
  }
  if (wi->y_scroll_incr > 0) {
    if (y_origin >= 0) {
      y_origin += wi->y_scroll_incr/2;
    }
    else {
      y_origin = (-y_origin) + wi->y_scroll_incr/2;
    }
  }

  /*
   * Adjust the origin if necessary to keep as much as possible of the
   * canvas in the view.  The variables left, right, etc. keep track of
   * how much extra space there is on each side of the view before it
   * will stick out past the scroll region.  If one side sticks out past
   * the edge of the scroll region, adjust the view to bring that side
   * back to the edge of the scrollregion (but don't move it so much that
   * the other side sticks out now).  If scroll increments are in effect,
   * be sure to adjust only by full increments.
   */
  if (wi->confine && (wi->region != NULL)) {
    left = (int) (x_origin - wi->scroll_xo);
    right = (int) (wi->scroll_xc - (x_origin + Tk_Width(wi->win)));
    top = (int) (y_origin - wi->scroll_yo);
    bottom = (int) (wi->scroll_yc - (y_origin + Tk_Height(wi->win)));
    if ((left < 0) && (right > 0)) {
      delta = (right > -left) ? -left : right;
      if (wi->x_scroll_incr > 0) {
        delta -= delta % wi->x_scroll_incr;
      }
      x_origin += delta;
    }
    else if ((right < 0) && (left > 0)) {
      delta = (left > -right) ? -right : left;
      if (wi->x_scroll_incr > 0) {
        delta -= delta % wi->x_scroll_incr;
      }
      x_origin -= delta;
    }
    if ((top < 0) && (bottom > 0)) {
      delta = (bottom > -top) ? -top : bottom;
      if (wi->y_scroll_incr > 0) {
        delta -= delta % wi->y_scroll_incr;
      }
      y_origin += delta;
    }
    else if ((bottom < 0) && (top > 0)) {
      delta = (top > -bottom) ? -bottom : top;
      if (wi->y_scroll_incr > 0) {
        delta -= delta % wi->y_scroll_incr;
      }
      y_origin -= delta;
    }
  }

  /*
   * If the requested origin is not already set, translate the
   * top group and update the scrollbars.
   */
  if ((wi->origin.x != x_origin) || (wi->origin.y != y_origin)) {
    wi->origin.x = x_origin;
    wi->origin.y = y_origin;
    ZnITEM.ResetTransfo(wi->top_group);
    ZnITEM.TranslateItem(wi->top_group, -x_origin, -y_origin, False);
    SET(wi->flags, ZN_UPDATE_SCROLLBARS);
  }
}


/*
 *----------------------------------------------------------------------
 *
 * ScrollFractions --
 *
 *      Given the range that's visible in the window and the "100%
 *      range", return a list of two real representing the scroll
 *      fractions.  This procedure is used for both x and y scrolling.
 *
 * Results:
 *      Return a string as a Tcl_Obj holding two real numbers
 *      describing the scroll fraction (between 0 and 1) corresponding
 *      to the arguments.
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
#ifdef PTK
static void
ScrollFractions(ZnReal  view1,  /* Lowest coordinate visible in the window. */
                ZnReal  view2,  /* Highest coordinate visible in the window. */
                ZnReal  region1,/* Lowest coordinate in the object. */
                ZnReal  region2,/* Highest coordinate in the object. */
                ZnReal  *first,
                ZnReal  *last)
#else
static Tcl_Obj *
ScrollFractions(ZnReal  view1,  /* Lowest coordinate visible in the window. */
                ZnReal  view2,  /* Highest coordinate visible in the window. */
                ZnReal  region1,/* Lowest coordinate in the object. */
                ZnReal  region2)/* Highest coordinate in the object. */
#endif
{
  ZnReal range, f1, f2;
  char   buffer[2*TCL_DOUBLE_SPACE+2];

  range = region2 - region1;
  if (range <= 0) {
    f1 = 0;
    f2 = 1.0;
  }
  else {
    f1 = (view1 - region1)/range;
    if (f1 < 0) {
      f1 = 0.0;
    }
    f2 = (view2 - region1)/range;
    if (f2 > 1.0) {
      f2 = 1.0;
    }
    if (f2 < f1) {
      f2 = f1;
    }
  }
#ifdef PTK
  *first = f1;
  *last = f2;
#else
  sprintf(buffer, "%g %g", f1, f2);
  return Tcl_NewStringObj(buffer, -1);
#endif
}


/*
 *--------------------------------------------------------------
 *
 * UpdateScrollbars --
 *
 *      This procedure is invoked whenever zinc has changed in
 *      a way that requires scrollbars to be redisplayed (e.g.
 *      the view has changed).
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      If there are scrollbars associated with zinc, then
 *      their scrolling commands are invoked to cause them to
 *      redisplay.  If errors occur, additional Tcl commands may
 *      be invoked to process the errors.
 *
 *--------------------------------------------------------------
 */
static void
UpdateScrollbars(ZnWInfo        *wi)
{
  int           result;
  Tcl_Interp    *interp;
  int           x_origin, y_origin, width, height;
  int           scroll_xo, scroll_xc, scroll_yo, scroll_yc;
#ifdef PTK
  LangCallback  *x_scroll_cmd, *y_scroll_cmd;
#else
  Tcl_Obj       *x_scroll_cmd, *y_scroll_cmd;
#endif
  Tcl_Obj       *fractions;

  /*
   * Save all the relevant values from wi, because it might be
   * deleted as part of either of the two calls to Tcl_VarEval below.
   */
  interp = wi->interp;
  Tcl_Preserve((ClientData) interp);
  x_scroll_cmd = wi->x_scroll_cmd;
  if (x_scroll_cmd != NULL) {
    Tcl_Preserve((ClientData) x_scroll_cmd);
  }
  y_scroll_cmd = wi->y_scroll_cmd;
  if (y_scroll_cmd != NULL) {
    Tcl_Preserve((ClientData) y_scroll_cmd);
  }
  x_origin = (int) wi->origin.x;
  y_origin = (int) wi->origin.y;
  width = Tk_Width(wi->win);
  height = Tk_Height(wi->win);
  scroll_xo = wi->scroll_xo;
  scroll_xc = wi->scroll_xc;
  scroll_yo = wi->scroll_yo;
  scroll_yc = wi->scroll_yc;
  CLEAR(wi->flags, ZN_UPDATE_SCROLLBARS);
  if (wi->x_scroll_cmd != NULL) {
#ifdef PTK
    ZnReal first, last;
    ScrollFractions(x_origin, x_origin + width, scroll_xo, scroll_xc, &first, &last);
    result = LangDoCallback(interp, x_scroll_cmd, 0, 2, " %g %g", first, last);
#else
    fractions = ScrollFractions(x_origin, x_origin + width, scroll_xo, scroll_xc);
    result = Tcl_VarEval(interp, Tcl_GetString(x_scroll_cmd), " ", Tcl_GetString(fractions), NULL);
    Tcl_DecrRefCount(fractions);
#endif
    if (result != TCL_OK) {
      Tcl_BackgroundError(interp);
    }
    Tcl_ResetResult(interp);
    Tcl_Release((ClientData) x_scroll_cmd);
  }
  
  if (y_scroll_cmd != NULL) {
#ifdef PTK
    ZnReal      first, last;
    ScrollFractions(y_origin, y_origin + height, scroll_yo, scroll_yc, &first, &last);
    result = LangDoCallback(interp, y_scroll_cmd, 0, 2, " %g %g", first, last);
#else
    fractions = ScrollFractions(y_origin, y_origin + height, scroll_yo, scroll_yc);
    result = Tcl_VarEval(interp, Tcl_GetString(y_scroll_cmd), " ", Tcl_GetString(fractions), NULL);
    Tcl_DecrRefCount(fractions);
#endif
    if (result != TCL_OK) {
      Tcl_BackgroundError(interp);
    }
    Tcl_ResetResult(interp);
    Tcl_Release((ClientData) y_scroll_cmd);
  }
  Tcl_Release((ClientData) interp);
}


/*
 *----------------------------------------------------------------------
 *
 * ZnDoItem --
 *
 *      Either add a tag to an item or add the item id/part to the
 *      interpreter result, depending on the value of tag. If tag
 *      is NULL, the item id/part is added to the result, otherwise
 *      the tag is added to the item.
 *
 *----------------------------------------------------------------------
 */
void
ZnDoItem(Tcl_Interp     *interp,
         ZnItem         item,
         int            part,
         Tk_Uid         tag_uid)
{
  if (tag_uid == NULL) {
    Tcl_Obj  *l;
    l = Tcl_GetObjResult(interp);
    Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(item->id));
    if (part != ZN_NO_PART) {
      Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(part));
    }
  }
  else {
    /*printf("Adding tag %s to item %d\n", tag_uid, item->id);*/
    ZnITEM.AddTag(item, tag_uid);
  }
}


/*
 *----------------------------------------------------------------------
 *
 * FindArea --
 *      Search the items that are enclosed or overlapping a given
 *      area of the widget. It is used by FindItems.
 *      If tag_uid is not NULL, all the items found are tagged with
 *      tag_uid. If tag_uid is NULL, the items found are added to the
 *      interp result. If enclosed is 1, the search look for
 *      items enclosed in the area. If enclosed is 0, it looks
 *      for overlapping and enclosed items.
 *      If an error occurs, a message is left in the interp result
 *      and TCL_ERROR is returned.
 *
 *----------------------------------------------------------------------
 */
static int
FindArea(ZnWInfo        *wi,
         Tcl_Obj *CONST args[],
         Tk_Uid         tag_uid,
         ZnBool         enclosed,
         ZnBool         recursive,
         ZnBool         override_atomic,
         ZnItem         group)
{
  ZnPos         pos;
  ZnBBox        area;
  ZnToAreaStruct ta;
  double        d;

  if (Tcl_GetDoubleFromObj(wi->interp, args[0], &d) == TCL_ERROR) {
    return TCL_ERROR;
  }
  area.orig.x = d;
  if (Tcl_GetDoubleFromObj(wi->interp, args[1], &d) == TCL_ERROR) {
    return TCL_ERROR;
  }
  area.orig.y = d;
  if (Tcl_GetDoubleFromObj(wi->interp, args[2], &d) == TCL_ERROR) {
    return TCL_ERROR;
  }
  area.corner.x = d;
  if (Tcl_GetDoubleFromObj(wi->interp, args[3], &d) == TCL_ERROR) {
    return TCL_ERROR;
  }
  area.corner.y = d;
  if (area.corner.x < area.orig.x) {
    pos = area.orig.x;
    area.orig.x = area.corner.x;
    area.corner.x = pos;
  }
  if (area.corner.y < area.orig.y) {
    pos = area.orig.y;
    area.orig.y = area.corner.y;
    area.corner.y = pos;
  }
  area.corner.x += 1;
  area.corner.y += 1;

  ta.tag_uid = tag_uid;
  ta.enclosed = enclosed;
  ta.in_group = group;
  ta.recursive = recursive;
  ta.override_atomic = override_atomic;
  ta.report = False;
  ta.area = &area;
  wi->top_group->class->ToArea(wi->top_group, &ta);
  
  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * FindItems --
 *
 *      This procedure interprets the small object query langage for
 *      commands like addtag and find.
 *      If new_tag is NULL, the procedure collects all the objects
 *      matching the request and return them in the interpreter result.
 *      If new_tag is non NULL, it is interpreted as the tag to add to
 *      all matching objects. In this case the interpreter result is
 *      left empty.
 *
 *----------------------------------------------------------------------
 */
static int
FindItems(ZnWInfo       *wi,
          int           argc,
          Tcl_Obj *CONST args[],
          Tcl_Obj       *tag,           /* NULL to search or tag to add tag. */
          int           first,          /* First arg to process in args */
          ZnTagSearch   **search_var)
{
  Tk_Uid        tag_uid = NULL;
  int           index, result;
  ZnItem        item;
  ZnPickStruct  ps;
  char          *str;
#ifdef PTK_800
  static char *search_cmd_strings[] =
#else
  static CONST char *search_cmd_strings[] =
#endif
  {
    "above", "ancestors", "atpriority", "below", "closest", "enclosed",
    "overlapping", "withtag", "withtype", NULL
  };
  enum          search_cmds {
    ZN_S_ABOVE, ZN_S_ANCESTORS, ZN_S_ATPRIORITY, ZN_S_BELOW, ZN_S_CLOSEST,
    ZN_S_ENCLOSED, ZN_S_OVERLAPPING, ZN_S_WITHTAG, ZN_S_WITHTYPE
  };
  
  if (Tcl_GetIndexFromObj(wi->interp, args[first], search_cmd_strings,
                          "search command", 0, &index) != TCL_OK) {
    return TCL_ERROR;
  }
  
  if (tag) {
    tag_uid = Tk_GetUid(Tcl_GetString(tag));
  }
  
  switch((enum search_cmds) index) {
    /*
     * above
     */
  case ZN_S_ABOVE:
    {
      if (argc != first+2) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId");
        return TCL_ERROR;
      }
      result = ZnItemWithTagOrId(wi, args[first+1], &item, search_var);
      if (result == TCL_OK) {
        if ((item != ZN_NO_ITEM) && (item->previous != ZN_NO_ITEM)) {
          ZnDoItem(wi->interp, item->previous, ZN_NO_PART, tag_uid);
        }
      }
      else {
        return TCL_ERROR;
      }
    }
    break;
    /*
     * ancestors
     */
  case ZN_S_ANCESTORS:
    {
      Tk_Uid uid = NULL;
      if ((argc != first+2) && (argc != first+3)) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId ?withTag?");
        return TCL_ERROR;
      }
      result = ZnItemWithTagOrId(wi, args[first+1], &item, search_var);
      if (result == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (item) {
        item = item->parent;
        if (argc == first+3) {
          uid = Tk_GetUid(Tcl_GetString(args[first+2]));
        }
        while (item != ZN_NO_ITEM) {
          if (!uid || ZnITEM.HasTag(item, uid)) {
            ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
          }
          item = item->parent;
        }
      }
    }
    break;
      /*
       * atpriority
       */
  case ZN_S_ATPRIORITY:
    {
      int pri;
      
      if ((argc != first+2) && (argc != first+3)) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "pri ?tagOrId?");
        return TCL_ERROR;
      }
      if ((Tcl_GetIntFromObj(wi->interp, args[first+1], &pri) == TCL_ERROR) ||
          (pri < 0)){
        return TCL_ERROR;
      }
      
      /*
       * Go through the item table and collect all items with
       * the given priority.
       */
      if (ZnTagSearchScan(wi, (argc == first+3) ? args[first+2] : NULL,
                          search_var) == TCL_ERROR) {
        return TCL_ERROR;
      }
      for (item = ZnTagSearchFirst(*search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
        if (item->priority == (unsigned int) pri) {
          ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
        }
      }
    }
    break;
    /*
     * below
     */
  case ZN_S_BELOW:
    {
      ZnItem    next;
      
      if (argc != first+2) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId");
        return TCL_ERROR;
      }
      item = ZN_NO_ITEM;
      if (ZnTagSearchScan(wi, args[first+1], search_var) == TCL_ERROR) {
        return TCL_ERROR;
      }
      for (next = ZnTagSearchFirst(*search_var);
           next != ZN_NO_ITEM; next = ZnTagSearchNext(*search_var)) {
        item = next;
      }
      if ((item != ZN_NO_ITEM) && (item->next != ZN_NO_ITEM)) {
        ZnDoItem(wi->interp, item->next, ZN_NO_PART, tag_uid);
      }
    }
    break;
    /*
     * closest
     */
  case ZN_S_CLOSEST:
    {
      int       halo = 1;
      ZnPoint   p;
      double    d;

      if ((argc < first+3) || (argc > first+6)) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "x y ?halo? ?start?, ?recursive?");
        return TCL_ERROR;      
      }
      if (Tcl_GetDoubleFromObj(wi->interp, args[first+1], &d) == TCL_ERROR) {
        return TCL_ERROR;
      }
      p.x = d;
      if (Tcl_GetDoubleFromObj(wi->interp, args[first+2], &d) == TCL_ERROR) {
        return TCL_ERROR;
      }
      p.y = d;
      if (argc > first+3) {
        if (Tcl_GetIntFromObj(wi->interp, args[first+3], &halo) == TCL_ERROR) {
          return TCL_ERROR;
        }
        if (halo < 0) {
          halo = 0;
        }
      }

      ps.in_group = ZN_NO_ITEM;
      ps.start_item = ZN_NO_ITEM;
      item = ZN_NO_ITEM;      
      if (argc > (first+4)) {
        result = ZnItemWithTagOrId(wi, args[first+4], &item, search_var);
        if ((result == TCL_OK) && (item != ZN_NO_ITEM)) {
          if ((item->class == ZnGroup) && !ZnGroupAtomic(item)) {
            ps.in_group = item;
          }
          else {
            ps.in_group = item->parent;
            ps.start_item = item->next;
          }
        }
      }
      ps.recursive = True;
      ps.override_atomic = False;
      if (argc > first+5) {
        result = Tcl_GetBooleanFromObj(wi->interp, args[first+5], &ps.recursive);
        if (result != TCL_OK) {
          Tcl_ResetResult(wi->interp);
          str = Tcl_GetString(args[first+5]);
          if (strcmp(str, "override") != 0) { 
            Tcl_AppendResult(wi->interp,
                             "recursive should be a boolean value or ",
                             "override \"", str, "\"", NULL);
            return TCL_ERROR;
          }
          ps.recursive = True;
          ps.override_atomic = True;
        }
      }
      /*
       * We always start the search at the top group to use the
       * transform and clip machinery of the group item. The items
       * are not required to cache the device coords, etc. So we need
       * to setup the correct context before calling the Pick method
       * for each item.
       */
      ps.aperture = halo;
      ps.point = &p;
      wi->top_group->class->Pick(wi->top_group, &ps);
      
      if (ps.a_item != ZN_NO_ITEM) {
        ZnDoItem(wi->interp, ps.a_item, ps.a_part, tag_uid);
        /*printf("first %d %d\n", ps.a_item->id, ps.a_part);*/
      }
    }
    break;
    /*
     * enclosed
     */
  case ZN_S_ENCLOSED:
    {
      if ((argc < first+5) || (argc > first+7)) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup? ?recursive?");
        return TCL_ERROR;
      }
      item = wi->top_group;
      if (argc > first+5) {
        result = ZnItemWithTagOrId(wi, args[first+5], &item, search_var);
        if ((result != TCL_OK) || (item == ZN_NO_ITEM) || (item->class != ZnGroup)) {
          return TCL_ERROR;
        }
      }
      ps.recursive = True;
      ps.override_atomic = False;
      if (argc > first+6) {
        result = Tcl_GetBooleanFromObj(wi->interp, args[first+6], &ps.recursive);
        if (result != TCL_OK) {
          Tcl_ResetResult(wi->interp);
          str = Tcl_GetString(args[first+6]);
          if (strcmp(str, "override") != 0) { 
            Tcl_AppendResult(wi->interp,
                             "recursive should be a boolean value or ",
                             "override \"", str, "\"", NULL);
            return TCL_ERROR;
          }
          ps.recursive = True;
          ps.override_atomic = True;
        }
      }
      return FindArea(wi, args+first+1, tag_uid,
                      True, ps.recursive, ps.override_atomic,
                      item);
    }
    break;
    /*
     * overlapping
     */
  case ZN_S_OVERLAPPING:
    {
      if ((argc < first+5) || (argc > first+7)) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "x1 y1 x2 y2 ?inGroup? ?recursive?");
        return TCL_ERROR;
      }
      item = wi->top_group;
      if (argc > first+5) {
        result = ZnItemWithTagOrId(wi, args[first+5], &item, search_var);
        if ((result != TCL_OK) || (item == ZN_NO_ITEM) || (item->class != ZnGroup)) {
          return TCL_ERROR;
        }
      }
      ps.recursive = True;
      ps.override_atomic = False;
      if (argc > first+6) {
        result = Tcl_GetBooleanFromObj(wi->interp, args[first+6], &ps.recursive);
        if (result != TCL_OK) {
          Tcl_ResetResult(wi->interp);
          str = Tcl_GetString(args[first+6]);
          if (strcmp(str, "override") != 0) { 
            Tcl_AppendResult(wi->interp,
                             "recursive should be a boolean value or ",
                             "override \"", str, "\"", NULL);
            return TCL_ERROR;
          }
          ps.recursive = True;
          ps.override_atomic = True;
        }
      }
      return FindArea(wi, args+first+1, tag_uid,
                      False, ps.recursive, ps.override_atomic,
                      item);
    }
    break;
    /*
     * withtag
     */
  case ZN_S_WITHTAG:
    {
      if (argc != first+2) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "tagOrId");
        return TCL_ERROR;
      }
      if (ZnTagSearchScan(wi, args[first+1], search_var) == TCL_ERROR) {
        return TCL_ERROR;
      }
      for (item = ZnTagSearchFirst(*search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
        ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
      }
    }
    break;
    /*
     * withtype
     */
  case ZN_S_WITHTYPE:
    {
      ZnItemClass       cls;
      
      if ((argc != first+2) && (argc != first+3)) {
        Tcl_WrongNumArgs(wi->interp, first+1, args, "itemType ?tagOrId?");
        return TCL_ERROR;
      }
      cls = ZnLookupItemClass(Tcl_GetString(args[first+1]));
      if (!cls) {
        Tcl_AppendResult(wi->interp, "unknown item type \"",
                         Tcl_GetString(args[first+1]), "\"", NULL);
        return TCL_ERROR;
      }
      
      /*
       * Go through the item table and collect all items with
       * the given item type.
       */
      if (ZnTagSearchScan(wi, (argc == first+3) ? args[first+2] : NULL,
                          search_var) == TCL_ERROR) {
        return TCL_ERROR;
      }
      for (item = ZnTagSearchFirst(*search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(*search_var)) {
        if (item->class == cls) {
          ZnDoItem(wi->interp, item, ZN_NO_PART, tag_uid);
        }
      }
    }
    break;
  }
  
  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * ZnParseCoordList --
 *
 *----------------------------------------------------------------------
 */
int
ZnParseCoordList(ZnWInfo        *wi,
                 Tcl_Obj        *arg,
                 ZnPoint        **pts,
                 char           **controls,
                 unsigned int   *num_pts,
                 ZnBool         *old_format)
{
  Tcl_Obj       **elems, **selems;
  int           i, result, num_elems, num_selems;
  ZnPoint       *p;
  int           old_style, len;
  char          *str;
  double        d;

  if (controls) {
    *controls = NULL;
  }
  if (old_format) {
    *old_format = True;
  }
  result = Tcl_ListObjGetElements(wi->interp, arg, &num_elems, &elems);
  if (result == TCL_ERROR) {
  coord_error:
    Tcl_AppendResult(wi->interp, " malformed coord list", NULL);
    return TCL_ERROR;
  }
  if (num_elems == 0) {
    *num_pts = 0;
    *pts = NULL;
    return TCL_OK;
  }

  /*
   * If first element is not a sublist, consider the whole list
   * as a flat array of coordinates in the old style. It can still
   * be a single point with or without a control flag.
   * If not, the list consists in sublists describing each point
   * with its control flag.
   */
  result = Tcl_GetDoubleFromObj(wi->interp, elems[0], &d);
  old_style = (result == TCL_OK);

  if (old_style) {
    if ((num_elems%2) == 0) {
      *num_pts = num_elems/2;
      ZnListAssertSize(ZnWorkPoints, *num_pts);
      *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints);
      for (i = 0; i < num_elems; i += 2, p++) {
        if (Tcl_GetDoubleFromObj(wi->interp, elems[i], &d) == TCL_ERROR) {
          goto coord_error;
        }
        p->x = d;
        if (Tcl_GetDoubleFromObj(wi->interp, elems[i+1], &d) == TCL_ERROR) {
          goto coord_error;
        }
        p->y = d;
        /*printf("Parsed a point: %g@%g, ", p->x, p->y);*/
      }
      /*printf("\n");*/
    }
    else if (num_elems == 3) {
      *num_pts = 1;
      ZnListAssertSize(ZnWorkPoints, *num_pts);
      *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints);
      if (Tcl_GetDoubleFromObj(wi->interp, elems[0], &d) == TCL_ERROR) {
        goto coord_error;
      }
      p->x = d;
      if (Tcl_GetDoubleFromObj(wi->interp, elems[1], &d) == TCL_ERROR) {
        goto coord_error;
      }
      p->y = d;
      if (controls) {
        if (! *controls) {
          *controls = ZnMalloc(*num_pts * sizeof(char));
          memset(*controls, 0, *num_pts * sizeof(char));
        }
        str = Tcl_GetStringFromObj(elems[2], &len);
        if (len) {
          (*controls)[0] = str[0];
        }
      }
    }
    else {
      goto coord_error;
    }
  }
  else {
    Tcl_ResetResult(wi->interp);
    *num_pts = num_elems;
    ZnListAssertSize(ZnWorkPoints, *num_pts);
    *pts = p = (ZnPoint *) ZnListArray(ZnWorkPoints);
    for (i = 0; i < num_elems; i++, p++) {
      result = Tcl_ListObjGetElements(wi->interp, elems[i], &num_selems, &selems);
      if ((result == TCL_ERROR) || (num_selems < 2) || (num_selems > 3)) {
        goto coord_error;
      }
      if (Tcl_GetDoubleFromObj(wi->interp, selems[0], &d) == TCL_ERROR) {
        goto coord_error;
      }
      p->x = d;
      if (Tcl_GetDoubleFromObj(wi->interp, selems[1], &d) == TCL_ERROR) {
        goto coord_error;
      }
      p->y = d;
      if (controls) {
        if (num_selems == 3) {
          if (! *controls) {
            *controls = ZnMalloc(*num_pts * sizeof(char));
            memset(*controls, 0, *num_pts * sizeof(char));
          }
          str = Tcl_GetStringFromObj(selems[2], &len);
          if (len) {
            (*controls)[i] = str[0];
          }
        }
      }
    }
  }
  
  if (old_format) {
    *old_format = old_style;
  }
  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * Contour --
 *
 *----------------------------------------------------------------------
 */
static int
Contour(ZnWInfo *wi,
        int             argc,
        Tcl_Obj *CONST  args[],
        ZnTagSearch     **search_var)
{
  ZnPoint       *points;
  ZnItem        item, shape;
  unsigned int  i, j, k,num_points;
  int           cmd, cw, result;
  int           winding_flag, revert = False;
  long          index;
  char          *controls;
  ZnBool        simple=False;
  ZnPoly        poly;
  ZnTransfo     t, inv;
  ZnContour     *contours;

  /* Keep this array in sync with ZnContourCmd in Types.h */
#ifdef PTK_800
  static char *op_strings[] =
#else
  static CONST char *op_strings[] =
#endif
  {
    "add", "remove", NULL
  };
  
  result = ZnItemWithTagOrId(wi, args[2], &item, search_var);
  if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)){
    Tcl_AppendResult(wi->interp, "unknown item \"", Tcl_GetString(args[2]),
                     "\"", NULL);
    return TCL_ERROR;
  }
  if (!item->class->Contour) {
    if (item->class->GetClipVertices ||
        item->class->GetContours) {
      Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(1));
    }
    else {
      Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(0));
    }
    return TCL_OK;
  }
  if (argc == 3) {
    /*
     * Requesting the number of contours.
     */
    Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(item->class->Contour(item, -1, 0, NULL)));
    return TCL_OK;    
  }
  /*
   * Get the sub-command
   */
  if (Tcl_GetIndexFromObj(wi->interp, args[3], op_strings,
                          "contour operation", 0, &cmd) != TCL_OK) {
    return TCL_ERROR;
  }
  /*
   * Get the winding flag.
   */
  if ((Tcl_GetIntFromObj(wi->interp, args[4], &winding_flag) != TCL_OK) ||
      (winding_flag < -1) || (winding_flag > 1)) {
    Tcl_AppendResult(wi->interp, " incorrect winding flag, should be -1, 0, 1, \"",
                     Tcl_GetString(args[4]), "\"", NULL);
    return TCL_ERROR;
  }
  index = ZnListTail;
  if (((argc == 6) && (cmd == ZN_CONTOUR_REMOVE)) || (argc == 7)) {
    /* Look for an index value. */
    if (Tcl_GetLongFromObj(wi->interp, args[5], &index) != TCL_OK) {
      Tcl_AppendResult(wi->interp, " incorrect contour index \"",
                       Tcl_GetString(args[5]), "\"", NULL);
      return TCL_ERROR;
    }
    argc--;
    args++;
  }

  if (cmd == ZN_CONTOUR_REMOVE) {
    Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(item->class->Contour(item, ZN_CONTOUR_REMOVE, index, NULL)));
  }
  else {
    result = ZnItemWithTagOrId(wi, args[5], &shape, search_var);
    if ((result == TCL_ERROR) || (shape == ZN_NO_ITEM)) {
      Tcl_ResetResult(wi->interp);
      if (ZnParseCoordList(wi, args[5], &points,
                           &controls, &num_points, NULL) == TCL_ERROR) {
        return TCL_ERROR;
      }
      /*
       * Processing contours from an explicit list.
       */
      ZnPolyContour1(&poly, NULL, num_points, False);
      /*
       * Allocate a fresh point array, ZnParseCoordList returns a shared
       * array. The control array is not shared and can be passed along.
       */
      poly.contours[0].points = ZnMalloc(num_points*sizeof(ZnPoint));
      cw = poly.contours[0].cw = !ZnTestCCW(points, num_points);
      if (winding_flag != 0) {
        revert = cw ^ (winding_flag == -1);
      }
      if (revert) {
        /* Revert the contour */
        for (i = 0; i < num_points; i++) {
          poly.contours[0].points[num_points-i-1] = points[i];
        }
        if (controls) {
          char ch;
          for (i = 0, j = num_points-1; i < j; i++, j--) {
            ch = controls[i];
            controls[i] = controls[j];
            controls[j] = ch;
          }
        }
      }
      else {
        memcpy(poly.contours[0].points, points, num_points*sizeof(ZnPoint));
      }
      poly.contours[0].controls = controls;
    }
    else {
      /*
       * Processing contours from an item
       */
      if (winding_flag == 0) {
        Tcl_AppendResult(wi->interp,
                         "Must supply an explicit winding direction (-1, 1)\nwhen adding a contour from an item",
                         NULL);
        return TCL_ERROR;
      }
      /*
       * If something has changed in the geometry we need to
       * update or the shape will be erroneous.
       */
      Update(wi);
      if (!shape->class->GetContours &&
          !shape->class->GetClipVertices) {
        Tcl_AppendResult(wi->interp, "class: \"", shape->class->name,
                         "\" can't give a polygonal shape", NULL);
        return TCL_ERROR;
      }
      if (!shape->class->GetContours) {
        ZnTriStrip      tristrip;
        /*
         * If there is no GetContours method try to use
         * the GetClipVertices. It works only for simple
         * shapes (i.e tose returning a bounding box).
         */
        tristrip.num_strips = 0;
        /*
         * GetClipVertices _may_ return a tristrip describing a fan
         * this would lead to strange results. For now, this case
         * should not appear, the items candidates to such a behavior
         * export a GetContours method which has higher precedence.
         */
        simple = shape->class->GetClipVertices(shape, &tristrip);
        ZnPolyContour1(&poly, tristrip.strip1.points, tristrip.strip1.num_points,
                       False);
        poly.contours[0].controls = NULL;
      }
      else {
        poly.num_contours = 0;
        simple = shape->class->GetContours(shape, &poly);
      }
      if (poly.num_contours == 0) {
        return TCL_OK;
      }
      /*
       * Compute the tranform to map the device points
       * into the coordinate space of item.
       */
      ZnITEM.GetItemTransform(item, &t);
      ZnTransfoInvert(&t, &inv);
      /*
       * Make a new transformed poly and unshare
       * the contour(s) returned by the item.
       */
      if (simple) {
        ZnPoint p[4];
        p[0] = poly.contours[0].points[0];
        p[2] = poly.contours[0].points[1];
        if (winding_flag == -1) {
          p[1].x = p[2].x;
          p[1].y = p[0].y;
          p[3].x = p[0].x;
          p[3].y = p[2].y;
        }
        else {
          p[1].x = p[0].x;
          p[1].y = p[2].y;
          p[3].x = p[2].x;
          p[3].y = p[0].y;
        }
        points = ZnMalloc(4*sizeof(ZnPoint));
        ZnTransformPoints(&inv, p, points, 4);
        poly.contours[0].points = points;
        poly.contours[0].num_points = 4;
        poly.contours[0].cw = (winding_flag == -1);
        poly.contours[0].controls = NULL;
      }
      else {
        /* Unshare the contour array or use the static storage */
        contours = poly.contours;
        if (poly.num_contours == 1) {
          poly.contours = &poly.contour1;
        }
        else {
          poly.contours = ZnMalloc(poly.num_contours*sizeof(ZnContour));
        }
        for (i = 0; i < poly.num_contours; i++) {
          points = contours[i].points;
          num_points = contours[i].num_points;
          cw = contours[i].cw;
          poly.contours[i].num_points = num_points;
          poly.contours[i].cw = cw;
          if (contours[i].controls) {
            /* 
             * The controls array returned by GetContour is shared.
             * Here we unshare it.
             */
            poly.contours[i].controls = ZnMalloc(num_points*sizeof(char));
          }
          /*
           * Unshare the point array.
           */
          poly.contours[i].points = ZnMalloc(num_points*sizeof(ZnPoint));
          ZnTransformPoints(&inv, points, poly.contours[i].points, num_points);
          
          if ((((poly.num_contours == 1) && ((winding_flag == -1) ^ cw)) ||
               ((poly.num_contours > 1) && (winding_flag == -1)))) {
            ZnPoint p;
            
            revert = True;
            /* Revert the points */
            poly.contours[i].cw = ! cw;
            for (j = 0, k = num_points-1; j < k; j++, k--) {
              p = poly.contours[i].points[j];
              poly.contours[i].points[j] = poly.contours[i].points[k];
              poly.contours[i].points[k] = p;
            }
            
            /* Revert the controls */
            if (contours[i].controls) {
              for (j = 0; j < num_points; j++) {
                poly.contours[i].controls[num_points-j-1] = contours[i].controls[j];
              }
            }
          }
          else {
            if (contours[i].controls) {
              memcpy(poly.contours[i].controls, contours[i].controls, num_points);
            }
          }
        }
      }
    }

    result = item->class->Contour(item, ZN_CONTOUR_ADD, index, &poly);
    if (revert) {
      result = -result;
    }
    Tcl_SetObjResult(wi->interp, Tcl_NewIntObj(result));
    
    if (poly.contours != &poly.contour1) {
      /*
       * Must not use ZnPolyFree: the point and controls arrays
       * are passed along to the item and no longer ours.
       */
      ZnFree(poly.contours);
    }
  }

  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * Coords --
 *
 *----------------------------------------------------------------------
 */
static int
Coords(ZnWInfo          *wi,
       int              argc,
       Tcl_Obj  *CONST  args[],
       ZnTagSearch      **search_var)
{
  ZnPoint       *points;
  ZnItem        item;
  unsigned int  num_points, i;
  int           result, cmd = ZN_COORDS_READ;
  long          index, contour = 0;
  char          *str, *controls = NULL;
  Tcl_Obj       *l, *entries[3];
  
  result = ZnItemWithTagOrId(wi, args[2], &item, search_var);
  if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
    Tcl_AppendResult(wi->interp, " unknown item \"",
                     Tcl_GetString(args[2]), "\"", NULL);
    return TCL_ERROR;
  }
  if (!item->class->Coords) {
    Tcl_AppendResult(wi->interp, " ", item->class->name,
                     " does not support the coords command", NULL);
    return TCL_ERROR;
  }
  num_points = 0;
  /*printf("  coords: argc=%d, item %d class: %s\n",
    argc, item->id, item->class->name);*/
  if (argc == 3) {
    /* Get all coords of default contour (0). */
    if (item->class->Coords(item, 0, 0, ZN_COORDS_READ_ALL,
                            &points, &controls, &num_points) == TCL_ERROR) {
      return TCL_ERROR;
    }
  coords_read:
    /*printf("  coords: read %d points, first is %g@%g\n",
      num_points, points->x, points->y);*/
    l = Tcl_GetObjResult(wi->interp);
    if (ISSET(item->class->flags, ZN_CLASS_ONE_COORD)) {
      Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->x));
      Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->y));      
      if (controls && *controls) {
        Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewStringObj(controls, 1));
      }
    }
    else {
      for (i = 0; i < num_points; i++, points++) {
        entries[0] = Tcl_NewDoubleObj(points->x);
        entries[1] = Tcl_NewDoubleObj(points->y);
        if (controls && controls[i]) {
          entries[2] = Tcl_NewStringObj(&controls[i], 1);
          Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewListObj(3, entries));
        }
        else {
          Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewListObj(2, entries));
        }
      }
    }
    return TCL_OK;
  }

  /*
   * See if it is an ADD or REMOVE op.
   */
  i = 3;
  str = Tcl_GetString(args[3]);
  if ((str[0] == 'a') && (strcmp(str, "add") == 0)) {
    if ((argc < 5) || (argc > 7)) {
      Tcl_WrongNumArgs(wi->interp, 1, args,
                       "coords tagOrId add ?contour? ?index? coordList");
      return TCL_ERROR;
    }
    cmd = ZN_COORDS_ADD;
    i++;
  }
  else if ((str[0] == 'r') && (strcmp(str, "remove") == 0)) {
    if ((argc != 5) && (argc != 6)) {
      Tcl_WrongNumArgs(wi->interp, 1, args,
                       "coords tagOrId remove ?contour? index");
      return TCL_ERROR;
    }
    cmd = ZN_COORDS_REMOVE;
    i++;
  }
  
  /*
   * Try to see if the next param is a vertex index,
   * a contour index or a coord list.
   */
  /* printf("  coords: arg %d is %s\n", i, Tcl_GetString(args[i])); */
  if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != TCL_OK) {
    Tcl_ResetResult(wi->interp);
    if (((argc == 5) && (cmd != ZN_COORDS_ADD) && (cmd != ZN_COORDS_REMOVE)) ||
        (argc == 6) || (argc == 7)) {
      Tcl_AppendResult(wi->interp, " incorrect contour index \"",
                       Tcl_GetString(args[i]), "\"", NULL);
      return TCL_ERROR;
    }
    else if ((argc == 5) && (cmd != ZN_COORDS_ADD)) {
      Tcl_AppendResult(wi->interp, " incorrect coord index \"",
                       Tcl_GetString(args[i]), "\"", NULL);
      return TCL_ERROR;
    }
    else if (ZnParseCoordList(wi, args[argc-1], &points,
                              &controls, &num_points, NULL) == TCL_ERROR) {
      return TCL_ERROR;
    }
    if (cmd == ZN_COORDS_ADD) {
      /* Append coords at end of default contour (0). */
      if (item->class->Coords(item, 0, 0, ZN_COORDS_ADD_LAST,
                              &points, &controls, &num_points) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    else {
      /* Set all coords of default contour (0). */
      if (item->class->Coords(item, 0, 0, ZN_COORDS_REPLACE_ALL,
                              &points, &controls, &num_points) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    if (controls) {
      ZnFree(controls);
    }
    return TCL_OK;
  }

  contour = index;
  if (argc == 4) {
    /* Get all coords of contour. */
    if (item->class->Coords(item, contour, 0, ZN_COORDS_READ_ALL,
                            &points, &controls, &num_points) == TCL_ERROR) {
      return TCL_ERROR;
    }
    goto coords_read;
  }
  else if ((argc == 5) && (cmd == ZN_COORDS_REMOVE)) {
    /*  Remove coord at index in default contour (0). */
    if (item->class->Coords(item, 0, index, ZN_COORDS_REMOVE,
                            &points, &controls, &num_points) == TCL_ERROR) {
      return TCL_ERROR;
    }
    return TCL_OK;
  }
  /*
   * Try to see if the next param is a vertex index or a coord list.
   */
  i++;
  /*printf("  coords: arg %d is %s\n", i, Tcl_GetString(args[i]));*/
  if (Tcl_GetLongFromObj(wi->interp, args[i], &index) != TCL_OK) {
    Tcl_ResetResult(wi->interp);
    if ((argc == 7) || ((argc == 6) && (cmd != ZN_COORDS_ADD))) {
      Tcl_AppendResult(wi->interp, " incorrect coord index \"",
                       Tcl_GetString(args[i]), "\"", NULL);
      return TCL_ERROR;
    }
    else if (ZnParseCoordList(wi, args[argc-1], &points,
                              &controls, &num_points, NULL) == TCL_ERROR) {
      return TCL_ERROR;
    }
    if (cmd == ZN_COORDS_ADD) {
      /* Append coords at end of contour. */
      if (item->class->Coords(item, contour, 0, ZN_COORDS_ADD_LAST,
                              &points, &controls, &num_points) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    else {
      /* Set all coords of contour. */
      if (item->class->Coords(item, contour, 0, ZN_COORDS_REPLACE_ALL,
                              &points, &controls, &num_points) == TCL_ERROR) {
        return TCL_ERROR;
      }
    }
    if (controls) {
      ZnFree(controls);
    }
    return TCL_OK;
  }
  if (argc == 5) {
    /* Get coord of contour at index. */
    if (item->class->Coords(item, contour, index, ZN_COORDS_READ,
                            &points, &controls, &num_points) == TCL_ERROR) {
      return TCL_ERROR;
    }
    if (num_points) {
      /*printf("  coords: read contour:%d, index:%d, point is %g@%g\n",
        contour, index, points->x, points->y);    */
      l = Tcl_GetObjResult(wi->interp);
      Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->x));
      Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(points->y));
      if (controls && *controls) {
        Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewStringObj(controls, 1));
      }
    }
    return TCL_OK;
  }
  else if ((argc == 6) && (cmd == ZN_COORDS_REMOVE)) {
    /*  Remove coord of contour at index. */
    if (item->class->Coords(item, contour, index, ZN_COORDS_REMOVE,
                            &points, &controls, &num_points) == TCL_ERROR) {
      return TCL_ERROR;
    }
    return TCL_OK;
  }
  
  /* Set a single coord or add coords at index in contour. */
  if (ZnParseCoordList(wi, args[argc-1], &points,
                       &controls, &num_points, NULL) == TCL_ERROR) {
    return TCL_ERROR;
  }
  if (argc == 6) {
    num_points = 1;
    cmd = ZN_COORDS_REPLACE;
  }
  if (item->class->Coords(item, contour, index, cmd,
                          &points, &controls, &num_points) == TCL_ERROR) {
    return TCL_ERROR;
  }
  if (controls) {
    ZnFree(controls);
  }
  return TCL_OK;
}


/*
 *----------------------------------------------------------------------
 *
 * WidgetObjCmd --
 *
 *      This procedure is invoked to process the Tcl command
 *      that corresponds to a widget managed by this module.
 *      See the user documentation for details on what it does.
 *
 * Results:
 *      A standard Tcl result.
 *
 * Side effects:
 *      See the user documentation.
 *
 *----------------------------------------------------------------------
 */
static int
WidgetObjCmd(ClientData         client_data,    /* Information about the widget. */
             Tcl_Interp         *interp,        /* Current interpreter. */
             int                argc,           /* Number of arguments. */
             Tcl_Obj *CONST     args[])         /* Arguments. */
{
  ZnWInfo       *wi = (ZnWInfo *) client_data;
  int           length, result, cmd_index, index;
  ZnItem        item, item2;
  int           field = ZN_NO_PART;
  unsigned int  num = 0, i, j;
  char          *end, *str;
  ZnTransfo     *t = NULL;
  Tcl_Obj       *l;
  ZnTagSearch   *search_var = NULL;
  Tcl_HashEntry *entry;
  ZnPoint       *points;
  ZnPoint       p;
  unsigned int  num_points;
  ZnList        to_points;
  Tcl_Obj       *entries[3];
  char          c[] = "c";
  double        d;

#ifdef PTK_800
  static char *sub_cmd_strings[] =
#else
  static CONST char *sub_cmd_strings[] =
#endif
  {
    "add", "addtag", "anchorxy", "bbox", "becomes", "bind",
    "cget", "chggroup", "clone", "collapsemotions", "configure",
    "contour", "coords", "currentpart", "cursor", "dchars",
    "dtag", "find", "fit", "focus", "gdelete",
    "gettags", "gname", "group", "hasanchors", "hasfields",
    "hastag", "index", "insert", "itemcget", "itemconfigure",
    "layout", "lower", "monitor", "numparts", "postscript",
    "raise", "remove", "rotate", "scale", "select", "skew",
    "smooth", "tapply", "tcompose", "tdelete", "tget",
    "transform", "translate", "treset", "trestore", "tsave",
    "tset", "type", "vertexat", "xview", "yview", NULL
  };
  enum          sub_cmds {
    ZN_W_ADD, ZN_W_ADDTAG, ZN_W_ANCHORXY, ZN_W_BBOX, ZN_W_BECOMES, ZN_W_BIND,
    ZN_W_CGET, ZN_W_CHGGROUP, ZN_W_CLONE, ZN_W_COLLAPSEMOTIONS, 
    ZN_W_CONFIGURE, ZN_W_CONTOUR, ZN_W_COORDS, ZN_W_CURRENTPART, ZN_W_CURSOR,
    ZN_W_DCHARS, ZN_W_DTAG, ZN_W_FIND, ZN_W_FIT, ZN_W_FOCUS, ZN_W_GDELETE,
    ZN_W_GETTAGS, ZN_W_GNAME, ZN_W_GROUP, ZN_W_HASANCHORS, ZN_W_HASFIELDS,
    ZN_W_HASTAG, ZN_W_INDEX, ZN_W_INSERT, ZN_W_ITEMCGET, ZN_W_ITEMCONFIGURE,
    ZN_W_LAYOUT, ZN_W_LOWER, ZN_W_MONITOR, ZN_W_NUMPARTS, ZN_W_POSTSCRIPT,
    ZN_W_RAISE, ZN_W_REMOVE, ZN_W_ROTATE, ZN_W_SCALE, ZN_W_SELECT, ZN_W_SKEW,
    ZN_W_SMOOTH, ZN_W_TAPPLY, ZN_W_TCOMPOSE, ZN_W_TDELETE, ZN_W_TGET,
    ZN_W_TRANSFORM, ZN_W_TRANSLATE, ZN_W_TRESET, ZN_W_TRESTORE, ZN_W_TSAVE,
    ZN_W_TSET, ZN_W_TYPE, ZN_W_VERTEX_AT, ZN_W_XVIEW, ZN_W_YVIEW
  };
#ifdef PTK_800
  static char *sel_cmd_strings[] =
#else
  static CONST char *sel_cmd_strings[] =
#endif
  {
    "adjust", "clear", "from", "item", "to", NULL
  };
  enum          sel_cmds {
    ZN_SEL_ADJUST, ZN_SEL_CLEAR, ZN_SEL_FROM, ZN_SEL_ITEM, ZN_SEL_TO
  };

  
  if (argc < 2) {
    Tcl_WrongNumArgs(interp, 1, args, "subcommand ?args?");
    return TCL_ERROR;
  }

  Tcl_Preserve((ClientData) wi);
  
  if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings,
                          "subcommand", 0, &cmd_index) != TCL_OK) {
    goto error;
  }
  result = TCL_OK;

  /*printf("executing command \"%s\", argc=%d\n",
    Tcl_GetString(args[1]), argc);*/
  switch((enum sub_cmds) cmd_index) {
    /*
     * add
     */
  case ZN_W_ADD:
    {
      ZnItem      group;
      ZnItemClass cls;
      
      if (argc == 2) { /* create subcommand alone, return the list of known
                        * object types. */
        ZnItemClass     *classes = ZnListArray(ZnItemClassList());
        
        num = ZnListSize(ZnItemClassList());
        l = Tcl_GetObjResult(interp);
        for (i = 0; i < num; i++) {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(classes[i]->name, -1));
        }
        goto done;
      }
      if ((argc < 4)) {
      add_err:
        Tcl_WrongNumArgs(interp, 1, args, "add type group ?args?");
        goto error;
      }
      str = Tcl_GetString(args[2]);
      if (str[0] == '-') {
        goto add_err;
      }
      cls = ZnLookupItemClass(str);
      if (!cls) {
        Tcl_AppendResult(interp, "unknown item type \"", str, "\"", NULL);
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[3], &group, &search_var);
      if ((result == TCL_ERROR) || (group == ZN_NO_ITEM) ||
          (group->class != ZnGroup)) {
        Tcl_AppendResult(interp, ", group item expected, got \"",
                         Tcl_GetString(args[3]), "\"", NULL);
        goto error;
      }
      
      argc -= 4;
      args += 4;
      item = ZnCreateItem(wi, cls, &argc, &args);
      if (item == ZN_NO_ITEM) {
        goto error;
      }
      ZnITEM.InsertItem(item, group, ZN_NO_ITEM, True);
      if (ZnITEM.ConfigureItem(item, ZN_NO_PART, argc, args, True) == TCL_ERROR) {
        goto error;
      }
      wi->hot_item = item;
      wi->hot_prev = item->previous;
      l = Tcl_NewLongObj(item->id);
      Tcl_SetObjResult(interp, l);
    }
    break;
    /*
     * addtag
     */
  case ZN_W_ADDTAG:
    {
      if (argc < 4) {
        Tcl_WrongNumArgs(interp, 1, args, "addtag tag searchCommand ?arg arg ...?");
        goto error;
      }
      result = FindItems(wi, argc, args, args[2], 3, &search_var);
    }
    break;
    /*
     * anchorxy
     */
  case ZN_W_ANCHORXY:
    {
      Tk_Anchor anchor;
      
      if (argc != 4) {
        Tcl_WrongNumArgs(interp, 1, args, "anchorxy tagOrId anchor");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM) ||
          ISCLEAR(item->class->flags, ZN_CLASS_HAS_ANCHORS)) {
        Tcl_AppendResult(interp, "unknown item or doesn't support anchors \"",
                         Tcl_GetString(args[2]), NULL);
        goto error;
      }
      if (Tk_GetAnchor(interp, Tcl_GetString(args[3]), &anchor)) {
        goto error;
      }
      /*
       * If something has changed in the geometry we need to
       * update or the anchor location will be erroneous.
       */
      Update(wi);
      item->class->GetAnchor(item, anchor, &p);
      l = Tcl_GetObjResult(wi->interp);
      Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(p.x));
      Tcl_ListObjAppendElement(wi->interp, l, Tcl_NewDoubleObj(p.y));
    }
    break;
    /*
     * becomes
     */
  case ZN_W_BECOMES:
    {
      Tcl_AppendResult(interp, "Command not yet implemented", NULL);
      goto error;
    }
    break;
    /*
     * bbox
     */
  case ZN_W_BBOX:
    {
      ZnBBox    bbox;
      ZnDim     width, height;
      ZnFieldSet fs;

      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args, "bbox ?-field fieldNo? ?-label? tagOrId ?tagOrId ...?");
        goto error;
      }
      argc -= 2;
      args += 2;
      
      Update(wi);
      ZnResetBBox(&bbox);

      str = Tcl_GetString(args[0]);
      if (*str == '-') {
        if ((strcmp(str, "-field") == 0) && (argc > 2)) {
          if (Tcl_GetIntFromObj(wi->interp, args[1], &field) == TCL_ERROR) {
            goto error;
          }
          argc -= 2;
          args += 2;
        }
        else if ((strcmp(str, "-label") == 0) && (argc > 1)) {
          field = -1;
          argc--;
          args++;
        }
        else {
          Tcl_AppendResult(interp, "bbox option should be -field numField or -label",
                           NULL);
          goto error;
        }
        result = ZnItemWithTagOrId(wi, args[0], &item, &search_var);
        if ((result == TCL_ERROR) || (item == ZN_NO_ITEM) ||
            ! item->class->GetFieldSet) {
          Tcl_AppendResult(interp, "unknown item or doesn't support fields \"",
                           Tcl_GetString(args[0]), "\"", NULL);
          goto error;
        }
        fs = item->class->GetFieldSet(item);
        if (field >= 0) {
          if ((unsigned int) field >= fs->num_fields) {
            Tcl_AppendResult(interp, "field index is out of bounds", NULL);
            goto error;   
          }
          ZnFIELD.GetFieldBBox(fs, field, &bbox);
        }
        else {
          ZnFIELD.GetLabelBBox(fs, &width, &height);
          if (width && height) {
            p.x = ZnNearestInt(fs->label_pos.x);
            p.y = ZnNearestInt(fs->label_pos.y);
            ZnAddPointToBBox(&bbox, p.x, p.y);
            p.x += width;
            p.y += height;
            ZnAddPointToBBox(&bbox, p.x, p.y);
          }
        }       
      }
      else {
        for (i = 0; i < (unsigned int) argc; i++) {
          /*
           * Check for options in wrong place amidst tags.
           */
          str = Tcl_GetString(args[i]);
          if (*str == '-') {
            Tcl_AppendResult(interp, "bbox options should be specified before any tag", NULL);
            goto error;
          }
          if (ZnTagSearchScan(wi, args[i], &search_var) == TCL_ERROR) {
            goto error;
          }     
          for (item = ZnTagSearchFirst(search_var);
               item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
            ZnAddBBoxToBBox(&bbox, &item->item_bounding_box);
          }
        }
      }

      if (!ZnIsEmptyBBox(&bbox)) {
        l = Tcl_GetObjResult(interp);
        Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.orig.x));
        Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.orig.y));
        Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.corner.x));
        Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(bbox.corner.y));
      }
    }
    break;
    /*
     * bind
     */
  case ZN_W_BIND:
    {
      ClientData        elem = 0;
      int               part = ZN_NO_PART;
      
      if ((argc < 3) || (argc > 6)) {
        Tcl_WrongNumArgs(interp, 1, args,
                         "bind tagOrId ?part? ?sequence? ?command?");
        goto error;
      }
      /*
       * Test if (a) an itemid or (b) an itemid:part or
       * (c) an item part or (d) a tag is provided.
       */
      str = Tcl_GetString(args[2]);

      argc -= 3;
      args += 3;

      if (isdigit(str[0])) {
        int     id;
        
        id = strtoul(str, &end, 0);
        if ((*end != 0) && (*end != ':')) {
          goto bind_a_tag;
        }
        entry = Tcl_FindHashEntry(wi->id_table, (char *) id);
        if (entry == NULL) {
          Tcl_AppendResult(interp, "item \"", str, "\" doesn't exist", NULL);
          goto error;
        }
        item = elem = Tcl_GetHashValue(entry);
        if (!elem) {
          goto error;
        }

        if (*end == ':') {
          /*
           * The part is provided with the id (old method).
           */
          end++;
        part_encode:
          if (item->class->Part) {
            l = Tcl_NewStringObj(end, -1);
            if (item->class->Part(item, &l, &part) == TCL_ERROR) {
              goto error;
            }
            elem = EncodeItemPart(item, part);
          }
          else {
            Tcl_AppendResult(interp, "item \"", str, "\" doesn't have parts", NULL);
            goto error;
          }
        }
        else {
          /*
           * Check if a part is given in the next parameter
           * (alternative method for providing a part).
           */
          if (argc > 3) {
            str = Tcl_GetString(args[0]);
            if (str[0] != '<') {
              end = str;
              argc--;
              args++;
              goto part_encode;
            }
          }
        }
        /*printf("adding element 0x%X to the binding table of item 0x%X\n", elem, item);*/
      }
      else {
      bind_a_tag:
        elem = (ClientData) Tk_GetUid(str);
      }
      
      /*
       * Make a binding table if the widget doesn't already have one.
       */ 
      if (wi->binding_table == NULL) {
        wi->binding_table = Tk_CreateBindingTable(interp);
      }
      
      if (argc == 2) {
        int         append = 0;
        unsigned long mask;

        str = Tcl_GetString(args[1]);
        if (str[0] == 0) {
          result = Tk_DeleteBinding(interp, wi->binding_table, elem,
                                    Tcl_GetString(args[0]));
          goto done;
        }
#ifdef PTK
        mask = Tk_CreateBinding(interp, wi->binding_table,
                                elem, Tcl_GetString(args[0]), args[1], append);
#else
        if (str[0] == '+') {
          str++;
          append = 1;
        }
        mask = Tk_CreateBinding(interp, wi->binding_table,
                                elem, Tcl_GetString(args[0]), str, append);
#endif
        if (mask == 0) {
          goto error;
        }
        if (mask & (unsigned) ~(ButtonMotionMask | Button1MotionMask |
                                Button2MotionMask | Button3MotionMask |
                                Button4MotionMask | Button5MotionMask | 
                                ButtonPressMask | ButtonReleaseMask |
                                EnterWindowMask | LeaveWindowMask |
                                KeyPressMask | KeyReleaseMask |
                                PointerMotionMask | VirtualEventMask |
                                MouseWheelMask)) {
          Tk_DeleteBinding(interp, wi->binding_table, elem, Tcl_GetString(args[3]));
          Tcl_ResetResult(interp);
          Tcl_AppendResult(interp, "requested illegal events; ",
                           "only key, button, motion, enter, leave ",
                           "mousewheel and virtual events may be used", NULL);
          goto error;
        }
      }
      else if (argc == 1) {
#ifdef PTK
        Tcl_Obj *command;
        command = Tk_GetBinding(interp, wi->binding_table, elem,
                                Tcl_GetString(args[0]));
        if (command == NULL) {
          char *string = Tcl_GetString(Tcl_GetObjResult(interp));
          /*
           * Ignore missing binding errors.  This is a special hack
           * that relies on the error message returned by FindSequence
           * in tkBind.c.
           */
          if (string[0] != '\0') {
            goto error;
          }
          else {
            Tcl_ResetResult(interp);
          }
        }
        else {
          Tcl_SetObjResult(interp, command);
        }
#else
        CONST char *command;
        command = Tk_GetBinding(interp, wi->binding_table, elem,
                                Tcl_GetString(args[0]));
        if (command == NULL) {
          goto error;
        }
        Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
#endif
      }
      else {
        Tk_GetAllBindings(interp, wi->binding_table, elem);
      }
    }
    break;
    /*
     * cget
     */
  case ZN_W_CGET:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "cget option");
        goto error;
      }
#ifdef PTK_800
      result = Tk_ConfigureValue(interp, wi->win, config_specs,
                                 (char *) wi, Tcl_GetString(args[2]), 0);
#else
      l = Tk_GetOptionValue(interp, (char *) wi, wi->opt_table, args[2], wi->win);
      if (l == NULL) {
        goto error;
      }
      Tcl_SetObjResult(interp, l);
#endif
    }
    break;
    /*
     * chggroup
     */
  case ZN_W_CHGGROUP:
    {
      ZnItem    grp, scan;
      int       adjust=0;
      ZnTransfo inv, t, t2, *this_one=NULL;
      
      if ((argc != 4) && (argc != 5)) {
        Tcl_WrongNumArgs(interp, 1, args, "chggroup tagOrIg group ?adjustTransform?");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[3], &grp, &search_var);
      if ((result == TCL_ERROR) || (grp == ZN_NO_ITEM)|| (grp->class != ZnGroup)) {
        goto error;
      }
      if (item->parent == grp) {
        /*
         * Nothing to be done, the item is already in the
         * target group.
         */
        goto done;
      }
      /*
       * Check the ancestors to find if item is an
       * ancestor of grp, which would lead to a
       * forbidden move.
       */
      for (scan = grp; scan && (scan != item); scan = scan->parent);
      if (scan == item) {
        Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]),
                         "\" is a descendant of \"", Tcl_GetString(args[2]),
                         "\" and can't be used as its parent", NULL);
        goto error;
      }
      if (argc == 5) {
        if (Tcl_GetBooleanFromObj(interp, args[4], &adjust) != TCL_OK) {
          goto error;
        }
      }
      if ((item->parent == grp) || (item->parent == ZN_NO_ITEM)) {
        goto done;
      }
      if (adjust) {
        ZnITEM.GetItemTransform(grp, &t);
        ZnTransfoInvert(&t, &inv);
        ZnITEM.GetItemTransform(item->parent, &t);
        ZnTransfoCompose(&t2, &t, &inv);
        this_one = &t2;
        if (item->transfo) {
          ZnTransfoCompose(&t, item->transfo, &t2);
          this_one = &t;
        }
      }
      ZnITEM.ExtractItem(item);
      ZnITEM.InsertItem(item, grp, ZN_NO_ITEM, True);
      /*
       * The item can be a group in which case we must
       * use the ZN_TRANSFO_FLAG to force an update of
       * the children. In all other case ZN_COORDS_FLAG
       * is enough.
       */
      ZnITEM.Invalidate(item,
                      item->class==ZnGroup?ZN_TRANSFO_FLAG:ZN_COORDS_FLAG);
      if (adjust) {
        ZnITEM.SetTransfo(item, this_one);
      }
    }
    break;
    /*
     * clone
     */
  case ZN_W_CLONE:
    {
      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args, "clone tagOrId ?option value ...?");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) ||
          (item == ZN_NO_ITEM) || (item == wi->top_group)) {
        goto error;
      }
      argc -= 3;
      args += 3;
      item2 = ZnITEM.CloneItem(item);
      ZnITEM.InsertItem(item2, item->parent, ZN_NO_ITEM, True);
      if (ZnITEM.ConfigureItem(item2, ZN_NO_PART, argc, args, False) == TCL_ERROR) {
        goto error;
      }
      l = Tcl_NewLongObj(item2->id);
      Tcl_SetObjResult(interp, l);
    }
    break;
    /*
     * collapsemotions
     */
  case ZN_W_COLLAPSEMOTIONS:
    {
      ZnBool collapse, current;

      if ((argc != 2) && (argc != 3)) {
        Tcl_WrongNumArgs(interp, 1, args, "collapsemotions ?boolean?");
        goto error;
      }
      if (argc == 3) {
        if (Tcl_GetBooleanFromObj(interp, args[2], &collapse) != TCL_OK) {
          goto error;
        }
        current = Tk_CollapseMotionEvents(wi->dpy, collapse);
      }
      else {
        current = Tk_CollapseMotionEvents(wi->dpy, 1);
        Tk_CollapseMotionEvents(wi->dpy, current);
      }
      Tcl_SetObjResult(interp, Tcl_NewBooleanObj(current));
      break;
    }
    /*
     * configure
     */
  case ZN_W_CONFIGURE:
    {
#ifdef PTK_800
      if (argc == 2) {
        result = Tk_ConfigureInfo(interp, wi->win, config_specs,
                                  (char *) wi, (char *) NULL, 0);
      }
      else if (argc == 3) {
        result = Tk_ConfigureInfo(interp, wi->win, config_specs,
                                  (char *) wi, Tcl_GetString(args[2]), 0);
      }
      else {
        result = Configure(interp, wi, argc-2, args+2, TK_CONFIG_ARGV_ONLY);
      }
#else
      if (argc == 2) {
        l = Tk_GetOptionInfo(interp, (char *) wi, wi->opt_table,
                             (argc == 3) ? args[2] : NULL, wi->win);
        if (l == NULL) {
          goto error;
        }
        else {
          Tcl_SetObjResult(interp, l);
        }
      }
      else {
        result = Configure(interp, wi, argc-2, args+2);
      }
#endif
    }
    break;
    /*
     * contour
     */
  case ZN_W_CONTOUR:
    {
      if ((argc < 3) || (argc > 7)) {
        Tcl_WrongNumArgs(interp, 1, args,
                         "contour tagOrId ?operator windingFlag? ?index? ?coordListOrTagOrId?");
        goto error;
      }
      if (Contour(wi, argc, args, &search_var) == TCL_ERROR) {
        goto error;
      }
      break;
    }
    /*
     * coords
     */
  case ZN_W_COORDS:
    {
      if ((argc < 3) || (argc > 7)) {
        Tcl_WrongNumArgs(interp, 1, args,
                         "coords tagOrId ?add/remove? ?contour? ?index? ?coordList?");
        goto error;
      }
      if (Coords(wi, argc, args, &search_var) == TCL_ERROR) {
        goto error;
      }
    }
    break;
    /*
     * currentpart
     */
  case ZN_W_CURRENTPART:
    {
      ZnBool    only_fields = False;
      if ((argc != 2) && (argc != 3)) {
        Tcl_WrongNumArgs(interp, 1, args, "currentpart ?onlyFields?");
        goto error;
      }
      if (argc == 3) {
        if (Tcl_GetBooleanFromObj(interp, args[2], &only_fields) != TCL_OK) {
          goto error;
        }
      }
      if ((wi->current_item != ZN_NO_ITEM) &&
          (wi->current_item->class->Part != NULL) &&
          ((wi->current_part >= 0) || !only_fields)) {
        l = NULL;
        wi->current_item->class->Part(wi->current_item, &l, &wi->current_part);
        Tcl_SetObjResult(interp, l);
      }
    }
    break;
    /*
     * cursor
     */
  case ZN_W_CURSOR:
    {
      if ((argc != 4) && (argc != 5)) {
        Tcl_WrongNumArgs(interp, 1, args, "cursor tagOrId ?field? index");
        goto error;
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      if (argc == 5) {
        if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
          field = ZN_NO_PART;
          if (Tcl_GetString(args[3])[0] != 0) { 
            Tcl_AppendResult(interp, "invalid field index \"",
                             Tcl_GetString(args[3]),
                             "\", should be a positive integer", NULL);
            goto error;
          }
        }
        argc--;
        args++;
      }
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        if ((item->class->Cursor == NULL) ||
            (item->class->Index == NULL)) {
          continue;
        }
        result = (*item->class->Index)(item, field, args[3], &index);
        if (result != TCL_OK) {
          goto error;
        }
        
        (*item->class->Cursor)(item, field, index);
        if ((item == wi->focus_item) && (field == wi->focus_field) &&
            wi->text_info.cursor_on) {
          ZnITEM.Invalidate(item, ZN_DRAW_FLAG);
        }
      }
    }
    break;
    /*
     * dchars
     */
  case ZN_W_DCHARS:
    {
      int        first, last;
      ZnTextInfo *ti = &wi->text_info;

      if ((argc < 4) || (argc > 6)) {
        Tcl_WrongNumArgs(interp, 1, args, "dchars tagOrId ?field? first ?last?");
        goto error;
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      if (argc == 6) {
        if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
          field = ZN_NO_PART;
          if (Tcl_GetString(args[3])[0] != 0) { 
            Tcl_AppendResult(interp, "invalid field index \"",
                             Tcl_GetString(args[3]),
                             "\", should be a positive integer", NULL);
            goto error;
          }
        }
        argc--;
        args++;
      }
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        if ((item->class->Index == NULL) ||
            (item->class->DeleteChars == NULL)) {
          continue;
        }
        result = (*item->class->Index)(item, field, args[3], &first);
        if (result != TCL_OK) {
          goto error;
        }
        if (argc == 5) {
          result = (*item->class->Index)(item, field, args[4], &last);
          if (result != TCL_OK) {
            goto error;
          }
        }
        else {
          last = first;
        }
        (*item->class->DeleteChars)(item, field, &first, &last);

        /*
         * Update indexes for the selection to reflect the
         * change.
         */
        if ((ti->sel_item == item) && (ti->sel_field == field)) {
          int count = last + 1 - first;
          if (ti->sel_first > first) {
            ti->sel_first -= count;
            if (ti->sel_first < first) {
              ti->sel_first = first;
            }
          }
          if (ti->sel_last >= first) {
            ti->sel_last -= count;
            if (ti->sel_last < (first-1)) {
              ti->sel_last = first-1;
            }
          }
          if (ti->sel_first >= ti->sel_last) {
            ti->sel_item = ZN_NO_ITEM;
            ti->sel_field = ZN_NO_PART;
          }
          if ((ti->anchor_item == item) && (ti->anchor_field == field) &&
              (ti->sel_anchor > first)) {
            ti->sel_anchor -= count;
            if (ti->sel_anchor < first) {
              ti->sel_anchor = first;
            }
          }
        }
      }
    }
    break;
    /*
     * dtag
     */
  case ZN_W_DTAG:
    {
      Tk_Uid            tag;
      
      if ((argc != 3) && (argc != 4)) {
        Tcl_WrongNumArgs(interp, 1, args, "dtag tagOrId ?tagToDelete?");
        goto error;
      }
      if (argc == 4) {
        tag = Tk_GetUid(Tcl_GetString(args[3]));
      }
      else {
        tag = Tk_GetUid(Tcl_GetString(args[2]));
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        ZnITEM.RemoveTag(item, (char *) tag);
      }
    }
    break;
    /*
     * find
     */
  case ZN_W_FIND:
    {
      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args, "find searchCommand ?arg arg ...?");
        goto error;
      }
      result = FindItems(wi, argc, args, NULL, 2, &search_var);
    }
    break;
    /*
     * fit
     */
  case ZN_W_FIT:
    {
      if (argc != 4) {
        Tcl_WrongNumArgs(interp, 1, args, "fit coordList error");
        goto error;
      }
      if (ZnParseCoordList(wi, args[2], &points,
                           NULL, &num_points, NULL) == TCL_ERROR) {
        return TCL_ERROR;
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
        goto error;
      }
      to_points = ZnListNew(32, sizeof(ZnPoint));
      ZnFitBezier(points, num_points, d, to_points);
      points = (ZnPoint *) ZnListArray(to_points);
      num_points = ZnListSize(to_points);
      l = Tcl_GetObjResult(interp);
      for (i = 0; i < num_points; i++, points++) {
        entries[0] = Tcl_NewDoubleObj(points->x);
        entries[1] = Tcl_NewDoubleObj(points->y);
        if (i % 3) {
          entries[2] = Tcl_NewStringObj(c, -1);
          Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(3, entries));
        }
        else {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries));
        }
      } 
      ZnListFree(to_points);
    }
    break;
    /*
     * focus
     */
  case ZN_W_FOCUS:
    {
      if (argc > 4) {
        Tcl_WrongNumArgs(interp, 1, args, "focus ?tagOrId? ?field?");
        goto error;
      }
      item = wi->focus_item;
      if (argc == 2) {
        field = wi->focus_field;
        if (item != ZN_NO_ITEM) {
          l = Tcl_GetObjResult(interp);
          Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(item->id));
          if (field != ZN_NO_PART) {
            Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(field));
          }
          else {
            Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj("", -1));
          }
        }
        break;
      }
      if ((item != ZN_NO_ITEM) && (item->class->Cursor != NULL) &&
          ISSET(wi->flags, ZN_GOT_FOCUS)) {
        ZnITEM.Invalidate(item, ZN_COORDS_FLAG);
      }
      if (Tcl_GetString(args[2])[0] == 0) {
        wi->focus_item = ZN_NO_ITEM;
        wi->focus_field = ZN_NO_PART;
        break;
      }
      if (ZnItemWithTagOrId(wi, args[2], &item, &search_var) == TCL_ERROR) {
        goto error;
      }
      if (argc == 4) {
        if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
          field = ZN_NO_PART;
          if (Tcl_GetString(args[3])[0] != 0) { 
            Tcl_AppendResult(interp, "invalid field index \"",
                             Tcl_GetString(args[3]),
                             "\", should be a positive integer", NULL);
            goto error;
          }
        }
      }
      wi->focus_item = item;
      wi->focus_field = field;
      if (ISSET(wi->flags, ZN_GOT_FOCUS) && (item->class->Cursor != NULL)) {
        ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
      }
    }
    break;
    /*
     * gdelete
     */
  case ZN_W_GDELETE:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "gdelete gName");
        goto error;
      }
      ZnDeleteGradientName(Tcl_GetString(args[2]));
    }    
    break;
    /*
     * gettags
     */
  case ZN_W_GETTAGS:
    {
      Tk_Uid    *tags;
      
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "gettags tagOrId");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      if (!item->tags || !ZnListSize(item->tags)) {
        goto done;
      }
      else {
        num = ZnListSize(item->tags);
        tags = (Tk_Uid *) ZnListArray(item->tags);
        l = Tcl_GetObjResult(interp);
        for (i = 0; i < num; i++) {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(tags[i], -1));
        }
      }
    }
    break;
    /*
     * gname
     */
  case ZN_W_GNAME:
    {
      ZnBool    ok;
      
      if ((argc != 3) && (argc != 4)) {
        Tcl_WrongNumArgs(interp, 1, args, "gname ?grad? gName");
        goto error;
      }
      if (argc == 3) {
        l = Tcl_NewBooleanObj(ZnGradientNameExists(Tcl_GetString(args[2])));
        Tcl_SetObjResult(interp, l);
      }
      else {
        ok = ZnNameGradient(interp, wi->win, Tcl_GetString(args[2]),
                            Tcl_GetString(args[3]));
        if (!ok) {
          goto error;
        }
      }
    }
    break;
    /*
     * group
     */
  case ZN_W_GROUP:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "group tagOrId");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      if (item->parent != ZN_NO_ITEM) {
        l = Tcl_NewLongObj(item->parent->id);
        Tcl_SetObjResult(interp, l);
      }
      else {
        /*
         * Top group is its own parent.
         */
        l = Tcl_NewLongObj(item->id);
        Tcl_SetObjResult(interp, l);
      }
    }
    break;
    /*
     * hasanchors
     */
  case ZN_W_HASANCHORS:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "hasanchors tagOrId");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      l = Tcl_NewBooleanObj(ISSET(item->class->flags, ZN_CLASS_HAS_ANCHORS) ? 1 : 0);
      Tcl_SetObjResult(interp, l);
    }
    break;
    /*
     * hasfields
     */
  case ZN_W_HASFIELDS:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "hasfields tagOrId");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      l =  Tcl_NewBooleanObj(item->class->GetFieldSet?1:0);
      Tcl_SetObjResult(interp, l);
    }
    break;
    /*
     * hastag
     */
  case ZN_W_HASTAG:
    {
      if (argc != 4) {
        Tcl_WrongNumArgs(interp, 1, args, "hastag tagOrId tag");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      l = Tcl_NewBooleanObj(ZnITEM.HasTag(item,
                                          Tk_GetUid(Tcl_GetString(args[3]))));
      Tcl_SetObjResult(interp, l);
    }
    break;
    /*
     * index
     */
  case ZN_W_INDEX:
    {
      if ((argc != 4) && (argc != 5)) {
        Tcl_WrongNumArgs(interp, 1, args, "index tagOrId ?field? string");
        goto error;
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      if (argc == 5) {
        if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
          field = ZN_NO_PART;
          if (Tcl_GetString(args[3])[0] != 0) {
            Tcl_AppendResult(interp, "invalid field index \"",
                             Tcl_GetString(args[3]),
                             "\", should be a positive integer", NULL);
            goto error;
          }
        }
        argc--;
        args++;
      }
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        if (item->class->Index != NULL) {
          result = (*item->class->Index)(item, field, args[3], &index);
          if (result != TCL_OK) {
            goto error;
          }
          l = Tcl_NewIntObj(index);
          Tcl_SetObjResult(interp, l);
          goto done;
        }
      }
      Tcl_AppendResult(interp, "can't find an indexable item \"",
                       Tcl_GetString(args[2]), "\"", NULL);
      goto error;
    }
    break;
    /*
     * insert
     */
  case ZN_W_INSERT:
    {
      ZnTextInfo *ti = &wi->text_info;
      char       *chars;

      if ((argc != 5) && (argc != 6)) {
        Tcl_WrongNumArgs(interp, 1, args, "insert tagOrId ?field? before string");
        goto error;
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      if (argc == 6) {
        if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
          field = ZN_NO_PART;
          if (Tcl_GetString(args[3])[0] != 0) { 
            Tcl_AppendResult(interp, "invalid field index \"",
                             Tcl_GetString(args[3]),
                             "\", should be a positive integer", NULL);
            goto error;
          }
        }
        argc--;
        args++;
      }
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        if ((item->class->Index == NULL) ||
            (item->class->InsertChars == NULL)) {
          continue;
        }
        result = (*item->class->Index)(item, field, args[3], &index);
        if (result != TCL_OK) {
          goto error;
        }
        chars = Tcl_GetString(args[4]);
        (*item->class->InsertChars)(item, field, &index, chars);
        /*
         * Inserting characters invalidates selection indices.
         */
        if ((ti->sel_item == item) && (ti->sel_field == field)) {
          length = strlen(chars);
          if (ti->sel_first >= index) {
            ti->sel_first += length;
          }
          if (ti->sel_last >= index) {
            ti->sel_last += length;
          }
          if ((ti->anchor_item == item) && (ti->anchor_field == field) &&
              (ti->sel_anchor >= index)) {
            ti->sel_anchor += length;
          }
        }
      }
    }
    break;
    /*
     * itemcget
     */
  case ZN_W_ITEMCGET:
    {
      if (argc < 4) {
      itemcget_syntax:
        Tcl_WrongNumArgs(interp, 1, args, "itemcget tagOrId ?field? option");
        goto error;
      }    
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      if (argc == 5) {
        if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
          field = ZN_NO_PART;
          if (Tcl_GetString(args[3])[0] != 0) {
            Tcl_AppendResult(interp, "invalid field index \"",
                             Tcl_GetString(args[3]),
                             "\", should be a positive integer", NULL);
            goto error;
          }
        }
        argc--;
        args++;
      }
      if (argc != 4) {
        goto itemcget_syntax;     
      }
      if (ZnITEM.QueryItem(item, field, 1, &args[3]) != TCL_OK) {
        goto error;
      }
    }
    break;
    /*
     * itemconfigure
     */
  case ZN_W_ITEMCONFIGURE:
    {
      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args,
                         "itemconfigure tagOrId ?field? option value ?option value? ...");
        goto error;
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      if ((argc > 3) && (Tcl_GetString(args[3])[0] != '-')) {
        if (Tcl_GetIntFromObj(interp, args[3], &field) != TCL_OK) {
          field = ZN_NO_PART;
          if (Tcl_GetString(args[3])[0] != 0) { 
            Tcl_AppendResult(interp, "invalid field index \"",
                             Tcl_GetString(args[3]),
                             "\", should be a positive integer", NULL);
            goto error;
          }
        }
        argc--;
        args++;
      }
      argc -= 3;
      args += 3;
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        if (argc < 2) {
          if (field == ZN_NO_PART) {
            result = ZnAttributesInfo(wi->interp, item, item->class->attr_desc, argc, args);
          }
          else if (item->class->GetFieldSet) {
            ZnFieldSet fs = item->class->GetFieldSet(item);
            if (field < (int) ZnFIELD.NumFields(fs)) {
              result = ZnAttributesInfo(wi->interp, ZnFIELD.GetFieldStruct(fs, field),
                                        ZnFIELD.attr_desc, argc, args);
            }
            else {
              Tcl_AppendResult(interp, "field index out of bound", NULL);
              goto error;
            }
          }
          else {
            Tcl_AppendResult(interp, "the item does not support fields", NULL);
            goto error;
          }
          goto done;
        }
        else {
          result = ZnITEM.ConfigureItem(item, field, argc, args, False);
        }
        if (result == TCL_ERROR) {
          goto error;
        }
      }
    }
    break;
    /*
     * layout
     */
  case ZN_W_LAYOUT:
    {
      if (argc < 4) {
        Tcl_WrongNumArgs(interp, 1, args,
                         "layout operator ?args...? tagOrId ?tagOrId...?");
        goto error;
      }
      if (LayoutItems(wi, argc-2, args+2) == TCL_ERROR) {
        goto error;
      }
    }
    break;
    /*
     * lower
     */
  case ZN_W_LOWER:
    {
      ZnItem      first, group, mark = ZN_NO_ITEM;
      
      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args, "lower tagOrId ?belowThis?");
        goto error;
      }
      if (argc == 4) {
        if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) {
          goto error;
        }
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
          mark = item;
        }
        if (mark == ZN_NO_ITEM) {
          Tcl_AppendResult(interp, "unknown tag or item \"",
                           Tcl_GetString(args[3]), "\"", NULL);
          goto error;
        }
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      item = ZnTagSearchFirst(search_var);
      if ((item == ZN_NO_ITEM) || (item == wi->top_group)) {
        goto done;
      }
      first = item;
      if (mark == ZN_NO_ITEM) {
        mark = ZnGroupTail(item->parent);
      }
      group = mark->parent;
      do {
        if ((item->parent == group) && (item != mark)) {
          ZnITEM.UpdateItemPriority(item, mark, False);
          mark = item;
        }
        item = ZnTagSearchNext(search_var);
      }
      while ((item != ZN_NO_ITEM) && (item != first));
    }
    break;
    /*
     * monitor
     */
  case ZN_W_MONITOR:
    {
#ifndef _WIN32
      ZnBool  on_off;
      
      if ((argc != 2) && (argc != 3)) {
        Tcl_WrongNumArgs(interp, 1, args, "monitor ?onOff?");
        goto error;
      }
      if (argc == 3) {
        if (Tcl_GetBooleanFromObj(interp, args[2], &on_off) != TCL_OK) {
          goto error;
        }
        ASSIGN(wi->flags, ZN_MONITORING, on_off);
        if (on_off == True) {
          ZnResetChronos(wi->total_draw_chrono);
          ZnResetChronos(wi->this_draw_chrono);
        }
      }
      if ((argc == 2) || (on_off == False)) {
        long ttime, ltime;
        int  num_actions;
        ZnGetChrono(wi->total_draw_chrono, &ttime, &num_actions);
        ZnGetChrono(wi->this_draw_chrono, &ltime, NULL);
        l = Tcl_GetObjResult(interp);
        Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(num_actions));
        Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ltime));
        Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime));
        /*Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_w));
        Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(wi->damaged_area_h));
        Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ttime));*/
      }
#endif
    }
    break;
    /*
     * numparts
     */
  case ZN_W_NUMPARTS:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "numparts tagOrId");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
        goto error;
      }
      l = Tcl_NewIntObj((int) item->class->num_parts);
      Tcl_SetObjResult(interp, l);
    }
    break;
    /*
     * postscript
     */
  case ZN_W_POSTSCRIPT:
    {
      if (ZnPostScriptCmd(wi, argc, args) != TCL_OK) {
        goto error;
      }
    }
    break;
    /*
     * raise
     */
  case ZN_W_RAISE:
    {
      ZnItem      group, mark = ZN_NO_ITEM;
      
      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args, "raise tagOrId ?aboveThis?");
        goto error;
      }
      if (argc == 4) {
        /*
         * Find the topmost item with the tag.
         */
        if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) {
          goto error;
        }
        mark = ZnTagSearchFirst(search_var);
        if (mark == ZN_NO_ITEM) {
          Tcl_AppendResult(interp, "unknown tag or item \"",
                           Tcl_GetString(args[3]), "\"", NULL);
          goto error;
        }
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      item = ZnTagSearchFirst(search_var);
      if ((item == ZN_NO_ITEM) || (item == wi->top_group)) {
        goto done;
      }
      if (mark == ZN_NO_ITEM) {
        mark = ZnGroupHead(item->parent);
      }
      group = mark->parent;
      for (; item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        if (item->parent != group) {
          continue;
        }
        if (item != mark) {
          ZnITEM.UpdateItemPriority(item, mark, True);
        }
      }
    }
    break;
    /*
     * remove
     */
  case ZN_W_REMOVE:
    {
      unsigned int num_fields;
      
      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args, "remove tagOrId ?tagOrId ...?");
        goto error;
      }
      argc -= 2;
      args += 2;
      for (i = 0; i < (unsigned int) argc; i++) {
        if (ZnTagSearchScan(wi, args[i], &search_var) == TCL_ERROR) {
          goto error;
        }
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
          if (item == wi->top_group) {
            continue;
          }
          if (wi->binding_table != NULL) {
            Tk_DeleteAllBindings(wi->binding_table, (ClientData) item);
            if (item->class->GetFieldSet) {
              num_fields = ZnFIELD.NumFields(item->class->GetFieldSet(item));
              for (j = 0; j < num_fields; j++) {
                Tk_DeleteAllBindings(wi->binding_table,
                                     (ClientData) EncodeItemPart(item, j));
              }
            }
            for (j = 0; j < item->class->num_parts; j++) {
              Tk_DeleteAllBindings(wi->binding_table,
                                   (ClientData) EncodeItemPart(item, -(int)(j+2)));
            }
          }
          ZnITEM.DestroyItem(item);
        }
      }
    }
    break;
    /*
     * rotate
     */
  case ZN_W_ROTATE:
    {
      ZnBool    deg=False;

      if ((argc < 4) && (argc > 7)) {
        Tcl_WrongNumArgs(interp, 1, args, "rotate tagOrIdOrTransform angle ?degree? ?centerX centerY?");
        goto error;
      }
      
      if (argc > 5) {
        if (Tcl_GetDoubleFromObj(interp, args[argc-2], &d) == TCL_ERROR) {
          goto error;
        }
        p.x = d;
        if (Tcl_GetDoubleFromObj(interp, args[argc-1], &d) == TCL_ERROR) {
          goto error;
        }
        p.y = d;
      }
      if ((argc == 5) || (argc == 7)) {
        if (Tcl_GetBooleanFromObj(interp, args[4], &deg) != TCL_OK) {
          goto error;
        }
        
      }
      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
          goto error;
        }
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
        goto error;
      }

      if (t) {
        if (argc > 5) {
          ZnTranslate(t, -p.x, -p.y, False);
        }
        if (deg) {
          ZnRotateDeg(t, d);
        }
        else {
          ZnRotateRad(t, d);
        }
        if (argc > 5) {
          ZnTranslate(t, p.x, p.y, False);
        }
      }
      else {
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
          ZnITEM.RotateItem(item, d, deg, (argc > 5) ? &p : NULL);
        }
      }
    }
    break;
    /*
     * scale
     */
  case ZN_W_SCALE:
    {
      ZnPoint   scale;
      
      if ((argc != 5) && (argc != 7)) {
        Tcl_WrongNumArgs(interp, 1, args,
                         "scale tagOrIdOrTransform xFactor yFactor ?centerX centerY?");
        goto error;
      }
      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
          goto error;
        }
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
        goto error;
      }
      scale.x = d;
      if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) {
        goto error;
      }
      scale.y = d;
      if (argc == 7) {
        if (Tcl_GetDoubleFromObj(interp, args[5], &d) == TCL_ERROR) {
          goto error;
        }
        p.x = d;
        if (Tcl_GetDoubleFromObj(interp, args[6], &d) == TCL_ERROR) {
          goto error;
        }
        p.y = d;
      }

      if (t) {
        if (argc == 7) {
          ZnTranslate(t, -p.x, -p.y, False);
        }
        ZnScale(t, scale.x, scale.y);
        if (argc == 7) {
          ZnTranslate(t, p.x, p.y, False);
        }
      }
      else {
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
          ZnITEM.ScaleItem(item, scale.x, scale.y, (argc == 7) ? &p : NULL);
        }
      }
    }
    break;
    /*
     * select
     */
  case ZN_W_SELECT:
    {
      ZnTextInfo *ti = &wi->text_info;

      if (argc < 3) {
        Tcl_WrongNumArgs(interp, 1, args, "select option ?tagOrId? ?arg?");
        goto error;
      }
      if (argc >= 4) {
        if (ZnTagSearchScan(wi, args[3], &search_var) == TCL_ERROR) {
          goto error;
        }
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
          if ((item->class->Index != NULL) &&
              (item->class->Selection != NULL)) {
            break;
          }
        }
        if (item == ZN_NO_ITEM) {
          Tcl_AppendResult(interp, "can't find an indexable item \"",
                           Tcl_GetString(args[3]), "\"", NULL);
          goto error;
        }
      }
      if (Tcl_GetIndexFromObj(interp, args[2], sel_cmd_strings,
                              "selection option", 0, &cmd_index) != TCL_OK) {
        goto error;
      }
      if ((argc == 5) || (argc == 6)) {
        if (argc == 6) {
          if (Tcl_GetIntFromObj(interp, args[4], &field) != TCL_OK) {
            field = ZN_NO_PART;
            if (Tcl_GetString(args[4])[0] != 0) {
              Tcl_AppendResult(interp, "invalid field index \"",
                               Tcl_GetString(args[4]),
                               "\", should be a positive integer", NULL);
              goto error;
            }
          }
          argc--;
          args++;
        }
        result = item->class->Index(item, field, args[4], &index);
        if (result != TCL_OK) {
          goto error;
        }
      }
      switch ((enum sel_cmds) cmd_index) {
      case ZN_SEL_ADJUST:
        if (argc != 5) {
          Tcl_WrongNumArgs(interp, 1, args, "select adjust tagOrId ?field? index");
          goto error;
        }
        if ((ti->sel_item == item) && (ti->sel_field == field)) {
          if (index < (ti->sel_first + ti->sel_last)/2) {
            ti->sel_anchor = ti->sel_last+1;
          }
          else {
            ti->sel_anchor = ti->sel_first;
          }
        }
        SelectTo(item, field, index);
        break;
      case ZN_SEL_CLEAR:
        if (argc != 3) {
          Tcl_WrongNumArgs(interp, 1, args, "select clear");
          goto error;
        }
        if (ti->sel_item != ZN_NO_ITEM) {
          ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG);
          ti->sel_item = ZN_NO_ITEM;
          ti->sel_field = ZN_NO_PART;
        }
        break;
      case ZN_SEL_FROM:
        if (argc != 5) {
          Tcl_WrongNumArgs(interp, 1, args, "select from tagOrId ?field? index");
          goto error;
        }
        ti->anchor_item = item;
        ti->anchor_field = field;
        ti->sel_anchor = index;
        break;
      case ZN_SEL_ITEM:
        if (argc != 3) {
          Tcl_WrongNumArgs(interp, 1, args, "select item");
          goto error;
        }
        if (ti->sel_item != ZN_NO_ITEM) {
          l = Tcl_GetObjResult(interp);
          Tcl_ListObjAppendElement(interp, l, Tcl_NewLongObj(ti->sel_item->id));
          if (ti->sel_field != ZN_NO_PART) {
            Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(ti->sel_field));
          }
          else {
            Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj("", -1));
          }
        }
        break;
      case ZN_SEL_TO:
        if (argc != 5) {
          Tcl_WrongNumArgs(interp, 1, args, "select to tagOrId ?field? index");
          goto error;
        }
        SelectTo(item, field, index);
        break;
      }
    }
    break;
    /*
     * Skew
     */
  case ZN_W_SKEW:
    {
      double   x_skew, y_skew;
      
      if (argc != 5) {
        Tcl_WrongNumArgs(interp, 1, args, "skew tagOrIdOrTransform xSkewAngle ySkewAngle");
        goto error;
      }
      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
          goto error;
        }
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &x_skew) == TCL_ERROR) {
        goto error;
      }
      if (Tcl_GetDoubleFromObj(interp, args[4], &y_skew) == TCL_ERROR) {
        goto error;
      }
      
      if (t) {
        ZnSkewRad(t, x_skew, y_skew);
      }
      else {
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
          ZnITEM.SkewItem(item, x_skew, y_skew);
        }
      }
    }
    break;
    /*
     * smooth
     */
  case ZN_W_SMOOTH:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "smooth coordList");
        goto error;
      }
      if (ZnParseCoordList(wi, args[2], &points,
                           NULL, &num_points, NULL) == TCL_ERROR) {
        return TCL_ERROR;
      }
      to_points = ZnListNew(32, sizeof(ZnPoint));
      ZnSmoothPathWithBezier(points, num_points, to_points);
      points = (ZnPoint *) ZnListArray(to_points);
      num_points = ZnListSize(to_points);
      l = Tcl_GetObjResult(interp);
      for (i = 0; i < num_points; i++, points++) {
        entries[0] = Tcl_NewDoubleObj(points->x);
        entries[1] = Tcl_NewDoubleObj(points->y);
        Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries));
      }
      ZnListFree(to_points);
    }
    break;
    /*
     * tapply
     */
  case ZN_W_TAPPLY:
    {
      Tcl_AppendResult(interp, "Command not yet implemented", NULL);
      goto error;
    }
    break;
    /*
     * tcompose
     */
  case ZN_W_TCOMPOSE:
    {
      ZnTransfo *to;
      ZnBool    invert=False;
      ZnTransfo res_t, inv_t;

      if ((argc != 4) && (argc != 5)) {
        Tcl_WrongNumArgs(interp, 1, args, "tcompose transformTo aTransform ?invert?");
        goto error;
      }
      if (argc == 5) {
        if (Tcl_GetBooleanFromObj(interp, args[4], &invert) != TCL_OK) {
          goto error;
        }
        argc--;
      }
      
      str = Tcl_GetString(args[3]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
        item = NULL;
      }
      else {
        result = ZnItemWithTagOrId(wi, args[3], &item, &search_var);
        if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
          Tcl_ResetResult(interp);
          Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]),
                           "\" must be either a tag, ",
                           "an id or a transform name", (char *) NULL);
          goto error;
        }
        t = item->transfo;
      }

      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        to = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
        if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
          Tcl_ResetResult(interp);
          Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
                           "\" must be either a tag, ",
                           "an id or a transform name", (char *) NULL);
          goto error;
        }
        to = item->transfo;
      }

      if (invert) {
        ZnTransfoInvert(t, &inv_t);
        ZnTransfoCompose(&res_t, to, &inv_t);
      }
      else {
        ZnTransfoCompose(&res_t, to, t);
      }

      if (item != ZN_NO_ITEM) {
        /* Set back the transform in the item */
        ZnITEM.SetTransfo(item, &res_t);
      }
      else {
        ZnTransfoFree(to);
        Tcl_SetHashValue(entry, ZnTransfoDuplicate(&res_t));
      }

      break;
    }
    /*
     * tdelete
     */
  case ZN_W_TDELETE:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "tdelete tName");
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
      if (entry == NULL) {
        Tcl_AppendResult(interp, "\"", Tcl_GetString(args[2]),
                         "\" must be a transform name", (char *) NULL);
        goto error;
      }
      t = (ZnTransfo *) Tcl_GetHashValue(entry);
      ZnTransfoFree(t);
      Tcl_DeleteHashEntry(entry);
    }
    break;
    /*
     * tget
     */
  case ZN_W_TGET:
    {
      ZnPoint   scale, trans;
      ZnReal    rotation, skewxy;
      ZnBool    raw=1, get_trans=0, get_rot=0;
      ZnBool    get_scale=0, get_skew=0;
      ZnTransfo tid;

      if ((argc != 3) && (argc != 4)) {
      err_tget:
        Tcl_WrongNumArgs(interp, 1, args, "tget transform ?all|translation|scale|rotation|skew?");
        goto error;
      }
      if (argc == 4) {
        raw = 0;
        str = Tcl_GetString(args[3]);
        length = strlen(str);
        if (strncmp(str, "all", length) == 0) {
          get_scale = get_rot = get_trans = get_skew = 1;
        }
        else if (strncmp(str, "translation", length) == 0) {
          get_trans = 1;
        }
        else if (strncmp(str, "scale", length) == 0) {
          get_scale = 1;
        }
        else if (strncmp(str, "rotation", length) == 0) {
          get_rot = 1;
        }
        else if (strncmp(str, "skew", length) == 0) {
          get_skew = 1;
        }
        else {
          goto err_tget;
        }
      }
      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
        if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
          Tcl_ResetResult(interp);
          Tcl_AppendResult(interp, "\"", Tcl_GetString(args[3]),
                           "\" must be either a tag, ",
                           "an id or a transform name", (char *) NULL);
          goto error;
        }
        t = item->transfo;
      }
      l = Tcl_GetObjResult(interp);
      if (raw) {
        if (!t) {
          ZnTransfoSetIdentity(&tid);
          t = &tid;
        }
        for (i = 0; i < 6; i++) {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(t->_[i/2][i%2]));
        }
      }
      else {
        ZnTransfoDecompose(t, get_scale?&scale:NULL, get_trans?&trans:NULL,
                           get_rot?&rotation:NULL, get_skew?&skewxy:NULL);
        if (get_trans) {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(trans.x));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(trans.y));
        }
        if (get_scale) {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(scale.x));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(scale.y));
        }
        if (get_rot) {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(rotation));
        }
        if (get_skew) {
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(skewxy));
        }
      }
      break;
    }
    /*
     * transform
     */
  case ZN_W_TRANSFORM:
    {
      char      *controls, *tag;
      ZnPoint   *p, xp;
      ZnTransfo *from_t=NULL, *to_t=NULL, *result_t;
      ZnTransfo t1, t2, t3;
      ZnBool    old_format;

      if ((argc != 4) && (argc != 5)) {
        Tcl_WrongNumArgs(interp, 1, args, "transform ?tagOrIdFrom? tagOrIdTo coordlist");
        goto error;
      }
      
      if (argc == 5) {
        /*
         * Setup the source transform.
         */
        tag = Tcl_GetString(args[2]);
        if (strlen(tag) == 0) {
          Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
          goto error;
        }
        if (strcmp(tag, "device") == 0) {
          from_t = &t1;
          ZnTransfoSetIdentity(from_t);
        }
        else {
          entry = Tcl_FindHashEntry(wi->t_table, tag);
          if (entry != NULL) {
            /* from is a named transform */
            from_t = (ZnTransfo *) Tcl_GetHashValue(entry);
          }
          else {
            result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
            if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
              Tcl_ResetResult(interp);
              Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-2]),
                               "\" must be either identity or a tag or ",
                               "an id or a transform name", (char *) NULL);
              goto error;
            }
            ZnITEM.GetItemTransform(item, &t1);
            from_t = &t1;
          }
        }
      }
      /*
       * Setup the destination transform
       */
      tag = Tcl_GetString(args[argc-2]);
      if (strlen(tag) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      if (strcmp(tag, "device") == 0) {
        to_t = &t2;
        ZnTransfoSetIdentity(to_t);
      }
      else {
        entry = Tcl_FindHashEntry(wi->t_table, tag);
        if (entry != NULL) {
          /* to is a named transform */
          to_t = (ZnTransfo *) Tcl_GetHashValue(entry);
        }
        else {
          result = ZnItemWithTagOrId(wi, args[argc-2], &item, &search_var);
          if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
            Tcl_ResetResult(interp);
            Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-2]),
                             "\" must be either identity a tag or ",
                             "an id or a transform name", (char *) NULL);
            goto error;
          }
          ZnITEM.GetItemTransform(item, &t2);
          to_t = &t2;
        }
      }
      ZnTransfoInvert(to_t, &t3);
      to_t = &t3;
      result_t = to_t;

      if (argc == 5) {
        ZnTransfoCompose(&t2, from_t, to_t);
        result_t = &t2;
      }
      /*ZnPrintTransfo(&t);
        ZnPrintTransfo(&inv);*/
      
      if (ZnParseCoordList(wi, args[argc-1], &p,
                           &controls, &num_points, &old_format) == TCL_ERROR) {
        Tcl_AppendResult(interp, " invalid coord list \"",
                         Tcl_GetString(args[argc-1]), "\"", NULL);
        goto error;
      }
      l = Tcl_GetObjResult(interp);
      if (old_format) {
        for (i = 0; i < num_points; i++, p++) {
          ZnTransformPoint(result_t, p, &xp);
          /*printf("p->x=%g, p->y=%g, xp.x=%g, xp.y=%g\n", p->x, p->y, xp.x, xp.y);*/
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(xp.x));
          Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(xp.y));
          /* The next case only applies for a one point
           * list with a control flag.
           */
          if (controls && controls[i]) {
            c[0] = controls[i];
            Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(c, -1));
          }
        }
      }
      else {
        for (i = 0; i < num_points; i++, p++) {
          ZnTransformPoint(result_t, p, &xp);
          /*printf("p->x=%g, p->y=%g, xp.x=%g, xp.y=%g\n", p->x, p->y, xp.x, xp.y);*/
          entries[0] = Tcl_NewDoubleObj(xp.x);
          entries[1] = Tcl_NewDoubleObj(xp.y);
          if (controls && controls[i]) {
            c[0] = controls[i];
            entries[2] = Tcl_NewStringObj(c, -1);
            Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(3, entries));
          }
          else {
            Tcl_ListObjAppendElement(interp, l, Tcl_NewListObj(2, entries));
          }
        }
      }
    }
    break;
    /*
     * translate
     */
  case ZN_W_TRANSLATE:
    {
      ZnBool abs = False;

      if ((argc != 5) && (argc != 6)) {
        Tcl_WrongNumArgs(interp, 1, args, "translate tagOrIdOrTransform xAmount yAmount ?abs?");
        goto error;
      }
      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
          goto error;
        }
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
        goto error;
      }
      p.x = d;
      if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) {
        goto error;
      }
      p.y = d;
      if (argc == 6) {
        if (Tcl_GetBooleanFromObj(interp, args[5], &abs) == TCL_ERROR) {
          goto error;
        }
      }

      if (t) {
        ZnTranslate(t, p.x, p.y, abs);
      }
      else {
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item =ZnTagSearchNext(search_var)) {
          ZnITEM.TranslateItem(item, p.x, p.y, abs);
        }
      }
    }
    break;
    /*
     * treset
     */
  case ZN_W_TRESET:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "treset tagOrIdOrTransform");
        goto error;
      }
      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
          goto error;
        }
      }

      if (t) {
        ZnTransfoSetIdentity(t);
      }
      else {
        for (item = ZnTagSearchFirst(search_var);
             item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
          ZnITEM.ResetTransfo(item);
        }
      }
    }
    break;
    /*
     * trestore
     */
  case ZN_W_TRESTORE:
    {
      if (argc != 4) {
        Tcl_WrongNumArgs(interp, 1, args, "trestore tagOrId tName");
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[argc-1]));
      if (entry == NULL) {
        Tcl_AppendResult(interp, "\"", Tcl_GetString(args[argc-1]),
                         "\" must be a transform name", (char *) NULL);
        goto error;
      }
      t = (ZnTransfo *) Tcl_GetHashValue(entry);
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        ZnITEM.SetTransfo(item, t);
      }
    }
    break;
    /*
     * tsave
     */
  case ZN_W_TSAVE:
    {
      int       is_ident, new, invert=0;
      ZnTransfo *inv, ident;
      char      *from;

      if ((argc != 3) && (argc != 4) && (argc != 5)) {
        Tcl_WrongNumArgs(interp, 1, args, "tsave ?tagOrIdOrTransform? tName ?invert?");
        goto error;
      }
      if (argc == 3) {
        entry = Tcl_FindHashEntry(wi->t_table, Tcl_GetString(args[2]));
        l = Tcl_NewBooleanObj(entry != NULL);
        Tcl_SetObjResult(interp, l);
        goto done;
      }
      from = Tcl_GetString(args[2]);
      is_ident = strcmp(from, "identity") == 0;
      if (is_ident) {
        t = &ident;
        ZnTransfoSetIdentity(t);
      }
      else {
        entry = Tcl_FindHashEntry(wi->t_table, from);
        if (entry != NULL) {
          t = (ZnTransfo *) Tcl_GetHashValue(entry);
        }
        else {
          result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
          if ((result == TCL_ERROR) || (item == ZN_NO_ITEM)) {
            goto error;
          }
          t = item->transfo;
        }
      }
      if (argc == 5) {
        if (Tcl_GetBooleanFromObj(interp, args[4], &invert) != TCL_OK) {
          goto error;
        }
        argc--;
      }
      entry = Tcl_CreateHashEntry(wi->t_table, Tcl_GetString(args[argc-1]), &new);
      if (!new) {
        ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(entry));
      }
      if (invert && !is_ident) {
        inv = ZnTransfoNew();
        ZnTransfoInvert(t, inv);
        Tcl_SetHashValue(entry, inv);
      }
      else {
        Tcl_SetHashValue(entry, ZnTransfoDuplicate(t));
      }
    }
    break;
    /*
     * tset
     */
  case ZN_W_TSET:
    {
      ZnTransfo     new;

      if (argc != 9) {
        Tcl_WrongNumArgs(interp, 1, args,
                         "tset tagOrIdorTransform m00 m01 m10 m11 m20 m21");
        goto error;
      }
      
      for (i = 0; i < 6; i++) {
        if (Tcl_GetDoubleFromObj(interp, args[3+i], &d) == TCL_ERROR) {
          goto error;
        }
        new._[i/2][i%2] = (float) d;
      }
      str = Tcl_GetString(args[2]);
      if (strlen(str) == 0) {
        Tcl_AppendResult(interp, " must provide a valid tagOrIdOrTransform", NULL);
        goto error;
      }
      entry = Tcl_FindHashEntry(wi->t_table, str);
      if (entry != NULL) {
        t = (ZnTransfo *) Tcl_GetHashValue(entry);
      }
      else {
        if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
          goto error;
        }

        if (t) {
          *t = new;
        }
        else {
          for (item = ZnTagSearchFirst(search_var);
               item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
            ZnITEM.SetTransfo(item, &new);
          }
        }
      }
      break;
    }
    /*
     * type
     */
  case ZN_W_TYPE:
    {
      if (argc != 3) {
        Tcl_WrongNumArgs(interp, 1, args, "type tagOrId");
        goto error;
      }
      result = ZnItemWithTagOrId(wi, args[2], &item, &search_var);
      if (result == TCL_ERROR) {
        goto error;
      }
      if (item != ZN_NO_ITEM) {
        l = Tcl_NewStringObj(item->class->name, -1);
        Tcl_SetObjResult(interp, l);      
      }
    }
    break;
    /*
     * vertexat
     */
  case ZN_W_VERTEX_AT:
    {
      int contour, vertex, o_vertex;
      
      if (argc != 5) {
        Tcl_WrongNumArgs(interp, 1, args, " vertexat tagOrId x y");
        goto error;
      }
      if (ZnTagSearchScan(wi, args[2], &search_var) == TCL_ERROR) {
        goto error;
      }
      for (item = ZnTagSearchFirst(search_var);
           item != ZN_NO_ITEM; item = ZnTagSearchNext(search_var)) {
        if (item->class->PickVertex != NULL) {
          break;
        }
      }
      if (item == ZN_NO_ITEM) {
        Tcl_AppendResult(interp, "can't find a suitable item \"",
                         Tcl_GetString(args[2]), "\"", NULL);
        goto error;
      }
      if (Tcl_GetDoubleFromObj(interp, args[3], &d) == TCL_ERROR) {
        goto error;
      }
      p.x = d;
      if (Tcl_GetDoubleFromObj(interp, args[4], &d) == TCL_ERROR) {
        goto error;
      }
      p.y = d;
      item->class->PickVertex(item, &p, &contour, &vertex, &o_vertex);
      l = Tcl_GetObjResult(interp);
      Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(contour));
      Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(vertex));
      Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(o_vertex));
      break;
    }

    /* xview */
  case ZN_W_XVIEW:
    {
      int       count, type;
      ZnReal    new_x=0.0, fraction;
      
      if (argc == 2) {
#ifdef PTK
        ZnReal  first, last;
        ScrollFractions(wi->origin.x, wi->origin.x + Tk_Width(wi->win),
                        wi->scroll_xo, wi->scroll_xc, &first, &last);
        Tcl_DoubleResults(interp, 2, 0, first, last);
#else
        Tcl_SetObjResult(interp,
                         ScrollFractions(wi->origin.x, wi->origin.x + Tk_Width(wi->win),
                                         wi->scroll_xo, wi->scroll_xc));
#endif
      }
      else {
        type = Tk_GetScrollInfoObj(interp, argc, args, &fraction, &count);
        switch (type) {
        case TK_SCROLL_ERROR:
          result = TCL_ERROR;
          goto done;
        case TK_SCROLL_MOVETO:
          new_x = (wi->scroll_xo + (int) (fraction * (wi->scroll_xc - wi->scroll_xo) + 0.5));
          break;
        case TK_SCROLL_PAGES:
          new_x = (int) (wi->origin.x + count * 0.9 * Tk_Width(wi->win));
          break;
        case TK_SCROLL_UNITS:
          if (wi->x_scroll_incr > 0) {
            new_x = wi->origin.x + count * wi->x_scroll_incr;
          }
          else {
            new_x = (int) (wi->origin.x + count * 0.1 * Tk_Width(wi->win));
          }
          break;
        }
        ZnSetOrigin(wi, new_x, wi->origin.y);
      }
      break;
    }
    
    /*yview */
  case ZN_W_YVIEW:
    {
      int       count, type;
      ZnReal    new_y = 0.0, fraction;

      if (argc == 2) {
#ifdef PTK
        ZnReal  first, last;
        ScrollFractions(wi->origin.y, wi->origin.y + Tk_Height(wi->win),
                        wi->scroll_yo, wi->scroll_yc, &first, &last);
        Tcl_DoubleResults(interp, 2, 0, first, last);
#else
        Tcl_SetObjResult(interp,
                         ScrollFractions(wi->origin.y, wi->origin.y + Tk_Height(wi->win),
                                         wi->scroll_yo, wi->scroll_yc));
#endif
      }
      else {
        type = Tk_GetScrollInfoObj(interp, argc, args, &fraction, &count);
        switch (type) {
        case TK_SCROLL_ERROR:
          result = TCL_ERROR;
          goto done;
        case TK_SCROLL_MOVETO:
          new_y = (wi->scroll_yo + (int) (fraction * (wi->scroll_yc - wi->scroll_yo) + 0.5));
          break;
        case TK_SCROLL_PAGES:
          new_y = (int) (wi->origin.y + count * 0.9 * Tk_Height(wi->win));
          break;
        case TK_SCROLL_UNITS:
          if (wi->y_scroll_incr > 0) {
            new_y = wi->origin.y + count * wi->y_scroll_incr;
          }
          else {
            new_y = (int) (wi->origin.y + count * 0.1 * Tk_Height(wi->win));
          }
          break;
        }
        ZnSetOrigin(wi, wi->origin.x, new_y);
      }
      break;
    }
  }
  
 done:
  ZnTagSearchDestroy(search_var);
  Tcl_Release((ClientData) wi);
  return result;
  
 error:
  result = TCL_ERROR;
  goto done;
}


/*
 *----------------------------------------------------------------------
 *
 * Configure --
 *
 *      This procedure is called to process an args/argc list in
 *      conjunction with the Tk option database to configure (or
 *      reconfigure) a Zinc widget.
 *
 * Results:
 *      The return value is a standard Tcl result.  If TCL_ERROR is
 *      returned, then interp->result contains an error message.
 *
 * Side effects:
 *      Configuration information, such as colors, border width,
 *      etc. get set for the widget;  old resources get freed,
 *      if there were any.
 *
 *----------------------------------------------------------------------
 */
#ifdef PTK_800
static int
Configure(Tcl_Interp            *interp,/* Used for error reporting. */
          ZnWInfo               *wi,    /* Information about widget. */
          int                   argc,   /* Number of valid entries in args. */
          Tcl_Obj       *CONST  args[], /* Arguments. */
          int                   flags)  /* Flags to pass to Tk_ConfigureWidget. */
{
#define CONFIG_PROBE(offset) (ISSET(config_specs[offset].specFlags, \
                                    TK_CONFIG_OPTION_SPECIFIED))
  ZnBool  init;
  int     render;

  init = wi->fore_color == NULL;
  render = wi->render;
  if (Tk_ConfigureWidget(interp, wi->win, config_specs, argc,
#ifdef PTK
                         (Tcl_Obj **) args, (char *) wi, flags) != TCL_OK)
#else
                         (CONST char **) args, (char *) wi, flags|TK_CONFIG_OBJS) != TCL_OK)
#endif
  {
    return TCL_ERROR;
  }
  if (!init) {
    if (wi->render != render) {
      ZnWarning("It is not possible to change the -render option after widget creation.\n");
    }
    wi->render = render;
  }
  /*
   * Reset the render mode if GL is not available. It'll be too late
   * to do this after images or fonts have been allocated.
   */
  if ((wi->render != 0) && ISCLEAR(wi->flags, ZN_HAS_GL)) {
    fprintf(stderr, "GLX not available (need at least a 24 bits buffer with stencil)\n");
    wi->render = 0;
  }

#ifdef GL
  if (CONFIG_PROBE(FONT_SPEC) || !wi->font_tfi) {
    if (wi->font_tfi) {
      ZnFreeTexFont(wi->font_tfi);
    }
    wi->font_tfi = ZnGetTexFont(wi, wi->font);
  }
#ifdef ATC
  if (CONFIG_PROBE(MAP_TEXT_FONT_SPEC) || !wi->map_font_tfi) {
    if (wi->map_font_tfi) {
      ZnFreeTexFont(wi->map_font_tfi);
    }
    wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font);
  }
#endif
#endif

#if defined(GL) && defined(ROTATION)
  //
  // No rotation correction if no GL rendering
  if (CONFIG_PROBE(SCREEN_ROTATION_SPEC) || CONFIG_PROBE(ENABLE_ROTATION_SPEC)) {
    if (!wi->render) {
      wi->screen_rotation = 0;
      wi->enable_rotation = 0;
    }
    else {
      SET(wi->flags, ZN_UPDATE_CANVASTEX);
      ZnNeedRedisplay(wi);
    }
  }
#endif

  /*
   * Maintain the pick aperture within meaningful bounds.
   */
  if (wi->pick_aperture < 0) {
    wi->pick_aperture = 0;
  }
  if (CONFIG_PROBE(BACK_COLOR_SPEC) || !wi->relief_grad) {
    XColor         *color;
    unsigned short alpha;

    Tk_SetWindowBackground(wi->win, ZnGetGradientPixel(wi->back_color, 0.0));
    if (wi->relief_grad) {
      ZnFreeGradient(wi->relief_grad);
      wi->relief_grad = NULL;
    }
    if (wi->relief != ZN_RELIEF_FLAT) {
      color = ZnGetGradientColor(wi->back_color, 0.0, &alpha);
      wi->relief_grad = ZnGetReliefGradient(interp, wi->win,
                                            Tk_NameOfColor(color), alpha);
    }
  }
  if (CONFIG_PROBE(BACK_COLOR_SPEC) || CONFIG_PROBE(LIGHT_ANGLE_SPEC)) {
    ZnDamageAll(wi);
  }
  if (CONFIG_PROBE(RELIEF_SPEC)) {
    ZnNeedRedisplay(wi);
  }
  
  wi->inset = wi->border_width + wi->highlight_width;
  if (CONFIG_PROBE(BORDER_WIDTH_SPEC) ||
      CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC)) {
    ZnDamageAll(wi);
  }
#ifdef ATC
  if (CONFIG_PROBE(SPEED_VECTOR_LENGTH_SPEC) ||
      CONFIG_PROBE(VISIBLE_HISTORY_SIZE_SPEC) ||
      CONFIG_PROBE(MANAGED_HISTORY_SIZE_SPEC)) {
    ZnITEM.InvalidateItems(wi->top_group, ZnTrack);
  }
  if (CONFIG_PROBE(MAP_DISTANCE_SYMBOL_SPEC)) {
    ZnITEM.InvalidateItems(wi->top_group, ZnMap);
  }
  if (CONFIG_PROBE(TRACK_SYMBOL_SPEC)) {
    ZnITEM.InvalidateItems(wi->top_group, ZnTrack);
    ZnITEM.InvalidateItems(wi->top_group, ZnWayPoint);
  }
#endif
        
  /*
   * Request the new geometry.
   */
  if (CONFIG_PROBE(WIDTH_SPEC) || CONFIG_PROBE(HEIGHT_SPEC) ||
      CONFIG_PROBE(BORDER_WIDTH_SPEC) ||
      CONFIG_PROBE(HIGHLIGHT_THICKNESS_SPEC) || ISCLEAR(wi->flags, ZN_REALIZED)) {
    Tk_GeometryRequest(wi->win, wi->opt_width, wi->opt_height);
  }

  if (CONFIG_PROBE(TILE_SPEC)) {
    ZnDamageAll(wi);
  }
  
  /*
   * Update the registration with the overlap manager.
   */
#ifdef ATC
  if (CONFIG_PROBE(OVERLAP_MANAGER_SPEC)) {
    Tcl_HashEntry       *entry;
    ZnItem              grp;

    if (wi->om_group != ZN_NO_ITEM) {
      OmUnregister((void *) wi);
      wi->om_group = ZN_NO_ITEM;
    }
    if (wi->om_group_id != 0) {
      entry = Tcl_FindHashEntry(wi->id_table, (char *) wi->om_group_id);
      if (entry != NULL) {
        grp = (ZnItem) Tcl_GetHashValue(entry);
        if (grp->class == ZnGroup) {
          OmRegister((void *) wi, ZnSendTrackToOm, ZnSetLabelAngleFromOm, ZnQueryLabelPosition);
          wi->om_group = grp;
        }
      }
    }
  }
#endif

  if (CONFIG_PROBE(INSERT_WIDTH_SPEC) && wi->focus_item) {
    ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
  }
  /*
   * Update the blinking cursor timing if on/off time has changed.
   */
  if (ISSET(wi->flags, ZN_GOT_FOCUS) &&
      (CONFIG_PROBE(INSERT_ON_TIME_SPEC) ||
       CONFIG_PROBE(INSERT_OFF_TIME_SPEC))) {
    Focus(wi, True);
  }

  if (CONFIG_PROBE(SCROLL_REGION_SPEC)) {
    /*
     * Compute the scroll region
     */
    wi->scroll_xo = wi->scroll_yo = 0;
    wi->scroll_xc = wi->scroll_yc = 0;
    if (wi->region != NULL) {
      int        argc2;
#ifdef PTK
      Arg       *args2;
#else
      CONST char **args2;
#endif

#ifdef PTK
      if (Tcl_ListObjGetElements(interp, wi->region, &argc2, &args2) != TCL_OK)
#else
      if (Tcl_SplitList(interp, wi->region, &argc2, &args2) != TCL_OK)
#endif
      {
        return TCL_ERROR;
      }
      if (argc2 != 4) {
        Tcl_AppendResult(interp, "bad scrollRegion \"", wi->region, "\"", (char *) NULL);
      badRegion:
#ifndef PTK
        ZnFree(wi->region);
        ZnFree(args2);
#endif
        wi->region = NULL;
        return TCL_ERROR;
      }
#ifdef PTK
      if ((Tk_GetPixels(interp, wi->win, LangString(args2[0]), &wi->scroll_xo) != TCL_OK) ||
          (Tk_GetPixels(interp, wi->win, LangString(args2[1]), &wi->scroll_yo) != TCL_OK) ||
          (Tk_GetPixels(interp, wi->win, LangString(args2[2]), &wi->scroll_xc) != TCL_OK) ||
          (Tk_GetPixels(interp, wi->win, LangString(args2[3]), &wi->scroll_yc) != TCL_OK))
#else
      if ((Tk_GetPixels(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) ||
          (Tk_GetPixels(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) ||
          (Tk_GetPixels(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) ||
          (Tk_GetPixels(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK))
#endif
      {
        goto badRegion;
      }
    }
  }

  if (CONFIG_PROBE(SCROLL_REGION_SPEC) ||
      CONFIG_PROBE(CONFINE_SPEC)) {
    ZnSetOrigin(wi, wi->origin.x, wi->origin.y);
    SET(wi->flags, ZN_UPDATE_SCROLLBARS);
  }
  
  if (CONFIG_PROBE(FOLLOW_POINTER_SPEC)) {
    if (wi->follow_pointer) {
      /* Flag has just been turned on, process
       * the last known positional event to update
       * the item under pointer.
       */
      if (wi->pick_event.type == ButtonPress ||
          wi->pick_event.type == ButtonRelease ||
          wi->pick_event.type == MotionNotify ||
          wi->pick_event.type == EnterNotify ||
          wi->pick_event.type == LeaveNotify) {
        Tcl_Preserve((ClientData) wi);
        CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK);
        PickCurrentItem(wi, &wi->pick_event);
        Tcl_Release((ClientData) wi);
      }
    }
  }
  
  return TCL_OK;
}
#else /* PTK_800 */
static void
TileUpdate(void *client_data)
{
  ZnWInfo *wi = (ZnWInfo*) client_data;

  ZnDamageAll(wi);
}

static int
Configure(Tcl_Interp            *interp,/* Used for error reporting. */
          ZnWInfo               *wi,    /* Information about widget. */
          int                   argc,   /* Number of valid entries in args. */
          Tcl_Obj       *CONST  args[]) /* Arguments. */
{
  ZnBool                init;
  int                   render, mask, error;
  Tk_SavedOptions       saved_options;
  Tcl_Obj               *error_result = NULL;

  render = wi->render;
  init = render < 0;

  for (error = 0; error <= 1; error++) {
    if (!error) {
      if (Tk_SetOptions(interp, (char *) wi, wi->opt_table, argc, args,
                        wi->win, &saved_options, &mask) != TCL_OK) {
        continue;
      }
    }
    else {
      /* Save the error value for later report */
      error_result = Tcl_GetObjResult(interp);
      Tcl_IncrRefCount(error_result);
      Tk_RestoreSavedOptions(&saved_options);
    }

    if (!init) {
      if (render != wi->render) {
        ZnWarning("It is not possible to change the -render option after widget creation.\n");
        wi->render = render;
      }
    }
    else if (wi->render < 0) {
      wi->render = 0;
    }
    /*
     * Reset the render mode if GL is not available. It'll be too late
     * to do this after images or fonts have been allocated.
     */
    else if ((wi->render != 0) && ISCLEAR(wi->flags, ZN_HAS_GL)) {
      fprintf(stderr, "GLX not available (need at least a 24 bits buffer with stencil)\n");
      wi->render = 0;
    }

#if defined(GL) && defined(ROTATION)
    if ((mask & CONFIG_ROTATION) || (mask & CONFIG_ENABLE_ROTATION) || init) {
      if (!wi->render) {
        wi->screen_rotation = 0;
        wi->enable_rotation = 0;
      }
      else {
        SET(wi->flags, ZN_UPDATE_CANVASTEX);
        ZnNeedRedisplay(wi);
      }
    }
#endif

    if ((mask & CONFIG_SCROLL_REGION) || init) {
      /*
       * Compute the scroll region
       */
      wi->scroll_xo = wi->scroll_yo = 0;
      wi->scroll_xc = wi->scroll_yc = 0;
      if (wi->region != NULL) {
        int      argc2;
        Tcl_Obj **args2;
        
        if (Tcl_ListObjGetElements(interp, wi->region, &argc2, &args2) != TCL_OK) {
        badRegion:
          Tcl_AppendResult(interp, "bad scrollRegion \"",
                           Tcl_GetString(wi->region), "\"", (char *) NULL);
          continue;
        }
        if (argc2 != 4) {
          goto badRegion;
        }
        if ((Tk_GetPixelsFromObj(interp, wi->win, args2[0], &wi->scroll_xo) != TCL_OK) ||
            (Tk_GetPixelsFromObj(interp, wi->win, args2[1], &wi->scroll_yo) != TCL_OK) ||
            (Tk_GetPixelsFromObj(interp, wi->win, args2[2], &wi->scroll_xc) != TCL_OK) ||
            (Tk_GetPixelsFromObj(interp, wi->win, args2[3], &wi->scroll_yc) != TCL_OK)) {
          goto badRegion;
        }
      }
    }
    
    if ((mask & CONFIG_SET_ORIGIN) || init) {
      ZnSetOrigin(wi, wi->origin.x, wi->origin.y);
      SET(wi->flags, ZN_UPDATE_SCROLLBARS);
    }
    
#ifdef GL
    if ((mask & CONFIG_FONT) || !wi->font_tfi) {
      if (wi->font_tfi) {
        ZnFreeTexFont(wi->font_tfi);
      }
      wi->font_tfi = ZnGetTexFont(wi, wi->font);
    }
#ifdef ATC
    if ((mask & CONFIG_MAP_FONT) || !wi->map_font_tfi) {
      if (wi->map_font_tfi) {
        ZnFreeTexFont(wi->map_font_tfi);
      }
      wi->map_font_tfi = ZnGetTexFont(wi, wi->map_text_font);
    }
#endif
#endif

    if ((mask & CONFIG_TILE) || init) {
      char *tile_name;
      if (wi->tile) {
        ZnFreeImage(wi->tile, TileUpdate, wi);
      }
      if (!wi->tile_obj || !*(tile_name = Tcl_GetString(wi->tile_obj))) {
        wi->tile = ZnUnspecifiedImage;
      }
      else {
        wi->tile = ZnGetImage(wi, tile_name, TileUpdate, wi);
        if (wi->tile == ZnUnspecifiedImage) {
          Tcl_AppendResult(interp, "Incorrect tile \"", tile_name, "\"", (char *) NULL);
          continue;
        }
      }
    }

#ifdef ATC
    if ((mask & CONFIG_MAP_SYMBOL) || init) {
      if (wi->map_distance_symbol) {
        ZnFreeImage(wi->map_distance_symbol, NULL, NULL);
      }
      wi->map_distance_symbol = ZnGetImage(wi, Tcl_GetString(wi->map_symbol_obj), NULL, NULL);
      if ((wi->map_distance_symbol == ZnUnspecifiedImage) ||
          ! ZnImageIsBitmap(wi->map_distance_symbol)) {
        Tcl_AppendResult(interp, "Incorrect bitmap \"",
                         Tcl_GetString(wi->map_symbol_obj), "\"", (char *) NULL);
        continue;
      }
    }
    
    if ((mask & CONFIG_TRACK_SYMBOL) || init) {
      if (wi->track_symbol) {
        ZnFreeImage(wi->track_symbol, NULL, NULL);
      }
      wi->track_symbol = ZnGetImage(wi, Tcl_GetString(wi->track_symbol_obj), NULL, NULL);
      if ((wi->track_symbol == ZnUnspecifiedImage) ||
          ! ZnImageIsBitmap(wi->track_symbol)) {
        Tcl_AppendResult(interp, "Incorrect bitmap \"",
                         Tcl_GetString(wi->track_symbol_obj), "\"", (char *) NULL);
        continue;
 
      }
    }
#endif

    /*
     * Maintain the pick aperture within meaningful bounds.
     */
    if (wi->pick_aperture < 0) {
      wi->pick_aperture = 0;
    }

    if ((mask & CONFIG_BACK_COLOR) || !wi->relief_grad) {
      XColor       *color;
      unsigned short alpha;
      
      Tk_SetWindowBackground(wi->win, ZnGetGradientPixel(wi->back_color, 0.0));
      if (wi->relief_grad) {
        ZnFreeGradient(wi->relief_grad);
        wi->relief_grad = NULL;
      }
      if (wi->relief != ZN_RELIEF_FLAT) {
        color = ZnGetGradientColor(wi->back_color, 0.0, &alpha);
        wi->relief_grad = ZnGetReliefGradient(interp, wi->win,
                                              Tk_NameOfColor(color), alpha);
      }
    }
    if (mask & CONFIG_DAMAGE_ALL) {
      ZnDamageAll(wi);
    }
    if ((mask & CONFIG_REDISPLAY) || init) {
      ZnNeedRedisplay(wi);
    }
    
    wi->inset = wi->border_width + wi->highlight_width;
    
#ifdef ATC
    if (mask & CONFIG_INVALIDATE_TRACKS) {
      ZnITEM.InvalidateItems(wi->top_group, ZnTrack);
    }
    if (mask & CONFIG_INVALIDATE_MAPS) {
      ZnITEM.InvalidateItems(wi->top_group, ZnMap);
    }
    if (mask & CONFIG_INVALIDATE_WPS) {
      ZnITEM.InvalidateItems(wi->top_group, ZnWayPoint);
    }
#endif
                
    /*
     * Request the new geometry.
     */
    if ((mask & CONFIG_REQUEST_GEOM) || init) {
      Tk_GeometryRequest(wi->win, wi->opt_width, wi->opt_height);
    }
    
    /*
     * Update the registration with the overlap manager.
     */
#ifdef ATC
    if (mask & CONFIG_OM) {
      Tcl_HashEntry     *entry;
      ZnItem            grp;
      
      if (wi->om_group != ZN_NO_ITEM) {
        OmUnregister((void *) wi);
        wi->om_group = ZN_NO_ITEM;
      }
      if (wi->om_group_id != 0) {
        entry = Tcl_FindHashEntry(wi->id_table, (char *) wi->om_group_id);
        if (entry != NULL) {
          grp = (ZnItem) Tcl_GetHashValue(entry);
          if (grp->class == ZnGroup) {
            OmRegister((void *) wi, ZnSendTrackToOm, ZnSetLabelAngleFromOm, ZnQueryLabelPosition);
            wi->om_group = grp;
          }
        }
      }
    }
#endif
    
    if ((mask & CONFIG_FOCUS_ITEM) && wi->focus_item) {
      ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
    }
    /*
     * Update the blinking cursor timing if on/off time has changed.
     */
    if (ISSET(wi->flags, ZN_GOT_FOCUS) && (mask & CONFIG_FOCUS)) {
      Focus(wi, True);
    }
    
    if (mask & CONFIG_FOLLOW_POINTER) {
      if (wi->follow_pointer) {
        /* Flag has just been turned on, process
         * the last known positional event to update
         * the item under pointer.
         */
        if (wi->pick_event.type == ButtonPress ||
            wi->pick_event.type == ButtonRelease ||
            wi->pick_event.type == MotionNotify ||
            wi->pick_event.type == EnterNotify ||
            wi->pick_event.type == LeaveNotify) {
          Tcl_Preserve((ClientData) wi);
          CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK);
          PickCurrentItem(wi, &wi->pick_event);
          Tcl_Release((ClientData) wi);
        }
      }
    }
    break;
  }

  if (error) {
    Tcl_SetObjResult(interp, error_result);
    Tcl_DecrRefCount(error_result);
    return TCL_ERROR;
  }
  else {
    Tk_FreeSavedOptions(&saved_options);
    return TCL_OK;
  }
}
#endif

/*
 *----------------------------------------------------------------------
 *
 * Focus --
 *
 *      This procedure is called whenever a zinc gets or loses the
 *      input focus.  It's also called whenever the window is
 *      reconfigured while it has the focus.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      The cursor gets turned on or off.
 *
 *----------------------------------------------------------------------
 */
static void
Blink(ClientData        client_data)
{
  ZnWInfo *wi = (ZnWInfo *) client_data;

  if (ISCLEAR(wi->flags, ZN_GOT_FOCUS) || (wi->insert_off_time == 0)) {
    return;
  }
  if (wi->text_info.cursor_on) {
    wi->text_info.cursor_on = 0;
    wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time, Blink, client_data);
  }
  else {
    wi->text_info.cursor_on = 1;
    wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_on_time, Blink, client_data);
  }
  if ((wi->focus_item != ZN_NO_ITEM) && (wi->focus_item->class->Cursor != NULL)) {
    ZnITEM.Invalidate(wi->focus_item, ZN_DRAW_FLAG);
  }
}

static void
Focus(ZnWInfo   *wi,
      ZnBool            got_focus)
{
  Tcl_DeleteTimerHandler(wi->blink_handler);
  if (got_focus) {
    SET(wi->flags, ZN_GOT_FOCUS);
    wi->text_info.cursor_on = 1;
    if (wi->insert_off_time != 0) {
      wi->blink_handler = Tcl_CreateTimerHandler(wi->insert_off_time, Blink, (ClientData) wi);
    }
  }
  else {
    CLEAR(wi->flags, ZN_GOT_FOCUS);
    wi->text_info.cursor_on = 0;
    wi->blink_handler = (Tcl_TimerToken) NULL;
  }
  if ((wi->focus_item != ZN_NO_ITEM) &&
      (wi->focus_item->class->Cursor != NULL)){
    ZnITEM.Invalidate(wi->focus_item, ZN_COORDS_FLAG);
  }
  /*printf("focus %s\n", got_focus ? "in" : "out");*/
  if (wi->highlight_width > 0) {
    ZnNeedRedisplay(wi);
  }
}


/*
 *----------------------------------------------------------------------
 *
 * Event --
 *
 *      This procedure is invoked by the Tk dispatcher for various
 *      events on Zincs.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      When the window gets deleted, internal structures get
 *      cleaned up.  When it gets exposed, it is redisplayed.
 *
 *----------------------------------------------------------------------
 */
static void
TopEvent(ClientData     client_data,    /* Information about widget. */
         XEvent         *event)
{
  ZnWInfo       *wi = (ZnWInfo *) client_data;
  if (event->type == ConfigureNotify) {
    /*printf("Window moved\n");*/
    SET(wi->flags, ZN_CONFIGURE_EVENT);
  }  
}

static void
FinishSetup(ZnWInfo *wi)
{
  XGCValues values;
  Tk_Window top_level;

  if (!wi->gc) {
    SET(wi->flags, ZN_REALIZED);
    top_level = wi->win;
    while (!Tk_IsTopLevel(top_level)) {
      top_level = Tk_Parent(top_level);
    }
#ifdef GL
    InitRendering2(wi, top_level);
#endif

    /*
     * Get the work GC and suppress GraphicExpose
     * and NoExpose events reception.
     */
    wi->gc = XCreateGC(wi->dpy, Tk_WindowId(wi->win), 0, NULL);
    values.graphics_exposures = False;
    XChangeGC(wi->dpy, wi->gc, GCGraphicsExposures, &values);

    /*
     * Set the real top window above us.
     */
    {
      Window parent, root, *children=NULL;
      int success;
      unsigned int num_children;
      
      success = XQueryTree(wi->dpy, Tk_WindowId(top_level), &root, &parent,
                           &children, &num_children);
      if (!success || (root == parent)) {
        wi->real_top = Tk_WindowId(top_level);
      }
      else {
        wi->real_top = parent;
      }
      /*
       * Needed under glx to suspend update with scissors after
       * a move to synchronise the two buffers. Fix a refresh
       * bug when the window is partially clipped by the display
       * border. Can be usefull under Windows too.
       */
      Tk_CreateEventHandler(top_level, StructureNotifyMask, TopEvent, (ClientData) wi);
      if (children && success) {
        XFree(children);
      }
    }
  }
}

static void
Event(ClientData client_data,   /* Information about widget. */
      XEvent    *event) /* Information about event. */
{
  ZnWInfo   *wi = (ZnWInfo *) client_data;
  ZnBBox    bbox;

  //printf("=============== DEBUT %s %d EVENT ==================\n",
    //     event->type == MapNotify ? "MAP":
    //     event->type == Expose? "EXPOSE" :
    //     event->type == ConfigureNotify ? "CONFIGURE" :
    //     event->type == VisibilityNotify ? "VISIBILITY" :
    //     event->type == DestroyNotify ? "DESTROY" :
    //     "??", event->type);
  if (event->type == MapNotify) {
    SET(wi->flags, ZN_CONFIGURE_EVENT);
    FinishSetup(wi);
    wi->width = wi->opt_width;
    wi->height = wi->opt_height;
    ZnNeedRedisplay(wi);
  }
  else if (event->type == Expose) {
    ZnDim width, height;

    SET(wi->flags, ZN_CONFIGURE_EVENT);
    FinishSetup(wi);
    bbox.orig.x = (((XExposeEvent*) event)->x);
    bbox.orig.y = (((XExposeEvent*) event)->y);
    width = ((XExposeEvent*) event)->width;
    height = ((XExposeEvent*) event)->height;
    if (bbox.orig.x < 0) {
      width += bbox.orig.x;
      bbox.orig.x = 0;
    }
    if (bbox.orig.y < 0) {
      height += bbox.orig.y;
      bbox.orig.y = 0;
    }
    bbox.corner.x = MIN(wi->opt_width, bbox.orig.x + width);
    bbox.corner.y = MIN(wi->opt_height, bbox.orig.y + height);
    
    //printf("expose %d %d %d %d\n",
      //     ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y,
      //     ((XExposeEvent*) event)->width, ((XExposeEvent*) event)->height);
    /*
     * Add the exposed area to the expose region and
     * schedule an asynchronous redisplay of the window
     * if we are done adding exposed parts.
     */
    ZnAddBBoxToBBox(&wi->exposed_area, &bbox);
    if (/*(((XExposeEvent*) event)->count == 0) &&*/
        !ZnIsEmptyBBox(&wi->exposed_area)) {
      ZnNeedRedisplay(wi);
    }
  }
  /*
   * Resize the double buffer pixmap and prepare to redisplay
   * the whole scene. The transform parameters are not
   * modified as a result of the resize. If the application
   * need such change, it can bind a handler on <Configure>.
   */
  else if (event->type == ConfigureNotify) {
    int    int_width, int_height;

    SET(wi->flags, ZN_CONFIGURE_EVENT);
    FinishSetup(wi);

    int_width = Tk_Width(wi->win);
    int_height = Tk_Height(wi->win);
    
    bbox.orig.x = bbox.orig.y = 0;
    bbox.corner.x = MAX(wi->opt_width, int_width);
    bbox.corner.y = MAX(wi->opt_height, int_height);
    wi->opt_width = wi->width = int_width;
    wi->opt_height = wi->height = int_height;

    ZnResetTransformStack(wi);

    SET(wi->flags, ZN_UPDATE_SCROLLBARS);
    /*
     * The call below is needed in order to recenter the view if
     * it's confined and the scroll region is smaller than the
     * window.
     */
    ZnSetOrigin(wi, wi->origin.x, wi->origin.y);

    ZnDamage(wi, &bbox);
    ZnITEM.Invalidate(wi->top_group, ZN_TRANSFO_FLAG);
    
    /*
     * Reallocate the double buffer pixmap/image.
     */
    if (!wi->render) {
      /*printf("reallocating double buffer\n");*/
      if (wi->draw_buffer) {
        Tk_FreePixmap(wi->dpy, wi->draw_buffer);
      }
      wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen),
                                     int_width, int_height,
                                     DefaultDepthOfScreen(wi->screen));
    }
    else {
#if defined(GL)
#if defined(MAC_OSX_TK)
      ZnGLContextEntry *ce = ZnGLMakeCurrent(wi->dpy, wi);
      UpdateBufferRect(ce, wi->win);
      aglUpdateContext(ce->context);
#endif
      SET(wi->flags, ZN_UPDATE_CANVASTEX);
#endif
    }
    /*
     * In case of a window reconfiguration following a change
     * of border size, set the exposed area to force a copy
     * of the back buffer to the screen.
     */
    bbox.orig.x = bbox.orig.y = 0;
    bbox.corner.x = Tk_Width(wi->win);
    bbox.corner.y = Tk_Height(wi->win);
    ZnAddBBoxToBBox(&wi->exposed_area, &bbox);      
    ZnNeedRedisplay(wi);
  }
  /*
   * Take into account that the window has been actually cancelled.
   * Remove the corresponding widget command, unregister any
   * pending Redisplay and eventually free the widget's memory.
   */
  else if (event->type == DestroyNotify) {
    Destroy(wi);
  }
  else if (event->type == FocusIn) {
    if (event->xfocus.detail != NotifyInferior) {
      Focus(wi, True);
    }
  }
  else if (event->type == FocusOut) {
    if (event->xfocus.detail != NotifyInferior) {
      Focus(wi, False);
    }
  }
  
  /*printf("=============== FIN %s EVENT ==================\n",
         event->type == MapNotify ? "MAP":
         event->type == Expose? "EXPOSE" :
         event->type == ConfigureNotify ? "CONFIGURE" :
         event->type == VisibilityNotify ? "VISIBILITY" :
         event->type == DestroyNotify ? "DESTROY" :
         "??");*/
}


/*
 *----------------------------------------------------------------------
 *
 * DoEvent --
 *
 *      Trigger the bindings associated with an event.
 *
 *----------------------------------------------------------------------
 */
static void
DoEvent(ZnWInfo *wi,
        XEvent  *event,
        ZnBool  bind_item, /* Controls whether item bindings will trigger.
                            * Useful for Enter/Leaves between fields */
        ZnBool  bind_part) /* Controls whether part bindings will trigger.
                            * Useful for precise control of Enter/Leaves
                            * during grabs. */
{
#define NUM_STATIC 4
  ClientData            items[NUM_STATIC], *its;
  static unsigned int   worksize = 128, len, num, num_tags;
  static char           *workspace = NULL;
  unsigned int          i, ptr;
  ClientData            *tag_list = NULL;
  ZnItem                item;
  int                   part;

#define BIND_ITEM(test)                 \
  if (bind_item && (test)) {            \
    its[ptr] = (ClientData) all_uid;    \
    ptr++;                              \
    for (i = 0; i < num_tags; i++) {    \
      its[ptr] = tag_list[i];           \
      ptr++;                            \
    }                                   \
    its[ptr] = (ClientData) item;       \
    ptr++;                              \
  }

  if (wi->binding_table == NULL) {
    //printf("no bindings\n");
    return;
  }

  item = wi->current_item;
  part = wi->current_part;
  if ((event->type == KeyPress) || (event->type == KeyRelease)) {
    item = wi->focus_item;
    part = wi->focus_field;
  }
  
  if ((item == ZN_NO_ITEM) || !item->class->IsSensitive(item, ZN_NO_PART)) {
    return;
  }
  
  /*
   * Set up an array with all the relevant elements for processing
   * this event.  The relevant elements are (a) the event's item/part
   * tag (i.e item:part), (b) the event's item, (c) the tags
   * associated with the event's item, and (d) the tag 'all'.
   */
  num = 0;
  num_tags = 0;
  its = items;
  bind_part = (bind_part &&
               (part != ZN_NO_PART) &&
               item->class->IsSensitive(item, part) &&
               ((wi->current_item != ZN_NO_ITEM) &&
                (wi->current_item->class->num_parts ||
                 wi->current_item->class->GetFieldSet)));

  //printf("type=%s, current=%d, new=%d --> %s, currentp %d, newp %d\n",
    //     event->type==EnterNotify?"<Enter>":
    //     event->type==LeaveNotify?"<Leave>":
    //     event->type==MotionNotify?"<Motion>":"other",
    //     wi->current_item?wi->current_item->id:0,
    //     wi->new_item?wi->new_item->id:0,
    //     bind_item?"bind":"nobind",
    //     wi->current_part, wi->new_part);
  if (bind_item) {
    num += 2;
  }
  if (bind_part) {
    num++;
    if (!workspace) {
      workspace = ZnMalloc(worksize);
    }
  }
  if (item->tags) {
    num_tags = ZnListSize(item->tags);
    if (bind_item) {
      num += num_tags;
    }
    if (bind_part) {
      num += num_tags;
    }
    tag_list = (ClientData *) ZnListArray(item->tags);
    if (num > NUM_STATIC) {
      its = (ClientData *) ZnMalloc(num*sizeof(ClientData));
    }
  }

  ptr = 0;

  BIND_ITEM(event->type != LeaveNotify);
  
  if (bind_part) {
    /*
     * Add here a binding for each tag suffixed by :part
     */
    for (i = 0; i < num_tags; i++) {
      len = strlen(tag_list[i])+ TCL_INTEGER_SPACE;
      if (worksize < len) {
        worksize = len + 10;
        workspace = ZnRealloc(workspace, len);
      }
      sprintf(workspace, "%s:%d", (char *) tag_list[i], part);
      its[ptr] = (ClientData) Tk_GetUid(workspace);
      ptr++;
    }
    /*
     * Add here a binding for id:part
     */
    its[ptr] = EncodeItemPart(item, part);
    ptr++;
  }
  
  BIND_ITEM(event->type == LeaveNotify);

  /*
   * Invoke the binding system.
   */
  Tk_BindEvent(wi->binding_table, event, wi->win, (int) num, its);
  if (its != items) {
    ZnFree(its);
  }

#undef BIND_ITEM
}


/*
 *----------------------------------------------------------------------
 *
 * PickCurrentItem --
 *
 *      Finds the topmost item/field that contains the pointer and mark
 *      it has the current item. Generates Enter/leave events on the
 *      old and new current items/fields has necessary.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      The current item/field may change.  If it does,
 *      then the commands associated with item entry and exit
 *      could do just about anything.  A binding script could
 *      delete the widget, so callers should protect themselves
 *      with Tcl_Preserve and Tcl_Release.
 *
 * Note:
 *      See the Bind function's note.
 *
 *----------------------------------------------------------------------
 */
static void
PickCurrentItem(ZnWInfo *wi,
                XEvent  *event)
{
  int    button_down;
  ZnBool enter_item;
  ZnBool grab_release = False;

  /*printf("PickCurrent current=%d, new=%d\n",
         wi->current_item?wi->current_item->id:0,
         wi->new_item?wi->new_item->id:0);*/
  /*
   * Check whether or not a button is down.  If so, we'll log entry
   * and exit into and out of the current item, but not entry into
   * any other item.  This implements a form of grabbing equivalent
   * to what the X server does for windows.
   */
  button_down = wi->state
    & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask);
  if (!button_down) {
    grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM);
    CLEAR(wi->flags, ZN_GRABBED_ITEM);
    CLEAR(wi->flags, ZN_GRABBED_PART);
  }
  
  /*
   * Save information about this event in the widget.  The saved event
   * is used for two purposes:
   *
   * 1. Event bindings: if the current item changes, fake events are
   *    generated to allow item-enter and item-leave bindings to trigger.
   * 2. Reselection: if the current item gets deleted, can use the
   *    saved event to find a new current item.
   * Translate MotionNotify events into EnterNotify events, since that's
   * what gets reported to item handlers.
   */
  if (event != &wi->pick_event) {
    if ((event->type == MotionNotify) || (event->type == ButtonRelease)) {
      wi->pick_event.xcrossing.type = EnterNotify;
      wi->pick_event.xcrossing.serial = event->xmotion.serial;
      wi->pick_event.xcrossing.send_event = event->xmotion.send_event;
      wi->pick_event.xcrossing.display = event->xmotion.display;
      wi->pick_event.xcrossing.window = event->xmotion.window;
      wi->pick_event.xcrossing.root = event->xmotion.root;
      wi->pick_event.xcrossing.subwindow = None;
      wi->pick_event.xcrossing.time = event->xmotion.time;
      wi->pick_event.xcrossing.x = event->xmotion.x;
      wi->pick_event.xcrossing.y = event->xmotion.y;
      wi->pick_event.xcrossing.x_root = event->xmotion.x_root;
      wi->pick_event.xcrossing.y_root = event->xmotion.y_root;
      wi->pick_event.xcrossing.mode = NotifyNormal;
      wi->pick_event.xcrossing.detail = NotifyNonlinear;
      wi->pick_event.xcrossing.same_screen = event->xmotion.same_screen;
      wi->pick_event.xcrossing.focus = False;
      wi->pick_event.xcrossing.state = event->xmotion.state;
    }
    else {
      wi->pick_event = *event;
    }
  }

  /*
   * If this is a recursive call (there's already a partially completed
   * call pending on the stack;  it's in the middle of processing a
   * Leave event handler for the old current item) then just return;
   * the pending call will do everything that's needed.
   */
  if (ISSET(wi->flags, ZN_REPICK_IN_PROGRESS)) {
    fprintf(stderr, "PickCurrentItem recursive\n");
    return;
  }

  /*
   * A LeaveNotify event automatically means that there's no current
   * object, so the check for closest item can be skipped.
   */
  if (wi->pick_event.type != LeaveNotify) {
    ZnPickStruct ps;
    ZnReal       dist;
    ZnPoint      p;
    
    p.x = wi->pick_event.xcrossing.x;
    p.y = wi->pick_event.xcrossing.y;
    ps.point = &p;
    ps.in_group = ZN_NO_ITEM;
    ps.start_item = ZN_NO_ITEM;
    ps.aperture = wi->pick_aperture;
    ps.recursive = True;
    ps.override_atomic = False;
    dist = wi->top_group->class->Pick(wi->top_group, &ps);
    if (dist == 0.0) {
      wi->new_item = ps.a_item;
      wi->new_part = ps.a_part;
    }
    else {
      wi->new_item = ZN_NO_ITEM;
      wi->new_part = ZN_NO_PART;
    }
  }
  else {
    wi->new_item = ZN_NO_ITEM;
    wi->new_part = ZN_NO_PART;
  }
  /*
   * This state is needed to do a valid detection
   * of Enter during a grab.
   */
  enter_item = ((wi->new_item != wi->current_item) || ISSET(wi->flags, ZN_GRABBED_ITEM));

  /*printf("------ PickCurrentItem current: %d %d, new %d %d\n",
         wi->current_item==ZN_NO_ITEM?0:wi->current_item->id, wi->current_part,
         wi->new_item==ZN_NO_ITEM?0:wi->new_item->id, wi->new_part);*/

  if ((wi->new_item == wi->current_item) &&
      (wi->new_part == wi->current_part) &&
      ISCLEAR(wi->flags, ZN_GRABBED_ITEM) &&
      ISCLEAR(wi->flags, ZN_GRABBED_PART)) {
    /*
     * Nothing to do: the current item/part hasn't changed.
     */
    return;
  }

  /*
   * Simulate a LeaveNotify event on the previous current item.
   * Remove the "current" tag from the previous current item.
   */
  if ((wi->current_item != ZN_NO_ITEM) &&
      (((wi->new_item != wi->current_item) || (wi->new_part != wi->current_part)) &&
       ISCLEAR(wi->flags, ZN_GRABBED_ITEM))) {
      ZnItem item = wi->current_item;
    /*
     * Actually emit the event only if not releasing a grab
     * on button up.
     */
    if (!grab_release) {
      XEvent event;
      event = wi->pick_event;
      event.type = LeaveNotify;
      
      /*printf("== LEAVE %d %d ==\n", wi->current_item->id, wi->current_part);*/
      /*
       * If the event's detail happens to be NotifyInferior the
       * binding mechanism will discard the event.  To be consistent,
       * always use NotifyAncestor.
       */
      event.xcrossing.detail = NotifyAncestor;
      SET(wi->flags, ZN_REPICK_IN_PROGRESS);
      DoEvent(wi, &event,
              wi->new_item != wi->current_item, ISCLEAR(wi->flags, ZN_GRABBED_PART));
      CLEAR(wi->flags, ZN_REPICK_IN_PROGRESS);
    }
    
    /*
     * In all cases, if a grab is not current, remove the current tag.
     *
     * The check on item below is needed because there could be an
     * event handler for <LeaveNotify> that deletes the current item.
     */
    if ((item == wi->current_item) && !button_down) {
      /*printf("^^^ Removing 'current' from %d\n", wi->current_item->id);*/
      ZnITEM.RemoveTag(item, current_uid);
    }    
    /*
     * Note:  during DoEvent above, it's possible that
     * wi->new_item got reset to NULL because the
     * item was deleted.
     */
  }

  /*
   * Special note:  it's possible that wi->new_item == wi->current_item
   * here. This can happen, for example, if a grab was set or
   * if there is only a change in the part number.
   */
  if ((wi->new_item != wi->current_item) && button_down) {
    SET(wi->flags, ZN_GRABBED_ITEM);
  }
  else {
    if (button_down) {
      grab_release = ISSET(wi->flags, ZN_GRABBED_ITEM);
    }
    CLEAR(wi->flags, ZN_GRABBED_ITEM);
    wi->current_item = wi->new_item;
  }
  if ((wi->new_part != wi->current_part) && button_down) {
    SET(wi->flags, ZN_GRABBED_PART);
  }
  else {
    CLEAR(wi->flags, ZN_GRABBED_PART);
    wi->current_part = wi->new_part;
  }
  
  if (!grab_release &&
      (ISSET(wi->flags, ZN_GRABBED_PART) || ISSET(wi->flags, ZN_GRABBED_ITEM))) {
    return;
  }
  
  if (wi->current_item != ZN_NO_ITEM) {
    XEvent event;
    /*
     * Add the tag 'current' to the current item under the pointer.
     */
    /*printf("Adding 'current' to %d\n", wi->current_item->id);*/
    ZnDoItem((Tcl_Interp *) NULL, wi->current_item, ZN_NO_PART, current_uid);
    /*
     * Then emit a fake Enter event on it.
     */
    /*printf("== ENTER %d %d ==\n",wi->current_item->id, wi->current_part);*/
    event = wi->pick_event;
    event.type = EnterNotify;
    event.xcrossing.detail = NotifyAncestor;
    DoEvent(wi, &event,
            enter_item, !(grab_release && ISSET(wi->flags, ZN_GRABBED_PART)));
  }
}


/*
 *----------------------------------------------------------------------
 *
 * Bind --
 *
 *      This procedure is invoked by the Tk dispatcher to handle
 *      events associated with bindings on items.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Depends on the command invoked as part of the binding
 *      (if there was any).
 *
 * Note:
 *      This has been taken as is from the Tk canvas. It might not
 *      not be fully adequate for the purpose. But at least this
 *      provides two benefits: a/ It is believe to be correct and
 *      b/ users are accustomed to its behavior.
 *
 *----------------------------------------------------------------------
 */
static void
Bind(ClientData client_data,    /* Information about widget. */
     XEvent     *event)         /* Information about event. */
{
  ZnWInfo       *wi = (ZnWInfo *) client_data;
  
  Tcl_Preserve((ClientData) wi);

  /*
   * This code below keeps track of the current modifier state in
   * wi->state.  This information is used to defer repicks of
   * the current item while buttons are down.
   */
  if ((event->type == ButtonPress) || (event->type == ButtonRelease)) {
    int mask;
    
#if defined(GL) && defined(ROTATION)
    if (wi->enable_rotation) {
      TransformEvent(wi, event);
    }
#endif
    switch (event->xbutton.button) {
    case Button1:
      mask = Button1Mask;
      break;
    case Button2:
      mask = Button2Mask;
      break;
    case Button3:
      mask = Button3Mask;
      break;
    case Button4:
      mask = Button4Mask;
      break;
    case Button5:
      mask = Button5Mask;
      break;
    default:
      mask = 0;
      break;
    }    
    /*
     * For button press events, repick the current item using the
     * button state before the event, then process the event.  For
     * button release events, first process the event, then repick
     * the current item using the button state *after* the event
     * (the button has logically gone up before we change the
     * current item).
     */
    
    if (event->type == ButtonPress) {
      /*
       * On a button press, first repick the current item using
       * the button state before the event, then process the event.
       */      
      wi->state = event->xbutton.state;
      PickCurrentItem(wi, event);
      wi->state ^= mask;
      if (wi->current_item != ZN_NO_ITEM) {
        DoEvent(wi, event, True, True);
      }
    }
    else {
      /*
       * Button release: first process the event, with the button
       * still considered to be down.  Then repick the current
       * item under the assumption that the button is no longer down.
       */
      wi->state = event->xbutton.state;
      DoEvent(wi, event, True, True);
      event->xbutton.state ^= mask;
      wi->state = event->xbutton.state;
      PickCurrentItem(wi, event);
      event->xbutton.state ^= mask;
    }
    goto done;
  }
  
  else if ((event->type == EnterNotify) || (event->type == LeaveNotify)) {
#if defined(GL) && defined(ROTATION)
    if (wi->enable_rotation) {
      TransformEvent(wi, event);
    }
#endif
    wi->state = event->xcrossing.state;
    PickCurrentItem(wi, event);
    goto done;
  }
  
  else if (event->type == MotionNotify) {
#if defined(GL) && defined(ROTATION)
    if (wi->enable_rotation) {
      TransformEvent(wi, event);
    }
#endif
    wi->state = event->xmotion.state;
    if (wi->follow_pointer) {
      PickCurrentItem(wi, event);
    }
    else {
      /* Copy the event for later processing
       * and skip the picking phase.
       */
      wi->pick_event = *event;
    }
  }

  DoEvent(wi, event, True, True);
  
done:
  Tcl_Release((ClientData) wi);
}


/*
 *----------------------------------------------------------------------
 *
 * LostSelection --
 *
 *      This procedure is called back by Tk when the selection is
 *      grabbed away from a zinc widget.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      The existing selection is unhighlighted, and the window is
 *      marked as not containing a selection.
 *
 *----------------------------------------------------------------------
 */
static void
LostSelection(ClientData        client_data)
{
  ZnWInfo       *wi = (ZnWInfo *) client_data;
  ZnTextInfo    *ti = &wi->text_info;
  
  if (ti->sel_item != ZN_NO_ITEM) {
    ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG);
  }
  ti->sel_item = ZN_NO_ITEM;
  ti->sel_field = ZN_NO_PART;
}


/*
 *----------------------------------------------------------------------
 *
 * SelectTo --
 *
 *      Modify the selection by moving its un-anchored end.  This could
 *      make the selection either larger or smaller.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      The selection changes.
 *
 *----------------------------------------------------------------------
 */
static void
SelectTo(ZnItem item,
         int    field,
         int    index)
{
  ZnWInfo       *wi = item->wi;
  ZnTextInfo    *ti = &wi->text_info;
  int           old_first, old_last, old_field;
  ZnItem        old_sel_item;

  old_first = ti->sel_first;
  old_last = ti->sel_last;
  old_sel_item = ti->sel_item;
  old_field = ti->sel_field;
  
  /*
   * Grab the selection if we don't own it already.
   */
  if (ti->sel_item == ZN_NO_ITEM) {
    Tk_OwnSelection(wi->win, XA_PRIMARY, LostSelection, (ClientData) wi);
  }
  else if ((ti->sel_item != item) || (ti->sel_field != field)) {
    ZnITEM.Invalidate(ti->sel_item, ZN_DRAW_FLAG);
  }
  ti->sel_item = item;
  ti->sel_field = field;
  
  if ((ti->anchor_item != item) || (ti->anchor_field) != field) {
    ti->anchor_item = item;
    ti->anchor_field = field;
    ti->sel_anchor = index;
  }
  if (ti->sel_anchor <= index) {
    ti->sel_first = ti->sel_anchor;
    ti->sel_last = index;
  }
  else {
    ti->sel_first = index;
    ti->sel_last = ti->sel_anchor;
  }
  if ((ti->sel_first != old_first) ||
      (ti->sel_last != old_last) ||
      (item != old_sel_item)) {
    ZnITEM.Invalidate(item, ZN_DRAW_FLAG);
  }
}


/*
 *--------------------------------------------------------------
 *
 * FetchSelection --
 *
 *      This procedure is invoked by Tk to return part or all of
 *      the selection, when the selection is in a zinc widget.
 *      This procedure always returns the selection as a STRING.
 *
 * Results:
 *      The return value is the number of non-NULL bytes stored
 *      at buffer.  Buffer is filled (or partially filled) with a
 *      NULL-terminated string containing part or all of the selection,
 *      as given by offset and maxBytes.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
static int
FetchSelection( ClientData      client_data,
                int             offset,         /* Offset within selection of first
                                                 * character to be returned. */
                char            *buffer,        /* Location in which to place
                                                 * selection. */
                int             max_bytes)      /* Maximum number of bytes to place
                                                 * at buffer, not including terminating
                                                 * NULL character. */
{
  ZnWInfo       *wi = (ZnWInfo *) client_data;
  ZnTextInfo    *ti = &wi->text_info;
  
  if (ti->sel_item == ZN_NO_ITEM) {
    return -1;
  }
  if (ti->sel_item->class->Selection == NULL) {
    return -1;
  }
  return (*ti->sel_item->class->Selection)(ti->sel_item, ti->sel_field,
                                           offset, buffer, max_bytes);
}


/*
 *----------------------------------------------------------------------
 *
 * CmdDeleted --
 *
 *      This procedure is invoked when a widget command is deleted. If
 *      the widget isn't already in the process of being destroyed,
 *      this command destroys it.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      The widget is destroyed.
 *
 *----------------------------------------------------------------------
 */
static void
CmdDeleted(ClientData client_data) /* Pointer to widget record for widget. */
{
  ZnWInfo       *wi = (ZnWInfo *) client_data;

  if (wi->win != NULL) {
    Tk_DestroyWindow(wi->win);
  }
}


/*
 *----------------------------------------------------------------------
 *
 * Destroy --
 *
 *      This procedure is invoked by Tk_EventuallyFree or Tk_Release
 *      to clean up the internal structure of the widget at a safe time
 *      (when no-one is using it anymore).
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Everything associated with the widget is freed up.
 *
 *----------------------------------------------------------------------
 */
static void
Destroy(ZnWInfo *wi)
{
  unsigned int  num;
  Tcl_HashSearch search;
  Tcl_HashEntry *entry;
#ifdef GL
  unsigned int  i;
  ZnGLContextEntry *ce;
  ZnWInfo       **wip;
#endif

  //printf("Destroy begining\n");
  /*
   * This procedure could be invoked either because the window was
   * destroyed and the command was then deleted (in which case win
   * is NULL) or because the command was deleted, and then this procedure
   * destroys the widget.
   */
  CLEAR(wi->flags, ZN_REALIZED);
#ifdef PTK
  Lang_DeleteWidget(wi->interp, wi->cmd);
#else 
  Tcl_DeleteCommandFromToken(wi->interp, wi->cmd);
#endif
  /*
   * Remove the redisplay scheduled by the cleanup.
   * It will fire when the widget will be gone and
   * will corrupt memory.
   */
  if (ISSET(wi->flags, ZN_UPDATE_PENDING)) {
    Tcl_CancelIdleCall(Redisplay, (ClientData) wi);
  }
  /*
   * Unregister form the overlap manager.
   */
#ifdef ATC
  if (wi->om_group != ZN_NO_ITEM) {
    OmUnregister((void *) wi);
  }
#endif

  /*
   * Print remaining items.
   */
  
  /* Free all items. */
  /*fprintf(stderr, "Item count before cleanup: %d\n", wi->num_items);*/
  ZnITEM.DestroyItem(wi->top_group);
  /*fprintf(stderr, "Remaining item count: %d\n", wi->num_items);*/

  for (num = 0; num < ZN_NUM_ALPHA_STEPS; num++) {
    if (wi->alpha_stipples[num] != None) {
      Tk_FreeBitmap(wi->dpy, wi->alpha_stipples[num]);
      wi->alpha_stipples[num] = None;
    }
  }

  Tcl_DeleteHashTable(wi->id_table);
  ZnFree(wi->id_table);

  /*
   * Free the transform table contents.
   */
  entry = Tcl_FirstHashEntry(wi->t_table, &search);
  while (entry != NULL) {
    ZnTransfoFree((ZnTransfo *) Tcl_GetHashValue(entry));
    entry = Tcl_NextHashEntry(&search);
  }
  Tcl_DeleteHashTable(wi->t_table);
  ZnFree(wi->t_table);

  if (wi->binding_table != NULL) {
    Tk_DeleteBindingTable(wi->binding_table);
  }

  /* Free the tile */
  if (wi->tile != ZnUnspecifiedImage) {
#ifdef PTK_800
    ZnFreeImage(wi->tile, ZnImageUpdate, wi);
#else
    ZnFreeImage(wi->tile, TileUpdate, wi);
#endif
    wi->tile = ZnUnspecifiedImage;
  }

#ifdef ATC
  /* Free the symbols */
  if (wi->map_distance_symbol != ZnUnspecifiedImage) {
    ZnFreeImage(wi->map_distance_symbol, NULL, NULL);
    wi->map_distance_symbol = ZnUnspecifiedImage;
  }
  if (wi->track_symbol != ZnUnspecifiedImage) {
    ZnFreeImage(wi->track_symbol, NULL, NULL);
    wi->track_symbol = ZnUnspecifiedImage;
  }
#endif

  /* Free the double buffer pixmap/image */
  if (wi->draw_buffer) {
    Tk_FreePixmap(wi->dpy, wi->draw_buffer);
    wi->draw_buffer = 0;
  }

#ifdef PTK_800
  if (wi->fore_color) {
    ZnFreeGradient(wi->fore_color);
    wi->fore_color = NULL;
  }
  if (wi->back_color) {
    ZnFreeGradient(wi->back_color);
    wi->back_color = NULL;
  }
#endif
  if (wi->relief_grad) {
    ZnFreeGradient(wi->relief_grad);
    wi->relief_grad = NULL;
  }
  if (wi->gc) {
    XFreeGC(wi->dpy, wi->gc);
    wi->gc = 0;
  }

  Tcl_DeleteTimerHandler(wi->blink_handler);

#ifdef PTK_800
  Tk_FreeOptions(config_specs, (char *) wi, wi->dpy, 0);
#else
  Tk_FreeConfigOptions((char *) wi, wi->opt_table, wi->win);
#endif

#ifdef GL
  if (wi->font_tfi) {
    ZnFreeTexFont(wi->font_tfi);
    wi->font_tfi = NULL;
  }
#ifdef ATC
  if (wi->map_font_tfi) {
    ZnFreeTexFont(wi->map_font_tfi);
    wi->map_font_tfi = NULL;
  }
#endif
#ifdef ROTATION
  if (wi->canvastex) {
    glDeleteFramebuffersEXT(1, &wi->fbo);
    glDeleteRenderbuffersEXT(1, &wi->depthstencil);
    glDeleteTextures(1, &wi->canvastex);
    wi->canvastex = 0;
  }
#endif
  /*
   * Remove the widget from the context list and
   * free the context if no more widgets are active.
   */
  ce = ZnGetGLContext(wi->dpy);
  if (ce) {
    wip = ZnListArray(ce->widgets);
    num = ZnListSize(ce->widgets);
    for (i = 0; i < num; i++, wip++) {
      if (*wip == wi) {
        ZnListDelete(ce->widgets, i);
      }
    }
    /*
     * This code cause spurious X11 server reboots
     * with nvidia drivers (not tested with others
     * though). Thus it has been limited to WIN for
     * the time being.
     */
#if 1 /*def _WIN32*/
    if (ZnListSize(ce->widgets) == 0) {
      ZnGLContextEntry *prev, *next;
      /*printf("Freeing a GL context\n");*/
      if (ce == gl_contexts) {
        gl_contexts = ce->next;
      }
      else {
        for (prev = gl_contexts, next = gl_contexts->next; next;
             prev = next, next = next->next) {
          if (next == ce) {
            prev->next = next->next;
            break;
          }
        }
      }
#ifdef PLATFORM_SDL
      SdlTkGLXDestroyContext(wi->dpy, Tk_WindowId(wi->win), ce->context);
#elif defined(_WIN32)
      ZnGLReleaseContext(wi, ce);
      wglDeleteContext(ce->context);
#elif defined(MAC_OSX_TK)
      aglDestroyPixelFormat(ce->pix_fmt);
      aglDestroyContext(ce->context);
#else
      glXDestroyContext(ce->dpy, ce->context);
      /*
       * This call seems to be a problem for X11/Mesa
       */
      /*XFreeColormap(ce->dpy, ce->colormap);*/
      XFree(ce->visual);
#endif
      ZnListFree(ce->widgets);
      ZnFree(ce);
    }
#endif
  }
#endif
  /*
  if (wi->font) {
    Tk_FreeFont(wi->font);
  }
  if (wi->map_text_font) {
    Tk_FreeFont(wi->map_text_font);
  }*/
  
  /*
   * Should be empty by now.
   */
  ZnFreeTransformStack(wi);
  ZnFreeClipStack(wi);

#ifndef _WIN32
  ZnFreeChrono(wi->total_draw_chrono);
  ZnFreeChrono(wi->this_draw_chrono);
#endif

  wi->win = NULL;
  Tcl_EventuallyFree((ClientData) wi, TCL_DYNAMIC);
  /*printf("Destroy ending\n");*/
}


/*
 **********************************************************************************
 *
 * ZnDamage --
 *
 **********************************************************************************
 */
void
ZnDamage(ZnWInfo        *wi,
         ZnBBox         *damage)
{
  if ((damage == NULL) || ZnIsEmptyBBox(damage)) {
    return;
  }
  
  /*printf("damaging area: %g %g %g %g\n", damage->orig.x,
    damage->orig.y, damage->corner.x, damage->corner.y);*/

  if (ZnIsEmptyBBox(&wi->damaged_area)) {
    wi->damaged_area.orig.x = damage->orig.x;
    wi->damaged_area.orig.y = damage->orig.y;
    wi->damaged_area.corner.x = damage->corner.x;
    wi->damaged_area.corner.y = damage->corner.y;
    ZnNeedRedisplay(wi);
  }
  else {
    wi->damaged_area.orig.x = MIN(wi->damaged_area.orig.x, damage->orig.x);
    wi->damaged_area.orig.y = MIN(wi->damaged_area.orig.y, damage->orig.y);
    wi->damaged_area.corner.x = MAX(wi->damaged_area.corner.x, damage->corner.x);
    wi->damaged_area.corner.y = MAX(wi->damaged_area.corner.y, damage->corner.y);
  }
  /*printf("damaged area: %g %g %g %g\n", wi->damaged_area.orig.x,
         wi->damaged_area.orig.y, wi->damaged_area.corner.x,
         wi->damaged_area.corner.y);*/
}

void
ZnDamageAll(ZnWInfo *wi)
{
  ZnBBox bbox;

  bbox.orig.x = bbox.orig.y = 0;
  bbox.corner.x = Tk_Width(wi->win);
  bbox.corner.y = Tk_Height(wi->win);
  ZnDamage(wi, &bbox);
}

static void
ClampDamageArea(ZnWInfo *wi)
{
  int   width, height;

  if (wi->damaged_area.orig.x < wi->inset) {
    wi->damaged_area.orig.x = wi->inset;
  }
  if (wi->damaged_area.orig.y < wi->inset) {
    wi->damaged_area.orig.y = wi->inset;
  }
  if (wi->damaged_area.corner.x < wi->inset) {
    wi->damaged_area.corner.x = wi->inset;
  }
  if (wi->damaged_area.corner.y < wi->inset) {
    wi->damaged_area.corner.y = wi->inset;
  }
  width = wi->width - wi->inset;
  height = wi->height - wi->inset;
  if (wi->damaged_area.orig.x > width) {
    wi->damaged_area.orig.x = width;
  }
  if (wi->damaged_area.orig.y > height) {
    wi->damaged_area.orig.y = height;
  }
  if (wi->damaged_area.corner.x > width) {
    wi->damaged_area.corner.x = width;
  }
  if (wi->damaged_area.corner.y > height) {
    wi->damaged_area.corner.y = height;
  }
}


/*
 **********************************************************************************
 *
 * Update --
 *
 **********************************************************************************
 */
static void
Update(ZnWInfo  *wi)
{
  /*
   * Give the overlap manager a chance to do its work.
   */
#ifdef ATC
  if ((wi->om_group != ZN_NO_ITEM) && ZnGroupCallOm(wi->om_group)) {  
    ZnPoint scale={1.0,1.0};
    if (wi->om_group->transfo) {
      ZnTransfoDecompose(wi->om_group->transfo, &scale,
                            NULL, NULL, NULL);
    }
    OmProcessOverlap((void *) wi, wi->width, wi->height, scale.x);
    ZnGroupSetCallOm(wi->om_group, False);
  }
#endif
  if (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) ||
      ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG)) {
    wi->top_group->class->ComputeCoordinates(wi->top_group, False);
  }
}

#if defined(GL) && defined(ROTATION)
static void
TransformEvent(ZnWInfo *wi,
               XEvent  *event)
{
  ZnPoint p, xp;

  p.x = event->xmotion.x;
  p.y = event->xmotion.y;
  ZnTransformPoint(&wi->rotation_transfo, &p, &xp);
  event->xmotion.x = ZnNearestInt(xp.x);
  event->xmotion.y = ZnNearestInt(xp.y);
}

static void
SetupRotationTexture(ZnWInfo *wi)
{
  ZnReal offsetX, offsetY;
  ZnReal tex_width, tex_height;
  int    i;
  GLenum status;

  //
  // Create the canvas buffer if needed (rotation)
  if (ISSET(wi->flags, ZN_UPDATE_CANVASTEX)) {
    CLEAR(wi->flags, ZN_UPDATE_CANVASTEX);
    //
    // Free the canvas texture it'll be recreated
    // automatically with the correct size.
    if (wi->canvastex) {
      glDeleteTextures(1, &wi->canvastex);
      wi->canvastex = 0;
    }
    if (wi->depthstencil) {
      glDeleteRenderbuffersEXT(1, &wi->depthstencil);
      wi->depthstencil = 0;
    }
    //
    // Compute the intermediate canvas size
    wi->width = wi->height = hypot(wi->opt_width, wi->opt_height);
    tex_width = To2Power(wi->width);
    tex_height = To2Power(wi->height);
    //
    // Transform the window rectangle around the origin and
    // compute window coordinates in texture space (center of window
    // on texture center)
    ZnTransfoSetIdentity(&wi->rotation_transfo);
    offsetX = ZnNearestInt(wi->opt_width/2.0);
    offsetY = ZnNearestInt(wi->opt_height/2.0);
    ZnTranslate(&wi->rotation_transfo, -offsetX, -offsetY, 0);
    ZnRotateDeg(&wi->rotation_transfo, -wi->screen_rotation);
    //printf("taille: %d %d, rotation: %d, centre: %g %g\n",
      //     wi->opt_width, wi->opt_height, wi->screen_rotation, offsetX, offsetY);
    wi->texcoords[0].x = wi->texcoords[0].y = 0;
    wi->texcoords[1].x = 0; wi->texcoords[1].y = wi->opt_height;
    wi->texcoords[2].x = wi->opt_width; wi->texcoords[2].y = wi->opt_height;
    wi->texcoords[3].x = wi->opt_width; wi->texcoords[3].y = 0;
    ZnTranslate(&wi->rotation_transfo, wi->width / 2, wi->height / 2, 0);
    ZnScale(&wi->rotation_transfo, 1.0/tex_width, 1.0/tex_height); 
    ZnTransformPoints(&wi->rotation_transfo, wi->texcoords, wi->texcoords, 4);
    //
    // Compute event transformation to map incoming mouse event.
    ZnTransfoSetIdentity(&wi->rotation_transfo);
    ZnTranslate(&wi->rotation_transfo, -offsetX, -offsetY, 0);
    ZnRotateDeg(&wi->rotation_transfo, wi->screen_rotation);
    ZnTranslate(&wi->rotation_transfo, wi->width / 2, wi->height / 2, 0);
    //
    // Create a FBO if needed.
    if (wi->fbo == 0) {
      glGenFramebuffersEXT(1, &wi->fbo);
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wi->fbo);
    //
    // Create a depth/stencil buffer combo.
    glGenRenderbuffersEXT(1, &wi->depthstencil);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, wi->depthstencil);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
                             tex_width, tex_height);
    //
    // Create a texture for rendering.
    glGenTextures(1, &wi->canvastex);
    glBindTexture(GL_TEXTURE_2D, wi->canvastex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glGetError();
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height,
                 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    if (glGetError() != GL_NO_ERROR) {
      ZnWarning("Can't allocate a texture for the intermediate canvas\n");
    }
    //
    // Attach a depth/stencil combo to the fbo.
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
                                 GL_RENDERBUFFER_EXT, wi->depthstencil);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
                                 GL_RENDERBUFFER_EXT, wi->depthstencil);
    //
    // Attach the texture to the fbo.
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                              GL_TEXTURE_2D, wi->canvastex, 0);
    status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
      ZnWarning("Frame buffer installation is not complete\n");
    }
  }
  //
  // Redirect all GL primitives to the FBO.
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wi->fbo);
}

static void
FinalizeRotation(ZnWInfo *wi)
{
  //
  // Ok we have the intermediate texture ready we'll cast it
  // to the window now. We use a quad the size of the window
  // 
  // First stop redirecting primitives to the fbo.
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

  glViewport(0, 0, wi->opt_width, wi->opt_height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0, wi->opt_width, 0.0, wi->opt_height, -1.0, 1.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  //glDisable(GL_BLEND);
  glColor4us(65535, 65535, 65535, 65535);

  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, wi->canvastex);
  glBegin(GL_QUADS);
  glTexCoord2d(wi->texcoords[0].x, wi->texcoords[0].y);
  glVertex2i(0, 0);
  glTexCoord2d(wi->texcoords[1].x, wi->texcoords[1].y);
  glVertex2i(0, wi->opt_height);
  glTexCoord2d(wi->texcoords[2].x, wi->texcoords[2].y);
  glVertex2i(wi->opt_width, wi->opt_height);
  glTexCoord2d(wi->texcoords[3].x, wi->texcoords[3].y);
  glVertex2i(wi->opt_width, 0);
  glEnd();
  glDisable(GL_TEXTURE_2D);
}
#endif

/*
 **********************************************************************************
 *
 * Repair --
 *
 **********************************************************************************
 */
#if defined (_WIN32)
#define START \
  QueryPerformanceCounter(&start)

#define STOP_PRINT(text) \
    QueryPerformanceCounter(&stop); \
    printf(text##" : %g ms\n", \
           ((double) (stop.QuadPart - start.QuadPart)) * 1000.0 / ((double) sw_freq.QuadPart))
#endif

static void
Repair(ZnWInfo  *wi)
{
  XGCValues     values;
  ZnPoint       p[5];
  ZnTriStrip    tristrip;
#ifdef GL
  XColor        *color;
  int           darea_x1, darea_x2, darea_y1, darea_y2;
  ZnGLContextEntry *ce;
#endif
  //LARGE_INTEGER start, stop, sw_freq;
  
  //QueryPerformanceFrequency(&sw_freq);
  //START;
  /*SET(wi->flags, ZN_CONFIGURE_EVENT);*/
  if (wi->render) {
#ifdef GL
    /* Load deferred font glyphs just before making the context
     * current. Mandatory under Windows (probably due to hdc use conflict).
     */
    ZnGetDeferredGLGlyphs();

    ZnGLWaitX();

    /* Test if we must use damage or not */ 
    if (wi->usedamage) {
      if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
         ClampDamageArea(wi);
         /*
         * Merge the exposed area.
         */
         ZnAddBBoxToBBox(&wi->damaged_area, &wi->exposed_area);
         if (ZnIsEmptyBBox(&wi->damaged_area)) {
            return;
         }
      }
    }
    

    //printf("Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT));
    ce = ZnGLMakeCurrent(wi->dpy, wi);
    
    // PRE-RENDERING Method. Called for non directAccess viewports and other special effects
    // ONLY IF WE HAVE AT LEAST ONE VIEWPORT
    if (wi->nb_of_viewport_items > 0) {
      wi->top_group->class->PreRender(wi->top_group);    
    }
    
    glDrawBuffer(GL_BACK);

#if defined(GL) && defined(ROTATION)
    //
    // Setup for rotation and select the rendering fbo.
    if (wi->enable_rotation) {
      SetupRotationTexture(wi);
    }
#endif

    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
#if 0
    glEnable(GL_POLYGON_SMOOTH);   /*  expensive ? */
#endif

    glEnable(GL_BLEND);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glClearStencil(0);    
    color = ZnGetGradientColor(wi->back_color, 0.0, NULL);
    glClearColor((GLfloat) color->red/65536, (GLfloat) color->green/65536,
                 (GLfloat) color->blue/65536, 0.0);

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    /*
     * Init the composite group alpha.
     */
    wi->alpha = 100;
    
    /* Test if we must use damage or not */
    if (wi->usedamage) {
      if (ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)) {
         /*
         * Set the damaged area as the viewport area.
         */
         darea_x1 = (int) ZnNearestInt(wi->damaged_area.orig.x);
         darea_y1 = (int) ZnNearestInt(wi->damaged_area.orig.y);
         darea_x2 = (int) ZnNearestInt(wi->damaged_area.corner.x);
         darea_y2 = (int) ZnNearestInt(wi->damaged_area.corner.y);
      }
      else {
         darea_x1 = darea_y1 = wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0;
         darea_x2 = wi->damaged_area.corner.x = wi->width;
         darea_y2 = wi->damaged_area.corner.y = wi->height;
      }
      
    } else {
      /*
      * We do not use the damaged area set it to the whole area.
      */
      darea_x1 = darea_y1 = wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0;
      darea_x2 = wi->damaged_area.corner.x = wi->width;
      darea_y2 = wi->damaged_area.corner.y = wi->height;
   }


    //
    // glViewport and glOrtho must always be used together with
    // matching parameters to keep the mapping straight (no distorsion).
    if (wi->usedamage == 2) {
      // usedamage == 2
      glViewport(0, 0, wi->width, wi->height);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0, wi->width, wi->height, 0, -1.0, 1.0);
      glMatrixMode(GL_MODELVIEW);
    } 
    else {
      glViewport(darea_x1, wi->height - darea_y2, darea_x2 - darea_x1, darea_y2 - darea_y1);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(darea_x1, darea_x2, darea_y2, darea_y1, -1.0, 1.0);
      glMatrixMode(GL_MODELVIEW);
    }
    
    /*
     * Clear the GL buffers.
     */
    glClear(GL_STENCIL_BUFFER_BIT);

    /*
     * Use clipping if needed (optimization for non-Nvidia cards)
     */
    if (wi->usedamage == 2) {
      // Clip the damaged region
      // This point array will contain our damage mask coordinates
      ZnPoint _ptClip [ 2 ];
      // This triangle strip will contain our specific damage clipping zone.
      ZnTriStrip    tristripClip;
      _ptClip [0].x = darea_x1; 
      _ptClip [0].y = darea_y1;
      _ptClip [1].x = darea_x2;
      _ptClip [1].y = darea_y2;

      ZnTriStrip1(&tristripClip, _ptClip, 2, False);
      ZnPushClip(wi, &tristripClip, True, True);
    }


    /*
     * Setup the background tile or the background color.
     */
    if (wi->tile != ZnUnspecifiedImage) {
      ZnBBox bbox;
      
      bbox.orig.x = bbox.orig.y = 0.0;
      bbox.corner.x = wi->width;
      bbox.corner.y = wi->height;
      ZnRenderTile(wi, wi->tile, NULL, NULL, NULL, (ZnPoint *) &bbox);
    }
    else {
      color = ZnGetGradientColor(wi->back_color, 0.0, NULL);
      glColor4us(color->red, color->green, color->blue, 65535);
      glBegin(GL_QUAD_STRIP);
      glVertex2d(wi->damaged_area.orig.x, wi->damaged_area.orig.y);
      glVertex2d(wi->damaged_area.orig.x, wi->damaged_area.corner.y);
      glVertex2d(wi->damaged_area.corner.x, wi->damaged_area.orig.y);
      glVertex2d(wi->damaged_area.corner.x, wi->damaged_area.corner.y);
      glEnd();
    }

    wi->top_group->class->Render(wi->top_group);


   /*
    * Stop clipping if needed (optimizations for non-Nvidia cards)
    */
    if (wi->usedamage == 2) {
       // Stop clipping !
      ZnPopClip(wi, True);
    }

#if defined(GL) && defined(ROTATION)
    if (wi->enable_rotation) {
      FinalizeRotation(wi);
    }
#endif

    if ((wi->border_width > 0) || (wi->highlight_width > 0)) {
      unsigned short alpha;

      /* Test if we are using damage or not */
      if (wi->usedamage == 2) {
         glViewport(0, 0, wi->width, wi->height);
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         glOrtho(0.0, wi->width, wi->height, 0.0, -1.0, 1.0);
         glMatrixMode(GL_MODELVIEW);
      }
      else {
         glViewport(0, 0, wi->opt_width, wi->opt_height);
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         glOrtho(0.0, wi->opt_width, wi->opt_height, 0.0, -1.0, 1.0);
         glMatrixMode(GL_MODELVIEW);
      }

      if (wi->highlight_width > 0) {
        color = ZnGetGradientColor(ISSET(wi->flags, ZN_GOT_FOCUS)?wi->highlight_color:
                                   wi->highlight_bg_color, 0.0, &alpha);
        alpha = ZnComposeAlpha(alpha, 100);
        glColor4us(color->red, color->green, color->blue, alpha);
        
        glBegin(GL_QUAD_STRIP);
        glVertex2d(0.0, 0.0);
        glVertex2i(wi->highlight_width, wi->highlight_width);
        glVertex2i(wi->opt_width, 0);
        glVertex2i(wi->opt_width - wi->highlight_width, wi->highlight_width);
        glVertex2i(wi->opt_width, wi->opt_height);
        glVertex2i(wi->opt_width - wi->highlight_width, wi->opt_height - wi->highlight_width);
        glVertex2i(0, wi->opt_height);
        glVertex2i(wi->highlight_width, wi->opt_height - wi->highlight_width);
        glVertex2i(0, 0);
        glVertex2i(wi->highlight_width, wi->highlight_width);
        glEnd();
      }
      if (wi->border_width > 0) {
        if (wi->relief != ZN_RELIEF_FLAT) {
          p[4].x = p[4].y = p[3].y = p[1].x = wi->highlight_width;
          p[0] = p[4];
          p[3].x = p[2].x = wi->opt_width - wi->highlight_width;
          p[2].y = p[1].y = wi->opt_height - wi->highlight_width;
          ZnRenderPolygonRelief(wi, wi->relief, wi->relief_grad,
                                False, p, 5, (ZnReal) wi->border_width);
        }
        else {
          color = ZnGetGradientColor(wi->back_color, 0.0, &alpha);
          alpha = ZnComposeAlpha(alpha, 100);
          glColor4us(color->red, color->green, color->blue, alpha);
          
          glBegin(GL_QUAD_STRIP);
          glVertex2d(0.0, 0.0);
          glVertex2i(wi->highlight_width, wi->highlight_width);
          glVertex2i(wi->opt_width, 0);
          glVertex2i(wi->opt_width - wi->highlight_width, wi->highlight_width);
          glVertex2i(wi->opt_width, wi->opt_height);
          glVertex2i(wi->opt_width - wi->highlight_width, wi->opt_height - wi->highlight_width);
          glVertex2i(0, wi->opt_height);
          glVertex2i(wi->highlight_width, wi->opt_height - wi->highlight_width);
          glVertex2i(0, 0);
          glVertex2i(wi->highlight_width, wi->highlight_width);
          glEnd();
        }
      }
    }
    CLEAR(wi->flags, ZN_CONFIGURE_EVENT);

    /* Switch the GL buffers. */
#if 0
    glDisable(GL_BLEND);
    glDisable(GL_STENCIL_TEST);
    glDrawBuffer(GL_FRONT);
    glReadBuffer(GL_BACK);
    glRasterPos2i(darea_x1, darea_y2);
    glCopyPixels(darea_x1, int_height-darea_y2, darea_x2 - darea_x1, darea_y2 - darea_y1,
                 GL_COLOR);
    glFlush();
#else
    ZnGLSwapBuffers(ce, wi);
#endif

    /*
     * Wait the end of GL update if we need to synchronize
     * to monitor perfs.
     */
    if (ISSET(wi->flags, ZN_MONITORING)) {
      ZnGLWaitGL();
    }

    ZnGLReleaseContext(wi, ce);
    //STOP_PRINT("Total GL");
#endif
  }
  else {
    XRectangle  r, rs[4];
    ZnBBox      merge;

    //START;
    ClampDamageArea(wi);
    /*
m     * Merge the damaged area with the exposed area.
     */
    ZnResetBBox(&merge);
    ZnCopyBBox(&wi->damaged_area, &merge);
    ZnAddBBoxToBBox(&merge, &wi->exposed_area);
    if (!ZnIsEmptyBBox(&merge)) {
      
      /* Set the whole damaged area as clip rect. */
      wi->damaged_area.orig.x = r.x = ZnNearestInt(wi->damaged_area.orig.x);
      wi->damaged_area.orig.y = r.y = ZnNearestInt(wi->damaged_area.orig.y);
      wi->damaged_area.corner.x = ZnNearestInt(wi->damaged_area.corner.x);
      wi->damaged_area.corner.y = ZnNearestInt(wi->damaged_area.corner.y);
      r.width = (unsigned short) (wi->damaged_area.corner.x - wi->damaged_area.orig.x);
      r.height = (unsigned short) (wi->damaged_area.corner.y - wi->damaged_area.orig.y);
      p[0] = wi->damaged_area.orig;
      p[1] = wi->damaged_area.corner;
      ZnTriStrip1(&tristrip, p, 2, False);
      ZnPushClip(wi, &tristrip, True, True);
      
      /* Fill the background of the double buffer pixmap. */
      if (wi->tile == ZnUnspecifiedImage) {
        values.foreground = ZnGetGradientPixel(wi->back_color, 0.0);
        values.fill_style = FillSolid;
        XChangeGC(wi->dpy, wi->gc, GCFillStyle|GCForeground, &values);
      }
      else {
        values.fill_style = FillTiled;
        values.tile = ZnImagePixmap(wi->tile, wi->win);
        values.ts_x_origin = values.ts_y_origin = 0;
        XChangeGC(wi->dpy, wi->gc,
                  GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin,
                  &values);
      }
      XFillRectangle(wi->dpy, wi->draw_buffer, wi->gc, r.x, r.y, r.width, r.height);
      
      /* Draw the items */
      wi->top_group->class->Draw(wi->top_group);
      
      ZnPopClip(wi, True);
      
      /*
       * Send the merged area back to screen.
       */
      merge.orig.x = MAX(merge.orig.x, wi->inset);
      merge.orig.y = MAX(merge.orig.y, wi->inset);
      merge.corner.x = MIN(merge.corner.x, wi->opt_width-wi->inset);
      merge.corner.y = MIN(merge.corner.y, wi->opt_height-wi->inset);
      ZnBBox2XRect(&merge, &r);
      XCopyArea(wi->dpy,
                wi->draw_buffer, Tk_WindowId(wi->win), wi->gc,
                r.x, r.y, r.width, r.height, r.x, r.y);
    }
    
    /*
     * Redraw the borders.
     */
    if (wi->border_width > 0) {
      Pixmap      save;
      
      save = wi->draw_buffer;
      wi->draw_buffer = Tk_WindowId(wi->win);
      if (wi->relief_grad != ZN_RELIEF_FLAT) {
        r.x = r.y = wi->highlight_width;
        r.width = wi->opt_width - 2*wi->highlight_width;
        r.height = wi->opt_height - 2*wi->highlight_width;
        ZnDrawRectangleRelief(wi, wi->relief, wi->relief_grad, &r,
                              (ZnDim) wi->border_width);
      }
      else {
        XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(wi->back_color, 0.0));
        XSetFillStyle(wi->dpy, wi->gc, FillSolid);
        rs[0].x = rs[0].y = wi->highlight_width;
        rs[0].width = wi->opt_width - 2*wi->highlight_width;
        rs[0].height = wi->border_width;
        rs[1].x = wi->opt_width - wi->highlight_width - wi->border_width;
        rs[1].y = 0;
        rs[1].width = wi->border_width;
        rs[1].height = wi->opt_height - 2*wi->highlight_width;
        rs[2].x = 0;
        rs[2].y = wi->opt_height - wi->highlight_width - wi->border_width;
        rs[2].width = rs[0].width;
        rs[2].height = wi->border_width;
        rs[3].x = rs[3].y = wi->highlight_width;
        rs[3].width = wi->border_width;
        rs[3].height = rs[1].height;
        XFillRectangles(wi->dpy, Tk_WindowId(wi->win), wi->gc, rs, 4);
      }
      wi->draw_buffer = save;
    }
    if (wi->highlight_width > 0) {
      XSetForeground(wi->dpy, wi->gc,
                     ZnGetGradientPixel(ISSET(wi->flags, ZN_GOT_FOCUS)?wi->highlight_color:
                                        wi->highlight_bg_color, 0.0));
      XSetFillStyle(wi->dpy, wi->gc, FillSolid);
      rs[0].x = rs[0].y = 0;
      rs[0].width = wi->opt_width;
      rs[0].height = wi->highlight_width;
      rs[1].x = wi->opt_width - wi->highlight_width;
      rs[1].y = 0;
      rs[1].width = wi->highlight_width;
      rs[1].height = wi->opt_height;
      rs[2].x = 0;
      rs[2].y = wi->opt_height - wi->highlight_width;
      rs[2].width = wi->opt_width;
      rs[2].height = wi->highlight_width;
      rs[3].x = rs[3].y = 0;
      rs[3].width = wi->highlight_width;
      rs[3].height = wi->opt_height;
      XFillRectangles(wi->dpy, Tk_WindowId(wi->win), wi->gc, rs, 4);
    }
    //STOP_PRINT("Total GDI");
  }
}


/*
 *----------------------------------------------------------------------
 *
 * Redisplay --
 *
 *      This procedure redraws the contents of a Zinc window.
 *      It is invoked as a do-when-idle handler, so it only runs
 *      when there's nothing else for the application to do.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      Information appears on the screen.
 *
 *----------------------------------------------------------------------
 */

static void
Redisplay(ClientData client_data)       /* Information about the widget. */
{
  ZnWInfo       *wi = (ZnWInfo *) client_data;
  
  CLEAR(wi->flags, ZN_UPDATE_PENDING);
  if (ISCLEAR(wi->flags, ZN_REALIZED) || !Tk_IsMapped(wi->win)) {
    return;
  }

  if (ISSET(wi->flags, ZN_MONITORING)) {
#ifndef _WIN32
    ZnXStartChrono(wi->total_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
    ZnResetChronos(wi->this_draw_chrono);
    ZnXStartChrono(wi->this_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
#endif
  }
  
  do {
    /*
     * Update the items.
     */
    Update(wi);
    
    /*
     * Do enter/leave processing after the overlap manager
     * has finished with the items. Do it has many times
     * as needed, each round may trigger callbacks that
     * result in moved items and so forth. It can even
     * lead to the widget destruction, this is the reason
     * for Tcl_Preserve/Tcl_Release.
     */
    if (ISSET(wi->flags, ZN_INTERNAL_NEED_REPICK)) {
      Tk_Window tkwin;

      if (wi->follow_pointer) {
        Tcl_Preserve((ClientData) wi);
        CLEAR(wi->flags, ZN_INTERNAL_NEED_REPICK);
        PickCurrentItem(wi, &wi->pick_event);
        tkwin = wi->win;
        Tcl_Release((ClientData) wi);
        if (tkwin == NULL) {
          return;
        }
      }
      else if (ISCLEAR(wi->top_group->inv_flags, ZN_COORDS_FLAG) &&
               ISCLEAR(wi->top_group->inv_flags, ZN_TRANSFO_FLAG)) {
        /* Don't repick now but escape the loop if
         * the geometry is updated. */
        break;
      }
    }
  }
  while (ISSET(wi->top_group->inv_flags, ZN_COORDS_FLAG) ||
         ISSET(wi->top_group->inv_flags, ZN_TRANSFO_FLAG) ||
         ISSET(wi->flags, ZN_INTERNAL_NEED_REPICK));
  
  /*
   * Repair the scene where it is no longer up to date,
   * then send the merged area back to the screen.
   */
  Repair(wi);
  
  /*
   * Reset the exposed & damaged areas.
   */
  ZnResetBBox(&wi->exposed_area);
  ZnResetBBox(&wi->damaged_area);

  if (ISSET(wi->flags, ZN_MONITORING)) {
#ifndef _WIN32
    ZnXStopChrono(wi->total_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
    ZnXStopChrono(wi->this_draw_chrono, wi->dpy, Tk_WindowId(wi->win));
#endif
  }

  if (ISSET(wi->flags, ZN_UPDATE_SCROLLBARS)) {
    UpdateScrollbars(wi);
  }
}

#ifndef _WIN32
#  ifdef __APPLE__
#    define CALLBACK
#  else
#    define CALLBACK GLAPIENTRY
#  endif
#endif

static void CALLBACK
ZnTessBegin(GLenum      type,
            void        *data)
{
  ZnPoly        *outlines = data;
  ZnTriStrip    *tristrips = data;

  ZnListEmpty(ZnWorkPoints);
  ZnTesselator.type = type;
  if (type == GL_LINE_LOOP) {
    outlines->num_contours++;
    outlines->contours = ZnRealloc(outlines->contours,
                                   outlines->num_contours * sizeof(ZnContour));
  }
  else {
    tristrips->num_strips++;
    tristrips->strips = ZnRealloc(tristrips->strips,
                                  tristrips->num_strips * sizeof(ZnStrip));
    tristrips->strips[tristrips->num_strips-1].fan = (type==GL_TRIANGLE_FAN);
  }
  //printf("Debut de fragment de type: %s\n",
         //(type == GL_TRIANGLE_FAN) ? "FAN" : 
         //(type == GL_TRIANGLE_STRIP) ? "STRIP" :
         //(type == GL_TRIANGLES) ? "TRIANGLES" :
         //(type == GL_LINE_LOOP) ? "LINE LOOP" : "");
}

static void CALLBACK
ZnTessVertex(void       *vertex_data,
             void       *data)
{
  ZnTriStrip    *tristrips = data;
  ZnPoint       p;
  int           size;

  p.x = ((GLdouble *) vertex_data)[0];
  p.y = ((GLdouble *) vertex_data)[1];
  //printf("Sommet en %g %g\n", p.x, p.y);
  size = ZnListSize(ZnWorkPoints);
  if ((ZnTesselator.type == GL_TRIANGLES) && (size == 3)) {
    tristrips->strips[tristrips->num_strips-1].num_points = size;
    tristrips->strips[tristrips->num_strips-1].points = ZnMalloc(size * sizeof(ZnPoint));
    memcpy(tristrips->strips[tristrips->num_strips-1].points,
           ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint));
    //printf("Fin de fragment intermediaire %d, num points: %d\n", tristrips->num_strips-1, size);
    /* Allocate a new fragment */
    ZnListEmpty(ZnWorkPoints);
    tristrips->num_strips++;
    tristrips->strips = ZnRealloc(tristrips->strips,
                                    tristrips->num_strips * sizeof(ZnStrip));
    tristrips->strips[tristrips->num_strips-1].fan = False;
  }
  ZnListAdd(ZnWorkPoints, &p, ZnListTail);
}

static void CALLBACK
ZnTessEnd(void  *data)
{
  ZnPoly        *outlines = data;
  ZnTriStrip    *tristrips = data;
  unsigned int  size = ZnListSize(ZnWorkPoints);
  unsigned int  num;

  if (ZnTesselator.type == GL_LINE_LOOP) {
    /* Add the last point to close the outline */
    size++;
    num = outlines->num_contours;
    outlines->contours[num-1].num_points = size;
    outlines->contours[num-1].points = ZnMalloc(size * sizeof(ZnPoint));
    memcpy(outlines->contours[num-1].points,
           ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint));
    outlines->contours[num-1].points[size-1] = outlines->contours[num-1].points[0];
    outlines->contours[num-1].cw = !ZnTestCCW(outlines->contours[num-1].points, size);
  }
  else {
    num = tristrips->num_strips;
    tristrips->strips[num-1].num_points = size;
    tristrips->strips[num-1].points = ZnMalloc(size * sizeof(ZnPoint));
    memcpy(tristrips->strips[num-1].points,
           ZnListArray(ZnWorkPoints), size * sizeof(ZnPoint));
  }
  //printf("Fin de fragment %d, num points: %d\n", num, size);
}

static void CALLBACK
ZnTessCombine(GLdouble  coords[3],
              void      *vertex_data[4],
              GLfloat   weight[4],
              void      **out_data,
              void      *data)
{
  ZnCombineData *cdata;
  
  cdata = ZnMalloc(sizeof(ZnCombineData));
  cdata->v[0] = coords[0];
  cdata->v[1] = coords[1];
  cdata->next = ZnTesselator.combine_list;
  ZnTesselator.combine_list = cdata;
  *out_data = &cdata->v;
        ZnTesselator.combine_length++;
  //printf("Creation d'un nouveau sommet en %g %g\n",
    //cdata->v[0], cdata->v[1]);
}

static void CALLBACK
ZnTessError(GLenum      errno,
            void        *data)
{
  fprintf(stderr, "Tesselation error in curve item: %d\n", errno);
}


static void
InitZinc(Tcl_Interp *interp) {
  static ZnBool inited = False;
  unsigned int  i, x, y, bit;
  char          name[TCL_INTEGER_SPACE + 20];
  
  if (inited) {
    return;
  }
  
  /*
   * Add the specific bitmaps.
   */
  for (i = 0; i < sizeof(SYMBOLS_BITS)/(SYMBOL_WIDTH*SYMBOL_HEIGHT/8); i++) {
    sprintf(name, "AtcSymbol%d", i+1);
    Tk_DefineBitmap(interp, Tk_GetUid(name),
                    SYMBOLS_BITS[i], SYMBOL_WIDTH, SYMBOL_HEIGHT);
  }
  
  for (i = 0; i < ZN_NUM_ALPHA_STEPS; i++) {
    for (y = 0; y < 4; y++) {
      bitmaps[i][y][0] = 0;
      for (x = 0; x < 4; x++) {
        /*
         * Use the dither4x4 matrix to determine if this bit is on
         */
        bit = (i >= dither4x4[y][x]) ? 1 : 0;
        /*
         * set the bit in the array used to make the X Bitmap
         * mirror the pattern in x & y to make an 8x8 bitmap.
         */
        if (bit) {
          bitmaps[i][y][0] |= (1 << x);
          bitmaps[i][y][0] |= (1 << (4 + x));
        } 
      }
      bitmaps[i][y][1] = bitmaps[i][y][2] = bitmaps[i][y][3] = bitmaps[i][y][0];
      bitmaps[i][y+4][0] = bitmaps[i][y+4][1] = bitmaps[i][y][0];
      bitmaps[i][y+4][2] = bitmaps[i][y+4][3] = bitmaps[i][y][0];
      bitmaps[i][y+8][0] = bitmaps[i][y+8][1] = bitmaps[i][y][0];
      bitmaps[i][y+8][2] = bitmaps[i][y+8][3] = bitmaps[i][y][0];
      bitmaps[i][y+12][0] = bitmaps[i][y+12][1] = bitmaps[i][y][0];
      bitmaps[i][y+12][2] = bitmaps[i][y+12][3] = bitmaps[i][y][0];
      bitmaps[i][y+16][0] = bitmaps[i][y+16][1] = bitmaps[i][y][0];
      bitmaps[i][y+16][2] = bitmaps[i][y+16][3] = bitmaps[i][y][0];
      bitmaps[i][y+20][0] = bitmaps[i][y+20][1] = bitmaps[i][y][0];
      bitmaps[i][y+20][2] = bitmaps[i][y+20][3] = bitmaps[i][y][0];
      bitmaps[i][y+24][0] = bitmaps[i][y+24][1] = bitmaps[i][y][0];
      bitmaps[i][y+24][2] = bitmaps[i][y+24][3] = bitmaps[i][y][0];
      bitmaps[i][y+28][0] = bitmaps[i][y+28][1] = bitmaps[i][y][0];
      bitmaps[i][y+28][2] = bitmaps[i][y+28][3] = bitmaps[i][y][0];
    }
    sprintf(name, "AlphaStipple%d", i);
    Tk_DefineBitmap(interp, Tk_GetUid(name), (char *) bitmaps[i], 32, 32);
  }

  /*
   * Initialize the temporary lists.
   */
  ZnWorkPoints = ZnListNew(8, sizeof(ZnPoint));
  ZnWorkXPoints = ZnListNew(8, sizeof(XPoint));
  ZnWorkStrings = ZnListNew(8, sizeof(char *));
  
  /*
   * Allocate a GLU tesselator.
   */
  ZnTesselator.tess = gluNewTess();
  ZnTesselator.combine_list = NULL;
        ZnTesselator.combine_length = 0;
  gluTessCallback(ZnTesselator.tess, GLU_TESS_BEGIN_DATA,
                  (_GLUfuncptr) ZnTessBegin);
  gluTessCallback(ZnTesselator.tess, GLU_TESS_VERTEX_DATA,
                  (_GLUfuncptr) ZnTessVertex);
  gluTessCallback(ZnTesselator.tess, GLU_TESS_END_DATA,
                  (_GLUfuncptr) ZnTessEnd);
  gluTessCallback(ZnTesselator.tess, GLU_TESS_COMBINE_DATA,
                  (_GLUfuncptr) ZnTessCombine);
  gluTessCallback(ZnTesselator.tess, GLU_TESS_ERROR_DATA,
                  (_GLUfuncptr) ZnTessError);
  gluTessNormal(ZnTesselator.tess, 0.0, 0.0, -1.0);

  /*
   * Initialize the item module.
   */
  ZnItemInit();
  
  all_uid = Tk_GetUid("all");
  current_uid = Tk_GetUid("current");  
  and_uid = Tk_GetUid("&&");
  or_uid = Tk_GetUid("||");
  xor_uid = Tk_GetUid("^");
  paren_uid = Tk_GetUid("(");
  end_paren_uid = Tk_GetUid(")");
  neg_paren_uid = Tk_GetUid("!(");
  tag_val_uid = Tk_GetUid("!!");
  neg_tag_val_uid = Tk_GetUid("!");
  dot_uid = Tk_GetUid(".");
  star_uid = Tk_GetUid("*");

  /*
   * Initialise Overlap manager library.
   */
#ifdef ATC
  OmInit();
#endif

  inited = True;
}

#ifdef BUILD_Tkzinc
#   undef TCL_STORAGE_CLASS
#   define TCL_STORAGE_CLASS DLLEXPORT
#endif

/*
 *----------------------------------------------------------------------
 *
 * Tkzinc_Init --
 *
 *      This procedure is invoked by Tcl_AppInit in tkAppInit.c to
 *      initialize the widget.
 *
 *----------------------------------------------------------------------
 */
EXTERN int
Tkzinc_Init(Tcl_Interp *interp) /* Used for error reporting. */
{
#ifndef PTK
  if (
# ifdef USE_TCL_STUBS
      Tcl_InitStubs(interp, "8.4", 0)
# else
      Tcl_PkgRequire(interp, "Tcl", "8.4", 0)
# endif
      == NULL) {
    return TCL_ERROR;
  }

  if (
# ifdef USE_TK_STUBS
      Tk_InitStubs(interp, "8.4", 0)
# else
      Tcl_PkgRequire(interp, "Tk", "8.4", 0)
# endif
      == NULL) {
    return TCL_ERROR;
  }
#endif
  /*
   * Create additional commands
   */
  Tcl_CreateObjCommand(interp, "zinc", ZincObjCmd,
                       (ClientData) Tk_MainWindow(interp),
                       (Tcl_CmdDeleteProc *) NULL);
#ifdef ATC
  Tcl_CreateObjCommand(interp, "mapinfo", ZnMapInfoObjCmd,
                       (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
  Tcl_CreateObjCommand(interp, "videomap", ZnVideomapObjCmd,
                       (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
#endif
    
#ifndef PTK
  if (Tcl_PkgProvide(interp, "Tkzinc", PACKAGE_VERSION) == TCL_ERROR) {
    return TCL_ERROR;
  }
#endif

  return TCL_OK;
}

EXTERN int
Tkzinc_SafeInit(Tcl_Interp *interp)   /* Used for error reporting. */
{
  return Tkzinc_Init(interp);
}

EXTERN int
Tkzinc_debug_Init(Tcl_Interp *interp)   /* Used for error reporting. */
{
  return Tkzinc_Init(interp);
}

#ifdef _WIN32
/*
 *----------------------------------------------------------------------
 *
 * DllEntryPoint --
 *
 *      This wrapper function is used by Windows to invoke the
 *      initialization code for the DLL.  If we are compiling
 *      with Visual C++, this routine will be renamed to DllMain.
 *      routine.
 *
 * Results:
 *      Returns TRUE;
 *
 * Side effects:
 *      None.
 *
 *----------------------------------------------------------------------
 */
BOOL APIENTRY
DllEntryPoint(HINSTANCE hInst,     /* Library instance handle. */
              DWORD     reason,   /* Reason this function is being called. */
              LPVOID    reserved) /* Not used. */
{
    return TRUE;
}
#endif

Added jni/tkzinc/generic/tkZinc.h.





















































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
 * tkZinc.h -- Header file for Tk zinc widget.
 *
 * Authors              : Patrick Lecoanet.
 * Creation date        : Mon Mar 15 14:02:03 1999
 *
 * $Id$
 */

/*
 *  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */


#ifndef _tkZinc_h
#define _tkZinc_h

#include "WidgetInfo.h"
#include "Item.h"
#include "List.h"
#include "MapInfo.h"

#if defined(MAC_OSX_TK)
  #include <AGL/glu.h>
#elif defined(__APPLE__)
  #include <OpenGL/glu.h>
#else
  #include <GL/glu.h>
#endif

typedef struct _ZnTagSearch {
  ZnWInfo       *wi;
  ZnItem        current;        /* Pointer to last item returned. */
  ZnItem        previous;       /* The item right before the current
                                 * is tracked so if the current is
                                 * deleted we don't have to start from the
                                 * beginning. */
  ZnBool        over;           /* Non-zero means NextItem should always
                                 * return NULL. */
  int           type;           /* search type */
  unsigned int  id;             /* item id for searches by id */

  Tk_Uid        tag;            /* tag expression string */
  int           tag_index;      /* current position in string scan */
  int           tag_len;        /* length of tag expression string */

  char          *rewrite_buf;   /* tag string (after removing escapes) */
  unsigned int  rewrite_buf_alloc;      /* available space for rewrites */

  struct _TagSearchExpr *expr;  /* compiled tag expression */
  ZnItem        group;
  ZnBool        recursive;
  ZnList        item_stack;
} ZnTagSearch;

/*
 * Structure used by the tesselator.
 */
typedef struct _ZnCombineData {
  ZnReal                v[2];
  struct _ZnCombineData *next;
} ZnCombineData;

typedef struct _ZnTess {
  GLUtesselator *tess;
  ZnCombineData *combine_list;
  int           type;
        int   combine_length;
} ZnTess;

extern ZnList      ZnWorkPoints;
extern ZnList      ZnWorkXPoints;
extern ZnList      ZnWorkStrings;
extern ZnTess      ZnTesselator;

#ifdef GL
typedef struct _ZnGLContextEntry {
  ZnGLContext   context;
  Display       *dpy;
  ZnReal        max_line_width;
  ZnReal        max_point_width;
  unsigned int  max_tex_size;
  ZnList        widgets;
#ifndef PLATFORM_SDL
#ifdef _WIN32
  PIXELFORMATDESCRIPTOR pfd;
  int           ipixel;
  HWND          hwnd;   /* Temporary storage between MakeCurrent and Release */
  HDC           hdc;
#elif defined(__APPLE__)
  AGLPixelFormat pix_fmt;
  GWorldPtr     gworld;
  Tk_Window     top_win;
#else
  XVisualInfo   *visual; /* Should these two be managed by screen ? */
  Colormap      colormap;
#endif
#endif
  struct _ZnGLContextEntry *next;
} ZnGLContextEntry;

ZnGLContextEntry *ZnGetGLContext(Display *dpy);
ZnGLContextEntry *ZnGLMakeCurrent(Display *dpy, ZnWInfo *wi);
void ZnGLReleaseContext(ZnWInfo *wi, ZnGLContextEntry *ce);
#endif

int ZnParseCoordList(ZnWInfo *wi, Tcl_Obj *arg, ZnPoint **pts,
                     char **controls, unsigned int *num_pts, ZnBool *old_format);
int ZnItemWithTagOrId(ZnWInfo *wi, Tcl_Obj *tag_or_id,
                      ZnItem *item, ZnTagSearch **search_var);
void ZnTagSearchDestroy(ZnTagSearch *search);
void ZnDoItem(Tcl_Interp *interp, ZnItem item, int part, Tk_Uid tag_uid);
void ZnNeedRedisplay(ZnWInfo *wi);
void ZnDamage(ZnWInfo *wi, ZnBBox *damage);
void ZnDamageAll(ZnWInfo *wi);


#endif /* _tkZinc_h */

Added jni/tkzinc/library/pkgIndex.tcl.



























>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

package ifneeded zincText 1.0 [list source [file join $dir zincText.tcl]]
package ifneeded zincLogo 1.0 [list source [file join $dir zincLogo.tcl]]
package ifneeded zincGraphics 1.0 [list source [file join $dir zincGraphics.tcl]]

Added jni/tkzinc/library/zincGraphics.tcl.





















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
#
#-----------------------------------------------------------------------------------
#
#      Graphics.tcl
#      some graphic design functions
#
#-----------------------------------------------------------------------------------
#  Functions to create complexe graphic component :
#  ------------------------------------------------
#      BuildZincItem          (realize a zinc item from description hash table)
#
#  Function to compute complexe geometrical forms :
#  (text header of functions explain options for each form,
#  function return curve coords using control points of cubic curve)
#  -----------------------------------------------------------------
#      RoundedRectangleCoords (return curve coords of rounded rectangle)
#      HippodromeCoords       (return curve coords of circus form)
#      PolygonCoords          (return curve coords of regular polygon)
#      RoundedCurveCoords     (return curve coords of rounded curve)
#      PolylineCoords         (return curve coords of polyline)
#      TabBoxCoords           (return curve coords of tabBox's pages)
#      PathLineCoords         (return triangles coords of pathline)
#
#  Geometrical basic Functions :
#  -----------------------------
#      PerpendicularPoint
#      LineAngle
#      VertexAngle
#      ArcPts
#      RadPoint
#
#  Pictorial Functions  :
#  ----------------------
#      SetGradients
#      GetPattern
#      GetTexture
#      GetImage
#      InitPixmaps
#      HexaRGBcolor
#      CreateGraduate
#
#-----------------------------------------------------------------------------------
#      Authors: Jean-Luc Vinot <vinot@cena.fr>
#		Patrick Lecoanet <lecoanet@cena.fr> (Straight translation
#		to Tcl, based on Graphics.pm revision 1.9)
# $Id: 
#-----------------------------------------------------------------------------------

namespace eval ::zincGraphics {

  package provide zincGraphics 1.0

  namespace export BuildZincItem RoundedRectangleCoords HippodromeCoords \
    PolygonCoords RoundedCurveCoords PolylineCoords TabBoxCoords PathLineCoords \
    PerpendicularPoint SetGradients GetPattern GetTexture GetImage InitPixmaps \
    HexaRGBcolor CreateGraduate

  namespace eval v {
    # constante facteur point directeur
    variable constPtdFactor 0.5523
    variable Gradients {}
    variable textures {}
    variable images {}
    variable bitmaps {}
    variable pi 3.14159
  }

  if { ![info exists zinc_library] } {
    set zinc_library [file dirname [info script]]
  }
  
  set imagePath [file join $zinc_library .. demos images]

  proc deg2rad {angle} {
    return [expr {$angle * $v::pi / 180.0}]
  }
  
  proc TLGet {list tag {default ""}} {
    foreach {key val} $list {
      if { [string compare $key $tag] == 0 } {
	return $val
      }
    }
    return $default
  }

  #proc TLGet {assoc tag {default ""}} {
    #    array set temp $assoc
    #    if { [info exists temp($tag)] } {
      #	return $temp($tag)
    #    }
    #    return $default
  #}

  proc PointX {point} {
    return [lindex $point 0]
  }

  proc PointY {point} {
    return [lindex $point 1]
  }

  #-----------------------------------------------------------------------------------
  # Graphics::BuildZincItem
  # Création d'un objet Zinc de représentation
  # paramètres :
  # widget : <widget>
  # parentGroup : <group>
  # style : {hash table options}
  # specificTags : [list of specific tags] to add to params -tags
  # name : <str> nom de l'item
  #-----------------------------------------------------------------------------------
  # type d'item valide :
  # les items natifs zinc : group, rectangle, arc, curve, text, icon
  # les items ci-après permettent de spécifier des curves 'particulières' :
  # -roundedrectangle : rectangle à coin arrondi
  #       -hippodrome : hippodrome
  #         -polygone : polygone régulier à n cotés (convexe ou en étoile)
  #     -roundedcurve : curve multicontours à coins arrondis (rayon unique)
  #         -polyline : curve multicontours à coins arrondis (le rayon pouvant être défini 
  #                     spécifiquement pour chaque sommet)
  #         -pathline : création d'une ligne 'épaisse' avec l'item Zinc triangles
  #                     décalage par rapport à un chemin donné (largeur et sens de décalage)
  #                     dégradé de couleurs de la ligne (linéaire, transversal ou double)
  #-----------------------------------------------------------------------------------
  proc BuildZincItem {zinc parentGroup styleTL specificTags name} {
    array set style $styleTL
    if { [info exists style(-params)] } {
      array set params $style(-params)
    }

    if { ! $parentGroup } {
      set parentGroup 1
    }

    if { [llength $specificTags] } {
      if { [info exists params(-tags)] } {
	set params(-tags) [concat $specificTags $params(-tags)]
      } else {
	set params(-tags) $specificTags
      }
    }

    set itemType $style(-itemtype)
    set coords {}
    if { [info exists style(-coords)] } {
     set coords $style(-coords)
    }
    # gestion des polygones particuliers et à coin arrondi
    switch -- $itemType { 
      roundedrectangle {
	set itemType curve
	set params(-closed) 1
	set coords [RoundedRectangleCoords $coords $styleTL]
      }
      hippodrome {
	set itemType curve
	set params(-closed) 1
	set coords [HippodromeCoords $coords $styleTL]
      }
      polygone {
	set itemType curve
	set params(-closed) 1
	set coords [PolygonCoords $coords $styleTL]
      }
      roundedcurve -
      polyline {
	set itemType curve
	if { $itemType eq "roundedcurve" } {
	  set params(-closed) 1
	  set coords [RoundedCurveCoords $coords $styleTL]
	} else {
	  set coords [PolylineCoords $coords $styleTL]
	}
	#
	# multi-contours
	if { [info exists style(-contours)] } {
	  set contours $style(-contours)
	  set numContours [llength $contours]
	  for {set i 0} {$i < $numContours} {incr i} {
	    # radius et corners peuvent être défini spécifiquement
	    # pour chaque contour
	    foreach {type way inCoords radius corners cornersRadius} \
	      [lindex $contours $i] break

	    if { $radius eq "" } {
	      set radius $style(-radius)
	    }
	    if { $itemType eq "roundedcurve" } {
	      set newCoords [RoundedCurveCoords $inCoords [list -radius $radius \
							       -corners $corners]]
	    } else {
	      set newCoords [PolylineCoords $inCoords \
				 [list -radius $radius -corners $corners \
				      -cornersradius $cornersRadius]]
	    }
	    lset style(-contours) $i [list $type $way $newCoords]
	  }
	}
      }
      pathline {
	set itemType triangles
	if { [info exists style(-metacoords)] } {
	  set coords [MetaCoords $style(-metacoords)]
	}

	if { [info exists style(-graduate)] } {
	  set numColors [llength $coords]
	  set params(-colors) [PathGraduate $numColors $style(-graduate)]
	}
	set coords [PathLineCoords $coords $styleTL]
      }
    }

    switch -- $itemType {
      group {
	  set item [eval {$zinc add $itemType $parentGroup} [array get params]]
	if { [llength $coords] } {
	  $zinc coords $item $coords
	}

      }
      text -
      icon {
	set imageFile ""
	if { $itemType eq "icon" } {
	  set imageFile $params(-image)
	  if { $imageFile ne "" } {
	    set params(-image) [InitPixmap $imageFile]
	  }
	}

	  set item [eval {$zinc add $itemType $parentGroup -position $coords} [array get params]]
	if { $imageFile ne "" } {
	  set params(-image) $imageFile
	}
      }
      default {
	set item [eval {$zinc add $itemType $parentGroup $coords} [array get params]]
	if { $itemType eq "curve" && [info exists style(-contours)] } {
	  foreach contour $style(-contours) {
	    eval $zinc contour $item $contour
	  }
	}

	# gestion du mode norender
	if { [info exists style(-texture)] } {
	  set texture [GetTexture $style(-texture)]
	  if { $texture ne "" } {
	    $zinc itemconfigure $item -tile $texture
	  }
	}

	if { [info exists style(-fillpattern)] } {
	  set bitmap [GetBitmap $style(-fillpattern)]
	  if { $bitmap ne "" } {
	    $zinc itemconfigure $item -fillpattern $bitmap
	  }
	}
      }
    }

    # transformation scale de l'item si nécessaire
    if { [info exists style(-scale)] } {
      $zinc scale $item $style(-scale)
    }

    # transformation rotate de l'item si nécessaire
    if { [info exists style(-rotate)] } {
      $zinc rotate $item [deg2rad $style(-rotate)]
    }
    # transformation scale de l'item si nécessaire
    if { [info exists style(-translate)] } {
      $zinc translate $item $style(-translate)
    }

    return $item
  }

  #-----------------------------------------------------------------------------------
  # FONCTIONS GEOMETRIQUES
  #-----------------------------------------------------------------------------------

  #-----------------------------------------------------------------------------------
  # Graphics::MetaCoords
  # retourne une liste de coordonnées en utilisant la fonction d'un autre type d'item
  # paramètres : (options)
  #   -type : type de primitive utilisée
  # -coords : coordonnées nécessitée par la fonction [type]Coords
  #  + options spécialisées passés à la fonction [type]Coords
  #-----------------------------------------------------------------------------------
  proc MetaCoords {options} {
    set pts {}
    set type [TLGet $options -type]
    set coords [TLGet $options -coords]

    switch -- $type {
      polygone {
	set pts [PolygonCoords $coords $options]
      }
      hippodrome {
	set pts [HippodromeCoords $coords $options]
      }
      polyline {
	set pts [PolylineCoords $coords $options]
      }
    }

    return $pts
  }

  #-----------------------------------------------------------------------------------
  # Graphics::RoundedRectangleCoords
  # calcul des coords du rectangle à coins arrondis
  # paramètres :
  # coords : point centre du polygone
  # options :
  #  -radius : rayon de raccord d'angle
  # -corners : liste des raccords de sommets [0 (aucun raccord)|1] par défaut [1,1,1,1]
  #-----------------------------------------------------------------------------------
  proc RoundedRectangleCoords {coords optionsTL} {
    foreach {p0 p1} $coords break
    foreach {x0 y0} $p0 break
    foreach {xn yn} $p1 break

    set radius [TLGet $optionsTL -radius]
    set corners [TLGet $optionsTL -corners]
    if { [llength $corners] == 0 } {
      set corners [list 1 1 1 1]
    }

    # attention aux formes 'négatives'
    if { $xn < $x0 } {
      set xs $x0
      set x0 $xn
      set xn $xs
    }
    if { $yn < $y0 } {
      set ys $y0
      set y0 $yn
      set yn $ys
    }

    set height [_min [expr {$xn - $x0}] [expr {$yn - $y0}]]

    if { $radius eq "" } {
      set radius [expr {int($height/10.0)}]
      if { $radius < 3 } {
	set radius 3
      }
    }

    if { $radius < 2 } {
      return [list [list $x0 $y0] [list $x0 $yn] \
	[list $xn $yn] [list $xn $y0]]
    }


    # correction de radius si necessaire
    set maxRad $height
    if { $corners eq "" } {
      set maxRad [expr {$maxRad / 2.0}]
    }
    if { $radius > $maxRad } {
      set radius $maxRad
    }

    # points remarquables
    set ptdDelta [expr {$radius * $v::constPtdFactor}]
    set x2 [expr {$x0 + $radius}]
    set x3 [expr {$xn - $radius}]
    set x1 [expr {$x2 - $ptdDelta}]
    set x4 [expr {$x3 + $ptdDelta}]
    set y2 [expr {$y0 + $radius}]
    set y3 [expr {$yn - $radius}]
    set y1 [expr {$y2 - $ptdDelta}]
    set y4 [expr {$y3 + $ptdDelta}]

    # liste des 4 points sommet du rectangle : angles sans raccord circulaire
    set anglePts [list [list $x0 $y0] [list $x0 $yn] \
      [list $xn $yn] [list $xn $y0]]

    # liste des 4 segments quadratique : raccord d'angle = radius
    set roundeds [list \
	[list [list $x2 $y0] [list $x1 $y0 c] \
	      [list $x0 $y1 c] [list $x0 $y2]] \
        [list [list $x0 $y3] [list $x0 $y4 c] \
              [list $x1 $yn c] [list $x2 $yn]] \
        [list [list $x3 $yn] [list $x4 $yn c] \
              [list $xn $y4 c] [list $xn $y3]] \
        [list [list $xn $y2] [list $xn $y1 c] \
              [list $x4 $y0 c] [list $x3 $y0]]]

    set pts [list]
    set previous 0
    foreach seg $roundeds aPt $anglePts corner $corners {
      set px 0
      set py 0
      if { $corner } {
	# on teste si non duplication de point
	foreach {nx ny} [lindex $seg 0] break
	if { $previous && ($px == $nx && $py == $ny) } {
	  eval lappend pts [lrange $seg 1 end]
	} else {
	  eval lappend pts $seg
	}
	foreach {px py} [lindex $seg 3] break
	set previous 1
      } else {
	lappend pts $aPt
      }
    }
    return $pts
  }

  #-----------------------------------------------------------------------------------
  # Graphics::HippodromeCoords
  # calcul des coords d'un hippodrome
  # paramètres :
  # coords : coordonnées du rectangle exinscrit
  # options :
  # -orientation : orientation forcée de l'ippodrome [horizontal|vertical]
  #     -corners : liste des raccords de sommets [0|1] par défaut [1,1,1,1]
  #       -trunc : troncatures [left|right|top|bottom|both]
  #-----------------------------------------------------------------------------------
  proc HippodromeCoords {coords optionsTL} {
    foreach {p0 p1} $coords break
    foreach {x0 y0} $p0 break
    foreach {xn yn} $p1 break

    set orientation [TLGet $optionsTL -orientation none]

    # orientation forcée de l'hippodrome (sinon hippodrome sur le plus petit coté)
    switch -- $orientation {
      horizontal { set height [expr {abs($yn - $y0)}] }
      vertical { set height [expr {abs($xn - $x0)}] }
      default { set height [_min [expr {abs($xn - $x0)}] [expr {abs($yn - $y0)}]] }
    }

    set radius [expr {$height/2.0}]

    set corners [TLGet $optionsTL -corners]
    set trunc [TLGet $optionsTL -trunc]
    if { [llength $corners] == 0 } {
      switch -- $trunc {
	both { return [list [list $x0 $y0] [list $x0 $yn] \
	  [list $xn $yn] [list $xn $y0]] }
	left { set corners [list 0 0 1 1] }
	right { set corners [list 1 1 0 0] }
	top { set corners [list 0 1 1 0] }
	bottom { set corners [list 1 0 0 1] }
	default { set corners [list 1 1 1 1] }
      }
    }

    # l'hippodrome est un cas particulier de roundedRectangle
    # on retourne en passant la 'configuration' à la fonction
    # générique roundedRectangleCoords
    return [RoundedRectangleCoords $coords [list -radius [expr {$height/2.0}] -corners $corners]]
  }


  #-----------------------------------------------------------------------------------
  # Graphics::PolygonCoords
  # calcul des coords d'un polygone régulier
  # paramètres :
  # coords : point centre du polygone
  # options :
  #      -numsides : nombre de cotés
  #        -radius : rayon de définition du polygone (distance centre-sommets)
  #  -innerradius : rayon interne (polygone type étoile)
  #       -corners : liste des raccords de sommets [0|1] par défaut [1,1,1,1]
  # -cornerradius : rayon de raccord des cotés
  #    -startangle : angle de départ du polygone
  #-----------------------------------------------------------------------------------
  proc PolygonCoords {coords optionsTL} {
    set numSides [TLGet $optionsTL -numsides 0]
    set radius [TLGet $optionsTL -radius 0]
    if { $numSides < 3 || !$radius } {
      puts "Vous devez au moins spécifier un nombre de cotés >= 3 et un rayon..."
      return {};
    }

    if { [llength $coords] } {
      foreach {cx cy} $coords break
    } else {
      set cx 0
      set cy 0
    }

    set startAngle [TLGet $optionsTL -startangle 0]
    set angleStep [expr {360.0/$numSides}]
    set innerRadius [TLGet $optionsTL -innerradius 0]
    set pts [list]

    # points du polygone
    for {set i 0} {$i < $numSides} {incr i} {
      set p [RadPoint $cx $cy $radius [expr {$startAngle + ($angleStep*$i)}]]
      lappend pts $p

      # polygones 'étoiles'
      if { $innerRadius } {
	set p [RadPoint $cx $cy $innerRadius [expr {$startAngle + ($angleStep*($i+ 0.5))}]]
	lappend pts $p
      }
    }

    set cornerRadius [TLGet $optionsTL -cornerradius {}]
    if { $cornerRadius ne "" } {
      set pts [RoundedCurveCoords $pts [list -radius $cornerRadius -corners \
					    [TLGet $optionsTL -corners {}]]]
    }
    return $pts
  }

  #-----------------------------------------------------------------------------------
  # Graphics::RoundedAngle
  # THIS FUNCTION IS NO MORE USED, NEITHER EXPORTED
  # curve d'angle avec raccord circulaire
  # paramètres :
  # zinc : widget
  # parentGroup : group zinc parent
  # coords : les 3 points de l'angle
  # radius : rayon de raccord
  #-----------------------------------------------------------------------------------
  proc RoundedAngle {zinc parentGroup coords radius} {
    foreach {pt0 pt1 pt2} $coords break

    foreach {cornerPts centerPts} [RoundedAngleCoords $coords $radius] break
    foreach {cx0 cy0} $centerPts break

    # valeur d'angle et angle formé par la bisectrice
    # set angle [VertexAngle $pt0 $pt1 $pt2]

    if { $parentGroup eq "" } {
      set parentGroup 1
    }

    set cornerPts [linsert $cornerPts 0 $pt0]
    lappend cornerPts $pt2
    $zinc add curve $parentGroup $cornerPts -closed 0 -linewidth 1 -priority 20
  }

  #-----------------------------------------------------------------------------------
  # Graphics::RoundedAngleCoords
  # calcul des coords d'un raccord d'angle circulaire
  #-----------------------------------------------------------------------------------
  # le raccord circulaire de 2 droites sécantes est traditionnellement réalisé par un
  # arc (conique) du cercle inscrit de rayon radius tangent à ces 2 droites
  #
  # Quadratique :
  # une approche de cette courbe peut être réalisée simplement par le calcul de 4 points
  # spécifiques qui définiront - quelle que soit la valeur de l'angle formé par les 2
  # droites - le segment de raccord :
  # - les 2 points de tangence au cercle inscrit seront les points de début et de fin
  # du segment de raccord
  # - les 2 points de controle seront situés chacun sur le vecteur reliant le point de
  # tangence au sommet de l'angle (point secant des 2 droites)
  # leur position sur ce vecteur peut être simplifiée comme suit :
  # - à un facteur de 0.5523 de la distance au sommet pour un angle >= 90° et <= 270°
  # - à une 'réduction' de ce point vers le point de tangence pour les angles limites
  # de 90° vers 0° et de 270° vers 360°
  # ce facteur sera légérement modulé pour recouvrir plus précisement l'arc correspondant
  #-----------------------------------------------------------------------------------
  proc RoundedAngleCoords {coords radius} {
    foreach {pt0 pt1 pt2} $coords break
    foreach {pt1x pt1y} $pt1 break
    
    # valeur d'angle et angle formé par la bisectrice
    foreach {angle bisecAngle} [VertexAngle $pt0 $pt1 $pt2] break

    # distance au centre du cercle inscrit : rayon/sinus demi-angle
    set sin [expr {sin([deg2rad $angle] / 2.0)}]
    set delta [expr {$sin ? abs($radius / $sin) : $radius}]

    # point centre du cercle inscrit de rayon $radius
    set refAngle [expr {($angle < 180) ? $bisecAngle+90 : $bisecAngle-90}]
    set c0 [RadPoint $pt1x $pt1y $delta $refAngle]

    # points de tangeance : pts perpendiculaires du centre aux 2 droites
    set p1 [PerpendicularPoint $c0 [list $pt0 $pt1]]
    set p2 [PerpendicularPoint $c0 [list $pt1 $pt2]]
    foreach {p1x p1y} $p1 break
    foreach {p2x p2y} $p2 break

    # point de controle de la quadratique
    # facteur de positionnement sur le vecteur pt.tangence, sommet
    set ptdFactor $v::constPtdFactor
    if { $angle < 90 || $angle > 270 } {
      set diffAngle [expr {($angle < 90) ? $angle : 360 - $angle}]
      if { $diffAngle > 15 } {
	set ptdFactor [expr {$ptdFactor - (((90.0 - $diffAngle)/90.0) * ($ptdFactor/4.0))}]
      }
      set ptdFactor [expr {($diffAngle/90.0) * \
	  ($ptdFactor + ((1.0 - $ptdFactor) * (90.0 - $diffAngle)/90.0))}]
    } else {
      set diffAngle [expr {abs(180.0 - $angle)}]
      if { $diffAngle > 15 } {
	set ptdFactor [expr {$ptdFactor + (((90.0 - $diffAngle)/90.0) * ($ptdFactor/3.0))}]
      }
    }

    # delta xy aux pts de tangence
    set d1x [expr {($pt1x - $p1x) * $ptdFactor}]
    set d1y [expr {($pt1y - $p1y) * $ptdFactor}]
    set d2x [expr {($pt1x - $p2x) * $ptdFactor}]
    set d2y [expr {($pt1y - $p2y) * $ptdFactor}]

    # les 4 points de l'arc 'quadratique' et le centre du cercle inscrit
    set cornerPts [list $p1 \
		       [list [expr {$p1x + $d1x}] [expr {$p1y + $d1y}] c] \
		       [list [expr {$p2x + $d2x}] [expr {$p2y + $d2y}] c] \
		       $p2]

    return [list $cornerPts $c0]
  }

  #-----------------------------------------------------------------------------------
  # Graphics::RoundedCurveCoords
  # retourne les coordonnées d'une curve à coins arrondis
  # paramètres :
  # coords : points de la curve
  # options :
  #  -radius : rayon de raccord d'angle
  # -corners : liste des raccords de sommets [0|1] par défaut [1,1,1,1]
  #-----------------------------------------------------------------------------------
  proc RoundedCurveCoords {coords options} {
    set numFaces [llength $coords]
    set curvePts {}
    set radius [TLGet $options -radius 0]
    set corners [TLGet $options -corners {}]

    for {set index 0} {$index < $numFaces} {incr index} {
      if { ([llength $corners] > $index) && ([lindex $corners $index] == 0) } {
	lappend curvePts [lindex $coords $index]
      } else {
	set prev [expr {$index ? $index - 1 : $numFaces - 1}]
	set next [expr {($index > $numFaces - 2) ? 0 : $index + 1}]
	set angleCoords [list [lindex $coords $prev] \
			     [lindex $coords $index] \
			     [lindex $coords $next]]
	foreach {quadPts centerPts} [RoundedAngleCoords $angleCoords $radius] break
	set curvePts [concat $curvePts $quadPts]
      }
    }
    return $curvePts
  }

  #-----------------------------------------------------------------------------------
  # Graphics::PolylineCoords
  # retourne les coordonnées d'une polyline
  # paramètres :
  # coords : sommets de la polyline
  # options :
  #        -radius : rayon global de raccord d'angle
  #       -corners : liste des raccords de sommets [0|1] par défaut [1,1,1,1],
  # -cornersradius : liste des rayons de raccords de sommets
  #-----------------------------------------------------------------------------------
  proc PolylineCoords {coords options} {
    set numFaces [llength $coords]
    set curvePts {}

    set radius [TLGet $options -radius 0]
    set cornersRadius [TLGet $options -cornersradius]

    if { [llength $cornersRadius] } {
      set corners $cornersRadius
    } else {
      set corners [TLGet $options -corners]
    }

    set numCorners [llength $corners]
    for {set index 0} {$index < $numFaces} {incr index} {
      if { $numCorners && (($index >= $numCorners) || ![lindex $corners $index]) } {
	foreach {x y} [lindex $coords $index] { lappend curvePts [list $x $y] }
      } else {
	set prev [expr {$index ? $index - 1 : $numFaces - 1}]
	set next [expr {($index > $numFaces - 2) ? 0 : $index + 1}]
	set angleCoords [list [lindex $coords $prev] [lindex $coords $index] \
			     [lindex $coords $next]]

        if { [llength $cornersRadius] } {
	  set rad [lindex $cornersRadius $index]
	} else {
	  set rad $radius
	}
	foreach {cornerPts centerPts} [RoundedAngleCoords $angleCoords $rad] break
	set curvePts [concat $curvePts $cornerPts]
      }
    }

    return $curvePts
  }

  #-----------------------------------------------------------------------------------
  # Graphics::PathLineCoords
  # retourne les coordonnées d'une pathLine
  # paramètres :
  # coords : points de path
  # options :
  #    -closed : ligne fermée
  #  -shifting : sens de décalage [both|left|right] par défaut both
  # -linewidth : epaisseur de la ligne
  #-----------------------------------------------------------------------------------
  proc PathLineCoords {coords options} {
    set numFaces [llength $coords]
    set pts {}

    set closed [TLGet $options -closed]
    set lineWidth [TLGet $options -linewidth 0]
    set shifting [TLGet $options -shifting both]

    if { ! $numFaces || $lineWidth < 2 } {
      return {}
    }

    set previous {}
    if { $closed } {
      set previous [lindex $coords [expr $numFaces - 1]]
    }
    set next [lindex $coords 1]
    if { $shifting eq "both" } {
      set lineWidth [expr {$lineWidth / 2.0}]
    }

    for {set i 0} {$i < $numFaces} {incr i} {
      set pt [lindex $coords $i]
      foreach {ptX ptY} $pt break
      foreach {nextX nextY} $next break

      if { [llength $previous] == 0 } {
	# extrémité de curve sans raccord -> angle plat
	set previous [list [expr {$ptX + ($ptX - $nextX)}] \
	  [expr {$ptY + ($ptY - $nextY)}]]
      }

      foreach {angle bisecAngle} [VertexAngle $previous $pt $next] break

      # distance au centre du cercle inscrit : rayon/sinus demi-angle
      set sin [expr {sin([deg2rad [expr $angle/2.0]])}]
      set delta [expr {$sin ? abs($lineWidth / $sin) : $lineWidth}]

      if { $shifting eq "left" || $shifting eq "right" } {
	set adding [expr {($shifting eq "left") ? 90 : -90}]
	foreach {x y} [RadPoint $ptX $ptY $delta [expr {$bisecAngle + $adding}]] {
	  lappend pts $x $y
	}
	lappend pts $ptX $ptY

      } else {
	foreach {x y} [RadPoint $ptX $ptY $delta [expr {$bisecAngle + 90}]] {
	  lappend pts $x $y
	}
	foreach {x y} [RadPoint $ptX $ptY $delta [expr {$bisecAngle - 90}]] {
	  lappend pts $x $y
	}
      }

      if { $i == [expr $numFaces - 2] } {
	if { $closed } {
	  set next [lindex $coords 0]
	} else {
	  set nextI [expr $i + 1]
	  set next [list [expr {2 * [PointX [lindex $coords $nextI]] - [PointX $pt]}] \
	    [expr {2 * [PointY [lindex $coords $nextI]] - [PointY $pt]}]]
	}
      } else {
	set next [lindex $coords [expr {$i + 2}]]
      }
      set previous [lindex $coords $i]
    }

    if { $closed } {
      lappend pts [lindex $pts 0] [lindex $pts 1] [lindex $pts 2] [lindex $pts 3]
    }

    return $pts
  }

  #-----------------------------------------------------------------------------------
  # Graphics::PerpendicularPoint
  # retourne les coordonnées du point perpendiculaire abaissé d'un point sur une ligne
  #-----------------------------------------------------------------------------------
  proc PerpendicularPoint {point line} {
    foreach {x y} $point {p1 p2} $line break
    foreach {x1 y1} $p1 {x2 y2} $p2 break

    # cas particulier de lignes ortho.
    set minDist .01
    if { abs($y2 - $y1) < $minDist } {
      # la ligne de référence est horizontale
      return [list $x $y1]
    } elseif { abs($x2 - $x1) < $minDist } {
      # la ligne de référence est verticale
      return [list $x1 $y]
    }

    set a1 [expr {double($y2 - $y1) / double($x2 - $x1)}]
    set b1 [expr {$y1 - $a1 * $x1}]

    set a2 [expr {-1.0 / $a1}]
    set b2 [expr {$y - $a2 * $x}]

    set xRet [expr {double($b2 - $b1) / double($a1 - $a2)}]
    set yRet [expr {$a1 * $xRet + $b1}]

    return [list $xRet $yRet]
  }

  #-----------------------------------------------------------------------------------
  # Graphics::LineAngle
  # retourne l'angle d'un point par rapport à un centre de référence
  #-----------------------------------------------------------------------------------
  proc LineAngle {p center} {
    foreach {x y} $p {xref yref} $center break
    set angle [expr {(atan2($y - $yref, $x - $xref) + $v::pi/2.0) * 180.0 / $v::pi}]
    if { $angle < 0 } {
      set angle [expr {$angle + 360}]
    }
    return $angle
  }

  #-----------------------------------------------------------------------------------
  # Graphics::VertexAngle
  # retourne la valeur de l'angle formée par 3 points
  # ainsi que l'angle de la bisectrice
  #-----------------------------------------------------------------------------------
  proc VertexAngle {pt0 pt1 pt2} {
    set angle1 [LineAngle $pt1 $pt0]
    set angle2 [LineAngle $pt1 $pt2]

    if { $angle2 < $angle1 } {
      set angle2 [expr $angle2 + 360]
    }
    set alpha [expr {$angle2 - $angle1}]
    set bisectrice [expr {$angle1 + ($alpha/2.0)}]

    return [list $alpha $bisectrice]
  }

  #-----------------------------------------------------------------------------------
  # Graphics::ArcPts
  # calcul des points constitutif d'un arc
  # params : x,y centre, rayon, angle départ, delta angulaire, pas en degré
  #-----------------------------------------------------------------------------------
  proc ArcPts {x y rad angle extent step debug} {
    set pts {}

    if { $extent > 0 } {
      for {set alpha $angle} {$alpha <= ($angle + $extent)} {incr $alpha $step} {
	foreach {xn yn} [RadPoint $x $y $rad $alpha] {}
	lappend pts $xn $yn
      }
    } else {
      for {set alpha $angle} {$alpha >= ($angle + $extent)} {incr $alpha $step} {
	lappend pts [RadPoint $x $y $rad $alpha]
      }
    }
    return $pts
  }

  #-----------------------------------------------------------------------------------
  # Graphics::RadPoint
  # retourne le point circulaire défini par centre-rayon-angle
  #-----------------------------------------------------------------------------------
  proc RadPoint {x y rad angle} {
    set alpha [deg2rad $angle]

    set xpt [expr {$x + ($rad * cos($alpha))}]
    set ypt [expr {$y + ($rad * sin($alpha))}]

    return [list $xpt $ypt]
  }


  #-----------------------------------------------------------------------------------
  # TabBoxCoords
  # Calcul des shapes de boites à onglets
  #
  # coords : coordonnées rectangle de la bounding box
  #
  # options
  #                  -numpages <n> : nombre de pages (onglets) de la boite
  #              -anchor [n|e|s|w] : ancrage des onglets
  # -alignment [left|center|right] : alignement des onglets sur le coté d'ancrage
  # -tabwidth [<n>|[<n1>,<n2>,<n3>...]|auto] : largeur des onglets
  #          -tabheight [<n>|auto] : hauteur des onglets
  #                  -tabshift <n> : décalage onglet
  #                    -radius <n> : rayon des arrondis d'angle
  #                   -overlap <n> : distance de recouvrement des onglets
  #-----------------------------------------------------------------------------------
  proc TabBoxCoords args {
    set coords [lindex $args 0]
    set options [lrange $args 1 end]
    foreach {p0 p1} $coords break
    foreach {x0 y0} $p0 {xn yn} $p1 break
    set numPages [TLGet $options -numpages 0]

    if { $x0 eq "" || $y0 eq "" || $xn eq "" || $yn eq "" || !$numPages } {
      puts "Vous devez au minimum spécifier le rectangle englobant et le nombre de pages"
      return {}
    }

    set anchor [TLGet $options -anchor n]
    set alignment [TLGet $options -alignment left]
    set len [TLGet $options -tabwidth auto]
    set thick [TLGet $options -tabheight auto]
    set biso [TLGet $options -tabshift auto]
    set radius [TLGet $options -radius 0]
    set overlap [TLGet $options -overlap 0]
    set orientation [expr {($anchor eq "n" || $anchor eq "s") ? "horizontal" : "vertical"}]
    set maxwidth [expr {($orientation eq "horizontal") ? ($xn - $x0) : ($yn - $y0)}]
    set tabswidth 0
    set align 1

    if { $len eq "auto" } {
      set tabswidth $maxwidth
      set len [expr {($tabswidth + ($overlap * ($numPages - 1)))/$numPages}]
    } else {
      if { [llength $len] > 1 } {
	foreach w $len {
	  set tabswidth [expr {$tabswidth + ($w - $overlap)}]
	}
	set tabswidth [expr {$tabswidth + $overlap}]
      } else {
	set tabswidth [expr {($len * $numPages) - ($overlap * ($numPages - 1))}]
      }
      if { $tabswidth > $maxwidth } {
	set tabswidth $maxwidth
	set len [expr {($tabswidth + ($overlap * ($numPages - 1)))/$numPages}]
      }
      if { $alignment eq "center" && (($maxwidth - $tabswidth) > $radius) } {
	set align 0
      }
    }
    if { $thick eq "auto" } {
      set thick [expr {($orientation eq "horizontal") ? \
	  int(($yn - $y0)/10.0) : int(($xn - $y0)/10.0)}]
      if {$thick < 10 } {
	set thick 10
      } elseif {$thick > 40} {
	set thick 40
      }
    }
    if { $biso eq "auto" } {
      set biso [expr {int($thick/2.0)}]
    }
    if { ($alignment eq "right" && $anchor ne "w") || \
	     ($anchor eq "w" && $alignment ne "right") } {
      if { [llength $len] > 1 } {
	for {set p 0} {$p < $numPages} {incr p} {
	    lset len $p [expr {-[lindex $len $p]}]
	}
      } else {
	  set len [expr {-$len}]
      }
      set biso [expr {-$biso}]
	set overlap [expr {-$overlap}]
    }

    if { $alignment eq "center" } {
      set biso1 [expr {$biso / 2.0}]
      set biso2 $biso1
    } else {
      set biso1 0
      set biso2 $biso
    }

    if { $orientation eq "vertical" } {
      if { $anchor eq "w" } {
	set thick [expr {-$thick}]
	set startx $x0
	set endx $xn
      } else {
	set startx $xn
	set endx $x0
      }
      if { ($anchor eq "w" && $alignment ne "right") || \
	($anchor eq "e" && $alignment eq "right") } {
	set starty $yn
	set endy $y0
      } else {
	set starty $y0
	set endy $yn
      }

      set xref [expr {$startx - $thick}]
      set yref $starty
      if  { $alignment eq "center" } {
	set ratio [expr {($anchor eq "w") ? -2 : 2}]
	set yref [expr {$yref + (($maxwidth - $tabswidth)/$ratio)}]
      }

      set cadre [list [list $xref $endy] [list $endx $endy] \
	[list $endx $starty] [list $xref $starty]]
      #
      # flag de retournement de la liste des pts de 
      # curve si nécessaire -> sens anti-horaire
      set inverse [expr {$alignment ne "right"}]
    } else {
      if { $anchor eq "s" } {
	set thick [expr {-$thick}]
      }
      if { $alignment eq "right" } {
	set startx $xn
	set endx $x0
      } else {
	set startx $x0
	set endx $xn
      }
      if { $anchor eq "s" } {
	set starty $yn
	set endy $y0
      } else {
	set starty $y0
	set endy $yn
      }

      set yref [expr {$starty + $thick}]
      if { $alignment eq "center" } {
	set xref [expr {$x0 + (($maxwidth - $tabswidth)/2.0)}]
      } else {
	set xref $startx
      }

      set cadre [list [list $endx $yref] [list $endx $endy] \
	[list $startx $endy] [list $startx $yref]]
      #
      # flag de retournement de la liste des pts de
      # curve si nécessaire -> sens anti-horaire
      set inverse [expr {($anchor eq "n" && $alignment ne "right") || \
	  ($anchor eq "s" && $alignment eq "right")}]
    }

    for {set i 0} {$i < $numPages} {incr i} {
      set pts {}
      #
      # décrochage onglet
      #push (@pts, ([$xref, $yref])) if $i > 0;
      #
      # cadre
      set pts [lrange $cadre 0 end]
      #
      # points onglets
      if { $i > 0 || ! $align } {
	lappend pts [list $xref $yref]
      }
      set tw [expr {([llength $len] > 1) ? [lindex $len $i] : $len}]
      if { $orientation eq "vertical" } {
	set tabdxy [list $thick $biso1 $thick [expr {$tw - $biso2}] 0 $tw]
      } else {
	set tabdxy [list $biso1 [expr {-$thick}] [expr {$tw - $biso2}] [expr {-$thick}] $tw 0]
      }
      foreach {dx dy} $tabdxy {
	lappend pts [list [expr {$xref + $dx}] [expr {$yref + $dy}]]
      }

      if { $radius } {
	if { $i > 0 || ! $align } {
	  set corners [list 0 1 1 1 0 1 1 0]
	} else {
	  set corners [list 0 1 1 0 1 1 0 0 0]
	}
	set curvePts [RoundedCurveCoords $pts [list -radius $radius -corners $corners]]
	if { $inverse } {
	  set curvePts [lreverse $curvePts]
	}
	lappend shapes $curvePts
      } else {
	if { $inverse } {
	  set pts [lreverse $pts]
	}
        lappend shapes $pts
      }

      if { $orientation eq "horizontal" } {
	lappend titlesCoords [list [expr {$xref + ($tw - ($biso2 - $biso1))/2.0}] \
				  [expr {$yref - ($thick/2.0)}]]
	set xref [expr {$xref + ($tw - $overlap)}]
      } else {
	lappend titlesCoords [list [expr {$xref + ($thick/2.0)}] \
	  [expr {$yref + ($len - (($biso2 - $biso1)/2.0))/2.0}]]
	set yref [expr {$yref + ($len - $overlap)}]
      }
    }

    return [list $shapes $titlesCoords $inverse]
  }

  #-----------------------------------------------------------------------------------
  # RESOURCES GRAPHIQUES GRADIENTS, PATTERNS, TEXTURES, IMAGES...
  #-----------------------------------------------------------------------------------
  #-----------------------------------------------------------------------------------
  # Graphics::SetGradients
  # création de gradient nommés Zinc
  #-----------------------------------------------------------------------------------
  proc SetGradients {zinc grads} {
    # initialise les gradients de taches
    if { ! [llength $v::Gradients] } {
      foreach {name gradient} $grads {
	# création des gradients nommés
	$zinc gname $gradient $name
	lappend v::Gradients $name
      }
    }
  }

  #-----------------------------------------------------------------------------------
  # Graphics::GetPattern
  # retourne la ressource bitmap en l'initialisant si première utilisation
  #-----------------------------------------------------------------------------------
  proc GetPattern {name} {
    global bitmaps imagePath

    if { ![info exists bitmaps($name)] } {
      set bitmap "@[file join $imagePath $name]"
      set bitmaps($name) $bitmap
      return $bitmap
    }
    return $bitmaps($name)
  }

  #-----------------------------------------------------------------------------------
  # Graphics::GetTexture
  # retourne l'image de texture en l'initialisant si première utilisation
  #-----------------------------------------------------------------------------------
  proc GetTexture {name} {
    global imagePath

    if { ![info exists v::textures($name)] } {
      set texture [image create photo -file [file join $imagePath $name]]
      if { $texture ne "" } {
	set v::textures($name) $texture
      }
      return $texture
    }
    return $v::textures($name)
  }

  #-----------------------------------------------------------------------------------
  # Graphics::GetImage
  # retourne la ressource image en l'initialisant si première utilisation
  #-----------------------------------------------------------------------------------
  proc GetImage {name} {
    global imagePath

    if { ![info exists v::images($name)] } {
      set image [image create photo -file [file join $imagePath $name]]
      if { $image ne "" } {
	set v::images($name) $image
      }
      return $image
    }
    return $v::images($name)
  }

  #-----------------------------------------------------------------------------------
  # Graphics::InitPixmaps
  # initialise une liste de fichier image
  #-----------------------------------------------------------------------------------
  proc InitPixmaps {pixFiles} {
    set imgs {}
    foreach f $pixFiles {
      lappend imgs [GetImage $f]
    }    
    return $imgs
  }


  proc _min {n1 n2} {
    return [expr {($n1 > $n2) ? $n2 : $n1}]
  }

  proc _max {n1 n2} {
    return [expr {($n1 > $n2) ? $n1 : $n2}]
  }

  #-----------------------------------------------------------------------------------
  # Graphics::_trunc
  # fonction interne de troncature des nombres: n = position décimale 
  #-----------------------------------------------------------------------------------
  proc _trunc {val n} {
    regexp {([0-9]+)\.?([0-9]*)} $val match ent dec
    set str [expr {($val < 0) ? -$ent : $ent}]
    if { ($dec ne "") && ($n != 0) } {
      set dec [string range $dec 0 [expr {$n-1}]]
      if { $dec != 0 } {
	set str "$str.$dec"
      }
    }
    return $str;
  }

  #-----------------------------------------------------------------------------------
  # Graphics::RGBdec2hex
  # conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
  #-----------------------------------------------------------------------------------
  proc RGBdec2hex {rgb} {
    return [eval "format {#%04x%04x%04x} $rgb"]
  }

  #-----------------------------------------------------------------------------------
  # zincGraphics::PathGraduate
  # création d'un jeu de couleurs dégradées pour item pathLine
  #-----------------------------------------------------------------------------------
  proc PathGraduate {numColors style} {
    set type [TLGet $style -type]
    set colors [TLGet $style -colors]

    if { $type eq "linear" } {
      return [CreateGraduate $numColors $colors 2]

    } elseif { $type eq "double" } {
      set colors1 [CreateGraduate [expr {$numColors/2+1}] [lindex $colors 0]]
      set colors2 [CreateGraduate [expr {$numColors/2+1}] [lindex $colors 1]]
      set clrs {}
      for {set i 0} {$i <= $numColors} {incr i} {
	lappend clrs [lindex $colors1 $i] [lindex $colors2 $i]
      }
      return $clrs

    } elseif { $type eq "transversal" } {
      foreach {c1 c2} $colors break
      set clrs [list $c1 $c2]
      for {set i 0} {$i < $numColors} {incr i} {
	lappend clrs $c1 $c2
      }
      return $clrs;
    }
  }

  #-----------------------------------------------------------------------------------
  # Graphics::CreateGraduate
  # création d'un jeu de couleurs intermédiaires (dégradé) entre n couleurs
  #-----------------------------------------------------------------------------------
  proc CreateGraduate {totalSteps refColors {repeat 1}} {
    set colors {}
    set numGraduates [expr {[llength $refColors] - 1}]

    if { $numGraduates < 1 } {
      puts "Le dégradé necessite au minimum 2 couleurs de référence..."
      return {}
    }

    set steps [expr {($numGraduates > 1) ? ($totalSteps/($numGraduates - 1.0)) : $totalSteps}]

    for {set c 0} {$c < $numGraduates} {incr c} {
      set c1 [lindex $refColors $c]
      set c2 [lindex $refColors [expr {$c+1}]]

      #
      # Pas de duplication de la couleur de raccord entre
      # deux segments
      set thisSteps $steps
      if { $c < [expr $numGraduates - 1] } {
	set thisSteps [expr $thisSteps - 1]
      }
      for {set i 0} {$i < $thisSteps} {incr i} {
	set color [ComputeColor $c1 $c2 [expr {$i/($steps-1.0)}]]
	for {set k 0} {$k < $repeat} {incr k} {
	  lappend colors $color
	}
      }
    }

    return $colors
  }

  #-----------------------------------------------------------------------------------
  # Graphics::computeColor
  # calcul d'une couleur intermédiaire défini par un ratio ($ratio) entre 2 couleurs
  #-----------------------------------------------------------------------------------
  proc ComputeColor {color0 color1 ratio} {
    if { $ratio > 1.0 } {
      set ratio 1
    } elseif { $ratio < 0 } {
      set ratio 0
    }

    foreach {r0 g0 b0 a0} [ZnColorToRGB $color0] break
    foreach {r1 g1 b1 a1} [ZnColorToRGB $color1] break

    set r [expr {$r0 + int(($r1 - $r0) * $ratio)}]
    set g [expr {$g0 + int(($g1 - $g0) * $ratio)}]
    set b [expr {$b0 + int(($b1 - $b0) * $ratio)}]
    set a [expr {$a0 + int(($a1 - $a0) * $ratio)}]
    return [HexaRGBcolor $r $g $b $a]
  }

  proc ZnColorToRGB {znColor} {
    foreach {color alpha} [split $znColor ";"] break
    set pattern [expr {[string length $color] > 8 ? {#%4x%4x%4x} : {#%2x%2x%2x}}]
    scan $color $pattern r g b

    if {$alpha eq ""} {
      set alpha 100
    }

    return [list $r $g $b $alpha]
  }

  #-----------------------------------------------------------------------------------
  # Graphics::hexaRGBcolor
  # conversion d'une couleur RGB (255,255,255) au format Zinc '#ffffff'
  #-----------------------------------------------------------------------------------
  proc HexaRGBcolor {r g b args} {
    if { [llength $args] } {
      return [format {#%02x%02x%02x;%d} $r $g $b [lindex $args 0]]
    } else {
      return [format {#%02x%02x%02x} $r $g $b]   
    }
  }
}

proc lreverse {l} {
    set res {}
    set i [llength $l]
    while {$i} {
	lappend res [lindex $l [incr i -1]]
    }
    return $res
}

Added jni/tkzinc/library/zincLogo.tcl.























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#---------------------------------------------------------------
#  File            : LogoZinc.pm
#
#  Copyright (C) 2001-2002
#  Centre d'Études de la Navigation Aérienne
#  Authors: Vinot Jean-Luc <vinot@cena.fr>
#  $Id$
#---------------------------------------------------------------

package provide zincLogo 1.0

namespace eval ::zincLogo:: {

    set letters(coords) {
	{0 0} {106 0} {106 58} {122 41} {156 41} {131 69}
	{153 99} {203 41} {155 41} {155 0} {218 0} {240 0 c}
	{252 17 c} {252 34} {252 40 c} {249 50 c} {244 56}
	{202 105} {246 105} {246 87} {246 60 c} {271 37 c} {297 37}
	{323 37 c} {342 57 c} {344 68} {347 64 c} {350 60 c}
	{353 56} {363 46 c} {375 37 c} {395 37} {395 79} {393 79}
	{385 79 c} {379 86 c} {379 93} {379 100 c} {385 107 c}
	{393 107} {409 107} {409 148} {397 148} {378 148 c} {364 144 c}
	{354 133} {346 124} {346 148} {305 148} {305 87} {305 83 c}
	{301 79 c} {297 79} {293 79 c} {289 83 c} {289 87} {289 150}
	{251 150} {251 130} {251 126 c} {247 122 c} {243 122} {239 122 c}
	{235 126 c} {235 130} {235 150} {176 150} {154 150 c} {146 131 c}
	{146 114} {148 105} {120 105} {104 81} {104 105} {74 105} {74 41} {52 41}
	{52 105} {20 105} {20 41} {0 41}}
    set letters(lineWidth) 3
    set letters(lineColor) {#000000;80}
    set letters(fillColor) {=axial 270|#ffffff;100 0 28|#66848c;100 96|#7192aa;100 100}
    set letters(shadow,dXy) {6 6}
    set letters(shadow,fillColor) {#000000;18}

    set point(pos) {240 96}
    set point(alpha) 80
    set point(lineWidth) 1
    set point(lineColor) {#a10000;100}
    set point(fillColor) {=radial -20 -20|#ffffff;100 0|#f70000;100 48|#900000;100 80|#ab0000;100 100}
    set point(shadow,dXy) {5 5}
    set point(shadow,fillColor) {=path 0 0|#770000;64 0|#770000;64 65|#770000;0 100}
    
    

    proc create {zinc parent priority x y scaleX scaleY} {
	variable letters
	variable point
	#
	# Create a group to hold the various parts
	set logoGroup [$zinc add group $parent -priority $priority]
	
	#
	# Move the group in the right place
	$zinc coords $logoGroup "$x $y"
	
	#
	# Add a sub-group to isolate the scaling
	set scaleGroup [$zinc add group $logoGroup]
	$zinc scale $scaleGroup $scaleX $scaleY
	
	foreach {dx dy} $letters(shadow,dXy) break
	#
	# Create a curve for the main form shadow
	set lShadow [$zinc add curve $scaleGroup $letters(coords) \
			 -tags lettersShadow -closed 1 -filled 1 -linewidth 0 \
			 -fillcolor $letters(shadow,fillColor)]
	$zinc translate $lShadow $dx $dy
	
	set lineWidth [adjustLineWidth $letters(lineWidth) $scaleX $scaleY]
	
	#
	# Create a curve for the main form
	$zinc add curve $scaleGroup $letters(coords) -tags letters -closed 0 \
	    -filled 1 -fillcolor $letters(fillColor) -linewidth $lineWidth \
	    -linecolor $letters(lineColor)
	
	#
	# Create a group to hold the point and its shadow
	set pointGroup [$zinc add group $scaleGroup -alpha $point(alpha)]
	$zinc coords $pointGroup $point(pos)
	
	foreach {dx dy} $point(shadow,dXy) break
	#
	# Create a curve for the dot shadow
	set pShadow [$zinc add arc $pointGroup {-20 -20 20 20} -tags pointShadow \
			 -closed 1 -filled 1 -fillcolor $point(shadow,fillColor) \
			 -linewidth 0]
	$zinc translate $pShadow $dx $dy
	
	#
	# Create a curve for the dot
	$zinc add arc $pointGroup {-20 -20 20 20} -tags point -closed 1 \
	    -filled 1 -fillcolor $point(fillColor) -linewidth $point(lineWidth) \
	    -linecolor $point(lineColor)

	return $logoGroup
    }
	
    proc adjustLineWidth {lineWidth scaleX scaleY} {
	if {$lineWidth != 0} {
	    if {$lineWidth >= 2} {
		set ratio [expr ($scaleX > $scaleY) ? $scaleY : $scaleX]
		return [expr $lineWidth * $ratio]
	    }
	}
    }
}

Added jni/tkzinc/library/zincText.tcl.









































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#
# ZincText - Zinc extension for text input on text items and fields
#
# $Id$
#
# AUTHOR
#
# Patrick Lecoanet <lecoanet@cena.fr>
# (and documentation by Christophe Mertz <mertz@cena.fr>)
#
# Copyright (c) 2002 - 2003 CENA, Patrick Lecoanet
#
# See the file "Copyright" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
#
# SYNOPSIS
#
#  package require zincText;
#
#  zn_TextBindings $zinc
#
#  $zinc addtag text withtag $a_text
#  $zinc addtag text withtag $a_track
#  $zinc addtag text withtag $a_waypoint
#  $zinc addtag text withtag $a_tabular
#
#
# DESCRIPTION
#
# This module implements text input with the mouse and keyboard 'a la emacs'.
# Text items must have the 'text' tag and must of course be sensitive.
# Track, waypoint and tabular items have fields and these fields can
# be edited the same way. Only sensitive fields can be edited. the following
# interactions are supported:
#
#   <click 1>      To set the cursor position
#   <click 2>      To paste the current selection
#   <drag 1>       To make a selection
#   <shift drag 1> To extend the current selection
#   <shift 1>      To extend the current selection
#   <left arrow>,
#   <right arrow>  To move the cursor to the left or to the right
#   <up arrow>,
#   <down arrow>   To move the cursor up or down a line
#   <ctrl+a>,
#   <home>         To move the cursor at the begining of the line
#   <ctrl+e>
#   <end>          To move the cursor at the end of the line
#   <meta+<>,
#   <meta+>>       To move the cursor at the beginning / end of the text
#   <BackSpace>
#   <ctrl+h>       To delete the char just before the cursor
#   <Delete>       To delete the char just after the cursor
#   <Return>       To insert a return char. This does not validate the input!
#
#

proc zn_TextBindings {zinc} {
    $zinc bind text <1>              "startSel $zinc %x %y"
    $zinc bind text <2>              "pasteSel $zinc %x %y"
    $zinc bind text <B1-Motion>      "extendSel $zinc %x %y"
    $zinc bind text <Shift-B1-Motion> "extendSel $zinc %x %y"
    $zinc bind text <Shift-1>        "$zinc select adjust current @%x,%y"
    $zinc bind text <Left>           "moveCur $zinc -1"
    $zinc bind text <Right>          "moveCur $zinc 1"
    $zinc bind text <Up>             "setCur $zinc up"
    $zinc bind text <Down>           "setCur $zinc down"
    $zinc bind text <Control-a>      "setCur $zinc bol"
    $zinc bind text <Home>           "setCur $zinc bol"
    $zinc bind text <Control-e>      "setCur $zinc eol"
    $zinc bind text <End>            "setCur $zinc eol"
    $zinc bind text <Meta-less>      "setCur $zinc 0"
    $zinc bind text <Meta-greater>   "setCur $zinc end"
    $zinc bind text <KeyPress>       "insertKey $zinc %A"
    $zinc bind text <Shift-KeyPress> "insertKey $zinc %A"
    $zinc bind text <Return>         "insertChar $zinc \\n"
    $zinc bind text <BackSpace>      "textDel $zinc -1"
    $zinc bind text <Control-h>      "textDel $zinc -1"
    $zinc bind text <Delete>         "textDel $zinc 0"
}


proc pasteSel {w x y} {
    set item [$w focus]

    if {[llength $item] != 0} {
	catch {$w insert [lindex $item 0] [lindex $item 1] @$x,$y [selection get]}
    }
}


proc insertChar {w c} {
    set item [$w focus]
    set selItem [$w select item]

    if {[llength $item] == 0} {
	return;
    }
    
    if {([llength $selItem]!= 0) &&
	([lindex $selItem 0] == [lindex $item 0]) &&
	([lindex $selItem 1] == [lindex $item 1])} {
	$w dchars [lindex $item 0] [lindex $item 1] sel.first sel.last
    }
    $w insert [lindex $item 0] [lindex $item 1] insert $c
}


proc insertKey {w c} {
    if {! [binary scan $c {c} code]} {
	return
    }
    set code [expr $code & 0xFF]
    if {($code < 32) || ($code == 128)} {
	puts "rejet $code"
	return
    }
    
    insertChar $w $c
}


proc setCur {w where} {
    set item [$w focus]

    if {[llength $item] != 0} {
	$w cursor [lindex $item 0] [lindex $item 1] $where
    }
}


proc moveCur {w dir} {
    set item [$w focus]

    if {[llength $item] != 0} {
	set index [$w index [lindex $item 0] [lindex $item 1] insert]
	$w cursor [lindex $item 0] [lindex $item 1]  [expr $index + $dir]
    }
}


proc startSel {w x y} {
    set part [$w currentpart t]

    $w cursor current $part @$x,$y
    $w focus current $part
    focus $w
    $w select from current $part @$x,$y
}


proc extendSel {w x y} {
    set part [$w currentpart t]

    $w select to current $part @$x,$y
}


proc textDel {w dir} {
    set item [$w focus]
    set selItem [$w select item]

    if {[llength $item] == 0} {
	return;
    }

    if {([llength $selItem] != 0) &&
	([lindex $selItem 0] == [lindex $item 0]) &&
	([lindex $selItem 1] == [lindex $item 1])} {
	$w dchars [lindex $item 0] [lindex $item 1] sel.first sel.last
    } else {
	set ind [expr [$w index [lindex $item 0] [lindex $item 1] insert] + $dir]
	if { $ind >= 0 } {
	    $w dchars [lindex $item 0] [lindex $item 1] $ind $ind
	}
    }
}

package provide zincText 1.0

Added jni/tkzinc/macosx/OSXPort.c.











































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/*
 * OSXPort.c -- Compatibility layer for Mac OS X
 *
 * Authors		: Patrick Lecoanet.
 * Creation date	:
 *
 * $Id$
 */

/*
 *  Copyright (c) 2005 - CENA, Patrick Lecoanet --
 *
 * This code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this code; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#ifdef MAC_OSX_TK

#include "Types.h"
#include <Carbon/Carbon.h>

static const char rcsid[] = "$Id";
static const char compile_id[]="$Compile$";

#ifndef MIN
#define MIN(a, b) 	((a) <= (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) 	((a) >= (b) ? (a) : (b))
#endif


/*
 *----------------------------------------------------------------------
 *
 * ZnPointInRegion --
 *
 *	Test whether the specified point is inside a region.
 *
 * Results:
 *	Returns the boolean result of the test.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
int
ZnPointInRegion(TkRegion reg,
                int      x,
                int      y)
{
  RgnHandle rgn = (RgnHandle) reg;
  Point     pt;

  pt.h = x;
  pt.v = y;

  return (int) PtInRgn(pt, rgn);
}

/*
 *----------------------------------------------------------------------
 *
 * ZnUnionRegion --
 *
 *	Compute the union of two regions.
 *
 * Results:
 *	Returns the result in the dr_return region.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
void
ZnUnionRegion(TkRegion sra,
              TkRegion srb,
              TkRegion dr_return)
{
  RgnHandle srcRgnA = (RgnHandle) sra;
  RgnHandle srcRgnB = (RgnHandle) srb;
  RgnHandle destRgn = (RgnHandle) dr_return;

  UnionRgn(srcRgnA, srcRgnB, destRgn);
}

/*
 *----------------------------------------------------------------------
 *
 * ZnOffsetRegion --
 *
 *	Offset a region by the specified pixel offsets.
 *
 * Results:
 *	Returns the result in the dr_return region.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
void
ZnOffsetRegion(TkRegion reg,
               int      dx,
               int      dy)
{
  RgnHandle rgn = (RgnHandle) reg;
  OffsetRgn(rgn, (short) dx, (short) dy);
}

/*
 *----------------------------------------------------------------------
 *
 * ZnPolygonRegion --
 *
 *	Compute a region from a polygon.
 *
 * Results:
 *	Returns the result in the dr_return region.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
TkRegion
ZnPolygonRegion(XPoint *points,
                int    n,
                int	   fill_rule)
{
  RgnHandle rgn;
  int       i;

  rgn = NewRgn();

  OpenRgn();
  MoveTo((short) points[0].x, (short) points[0].y);
  for (i = 1; i < n; i++) {
    LineTo((short) points[i].x, (short) points[i].y);
  }
  LineTo((short) points[0].x, (short) points[0].y);
  CloseRgn(rgn);
  
  return (TkRegion) rgn;
}

#if 0
/*
 *----------------------------------------------------------------------
 *
 * XFillRectangles --
 *
 *	Fill multiple rectangular areas in the given drawable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws onto the specified drawable.
 *
 *----------------------------------------------------------------------
 */
void
XFillRectangles(Display    *display,
                Drawable   d,
                GC         gc,
                XRectangle *rectangles,
                int        nrectangles)
{
}

/*
 *----------------------------------------------------------------------
 *
 * XFillRectangle --
 *
 *	Fills a rectangular area in the given drawable.  This procedure
 *	is implemented as a call to XFillRectangles.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Fills the specified rectangle.
 *
 *----------------------------------------------------------------------
 */
void
XFillRectangle(Display      *display,
               Drawable     d,
               GC           gc,
               int          x,
               int          y,
               unsigned int width,
               unsigned int height)
{
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawLines --
 *
 *	Draw connected lines.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Renders a series of connected lines.
 *
 *----------------------------------------------------------------------
 */
void
XDrawLines(Display  *display,
           Drawable d,
           GC       gc,
           XPoint   *points,
           int      npoints,
           int      mode)
{
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawLine --
 *
 *	Draw a single line between two points in a given drawable. 
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a single line segment.
 *
 *----------------------------------------------------------------------
 */
void
XDrawLine(Display  *display,
          Drawable d,
          GC       gc,
          int      x1,
          int      y1,
          int      x2,
          int      y2)
{
}

/*
 *----------------------------------------------------------------------
 *
 * XFillPolygon --
 *
 *	Draws a filled polygon.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a filled polygon on the specified drawable.
 *
 *----------------------------------------------------------------------
 */
void
XFillPolygon(Display  *display,
             Drawable d,
             GC       gc,
             XPoint   *points,
             int      npoints,
             int      shape,
             int      mode)
{
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawRectangle --
 *
 *	Draws a rectangle.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a rectangle on the specified drawable.
 *
 *----------------------------------------------------------------------
 */
void
XDrawRectangle(Display *display,
               Drawable d,
               GC gc,
               int x,
               int y,
               unsigned int width,
               unsigned int height)
{
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawArc --
 *
 *	Draw an arc.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws an arc on the specified drawable.
 *
 *----------------------------------------------------------------------
 */
void
XDrawArc(Display      *display,
         Drawable     d,
         GC           gc,
         int          x,
         int          y,
         unsigned int width,
         unsigned int height,
         int          start,
         int          extent)
{
}

/*
 *----------------------------------------------------------------------
 *
 * XFillArc --
 *
 *	Draw a filled arc.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a filled arc on the specified drawable.
 *
 *----------------------------------------------------------------------
 */
void
XFillArc(Display      *display,
         Drawable     d,
         GC           gc,
         int          x,
         int          y,
         unsigned int width,
         unsigned int height,
         int          start,
         int          extent)
{
}
#endif

#endif

Added jni/tkzinc/redhat/changelog.









































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
$Version = "3.302";
$Release = 3;

$ChangeLog = ' 

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-1

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-2

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-3

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-4

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-5

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-6

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-7

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-8

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-9

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-10

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-11

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-12

 * Mon Mar 12 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.23-1

 * Tue Mar 13 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.23-2

 * Tue Mar 13 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.23-3

 * Fri Mar 16 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.24-1

 * Tue Apr 10 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.26-1

 * Wed Jan 16 2002 Stéphane Chatty
- Generation of version 3.2.3-1

 * Thu Apr 4 2002 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.2.4-1

 * Wed Sep 18 2002 Stéphane Chatty <chatty@intuilab.com>
- Generation of version 3.2.6-1

 * Mon Feb 17 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.6h-1
- Mandrake 9 compilation
- Removes installgpc in redhat/rules

 * Wed May 14 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.92-1
- Mandrake 9 compilation

 * Sat May 17 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.93-1
- Mandrake 9 compilation

 * Fri Jun 20 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.94-1
- Mandrake 9 compilation

 * Fri Jun 20 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.94-2
- Mandrake 9.1 compilation

 * Wed Oct 15 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.295-1
- Mandrake 9 compilation

 * Tue Oct 28 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.295-2

 * Fri Nov 28 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.295-3

 * Mon Dec 15 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.296-1

 * Thu Oct 21 2004 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.30-1
- Build a Mandrake 9.2 package

 * Mon Jun 27 2005 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.302-1
- Mandrake 9.1 package

 * Mon Jun 27 2005 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.302-2
- Mandrake 10.0 package

 * Mon Jun 27 2005 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.302-3
- Mandrake 10.1 package

';

Added jni/tkzinc/redhat/perl-Tk-Zinc.spec.









































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
Summary: Zinc, a canvas replacement for Tk
Name: perl-Tk-Zinc
Version: 3.296
Release: 1
Copyright: BSD
Vendor: Centre d'Etudes de la Navigation Aerienne
Packager: Alexandre Lemort <lemort@intuilab.com>
Distribution: Zinc
Group: System Environment/Libraries
Url: http://www.cena.fr/divisions/PII/
Source: perl-Tk-Zinc-3.296.tar.gz
Requires: perl-Tk
BuildArchitectures: i386
BuildRoot: /var/tmp/perl-Tk-Zinc-buildroot

%description
Zinc is a canvas like widget for the Tk toolkit. Its has been
 designed to provide a structured organization of its graphical
 components. It provides also advanced geometrical and graphical
 capabilities such as geometric construction (boolean ops),
 transformations, non rectangular clipping gradient fills, smart
 reliefs, etc.

This contains the dynamic libraries that are necessary for
running applications which use Zinc.

%prep
%setup -q -n perl-Tk-Zinc-%{version}

%build
./configure --enable-ptk=yes --enable-gl=damage --prefix=$RPM_BUILD_ROOT/usr --exec-prefix=$RPM_BUILD_ROOT/usr
cd Perl
./export2cpan
cd ../export2cpan/tk-zinc
perl Makefile.PL
make

%clean
rm -rf $RPM_BUILD_ROOT

%install
rm -rf $RPM_BUILD_ROOT
mkdirhier $RPM_BUILD_ROOT/usr/lib
cd export2cpan/tk-zinc
make PREFIX=$RPM_BUILD_ROOT/usr prefix=$RPM_BUILD_ROOT/usr INSTALLDIRS=perl install
find $RPM_BUILD_ROOT/usr -type f -print | sed "s@^$RPM_BUILD_ROOT@@g" | grep -v Zinc.bs | grep -v .packlist > ../../perl-Tk-Zinc-%{version}-filelist

%files -f perl-Tk-Zinc-%{version}-filelist
%defattr(-,root,root)

%changelog
 

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-1

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-2

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-3

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-4

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-5

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-6

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-7

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-8

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-9

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-10

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-11

 * Tue Oct 31 2000 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.19-12

 * Mon Mar 12 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.23-1

 * Tue Mar 13 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.23-2

 * Tue Mar 13 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.23-3

 * Fri Mar 16 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.24-1

 * Tue Apr 10 2001 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.1.26-1

 * Wed Jan 16 2002 Stéphane Chatty
- Generation of version 3.2.3-1

 * Thu Apr 4 2002 Stéphane Chatty <chatty@cena.fr>
- Generation of version 3.2.4-1

 * Wed Sep 18 2002 Stéphane Chatty <chatty@intuilab.com>
- Generation of version 3.2.6-1

 * Mon Feb 17 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.6h-1
- Mandrake 9 compilation
- Removes installgpc in redhat/rules

 * Wed May 14 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.92-1
- Mandrake 9 compilation

 * Sat May 17 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.93-1
- Mandrake 9 compilation

 * Fri Jun 20 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.94-1
- Mandrake 9 compilation

 * Fri Jun 20 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.2.94-2
- Mandrake 9.1 compilation

 * Wed Oct 15 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.295-1
- Mandrake 9 compilation

 * Tue Oct 28 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.295-2

 * Fri Nov 28 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.295-3

 * Mon Dec 15 2003 Alexandre Lemort <lemort@intuilab.com>
- Generation of version 3.296-1


Added jni/tkzinc/redhat/rules.































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$Summary = "Zinc, a canvas replacement for Tk";
$Name = "perl-Tk-Zinc";
$Copyright = "LGPL";
$Vendor = "Centre d'Etudes de la Navigation Aerienne";
$Url = "http://www.cena.fr/divisions/PII/";
$Distribution = "Zinc";
$Group = "System Environment/Libraries";
$BuildArchitectures = "i386";
$Requires = "perl-Tk";

$Build = "cd Perl
./export2cpan
cd ../export2cpan/tk-zinc
perl Makefile.PL
make";

$Install = "rm -rf \$RPM_BUILD_ROOT
mkdirhier \$RPM_BUILD_ROOT/usr/lib
cd export2cpan/tk-zinc
make PREFIX=\$RPM_BUILD_ROOT/usr prefix=\$RPM_BUILD_ROOT/usr INSTALLDIRS=perl pure_install
find \$RPM_BUILD_ROOT/usr -type f -print | sed \"s\@^\$RPM_BUILD_ROOT\@\@g\" \| grep -v Zinc.bs | grep -v .packlist > ../../$Name-\%{version}-filelist";

$Description = "Zinc is a canvas like widget for the Tk toolkit. Its has been
 designed to provide a structured organization of its graphical
 components. It provides also advanced geometrical and graphical
 capabilities such as geometric construction (boolean ops),
 transformations, non rectangular clipping gradient fills, smart
 reliefs, etc.

This contains the dynamic libraries that are necessary for
running applications which use Zinc.";

Added jni/tkzinc/sandbox/Controls.pm.

































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

package Controls;

$top = 1;

sub new {
    my $proto = shift;
    my $type = ref($proto) || $proto;
    my ($zinc) = @_;
    my $self = {};

    $self{'zinc'} = $zinc;
    $self{'cur_x'} = 0;
    $self{'cur_y'} = 0;
    $self{'cur_angle'} = 0;
    $self{'corner_x'} = 0;
    $self{'corner_y'} = 0;
    
    $self{'tlbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'tlbbox'}, [-3, -3, +3, +3]);
    $self{'trbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'trbbox'}, [-3, -3, +3, +3]);
    $self{'blbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'blbbox'}, [-3, -3, +3, +3]);
    $self{'brbbox'} = $zinc->add('group', $top,
				 -sensitive => 0, -visible => 0,
				 -tags => 'currentbbox');
    $zinc->add('rectangle', $self{'brbbox'}, [-3, -3, +3, +3]);
    $zinc->add('rectangle', $top, [0, 0, 1, 1],
	       -linecolor => 'red', -tags => 'lasso',
	       -visible => 0, -sensitive => 0);

    $zinc->Tk::bind('<Shift-ButtonPress-1>', [\&start_lasso, $self]);
    $zinc->Tk::bind('<Shift-ButtonRelease-1>', [\&fin_lasso, $self]);

    $zinc->Tk::bind('<ButtonPress-2>', sub { my $ev = $zinc->XEvent();
					     my @closest = $zinc->find('closest',
								      $ev->x, $ev->y);
					     print "at point=$closest[0]\n" });
    
    $zinc->Tk::bind('<ButtonPress-3>', [\&press, $self, \&motion]);
    $zinc->Tk::bind('<ButtonRelease-3>', [\&release, $self]);
    
    $zinc->Tk::bind('<Shift-ButtonPress-3>', [\&press, $self, \&zoom]);
    $zinc->Tk::bind('<Shift-ButtonRelease-3>', [\&release, $self]);
    
    $zinc->Tk::bind('<Control-ButtonPress-3>', [\&press, $self, \&rotate]);
    $zinc->Tk::bind('<Control-ButtonRelease-3>', [\&release, $self]);
    
    $zinc->Tk::bind('current', '<Enter>', [\&showbox, $self]);
    $zinc->Tk::bind('current', '<Leave>', [\&hidebox, $self]);

    bless ($self, $type);
    return $self;
}

#
# Controls for the window transform.
#
sub press {
    my ($zinc, $self, $action) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;

    $self->{'cur_x'} = $lx;
    $self->{'cur_y'} = $ly;
    $self->{'cur_angle'} = atan2($ly, $lx);
    $zinc->Tk::bind('<Motion>', [$action, $self]);
}

sub motion {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @it;
    my @res;
    
    @it = $zinc->find('withtag', 'controls');
    if (scalar(@it) == 0) {
	return;
    }
    @res = $zinc->transform($it[0], [$lx, $ly, $self->{'cur_x'}, $self->{'cur_y'}]);
    $zinc->translate('controls', $res[0] - $res[2], $res[1] - $res[3]);
    $self->{'cur_x'} = $lx;
    $self->{'cur_y'} = $ly;
}

sub zoom {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $maxx;
    my $maxy;
    my $sx;
    my $sy;
    
    if ($lx > $self->{'cur_x'}) {
	$maxx = $lx;
    } else {
	$maxx = $self->{'cur_x'};
    }
    if ($ly > $self->{'cur_y'}) {
	$maxy = $ly
    } else {
	$maxy = $self->{'cur_y'};
    }
    $sx = 1.0 + ($lx - $self->{'cur_x'})/$maxx;
    $sy = 1.0 + ($ly - $self->{'cur_y'})/$maxy;
    $self->{'cur_x'} = $lx;
    $self->{'cur_y'} = $ly;
    $zinc->scale('controls', $sx, $sy);
#   $main::scale *= $sx;
#   main::update_transform($zinc);
}

sub rotate {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my $langle;
    
    $langle = atan2($ly, $lx);
    $zinc->rotate('controls', -($langle - $self->{'cur_angle'}));
    $self->{'cur_angle'} = $langle;
}

sub release {
    my ($zinc, $self) = @_;
    $zinc->Tk::bind('<Motion>', '');
}

sub start_lasso {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @coords;
    
    $self->{'cur_x'} = $lx;
    $self->{'cur_y'} = $ly;
    $self->{'corner_x'} = $lx;
    $self->{'corner_y'} = $ly;
    @coords = $zinc->transform($top, [$lx, $ly]);
    $zinc->coords('lasso', [$coords[0], $coords[1], $coords[0], $coords[1]]);
    $zinc->itemconfigure('lasso', -visible => 1);
    $zinc->raise('lasso');
    $zinc->Tk::bind('<Motion>', [\&lasso, $self]);
}

sub lasso {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @coords;
    
    $self->{'corner_x'} = $lx;
    $self->{'corner_y'} = $ly;
    @coords = $zinc->transform($top, [$self->{'cur_x'}, $self->{'cur_y'}, $lx, $ly]);
    $zinc->coords('lasso', [$coords[0], $coords[1], $coords[2], $coords[3]]);
}

sub fin_lasso {
    my ($zinc, $self) = @_;
    my $enclosed;
    my $overlapping;
    
    $zinc->Tk::bind('<Motion>', '');
    $zinc->itemconfigure('lasso', -visible => 0);
    $enclosed = join(', ', $zinc->find('enclosed',
				       $self->{'cur_x'}, $self->{'cur_y'},
				       $self->{'corner_x'}, $self->{'corner_y'}));
    $overlapping = join(', ', $zinc->find('overlapping',
					  $self->{'cur_x'}, $self->{'cur_y'},
					  $self->{'corner_x'}, $self->{'corner_y'}));
    print "enclosed=$enclosed, overlapping=$overlapping\n";
}

sub showbox {
    my ($zinc, $self) = @_;
    my @coords;
    my @it;
    
    if (! $zinc->hastag('current', 'currentbbox')) {
	@it = $zinc->find('withtag', 'current');
	if (scalar(@it) == 0) {
	    return;
	}
	@coords = $zinc->transform($top, $zinc->bbox('current'));

	$zinc->coords($self->{'tlbbox'}, [$coords[0], $coords[1]]);
	$zinc->coords($self->{'trbbox'}, [$coords[2], $coords[1]]);
	$zinc->coords($self->{'brbbox'}, [$coords[2], $coords[3]]);
	$zinc->coords($self->{'blbbox'}, [$coords[0], $coords[3]]);
	$zinc->itemconfigure('currentbbox', -visible => 1);
    }
}

sub hidebox {
    my ($zinc, $self) = @_;
    my $ev = $zinc->XEvent();
    my $lx = $ev->x;
    my $ly = $ev->y;
    my @next;
    
    @next = $zinc->find('closest', $lx, $ly);
    if ((scalar(@next) == 0) ||
	! $zinc->hastag($next[0], 'currentbbox') ||
	$zinc->hastag('current', 'currentbbox')) {
	$zinc->itemconfigure('currentbbox', -visible => 0);
    }
}


Added jni/tkzinc/sandbox/alledges.pl.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-b&h-lucida-bold-r-normal-*-*-140-*-*-p-*-iso10646-1';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 300,
#		     -render => 1,
		     -backcolor => "grey50", # this will be transparent in the doc
		     )->pack();


my $i = 1;
my $x = 40;
my $y = 40;
foreach my $contour ( (['left'], ['right'], ['top'], ['bottom'],
		       ['top', 'bottom'], ['left','right'], ['left','top'], ['contour'],
		       ['oblique'], ['counteroblique'],['oblique','counteroblique']) )  {
    my $tab = $zinc->add('tabular', 1, 1, -position => [$x, $y],
			 -labelformat => "a5a5+0+0",
			 );
    my $contour_text = "['" . join ("','",@{$contour}) . "']";
    $zinc->itemconfigure($tab, 0,
			 -text => $contour_text,
			 -border => $contour,
			 -alignment => "center",
			 -filled => 1,
			 -backcolor => "gray95",
);
    $i++;
    if ($i == 5) {
	$x = 40;
	$y = $y + 50;
	$i = 1;
    }
    else {
	$x = $x + 160;
    }
}



MainLoop();

Added jni/tkzinc/sandbox/allgradients.pl.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr and N. Banoun banoun@cena.fr

use Tk;
use Tk::Zinc;
use strict;

my ($grp,, $s, $i);
my $defaultfont = '-b&h-lucida-bold-r-normal-*-*-140-*-*-p-*-iso10646-1';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 300,
		     -render => 1,
		     -backcolor => "red", # this will be transparent in the doc
		     )->pack();


$zinc->gname('black|white', 'axial 1');
$zinc->gname('black|white/90', 'axial 2');
$zinc->gname('black|white/30', 'axial 3');
$zinc->gname('black|black:0/30', 'axial 4');
$zinc->gname('white|black(-14 -20', 'radial 1');
$zinc->gname('white:50 0 70|black 50|white 100(0 0', 'radial 2');
$zinc->gname('white|black:80[-14 -20', 'path 1');
$zinc->gname('white|white 30|black:80[-14 -20', 'path 2');

$grp = $zinc->add('group', 1);
$zinc->add('rectangle', $grp, [0, 0, 70, 50],
	   -filled => 1,
	   -fillcolor => 'white',
	   );
$zinc->add('rectangle', $grp, [0, 0, 70, 50],
	   -filled => 1,
	   -linewidth => 1, # to help making the background transparent with gimp!

	   -fillcolor => 'axial 1',
	   -tags => ['rect']);
$zinc->add('text', $grp,
	   -text => 'axial 1',
	   -anchor => 'center',
	   -position => [35, -10],
	   -tags => ['txt']);
$zinc->translate($grp, 20, 30);
$i = 1;
foreach $s (('axial 2', 'axial 3', 'axial 4', 'radial 1',
	    'radial 2', 'path 1', 'path 2')) {
  $grp = $zinc->clone($grp);
  $zinc->addtag("g$grp", 'withtag', "$grp*attrs"); #, $grp, 0);
  $zinc->itemconfigure(".$grp.txt",
		       -text => $s);
  $zinc->itemconfigure(".$grp.rect",
		       -fillcolor => $s);
  $i++;
  if ($i == 5) {
    $zinc->translate($grp, -3*100, 80);
    $i = 1;
  }
  else {
    $zinc->translate($grp, 100, 0);
  }
}


MainLoop();

Added jni/tkzinc/sandbox/allgradients.tcl.

































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

lappend auto_path ..
package require Tkzinc

set defaultfont -b&h-lucida-bold-r-normal-*-*-140-*-*-p-*-iso10646-1
zinc .zinc -width 700 -height 300 -render 1 -backcolor red
pack .zinc


puts start
.zinc gname black|white {axial 1}
#.zinc gname {=conical 70 |white|gray20 50|white} {axial 2}
.zinc gname {=conical 70 |red|yellow 50|red} {axial 2}
.zinc gname {=axial -50 -50 50 50|black|white} {axial 3}
.zinc gname {=axial 30|black|black;0} {axial 4}
.zinc gname {=radial -50 -50 50 50|white|black} {radial 1}
.zinc gname {=radial 0 0|white;50 0 70|black 50|white 100} {radial 2}
.zinc gname {=path -14 -20|white|black;80} {path 1}
.zinc gname {=path -14 -20|white|white 30|black;80} {path 2}
puts end

set grp [.zinc add group 1]
#.zinc add rectangle $grp {0 0 70 50} -filled 1 -fillcolor white   
.zinc add rectangle $grp {0 0 200 300} -filled 1 -linewidth 1 \
    -fillcolor {axial 1} -tags rect
.zinc add text $grp -text {axial 1} -anchor center -position {35 -10} \
    -tags txt

.zinc translate $grp 20 30

set i 1
foreach s {{axial 2} {axial 3} {axial 4} {radial 1}
    {radial 2} {path 1} {path 2}} {

    set grp [.zinc clone $grp]
    .zinc addtag "g$grp" withtag "$grp*attrs"
    .zinc itemconfigure ".$grp.txt" -text $s
    .zinc itemconfigure ".$grp.rect" -fillcolor $s
    incr i
    
    if {$i == 5} {
	.zinc translate $grp [expr -3*100] 80
	set i 1
    } else {
	.zinc translate $grp 100 0
    }
}

Added jni/tkzinc/sandbox/alllineshapes.pl.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr

use Tk;
use Tk::Zinc;
use strict;

my $defaultfont = '-b&h-lucida-bold-r-normal-*-*-140-*-*-p-*-iso10646-1';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 420,
#		     -render => 1,
#		     -backcolor => "red", # this will be transparent in the doc
		     )->pack();


my $i = 1;
my $x = 20;
my $y = 20;
foreach my $lineshape ( qw(straight rightlightning leftlightning
			   rightcorner leftcorner doublerightcorner
			   doubleleftcorner) ) {
    my $wpt = $zinc->add('waypoint', 1, 1,
			 -position => [$x, $y],
			 -labelformat => "a5a5+0+0",
			 -leaderanchors => '% 100x100',
			 -leadershape => $lineshape,
			 -labeldistance => 120,
			 );
    $zinc->itemconfigure($wpt, 0,
			 -text => $lineshape,
			 -alignment => "center",
			 );
    $i++;
    if ($i == 4) {
	$x = 20;
	$y = $y + 150;
	$i = 1;
    }
    else {
	$x = $x + 210;
    }
}



MainLoop();

Added jni/tkzinc/sandbox/allreliefs.pl.













































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/perl
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr and N. Banoun banoun@cena.fr

use Tk;
use Tk::Photo;
use Tk::Zinc;
use strict;

my ($grp,, $s, $i);
my $defaultfont = '-adobe-helvetica-bold-r-normal-*-100-*-*-*-*-*-*';
my $mw = MainWindow->new();
my $zinc = $mw->Zinc(-width => 700, -height => 300,
		     -render => 1,
		     -backcolor => "red", # this will be transparent in the doc
		     )->pack();


$grp = $zinc->add('group', 1);
$zinc->add('rectangle', $grp, [0, 0, 70, 50],
	   -filled => 1,
	   -fillcolor => 'tan',
	   -linecolor => 'tan',
	   -linewidth => 6,
	   -relief => 'raised',
	   -tags => ['attrs']);
$zinc->add('text', $grp,
	   -text => 'raised',
	   -anchor => 'center',
	   -font => $defaultfont,
	   -position => [35, -10],
	   -tags => ['attrs']);
$zinc->translate($grp, 20, 30);
$i = 1;
foreach $s (('sunken', 'ridge', 'groove',
	     'roundraised', 'roundsunken', 'roundridge', 'roundgroove',
	     'raisedrule', 'sunkenrule')) {
  $grp = $zinc->clone($grp);
  $zinc->addtag("g$grp", 'withtag', 'attrs', $grp, 0);
  $zinc->itemconfigure("attrs && g$grp",
		       -text => $s,
		       -relief => $s);
  $i++;
  if ($i == 5) {
    $zinc->translate($grp, -3*100, 80);
    $i = 1;
  }
  else {
    $zinc->translate($grp, 100, 0);
  }
}


MainLoop();

Added jni/tkzinc/sandbox/allreliefs.tcl.





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# $Id$
# these simple samples have been developped by C. Mertz mertz@cena.fr and N. Banoun banoun@cena.fr

lappend auto_path [file join [file dirname [info script]] ..]
package require Tkzinc

set defaultfont "-adobe-helvetica-bold-r-normal-*-100-*-*-*-*-*-*"
zinc .z -width 700 -height 300 -render 1 -backcolor gray
pack .z

set grp [.z add group 1]
.z add rectangle $grp {0 0 70 50} -filled 1 -fillcolor tan -linecolor tan \
    -linewidth 6 -relief raised -tags attrs
.z add text $grp -text raised -anchor center -font $defaultfont \
    -position {35 -10} -tags texts
.z translate $grp 20 30

set i 1
foreach s {sunken ridge groove roundraised roundsunken roundridge roundgroove raisedrule sunkenrule} {
    set grp [.z clone $grp]
    .z itemconfigure "$grp.texts" -text $s
    .z itemconfigure "$grp.attrs" -relief $s
    incr i
    if {$i == 5} {
	.z translate $grp [expr -3*100] 80
	set i 1
    } else {
	.z translate $grp 100 0
    }
}

Added jni/tkzinc/sandbox/bouton-down.xpm.













































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/* XPM */
static char *on[] = {
/* width height num_colors chars_per_pixel */
"    90    86      249            2",
/* colors */
"b1 s mask c none",
".. c #f8fcf8",
".# c #080808",
".a c #101010",
".b c #181818",
".c c #202020",
".d c #f8f4f0",
".e c #605858",
".f c #484040",
".g c #383030",
".h c #282020",
".i c #201818",
".j c #302020",
".k c #181010",
".l c #100808",
".m c #e0ccc0",
".n c #806860",
".o c #503830",
".p c #f8e4d8",
".q c #805848",
".r c #c8bcb0",
".s c #887870",
".t c #f8dcc8",
".u c #f0d4c0",
".v c #d8bca8",
".w c #605048",
".x c #b89c88",
".y c #b09480",
".z c #403028",
".A c #785848",
".B c #f8b490",
".C c #705040",
".D c #885840",
".E c #f8ece0",
".F c #d8ccc0",
".G c #988c80",
".H c #c8ac98",
".I c #584840",
".J c #f8ccb0",
".K c #886858",
".L c #f8bc98",
".M c #382820",
".N c #a07058",
".O c #684838",
".P c #906048",
".Q c #b07050",
".R c #a06040",
".S c #f0e4d8",
".T c #d0c4b8",
".U c #b0a498",
".V c #908478",
".W c #706058",
".X c #c09c80",
".Y c #a07860",
".Z c #c89470",
".0 c #f8b488",
".1 c #b88460",
".2 c #805840",
".3 c #b07858",
".4 c #a87050",
".5 c #a06848",
".6 c #986040",
".7 c #b87048",
".8 c #b06840",
".9 c #f0dcc8",
"#. c #e8d4c0",
"## c #d0bca8",
"#a c #b09c88",
"#b c #f8d4b8",
"#c c #907868",
"#d c #e8c4a8",
"#e c #887060",
"#f c #d8b498",
"#g c #c8a488",
"#h c #705848",
"#i c #e0b490",
"#j c #b08c70",
"#k c #685040",
"#l c #c89c78",
"#m c #f8bc90",
"#n c #906850",
"#o c #a07050",
"#p c #b87850",
"#q c #b07048",
"#r c #a86840",
"#s c #f8e4d0",
"#t c #e0ccb8",
"#u c #d8c4b0",
"#v c #c0ac98",
"#w c #f8dcc0",
"#x c #a08c78",
"#y c #d8bca0",
"#z c #988470",
"#A c #f8cca8",
"#B c #786050",
"#C c #987860",
"#D c #d8ac88",
"#E c #d0a480",
"#F c #604838",
"#G c #b08460",
"#H c #584030",
"#I c #785840",
"#J c #d09c70",
"#K c #c89468",
"#L c #c08c60",
"#M c #b07850",
"#N c #906040",
"#O c #a87048",
"#P c #a06840",
"#Q c #f0d4b8",
"#R c #e0c4a8",
"#S c #d0b498",
"#T c #c8ac90",
"#U c #c0a488",
"#V c #b09478",
"#W c #e0bc98",
"#X c #a08468",
"#Y c #c09c78",
"#Z c #f8c498",
"#0 c #907058",
"#1 c #886850",
"#2 c #806048",
"#3 c #f8bc88",
"#4 c #a07858",
"#5 c #b88458",
"#6 c #b07040",
"#7 c #f8d4b0",
"#8 c #e8c4a0",
"#9 c #d8b490",
"a. c #d0ac88",
"a# c #f8cca0",
"aa c #c8a480",
"ab c #b89470",
"ac c #b08c68",
"ad c #f8c490",
"ae c #d0a478",
"af c #a88460",
"ag c #c89c70",
"ah c #c09468",
"ai c #987050",
"aj c #b88c60",
"ak c #f8bc80",
"al c #906848",
"am c #b08458",
"an c #a87850",
"ao c #886040",
"ap c #a07048",
"aq c #e0dcd0",
"ar c #a09c90",
"as c #807870",
"at c #e8dcc8",
"au c #e0d4c0",
"av c #c8bca8",
"aw c #c0b4a0",
"ax c #605850",
"ay c #a89c88",
"az c #f0dcc0",
"aA c #a09480",
"aB c #887868",
"aC c #403830",
"aD c #b09c80",
"aE c #685848",
"aF c #907860",
"aG c #605040",
"aH c #705840",
"aI c #483828",
"aJ c #f8f4e8",
"aK c #b8b4a8",
"aL c #b0aca0",
"aM c #989488",
"aN c #787068",
"aO c #f8ecd8",
"aP c #f0e4d0",
"aQ c #706860",
"aR c #d8ccb8",
"aS c #d0c4b0",
"aT c #b8ac98",
"aU c #585048",
"aV c #b0a490",
"aW c #504840",
"aX c #f8e4c8",
"aY c #988c78",
"aZ c #e0ccb0",
"a0 c #d8c4a8",
"a1 c #908470",
"a2 c #c8b498",
"a3 c #c0ac90",
"a4 c #b8a488",
"a5 c #f8dcb8",
"a6 c #786858",
"a7 c #e8cca8",
"a8 c #706050",
"a9 c #a89478",
"b. c #e0c4a0",
"b# c #d8bc98",
"ba c #a08c70",
"bb c #d0b490",
"bc c #988468",
"bd c #c8ac88",
"be c #302820",
"bf c #c0a480",
"bg c #b89c78",
"bh c #887058",
"bi c #e0bc90",
"bj c #584838",
"bk c #b09470",
"bl c #806850",
"bm c #a88c68",
"bn c #f8cc98",
"bo c #786048",
"bp c #504030",
"bq c #c8a478",
"br c #987858",
"bs c #b89468",
"bt c #886848",
"bu c #c8c4b8",
"bv c #888478",
"bw c #686058",
"bx c #484038",
"by c #282018",
"bz c #c8bca0",
"bA c #a89c80",
"bB c #e8d4b0",
"bC c #d8c4a0",
"bD c #c8b490",
"bE c #b8a480",
"bF c #a08c68",
"bG c #e0d4b8",
"bH c #f0e4c8",
"bI c #d8ccb0",
"bJ c #706048",
"bK c #e0dcc8",
"bL c #c0bca8",
"bM c #807868",
"bN c #f8f4e0",
"bO c #d8d4c0",
"bP c #787060",
"bQ c #f0ecd8",
"bR c #e8e4d0",
"bS c #c8c4b0",
"bT c #b0ac98",
"bU c #f8fcf0",
"bV c #f8fce8",
"bW c #505048",
"bX c #484840",
"bY c #303028",
"bZ c #282820",
"b0 c #181810",
"b2 c #000000",
/* pixels */
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1.0a#.J#waO.E.................E.p#w#ba#adb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1ad#A.taJ...d....#.bG#D#D#D#D#D#D#D#9#.bG........aJ#s#7bnb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#baO......#t#D#L.7.8.8.8.8.8#r.8.8.8.8.8.8.8.8.7#L#DbG......#s#Ab1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1a##s.d..aJb.#L.8.8#r#r#r#r#r#r#r.8#r.8#r.8#r#6.8#6.8#6#6.8.8.8#Kb.aJ...d#w#3b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#m#sbU..bG#J#r#r#r#r#r#r#r#r#r#r#r#r#r#r#r#r#r#r#r#r#O#r#O#r#O.8#q.8.8.8#J#.....#s#Zb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#m.t....b..7.8#r#r#r#r.R.R#P.R.R#P.R#P#P#P#P.5#P#P.5#P.5#P.5#r#O#r#O#O#O#O#q#q#q#pb.....aX#mb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1a5.d..b..7#r#r#r.R.R.R.R.R#P.6.6#P.6.6.6.P.R.6.6al#P.5.6.5#Pal.5al#P.5#P#r#O#O#O#6#q#q#p#d..aJ#bb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1a#aJ...9#5#r#r#r.R.R#P.R.6.6.6.6.6#N#N#N.P#N#N.Pal.6.6.P#Nal.P.P.Pal.5.Pal.5al.5#O#O#O#q#q#q#q#KaP...Ea#b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#7.daJae#r#r#r.R.R#P.6.6.6.6#N#N#Naoaoaoaoaobtaoaoaoaobtbt.Pbt.P.P.P.P.Pal.P.Palalalal.5ap#O#q#q#q#q#DaJ.d#wb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#3.t...9#p#r#r#r.R#P.6.6.6#N#Naoaoao.2.Dbt.q.2.q.2.2.q.q.q.q.2.2#2.2#2#2#2.qbtbtal.Palalalai#o#o#o.4.Q#p#M#LaP..#sa#b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1ak.E..b.#r#r.R.R.R.6.6.6#Naoao.D.D.2.q.q#I#I#I#F.z.M.ib0.#.#.#.#.#.#.#b0.i.MaI#F.q.q#2bt.P.Palalal.5ap#O.4#M#M#p#d...E.Bb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1a#aJ.d.Z#r#r.R#P.R.6.6#Nao.D.D.2.2#2.2#I.O.zby.#.#.#.#aC.gaQaQ.WaQbw.WaQ.gaC.#.#.#.#byaC.C#2#1bt#n#naiai#o#o.4#M#M#M#E..aJ#mb1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1a#.daJ.Z#r#r.R#P.6.6#N#N.Dao.2.2.q#I#IaI.i.#.#.caUbv.UaRaRaR#uaSaS#uaSaS##aS#####a.saW.c.#.#.i.o.q.qbt#nalai#o#o.4#M#M#p#EaJ.da#b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1a#.daJ#p#r#P.R.R.6.6#Naoao.2.2#2#IaH.M.a.#b0.e.UaRaRaRaRaR.TaR.TaS#uaSaS#uaS##aS###########aax.a.#.a.z.A#1bt#n#nai#o#oan#M#MahaJ.d#Zb1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1ad.E..#p#r.R#P.R.6#N#Nao.D.2.q.2#I.z.l.#bYbv.FaRaRaRaRaRaRaRaR#u.TaR.TaRaSaSaSaS##aS########bzbzbzaBbe.#.laI#2#1#n#nai#o.4an.3#pah...E#3b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1.E...Z#r#P#r.R.6#N#N.D.2.2.2#I#Hb0.#.caV.FaRaRaR.F.TaR.FaR.TaR.FaR.TaR.TaR#uaSbIaSaSaS########bzbz#Sbz#x.i.#b0#F#1#n#naiai.4an.3#p#E...Eb1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1.t..ae#r#r#r.6.6#Nao.D#2.2.A#Ibe.#.aas.F.TaR.F.T.FaR.FaR.F.FaR.FaR.FaRaRaRaRaRaR.TbIaS##aS##########bz#Sbz#SbP.k.#.M#2#1#nai#o#4anam#p#i..aXb1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1#A..b.#r#r#P.6.6#Naoao.2.2#I.Ob0.#.faSaRaRaR.F.F.FbO.F.FbO.FbO.FbKbOauauauau.m.maR#taR#ubIaSaS######bz##bz#Sa2a2a3bx.#.b#h#1#nai#o#4.3am#5bB...Jb1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1a#.d.9#r#r#P.R.6#N#N.D#2.2.A#F.#.#as.F.F.F.F.F.F.FbO.FbObObKbKbKaubRbRbRatbKatbKat#.bK#.aRaRaRbIaS######bzbz#Sbz#Sa2.Ha6.#.l#k#n#0br#o#4.3am#L.S.dadb1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1aO..#5#r#r.R.6#N#Nbt.2.2#IaI.l.baLaRaR.F.F.FbO.FbObObObKbKbRbRbRbR.p.S.S.S.p.S#saPaPaPaP#.auau#tbIbI##a0####bz#Sbz#Sa2.Ha9.a.lbx#n#0br#4#4.3#5ah..aOb1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1#7..#D#r#r#Pal.6.Pao.2.2.qaC.#.cbTaR.F.FaR.F.FbO.FbKbKbKbRbR.E.E.E.SaO.EaOaObQaObQ.p.S#saPaPbH.9bH#tbGbI#ua0#####Sa2a2a2a2a2a9be.#bp#nbr.N#4am.1.1b....Jb1b1b1b1b1b1b1",
"b1b1b1b1b1b1ad.d.S#6#r#P#P.6#Nao.q.2bo#H.#bYbSaR.F.F.F.FbObObObK.SbR.S.E.E.E.E.E.E.E.EbQ.EaOaO.SbQ#saPaPaPaPbH.9.9.9#taZ#ta0bzbzbza2#SbD.H#T#UbZ.#aG#0br.Nafam.1#L.EaJbnb1b1b1b1b1b1",
"b1b1b1b1b1b1#w..ah#r#r#P.6.P#Nbt.2#2#F.#.baSaR.F.FaRbObObOaqaq.S.E.E.E.E.E.EbN.EbN.E.E.E.EbQ.EbQaObQ.paP#saPaP.9.9#.az#.#.aZa0.vbz#Sa2a2a2#Ta3a4.a.l#k#0br#4af.1aj#E..#wb1b1b1b1b1b1",
"b1b1b1b1b1ad.dbG.8#r.5.R.P#Nao.2.q#k.a.bbT.FaR.F.F.FbO.FbKbRbR.E.E.EbNaJbNbNaJbNaJbNbN.EbN.EaOaO.SaO.S#saPaPaP.9bH.9#.az#Q#.aZaZ#ybz#S#S#TbD#Tbda9.a.kblbrbr#4#Gaj#LaP.d#mb1b1b1b1b1",
"b1b1b1b1b1#b..#L#r#r#P.6.Pao.q#2#I.i.#aMaR.T.F.F.FbObKaq.S.E.EaJbNaJaJ.EaJaJaJaJaJaJaJbN.E.E.E.E.EbQaObQaP#saPaPbH.9bHaz#.#QbGbG#R.vbza2a2.H#T#TbdaF.#.h.Kbr.Yaf#Gaj#l..a5b1b1b1b1b1",
"b1b1b1b1b1aJ.9.8#r.5.5al#Nbt#2.2.z.#.eaRaR.FbO.FbObKbRbR.E.EaJbNaJaJaJaJaJaJaJaJaJaJ.EaJbNbN.E.EbQaO.pbQ.p.SaPaP.9bH.9#.az#.#Q#QbGa0#R#S#SbD#T#T#Ua3aG.#aCbrbraf#Gaj#L.SaJb1b1b1b1b1",
"b1b1b1b1.J..#J#r#O#P.6#Nbt.q.2#k.lbYaR.FaR.F.FbObKbR.E.E.EaJ.EaJaJaJaJaJaJaJaJaJaJaJaJaJaJ.EbN.E.E.EbQaO.S#saP#sbH.9.9az#.azbG#QbG.JbB#y#Sa2#Ta3#Tbd#U.h.l#Bbr.Yafajah#W..#Ab1b1b1b1",
"b1b1b1b1#saJ.8#O#r.5al.Pbt.q.Aby.#bTaRaR.F.F.FbObK.S.E.EaJbNaJaJaJaJaJaJaJaJaJaJaJaJaJaJaJaJ.EbN.EbQ.E.SaOaP.paPaP.9bHazaz#.azbG#QbBbB.vbz#SbD#T#Ubd#gba.#.M#0.Yaf#GbsahaJaOb1b1b1b1",
"b1b1b1#m..#R#q#r.5.6.P.Pbt#2bj.#aUaR.F.T.F.F.FbKbR.E.EaJ.EaJaJaJaJaJ.daJbU.d.d.dbU.daJaJaJbNaJ.E.E.EaOaO.SaOaPaPaPbH.9.9#.az.u#Q#tbBbBa7#y#S#T#T#T#U#Ubdbx.##k#C.Yaf.1ah.u..adb1b1b1",
"b1b1b1#b..ah#r#O.5al.Pbt.q.A.i.a.raR.TaRbO.FbKbR.E.E.EbNaJaJaJaJaJbU.dbV.d.dbV.dbV.dbVaJaJaJaJbNbN.E.EbQaO.S.paPaPaPbH.9az#.azbG#QbBbB#dbB#y#SbD#T#Ubd#Ubg.k.c#0.Ybmacaha....Jb1b1b1",
"b1b1b1aOaJ.8#q#r.5al.Pbt.q#F.#aQaRaRaR.F.FbObKbR.E.EbNaJaJaJaJaJbUbUbU.dbUbV.dbU.dbUaJ.daJaJ.EaJ.E.EbQ.E.SaOaPaP#s.9.9atazaz#.#QbG#tbB#dbB#y#S#Tbd#UbdbfbfaE.#bo.YbmacbsahaJaXb1b1b1",
"b1b1b1.dbB.8#O.5.5al.Pbt.Abe.#aw.TaR.F.TbObKbR.p.E.EbN.EaJaJaJ.dbUbU.dbV.d..bUbU..bUaJbUaJaJaJaJbN.E.E.EbQbQ.paPaPaPbH.9#.az#.#Q#QbBbB#d#R#Rb#bD#Tbd#U#Ubfba.#bY#C.Yacbsab.9.db1b1b1",
"b1b1a#..#D#q#O#O.5.Pbt#2#I.laU.TaR.TaR.F.F.mbR.E.E.EaJaJaJaJaJaJ.dbUbU.dbU..bU....bU....aJaJaJaJ.EbN.E.E.paO.S#saPaP.9bH.9azaz#.#Q#t#tbBa7#R#ybb#T#Ubd#Ubfaabx.lbh#Xacahab#d..#Ab1b1",
"b1b1#A..#L#q#O#Oalal.P#2aC.#.GaR.TaR.FbOaubR.EbQ.EbN.EbNaJaJaJ.dbV.d..bUbU........bU..bU.daJaJaJbN.E.E.EaObQ.paPaPaPbH.9az#.#.#QbG.JbB#dbB#db.#SbD#Tbdbfbfbfbh.#.I#Cbmababa...#7b1b1",
"b1b1#b..#6#q#O.5alalbt.qby.baR.TaRaR.TbObObR.S.E.EbNaJaJaJaJaJaJ.dbUbUbU..............bUbUaJaJaJ.EbN.EbQ.EbQ.S#saPaP.9.9atazazbG#QbGbBbB#d#Rb.b#bbbd#U#Ubf.Xbf.abe#Xbmababae..#bb1b1",
"b1b1.p.S.7#q#O.4ai.P#1#2.#aUaSaRaRaR.FbKbR.p.EaObN.EbNaJaJaJ.daJbUbU....bU............bUbUbUaJaJaJ.E.E.EbQ.pbQ.S#saP.9bHaz#.az#QbG.JbB#dbB#db.b.#S#Tbd#Ubfbf#Ybp.lbcbmababagaJaOb1b1",
"b1b1aO#..7.Q.4.5al#nbt#F.#.saSaR.TaR.F.mbRaObQ.E.E.EaJaJaJaJaJbV.d.......................daJaJaJ.EbNbQ.EaObQ#saPaPaP.9.9ataz#..ubG#tbBaZa7#Rb.b.#9#Tbdbfbf.Xbf#B.#blbaab#Y#laP.Eb1b1",
"b1b1..#d#p#q.4ap#o.PbtaC.#awaS#u.TaR.FauatbQ.EaO.EbN.EaJaJaJaJ.dbV.dbU..................bUaJaJaJbNbN.E.EbQaO.S.paP.9bH.9az#.azbG#QbBbB#da7#db.b.#S#Tbd#Ubfbf#Yba.#bjbmab#Y#l.9.db1b1",
"b1b1..#9#p#M.4#oai#n#2.j.##uaSaR.TaRaRbObR.SaO.EbN.EaJbNaJaJaJbU.dbU....................bUbUaJaJ.E.E.E.EbQ.pbQaPaP.9.9ataz#.azbG#QbBbB#d#R#Rb.b.#9#Tbdbfbf.X#Y#Y.#bYbabg#YbqbG..b1b1",
"b1b1..#i#p#M.4#oai#n#2by.gaSaS#u.TaRauat.S.pbQaO.EbN.EaJaJaJaJaJbU....................bU.daJaJaJbNbN.EbQaO.S.paP#saPbHazat#Q.u#Q#tbB#dbBa7#db.b.#Wbbbd#gbfbf#Ybf.M.hbaab#Yaa#Q..b1b1",
"b1b1..b##p#M#M.4al#nbl.kbxaSaSaSaRaR.FataOaOaObQ.E.EbNaJaJaJaJaJaJbUbVbU................bU.daJ.EaJ.E.E.EaObQ#saPaP.9.9atazazbG#Q#tbBbB#R#d#R#Wb.#Wbbbdbf.Xbf#Y#YaC.kbabg#Yaa#Q..b1b1",
"b1b1..#W#p#pan#oai#nbt.#.WaS#u#u.TaRauataP.SaO.E.E.E.E.EaJaJaJaJaJaJ.dbUbUbU....bUbUbUbUbUaJaJbN.E.EbQaObQ.paPaPaP.9bH.9#.azbG#Q#tbB#dbBa7b.b.b.#Wbbbd#U#Ybf#Y#Y#k.#babgbf#EbG..b1b1",
"b1b1..#W#p#M#M#oai#nbl.#aQaSaSaSbIaR.Fat.paO.SaObQ.EbNbN.EaJaJaJaJaJaJ.daJbUbUaJ.dbUbU.daJaJaJ.EbN.EaObQ.pbQ#saP.9bH.9az#.az#QbG.JbB#d#R#Rb.b.#W#Wbb#gbfbf#Ybg#YaG.#babg.X#Eaz..b1b1",
"b1b1..#W#p#Man.4ai#n#1b2.WaS##aSaSaR#tataP.SaOaOaO.EbQ.EbN.EaJaJaJaJaJaJaJaJ.daJaJaJaJaJaJbNbN.E.EbQ.EbQ.paPaP#saP.9.9azaz#.bG#QbBbBbB#d#db.b.#W#Wbbbdbfbf#Ybf#YaG.#a9bEaaaa.u..b1b1",
"b1b1.daZ#p#5.3#o#o#nbl.#.W##aSaSaS#u.FataP#saP.SbQbQ.E.E.EbN.E.EbNaJaJaJaJaJaJaJaJaJaJaJaJaJ.E.E.EbQaOaObQ#saP.9bHazataz#.#Q#Q#tbBaZa7#R#R#Wb.#W#Wbb#gbfbf#Ybgbf#k.#babEbfa..9.db1b1",
"b1b1.p.9#5#pan.4br#n#1.#.WaS##aSaSaRaR#.aP.SaPaO.paOaO.EbQ.E.EbN.E.EaJbNaJaJaJaJbNbN.EbN.E.E.E.EbQaObQ.S#saPaPaP.9.9.9az#.#QbGbBbB#da7#db.b.b.b##Wa.aabf.X#Y#Y#YaEb2a9.X#Ua..E.pb1b1",
"b1b1aO.E#p#5.3#oai#n#1.#.W##aS##aS#uaRataP#saP.SaObQ.pbQ.EbQ.E.E.EbN.E.E.EbN.EbN.EaJ.E.E.EbQaObQaObQ.paPaPaPaP.9.9ataz#.bGaz#t.JaZa7#R#Rb.#W#W#W#9bbaabf#Ybg#Y#YaG.#a9bE#ga.aJ.pb1b1",
"b1b1#b..#p#5#4#4.Nbr#1.abx####aS##aSaRau.9aP#saP.S.pbQbQ.paObQ.E.E.EbN.EbN.E.E.E.E.EbN.E.EaO.EbQ.paJbQ#s#saPbHbH.9az#.az#QbGbBbB#dbB#db.b.b.#W#W#9a.aabf#Ybfbgbf.z.ba9bE#ga...#wb1b1",
"b1b1#7..#l#p#5an#o#0#1by.g######aS#ubIau.9aP#saP#saP.S.pbQbQaObQbQ.EbQ.E.E.E.EbN.E.EbQbQaObQ.SaObQaPaOaPbHaPbH.9atazazbG#..J#tbBa7#R#db.b.#Wb##W#9a.aabfbg#Y#YaabY.ha9#Ubdbz..#Ab1b1",
"b1b1ad..#i#5am#4#4br.Kbe.#######aS##aSaRau.9aPaPaP#sbQ#s.S.pbQ.SaOaObQ.EbQaObQbQbQbQaOaOaO.SaO.paPaO#saP#sbH.9bHazaz#.#Q#Q#tbBa7a7#db.b.#W#W#W#9bbaabf#Y#Y#Y#Ybf.#aCbAa4bdaz...Lb1b1",
"b1b1b1.d#.#5.3#4#4br#1aC.#a3#########u#ubG.9.9.9aPaPaPaPaOaP.SaObQ.SaOaOaObQ.SaOaO.pbQ.S.SaOaPaP#saPaPaXbHbH.9az#.#.#QbGbGbBbB#d#R#Rb.b.#W#W#W#9a.aabf#Ybg#Ybf#X.#aU.y#U#T.p.db1b1b1",
"b1b1b1#saJ#5am.3#4br#0#h.#bM########aSbI#t.9bH.9.9aP#saPaP#saP#s.S.p.S.S.S.pbQ.S.SaO.p#sbQaP#saPaPbHaPbHbHbHazazaz#.#QbG.JbB#dbB#R#8b.#W#W#W#9#Wa.aa#Ybf#Ybgbf#B.##e#a#Ubb.d#sb1b1b1",
"b1b1b1.J..aa#5#G#4br#0.K.laWbz#########ubG#..9.9bH.9.9aPaPaPaPaP#saPaP#saOaP.paP.paPaPaP#saPaPbHaPbHbHbH.9azazazbGazbB#tbBa7aZ#db.b.b.#W#Wb##9#9#Ebf#Y#Y#Ybfaabx.aa9a4#T##...Jb1b1b1",
"b1b1b1.0..bB#5#G#4#4#0#1bZb0bzbz#########ubGaz#..9.9bH.9.9aP#saPaPaP#saPaPaPaPaPaPaP#saPaPaPbHaP.9.9.9.9azazaz#..ubB#tbB#dbB#R#db.b.#W#W#W#9bia.aa#Y#YbE#Y#Ybf.kbYbAa4#T.p...0b1b1b1",
"b1b1b1b1.paJ.1#G#G#4br.Kbx.#a1bz##bC####bI#taz.9azat.9bH.9.9.9.9aPaPaP#saPaP#saPaPaP.9bH.9.9.9.9.9.9#.az#.#.#.#QbBbG.JbBbB#d#Rb.b.b.#Wb##9#W#9#Ebf#Ybf#Ybfbfbh.#ax#aa3#TbU#sb1b1b1b1",
"b1b1b1b1#A..#i.1af#4#Cbrbl.l.Ibzbz##bC#####uaZ#.azaz#.azatbHbH.9.9.9.9.9.9.9.9.9.9bH.9.9bH.9at.9az#.azazazbGazbG#QbBbB#d#d#R#8b.#W#W#W#W#9#9a.aa#Y#Y#Y#YbfbfaC.aaY.x#v.9..#Ab1b1b1b1",
"b1b1b1b1b1.E.Saj#Gaf#4#0.KbY.#.x#Sbzav#######taz#.#.az.9az#.azat.9.9bHbH.9bH.9bH.9.9.9at.9bHaz#.azaz#.azbG#Q#tbBbB#dbBa7#Rb.b.b.b.b##W#9bi#D#Ebfbfbg#Y#Ybfbk.#aCbAaV#TaJaJb1b1b1b1b1",
"b1b1b1b1b1#b..bq#G#G.Y#C#0aE.#a8bz#SbzbzbC##a0aZbGaz#.#.#.azatazazazat.9#.az#.az#.azataz#.az#.azaz#.azbG#QbG#QbB#dbBa7#R#db.b.#W#W#W#9#9#9a.bf#Y#Y#Y#YbfaaaE.#aBaVa3##..#bb1b1b1b1b1",
"b1b1b1b1b1.0.daP.1#Gafbrbr.Kby.a#vbz#Sbzbz##a0aZ.u#Q#.azaz#.az#.azatazazazataz#.az#.az#.azaz#.#.bG#QbG#QbB#QbB#dbB#d#R#Rb.b.#W#W#W#9#W#9#D#Ebf#Y#Ybgbfbfbg.abZayaVa2aJ.d#3b1b1b1b1b1",
"b1b1b1b1b1b1#b..#g#Gaf.Y#CaFaE.#aW#Sbz#S#Sbz####aZbG#QbG#Q#.az#.az.u#.#.az#.az#.az#.azbGazbG#Q#Q#QbGbBbBbB#dbB#d#R#Ra7#Wb.#W#W#W#9#9#9#Da.bf#Y#Ybf#Ybfaabx.#aNaV.H##..#wb1b1b1b1b1b1",
"b1b1b1b1b1b1.0.d.Ebs#Gaf.Y#Cbhbe.#bA#Sbzbz#Sbzbz.vaZ#QbG#QbG#QbG#QbGaz#Q#.#Q#.#QbG#QbG#QbG#QbGbGbB#QbBbB#dbBa7#Ra7b.b.b.#W#W#Wb##9bi#Da.bf#Y#Y#Y#Ybfbfbm.#.gaya3aw.d.d.Bb1b1b1b1b1b1",
"b1b1b1b1b1b1b1.J..#dbsafaf#CaF#B.a.ha2.H#Sbz#Sbz#ya0bB#QbG#QbG#QbG.u#QbG#QbG#QbG#QbG#QbG#QbBbB.JbBbB#d#dbB#R#R#db.b.b.#W#W#W#9#9bi#D#9#Eaa#Y#Y#Ybfbfaa.h.a.VaVaw.p..#Ab1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1aO..#Yacbm.Y#CaFbx.#.wa2a2a2a2#Sbz#ya0#RbBbBbB#t#QbGbG#QbG#QbG#Q#tbBbBbBbB#tbBaZ#d#dbB#R#R#db.b.b.b.#W#Wb#b#bi#9#Da.aabf#Y#Ybfbfbfaabj.#axaV#vav..#sb1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1#m.d.Sbsacbm.Y#CaF.h.##ca2a2a2a2#Sbzbz#y.vbB.JbBbB.JbBbBbBbBbBbB.JbBbB#dbB#d#dbBa7#R#Ra7b.b.b.b.#W#W#W#W#9bi#9#Da.bfbq#Y#Ybgbf#Ybfbh.#.gayaTbLaJ.d.Lb1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1#7...9bsbmbmbcbcbh.k.aa9.Ha2.Ha2#S#S#Sbz#ya0#dbBaZ#dbB#dbB#dbBaZ#d#dbB#dbB#d#R#R#d#db.b.b.#W#W#W#Wb##9#9#9a.a.bf#Ybf#Y#Y#Ybfaaba.a.baMaTaw.E...Jb1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1aX..#dbsbm#X#X#ca8.a.a#UbD.HbD.Ha2a2#Sbz#S.va7#dbB#dbBaZ#dbB#da7aZ#d#R#R#R#R#8b.b.b.b.#W#W#W#Wb##9bi#9a.aabf#Y#Y#Y#Ybfbfaabg.a.a.saTaw.p...tb1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1.E..a3#jac#X#XbcaG.#bZ#U#T#T.HbD.Ha2#S#S#S#y#y#y#R#d#d#R#R#R#R#d#Ra7#8b.b.b.b.#W#W#W#W#Wb##9bia.a.a.aa#Y#Y#Y#Ybgbfbfbfbg.h.#bMbTawbu...Eb1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1.L.E.d.Xabbabmbcbc.I.#.h#x#T#T#T#T#T#TbDa2#S#S#S#y#yb.a7#8#Rb.b.b.#Wb.b.#W#W#W#Wb##Wb##9bibba.aabfbf#Y#Ybgbf#Ybf#YbfbF.i.#bwaLaw.r.d.E.0b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1.0.d.dbfab#jba#Xbc.I.l.aba#U#T#T#Ta3#T#T#TbD#TbDbDb##S#S#fb.#Wb.b.#W#Wb.#W#W#W#Wa.bbbba.aaaabfbf#Ybgbf#Y#Ybfbfbfbm.a.abwbTaw.rbU.d.Lb1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1bn.d.d.Hbkbkba#X#za6.a.#a8bda3#U#Tbda3#Ta3#T#T#TbbbDbbbD#9#Sbbbbbbbbbbbbbbbbbbbdbdaaaabfbf#Y#Y#Y#Y#Y#YbfbfaabJ.#.abvaLbLbu.d.d#mb1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1#AaJ...H#Vbkbaba#z.n.i.#aCbEbd#U#Ubd#Ubd#Ubd#U#Tbd#Tbd#TbDbb#Tbd#Tbdbd#gbdaabf.Xbfbf#Y#Y#Ybg#Y#YbfbfbfbgbY.#.c.Gawawbu..aJ#mb1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#ZbN..bHbg#V#Vbabaa1aC.#.aa8bd#Ubda3bda3bdbd#U#U#U#Ubd#g#Uaa#gbf#gbfbfbfbf.X#Y#Y#Ybg#Y#Ybf#Ybfbf#YbJ.a.#.f.UaKbLaJ...p.0b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#m.t...Ebf#V#Va9ba#x.W.i.#.i#c#Ubf#Ubf#U#U#U#U#Ubf#Ubfbf#Ubfbfbf.Xbf.Xbf#Y#Ybgbf#Ybfbg#Ybfbf#C.i.#.hasawaK.r.d...t.0b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#A...d.ubEaDa9a9#xaY.I.l.#bea6bfbfbfbfbfbfbfbfbfbfbfbfbfbf.Xbf#Y#Y#Y#Ybgbf#Ybg#Ybfbfbl.h.#.a.e.UaKbLaJbUbU#7b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#Z.E..bQa3bEaDaDbAa9a1bxb0.#.a.I#Xbfbfbfbfbf.Xbf.X#Y.X#Y#Y#Y#Ybg#Ybg#Y#Ybfbf#Xbj.a.#.bbWaraKbLbu.d...E#Zb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#w.d..aPa3bEaDaDbA#xaA.wbZ.#.#.ibp#B#X#Y#Y#Y#Ybg#Ybg#Ybg#Y#Ybf#Ybcblbp.b.#.#bYbwaLaLbL.r.d..aJ#bb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#Z#s.....pa3.xa4#a#aayaAa1aUbY.#.#.#.#bebYaGaGaGaGaG#kaGbYbe.#.#.#.#.gaxaMaLaKbLbuaJ....aX#mb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1a#aX.....Eaz#UaVa4#a#aayayayaNax.fbY.h.#.#.#.#.#.#.#.hbYbX.easaLaLaLbL.rbN.d....#sadb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1ad.t.d...daOava3a3aTaTaTaVaVaV.UaV.UbTbTbTbTaLaLaLaLaLaw.r.r.rbu.dbU...daX#Zb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#7#s......aJ.pavbzbzbzawbzavavavav.ravavav.raS.TbuaJ.d......#s#7b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1ad#A.t.E........aJaJaO.E.E.E.EaJ.EaJ.d.d........aJ#s#A#Zb1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1#3a##b#w.p.E...........d.....EaO#w#wa##3b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
"b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1",
};

Added jni/tkzinc/sandbox/bouton.xpm.



















































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
/* XPM */
static char *on[] = {
/* width height num_colors chars_per_pixel */
"    90    86      236            2",
/* colors */
".b s mask c none",
".. c #f8fcf8",
".# c #f8fcf0",
".a c #f8fce8",
".c c #f8f4f0",
".d c #f8f4e8",
".e c #f8f4e0",
".f c #f8ece0",
".g c #f8ecd8",
".h c #f8ecd0",
".i c #f8e4d8",
".j c #f8e4d0",
".k c #f8e4c8",
".l c #f8dcc8",
".m c #f8dcc0",
".n c #f8dcb8",
".o c #f8d4b0",
".p c #f8ccb0",
".q c #f8cca8",
".r c #f8cca0",
".s c #f8cc98",
".t c #f8c498",
".u c #f8c490",
".v c #f8bc98",
".w c #f8bc90",
".x c #f8bc88",
".y c #f8bc80",
".z c #f8b490",
".A c #f8b488",
".B c #f0ecd8",
".C c #f0e4d8",
".D c #f0e4d0",
".E c #f0e4c8",
".F c #f0dcc8",
".G c #f0dcc0",
".H c #f0d4b8",
".I c #f0d4b0",
".J c #f0ccb0",
".K c #f0cca8",
".L c #e8e4d0",
".M c #e8dcc8",
".N c #e8d4b8",
".O c #e8d4b0",
".P c #e8ccb8",
".Q c #e8ccb0",
".R c #e8cca8",
".S c #e8c4a8",
".T c #e8c4a0",
".U c #e8c498",
".V c #e8bc98",
".W c #e0c4a8",
".X c #e0c4a0",
".Y c #e0c498",
".Z c #e0bc98",
".0 c #e0bc90",
".1 c #e0b488",
".2 c #e0b480",
".3 c #e0ac88",
".4 c #e0ac80",
".5 c #d8d4c0",
".6 c #d8bca0",
".7 c #d8bc98",
".8 c #d8b498",
".9 c #d8b490",
"#. c #d8b488",
"## c #d8ac88",
"#a c #d8ac80",
"#b c #d8ac78",
"#c c #d8a478",
"#d c #d8a470",
"#e c #d89c70",
"#f c #d0c4b0",
"#g c #d0bca8",
"#h c #d0bca0",
"#i c #d0b498",
"#j c #d0b490",
"#k c #d0ac88",
"#l c #d0a480",
"#m c #d0a478",
"#n c #d0a470",
"#o c #d09c70",
"#p c #d09c68",
"#q c #d09468",
"#r c #d09460",
"#s c #c8bcb0",
"#t c #c8bca8",
"#u c #c8b498",
"#v c #c8a480",
"#w c #c89c70",
"#x c #c89468",
"#y c #c88c60",
"#z c #c88c58",
"#A c #c88458",
"#B c #c88450",
"#C c #c0ac98",
"#D c #c0ac90",
"#E c #c0a478",
"#F c #c09c78",
"#G c #c08c68",
"#H c #c08c60",
"#I c #c08458",
"#J c #c08450",
"#K c #c07850",
"#L c #c07848",
"#M c #c07048",
"#N c #b8b4a0",
"#O c #b8aca0",
"#P c #b8a490",
"#Q c #b8a488",
"#R c #b8a480",
"#S c #b89c80",
"#T c #b89470",
"#U c #b88c60",
"#V c #b87848",
"#W c #b87048",
"#X c #b87040",
"#Y c #b86840",
"#Z c #b09c80",
"#0 c #b09470",
"#1 c #b08c68",
"#2 c #b07850",
"#3 c #b06840",
"#4 c #a8a490",
"#5 c #a88c68",
"#6 c #a87858",
"#7 c #a87050",
"#8 c #a86840",
"#9 c #a08c70",
"a. c #a07050",
"a# c #a07048",
"aa c #a06038",
"ab c #989488",
"ac c #989480",
"ad c #988c80",
"ae c #988c78",
"af c #988460",
"ag c #987860",
"ah c #987858",
"ai c #986848",
"aj c #986038",
"ak c #985838",
"al c #908470",
"am c #908468",
"an c #906040",
"ao c #906038",
"ap c #905838",
"aq c #888478",
"ar c #887870",
"as c #887868",
"at c #887060",
"au c #887058",
"av c #886850",
"aw c #886848",
"ax c #885030",
"ay c #807060",
"az c #807058",
"aA c #806858",
"aB c #806850",
"aC c #805838",
"aD c #787070",
"aE c #787068",
"aF c #787060",
"aG c #786860",
"aH c #786048",
"aI c #785840",
"aJ c #785030",
"aK c #784830",
"aL c #706860",
"aM c #706058",
"aN c #706050",
"aO c #705848",
"aP c #705840",
"aQ c #705038",
"aR c #704830",
"aS c #704828",
"aT c #686060",
"aU c #686058",
"aV c #686050",
"aW c #685850",
"aX c #685848",
"aY c #685840",
"aZ c #684028",
"a0 c #605048",
"a1 c #605040",
"a2 c #604838",
"a3 c #604028",
"a4 c #585048",
"a5 c #584840",
"a6 c #584838",
"a7 c #583820",
"a8 c #504840",
"a9 c #504038",
"b. c #504030",
"b# c #503828",
"ba c #503020",
"bb c #503018",
"bc c #484840",
"bd c #484038",
"be c #484030",
"bf c #483828",
"bg c #483020",
"bh c #403838",
"bi c #403830",
"bj c #403828",
"bk c #403028",
"bl c #403020",
"bm c #383830",
"bn c #383030",
"bo c #383028",
"bp c #382820",
"bq c #382018",
"br c #382010",
"bs c #302828",
"bt c #302820",
"bu c #302818",
"bv c #302018",
"bw c #302010",
"bx c #301810",
"by c #282828",
"bz c #282820",
"bA c #282020",
"bB c #282018",
"bC c #281810",
"bD c #201818",
"bE c #201810",
"bF c #201008",
"bG c #181818",
"bH c #181810",
"bI c #181010",
"bJ c #181008",
"bK c #180808",
"bL c #100808",
"bM c #080808",
"bN c #080800",
"bO c #080000",
"bP c #000000",
/* pixels */
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.A.r.p.m.g.f.................f.i.m.n.r.u.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.u.q.l.d.........P.N##############.8.N.N.........d.j.o.s.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.n.i.......P###I#L#3#3#3#3#3#3#3#Y#3#X#Y#X#3#Y#L#y##.N.......j.q.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.r.j.c...d.X#x#3#3#3#3#3#3#3#X#3#X#X#X#3#X#X#3#X#X#X#W#X#X#X#Y#q.X.d...c.m.x.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.w.j.#...N#o#3#3#3#3#3#3#3#X#X#3#X#X#3#X#X#X#X#X#W#X#W#W#X#X#W#W#X#W#X#Y#m.N.....j.t.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.w.l.....X#K#3#3#3#3#3#3#Y#X#X#X#3#X#X#W#X#W#X#W#W#W#X#W#X#W#W#W#W#W#V#V#M#V#W#M#I.X.....k.w.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.n.c...X#W#3#3#3#3#3#X#3#X#X#3#X#X#W#X#W#X#W#X#W#W#W#V#L#V#L#V#L#V#L#V#L#W#L#W#L#V#W#M#J.W...d.n.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.r.d...F#I#3#3#3#3#3#X#3#X#X#3#X#WaxaZbbbCbFbPbPbPbPbPbPbPbFbxbaaZap#L#L#L#K#L#L#K#L#L#K#L#K#M#q.D...f.r.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.o.c.d#m#3#3#3#3#3#X#X#3#X#XaaaZbrbPbPbPbPbibmaEaFaFaGaFaGaGbmbmbPbPbPbPbqaZ#8#K#K#K#K#K#L#K#L#K#K#M##.d.c.m.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.x.l...F#J#3#3#3#3#Y#X#X#3#XaSbCbPbPbDa4ad#t.E.D.F.E.F.F.F.F.G.G.G.G.G#Nala4bGbPbPbCaJ#J#J#J#J#J#J#J#K#J#K#x.D...j.r.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.y.f...X#3#3#3#3#X#X#3#X#8a7bKbPbIaU#t.D.j.D.D.j.F.D.F.E.F.E.F.F.G.G.G.N.G.G.H.N#CaWbLbPbJa3#W#J#K#J#J#J#J#J#K#J.Q...f.z.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.r.d.c#o#3#3#3#3#X#3#X#Xa3bObPbsac.D.j.D.j.D.j.D.D.j.D.j.D.E.F.E.M.F.M.G.G.N.G.N.H.N.N.OalbAbPbMaR#I#A#I#B#I#J#J#K#K#a...d.w.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.r.c.d#o#3#3#3#3#X#X#XaxbFbPbD#N.D.i.D.D.j.D.D.i.D.j.D.j.D.D.D.D.E.F.E.F.M.G.F.N.G.G.N.N.N.Q.O#ZbHbPbEan#A#I#I#A#A#I#A#I#a.d.c.r.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.r.c.d#J#3#3#3#X#X#3#XbabPbIaq.D.i.j.D.D.g.B.i.B.i.g.C.i.D.j.D.j.D.D.D.E.F.F.F.G.G.G.N.N.H.N.Q.Q.Q.QaybLbPba#z#A#z#I#B#I#B#I#q.d.c.t.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.u.f..#J#3#3#3#X#X#XaabEbPbc.M.D.g.D.B.g.g.C.i.B.i.g.B.i.g.C.C.j.D.j.D.D.D.F.E.F.M.G.G.N.G.N.N.N.Q.Q.R.R.6bebPbE#2#A#z#z#z#z#A#I#p...f.w.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.f..#o#3#3#X#X#X#WapbNbPaq.j.C.j.B.i.C.C.B.g.g.g.B.g.g.B.i.B.g.C.i.D.j.j.D.D.F.E.F.M.G.G.N.G.N.N.N.Q.Q.W.R.WaybPbNa##z#I#z#I#z#z#A##...f.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.l..#l#3#3#X#3#X#WaSbNbL#s.j.D.g.B.i.B.g.g.i.g.B.f.g.f.f.g.g.g.C.g.B.i.C.D.j.D.D.F.E.F.F.M.G.N.G.N.N.O.Q.Q.R.R.S#QbMbMaC#y#y#z#y#I#z#A.0...k.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.q...X#3#3#X#X#X#XaSbPbD#s.j.B.B.i.C.g.f.g.f.B.f.f.f.f.B.f.B.f.f.g.B.i.B.i.C.D.j.D.D.F.F.F.G.G.G.N.H.N.N.Q.Q.R.W.W.T#SbAbPaC#y#z#y#z#y#y#z.Q...p.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.r.c.F#W#X#X#3#X#WaxbPby.M.D.B.i.i.B.g.f.B.f.f.f.f.f.B.f.f.f.f.f.B.f.g.B.g.B.g.D.C.j.D.D.F.E.M.G.N.G.N.N.N.Q.Q.W.R.W.W.X.8bBbPai#y#y#y#z#z#y#y.C.c.u.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.g..#J#3#X#3#W#XakbMbL.M.j.g.C.B.g.f.B.f.f.f.f.f.f.e.f.e.e.f.e.f.f.f.f.f.g.C.g.g.D.D.j.D.E.F.F.M.F.N.G.N.H.N.Q.Q.R.W.R.X.X#jbMbM#7#p#r#q#y#y#y#o...g.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.o..###X#3#X#X#X#3bJbL#s.D.D.C.i.g.g.B.f.f.e.f.e.e.d.f.d.f.d.e.d.e.f.e.f.B.f.f.B.C.B.i.D.D.D.E.F.G.F.G.G.N.N.N.O.Q.R.R.W.X.Z.X#SbLbJ#H#x#r#q#r#r#r.X...p.b.b.b.b.b.b.b",
".b.b.b.b.b.b.u.c.C#V#3#X#X#W#VbCbP#4.h.D.g.g.B.f.B.f.f.f.f.e.d.d.f.d.e.d.d.d.d.d.e.f.e.f.f.B.f.g.g.i.D.j.D.D.E.M.G.F.N.G.N.N.Q.O.W.Q.X.S.X.X.ZambPbl#q#p#q#q#x#q#q.f.d.s.b.b.b.b.b.b",
".b.b.b.b.b.b.m..#x#Y#X#W#W#WaZbPaT.j.C.g.C.B.g.B.f.f.f.e.e.d.f.d.d.d.d.d.d.d.d.d.d.d.f.e.f.f.B.g.C.B.j.C.D.D.F.F.F.G.N.G.N.H.P.Q.Q.W.S.W.X.Z.Z.Ya1bPaQ#p#p#q#p#q#x##...m.b.b.b.b.b.b",
".b.b.b.b.b.u.c.N#X#X#X#X#W#8bNbs.h.D.j.C.g.i.f.g.f.f.e.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.e.f.e.f.f.g.B.C.j.D.j.D.F.F.M.G.N.G.N.N.Q.Q.R.W.T.X.X.Z.Z.ZbBbM#U#q#p#q#p#q#q.D.c.w.b.b.b.b.b",
".b.b.b.b.b.n..#y#X#W#W#W#LbrbP#t.D.j.C.g.C.f.B.f.e.f.d.f.f.d.d.d.d.d.d.d.d.d.d.d.d.d.d.d.e.f.f.B.f.g.g.C.D.D.D.E.F.G.F.G.N.N.N.O.Q.Q.R.W.X.X.X.Z.7#FbPb##p#o#p#q#p#q#a...n.b.b.b.b.b",
".b.b.b.b.b.d.F#3#W#X#W#LaxbPa4.D.D.D.g.C.g.B.f.f.f.e.f.d.d.d.d.d.d.c.#.d.c.c.#.c.d.d.d.f.d.e.f.f.g.B.C.B.j.D.D.F.F.M.F.N.G.N.N.Q.O.W.R.W.X.X.Z.Z.Z.9a9bPa.#o#p#o#o#p#q.C.d.b.b.b.b.b",
".b.b.b.b.p..#o#W#X#W#V#VbwbI.N.C.j.C.g.C.g.f.g.f.e.d.d.d.d.d.c.#.c.a.c.#.c.a.c.a.c.d.d.d.e.f.e.f.f.B.g.i.D.j.D.E.F.F.G.N.G.N.H.Q.Q.Q.R.W.T.X.Z.7.Z.9#kbMbu#e#e#o#p#o#p.Z...q.b.b.b.b",
".b.b.b.b.j.d#X#X#W#V#MajbPaE.D.D.D.i.B.g.B.f.f.f.f.e.d.d.d.d.#.#.#.c.#.d.#.c.#.c.a.d.d.d.d.d.f.f.f.g.B.B.i.D.D.D.F.E.M.G.N.G.N.N.Q.R.Q.W.X.X.X.Z.Z.9.0aXbP#6#d#e#e#e#o#p.c.g.b.b.b.b",
".b.b.b.w...W#W#X#L#V#LbgbP#f.D.j.D.h.C.i.f.B.f.f.d.f.d.d.d.d.#.c.#.d.#...#.#...#.c.#.d.d.d.d.e.f.f.f.C.g.C.j.D.D.F.F.G.G.G.N.N.O.Q.Q.W.T.W.Z.X.Z.7.0.9#FbPbf#c#n#n#o#e#o.H...u.b.b.b",
".b.b.b.n..#x#X#L#W#V#WbOa4.D.j.D.C.i.C.g.B.f.f.e.e.d.d.d.c.d.c.#.#.c.#...#.....#.#...d.d.d.d.f.f.f.f.B.g.D.D.D.D.E.M.G.F.N.N.N.P.Q.Q.R.W.X.X.X.Z.Z.9.9.9b.bM#w#c#c#e#d#o.0...p.b.b.b",
".b.b.b.i.d#X#V#V#L#KaKbP#4.j.F.D.j.B.g.g.f.g.f.f.d.d.d.d.d.d.#.c.#.#.c.........#...#.d.c.d.d.e.f.e.B.g.C.g.C.j.D.F.F.M.G.N.G.N.Q.O.Q.R.W.X.X.Z.7.Z.9.0#.agbPaw#c#m#c#m#e#o.c.k.b.b.b",
".b.b.b.c.Q#W#M#V#L#KbqbL.F.D.D.j.C.i.C.B.g.f.e.f.e.d.d.d.d.d.c.a.#...#.............#.#.d.d.d.d.f.f.f.g.B.C.j.D.D.F.E.G.G.N.G.N.P.Q.Q.R.S.W.X.X.Z.Z.9.9.9#.bMbk#c#c#c#c#c#c.F.c.b.b.b",
".b.b.r..#a#V#V#L#K#JbMa4.F.l.D.D.j.B.g.g.f.B.f.d.f.d.d.d.c.a.c.....................#...#.d.d.f.e.f.f.C.g.i.D.D.D.F.F.M.G.G.N.N.O.Q.Q.R.W.X.X.Z.Z.Z.9.0#.#.b.bM#b#a#c#c#c#n.S...q.b.b",
".b.b.q..#x#M#L#K#KaobPae.E.D.D.j.C.g.i.f.g.f.e.f.d.d.d.d.c.d.#...#...................d.d.d.e.d.f.f.f.g.B.C.j.D.D.E.M.G.G.N.G.N.Q.O.W.R.S.W.Z.X.Z.7.0.9#.#.avbP#1#a#c#a#b#c.0...o.b.b",
".b.b.n..#X#L#K#K#JaRbP#f.F.F.k.D.D.D.B.B.g.f.f.e.e.d.d.d.d.#.c.a.#...................#.c.d.d.f.e.f.B.B.i.B.D.D.F.F.F.G.G.N.N.N.Q.Q.Q.R.W.X.X.Z.Z.7.9.9#.###FbPaH.4#a#a#c#a#c...n.b.b",
".b.b.i.C#L#L#L#J#JbgbP.F.E.D.D.D.i.j.i.C.B.g.f.f.d.f.d.d.d.d.#.......................#.#.d.d.e.f.e.f.B.g.C.j.D.D.F.F.G.G.N.N.H.Q.Q.R.W.S.X.X.Z.Z.Z.0.9#.###.bPb..3#a.4#a#a#c.d.f.b.b",
".b.b.i.N#L#K#K#J#Kbwbn.G.F.F.F.D.D.D.B.i.g.f.e.f.e.d.d.d.c.a.c.#...................#.#.d.d.e.d.f.f.g.g.C.i.D.D.F.E.G.M.N.G.N.N.O.Q.Q.R.W.X.X.Y.Z.9.9#..9#a#.bpbt.2.1#a.4#a#a.D.g.b.b",
".b.b...Q#K#K#J#J#AbJbd.G.E.F.D.j.j.B.i.g.g.B.f.f.e.d.d.d.d.d.d.#.#.#.................#.c.d.d.e.f.f.B.B.g.D.j.D.E.F.M.G.G.N.N.P.Q.Q.R.W.S.Z.X.Z.Z.7.0#.#.###.bkbH.1#..1.1.4#a.F.c.b.b",
".b.b...9#K#J#J#K#IbPaG.F.F.E.E.D.D.j.D.g.C.f.f.f.e.f.d.d.d.d.d.d.#.#.#.#.....#.#.#.#.#.d.d.f.f.f.B.f.g.C.j.D.D.F.F.G.G.N.N.N.P.O.Q.W.R.X.X.Z.7.Z.9.9.9#.###aaYbP.1.1.1#..2##.H...b.b",
".b.b...0#K#J#J#A#AbPaL.G.F.F.F.j.D.i.D.g.g.B.g.f.f.f.e.e.d.d.d.d.d.d.d.a.#.a.c.#.#.c.d.d.e.e.f.e.g.B.i.B.D.j.F.E.M.F.G.G.N.H.Q.Q.R.R.W.X.X.X.Z.7.0.9#.###.##aYbP.0.1.1.1#..2.N...b.b",
".b.b...8#J#J#J#I#AbPaL.G.G.E.F.F.j.D.j.C.i.g.B.f.B.f.f.f.e.d.d.d.d.d.d.c.d.d.d.d.d.d.d.d.d.f.f.B.f.i.B.j.D.D.D.F.F.G.G.N.N.N.Q.Q.Q.W.S.X.X.Z.Z.0.9.9#.#.#a#.aYbP.0.0.1.1.1#..H...b.b",
".b.b...Z#K#J#I#A#zbPaL.G.G.G.F.E.D.j.D.D.D.C.g.B.f.f.e.e.f.f.f.d.d.d.d.d.d.d.d.d.d.e.d.f.f.f.f.B.g.B.C.j.D.D.E.F.M.G.G.N.N.P.Q.Q.R.R.W.Z.X.Z.Z.7.9#.#.######aYbP.0.0.0.0.1.1.N...b.b",
".b.b...Z#K#A#A#A#IbPaG.G.G.G.M.F.F.D.D.j.i.B.g.g.g.f.B.f.f.e.e.f.d.e.d.d.d.d.e.f.e.d.f.f.e.B.g.g.C.g.j.D.D.F.F.F.G.G.N.N.N.O.Q.W.R.W.X.X.Z.Z.7.0.9.9#.###a#.aYbP.Z.0.0.0.1.0.G...b.b",
".b.b...Z#J#I#I#z#zbPaG.N.G.G.F.E.F.F.D.D.D.j.B.i.B.B.f.B.f.f.f.e.f.d.f.f.e.f.e.d.f.f.f.f.B.f.B.B.g.D.D.D.D.E.F.M.G.G.G.N.N.Q.Q.Q.W.S.X.X.Z.Z.9.9.9#.#.#a#.##aPbP.V.Z.0.0.0.3.G...b.b",
".b.b.c.Q#I#B#z#z#zbJbd.G.N.G.G.F.E.F.F.D.j.C.j.C.g.i.B.f.B.f.f.f.f.f.f.e.f.f.f.f.f.f.f.B.f.g.g.d.j.C.j.D.D.M.F.G.G.G.N.N.N.Q.R.R.R.W.Z.X.Z.Z.7.0#.#.#a###.#.bjbI.U.Z.V.Z.0.0.F.c.b.b",
".b.b.i.M#I#z#I#z#ybvbn.G.N.G.G.G.F.F.F.j.D.D.D.B.D.B.B.i.B.g.B.f.B.f.f.f.f.e.f.f.B.g.B.g.g.C.B.D.B.j.D.E.E.F.M.G.G.N.N.N.Q.Q.Q.S.W.X.X.Z.Z.7.9.9.9#.#.#a###.bpbo.Y.V.Z.Z.Z.0.f.i.b.b",
".b.b.g.f#J#A#z#y#zbgbP.N.G.N.G.G.G.M.E.F.D.E.j.D.j.i.C.g.C.B.g.g.B.f.B.g.B.B.B.B.g.B.g.C.B.i.j.i.j.D.k.E.F.F.G.G.N.G.N.Q.Q.Q.W.W.T.X.Z.Z.Z.9.0#.#.#####.#.#.bPa6.T.U.Y.V.Z.0.d.i.b.b",
".b.b.n..#A#I#z#y#yaQbP#h.N.G.N.G.G.G.F.F.F.D.D.D.D.D.j.D.g.C.B.i.B.g.g.B.i.B.g.g.C.i.B.i.D.D.D.D.D.k.E.E.E.G.G.G.N.N.N.O.Q.R.R.W.X.Y.X.Z.7.0.9.9#.###a###.#0bPay.T.T.U.Y.V.Z...m.b.b",
".b.b.p..#m#z#z#z#y#7bPal.N.N.G.N.N.G.G.F.F.F.F.j.D.D.D.j.D.j.C.C.i.C.C.i.B.i.C.C.g.D.i.D.D.j.D.E.D.E.E.E.G.G.G.N.N.N.Q.Q.Q.R.W.T.X.X.7.Z.0.8#.#.#.#a#.#..1aubP#R.T.T.X.T.U.Q...q.b.b",
".b.b.u...8#z#y#y#r#qbNa4.N.N.N.N.G.M.G.G.G.F.E.F.F.D.D.D.D.D.D.h.D.D.g.D.i.D.C.h.D.j.D.D.j.D.D.D.E.F.E.G.G.G.N.N.N.N.Q.Q.R.W.W.X.X.Z.Z.Z.9.9#.#.#a#.###..9b.bM.K.S.T.T.U.Y.G...v.b.b",
".b.b.b.c.N#z#z#y#r#qblbL.N.H.N.G.N.G.N.M.G.M.F.F.E.F.E.D.j.D.j.D.D.j.D.D.D.D.j.D.D.D.D.D.E.F.F.F.F.E.G.G.G.N.G.N.P.Q.Q.R.W.R.X.Z.Z.Z.7.9.0.9#.#####a#.#..1bMa9.K.R.T.S.T.T.C.c.b.b.b",
".b.b.b.j.d#y#y#y#q#qaIbPae.N.N.N.G.N.G.N.G.G.G.M.F.E.F.F.F.F.D.D.D.D.D.D.D.D.D.D.F.D.F.D.F.E.M.G.G.G.G.G.N.N.N.Q.O.Q.R.R.W.X.X.X.Z.Z.0.7.9#.#.###a#.#.#.agbPam.K.R.K.T.S.T.c.j.b.b.b",
".b.b.b.p..#a#z#q#r#p#ybMa5.Q.P.N.N.N.N.G.N.G.G.G.G.G.F.E.F.E.F.F.F.F.F.F.F.F.F.F.E.F.F.F.F.F.F.G.G.M.N.N.N.N.O.P.Q.Q.R.W.T.X.X.Z.Z.7.9.9#.#.#.#a#.###..0bfbM.X.Q.K.R.R.T.H...p.b.b.b",
".b.b.b.A...N#y#r#q#p#pb#bP#u.Q.P.N.G.N.N.G.N.N.N.G.M.G.G.G.M.F.E.F.E.F.E.F.E.F.F.F.F.G.M.G.G.G.G.G.N.G.G.N.N.Q.Q.R.R.W.W.X.X.Z.Z.Z.9.0.9#.#####.###..1#EbPa5.J.Q.Q.S.K.K.C...A.b.b.b",
".b.b.b.b.j.d#r#q#p#q#p#6bPaM.O.Q.Q.N.N.N.N.G.N.F.N.G.N.M.M.G.G.M.F.F.G.G.G.G.G.G.M.G.G.G.G.G.G.N.N.G.N.Q.P.Q.Q.Q.R.W.S.X.X.Z.Z.7.9.0.9#.#.###a###.#..9aObP#D.I.Q.J.Q.R.S.#.j.b.b.b.b",
".b.b.b.b.q...0#x#q#p#o#pbubL.6.Q.Q.Q.N.H.N.N.G.N.G.N.G.G.N.G.G.G.G.G.M.G.M.G.G.G.G.G.G.G.N.N.N.G.N.N.Q.N.Q.R.Q.R.W.T.X.Z.X.Z.Z.0.7.9#.#.###.#.#a#..1#kbMbn.H.I.I.O.J.Q.G...q.b.b.b.b",
".b.b.b.b.b.d.C#q#p#q#p#eahbPa8.W.Q.Q.Q.Q.N.N.N.N.N.G.N.N.G.N.N.G.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.Q.N.Q.R.Q.R.R.W.W.X.X.X.Z.Z.7.9.9#.#.###.#a###.#..0b.bP#Q.H.H.O.I.R.J.d.d.b.b.b.b.b",
".b.b.b.b.b.n..###p#p#o#e#db#bP#P.R.W.Q.Q.Q.Q.P.H.N.N.N.N.G.N.G.N.N.G.G.G.G.N.G.N.N.N.N.N.N.N.N.Q.Q.Q.Q.Q.R.W.W.X.X.X.Z.Z.Z.9.9.0#.#.###.#a###.#..0#TbPa4.G.H.N.H.J.I.G...n.b.b.b.b.b",
".b.b.b.b.b.A.c.F#q#o#p#e#o#GbMbz.R.Q.W.Q.Q.O.Q.Q.Q.N.N.H.N.N.N.N.G.N.N.N.N.N.N.N.G.N.N.P.Q.Q.Q.Q.Q.R.R.W.W.S.X.X.Z.Z.Z.Z.9.Z.9#..9###.#a#.#.#..1.0bDbM.W.G.H.H.H.N.I.d.d.w.b.b.b.b.b",
".b.b.b.b.b.b.n...0#p#o#d#n#caIbPa0.W.R.W.R.Q.Q.O.Q.Q.Q.Q.Q.P.N.P.N.P.N.P.N.P.P.Q.Q.Q.Q.O.Q.Q.R.Q.R.W.R.S.X.X.X.Z.X.Z.7.9.0.9#..9#.#a#.###a#.#..0a2bPar.G.G.N.G.H.H.F.c.m.b.b.b.b.b.b",
".b.b.b.b.b.b.A.c.d#p#e#o#c#c#bbkbP#9.W.R.W.R.W.R.Q.Q.Q.O.Q.O.Q.Q.Q.Q.Q.Q.Q.O.Q.O.Q.Q.Q.Q.R.Q.W.R.W.R.X.X.X.X.Y.Z.Z.Z.9.0.9#.#.#.#a#.#a#.#.#..0afbPbc.G.G.G.G.G.H.H.c.c.z.b.b.b.b.b.b",
".b.b.b.b.b.b.b.p...S#e#o#c#c#c#obIbM#Q.W.W.W.R.W.R.W.Q.R.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.R.Q.R.W.R.W.W.S.X.X.X.X.X.Z.Z.Z.7.9.0.9#..9#.#a#.#####.#..0#TbMbG.N.l.G.G.G.H.G.g...q.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.i..###d#c#n#a#c#1bLbM.7.T.W.W.S.W.R.W.R.W.R.Q.W.R.Q.W.R.R.W.R.R.W.R.W.R.W.R.X.X.X.X.Z.Z.Z.Z.7.9.0.9.9#..9#.#a###.#a#.#..0#kbMbL#g.k.l.F.G.G.G.F...j.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.w.c.B#c#c#c#c#a.2ahbPbB#i.X.X.X.W.W.S.W.W.W.R.S.W.R.R.W.R.W.W.W.S.W.S.X.X.X.X.X.Z.X.Z.Z.7.Z.0.7.9#..9#.###a#.###a#.#..0#lbBbP#O.j.E.k.l.F.G.G.d.c.v.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.o...N#m#c#c#a#a.1aubPbB#S.X.X.X.X.X.X.T.W.X.W.T.W.W.W.S.X.S.X.X.X.Z.X.X.X.Z.Z.Z.Z.Z.7.0.9.9#..9#.#.#.#a#.#a#.#.#..0#TbHbPac.j.E.j.k.E.l.G.f...p.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.j...R#c#b#a#a.3.1aubLbM#Z.Z.X.Z.X.X.X.X.X.X.X.Y.X.Y.X.X.X.Y.X.X.X.Z.Z.Z.Z.Z.7.Z.9.0.9.9#..9#.#.###a###.###.#..0#TbMbLac.j.D.j.l.D.k.l.g...l.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.f...W#c.4#a.1#a.1#TbMbPaA.Z.Z.X.Z.Z.X.Z.X.Z.X.X.X.Z.X.Z.X.Z.Z.Z.Z.Z.7.Z.7.0.9.9.9.9#..9#.#####a#.#a#.#.#..0aNbPbI#s.g.j.j.j.D.k.D.g...f.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.v.f.c.0#a.4.1.1.1.1#vbBbPbi#j.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.7.Z.Z.7.Z.7.Z.9.9.0.8.0.9#.#.#.#.#a#.#a#.###.#..0#lbpbPbs.5.g.j.h.j.D.j.E.j...f.A.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.A.c.c.Z#a.2#..0.1.0.Va1bPbMaB.7.Z.7.Z.Z.7.Z.Z.7.Z.7.Z.Z.9.Z.9.0.9.0.9.9#.#.#.#.#.#####.#a###.#.#..1aBbMbPaL.g.g.g.g.j.h.j.j.i...d.v.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.t.c.c.R#..1.1.0.0.0.Y#0bAbPbI#9.0.9.9.0.9.9.0.9.0.9.9.0.9.9.9.9#..9#.#.###.#####a#.#a#.#.#.#.#5bIbPbs#N.f.g.g.h.i.g.j.h.f.c.d.v.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.q.d...Q.1.1.0.0.Z.V.Z.TazbLbPbBat.0.9.9.0.9.9.9.9.9.9#..9#..9#.#.#.###.###a#.###a#.#.#.aubBbPbIaq.e.f.g.g.g.g.g.h.D.f...d.v.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.t.f...F.1.0.0.Z.Z.U.U.T.7aNbHbPbMa2#0.9#..9#.#.#.#..9#.#.###.###a#.#a#.###a#.#.#0a2bMbPbDaD.L.f.g.f.g.f.g.g.i.g.d...i.A.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.w.k...f.Z.0.0.Y.Z.T.T.S.K.KambobPbPbIb.au#0#.#.#.#a#.###a#.#a###.###a#0aub.bIbPbPbhab.e.f.g.g.f.g.f.g.g.g.g.c...l.A.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.q...c.G.Z.V.U.Y.T.T.T.R.K.J#hatbdbPbPbPbPbtbtaYaYaYaYaYaYaYbtbtbPbPbPbPbcad.5.e.g.f.g.g.f.g.g.g.f.g.d.c...o.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.t.f...C.Q.Y.T.T.S.K.R.R.Q.O.I.H.H#PasaVbibtbPbPbPbPbPbPbPbsbiaTaq#N.f.e.g.f.g.f.g.f.g.f.g.f.g.e.c...f.u.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.m.c...D.R.T.T.T.K.R.J.Q.I.N.H.H.G.G.F.l.k.j.j.j.j.j.g.g.g.g.g.g.g.f.g.f.g.g.f.g.f.g.f.e.d...d.n.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.t.j.....D.Q.S.R.K.Q.Q.I.I.H.H.H.G.G.G.F.l.E.j.D.j.j.j.i.g.g.g.f.g.f.g.f.g.g.f.g.e.d.....k.w.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.r.k.....f.G.R.J.Q.I.N.H.H.G.G.G.G.l.E.j.E.j.D.h.j.g.h.g.g.g.f.g.g.f.g.f.e.#.c...k.u.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.u.m.c...c.B.G.I.J.H.H.G.H.G.G.l.l.k.k.j.j.j.j.h.i.g.g.g.g.f.g.e.c.#...c.k.s.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.o.j.......d.C.E.G.G.G.G.G.E.l.D.D.j.D.h.j.g.i.g.f.d.#.....#.i.o.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.u.q.k.f...c.....d.d.g.f.f.f.f.e.f.d.c.d.......#.d.j.o.t.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.w.r.n.m.i.f.....#.........c.f.g.l.n.r.w.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
".b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b",
};

Added jni/tkzinc/sandbox/conical.tcl.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

lappend auto_path ..
package require Tkzinc

set defaultfont -b&h-lucida-bold-r-normal-*-*-140-*-*-p-*-iso10646-1
zinc .zinc -width 700 -height 500 -render 1
pack .zinc


.zinc gname {=radial 0 0 |white|gray30} test1
.zinc gname {=conical 70 |white|gray30 50 50|white} test2

set grp [.zinc add group 1]
#.zinc add rectangle $grp {0 0 70 50} -filled 1 -fillcolor white   
.zinc add rectangle $grp {60 60 360 360} -filled 1 -linewidth 1 \
    -fillcolor test2 -tags rect

.zinc add rectangle $grp {140 140 280 280} -filled 1 -fillcolor gray

Added jni/tkzinc/sandbox/contours.tcl.



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so
package require Img

set top 1
set lw 8

set r [zinc .r -backcolor gray -relief sunken]
pack .r -expand t -fill both
.r configure -width 800 -height 500
.r scale $top 1 -1
#.r configure -drawbboxes t
set view [.r add group $top -tags controls]
#set poly [.r add curve $view "50 -150 300 -150 300 -300 50 -300 50 -150" \
#	-closed t -fillcolor tan]
set poly [.r add curve $view "50 -150 50 -300 300 -300 300 -150 50 -150" \
	-closed t -fillcolor tan -linecolor tan -linewidth 2 -relief raised]
.r scale $poly 2.0 2.0
.r translate $poly -60 150
set rect [.r add rectangle $view "50 -200 100 -50"]
set ellipse [.r add arc $view "150 -200 300 -350"]
set arc [.r add arc $view "-25 -150 125 -300"]
.r scale $arc 2.0 2.0
.r translate $arc -60 150

set mp [.r add curve $view ""  \
	    -linecolor yellow -fillcolor tan -fillpattern AlphaStipple8 \
	    -markercolor red -tags "poly" -linewidth $lw -filled t -closed t]

.r contour $mp add $poly
.r contour $mp addhole $ellipse
.r contour $mp addhole $rect
.r contour $mp add $arc

.r itemconfigure $mp -relief raised -visible t
.r lower $mp

#.r remove $arc $ellipse $rect $poly
.r remove  $rect $arc $ellipse

#.r itemconfigure $poly -relief raised -linewidth 8

# "50 -200 100 -200 100 -50 50 -50 50 -200"
source "controls.tcl"

Added jni/tkzinc/sandbox/controls.tcl.





























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
set tlbbox [.r add group $top -sensitive f -visible f -tags currentbbox]
.r add rectangle $tlbbox "-3 -3 +3 +3"
set trbbox [.r add group $top -sensitive f -visible f -tags currentbbox]
.r add rectangle $trbbox "-3 -3 +3 +3"
set blbbox [.r add group $top -sensitive f -visible f -tags currentbbox]
.r add rectangle $blbbox "-3 -3 +3 +3"
set brbbox [.r add group $top -sensitive f -visible f -tags currentbbox]
.r add rectangle $brbbox "-3 -3 +3 +3"
.r add rectangle $top "0 0 1 1" -linecolor red -tags "lasso" -visible f -sensitive f

#
# Controls for the window transform.
#
proc press {lx ly action} {
    global x y angle
    set x $lx
    set y $ly
    set angle [expr atan2($y, $x)]
    bind .r "<Motion>" "$action %x %y"
}

proc motion {lx ly} {
    global x y
    set it [.r find withtag controls]
    if {$it != ""} {
	set it [.r group [lindex $it 0]]
    }
    set res [.r transform $it "$lx $ly $x $y"]
    set nx [lindex $res 0]
    set ny [lindex $res 1]
    set ox [lindex $res 2]
    set oy [lindex $res 3]
    .r translate controls [expr $nx - $ox] [expr $ny - $oy]
    set x $lx
    set y $ly
}

proc zoom {lx ly} {
    global x y

    if {$lx > $x} {
	set maxx $lx
    } else {
	set maxx $x
    }
    if {$ly > $y} {
	set maxy $ly
    } else {
	set maxy $y
    }
    set sx [expr 1.0 + double($lx - $x)/$maxx]
    set sy [expr 1.0 + double($ly - $y)/$maxy]
    set x $lx
    set y $ly
    .r scale controls $sx $sy
}

proc rotate {lx ly} {
    global angle

    set langle [expr atan2($ly, $lx)]
    .r rotate controls [expr -($langle-$angle)]
    set angle $langle
}

proc release {} {
    bind .r "<Motion>" ""
}

proc start_lasso {lx ly} {
    global top x y cx cy
    set x $lx
    set y $ly
    set cx $lx
    set cy $ly
    set coords [.r transform $top "$x $y"]
    set fx [lindex $coords 0]
    set fy [lindex $coords 1]
    .r coords lasso  "$fx $fy $fx $fy"
    .r itemconfigure lasso -visible t
    .r raise lasso
    bind .r "<Motion>" "lasso %x %y"
}

proc lasso {lx ly} {
    global top x y cx cy
    set cx $lx
    set cy $ly
    set coords [.r transform $top "$x $y $lx $ly"]
    set fx [lindex $coords 0]
    set fy [lindex $coords 1]
    set fcx [lindex $coords 2]
    set fcy [lindex $coords 3]
    .r coords lasso  "$fx $fy $fcx $fcy"
}

proc fin_lasso {} {
    global x y cx cy
    
    bind .r "<Motion>" ""
    .r itemconfigure lasso -visible f
#    puts "x=$x, y=$y, cx=$cx, cy=$cy"
    puts "enclosed='[.r find enclosed $x $y $cx $cy]', overlapping='[.r find overlapping $x $y $cx $cy]'"
}

proc getrect {x y} {
    list [expr $x-3] [expr $y-3] [expr $x+3] [expr $y+3]
}

proc showbox {} {
    global top tlbbox trbbox blbbox brbbox
    
    if { ! [.r hastag current currentbbox]} {
	if {[catch {.r find withtag current} item] } {
	    return
	}
	set coords [.r transform $top [.r bbox current]]
	set xo [lindex $coords 0]
	set yo [lindex $coords 1]
	set xc [lindex $coords 2]
	set yc [lindex $coords 3]

	.r coords $tlbbox "$xo $yo"
	.r coords $trbbox "$xc $yo"
	.r coords $brbbox "$xc $yc"
	.r coords $blbbox "$xo $yc"
	.r itemconfigure currentbbox -visible t
    }
}

proc hidebox {lx ly} {
    set next [.r find closest $lx $ly]
    if {[llength $next] > 1} {
	set next [lindex $next 0]
    }
    if { $next == "" || ! [.r hastag $next currentbbox] ||\
	    [.r hastag current currentbbox]} {
	.r itemconfigure currentbbox -visible f
    }
}


bind  .r "<ButtonPress-1>" "start_lasso %x %y"
bind  .r "<ButtonRelease-1>" fin_lasso

bind  .r "<ButtonPress-2>" {puts "at point='[.r find closest %x %y]'"}

bind  .r "<ButtonPress-3>" "press %x %y motion"
bind  .r "<ButtonRelease-3>" release

bind  .r "<Shift-ButtonPress-3>" "press %x %y zoom"
bind  .r "<Shift-ButtonRelease-3>" release

bind  .r "<Control-ButtonPress-3>" "press %x %y rotate"
bind  .r "<Control-ButtonRelease-3>" release

.r bind current "<Enter>" showbox
.r bind current "<Leave>" {hidebox %x %y}

Added jni/tkzinc/sandbox/defs.tcl.



















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
# defs.tcl --
#
#	This file contains support code for the Tcl/Tk test suite.It is
#	It is normally sourced by the individual files in the test suite
#	before they run their tests.  This improved approach to testing
#	was designed and initially implemented by Mary Ann May-Pumphrey
#	of Sun Microsystems.
#
# Copyright (c) 1990-1994 The Regents of the University of California.
# Copyright (c) 1994-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
# 
# RCS: @(#) $Id$

# Initialize wish shell

if {[info exists tk_version]} {
    tk appname tktest
    wm title . tktest
} else {

    # Ensure that we have a minimal auto_path so we don't pick up extra junk.

    set auto_path [list [info library]]
}

# create the "tcltest" namespace for all testing variables and procedures

namespace eval tcltest {
    set procList [list test cleanupTests dotests saveState restoreState \
	    normalizeMsg makeFile removeFile makeDirectory removeDirectory \
	    viewFile bytestring set_iso8859_1_locale restore_locale \
	    safeFetch threadReap]
    if {[info exists tk_version]} {
	lappend procList setupbg dobg bgReady cleanupbg fixfocus
    }
    foreach proc $procList {
	namespace export $proc
    }

    # setup ::tcltest default vars
    foreach {var default} {verbose b match {} skip {}} {
	if {![info exists $var]} {
	    variable $var $default
	}
    }

    # Tests should not rely on the current working directory.
    # Files that are part of the test suite should be accessed relative to
    # ::tcltest::testsDir.

    set originalDir [pwd]
    set tDir [file join $originalDir [file dirname [info script]]]
    cd $tDir
    variable testsDir [pwd]
    cd $originalDir

    # Count the number of files tested (0 if all.tcl wasn't called).
    # The all.tcl file will set testSingleFile to false, so stats will
    # not be printed until all.tcl calls the cleanupTests proc.
    # The currentFailure var stores the boolean value of whether the
    # current test file has had any failures.  The failFiles list
    # stores the names of test files that had failures.

    variable numTestFiles 0
    variable testSingleFile true
    variable currentFailure false
    variable failFiles {}

    # Tests should remove all files they create.  The test suite will
    # check the current working dir for files created by the tests.
    # ::tcltest::filesMade keeps track of such files created using the
    # ::tcltest::makeFile and ::tcltest::makeDirectory procedures.
    # ::tcltest::filesExisted stores the names of pre-existing files.

    variable filesMade {}
    variable filesExisted {}

    # ::tcltest::numTests will store test files as indices and the list
    # of files (that should not have been) left behind by the test files.

    array set ::tcltest::createdNewFiles {}

    # initialize ::tcltest::numTests array to keep track fo the number of
    # tests that pass, fial, and are skipped.

    array set numTests [list Total 0 Passed 0 Skipped 0 Failed 0]

    # initialize ::tcltest::skippedBecause array to keep track of
    # constraints that kept tests from running

    array set ::tcltest::skippedBecause {}

    # tests that use thread need to know which is the main thread

    variable ::tcltest::mainThread 1
    if {[info commands testthread] != {}} {
	puts "Tk with threads enabled is known to have problems with X"
	set ::tcltest::mainThread [testthread names]
    }
}

# If there is no "memory" command (because memory debugging isn't
# enabled), generate a dummy command that does nothing.

if {[info commands memory] == ""} {
    proc memory args {}
}

# ::tcltest::initConfig --
#
# Check configuration information that will determine which tests
# to run.  To do this, create an array ::tcltest::testConfig.  Each
# element has a 0 or 1 value.  If the element is "true" then tests
# with that constraint will be run, otherwise tests with that constraint
# will be skipped.  See the README file for the list of built-in
# constraints defined in this procedure.
#
# Arguments:
#	none
#
# Results:
#	The ::tcltest::testConfig array is reset to have an index for
#	each built-in test constraint.

proc ::tcltest::initConfig {} {

    global tcl_platform tcl_interactive tk_version

    catch {unset ::tcltest::testConfig}

    # The following trace procedure makes it so that we can safely refer to
    # non-existent members of the ::tcltest::testConfig array without causing an
    # error.  Instead, reading a non-existent member will return 0.  This is
    # necessary because tests are allowed to use constraint "X" without ensuring
    # that ::tcltest::testConfig("X") is defined.

    trace variable ::tcltest::testConfig r ::tcltest::safeFetch

    proc ::tcltest::safeFetch {n1 n2 op} {
	if {($n2 != {}) && ([info exists ::tcltest::testConfig($n2)] == 0)} {
	    set ::tcltest::testConfig($n2) 0
	}
    }

    set ::tcltest::testConfig(unixOnly) \
	    [expr {$tcl_platform(platform) == "unix"}]
    set ::tcltest::testConfig(macOnly) \
	    [expr {$tcl_platform(platform) == "macintosh"}]
    set ::tcltest::testConfig(pcOnly) \
	    [expr {$tcl_platform(platform) == "windows"}]

    set ::tcltest::testConfig(unix) $::tcltest::testConfig(unixOnly)
    set ::tcltest::testConfig(mac) $::tcltest::testConfig(macOnly)
    set ::tcltest::testConfig(pc) $::tcltest::testConfig(pcOnly)

    set ::tcltest::testConfig(unixOrPc) \
	    [expr {$::tcltest::testConfig(unix) || $::tcltest::testConfig(pc)}]
    set ::tcltest::testConfig(macOrPc) \
	    [expr {$::tcltest::testConfig(mac) || $::tcltest::testConfig(pc)}]
    set ::tcltest::testConfig(macOrUnix) \
	    [expr {$::tcltest::testConfig(mac) || $::tcltest::testConfig(unix)}]

    set ::tcltest::testConfig(nt) [expr {$tcl_platform(os) == "Windows NT"}]
    set ::tcltest::testConfig(95) [expr {$tcl_platform(os) == "Windows 95"}]

    # The following config switches are used to mark tests that should work,
    # but have been temporarily disabled on certain platforms because they don't
    # and we haven't gotten around to fixing the underlying problem.

    set ::tcltest::testConfig(tempNotPc) [expr {!$::tcltest::testConfig(pc)}]
    set ::tcltest::testConfig(tempNotMac) [expr {!$::tcltest::testConfig(mac)}]
    set ::tcltest::testConfig(tempNotUnix) [expr {!$::tcltest::testConfig(unix)}]

    # The following config switches are used to mark tests that crash on
    # certain platforms, so that they can be reactivated again when the
    # underlying problem is fixed.

    set ::tcltest::testConfig(pcCrash) [expr {!$::tcltest::testConfig(pc)}]
    set ::tcltest::testConfig(macCrash) [expr {!$::tcltest::testConfig(mac)}]
    set ::tcltest::testConfig(unixCrash) [expr {!$::tcltest::testConfig(unix)}]

    # Set the "fonts" constraint for wish apps

    if {[info exists tk_version]} {
	set ::tcltest::testConfig(fonts) 1
	catch {destroy .e}
	entry .e -width 0 -font {Helvetica -12} -bd 1
	.e insert end "a.bcd"
	if {([winfo reqwidth .e] != 37) || ([winfo reqheight .e] != 20)} {
	    set ::tcltest::testConfig(fonts) 0
	}
	destroy .e
	catch {destroy .t}
	text .t -width 80 -height 20 -font {Times -14} -bd 1
	pack .t
	.t insert end "This is\na dot."
	update
	set x [list [.t bbox 1.3] [.t bbox 2.5]]
	destroy .t
	if {[string match {{22 3 6 15} {31 18 [34] 15}} $x] == 0} {
	    set ::tcltest::testConfig(fonts) 0
	}

	# Test to see if we have are running Unix apps on Exceed,
	# which won't return font failures (Windows-like), which is
	# not what we want from ann X server (other Windows X servers
	# operate as expected)

	set ::tcltest::testConfig(noExceed) 1
	if {$::tcltest::testConfig(unixOnly) && \
		[catch {font actual "\{xyz"}] == 0} {
	    puts "Running X app on Exceed, skipping problematic font tests..."
	    set ::tcltest::testConfig(noExceed) 0
	}
    }

    # Skip empty tests

    set ::tcltest::testConfig(emptyTest) 0

    # By default, tests that expost known bugs are skipped.

    set ::tcltest::testConfig(knownBug) 0

    # By default, non-portable tests are skipped.

    set ::tcltest::testConfig(nonPortable) 0

    # Some tests require user interaction.

    set ::tcltest::testConfig(userInteraction) 0

    # Some tests must be skipped if the interpreter is not in interactive mode

    set ::tcltest::testConfig(interactive) $tcl_interactive

    # Some tests must be skipped if you are running as root on Unix.
    # Other tests can only be run if you are running as root on Unix.

    set ::tcltest::testConfig(root) 0
    set ::tcltest::testConfig(notRoot) 1
    set user {}
    if {$tcl_platform(platform) == "unix"} {
	catch {set user [exec whoami]}
	if {$user == ""} {
	    catch {regexp {^[^(]*\(([^)]*)\)} [exec id] dummy user}
	}
	if {($user == "root") || ($user == "")} {
	    set ::tcltest::testConfig(root) 1
	    set ::tcltest::testConfig(notRoot) 0
	}
    }

    # Set nonBlockFiles constraint: 1 means this platform supports
    # setting files into nonblocking mode.

    if {[catch {set f [open defs r]}]} {
	set ::tcltest::testConfig(nonBlockFiles) 1
    } else {
	if {[catch {fconfigure $f -blocking off}] == 0} {
	    set ::tcltest::testConfig(nonBlockFiles) 1
	} else {
	    set ::tcltest::testConfig(nonBlockFiles) 0
	}
	close $f
    }

    # Set asyncPipeClose constraint: 1 means this platform supports
    # async flush and async close on a pipe.
    #
    # Test for SCO Unix - cannot run async flushing tests because a
    # potential problem with select is apparently interfering.
    # (Mark Diekhans).

    if {$tcl_platform(platform) == "unix"} {
	if {[catch {exec uname -X | fgrep {Release = 3.2v}}] == 0} {
	    set ::tcltest::testConfig(asyncPipeClose) 0
	} else {
	    set ::tcltest::testConfig(asyncPipeClose) 1
	}
    } else {
	set ::tcltest::testConfig(asyncPipeClose) 1
    }

    # Test to see if we have a broken version of sprintf with respect
    # to the "e" format of floating-point numbers.

    set ::tcltest::testConfig(eformat) 1
    if {[string compare "[format %g 5e-5]" "5e-05"] != 0} {
	set ::tcltest::testConfig(eformat) 0
    }

    # Test to see if execed commands such as cat, echo, rm and so forth are
    # present on this machine.

    set ::tcltest::testConfig(unixExecs) 1
    if {$tcl_platform(platform) == "macintosh"} {
	set ::tcltest::testConfig(unixExecs) 0
    }
    if {($::tcltest::testConfig(unixExecs) == 1) && \
	    ($tcl_platform(platform) == "windows")} {
	if {[catch {exec cat defs}] == 1} {
	    set ::tcltest::testConfig(unixExecs) 0
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec echo hello}] == 1)} {
	    set ::tcltest::testConfig(unixExecs) 0
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec sh -c echo hello}] == 1)} {
	    set ::tcltest::testConfig(unixExecs) 0
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec wc defs}] == 1)} {
	    set ::tcltest::testConfig(unixExecs) 0
	}
	if {$::tcltest::testConfig(unixExecs) == 1} {
	    exec echo hello > removeMe
	    if {[catch {exec rm removeMe}] == 1} {
		set ::tcltest::testConfig(unixExecs) 0
	    }
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec sleep 1}] == 1)} {
	    set ::tcltest::testConfig(unixExecs) 0
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec fgrep unixExecs defs}] == 1)} {
	    set ::tcltest::testConfig(unixExecs) 0
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec ps}] == 1)} {
	    set ::tcltest::testConfig(unixExecs) 0
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec echo abc > removeMe}] == 0) && \
		([catch {exec chmod 644 removeMe}] == 1) && \
		([catch {exec rm removeMe}] == 0)} {
	    set ::tcltest::testConfig(unixExecs) 0
	} else {
	    catch {exec rm -f removeMe}
	}
	if {($::tcltest::testConfig(unixExecs) == 1) && \
		([catch {exec mkdir removeMe}] == 1)} {
	    set ::tcltest::testConfig(unixExecs) 0
	} else {
	    catch {exec rm -r removeMe}
	}
    }
}

::tcltest::initConfig


# ::tcltest::processCmdLineArgs --
#
#	Use command line args to set the verbose, skip, and
#	match variables.  This procedure must be run after
#	constraints are initialized, because some constraints can be
#	overridden.
#
# Arguments:
#	none
#
# Results:
#	::tcltest::verbose is set to <value>

proc ::tcltest::processCmdLineArgs {} {
    global argv

    # The "argv" var doesn't exist in some cases, so use {}
    # The "argv" var doesn't exist in some cases.

    if {(![info exists argv]) || ([llength $argv] < 2)} {
	set flagArray {}
    } else {
	set flagArray $argv
    }

    if {[catch {array set flag $flagArray}]} {
	puts stderr "Error:  odd number of command line args specified:"
	puts stderr "        $argv"
	exit
    }
    
    # Allow for 1-char abbreviations, where applicable (e.g., -match == -m).
    # Note that -verbose cannot be abbreviated to -v in wish because it
    # conflicts with the wish option -visual.

    foreach arg {-verbose -match -skip -constraints} {
	set abbrev [string range $arg 0 1]
	if {([info exists flag($abbrev)]) && \
		([lsearch -exact $flagArray $arg] < \
		[lsearch -exact $flagArray $abbrev])} {
	    set flag($arg) $flag($abbrev)
	}
    }

    # Set ::tcltest::workingDir to [pwd].
    # Save the names of files that already exist in ::tcltest::workingDir.

    set ::tcltest::workingDir [pwd]
    foreach file [glob -nocomplain [file join $::tcltest::workingDir *]] {
	lappend ::tcltest::filesExisted [file tail $file]
    }

    # Set ::tcltest::verbose to the arg of the -verbose flag, if given

    if {[info exists flag(-verbose)]} {
	set ::tcltest::verbose $flag(-verbose)
    }

    # Set ::tcltest::match to the arg of the -match flag, if given

    if {[info exists flag(-match)]} {
	set ::tcltest::match $flag(-match)
    }

    # Set ::tcltest::skip to the arg of the -skip flag, if given

    if {[info exists flag(-skip)]} {
	set ::tcltest::skip $flag(-skip)
    }

    # Use the -constraints flag, if given, to turn on constraints that are
    # turned off by default: userInteractive knownBug nonPortable.  This
    # code fragment must be run after constraints are initialized.

    if {[info exists flag(-constraints)]} {
	foreach elt $flag(-constraints) {
	    set ::tcltest::testConfig($elt) 1
	}
    }
}

::tcltest::processCmdLineArgs


# ::tcltest::cleanupTests --
#
# Remove files and dirs created using the makeFile and makeDirectory
# commands since the last time this proc was invoked.
#
# Print the names of the files created without the makeFile command
# since the tests were invoked.
#
# Print the number tests (total, passed, failed, and skipped) since the
# tests were invoked.
#

proc ::tcltest::cleanupTests {{calledFromAllFile 0}} {
    set tail [file tail [info script]]

    # Remove files and directories created by the :tcltest::makeFile and
    # ::tcltest::makeDirectory procedures.
    # Record the names of files in ::tcltest::workingDir that were not
    # pre-existing, and associate them with the test file that created them.

    if {!$calledFromAllFile} {

	foreach file $::tcltest::filesMade {
	    if {[file exists $file]} {
		catch {file delete -force $file}
	    }
	}
	set currentFiles {}
	foreach file [glob -nocomplain [file join $::tcltest::workingDir *]] {
	    lappend currentFiles [file tail $file]
	}
	set newFiles {}
	foreach file $currentFiles {
	    if {[lsearch -exact $::tcltest::filesExisted $file] == -1} {
		lappend newFiles $file
	    }
	}
	set ::tcltest::filesExisted $currentFiles
	if {[llength $newFiles] > 0} {
	    set ::tcltest::createdNewFiles($tail) $newFiles
	}
    }

    if {$calledFromAllFile || $::tcltest::testSingleFile} {

	# print stats

	puts -nonewline stdout "$tail:"
	foreach index [list "Total" "Passed" "Skipped" "Failed"] {
	    puts -nonewline stdout "\t$index\t$::tcltest::numTests($index)"
	}
	puts stdout ""

	# print number test files sourced
	# print names of files that ran tests which failed

	if {$calledFromAllFile} {
	    puts stdout "Sourced $::tcltest::numTestFiles Test Files."
	    set ::tcltest::numTestFiles 0
	    if {[llength $::tcltest::failFiles] > 0} {
		puts stdout "Files with failing tests: $::tcltest::failFiles"
		set ::tcltest::failFiles {}
	    }
	}

	# if any tests were skipped, print the constraints that kept them
	# from running.

	set constraintList [array names ::tcltest::skippedBecause]
	if {[llength $constraintList] > 0} {
	    puts stdout "Number of tests skipped for each constraint:"
	    foreach constraint [lsort $constraintList] {
		puts stdout \
			"\t$::tcltest::skippedBecause($constraint)\t$constraint"
		unset ::tcltest::skippedBecause($constraint)
	    }
	}

	# report the names of test files in ::tcltest::createdNewFiles, and
	# reset the array to be empty.

	set testFilesThatTurded [lsort [array names ::tcltest::createdNewFiles]]
	if {[llength $testFilesThatTurded] > 0} {
	    puts stdout "Warning: test files left files behind:"
	    foreach testFile $testFilesThatTurded {
		puts "\t$testFile:\t$::tcltest::createdNewFiles($testFile)"
		unset ::tcltest::createdNewFiles($testFile)
	    }
	}

	# reset filesMade, filesExisted, and numTests

	set ::tcltest::filesMade {}
	foreach index [list "Total" "Passed" "Skipped" "Failed"] {
	    set ::tcltest::numTests($index) 0
	}

	# exit only if running Tk in non-interactive mode

	global tk_version tcl_interactive
	if {[info exists tk_version] && !$tcl_interactive} {
	    exit
	}
    } else {

	# if we're deferring stat-reporting until all files are sourced,
	# then add current file to failFile list if any tests in this file
	# failed

	incr ::tcltest::numTestFiles
	if {($::tcltest::currentFailure) && \
		([lsearch -exact $::tcltest::failFiles $tail] == -1)} {
	    lappend ::tcltest::failFiles $tail
	}
	set ::tcltest::currentFailure false
    }
}


# test --
#
# This procedure runs a test and prints an error message if the test fails.
# If ::tcltest::verbose has been set, it also prints a message even if the
# test succeeds.  The test will be skipped if it doesn't match the
# ::tcltest::match variable, if it matches an element in
# ::tcltest::skip, or if one of the elements of "constraints" turns
# out not to be true.
#
# Arguments:
# name -		Name of test, in the form foo-1.2.
# description -		Short textual description of the test, to
#			help humans understand what it does.
# constraints -		A list of one or more keywords, each of
#			which must be the name of an element in
#			the array "::tcltest::testConfig".  If any of these
#			elements is zero, the test is skipped.
#			This argument may be omitted.
# script -		Script to run to carry out the test.  It must
#			return a result that can be checked for
#			correctness.
# expectedAnswer -	Expected result from script.

proc ::tcltest::test {name description script expectedAnswer args} {
    incr ::tcltest::numTests(Total)

    # skip the test if it's name matches an element of skip

    foreach pattern $::tcltest::skip {
	if {[string match $pattern $name]} {
	    incr ::tcltest::numTests(Skipped)
	    return
	}
    }
    # skip the test if it's name doesn't match any element of match

    if {[llength $::tcltest::match] > 0} {
	set ok 0
	foreach pattern $::tcltest::match {
	    if {[string match $pattern $name]} {
		set ok 1
		break
	    }
        }
	if {!$ok} {
	    incr ::tcltest::numTests(Skipped)
	    return
	}
    }
    set i [llength $args]
    if {$i == 0} {
	set constraints {}
    } elseif {$i == 1} {

	# "constraints" argument exists;  shuffle arguments down, then
	# make sure that the constraints are satisfied.

	set constraints $script
	set script $expectedAnswer
	set expectedAnswer [lindex $args 0]
	set doTest 0
	if {[string match {*[$\[]*} $constraints] != 0} {

	    # full expression, e.g. {$foo > [info tclversion]}

	    catch {set doTest [uplevel #0 expr $constraints]}

	} elseif {[regexp {[^.a-zA-Z0-9 ]+} $constraints] != 0} {

	    # something like {a || b} should be turned into 
	    # $::tcltest::testConfig(a) || $::tcltest::testConfig(b).

 	    regsub -all {[.a-zA-Z0-9]+} $constraints \
		    {$::tcltest::testConfig(&)} c
	    catch {set doTest [eval expr $c]}
	} else {

	    # just simple constraints such as {unixOnly fonts}.

	    set doTest 1
	    foreach constraint $constraints {
		if {![info exists ::tcltest::testConfig($constraint)]
			|| !$::tcltest::testConfig($constraint)} {
		    set doTest 0

		    # store the constraint that kept the test from running

		    set constraints $constraint
		    break
		}
	    }
	}
	if {$doTest == 0} {
	    incr ::tcltest::numTests(Skipped)
	    if {[string first s $::tcltest::verbose] != -1} {
		puts stdout "++++ $name SKIPPED: $constraints"
	    }

	    # add the constraint to the list of constraints the kept tests
	    # from running

	    if {[info exists ::tcltest::skippedBecause($constraints)]} {
		incr ::tcltest::skippedBecause($constraints)
	    } else {
		set ::tcltest::skippedBecause($constraints) 1
	    }
	    return	
	}
    } else {
	error "wrong # args: must be \"test name description ?constraints? script expectedAnswer\""
    }
    memory tag $name
    set code [catch {uplevel $script} actualAnswer]
    if {$code != 0 || [string compare $actualAnswer $expectedAnswer] != 0} {
	incr ::tcltest::numTests(Failed)
	set ::tcltest::currentFailure true
	if {[string first b $::tcltest::verbose] == -1} {
	    set script ""
	}
	puts stdout "\n==== $name $description FAILED"
	if {$script != ""} {
	    puts stdout "==== Contents of test case:"
	    puts stdout $script
	}
	if {$code != 0} {
	    if {$code == 1} {
		puts stdout "==== Test generated error:"
		puts stdout $actualAnswer
	    } elseif {$code == 2} {
		puts stdout "==== Test generated return exception;  result was:"
		puts stdout $actualAnswer
	    } elseif {$code == 3} {
		puts stdout "==== Test generated break exception"
	    } elseif {$code == 4} {
		puts stdout "==== Test generated continue exception"
	    } else {
		puts stdout "==== Test generated exception $code;  message was:"
		puts stdout $actualAnswer
	    }
	} else {
	    puts stdout "---- Result was:\n$actualAnswer"
	}
	puts stdout "---- Result should have been:\n$expectedAnswer"
	puts stdout "==== $name FAILED\n" 
    } else { 
	incr ::tcltest::numTests(Passed)
	if {[string first p $::tcltest::verbose] != -1} {
	    puts stdout "++++ $name PASSED"
	}
    }
}

# ::tcltest::dotests --
#
#	takes two arguments--the name of the test file (such
#	as "parse.test"), and a pattern selecting the tests you want to
#	execute.  It sets ::tcltest::matching to the second argument, calls
#	"source" on the file specified in the first argument, and restores
#	::tcltest::matching to its pre-call value at the end.
#
# Arguments:
#	file    name of tests file to source
#	args    pattern selecting the tests you want to execute
#
# Results:
#	none

proc ::tcltest::dotests {file args} {
    set savedTests $::tcltest::match
    set ::tcltest::match $args
    source $file
    set ::tcltest::match $savedTests
}

proc ::tcltest::openfiles {} {
    if {[catch {testchannel open} result]} {
	return {}
    }
    return $result
}

proc ::tcltest::leakfiles {old} {
    if {[catch {testchannel open} new]} {
        return {}
    }
    set leak {}
    foreach p $new {
    	if {[lsearch $old $p] < 0} {
	    lappend leak $p
	}
    }
    return $leak
}

set ::tcltest::saveState {}

proc ::tcltest::saveState {} {
    uplevel #0 {set ::tcltest::saveState [list [info procs] [info vars]]}
}

proc ::tcltest::restoreState {} {
    foreach p [info procs] {
	if {[lsearch [lindex $::tcltest::saveState 0] $p] < 0} {
	    rename $p {}
	}
    }
    foreach p [uplevel #0 {info vars}] {
	if {[lsearch [lindex $::tcltest::saveState 1] $p] < 0} {
	    uplevel #0 "unset $p"
	}
    }
}

proc ::tcltest::normalizeMsg {msg} {
    regsub "\n$" [string tolower $msg] "" msg
    regsub -all "\n\n" $msg "\n" msg
    regsub -all "\n\}" $msg "\}" msg
    return $msg
}

# makeFile --
#
# Create a new file with the name <name>, and write <contents> to it.
#
# If this file hasn't been created via makeFile since the last time
# cleanupTests was called, add it to the $filesMade list, so it will
# be removed by the next call to cleanupTests.
#
proc ::tcltest::makeFile {contents name} {
    set fd [open $name w]
    fconfigure $fd -translation lf
    if {[string index $contents [expr {[string length $contents] - 1}]] == "\n"} {
	puts -nonewline $fd $contents
    } else {
	puts $fd $contents
    }
    close $fd

    set fullName [file join [pwd] $name]
    if {[lsearch -exact $::tcltest::filesMade $fullName] == -1} {
	lappend ::tcltest::filesMade $fullName
    }
}

proc ::tcltest::removeFile {name} {
    file delete $name
}

# makeDirectory --
#
# Create a new dir with the name <name>.
#
# If this dir hasn't been created via makeDirectory since the last time
# cleanupTests was called, add it to the $directoriesMade list, so it will
# be removed by the next call to cleanupTests.
#
proc ::tcltest::makeDirectory {name} {
    file mkdir $name

    set fullName [file join [pwd] $name]
    if {[lsearch -exact $::tcltest::filesMade $fullName] == -1} {
	lappend ::tcltest::filesMade $fullName
    }
}

proc ::tcltest::removeDirectory {name} {
    file delete -force $name
}

proc ::tcltest::viewFile {name} {
    global tcl_platform
    if {($tcl_platform(platform) == "macintosh") || \
		($::tcltest::testConfig(unixExecs) == 0)} {
	set f [open $name]
	set data [read -nonewline $f]
	close $f
	return $data
    } else {
	exec cat $name
    }
}

#
# Construct a string that consists of the requested sequence of bytes,
# as opposed to a string of properly formed UTF-8 characters.  
# This allows the tester to 
# 1. Create denormalized or improperly formed strings to pass to C procedures 
#    that are supposed to accept strings with embedded NULL bytes.
# 2. Confirm that a string result has a certain pattern of bytes, for instance
#    to confirm that "\xe0\0" in a Tcl script is stored internally in 
#    UTF-8 as the sequence of bytes "\xc3\xa0\xc0\x80".
#
# Generally, it's a bad idea to examine the bytes in a Tcl string or to
# construct improperly formed strings in this manner, because it involves
# exposing that Tcl uses UTF-8 internally.

proc ::tcltest::bytestring {string} {
    encoding convertfrom identity $string
}

# Locate tcltest executable

if {![info exists tk_version]} {
    set tcltest [info nameofexecutable]

    if {$tcltest == "{}"} {
	set tcltest {}
    }
}

set ::tcltest::testConfig(stdio) 0
catch {
    catch {file delete -force tmp}
    set f [open tmp w]
    puts $f {
	exit
    }
    close $f

    set f [open "|[list $tcltest tmp]" r]
    close $f
    
    set ::tcltest::testConfig(stdio) 1
}
catch {file delete -force tmp}

# Deliberately call the socket with the wrong number of arguments.  The error
# message you get will indicate whether sockets are available on this system.

catch {socket} msg
set ::tcltest::testConfig(socket) \
	[expr {$msg != "sockets are not available on this system"}]

#
# Internationalization / ISO support procs     -- dl
#

if {[info commands testlocale]==""} {

    # No testlocale command, no tests...
    # (it could be that we are a sub interp and we could just load
    # the Tcltest package but that would interfere with tests
    # that tests packages/loading in slaves...)

    set ::tcltest::testConfig(hasIsoLocale) 0
} else {
    proc ::tcltest::set_iso8859_1_locale {} {
	set ::tcltest::previousLocale [testlocale ctype]
	testlocale ctype $::tcltest::isoLocale
    }

    proc ::tcltest::restore_locale {} {
	testlocale ctype $::tcltest::previousLocale
    }

    if {![info exists ::tcltest::isoLocale]} {
	set ::tcltest::isoLocale fr
        switch $tcl_platform(platform) {
	    "unix" {

		# Try some 'known' values for some platforms:

		switch -exact -- $tcl_platform(os) {
		    "FreeBSD" {
			set ::tcltest::isoLocale fr_FR.ISO_8859-1
		    }
		    HP-UX {
			set ::tcltest::isoLocale fr_FR.iso88591
		    }
		    Linux -
		    IRIX {
			set ::tcltest::isoLocale fr
		    }
		    default {

			# Works on SunOS 4 and Solaris, and maybe others...
			# define it to something else on your system
			#if you want to test those.

			set ::tcltest::isoLocale iso_8859_1
		    }
		}
	    }
	    "windows" {
		set ::tcltest::isoLocale French
	    }
	}
    }

    set ::tcltest::testConfig(hasIsoLocale) \
	    [string length [::tcltest::set_iso8859_1_locale]]
    ::tcltest::restore_locale
} 

#
# procedures that are Tk specific
#

if {[info exists tk_version]} {

    # If the main window isn't already mapped (e.g. because the tests are
    # being run automatically) , specify a precise size for it so that the
    # user won't have to position it manually.

    if {![winfo ismapped .]} {
	wm geometry . +0+0
	update
    }

    # The following code can be used to perform tests involving a second
    # process running in the background.
    
    # Locate the tktest executable

    set ::tcltest::tktest [info nameofexecutable]
    if {$::tcltest::tktest == "{}"} {
	set ::tcltest::tktest {}
	puts stdout \
		"Unable to find tktest executable, skipping multiple process tests."
    }

    # Create background process
    
    proc ::tcltest::setupbg args {
	if {$::tcltest::tktest == ""} {
	    error "you're not running tktest so setupbg should not have been called"
	}
	if {[info exists ::tcltest::fd] && ($::tcltest::fd != "")} {
	    cleanupbg
	}
	
	# The following code segment cannot be run on Windows prior
	# to Tk 8.1b3 due to a channel I/O bug (bugID 1495).

	global tcl_platform
	set ::tcltest::fd [open "|[list $::tcltest::tktest -geometry +0+0 -name tktest] $args" r+]
	puts $::tcltest::fd "puts foo; flush stdout"
	flush $::tcltest::fd
	if {[gets $::tcltest::fd data] < 0} {
	    error "unexpected EOF from \"$::tcltest::tktest\""
	}
	if {[string compare $data foo]} {
	    error "unexpected output from background process \"$data\""
	}
	fileevent $::tcltest::fd readable bgReady
    }
    
    # Send a command to the background process, catching errors and
    # flushing I/O channels

    proc ::tcltest::dobg {command} {
	puts $::tcltest::fd "catch [list $command] msg; update; puts \$msg; puts **DONE**; flush stdout"
	flush $::tcltest::fd
	set ::tcltest::bgDone 0
	set ::tcltest::bgData {}
	tkwait variable ::tcltest::bgDone
	set ::tcltest::bgData
    }

    # Data arrived from background process.  Check for special marker
    # indicating end of data for this command, and make data available
    # to dobg procedure.

    proc ::tcltest::bgReady {} {
	set x [gets $::tcltest::fd]
	if {[eof $::tcltest::fd]} {
	    fileevent $::tcltest::fd readable {}
	    set ::tcltest::bgDone 1
	} elseif {$x == "**DONE**"} {
	    set ::tcltest::bgDone 1
	} else {
	    append ::tcltest::bgData $x
	}
    }

    # Exit the background process, and close the pipes

    proc ::tcltest::cleanupbg {} {
	catch {
	    puts $::tcltest::fd "exit"
	    close $::tcltest::fd
	}
	set ::tcltest::fd ""
    }

    # Clean up focus after using generate event, which
    # can leave the window manager with the wrong impression
    # about who thinks they have the focus. (BW)
    
    proc ::tcltest::fixfocus {} {
	catch {destroy .focus}
	toplevel .focus
	wm geometry .focus +0+0
	entry .focus.e
	.focus.e insert 0 "fixfocus"
	pack .focus.e
	update
	focus -force .focus.e
	destroy .focus
    }
}

# threadReap --
#
#	Kill all threads except for the main thread.
#	Do nothing if testthread is not defined.
#
# Arguments:
#	none.
#
# Results:
#	Returns the number of existing threads.

if {[info commands testthread] != {}} {
    proc ::tcltest::threadReap {} {
	testthread errorproc ThreadNullError
	while {[llength [testthread names]] > 1} {
	    foreach tid [testthread names] {
		if {$tid != $::tcltest::mainThread} {
		    catch {testthread send -async $tid {testthread exit}}
		    update
		}
	    }
	}
	testthread errorproc ThreadError
	return [llength [testthread names]]
    }
} else {
    proc ::tcltest::threadReap {} {
	return 1
    }   
}

# Need to catch the import because it fails if defs.tcl is sourced
# more than once.

catch {namespace import ::tcltest::*}
return

Added jni/tkzinc/sandbox/fvwm.xbm.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define fvwm_width 58
#define fvwm_height 26
static char fvwm_bits[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0xfc, 0x1b, 0xd8, 0xc0, 0xc0, 0xe6, 0x38, 0x00, 0xfc, 0x1b, 0xcc, 0xe0,
   0x60, 0xf7, 0x7d, 0x00, 0x30, 0x18, 0xcc, 0xe0, 0x60, 0xb3, 0x6d, 0x00,
   0x30, 0x38, 0xc6, 0xf1, 0x31, 0x9b, 0x67, 0x00, 0x30, 0x30, 0x86, 0xb1,
   0x31, 0xcf, 0x73, 0x00, 0x38, 0x30, 0x83, 0x99, 0x99, 0xc7, 0x31, 0x00,
   0x38, 0x30, 0x83, 0x99, 0x99, 0xc3, 0x30, 0x00, 0x18, 0xb0, 0x81, 0x8d,
   0x8d, 0xc1, 0x30, 0x00, 0x18, 0xb0, 0x81, 0x8d, 0x8d, 0xc1, 0x30, 0x00,
   0x1c, 0xf0, 0x80, 0x87, 0xc7, 0xe0, 0x38, 0x00, 0x1c, 0x60, 0x00, 0x03,
   0xc3, 0x60, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00};

Added jni/tkzinc/sandbox/lines.pl.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/perl -w

use Tk;
use Tk::Zinc;
    
$mw = MainWindow->new();

$top = 1;
$zinc = $mw->Zinc(-render => 1,
		  -borderwidth => 0,
		  -highlightthickness => 0,
		  -relief => 'sunken',
		  -takefocus => 1,
#		  -tile => $papier
		  );
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => 500, -height => 500);

print "coucou\n";
$view = $zinc->add('group', $top, -tags => "controls");
$mp3 = $zinc->add('curve', $view, [20, 280, 100, 430, 200, 430],
		  -linewidth => 9,
		  -closed => 0,
		  -linestyle => 'dashed',
		  -joinstyle => 'round',
#		  -firstend => [3, 12, 8],
#		  -lastend => "12 12 8",
		  -capstyle => 'round',
		  -linecolor => 'red:100');

$mw->Tk::bind('<p>', sub { print "perfs: ", join(',', $zinc->monitor()), "\n" });
$mw->Tk::bind('<t>', sub { $zinc->remove($mp3); });
$mw->Tk::bind('<q>', sub { exit(0); });
$zinc->focusFollowsMouse();
MainLoop();

Added jni/tkzinc/sandbox/logo.gif.

cannot compute difference between binary files

Added jni/tkzinc/sandbox/smooth.tcl.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so
package require Img

set top 1
set points "50 -150 100 -50 270 -130 220 -200 200 -180 180 -300 140 -320 70 -300"
set lw 3

set r [zinc .r -backcolor gray -relief sunken]
pack .r -expand t -fill both
.r configure -width 800 -height 500
.r scale $top 1 -1
#.r configure -drawbboxes t
set view [.r add group $top -tags controls]


set smooth [.r smooth $points]
set fit [.r fit  $points 0.1]


set mp [.r add curve $view $smooth \
	-linecolor yellow -fillcolor tan -fillpattern AlphaStipple8 \
	-tags "bezier" -linewidth $lw]
set mp2 [.r add curve $view $fit \
	-linecolor yellow -fillcolor tan -fillpattern AlphaStipple8 \
	-tags "bezier" -linewidth $lw]
set poly [.r add curve $view $points -marker AtcSymbol9]
set poly2 [.r add curve $view $points -marker AtcSymbol9]

.r translate $mp2 300 0
.r translate $poly2 300 0

source "controls.tcl"

Added jni/tkzinc/sandbox/testarc.tcl.

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so
package require Img

set top 1

#image create photo logo -file logo.gif
#image create photo papier -file texture-paper.xpm
#image create photo penguin -file xpenguin.png
#image create photo papier -file texture-paper.xpm

set r [zinc .r -backcolor gray -relief sunken -render 0]
pack .r -expand t -fill both
.r configure -width 800 -height 500
#.r configure -drawbboxes t
.r scale $top 1 -1
set view [.r add group $top -tags "controls"]
.r translate $view 200 -200
set view2  [.r add group $top]
.r translate $view2 300 -200

set arc [.r add arc $view "50 -10 200 -100" -filled t -closed t -pieslice t \
	-fillcolor "white|darkslateblue" -linewidth 1 \
	-startangle 0 -extent 120]
#set arc [.r add arc $view "50 -10 200 -100" -filled t -closed t -pieslice t -fillcolor "#ff0000|#00ff00" -linewidth 0]
#.r add arc $view "60 -20 190 -90" -filled t -closed t -pieslice t -fillcolor "white|darkslateblue" -linewidth 1 -linecolor white

#set arc2 [.r clone $arc -linecolor red -firstend "8 10 5"]
#.r rotate $arc2 10
#.r translate $arc2 100 -100

#.r add icon $view2 -image penguin
set cliparc [.r add arc $view "-100 100 100 -100" -filled t \
	-fillcolor tan ]
.r lower $cliparc
#.r rotate $cliparc 20 0 0
#.r translate $cliparc 100 -40
#.r itemconfigure $view2 -clip $cliparc
bind .r <1> ".r rotate $cliparc [expr 3.14/3] 0 0"
source "controls.tcl"
.r bind $cliparc <1> {puts a}
puts "[ .r bind  $cliparc <1> ]\n"

Added jni/tkzinc/sandbox/testbezier.pl.





























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/usr/bin/perl -w


use Tk;
use Tk::Zinc;
use Controls;
use Tk::Photo;
require Tk::PNG;


$top = 1;
$lw = 8;
$arrow = [8, 10, 6];

#
#          Cap, Filled, Border, Relief, Title
#
@show = (
	 ['round',      0, 1, 'flat',   'CapRound'],
	 ['butt',       0, 1, 'flat',   'CapButt'],
	 ['projecting', 0, 1, 'flat',   'CapProjecting'],
	 ['round',      0, 1, 'sunken', 'Sunken'],
	 ['round',      0, 1, 'raised', 'Raised'],
	 ['round',      0, 1, 'groove', 'Groove'],
	 ['round',      0, 1, 'ridge',  'Ridge'],
	 ['round',      1, 1, 'roundsunken', 'RoundSunken'],
	 ['round',      1, 1, 'roundraised', 'RoundRaised'],
	 ['round',      1, 1, 'roundgroove', 'RoundGroove'],
	 ['round',      1, 1, 'roundridge',  'RoundRidge'],
	 ['round',      1, 1, 'sunkenrule', 'SunkenRule'],
	 ['round',      1, 1, 'raisedrule',  'RaisedRule'],
	 ['round',      1, 0, 'flat',   'Fill'],
	 ['round',      1, 1, 'flat',   'FillBorder']);

$mw = MainWindow->new();
#$logo = $mw->Photo(-file => "logo.gif");
$papier = $mw->Photo(-file => "texture-paper.xpm");

$zinc = $mw->Zinc(-render => 1,
		  -lightangle => 120,
		  -borderwidth => 0,
		  -highlightthickness => 0,
		  -relief => 'sunken',
		  -takefocus => 1,
		  -backcolor => 'red'
	#	  -tile => $papier
		  );
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => 500, -height => 500);
$zinc->scale($top, 1, -1);

$view = $zinc->add('group', $top,
		   -tags => 'controls');
$clipbez = $zinc->add('bezier', $view, [20, -20,
					890, -20,
					890, -900,
					20, -400],
		      -linewidth => 0,
		      -filled => 1,
		      -fillcolor => 'tan');
#$zinc->itemconfigure($view,
#		     -clip => $clipbez);

#
# Create the model
#
$model = $zinc->add('group', $view);
$mp = $zinc->add('bezier', $model, [50, -150,
				    100, -50,
				    270, -130,
				    220, -200,
				    200, -180,
				    180, -300,
				    140, -160,
				    70, -300],
		 -fillcolor => 'tan',
		 -tags => 'bezier',
		 -linewidth =>$lw);
#$zinc->add('rectangle', $model, [50, -150, 100, -50]);
@bbox = $zinc->bbox($mp);
@bbox = $zinc->transform($model, \@bbox);
$x = ($bbox[2] + $bbox[0]) / 2;
$y = $bbox[1] + 5;
$zinc->add('text', $model,
	   -text => 'CapRound',
	   -color => 'blue',
	   -alignment => 'center',
	   -anchor => 's',
	   -tags => 'title',
	   -position => [$x, $y]);

#
# Now clone for each variation on the polygon
#
$col = 0;
$row = 0;
foreach $current (@show) {
  ($cap, $filled, $border, $relief, $title) = @{$current};
  $grp = $zinc->clone($model);
  $zinc->translate($grp, $col * 240, $row * (-290 - (2 * $lw)));
  $zinc->itemconfigure($zinc->find('withtag', "$grp*bezier"),
		       -capstyle => $cap,
		       -filled => $filled,
		       -linewidth => $border ? $lw : 0,
		       -relief => $relief,
		       -linecolor => $relief eq 'flat' ? 'yellow' : 'tan');
  $zinc->itemconfigure($zinc->find('withtag', "$grp*title"),
		       -text => $title);
  $col++;
  if ($col >= 4) {
    $col = 0;
    $row++;
  }
}

#
# Suppress the model
#
$zinc->remove($model);

my @coords = (
10, 0, 40, 0, 70, 0,
70, 0, 80, 0, 80, 10,
80, 10, 80, 40, 80, 70,
80, 70, 80, 80, 70, 80,
70, 80, 40, 80, 10, 80,
10, 80, 0, 80, 0, 70,
0, 70, 0, 40, 0, 10,
0, 10, 0, 0, 10, 0);
$zinc->add('bezier', $view, \@coords);

#
# Some optional graphic features
$closed = 0;
#set smooth 0
$arrows = 'none';

sub toggle_arrows {
  if ($arrows eq 'none') {
    $arrows = 'first';
    $f = $arrow;
    $l = '';
  }
  elsif ($arrows eq 'first') {
    $arrows = 'last';
    $f = '';
    $l = $arrow;
  }
  elsif ($arrows eq 'last') {
    $arrows = 'both';
    $f = $arrow;
    $l = $arrow;
  }
  elsif ($arrows eq 'both') {
    $arrows = 'none';
    $f = '';
    $l = '';
  }
  $zinc->itemconfigure('bezier',
		       -firstend => $f,
		       -lastend => $l)
}


sub toggle_closed {
  $closed = !$closed;
  foreach $ curve ($zinc->find('withtag', 'bezier')) {
    if ($closed) {
      @coords = $zinc->coords($curve, 0, 0);
      $zinc->coords($curve, 'add', \@coords);
    }
    else {
      $zinc->coords($curve, 'remove', -1)
    }
  }
}

$zinc->Tk::focus();

$zinc->Tk::bind('<a>', \&toggle_arrows);
$zinc->Tk::bind('<c>', \&toggle_closed);

$zinc->Tk::bind('<Shift-1>',
		sub {my $ev = $zinc->XEvent();
		     my $it = $zinc->find('closest', $ev->x, $ev->y);
		     print "$it ", $zinc->verticeat($it, $ev->x, $ev->y), "\n"});
$zinc->Tk::bind('<Shift-ButtonRelease-1>', sub {Tk::break});

new Controls($zinc);
MainLoop();

Added jni/tkzinc/sandbox/testbezier.tcl.







































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so
package require Img

set top 1
set lw 8
set arrow "8 10 6"


#
#  Cap        Filled Border Relief Title
#
set show {\
  {round      f      1      flat   CapRound}\
  {butt       f      1      flat   CapButt}\
  {projecting f      1      flat   CapProjecting}\
  {round      f      1      sunken Sunken}\
  {round      f      1      raised Raised}\
  {round      f      1      groove Groove}\
  {round      f      1      ridge  Ridge}\
  {round      t      1      sunken FilledSunken}\
  {round      t      1      raised FilledRaised}\
  {round      t      1      groove FilledGroove}\
  {round      t      1      ridge  FilledRidge}\
  {round      t      0      flat   Fill}\
  {round      t      1      flat   FillBorder}}

image create photo logo -file /usr/share/toccata/images/logo.gif
#image create photo papier -file /usr/share/toccata/images/dgtexture-dragstrip.xpm

set r [zinc .r -backcolor gray -relief sunken]
pack .r -expand t -fill both
.r configure -width 1024 -height 800
.r scale $top 1 -1
#.r configure -drawbboxes t
set view [.r add group $top -tags controls]

#
# Create the model
#
set model [.r add group $view]
set mp [.r add bezier $model "50 -150 100 -50 270 -130 220 -200 200 -180 180 -300 140 -160 70 -300" \
	    -linecolor yellow -fillcolor tan -fillpattern AlphaStipple8 \
	    -tags "bezier" -linewidth $lw]
#.r add rectangle $model "50 -150 100 -50"
set bbox [.r transform $model [.r bbox $mp]]
set x [expr ([lindex $bbox 2] + [lindex $bbox 0]) / 2]
set y [expr [lindex $bbox 1] + 5]
.r add text $model -text "CapRound" -color blue -alignment center -anchor s -tags "title" \
    -position "$x $y"

#
# Now clone for each variation on the polygon
#
set col 0
set row 0
foreach current $show {
    foreach {cap filled border relief title} $current {
	set grp [.r clone $model]
	.r translate $grp [expr $col * 240] [expr $row * (-290 - (2 * $lw))]
	.r itemconfigure [.r find withtag "bezier" $grp] \
	    -capstyle $cap -filled $filled \
	    -linewidth [expr $border ? $lw : 0] \
	    -relief $relief -linecolor [expr $relief == flat ? yellow : tan]
	.r itemconfigure [.r find withtag "title" $grp] -text $title
	incr col
	if {$col >= 4} {
	    set col 0
	    incr row
	}
    }
}

#
# Suppress the model
#
.r remove $model


#
# Some optional graphic features
set closed 0
#set smooth 0
set arrows none

proc toggle_arrows { } {
    global arrows arrow
    if {$arrows == "none"} {
	set arrows first
	set f $arrow
	set l ""
    } elseif {$arrows == "first"} {
	set arrows last
	set f ""
	set l $arrow
    } elseif {$arrows == "last"} {
	set arrows both
	set f $arrow
	set l $arrow
    } elseif {$arrows == "both"} {
	set arrows none
	set f ""
	set l ""
    }
    .r itemconfigure bezier -firstend $f -lastend $l
}


proc toggle_closed { } {
    global closed
    set closed [expr ! $closed]
    foreach curve [.r find withtag "bezier"] {
	if {$closed} {
	    .r coords $curve add [.r coords $curve 0]
	} {
	    .r coords $curve remove -1
	}
    }
	
}

focus .r

bind .r "<a>" toggle_arrows
bind .r "<c>" toggle_closed

bind .r "<Shift-1>" {set it [.r find closest %x %y]; puts "$it [.r verticeat $it %x %y]"}
bind .r "<Shift-ButtonRelease-1>" {break}

source "controls.tcl"

Added jni/tkzinc/sandbox/testbitmaps.tcl.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/local/bin/wish -f

lappend auto_path ..
package require Tkzinc
package require Img

set r [zinc .r -render 1 -backcolor gray -relief sunken]
set top 1
pack .r -expand t -fill both
.r configure -width 500 -height 800

set r [.r add rectangle $top "30 50 80 100" -filled t -fillpattern AlphaStipple0 -linewidth 1]
.r translate $r -55 -75
.r rotate $r 45
.r translate $r 55 75

.r add text $top -position "50 110" -text "0"
.r add rectangle $top "100 50 150 100" -filled t -fillpattern AlphaStipple1
.r add text $top -position "120 110" -text "1"
.r add rectangle $top "170 50 220 100" -filled t -fillpattern AlphaStipple2
.r add text $top -position "190 110" -text "2"
.r add rectangle $top "240 50 290 100" -filled t -fillpattern AlphaStipple3
.r add text $top -position "260 110" -text "3"
.r add rectangle $top "310 50 360 100" -filled t -fillpattern AlphaStipple4
.r add text $top -position "330 110" -text "4"
.r add rectangle $top "380 50 430 100" -filled t -fillpattern AlphaStipple5
.r add text $top -position "400 110" -text "5"

.r add rectangle $top "30 150 80 200" -filled t -fillpattern AlphaStipple6
.r add text $top -position "50 210" -text "6"
.r add rectangle $top "100 150 150 200" -filled t -fillpattern AlphaStipple7
.r add text $top -position "120 210" -text "7"
.r add rectangle $top "170 150 220 200" -filled t -fillpattern AlphaStipple8
.r add text $top -position "190 210" -text "8"
.r add rectangle $top "240 150 290 200" -filled t -fillpattern AlphaStipple9
.r add text $top -position "260 210" -text "9"
.r add rectangle $top "310 150 360 200" -filled t -fillpattern AlphaStipple10
.r add text $top -position "330 210" -text "10"
.r add rectangle $top "380 150 430 200" -filled t -fillpattern AlphaStipple11
.r add text $top -position "400 210" -text "11"

.r add rectangle $top "100 250 150 300" -filled t -fillpattern AlphaStipple12
.r add text $top -position "120 310" -text "12"
.r add rectangle $top "170 250 220 300" -filled t -fillpattern AlphaStipple13
.r add text $top -position "190 310" -text "13"
.r add rectangle $top "240 250 290 300" -filled t -fillpattern AlphaStipple14
.r add text $top -position "260 310" -text "14"
.r add rectangle $top "310 250 360 300" -filled t -fillpattern AlphaStipple15
.r add text $top -position "330 310" -text "15"

.r add text $top -position "180 360" -text "AlphaStipple" \
	-font "-*-lucida-bold-r-normal-*-14-*-*-*-*-*-*-*"

for {set i 0} {$i < 22} {incr i} {
    set num [expr $i + 1]
    .r add waypoint $top 0 \
	    -position "[expr 40 + ($i % 8)*60] [expr 420 + ($i / 8)*45]" \
	    -symbol "AtcSymbol$num"
    .r add text $top \
	    -position "[expr 36 + ($i % 8)*60] [expr 430 + ($i / 8)*45]" \
	    -text "$num" \
	    -font "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*"
}

.r add text $top -position "180 560" -text "AtcSymbol" \
	-font "-*-lucida-bold-r-normal-*-14-*-*-*-*-*-*-*"


set im [image create bitmap toto -background "red" -file fvwm.xbm]
set icim [.r add icon 1 -image $im -position {0 0}]
.r rotate $icim 20
.r scale $icim 1.2 1.2
.r translate $icim 50 320
#.r add icon 1 -image $im -position {300 10}
#.r add rectangle 1 {10 10 100 100} -tile $im -filled 1
#$im configure -background red

set icbit [.r add icon 1 -image @fvwm.xbm -position {100 400}]

#.r bind $icbit <Enter> ".r itemconfigure $icbit -color red; \
# $im configure -file fvwm.xbm -foreground black"
#.r bind $icbit <Leave> ".r itemconfigure $icbit -color black; \
# $im configure -file trash.xbm -foreground red "

#.r bind $icim <Enter> "$im configure -background black"
#.r bind $icim <Leave> "$im configure -background red"

Added jni/tkzinc/sandbox/testicon.tcl.













































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so
package require Img

set top 1

image create photo penguin -file xpenguin.png
image create photo bouton -file bouton.xpm
image create photo boutond -file bouton-down.xpm
set mask "fvwm.xbm"

set r [zinc .r -backcolor gray -relief sunken -render 1 -borderwidth 20]
pack .r -expand t -fill both
.r configure -width 800 -height 500
#.r configure -drawbboxes t
.r scale $top 1 -1
set view [.r add group $top -tags "controls"]

proc maskicon {x y group mask color anchor} {
    .r add icon $group -mask "@$mask" -position "$x $y" -anchor $anchor -color $color
    .r add rectangle $group [list [expr $x - 3.0] [expr $y - 3.0] \
    [expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red
}

proc imageicon {x y group image anchor} {
    .r add icon $group -image $image -position "$x $y" -anchor $anchor
    .r add rectangle $group [list [expr $x - 3.0] [expr $y - 3.0] \
	    [expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red
}

set x 50.0
set y -100.0
maskicon $x $y $view $mask yellow sw
set x [expr $x + 100.0]
maskicon $x $y $view $mask pink s
set x [expr $x + 100.0]
maskicon $x $y $view $mask violet se
set x 50
set y -150
maskicon $x $y $view $mask lightblue w
set x [expr $x + 100.0]
maskicon $x $y $view $mask blue center
set x [expr $x + 100.0]
maskicon $x $y $view $mask darkblue e
set x 50.0
set y -200.0
maskicon $x $y $view $mask violet nw
set x [expr $x + 100.0]
maskicon $x $y $view $mask pink n
set x [expr $x + 100.0]
maskicon $x $y $view $mask yellow ne
set x2 500.0
set y2 -300.0
imageicon $x2 $y2 $view penguin center

.r add icon $view -image bouton -position "$x2 $y2" -anchor center
.r add icon $view -image boutond -position [list [expr $x2 + 50] $y2] -anchor center
.r add text $view -text essai -position "$x2 $y2"

#
# Clip
#
puts "crée les clips"
set clip [.r add rectangle $view "50 -10 600 -300" -filled t \
	-linewidth 0 -fillcolor darkgray]
#.r rotate $clip [expr 3.14159 / 4]; #bug le rectangle forme un bonnet
# d'ane sous certains angles.
.r lower $clip
.r itemconfigure $view -clip $clip

.r addtag test withtype icon
.r bind test "<Shift-ButtonPress-1>"  "testpress %x %y"
.r bind test "<Shift-ButtonRelease-1>"  testrelease

proc testpress {lx ly} {
    global testx testy
    set testx $lx
    set testy $ly
    .r bind test "<Motion>" "testmotion %x %y"
}

proc testmotion {lx ly} {
    global testx testy
    set it [.r find withtag test]
    if {$it != ""} {
	set it [.r group [lindex $it 0]]
    }
    set res [.r transform $it "$lx $ly $testx $testy"]
    set nx [lindex $res 0]
    set ny [lindex $res 1]
    set ox [lindex $res 2]
    set oy [lindex $res 3]
    .r translate current [expr $nx - $ox] [expr $ny - $oy]
    set testx $lx
    set testy $ly
}
proc testrelease {} {
    .r bind test "<Motion>" ""
}

source controls.tcl

Added jni/tkzinc/sandbox/testplug.pl.







































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/perl

use Tk;

$mw = MainWindow->new();

$zinc = $mw->Zinc(-backcolor => 'gray',
		  -relief => 'sunken',
		  -width => 800,
		  -height => 500)->pack(-expand => 1,
					-fill => 'both');
$top = 1;
#$ent = $zinc->Entry();
#$entryitem = $zinc->add('window', $top,
#			-window => $ent,
#			-position => [100, 100]);
$dcontainer = $zinc->Frame(-container => 1);
$did = $dcontainer->id();
$vcontainer = $zinc->Frame(-container => 1);
$vid = $vcontainer->id();
#print "container id is $id\n";

$dlabel = $zinc->add('text', $top,
		     -text => "Digistrips",
		     -position => [150, 30]);
$zinc->bind($dlabel, '<1>', sub { $zinc->itemconfigure($vlabel, -color => 'black');
				  $zinc->itemconfigure($dlabel, -color => 'red');
				  $zinc->itemconfigure($vcontitem, -visible => 0);
				  $zinc->itemconfigure($dcontitem, -visible => 1); });
$vlabel = $zinc->add('text', $top,
		     -text => "Virtuosi",
		     -position => [250, 30]);
$zinc->bind($vlabel, '<1>', sub { $zinc->itemconfigure($dlabel, -color => 'black');
				  $zinc->itemconfigure($vlabel, -color => 'red');
				  $zinc->itemconfigure($dcontitem, -visible => 0);
				  $zinc->itemconfigure($vcontitem, -visible => 1); });
$dcontitem = $zinc->add('window', $top,
			-window => $dcontainer,
			-position => [50, 75],
			-visible => 0);
$vcontitem = $zinc->add('window', $top,
			-window => $vcontainer,
			-position => [50, 75],
			-visible => 0);

$mw->update();

system("digistripsIII -stan --use $did -style standalone-1024x768 &");
system("virtuosi -g 1024x768 -use $vid &");

MainLoop();

Added jni/tkzinc/sandbox/testpoly.tcl.



























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/local/bin/wish -f

lappend auto_path ..
package require Tkzinc
package require Img

set top 1
set lw 8
set marker AtcSymbol9
set arrow "8 10 6"


#
#  Cap        Join   Filled Border Relief Title
#
set show {\
  {round      round  f      1      flat   JoinRound}\
  {round      bevel  f      1      flat   JoinBevel}\
  {round      miter  f      1      flat   JoinMiter}\
  {butt       round  f      1      flat   CapButt}\
  {projecting round  f      1      flat   CapProjecting}\
  {round      round  f      1      sunken Sunken}\
  {round      round  f      1      raised Raised}\
  {round      round  f      1      groove Groove}\
  {round      round  f      1      ridge  Ridge}\
  {round      round  t      1      sunken FilledSunken}\
  {round      round  t      1      raised FilledRaised}\
  {round      round  t      1      groove FilledGroove}\
  {round      round  t      1      ridge  FilledRidge}\
  {round      round  f      0      flat   Marker}\
  {round      round  t      0      flat   Fill}\
  {round      round  t      1      flat   FillBorder}}

image create photo logo -file logo.gif
#image create photo papier -file /usr/share/toccata/images/dgtexture-dragstrip.xpm

set r [zinc .r -backcolor gray -relief sunken -render 0]
pack .r -expand t -fill both
.r configure -width 1024 -height 800
.r scale $top 1 -1
#.r configure -drawbboxes t
set view [.r add group $top -tags controls]

#
# Create the model
#
set model [.r add group $view]
set mp [.r add curve $model "50 -150 100 -50 270 -130 220 -200 200 -180 180 -300 140 -160 70 -300" \
	    -linecolor yellow -fillcolor tan -fillpattern AlphaStipple8 \
	    -markercolor red -tags "poly" -linewidth $lw]
.r add rectangle $model "50 -150 100 -50"
set bbox [.r transform $model [.r bbox $mp]]
set x [expr ([lindex $bbox 2] + [lindex $bbox 0]) / 2]
set y [expr [lindex $bbox 1] + 5]
.r add text $model -text "CapRound" -color blue -alignment center -anchor s -tags "title" \
    -position "$x $y"

#
# Now clone for each variation on the polygon
#
proc linecol { relief } {
    if {[string compare $relief flat]} {
	return yellow
    } else {
	return tan
    }
}

set col 0
set row 0
foreach current $show {
    foreach {cap join filled border relief title} $current {
	set grp [.r clone $model]
	.r translate $grp [expr $col * 240] [expr $row * (-290 - (2 * $lw))]
	.r itemconfigure [.r find withtag "$grp*poly"] \
	    -capstyle $cap -joinstyle $join -filled $filled \
	    -linewidth [expr $border ? $lw : 0] -relief $relief \
	    -linecolor [linecol $relief]
	.r itemconfigure [.r find withtag "$grp*title"] -text $title
	incr col
	if {$col >= 4} {
	    set col 0
	    incr row
	}
    }
}

#
# Suppress the model
#
.r remove $model


#
# Some optional graphic features
set closed 0
set marks 0
#set smooth 0
set arrows none

proc toggle_arrows { } {
    global arrows arrow
    if {$arrows == "none"} {
	set arrows first
	set f $arrow
	set l ""
    } elseif {$arrows == "first"} {
	set arrows last
	set f ""
	set l $arrow
    } elseif {$arrows == "last"} {
	set arrows both
	set f $arrow
	set l $arrow
    } elseif {$arrows == "both"} {
	set arrows none
	set f ""
	set l ""
    }
    .r itemconfigure poly -firstend $f -lastend $l
}

proc toggle_marks { } {
    global marks marker
    set marks [expr ! $marks]
    if {$marks} {
	.r itemconfigure poly -marker $marker
    } {
	.r itemconfigure poly -marker ""
    }
}

#proc toggle_smooth { } {
#    global smooth
#    set smooth [expr ! $smooth]
#    .r itemconfigure poly -smoothed $smooth
#}

proc toggle_closed { } {
    global closed
    set closed [expr ! $closed]
    foreach curve [.r find withtag "poly"] {
	.r itemconfigure $curve -closed $closed
    }
	
}

focus .r

bind .r "<a>" toggle_arrows
bind .r "<c>" toggle_closed
bind .r "<m>" toggle_marks

bind .r "<Shift-1>" {set it [.r find closest %x %y]; puts "$it [.r verticeat $it %x %y]"}
bind .r "<Shift-ButtonRelease-1>" {break}

source "controls.tcl"

Added jni/tkzinc/sandbox/testrect.pl.







































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/perl -w

use Tk;
use Tk::Zinc;

use Controls;

$mw = MainWindow->new();


###################################################
# creation zinc
###################################################
$top = 1;
$zinc_width = 800;
$zinc_height = 500;

$zinc = $mw->Zinc(-backcolor => 'gray65', -relief => 'sunken');
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => $zinc_width, -height => $zinc_height);

#$zinc->configure(-drawbboxes => 1);

#print "cells ", $zinc->cells(), " visual ", $zinc->visual(), " ", $zinc->visualsavailable(), "\n";

$zinc->scale($top, 1, -1);
$view = $zinc->add('group', $top, -tags => ["controls"]);
$zinc->translate($view, 300, -200);
$view2 = $zinc->add('group', $top);
$zinc->translate($view2, 100, -50);


#$rect0 = $zinc->add('rectangle', $view [100, -105, 200, -305],
#                    -filled => t,
#                    -fillcolor => "white|cadetblue3");

$color1 = 'darkslateblue';
$color2 = '#f0ffff';
$gangle = 0;
$shades = 8;
$rect1 = $zinc->add('rectangle', $view, [-50, 100, 50, -100],
		    -filled => 1,
		    -relief => 'flat',
		    -linewidth => 1,
		    -fillpattern => 'AlphaStipple7',
		    -fillcolor => "$color1|$color2/$gangle%$shades");
#
# Mire
$zinc->add('curve', $view, [-10, 0, 10, 0],
	   -linecolor => 'red');
$zinc->add('curve', $view, [0, -10, 0, 10],
	   -linecolor => 'red');

$handle = $zinc->add('arc', $view, [-3, -106, 3, -112],
		     -filled => 1,
		     -fillcolor => 'red');
$zinc->bind($handle, '<B1-Motion>', \&adjustcontrol);

sub adjustcontrol {
    my $ev = $zinc->XEvent();
    my $x;
    my $y;
    my ($xo, $yo, $xc, $yc) = $zinc->coords($rect1);

    ($x, $y) = $zinc->transform($view, [$ev->x, 0]);
    if ($x < $xo) {
	$x = $xo;
    }
    elsif ($x > $xc) {
	$x = $xc;
    }
    $zinc->coords($handle, [$x - 3, $yc-6, $x + 3, $yc-12]);
    $x = ($x - $xo)*100/($xc-$xo);
    $zinc->itemconfigure($rect1,
			 -fillcolor => "$color1 0 $x|$color2/$gangle%$shades");
}

#
# 72 61 139 = DarkSlateBlue
#
# 240 255 255 = azure
#
#set rect2 [.r add rectangle $view "202 -320 302 -350" -filled t -fillcolor darkgray -linewidth 2]

#set rect3 [.r add rectangle $view "250 -100 350 -300" -filled t -relief raised -linewidth 4 -fillcolor "white|cadetblue3" -linecolor white]

#set rect4 [.r add rectangle $view2 "0 0 101 -81" -linewidth 2 -linecolor darkgray -filled t]
#.r itemconfigure $rect4 -fillcolor "white|darkslateblue"

#set rect5 [.r add rectangle $view2 "0 0 101 -81" -linewidth 2 -linecolor blue -filled t -fillcolor blue -relief sunken]
#.r translate $rect5 0 -90


new Controls($zinc);

MainLoop();


1;

Added jni/tkzinc/sandbox/testrelief.pl.



















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/perl -w

use Tk;
use Tk::Zinc;
use Controls;

$top = 1;
$lw = 8;

$mw = MainWindow->new();
$zinc = $mw->Zinc(-backcolor => 'gray',
		  -relief => 'sunken',
		  -lightangle => 120,
		  -render => 1);
$zinc->pack(-expand => 1,
	    -fill => 'both');
$zinc->configure(-width => 1024,
		 -height => 800);
$zinc->scale($top, 1, -1);

$view = $zinc->add('group', $top, -tags => 'controls');

sub polypoints {
    ($ox, $oy, $rad, $n, $startangle) = @_;

    $step =  2 * 3.14159 / $n;
    $startangle = $startangle*3.14159/180;
    $coords = [];
    for ($i = 0; $i < $n; $i++) {
      $x = $ox + ($rad * cos($i * $step + $startangle));
      $y = $oy + ($rad * sin($i * $step + $startangle));
      push(@{$coords}, $x, $y);
    }
    push(@{$coords}, $coords->[0], $coords->[1]);
    return $coords
}

$zinc->add('curve', $view, polypoints(200, -200, 100, 40, 0),
	   -relief => 'raised',
	   -linewidth => $lw,
	   -smoothrelief => 1,
	   -fillcolor => 'lightblue',
	   -linecolor => 'lightblue',
	   -filled => 1);

$zinc->add('curve', $view, polypoints(450, -200, 100, 40, 0),
	   -relief => 'raised',
	   -linewidth => $lw,
	   -smoothrelief => 1,
	   -fillcolor => 'tan',
	   -linecolor => 'tan',
	   -filled => 1);

$zinc->add('curve', $view, polypoints(700, -200, 100, 40, 0),
	   -relief => 'sunken',
	   -linewidth => $lw,
	   -smoothrelief => 1,
	   -fillcolor => 'tan',
	   -linecolor => 'tan',
	   -closed => 1,
	   -filled => 1);

$zinc->add('curve', $view, polypoints(200, -450, 100, 7, -45),
	   -relief => 'sunken',
	   -linewidth => $lw,
	   -fillcolor => 'tan',
	   -linecolor => 'tan',
	   -filled => 1);


new Controls($zinc);
MainLoop();

Added jni/tkzinc/sandbox/testrelief.tcl.



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so

set top 1
set lw 8

set r [zinc .r -backcolor gray -relief sunken -lightangle 120 -render 0]
pack .r -expand t -fill both
.r configure -width 1024 -height 800
.r scale $top 1 -1

set view [.r add group $top -tags controls]

proc polypoints { ox oy rad n startangle } {
    set step [expr 2 * 3.14159 / $n]
    set startangle [expr $startangle*3.14159/180]
    set coords ""
    for {set i 0} {$i < $n} {incr i} {
	set x [expr $ox + ($rad * cos($i * $step + $startangle))];
	set y [expr $oy + ($rad * sin($i * $step + $startangle))];
	lappend coords $x $y;
    }
    lappend coords [lindex $coords 0] [lindex $coords 1]
    return $coords
}

set poly [ .r add curve $view [polypoints 200 -200 100 40 0] \
	-relief raised -linewidth $lw -smoothrelief 1 \
	-fillcolor lightblue -linecolor lightblue -filled t]

set poly [ .r add curve $view [polypoints 450 -200 100 40 0] \
	-relief raised -linewidth $lw \
	-fillcolor tan -linecolor tan -filled t]

set poly [ .r add curve $view [polypoints 700 -200 100 40 0] \
	-relief sunken -linewidth $lw \
	-fillcolor tan -linecolor tan -filled t]

set poly [ .r add curve $view [polypoints 200 -450 100 4 -45] \
	-relief sunken -linewidth $lw \
	-fillcolor tan -linecolor tan -filled t]


source "controls.tcl"

Added jni/tkzinc/sandbox/testshape.pl.









































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/perl -w

use Tk;
use Tk::Zinc;
use Controls;

$mw = MainWindow->new();

$top = 1;
$zinc = $mw->Zinc(-render => 1,
		  -borderwidth => 0,
#		  -fullreshape => 0,
		  -relief => 'sunken');
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => 500, -height => 500);

$zinc->gname('white:40 0 60|black 50|white 100(0 0', 'oeil');
$zinc->gname('white:0 0 10|black:100 100/0', 'oeil2');
$zinc->gname('white:100|black:100(-35 -25', 'boule');
$zinc->gname('white:100|black:100(-15 -100', 'arrondi');
$zinc->gname('white:100|black:100/45', 'cyl');
$zinc->gname('white|black[50 0', 'path');

# $arc = $zinc->add('arc', $top, [50, 50, 200, 100],
# 		  -visible => 0);
#$zinc->itemconfigure($top, -clip => $arc);

$view = $zinc->add('group', $top, -tags => "controls");
# $cv = $zinc->add('curve', $view, [50, 50, 100, 150, 270, 70,
# 				 220, 0, 200, 20, 180, 100,
# 				 140, 40, 70, 100],
# 		 -visible => 1,
# 		 -closed => 1,
# 		 -filled => 1);

$g1 = $zinc->add('group', $view);
$zinc->translate($g1, 100, 300);
$rect = $zinc->add('rectangle', $g1, [-40,-50, 40,50],
		   -filled => 1,
		   -fillcolor => 'path'
		  );
$g2 = $zinc->add('group', $view);
$zinc->translate($g2, 200, 300);
$arc = $zinc->add('arc', $g2, [0,0, 100,100],
		   -filled => 1,
		  -linecolor => 'white',
		   -fillcolor => 'boule',
		  -startangle => 120,
		  -extent => 120,
		  -closed => 1,
		  -pieslice => 1,
#		  -fillcolor => 'tan'
		 );
$arc2 = $zinc->add('arc', $view, [90,0, 160,50],
		   -visible => 0,
		   -linewidth => 0,
		   -filled => 1,
		   -fillcolor => 'brown');
$g3 = $zinc->add('group', $view);
$zinc->translate($g3, 300, 300);
$cv3 = $zinc->add('curve', $g3,
#		  [[-50, -40], [0, 0], [-50, 40], [50, 40], [50, -40]],
		  [-50, -40, 0, 0, -50, 40, 50, 40, 50, -40],
		  -visible => 0,
		  -filled => 1,
		  -fillcolor => "#ffffff:100 0 28|#66848c:100 80|#7192aa:100 100/270"
#		  -fillcolor => 'cyl'
);

# $rect = $zinc->add('rectangle', $view, [200,230, 220,250],
# 		   -visible => 1,
# 		   -linewidth => 2,
# 		   -relief => 'sunken',
# 		   -filled => 1,
# 		   -linecolor => 'white',
# 		   -fillcolor => 'tan');
$cv2 = $zinc->add('curve', $view, [],
		  -visible => 1,
		  -linewidth => 2,
		  -linecolor => 'white',
		  -fillcolor => 'tan',
		  -fillrule => 'positive',
		  -relief => 'sunken',
		  -closed => 1,
		  -filled => 1);
$text = $zinc->add('text', $view,
		   -visible => 1,
		   -text => 'Un Texte ICI°°°°°',
		   -position => [200, 100],
		   -color => '#008000');
$zinc->contour($cv2, 'add', 1, [[20, 20], [20, 100, 'c'], [120, 100], [120, 20]]);
$zinc->contour($cv2, 'add', -1, [40, 40, 80, 40, 80, 80, 40, 80]);
$zinc->contour($cv2, 'add', 1, [60, 50, 60, 60, 70, 60, 70, 50]);
$zinc->contour($cv2, 'add', -1, [90, 70, 150, 70, 150, 150, 90, 150]);
$zinc->contour($cv2, 'add', 1, [200, 200, 200, 220, 220, 220, 220, 200]);
$zinc->contour($cv2, 'add', -1, [100, 10, 180, 10, 180, 60, 100, 60]);

$zinc->contour($cv2, 'add', 1, $arc2);
$zinc->contour($cv2, 'add', 1, $text);

# $rect2 = $zinc->add('rectangle', $view, [40,81, 80,130],
# 		    -visible => 1,
# 		    -linewidth => 1,
# 		    -relief => 'sunken',
# 		    -filled => 1,
# 		    -linecolor => 'white',
# 		    -fillcolor => 'tan');

new Controls($zinc);

$zinc->Tk::bind('<a>', sub {print "hop\n", $zinc->contour($cv2, 'remove', 1);});
$zinc->Tk::bind('<b>', sub {my ($x,$y,$c) = $zinc->coords($cv2, 0, 1);
			    if ($c eq 'c') {
			      $zinc->coords($cv2, 0, 1, [[20, 100]]);
			    }
			    else {
			      $zinc->coords($cv2, 0, 1, [[20, 100, 'c']]);
			    }});
$zinc->Tk::bind('<1>', sub {
		  my $ev = $zinc->XEvent();
		  my $it = $zinc->find('closest', $ev->x, $ev->y);
		  print "Closest: $it\n";
#		  my @t = $zinc->vertexat($it, $ev->x, $ev->y);
#		  print "VertexAt: ", join(', ', @t), "\n";
		  $zinc->bind($cv2, '<1>', sub { print "zou\n";});
		  $zinc->coords($cv2, 0, [[100,0]]);
		  print $zinc->bind($cv2, '<1>'), "\n";
		});

$zinc->focusFollowsMouse();

MainLoop();

Added jni/tkzinc/sandbox/testshape.tcl.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so

set top 1

set r [zinc .r -render 0 -borderwidth 0 -fullreshape 0 -relief sunken]
pack $r -expand t -fill both
$r configure -width 500 -height 500

set arc [.r add arc $top "50 50 200 150" -visible 1 -closed 0 -filled 0 -fillcolor white -extent 200 -pieslice 0]

set cv [.r add curve $top "50 50 100 150 270 70 220 0 200 20 180 -100 140 40 70 -100" \
	-visible  0]

.r rotate $arc [expr 3.14/10] 125 100

.r itemconfigure $top -clip $cv

Added jni/tkzinc/sandbox/testtext.tcl.





















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
lappend auto_path ..

package require Tkzinc
package require Img

set mask "/usr/X11R6/include/X11/bitmaps/fvwm.xbm"

set r [zinc .r -backcolor gray -relief sunken \
	-insertbackground red -insertwidth 10 -render 0]
pack .r -expand t -fill both
.r configure -width 800 -height 500
# .r configure -drawbboxes t
set top [.r add group 1]
.r addtag controls withtag $top

.r add rectangle $top "-50 0 +50 1" -composescale 0
.r add rectangle $top "0 -50 1 +50" -composescale 0

set x 50.0
set y 100.0
.r add text $top -text "Ancrage Sud Ouest" -position "$x $y" -anchor sw \
	-color yellow
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x [expr $x + 200.0]
.r add text $top -text "Ancrage Sud" -position "$x $y" -anchor s -color pink
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x [expr $x + 200.0]
.r add text $top -text "Ancrage Sud Est" -position "$x $y" -anchor se \
	-color violet -overstriked y
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x 50
set y 150
.r add text $top -text "Ancrage Ouest" -position "$x $y" -anchor w -color lightblue
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x [expr $x + 200.0]
.r add text $top -text "Ancrage Central" -position "$x $y" -anchor center -color blue
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x [expr $x + 200.0]
.r add text $top -text "Ancrage Est" -position "$x $y" -anchor e -color darkblue
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x 50.0
set y 200.0
.r add text $top -text "Ancrage Nord Ouest" -position "$x $y" -anchor nw \
	-color violet -underlined y
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x [expr $x + 200.0]
.r add text $top -text "Ancrage Nord" -position "$x $y" -anchor n -color pink
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x [expr $x + 200.0]
.r add text $top -text "Ancrage Nord Est" -position "$x $y" -anchor ne -color yellow
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x 150
set y 300
.r add text $top -text "Ce texte tient sur plusieurs lignes.\nLes alignements :\n- à gauche\n- à droite\n- au centre\nsont également mis en évidence.\n" -position "$x $y" -anchor center
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x 400
set y 300
set anim [.r add text $top -text "Ce texte tient sur plusieurs lignes.\nLes alignements :\n- à gauche\n- à droite\n- au centre\nsont également mis en évidence.\nLe texte central montre l'utilisation\nd'un espacement des lignes programmable." -position "$x $y" -anchor center -alignment center -spacing -5 -font {times 14 bold italic}]
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red

set x 650
set y 300
.r add text $top -text "Ce texte tient sur plusieurs lignes.\nLes alignements :\n- à gauche\n- à droite\n- au centre\nsont également mis en évidence.\n" -position "$x $y" -anchor center -alignment right
.r add rectangle $top [list [expr $x - 3.0] [expr $y - 3.0] \
	[expr $x + 3.0] [expr $y + 3.0]] -filled 1 -fillcolor red


.r addtag text withtype text
.r bind text "<1>" {textB1press %x %y}
.r bind text "<B1-Motion>" {textB1move %x %y}
.r bind text "<Shift-B1-Motion>" {textB1move %x %y}
.r bind text "<Shift-1>" {.r select adjust current @%x,%y}
.r bind text "<KeyPress>" {.r insert [.r focus] insert %A}
.r bind text "<Shift-KeyPress>" {.r insert [.r focus] insert %A}
.r bind text "<Return>" {.r insert [.r focus] insert \n}
.r bind text "<Control-h>" textBs
.r bind text "<BackSpace>" textBs
.r bind text "<Delete>" textBs
.r bind text "<Control-d>" {.r dchars text sel.first sel.last}
.r bind text "<Control-v>" {.r insert [.r focus] insert [selection get]}

proc textB1press {x y} {
    .r cursor current "@$x,$y"
    .r focus current
    focus .r
    .r select from current "@$x,$y"
}

proc textB1move {x y} {
    .r select to current "@$x,$y"
}

proc textBs { } {
    set item [.r focus]
    set i [expr [.r index $item insert] - 1]
    if { $i >= 0 } {
	.r dchars $item $i
    }
}

#
# Add controls to the main group
#
source controls.tcl

#
# Line spacing animation (crude).
#
if {0} {
    set i 0
    while {1} {
	update
	after 200
	.r itemconfigure $anim -spacing [expr ($i % 20) - 5]
	incr i
    }
}

Added jni/tkzinc/sandbox/testwind.tcl.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/local/bin/wish -f

load ../tkzinc3.2.so

set top 1

set r [zinc .r -backcolor gray -relief sunken]
pack .r -expand t -fill both
.r configure -width 800 -height 500

.r addtag controls withtag $top

set ent [entry .r.entry]
set wind [.r add window $top -window $ent -position "100 100"]

set container [frame .r.cont -container t]
set id [winfo id $container]
puts "container id is $id\n"
set cont [.r add window $top -window $container -position "200 200"]

Added jni/tkzinc/sandbox/testzinc.pl.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
#!/usr/bin/perl -w


use Tk;
use Tk::Zinc;
use Tk::Photo;
use Tk::ZincText;
#use ZincText;
use Controls;

$map_path = "/usr/share/toccata/maps";

$mw = MainWindow->new();
$logo = $mw->Photo(-file => "logo.gif");


###################################################
# creation zinc
###################################################
$top = 1;
$scale = 1.0;
$center_x = 0.0;
$center_y = 0.0;
$zinc_width = 800;
$zinc_height = 500;
$delay = 2000;
$rate = 0.3;
%tracks = ();

$zinc = $mw->Zinc(-render => 2, -backcolor => 'gray65', -relief => 'sunken');
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => $zinc_width, -height => $zinc_height);
#$radar = $top;
$radar = $zinc->add('group', $radar, -tags => ['controls', 'radar']);
$zinc->configure(-overlapmanager => $radar);

new ZincText($zinc);
###################################################
# Création fonctions de contrôle à la souris
###################################################
new Controls($zinc);

###################################################
# creation panneau controle
###################################################
$rc = $mw->Frame()->pack();
$rc->Button(-text => 'Up',
	    -command => sub { $center_y -= 30.0;
			      update_transform($zinc); })->grid(-row => 0,
								-column => 2,
								-sticky, 'ew');
$rc->Button(-text => 'Down',
	    -command => sub { $center_y += 30.0;
			      update_transform($zinc); })->grid(-row => 2,
								-column => 2,
								-sticky, 'ew');
$rc->Button(-text => 'Left',
	    -command => sub { $center_x += 30.0;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 1);
$rc->Button(-text => 'Right',
	    -command => sub { $center_x -= 30.0;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 3);
$rc->Button(-text => 'Expand',
	    -command => sub { $scale *= 1.1;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 4);
$rc->Button(-text => 'Shrink',
	    -command => sub { $scale *= 0.9;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 0);
$rc->Button(-text => 'Reset',
	    -command => sub { $scale = 1.0;
			      $center_x = $center_y = 0.0;
			      update_transform($zinc); })->grid(-row => 1,
								-column => 2,
								-sticky, 'ew');
$rc->Button(-text => 'Quit',
	    -command => \&exit)->grid(-row => 3,
				      -column => 2);


###################################################
# Code de reconfiguration lors d'un
# redimensionnement.
###################################################
$zinc->Tk::bind('<Configure>', [\&resize]);

sub resize {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();
    my $width = $ev->w;
    my $height = $ev->h;
    my $bw = $zinc->cget(-borderwidth);
    $zinc_width = $width - 2*$bw;
    $zinc_height = $height - 2*$bw;
    update_transform($zinc);
}

sub update_transform {
    my ($zinc) = @_;

    $zinc->treset($top);
    $zinc->translate($top, -$center_x, -$center_y);
    $zinc->scale($top, $scale, $scale);
    $zinc->scale($top, 1, -1);
    $zinc->translate($top, $zinc_width/2, $zinc_height/2);
}


###################################################
# Creation de pistes.
###################################################
sub create_tracks {
    my $i = 20;
    my $j;
    my $track;
    my $x;
    my $y;
    my $w = $zinc_width / $scale;
    my $h = $zinc_height / $scale;
    my $d;
    my $item;
    
    for ( ; $i > 0; $i--) {
	$track = {};
	$track->{'item'} = $item = $zinc->add('track', $radar, 6);
	$tracks{$item} = $track;
	$track->{'x'} = rand($w) - $w/2 + $center_x;
	$track->{'y'} = rand($h) - $h/2 + $center_y;
	$d = (rand() > 0.5) ? 1 : -1;
	$track->{'vx'} =  (8.0 + rand(10.0)) * $d;
#	$track->{'vx'} = 10;
	$d = (rand() > 0.5) ? 1 : -1;
	$track->{'vy'} =  (8.0 + rand(10.0)) * $d;
#	$track->{'vy'} =  -10;
	$zinc->itemconfigure($item,
			     -lastasfirst => 1,
			     -symbolcolor => 'red',
			     -position => [$track->{'x'}, $track->{'y'}],
			     -speedvector => [$track->{'vx'}, $track->{'vy'}],
			     -speedvectorsensitive => 1,
			     -speedvectorwidth => 2,
			     -speedvectormark => 1,
			     -speedvectorticks => 1,
			     -labeldistance => 30,
			     -markersize => 20,
			     -historycolor => 'gray30',
			     -filledhistory => 0,
			     -circlehistory => 1,
			     -labelformat => "x71x50+0+0 a0a0^0^0 a0a0^0>1 a0a0>2>1 a0a0>3>1 a0a0^0>2"
			    );
	$zinc->itemconfigure($item, 0,
			     -filled => 0,
			     -backcolor => 'gray60',
#			     -border => "contour",
			     -sensitive => 1
			     );
	$zinc->itemconfigure($item, 1,
			     -filled => 1,
			     -backcolor => 'gray55',
			     -text => "AFR001");
	$zinc->itemconfigure($item, 2,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "360");
	$zinc->itemconfigure($item, 3,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "/");
	$zinc->itemconfigure($item, 4,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "410");
	$zinc->itemconfigure($item, 5,
			     -filled => 0,
			     -backcolor => 'gray65',
			     -text => "Balise");
	my $b_on = sub { #print_current($zinc);
			 $zinc->itemconfigure('current', $zinc->currentpart(),
					      -border => 'contour')};
	my $b_off = sub { #print_current($zinc);
			  $zinc->itemconfigure('current', $zinc->currentpart(),
					       -border => 'noborder')};
	my $tog_b = sub { my $current = $zinc->find('withtag', 'current');
			  my $curpart = $zinc->currentpart();
			  if ($curpart =~ '[0-9]+') {
			      my $on_off = $zinc->itemcget($current, $curpart, -sensitive);
			      $zinc->itemconfigure($current, $curpart,
						   -sensitive => !$on_off);
			  }
		      };
	for ($j = 0; $j < 6; $j++) {
	    $zinc->bind($item.":$j", '<Enter>', $b_on);
            $zinc->bind($item.":$j", '<Leave>', $b_off);
            $zinc->bind($item, '<1>', $tog_b);
            $zinc->bind($item, '<Shift-1>', sub {});
        }
	$zinc->bind($item, '<Enter>',
		    sub { #print_current($zinc);
			 $zinc->itemconfigure('current',
					      -historycolor => 'red',
					      -symbolcolor => 'red',
					      -markercolor => 'red',
					      -leaderwidth => 2,
					      -leadercolor => 'red',
					      -speedvectorwidth => 2,
					      -speedvectorcolor => 'red')});
        $zinc->bind($item, '<Leave>',
                    sub { #print_current($zinc);
			 $zinc->itemconfigure('current',
					      -historycolor => 'black',
					      -symbolcolor => 'black',
					      -markercolor => 'black',
					      -leaderwidth => 1,
					      -leadercolor => 'black',
					      -speedvectorwidth => 1,
					      -speedvectorcolor => 'black')});
        $zinc->bind($item.':position', '<1>', [\&create_route]);
        $zinc->bind($item.':position', '<Shift-1>', sub { });
        $track->{'route'} = 0;
    }
}

create_tracks();

sub print_current {
    my ($zinc) = @_;
    my $current;

    $current = $zinc->find('withtag', 'current');
    print join(' ', $current), "\n";
#    print ref($zinc->itemcget($current, -position)) ? 'ref' : 'pas ref', "\n";
#    print 'tout ';
#    for $attr ($zinc->itemconfigure($current)) {
#	print (join(',', @$attr));
#    }
#    print "\n\n";
#    print '-position ', join(',', $zinc->itemconfigure($current, -position)), "\n\n";
}

###################################################
# creation way point
###################################################
sub create_route {
    my ($zinc) = @_;
    my $wp;
    my $connected;
    my $x;
    my $y;
    my $i = 4;
    my $track = $tracks{$zinc->find('withtag', 'current')};
    
    if ($track->{'route'} == 0) {
	$x = $track->{'x'} + 8.0 * $track->{'vx'};
	$y = $track->{'y'} + 8.0 * $track->{'vy'};
	$connected = $track->{'item'};
	for ( ; $i > 0; $i--) {
	    $wp = $zinc->add('waypoint', 'radar', 2,
			     -position => [$x, $y],
			     -connecteditem => $connected,
			     -connectioncolor => 'green',
			     -symbolcolor => 'green',
			     -labelformat => 'x20x18+0+0');
	    $zinc->lower($wp, $connected);
	    $zinc->bind($wp.':0', '<Enter>',
			sub {$zinc->itemconfigure('current', 0, -border => 'contour')});
	    $zinc->bind($wp.':position', '<Enter>',
			sub {$zinc->itemconfigure('current', -symbolcolor => 'red')});
	    $zinc->bind($wp.':leader', '<Enter>',
			sub {$zinc->itemconfigure('current', -leadercolor => 'red')});
	    $zinc->bind($wp.':connection', '<Enter>',
			sub {$zinc->itemconfigure('current', -connectioncolor => 'red')});
	    $zinc->bind($wp.':0', '<Leave>',
			sub {$zinc->itemconfigure('current', 0, -border => '')});
	    $zinc->bind($wp.':position', '<Leave>',
			sub {$zinc->itemconfigure('current', -symbolcolor => 'green')});
	    $zinc->bind($wp.':leader', '<Leave>',
			sub {$zinc->itemconfigure('current', -leadercolor => 'black')});
	    $zinc->bind($wp.':connection', '<Leave>',
			sub {$zinc->itemconfigure('current', -connectioncolor => 'green')});
	    $zinc->itemconfigure($wp, 0,
				 -text => "$i",
				 -filled => 1,
                                 -backcolor => 'gray55');
	    $zinc->bind($wp.':position', '<1>', [\&del_way_point]);
	    $x += (2.0 + rand(8.0)) * $track->{'vx'};
	    $y += (2.0 + rand(8.0)) * $track->{'vy'};
	    $connected = $wp;
	}
	$track->{'route'} = $wp;
    }
    else {
	$wp = $track->{'route'};
	while ($wp != $track->{'item'}) {
	    $track->{'route'} = $zinc->itemcget($wp, -connecteditem);
	    $zinc->bind($wp.':position', '<1>', '');
	    $zinc->bind($wp.':position', '<Enter>', '');
	    $zinc->bind($wp.':position', '<Leave>', '');
	    $zinc->bind($wp.':leader', '<Enter>', '');
            $zinc->bind($wp.':leader', '<Leave>', '');
            $zinc->bind($wp.':connection', '<Enter>', '');
            $zinc->bind($wp.':connection', '<Leave>', '');
            $zinc->bind($wp.':0', '<Enter>', '');
            $zinc->bind($wp.':0', '<Leave>', '');
            $zinc->remove($wp);
	    $wp = $track->{'route'};
	}
	$track->{'route'} = 0;
    }
}

###################################################
# suppression waypoint intermediaire
###################################################
sub find_track {
    my ($zinc, $wp) = @_;
    my $connected = $wp;
    
    while ($zinc->type($connected) ne 'track') {
	$connected = $zinc->itemcget($connected, -connecteditem);
    }
    return $connected;
}

sub del_way_point {
    my ($zinc) = @_;
    my $wp = $zinc->find('withtag', 'current');
    my $track = $tracks{find_track($zinc, $wp)};
    my $next = $zinc->itemcget($wp, -connecteditem);
    my $prev;
    my $prevnext;

    $prev = $track->{'route'};
    if ($prev != $wp) {
	$prevnext = $zinc->itemcget($prev, -connecteditem);
	while ($prevnext != $wp) {
	    $prev = $prevnext;
	    $prevnext = $zinc->itemcget($prev, -connecteditem);
	}
    }
    $zinc->itemconfigure($prev, -connecteditem => $next);
    $zinc->bind($wp.':position', '<1>', '');
    $zinc->remove($wp);
    if ($wp == $track->{'route'}) {
	if ($next == $track->{'item'}) {
	    $track->{'route'} = 0;
	}
	else {
	    $track->{'route'} = $next;
	}
    }
}

sub stick_wp {
    my ($zinc) = @_;
    my $ev = $zinc->XEvent();

    if ($just_wiped) {
	$just_wiped = 0;
	return;
    }
    my ($x, $y) = $zinc->transform('radar', [$ev->x, $ev->y]);
    my $wp = $zinc->add('waypoint', 'radar', 2,
			-position => [$x, $y],
			-connectioncolor => 'red',
			-symbolcolor => 'red',
			-labelformat => 'a2a2+0+0',
			-tags => ['text']);
    $zinc->itemconfigure($wp, 0,
			 -text => "$x".'@'."$y",
			 -color => 'red',
			 -filled => 1,
			 -backcolor => 'gray55');
    $zinc->bind($wp.':position', '<1>', [\&wipe_wp]);
}

sub wipe_wp {
    my ($zinc) = @_;
    $zinc->remove('current');
    $just_wiped = 1;
}

$zinc->Tk::bind('<2>', [\&stick_wp]);


###################################################
# creation macro
###################################################
#$macro = $zinc->add("tabular", $radar, 10,
#    -labelformat => "x40x20+0+0 x40x20+40+0"
#    );
#$zinc->itemconfigure($macro, 0 , -text => "une");
#$zinc->itemconfigure($macro, 1, -text => "macro");
#$zinc->itemconfigure($macro, -connecteditem => $track);
#$zinc->bind($macro.":0", "<Enter>", [ \&borders, "on"]);
#$zinc->bind($macro.":0", "<Leave>", [ \&borders, "off"]);

###################################################
# creation ministrip
###################################################
$ministrip = $zinc->add("tabular", $radar, 10,
    -labelformat => "x80x20+0+0",
    -position => [100, 10]);
$zinc->itemconfigure($ministrip, 0 , -text => 'ministrip');
$zinc->bind($ministrip.':0', '<Enter>',
	    sub {$zinc->itemconfigure('current', 0, -border => 'contour')});
$zinc->bind($ministrip.':0', '<Leave>',
    sub {$zinc->itemconfigure('current', 0, -border => '')});

###################################################
# creation map
###################################################
$mw->videomap("load", "$map_path/videomap_paris-w_90_2", 0, "paris-w");
$mw->videomap("load", "$map_path/videomap_orly", 17, "orly");
$mw->videomap("load", "$map_path/hegias_parouest_TE.vid", 0, "paris-ouest");

$map = $zinc->add("map", $radar,
		  -color => 'gray80');
$zinc->itemconfigure($map,
		     -mapinfo => 'orly');

$map2 = $zinc->add("map", $radar,
		   -color => 'gray60',
		   -filled => 1,
		   -priority => 0,
		   -fillpattern => AlphaStipple6);
$zinc->itemconfigure($map2,
		     -mapinfo => 'paris-ouest');

$map3 = $zinc->add("map", $radar,
		   -color => 'gray50');
$zinc->itemconfigure($map3,
		     -mapinfo => "paris-w");


###################################################
# Map info
###################################################
#$mw->mapinfo('mpessai', 'create');
#$mw->mapinfo('mpessai', 'add', 'text', 'normal', 'simple', 0, 200, "Et voilà");
#$mw->mapinfo('mpessai', 'add', 'line', 'simple', 0,  0, 0, 0, 200);
#$mw->mapinfo('mpessai', 'add', 'line', 'simple', 5, -100, 100, 0, 0);
#$zinc->itemconfigure($map3, -mapinfo => 'mpessai');

#$c1= $zinc->add('curve', $radar, [],
#		-filled => 1,
#		-linewidth => 1,
#		-fillcolor => 'blue');
#$zinc->coords($c1, [200, 200, 300, 200, 300, 300, 200, 300]);
#$zinc->bind($c1, '<1>', sub {$zinc->coords($c1, 'remove', 0);});
#$zinc->bind($c1, '<2>', sub {$zinc->coords($c1, 'add', 0, [0, 0]);});
#$zinc->bind($c1, '<3>', sub {$zinc->coords($c1, []);});
#my $c = $zinc->add('curve', $radar, [],
#		   -filled => 1,
#		   -fillcolor => 'red');
#$zinc->contour($c, 'union', [100, 0, 0, 0, 0, 100, 100, 100]);
#$zinc->contour($c, 'diff', [75, 75, 25, 75, 25, 25, 75, 25]);
#print join(' ', $zinc->coords($c, 0)), "\n";
#print join(' ', $zinc->coords($c, 1)), "\n";


###################################################
# Rafraichissement des pistes
###################################################
$zinc->repeat($delay, [\&refresh, $zinc]);

sub refresh {
    my ($zinc) = @_;
    my $t;

    foreach $t (values(%tracks)) {
	$t->{'x'} += $t->{'vx'} * $rate;
	$t->{'y'} += $t->{'vy'} * $rate;
	$zinc->itemconfigure($t->{'item'},
			     -position => [$t->{'x'}, $t->{'y'}]);
    }
}

sub borders {
    my($widget, $onoff) = @_;
    $onoff = "on" unless $onoff;
    my $part = $zinc->currentpart;
    my $contour = "noborder";
    $contour = "contour" if ($onoff eq 'on');
    $zinc->itemconfigure('current', $part, -border => $contour) if ($part >= 0);
}

sub finditems {
    my($cornerx, $cornery) = @_;

    print "--- enclosed --->",
    join('|', $zinc->find('enclosed',$origx, $origy, $cornerx, $cornery)),"\n";
    print "--- overlapping --->",
    join('|',$zinc->find('overlapping',$origx, $origy, $cornerx, $cornery)),"\n\n";
}


MainLoop();


1;

Added jni/tkzinc/sandbox/textexpand.tcl.













>
>
>
>
>
>
1
2
3
4
5
6
zinc .z
pack .z

proc createItem {type params} {
    if 1 [concat .z add $type 1 $params]
}

Added jni/tkzinc/sandbox/texture-bois1.xpm.

































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/* XPM */
static char *on[] = {
/* width height num_colors chars_per_pixel */
"   256   256       57            1",
/* colors */
". c #f8dca8",
"# c #f8d4a8",
"a c #f8d4a0",
"b c #f8d498",
"c c #f8cca8",
"d c #f8cca0",
"e c #f8cc98",
"f c #f8cc90",
"g c #f8c4a0",
"h c #f8c498",
"i c #f8c490",
"j c #f8c488",
"k c #f8bc98",
"l c #f8bc90",
"m c #f8bc88",
"n c #f8bc80",
"o c #f8b490",
"p c #f8b488",
"q c #f8b480",
"r c #f8b478",
"s c #f8ac88",
"t c #f8ac80",
"u c #f8ac78",
"v c #f8ac70",
"w c #f8a478",
"x c #f8a470",
"y c #f8b488",
"z c #f8b480",
"A c #f8b478",
"B c #f8ac88",
"C c #f8ac80",
"D c #f8ac78",
"E c #f8ac70",
"F c #f8ac68",
"G c #f8a480",
"H c #f8a478",
"I c #f8a470",
"J c #f8a468",
"K c #f8ac80",
"L c #f8ac78",
"M c #f8ac70",
"N c #f8a478",
"O c #f8a470",
"P c #f8a468",
"Q c #f89c70",
"R c #f89c68",
"S c #f8ac78",
"T c #f8a478",
"U c #f8a470",
"V c #f8a468",
"W c #f89c70",
"X c #f89c68",
"Y c #f0a470",
"Z c #f0a468",
"0 c #f09c68",
"1 c #f09068",
"2 c #e09068",
/* pixels */
"hhehliieid#hqDqliifiiiiiihllhhkllyykhkhdhlpplhggeeehhilmmmllmpppqDDzqmihhhhhhilmODpmqDphhhihhmpqklllpCqlgllllppkhlqDqlhilqtqlhlqplkhltzplmpppmpmqmmmqmmmmquummqqnqqmquEuumlqtppplmqqqpmmpOqmOthuqqqpmmmmqmmmmmiieeefeeefiiimnqnmnqqEIuqquqihhlmlmmmmmmqqlilihilm",
"illmmmllhhilmmpmiimmqqqpllmppppClopplpppklpplkhhlliiillmopptqCCCmmpmmliiliiihilmlllltLDqqtqplmpmqtohhlollpplopplpmlmlllplmpmmpmqCpllpppmpppmllllmlihiihhhiiiheeiiijmmquuutpqlhghmllilllliqlhmldmqpqmqqqqmmmljmiiifeiiiimebaeeeeeiiimqqmmmmlhlmpmlllllllilililill",
"llmmlmlllpqqplmmmmmnqmmmlllpppyCCtzLNNKUCCKKLCCCDqqqtDqtqzDLCtzCDDAtztDDDDtqqqqqqqCqzCCqCDCqqpqpzCCqpCqpCCtqqppqqpppqqqppmpqtCCCNppCDpptqtqqppmqmmlilllimihhhhhheehimmmqllmppllptqlllmpqmqllpmlpiilmmmmmeeddeeeeieeeeeijiiiifiiilimqqqqqpqpmmpmmlmmmmqqqlmmpmmmm",
"mqttqppqDqqCDuqpqrruqqmmCCDLNLNTUNKLNLNKCCKNUUUTDDDDLLCzqCCCzpppqqpmpqqpqqzqqmpqppqpqqzCppqqpppplpqCCDCCqmpCqpqCtqqqCqpmqppqCDDzCppCCztLCzttqqpqmmmmqqqqpmmmmmmilhlmmllqqmmqpmlmililmppmplmmlmpmmmmmqqmiliiiimmmjiiiiiijiiiiiijjmlmnqqqtmmpmllhhlmmpqpmmmmppmmlm",
"DHMMDqDDDqqDDLCnEEIEDDDDIMNUUNNTLNLsyCClolppCCypmmmpqqpmlmmllmppliililiilmqqqmmmmlihkhlimmppllhilhggilpllklpplltmmllllmmllmmpmppppmmpqqtpqqmmlihllmqqmqnmmpmpmpmqpqutmmquqqqqqmllllpqqmmpmqtpqqpppmqqmlhiiehiiiimjjmjiijimnnnmmmmmqtuqqqquuqpqqqqqtqqqpmtqtqqtuu",
"DDLDtqqqmppqqqqquDEDrqqqpppCCzqCpCClmCCpmompyBplmmmmmmmllllllllpmllmmpmmlmmppmmmCplihhdglllmlhhhhhhhppmlhhhlkhhlhlllhiklhhlkillmpppllmpmilppmmmmmqqqqqqqqquuuquuqDOODuuDqqqqDEDruDuDtuuttqtDtuDqEOOOVPDqqqqqqqrqrurvvuuvuuvuvvuuuuvJIuuuDOOuqqtqqqqtqqqqquqqqqDD",
"pqqpmllmlmmmmlmpmqqqmliimmqCCCCCpCzppzCCtqtzCtztpqqqqppqppllppplmlilmmmmlllliililllmpmpqhilmlihlhllqDCplhhliihlllmmmilihhhhihlmpppllmllllmnqqqtutquuqqquqtquququpCNDqqqCrqqqrrrqqqtqpmpqmpmmmmlmlmqtqqmmmmmmnqqqjiimmjjmqnqqqqqnqqquqqqqpqqpmllhihiilllmhihhhimm",
"qqqqpmmmplillmmlmmquqqqqppqzCtqCzppqpppCllllppqCmqqqmmmpmlmpDNKtmliilmmlDrqmmlmpllmpmlillllplhhihhllllihimllhlmpDtmhdgiliihhillmpihmpihipmppmmmmmmmllimmmliiiililqDqmlpmimmmmmnnlpqqplllllihllhlmqtruqqmpnmqqqrqrqqqqnqqmiiimnmmqqqqqmmpmpqqqqqmppmmlillillmlmpq",
"mmpmllmpliillmmlmpqpqqqpmlmpqqtqpqCppmllllpppDKCmqCDzqlhlmppqqCzpmppmmllipqCqpmqptqppllpplillllmkihhhhllmptqplllmihlmqqDpmiilmqqlililmlilmmjlmmqmpmmmmmmmmlillmmtptqqpmmmmmmnnnmmpqqqqqqppplllmpqpmpnpmmmmleimmimjmjmmiiijmjmnqmmmmpmpqqtqppqtqpmmlpmlmqqmmlmpqp",
"pqqqmpqqppmmmlllqDqqmppmmmpqtDCDmomlllkillllmppmtqmlllmlllllpppsqqqtqqpmpmqqqppqmqpmmlilmppllppllllhilillpppllhlppquDDDDDplhhilmpmlhhhilimqqqmmlmmmmmlllpmmmmpqqpllllllmpmiimmqqllmpqpqpllmmppppqqqqqqmmmpmehmmmiiiiiiiimmmlmqnmmmmmmmmmppmllllltquqqmpqmmmqquDu",
"mpmppmppqqtqppmpmmlhhillhlmmqpqqtqqqppppqtqpqztpmmqDDqplDCtCpqypqqqqqqpqzqqqzqqqCDqptpmmpDDpmqpiqmmmllmppmmmmlmlmilqqpmmiihehlmmqqmmmmnqqqnnnmnqtqutuqqqqqqqqqqqtqtttqqtqqpmmmmntqttqtqqqqqtqqqqqqpmmmliqqnlimnmmiliiiljqmmjmnmmpqqqpmlmllmppqqtmpmpmpmmqqpmpmli",
"pmpqqqqpmmpqmmmmCzqqqqtDtuDDCuDDDCCtCzDzCCDCCDDtLDqzDDLMNOLLLCCCLDLDDDDDDzqzDDDDLLCtLDqqpCCqpqqpDtqpmmqqqqmppqqmqqmqqnppDDuDuqqqpmqqqqqnqnmmmmqumqnqqqqnpmpmpmpmllmmqpmlmmmmmpmmmpmmpmllmppmpmllmlmmmmqpmnpiiilimmjiilmmqnmimmmimmmmllllmmppmlllipqmquuqlmmmqqqq",
"tqtDDLDtMHMOUXOOOOMLLDDDDMHDuDOOpqpqqtqpmqpmpppmDqqqqqptmmptCCCzqqqqzzDDzqmqCzqpqtmpCzppmmmpqqCDzqmmmpmmqppqqqqmtqtDqqqqpmmmllilnpnqqqmimmqqnqnnmmlmmpnpqqnqmqmqqqqqqqpmhhhlpqttolmopqtqtpqppqttqtqqquuEquuuqqqqmmmmmmmqrqmmmmmmhilmlilippptuwtpqrtqqDDquutuDDOO",
"qqmqqtqqmllmpqmmlmpzqmmlllmilmpqqqqzCCqplmplllllmmpzqlhdkllllllkhhhhilmmmlilmmiimplhmpllphhllhhlmliillllmmmlmmmmllmqpmilqmlllmqtliimmmmjmnnnmmmmmpnqqqtrqtqtuuuupmmllpqppppqtuwIIHuuHIIHIIHuuuuHDuuqqrDIvEIFJIJJuvuuuruuxvuvvuqqmqquuuuwqqtIOXOEDIMDOOOODDDqqqqq",
"liliililhihiilllilmqqmllihhillmmtqpqttqplmpmlmppDmiihhhmmpllhhggiihilmqtlhhhihhhmlihlihllhhhhddchedhimmlmllillmliimmmiheqmjhedeeiimmjiimmmiiffijliihiimpmmpmqqquvuuruvxuIxuttwttutqpqpqpttqppmpmqnpmmmmmmmmmqnmnquvvurqruuvxxrqruuvuxuIIwutqqllhhehlmliihiiiilmm",
"ihihhhhihhlililmppqCCmiilillmmlllkhhhlhhhllllppqmihlmilmCqlhhhghhehhimqqmihhhhilpmlhhhhheddhlpleedeimqqqmmliiimmiiiiedeheiliihehimqqidaaaeeiieeeihhdehiiddddeimmmnqquvtptqtttpoohhdgllmlihllllklhhiihehhmihehiiiiimmiieemmqrqmimqqqmllllmpplllllmlmqqlhelmmliheh",
"qqqtDuqqpmqqqtMUqqmqqqqtDuDMIDuDODqtqmptDqqtDqqqpqCDDpmppDOOCmlllllqpklppmlhhhgddhhipidlllhimle#ddddghd#hdddddgheheemjeimiimieeeehiimmiiiiieeimmiieeeiedeeeeeeehiiinqnmiimmqmliimqqrqmmqihimmmiillllqmmqmmmmmheedeiiiililmmmiilljnnqnjjnmnnmmlnqtqplimmlqmmppmmm",
"qqqqmlmmqmqqlhmpqqmpqmpnlllmlliihhhmpqpmLCqCzqpqlllmmmptmpqpmpqDpmpDDqpqpppqmpmpmzqmppmlmmmmmmlhllllllhhhihhhdddiieimieeadeimilihehilqquqmmihiimmmiilmmimifeeheeeefjmnmnmqpnpnpqmmqqqmmpuqtuuqqqmpmqDqpqqqqqqmmmmppqqtutqppmllilnmmnmnnrqqqrqruuqqrqquEIqqqqqqpq",
"qDDDpllpmmqqilquqpmlllllqmlmmllmlllpCLqllllmplpqDphlptqplllihllmmllqCqmhilmmmlllqCLqmDLpqqtppmpqtqqqpqqtppqqpmllmmlmpmhhhilptqpmDuqqmqqqOJEuuruuqruuruuuqqmmmmmmmmpmmmpquuqtqtuuutqtuuqqqqttqppqmpqtDqmmpmmqqmmmpmmmpqqqqqqquqtqvrqrruvEuuruuqqqqDuqmllmuqmmmmqq",
"imtqmlilhhlmllqqCqpmmmmpqmllmmmmtqplpqmhllllmmpptpmlllihqpmppmpmpllqCqlhlllmppmledhhdlphdhhhdddhilhhhlpDqtDCztDLqqpmuqlmqppqqqikiillliilmmliihiiimmjlimjrqqqqrrururqqqnqqqqttuqpqpmmppllllmqpmmplqqqDqllihlmmmmmqpmilmpmqqpqquuqqmjmmmqqrqqqqqmilmmmlillqqpmpmqu",
"CDNONDDCUNNHCDLCLDCqCCDDLCzCDKLNOULCDUUDNDqtCDCqmqDCplmpmlhdhhlpppqqpmllqmllqqqpphmplmqmllmpmlllhhlllhlphhhdddipllilqmlllihlllhgilmmmlmlihiihfhilmmmiiilimqqqmpqmpmmmqpmpmmpqppppllpmlllpmppttqtqCtyCtmplllmpmppmmmhhilmmmlmmmmlqnqqqqqqlmqtqqtqpppqtDHtmptOHDtq",
"CtpppCtqCppmptCpLKCzCLLLCmlppqpppppqqDCqCqpmCOLCONLDDDCtDDCDCDDCmqtqpmppCpllmpllldhlllmplllmpmihlmqDqlhlqqmlhhlpllhlplillkhhlhkliliihehhiiliieieieilihhiimmqmmmmmmmlpqqlqpmmpttDtttCttDIDtpqtuDHCLCqCCqqqppqqpmpmmplilmmpmmmppmmimmqmmmqpqtuttuuCuttDDqpqtqCCtDO",
"CppqCCCCllllpKONzCzpyCKCKypzKCypLqptKDqpllhhmzCpODpmqCqipqCDDqmlqCDDCtqDODtqqppppqmlqtttpqttttppllpqpihhmllhhhhhpplkppkopmopopopmmmpquDDqqqnpmmmqqqruqqtqqqnqnqqpqqmmtqpqtttqtCHqppqtptCtppppsqttCCpCCppqpppppmpquuqqruuqqqqqquutqquHDtuDCttqtppllllppplCqpmlmCN",
"lpsCLCCslkkkkpCCyCCyzKCypplpyplhOpilqqpmpmlllpmllCUDpmpCllllihhlhlmpmmpmpqCqpqDDDXtlpCqqmptqpmlltpmqqmpDppppqqppLCplpplppoppppptDCtquqqntrtqqqqqnmmqqqnqvqqqtuuqpqtqpuDuptCttppptpppollpklpttppplCppptppppmppompuqqqqqqmqqqqpmmmqppqtqpmttmppqpplppolllllpptpppp",
"DCKNNUULNDDNNNCzNYULNYUKCKKCKLKCLLDNUOzzppqqqpqqCzqpmppphllhhhllhhipplllqNqhlmlllmlpqtqphlmpqpmlhhhhltCzqzqtzqpmCCptppptppptsttpppqpmpqtmmmpqqqqimplilmmqpmqqqmiipqmmqqqmptqppptpllpmllmlppppCDtptCCCCCDpllmpmllmmmquuqliqnpmlmummqtqpqCqqpptpkllqCqptCpNHLNLNOU",
"CqCLCCCsppompCLNKNSKLTTKUUTSUYYTLNDOYUNOCDLDLLOUOOLNNLOOzCCqtCqpqppqqpppmqmhlhdhlllhhlhghhllllhhllllhlllCtzqqpmlpmolplolspstpptompnppmqqqpmmmllilmmmilmmiihilmlhimmmpqtpmpppppppmpptCCCHtDNDDONDYWNCCLNONtpppppplilimliiilmilehnlilqqmmqlCDpCNNHNUNCCCOOCCCtCtpq",
"olpsmpplCpolmpCLpppppqpmppllpDzpqqppDCqCzCCppmpCCqqztqqCpqpqzCqmOODLDDDLDNCDDtqDtqqppqqmtqCqtqqpqzqplillllllpmpmppppppppplpppppoDCDDztCDqqqqqqpmmpqpmmlmppmpqqqpmmmmpDqqqqqDOUOLNOOLDtplpqCqpqqmlllpptqqqmllllpqqtqqqqqtuDuuuutDDtDELDtDCWVCqCqpLtmlhhhlllmmpmll",
"ppCLtCCtppppopppOLCDKzzLLCCCLTNCqzqzDzpqCqqpppqzCppDCmlqmpqCDONCqppppmppqpllllmtqztqqCtqpqqCCCCDqCDzqqpmqqqCDDDCCCCCCCzpLCCNCGHCqqqpqpqqqqqqqurqtutqqttuqquuuqpqntDruDLDDqqqzqpmillllllhmqqqptqppppqCCpkmpqqtqquqmqqqqqqqqmmqmmqDqpqCqqqlmlmlhglihlqzqDOCDCDDDCq",
"ihmmihlilmmmpmpqpmlpmllpmqqpmqqqptqCLCpqpmmpCDNDDqqNDppCpqDCDLLOCCzCDDDDLNDmlqCpppqmlmllhlmqqqqzppppqCzqCCCqCzqqpppppmppllllllmlpppmpmpmpmmpqmppmmlllmpqmpmllilimnqqmmnqqqmmpqqqpqtqqMODqtztqDCqCqmmpmmmhmmpmiihiiiimmliiihimlimmiiimmpnqCtDONtLDDDDCmlmmmmmllil",
"DtCtpmplmmmmmqqqmmmqpmmqmqqqpppqilmpqpimlllmpppmpmpqqmpqmpqmlllllmmppqCqqqCphpqhmpqppmpmlmpzzpqplmlmpqtmpmmpmpompmpmppppzpptptCppqqqqqqqqqqmqqpmlihiiimppmlhhimpinqniiimmmqqqDLOqqnmllmlmpmmmmmmlhllmppmqqtnpmpmmmmpqnmlnpmmqqmqrpjlmnpqpDCmpqmhihilmmqqmmmmmqqq",
"qmnqmmqmqqpppmpmlllmliillmppmmmlmppqCplpmppppmmmlpqqpppqpqpmllllppqpqCDCpmqplqCmhlmmmmmlilpppmmmmmpmmpppmpppqqCCmqppmppqplmplmpmlhlllmllmmmmpmqpqpmpqppqqpmllpqunqrrqnqrqqqqmmmjqmmmmmmqqnmmmmmmqDDMDqqmmmmiiimimmmmmlmlhieimmhiqnmjimiihqqlmqqpDrqqmqqqhhiimmmn",
"lhlmmqDqmllmnpmlquuqmmmlilmmqqpmppmmmlhmkmqqmptDlpplllmmllllpqplmqqmpqCqOppqllqqmmzppllilmmqmmmpmpppllmmlmllmlmmmmllmlmmmllmllmlllllppmllhihihhehdhiihehihhiilllffijifiifiimmmmlqmqqqmmnmmliilmmilillmqqqqqmiiieehiheeijlmlmqmiliiiimmmmlmlilhiqimmiimjhmmmqmmml",
"qmlilmptlpCtpollkllloohkloplkklpqmmqqmmmmmmmlmqzlmqDVtlimmmtEDqmmppqqqqCqpmpqqpplmqzDqmlhlpppoopppmllpolkkllkllplliillmllmllillmlillmmpmmqqmiiiimiiiliiinnmmnqqrilmmmmmnuqnmmmmimiijmmlillmpppppllplilmqutmmmmiilimillmmlihllmlimmmmmquummmllhilillillllnppllllm",
"qtppptDCCLOLtCCCDNCpCCCCCCCDCDNNMEOOPMDEnqqqnpmmqCqmqnpDDtpmpmmlqqCCtCCDzqpmmpqCmmmpmpmpllppppopzqmllllklllllllmlllilmmmmpqqqmihiiilmmmmqqqmmmiiifhijmjmlmiiiiiiimmnmmmmqqqmmmmmmmmmjmlimmppmlllmpqllilmqqqmqqmiiiiiiihillmlllllmqnmimmmmllillllllilmqqmpmpmpqqu",
"NMDDLDLDLOUNLCDNCDCtDCtCCtCCNNNLDDDMLDDDDDDDODqqtDDDDtqNMDtqqtCttCDDCDLNDDDtpqDLtqqqqqsqpqCLCCCCzLCzpCypklkhhhiliihhilllmmmmmlmmllpmmmmmmmmllmmiiiiiiiiimmmmmmmmmimmmmmlnmmmmmmmjjmmmmpqqtqttttpqtutqqqpnqquvurqqqqqqqqmmmpppmppruqmmlllqmlllllimmmmpzqqDEDDuDHO",
"nppqqqpppCDCtpplppppCtmppppptqqpqqqtqqqqCqnppqqpmqDDLzpqpqDDDMMDDLLNLLOVqCCCCtztACqCqzqpCCCLCKLLLLLDKLLKCCCtqqqqppmmmpmpmmllllmplmmpmpmpqmmmmmihmmijmlimmjmmmmmmiiimqqmmmmmmqqnqnqqqnquEutuuutttpqutqqqqqqmmqqrqrrqrquuuqtutqttuqqrqqqnpmmmpquDDDDtqDMICqCtqpmpq",
"pmqnqqtztLONLNCCtDCDOLCCCDLDCCCtLLNLDCDLqtpmllpqpqplttpplpqsqCplmpqqpqCCpmmpqqplqmlmqqmimmppppppqzzzyCKCCCCCCzqpmmmmpmmmqqquqmlihlmmpqquvuqqqqmimmmqqquvqqqmmmmmmmmqqqqnqqqruuurDEIEqqqutuqtqqplmpqmpmqpmmilimmmmmmmmmnqqqmppqqpnqqrtrtutuDutuDODzqpzDCmpmppqqqu",
"OODDDDDCMOTLHNONLLCpCDCDNNNONLNNMOOLDLNOOUOODCzDLNCtLNLHDNCzsCCpmppqppqqDpmlqqqpqmlimpmmlpppppppqzzppppollpmppliiilimmmmqqqqqmmmmmpqqqqqqqqruurqqqqqqqruvvurqruurtrruruquuuuuuruuEEuqmqrtqpqttqptuutqqpmmqqmnmnmqqqmmmqqqpmmpqppuuuDuqqqtDDupmqtqqmmqqqpquDDuDHO",
"DqqqqmmlpqppmpppqtpmqpqCCDCCDDDDpCCCCCCCCDLCCqppCNNLUUNLNNCCCNOCDLOOEDDDDqppqCtqzqqqqqCqpqqACzqqzDLzppzyCptpqqqmppmqqtqqmmmmmmqqqqqpqmmmmimqruqrrqqnmmmnqnnpnqqqurtrqqquqrqqrrqnqqqqqqtuqtqtuDuuuwDutqqmmmqqqqqqrruuqqquuuttuuuuEEEuqqmqlmpqqqDILLDDDNDDtqqppmpm",
"lmmpqqttmpqqtCtpqzqpCCqzDqmpzCzplpCDCCDCCtpppqpplCpopppCppplpCClpqqqplilllmmmmllmpzDzqqqmmqCqqppzLLzzCCCCCppqqmpmmmmmmmmlmqqpmmmlliimmmlpmmqqmmmqnnmmimqmmmmmmjjmpnqmmnqqqqqtuqqDDEEDuuDHuqqtqpmlpqqqqmlhihiiiimelnnlimmlmmlillpmmmqqqqDIODDqtqqDDCqmqqmpqppmlll",
"mmmmqtqmmpqpppuOptLUVLqqpCtmpCtmppCNODppqppqCCqpsqtpCCNNoppppCCpqpqCDqtCqpqpmlheelmllmmilliihihimmlillllkhllpmllmmmmmmpqmmimmqqmmqplipqmmlmmmimqqmlqqqmqqquuuuuutuuuqtqtuEOOEuqqqmpqqqlhmmmpqqqqlmllmlmmmmmmmmmimqrqmmmmmmlllllmmmmmqquuqutqqmlmlqqpllmlmmpqttql",
"mmpqqqtuttqqmpptmlppqpppCDLtqLODNDLLKtppCCCCDCCCCCLNCCCpqCpppppoqmpqqqqqmmllliihhimmqpmmlmlihhhilmmmpplhghkllliiiilmiljlqmmmiiiihililiiliimqqmmnlhilmilmllimmmmlmmqqmmpnmqqqqqqqqqpmpmqqpmmmqqqqppmppquuuuurqqnmimnmmqqmpqtqqqqtqqqnmmmmmmppqttuCqpnDDtmppmqqqml",
"mqruuuDOOECqppqtDqqtqCDOELOLDDMUUUOONDDLqCDCCCqCNKtqCCDLNONDDNCqqmmmllmplliiihhhilpqDqmlimmmiiimilmmmplhhhikiiiilmmmmmminqqmliimlhlmmllmilmqqnmmilmmmllmmllmpqmlilllmlllilillmpqquuqpqDOutqpqpqqlmlmmqqumqqqnqqqqqqqqqqqqqtuttqqmnmmmllllmmmmqtDDqmtHMtpqqquuttt",
"qqtuqqDDutqtqqqtqpqqqqqzLDDODqCDCtqCqqCNOUUVUOUVUDqtCLNNCqBqCtCtqqpmmmpnDLIDtqmmmmqDLqmmmmmliiimimmmomplkklillilmmmmqqnqmpmqnqqrtqppmmqqqqqmnqqqqrutqqqqmlilmnpmmmmpmmmmpppmmmpqqqCtqquDuuqqqqqqlllllmmmimqmqquurqjmmqqqmqqqtqppruqrtqurqqqpqquDDtDDDqqupmptqpmt",
"nmmmmmmmmmpqqqtpqCqqtztqCqpzDqmpqqqqqqCEqzDtqqqCDDLUVODDDLDOOUOOMLDDDDDDqqqqqppppmpDLqqqqmmmmmmjililillkllllllmmqqnqnqqqlmmnqquuquqmlpqmunmlmmnqqtuquuqppmpmppqqpqqqqtqqqrqtqtqtDHDOODDtnqqqqqqqlmpmpmllimmlimmnihhimqqmlllpmpqqqqqnqqqqqttuDDDDHEOOtmpDtqpppill",
"qmiilmlihllmplmmmmlhehhimiippmlimmpqqqqLqqqqqqqqqmptCqzDmmlmmmmmttAtqCqqqtDCDEVXCtADqqpqqqmnrDErDMOONDtpmpqtqpqqqqmmmmliijmmmnmmlqtmmqqimmlimmmipmmpqqqmuutqmqqtnpmqquuDqtqquDuuLDtCDHuqpqqrqnmmllmpmpmliliilmmihfjqqqmlmmlllllmiiiiimmpqqtqqpqpqqqqpllmpmmmllll",
"qmmmqqqpmpqpmllptCqmmmpmmllmmmlliiilmmmmiifhhiiilhhiilqOqpmmpmllimmmmnqpmnnqnqqDqCCplmmmnmmnrrAAimmmlihhpptqqpmqqnmlmiihiimmmiiihmmmmmmliihhimmillimmllpqmihhimppmmmmpqqqnppnpmmllhlpmlhmmqmmliillllllllqqqqqrqnmmquqqmqqpllllllmmmqqqqqmpmlllhilmpmmllhhhkhlpql",
"rqqqrvuuuDutqpquzDDqqqqmtDuqpmqqErqqnmlilihiiliiihilihmDpmllmihimmmmmqrqquDDqihehlmlilpqqmmiieeeeehddehhhlmpmimlqnmmmmieeimmmiimlhilliimihedimnmihhllehmplhhimqqqmlhlilltqmllihhllpqDtqmhiiiiimmllihiiimmmlmmnmhqqnqnmuJqnppqtqtnqqqqmlihihhhimpltODqpmlpqtptOIt",
"pqqpmppqmqpmpCCpDDqlmllpmqLDqpmmtmmpqppqqqppmqqpqqmllmpmqqquqpqmlmilmtzpdihmmhiehhlpqmmmlmjimrqnlliiihhiliiedeimhhlkihklmllpplklmlilmmlllqnpqqquilpqpmmmmihipuqlimmiilmiehhehimmpplmquqtqqtHqhiqimihhmqqlimmmmmqhilmmllmpmmmmmmluqpmlmpmlmpruqttqqqqmptIXDmilppp",
"qqDDDDztlqtsptplCDqlpqqtLCqCDCqplqqiimmhqqqqqqqqqDDDDDqqqqqpmpnqmpmmqqmhqqqqqlmhdehhiheheeeeeiieiiiiiiiihiihehimhklllhhhplpttpmpuurqqpieilliiihmpmllmqqqlpqpmpqqquunmqqqtrttqtttmqpptqpmqDODplllmmmiiimmmmpqmmlmllmqqpmlutpmmppmqtqqqtttqqqqpmmmmqqtqqqDDDtDDDzp",
"mpqtDDplmpzCCCqsmCqptCplqlllpmllqNIqpqqllmlmppqqqDDDCqqlqqqDtqpmqqqCDLuqmDqqpmqlllillihiilihiiiiiillllljlmpnlmmqlmpqqqpmtqqqtmpqqqqqqmidmqmmmiimtmihllllmmllmmmlnrqmlmqmlmmppmmmlmmmqtmmqDOIuutqqqqpmmmlqpmqmlmmmllpqmmltqmmqtqtlmpmmmmquqpqpmlpmmpppqtqDtqqCDDD",
"ODqzDLDCLtpqCCCNCDDLULqDCqqDtppDHuqttqppmpppmmmmlmpmqDLDqqqqqmllihilquzqlqmlmqDmqppqqqqqqqqmmmmmmmqqnmmmmqqqqqqqpqquttqqqppqpmlmmmmmmmieimmilieiqplmqqmhpmlmptqmlmrqnqmmqqtutqtuppllqqptplqLDqqDvEvurtqqqqnpmqquDuqqqttDuqppquDupuDuqqqqqqpmqqqqmqpqqqqqODCppqLO",
"VDqCMHDD0DppqqptzppDLqCYCDNUUzqDLCpzLDCqCDDCpplllmlilmpqqmlhhillmmllmlmmqtmmpqCqllmpqpmpmpmmmiljlmpmpmmpmmmqqqqmmmmmmmmmiimmmmmqpppmpmllelimpmllilmpqpmmhmqqmmqtjqqrqqqmqpmmlillutqpqppqIqtOOtqHIOEutrqqqpqqtqtutqqtqqquDutrutqmqDDDttqtmmpqqqqqtuqqtDDuDOOMLDDL",
"CqmtCqppLCqptCpllllCDllDppqqCtmlzLLpC0UtpCLLDCptqtqpmpmlpmpqCqqmDtqqqpmlqqlpnmqmlllmmmlimlmmmiiihimmmlmpmllmqtqmqpmllllimmmmlllmqmmmmmmpmpqquqqqmppmmmppmqqppqqqqqrqqmqqIqqttqtDqqquDuqDOOODDOODqqqmmmlilmqqtmmmhimpplllqqqqqpmllmppnqqpqtuqqtqqquuqtEHtqtLNDCtq",
"qqCOMDzDqCCCCCCppDLOUqmCqDDqqCtplCKppKCkhoCNLCKCpqCDOU00mqDUXUDqCpptppppqplptlppqmlmppmlmmlmqmllimmpmmmqpqpqqqqqrqpnmnmmqqqmmimmlmmmmpqqmqmmpmlmuuutpqqqxutruIutuEEDuuuEqpmqODqtmpptDtqDpqqptDtmqqmllmlimmptqmlllmqutqmmllppqqqqqqqqtDuqtDEtqqqtmqqqqtqqqqtqpppt",
"DqDOODDUtUUDCDCtLVNqCNUVCU0CpqLOsKTNKBployNTKCpompmlpqCDCqpqDLDCOLtzCtCOUDpLNppptpllpmppmllqqqmjpqtqpmqtqqrqmlmpqmmmmqqqmnqpmmqrqqtqqqqtqtmilihihhlmmppqmpqpmpqqmnquqqqtpiltDtlhqpmmqmpDummuOtqtqququuuqtqqqqpqquqpqqqqpqquuutuHOuqqtDumpqtpllqqlqtqqqtmCDNLDCqq",
"qtzDDLDDCqtpCLCppmpDLDqpVNDDDDLOKNUKCNLWYCyKCpoC0mlqlpzlpCDqpqCqptNUNzsLKKCHNDCUNDtDHDqtqqqmqDDqplmpmppmqmpphpuqqqruuuqqqqqnmqqqlpmlpqqqpqplhhihhimpqqqqmhhiquqpimmnqqnqqpmllptEqqpqtDqqtpqNPODDODqpqqqqpqqtqtqtpppmpppppmpmpqqqqpqmmpqtrqquDDutJEutuIDqDOUONUOC",
"qqppqDLLLLDCDNCqplpqDCDCNCqzCDNOUKCBKUBlNKCKKKKNUtCCqNOCqCCCqpllCpCNCppCtCppCCCCHqptDDtquHEDDOEuItuuuuutqtuIuDIuvuIIvuqqiiillmmquuuttuwupqqpqtttqqqqqqpmmpqqqqquqqqqqtuuIIDuuuDItEPODtDPUDtDHCtDutqqpqqqqpqqqpppmmmpmmlmlllllllhqmpmpnqqDtqDDutDuutqtDDttDqllpqm",
"DzqqqqqttDCCDNNNqppqCCCDAppqCDDCpCYNCCsKNKCCCKCCpDDCCOUDOCCUULtCNKCCCpCKCNCpCNKsLtpqCCqppqtqpqqpppqqmlplkipplppillmppmmlqqpqqqqqttttqttqtttqpqtqtqttqtqqqtuuqpqtqqnqqqquutqpqpppltDDpmptqqqDDqmmqqutqpqqpqqpqqpqpptqtppmpqpqppliqpqpqqtqtqqpqmqqqutqmpmpENDpmqCt",
"qqqqqqppqzCCCCLNUOLLDDLLtqqqqqpqCCKCLTCCCNCBCCKBpDLCCLCNppqDNLDNYNLNNNTWNTNKTUNNUDtCDDtpDDDqqqDDqptqomplqttpmppmqqquuuuutqpmqqpmmppmppqptutpppppmqpqqqttqqmpqqpmmmmmmmqmmmpppmmmmpquuqpmmpuOHqpqpqtqtqqtqqttttqttuuuutqqttttuttqqqmqqtqqtqqqqqqqEIOuqqtqqqqppqpm",
"lmpqCCCzDNDCpqszNLHCCqtqtCDCqpqtLCGstCpoCCCttNUHzCCDDqtNpCDCqCCDNKGCKNNTKNNWYGBNWUONNNDDUODtDOOIttuuqtutuHuqpqpqllppqpllmlllppplppqpppqppqpmpqqqqpmpppqqpmlmqqplnqpnpmmmlpqqppppqqpqDDtputqqmpqDqqqqtuttttqqqtqtqtqppqppqqqqqqqqqpqqqqpmmpppmppqquuqpqqDmpqqqpml",
"qqCqDDDOLOTDCCCtqtzqpqztqCDCCDDDstOCoppDCHCpCDNCCtCLCtCMpNOCCLNNKGCCCCCCGCKWWCpWNNNDDLNNutqqDDtqqpqppqtplpplmlhkmppttqtttpppppppmttqpppppqqqqttpquqqqqqqqquuutuuquuuttqqlpqqppqqqqqppqqDqqqqqquDHDtDDMHDutttqpqpqqpmlmmpqpmlppmppmppqpqplmmmpnpmpqqpmpqqOONLLDDD",
"OOOLDDDLDDNLDNNLLNODDLNLzCDDLNOLNtCqH0NGDHDDCCtpCptNCCNCoppptCLNKKKKKKNNNNKNTKGYCNCCCLHDDDCDDDtqtqpppuupqDututmpolptuwuwttqpppppqtutqqtqttuttuqpqqqutuuutuIxuquuqqqruuuuutttuuHHtuDutqDIqtHOOOOOLDDDDDDDtqqqtqtqttqpppqttqqqqqqpqqqqqqqquuuquIIHEEDuDEDuNEDNDDDD",
"DLOOLCztCDLDCLCCDLLqppqqNDCCNVUDHLXNDODOCCHNOHCtNzNLCNUpCpCNTNCNGNNNNWYYNTKCNNNWWONCHUODOONDDtDDHutqqHIqtOuptplpqttHIHHHuuwuwIIRuIOOIIIOuDIIIIutmmppmpmmqqtqqpmmqmqmpqquuqmpuOIuqqqqutqmttqqpqtqpqqqpppqqqtqtuuwuuuttuuututuwuutqqqtqtuIDtqptDEDuuttDXOOtCCDNLDD",
"mqCqqpqqCqqDDqqqNppqmlpqpmmpmpmlqDOW0UtDDDMOOVVOMOUNLVNCDNDLNLNLNCHUNCtNNNONONNNWNHNGGNNWGCHNNHHquIuuIDtuIOIDuutIuuOItqutttuuttptpqqqttututqtqttqplimmllllilhlmpunmmmimqqlhlmlllqqpmllqtqpqqtpmpptNptpCpptCtppppHIHutppqqpqquuruqttuRXItqqttuutqDMDDDDCqqqtzCCCs",
"tDDDzqCDDpmqqpmqplpplpqpillilpmmlpmtDtqqmppqtDHDDOOOUY0UNNTOUUUUNUUNOWYWWOQQOWRW1WTWNWWN0WNNQHCHDIOIHEutIDwutqtqpmpppmtElllmpqqtqpppmlmppppqqqqpuqppqtqpmmplmlppumimlilmqlhmpppqpmpmmmpqqqtDDtqtosCoptHCsCtptttppplllmppqmmqqqrullmqtqpmttpppqttpqCqqqzqpppppppl",
"CCCqtqtqUDtLDCCDCNLzpCDlpqqpmutlmqpipmmpmpqppqqpqCDuDODtDDDHHNONUWYOW01UWXWOOQXWWNNQWW1WWQQXUQOWIIHOIuttDuqqppppqpmpmlpuqqmlllllqpmpmlllmlmpqppmlmmmmmmmqqqqpppqqmiimlimqmlmpmqtppmpqtqpqqtDDtqqqCqqpCDDNDCtCLDtplhhllqqplilmmqrklppmlppqppmmpqtqqCqpqppLCqqCDCt",
"DCqqqtzCLCqCDCqCLKCtllphmppmmpmhptmhllllqqqqpmmlmqqqpqplppppqtCtCttCCsptCtpppppptoossCHttCHDtttDutqutppqqttmlilmmlmppmllqpppmpmpqqpqppmmpmppttqpqqtttttuttttqqqqqqqrqqquqqqtuttuDuDDIDDDEHEOIMHDHOCHqODNOONDNOONwtpllpqtlliiilmqllmplpqtllpppqqqqDDDqqmpDqppCCCt",
"NLDCKNNNDCCLNNLCNCCDzptCplpttpmlimlllllllppmmmplmmqqqqqpmpmppqqtpmmtuqtqDDututuuHsppptDtDwDtppmppmmqqmlppqqplhlpqpquuuttqqqqtqtqqqqqtqpqqqqquuuutuuuutuutuuutqtquvPIIuuIuuIOPIIOIOXOOOIOOOOHIOIILNCOCWOUNONUOUOUDwuttqtqpmpmlmqqlppppqttmptutttqtCDDDDCDCqptCLLK",
"OTUTUUUUNTUWUWUW0LNYONVWOuDPVuqtpqqqDqmpmqqpmlmlpqqqmpmppppmppppqDDqqOEplllllmpptpopptHHtDtqmlpmlllppppqptuuppptIuuuHIuuqtttqppmqqpqqmpqqpppmqqqmppmlllmqqqqqpqqquIvqmnqqquwHDHuuDOIuttDIDuttDDttCtDCDCtCDNONCNOHIOIDuuIuIEuuuuuuuuuHHEDIOOIHDHIOMOUOMLNOONOUWWX",
"CHNNNNNWCHNNNNNNUNOONLODUDDHDtqqOIDQVDqDtDDutqpqqqqqqmmmqqpppmppquqlmtqiqqpmpppqhhlllpuuqtqmmmnmppppmqqqqttttqqttutpmmpplpqttututqnqnpmpmnqqmmmppmmmlmlmlpmpmmmpqnqmmllilmpmqqqqqtqqppqtDHDDIOIDqtLNDtqqqtCDtqCOIHIDHuDwDIIuttuuHDHIIIHIOROOwDIOXODMOHDDCDLCDDLN",
"sCCNGCNNNNTNCKNWLTUNLOUCDDtqCDIHDttOWDtVtDODCDDDqrqqqqtuuqqqmpqpuqmmmqqquuqpmmqqttuHuuIHXWPHvIIxqtqmpqtppmmmpqqpqtutpqtuuuuuqqppqqpqpqqqquuutqqqqqpppppqpmppppqtrqnmmnqqqpmpqtqptqppqqqqpqtquHDqqqXO0LONtqqqqqCOHuppmpplqttmllmmmptuttttttutqtuDOqqtDDtCqtCCtpst",
"tCCtstCNNCtspstCNNNLDCttDHDDutquDDDOOVOHDDDDDDDIrvIJIvuuPuuIRItuODqtuEIEQIuqtuuuqtqqqtuuvurqqqqrpqqtttuEtutuIIutqppqwDtpppllmmmliiihmqqqmmmmiihhhhhilmmmqqtuuuutrqqquurqqqtIHuttuDuuuuHuuuttuttqDtmtNODqqtCDCttCqqqtqtttpmihhllopppmpmqtutqpqtttqtDOODCquW0NCDCp",
"pssspstCsssCHNCGCNUNHDDtppqtqpqtODCqtDDDqtCuCuDDuuIEuuquqqtuDttuDqquOOIIEuquuuqptqquxuqtuqqqqqqnpquuwuuuqpmlmpllilmpqplhmmlllllmtqmmmqqmmmmmmmnnpppqppppqqqtuuuuuuuvuExuIuuIIIIPQROOIHDHDuuDIIDwCtCDUXUODDHHDDLOOIHuuuuqtqpqppqpqquutttqpppqtqqtpqqtttqpCuCtCCCt",
"CCDCttCCtCHNOUONpDNLCCCtqtqqqppqIODDqqDDMHMDDtqqquDuqmpqpEWXOItqIuEOIEutIIuIJIxuIuuQWRuxqtqrrqqmlpppqttpuqpllmpplptqqpmmpqtpmlptuqmmmqnmqqmqtrttmmmmlmilllmmmpmpnnnqqqmmmmmllpqptttqppmlppmpppppqqDDDDDDqtqtDHOXWVOIDDttutDwHttttuHIIIDwOOIIIIHuuDDDDDDHDCHUXOtp",
"CHDHCNNOWONNNHNDGUWXOOOONHDHDtuupqqqqppmINODtqqpuDEEqqqtqDHqppqtuDuuuqmquuttqttuutptuttqqqqqqqnqqtqmpuDtutpqqttuqqqpmpqtppqqlmpqqqqmnqqtuqqqqqqmmpmlmmpmqqpppmmlmmpnmmmlpquttutqmpmpmmpppmpppmmllmqqpmompmmpqqDLIutqtqqqtttttttpttttttDIIDtqtqqtqqtqutDCqtDW1YNt",
"pppptDOXWODttqtttNUONDHNutuDIHIIODHDOOIDqqttqqttqqtqqqppltHDHNHtmpmpmlptuuuqpmqtwHuqquuupmmpqqqquutppDIuqpqqtqqquttqtuuIuttqtqtuqruuurvIvuqnqqmmppppppqqqtqqpppmqqnmmmpqmqtqpqqmsqsqttuututtqpppmpqqqtqttqtqqpqpqqpppqppttCCppppqpmpmqqppllllpppppppqqppIOHqptGt",
"pppppttuttqppppplptppomptqqtuttuDqmpptDttDuCqtCDqpmqtqqqlptCDtplqqpppqtuPQXOwttupuuplttqqtqnqqtrqtqqqutqtquIHtqtuttuIIHDIuttuuutuuvurqqvurruuvrrtqqqpppqqppmpmppnqqqqquvIIIuuuDIttutuuwwtuuuttttuDDDDDDODDDDDDqquuuuDDuDNOOOHCCCqttttqppmppqttqqqqqtqtqtHOHpkppk",
"uttqqqppqpqqttqqCNDCtttqtsqqtqqqODtqqtDDMDDtqqqqDDDCDOUW20NCpCLWOIDIDuuwuIIIuqtqtwIwuuwuuuqtqurtqttuttttxtuIuqqtmlmpqqpmpmlllpmlrqqrqqqnqqrruuuuuutqqqqtqqqqqqqtruuuuuEIDEDutqtIuuwuuuuuttwuuuuuDDDtqqqDtqtDHDDDDCDDDHDDDNONNHGHwuuHIwutttuuuutqtqtqtqtqlttttDHt",
"tuuDHutqDuttuuuuNOONDDHutqtuHuHHDDDCqqqqttqpmmmpqqqppCN0WUUXWLCNROOQOIuuttttttttuqpqttttttqqqqpmpmmllilqpmlpmlhmmpmlmpppqpmmmppmqjmqrqnmmmqqnmmmmmllllllmmllllllmnqnpnpqqpqtqpmqppmppopmppqpppppmpqmmmqummmqqtqqmmmpqqppppCCsppsDDuuDDIIHuuwDHIIIIDuuuuHODtDHtCN",
"qqtuvIutvuuuuuuIuPOIEIIEOwIOPOIPOOOutDHDODqqpppmptutmpmmlpqppmpplptqtqpppqqqqqpltqmlpmpmpmllqplmmllmppqqqpptwtqpqqtqqpqquuuttqtutppqtqttqqtqtqpmmquuqqmmillmmqqqlmmlimmqmpqqqqppqquqmmmpmqqqqqqqmmpqtpqtqqqqpmpqqlptutpmllpqqpllmppmmppmqqtqqqqqpqqqqtqtuutpqtuq",
"mpqqqqqqlpquuqmlmprqqqqpqqpttqttDDDttDDDOODDuDDDuHIutqppppqtppqqpDODtqqtmppqtDDDutqqqqppqtpputqutuutqtuuIuwIIIwIuwuuuuuwuwxuuuuuuuquutquuttuuxutqqqqmliilmmllilmlmmllmmmpmmllmmmmpnmmmmmmmqmmmmillmmmmmqqpqqmmmqIqmpqpmqtqpqpqqttuuttuuuqqqqpmpmqttqqqqmmpmmqqtq",
"mpmplmptqqqtqqpqmmqmpmpmpqqppqttmppmpqqqqpppqqttIIIDDHIuDHIIHIORtLOHCtCDtDDCDNNDIIHIHDuuIIEIIutwqtqqpmptqqmpmmptpmmmpqqpmmppmmlmliillilhmlllmpmmmmmmmqpqiliiiiiiqpmmpqpmqqmmmmqqqmppmqqqmqqqqqqqmlmpppqtqqpmplmppllpqpmlqpmmmmqtmmpmmqqpqqqqmpmpmqmpppmhlmqpmpqp",
"tqqpmmqqqqmpqppquuqpmqqqqttpqtuqpqqqqqtqpmmpqtqqqpqqtqtutuDDuDHODtqqDODqLHDuCDDtqtqtqtqquttqqplmmmpmllmpqpmlhklmppllmmpmmpqtqqppqpqttutuppmmmmmmpmmmquuuqqqqpqqtuxExEIuutuuuuutqrqqruuuuuuuuuvIIqtqtruuuvuuuuuuuqqquIutqtqttuttupqpmppmpmlmmmmmmqqppmqmlmpqqpqmq",
"uqqpqpqplmpuqqmmuqqqqqqtmqqppqtpqpqqqqpqqqqqpmppqqtqpmqqppmpmpqqpplltCqppppmpqtplmpppmpppplltqmppqqqmmquqqpmpqqqtqmpqqpmllmmpmlimmpnqqqmqquqqqtuqtqqqqqqqqqmmmmmquuutuuuqqtuutqpqqqqqqrqurqqqqqqqqtuutuqttqtqtqqHuqqqqtttqtuHuttuqqtqqqqqqqpqqqqtqqqqqqplmmpmqtu",
"qpmmmmmlqpqquqqqqqruuuuuptuuuutqqqpqqpppqqppmmllqtDuqpqDqqpppmppmpqplmplllllppqppqqqttqquqmpttpqmqqpmpqtmmllmppmqpmppmmltqttutqqqqqqqqqmillmlmpqqnmmmmliillmillllpqqpmqmpmpmmmmmllllllmmmliiliillmmpqqmliililllillllllmmqqpqppqquuqqqpmpqpqqpqpmmpmmmpmmlllmpmqt",
"qmllllllqmllillqmqquuquuwuDIIHDHDDDHDDuDDDDDtqtummpqpmqCmmmmmmmmmpqppmppppqppqpmppppqqqpttmlpmlmmmmmmmqqpqtqqqqpqtqtqtqpqqpmpppmqqqqqqmlliiilmmlilililmmlmmpqqqqqqtqqqtqmmllilllhiiiihilihhiilililmlmmmhllmlmqqmhlmpttppuqqpqpqtuqqqqmmpihhehhhhhlllhhlhmllmpmmm",
"pqmliimmqppnplilmmmmmlmutqqttqqutqqtqqqtuDDuCuDOODDLDCqDqqqtqtqqppppqDtpmpppqtqputqqttqpuuqqtqqututqtqtuqvIutqtqqtuuuqtqxurttrttqturqurqqmllmmieihiihilpmmqqmmmmmpmlmmlilllilhiiiimmilmpqmllmiiimppmpqpmimllpqpmppmllmqqpplmmlllmlillhhiliillmllimqpmlllihimqpmm",
"qqqpmpmpmmppmpqqqqqmllquqppqppqppppmppmpumpDDpmqDLOMDDDNDDDLLDDDDHEHHLOOuDDDIONDuuuuuuuwtuttqqpqqqqqrtrqpmmpmqmmqpmqtuqmpqttqmmmmiilmiiiiimiiiiilmmlmmpnmmmmlihlplilmllhhillpmmlmmmpqqmmqqnpqplmtuqqqtqppmpmpmmmpmompppmlhillhlmillillpqmlmmpmlilmpmqqmmqlmtupmq",
"uutqtqtqttrtqqqtnqqmilmqllpplpqqlmmmlilhpmmtqllqpqqqqqqqCqqqtqpqqCDDDDCDCttCDLuppppmmppqmpmpmllliiiiilmmmqqqmiihlhilmpmllmmlhhhlmmiiiihimmmmpnqqmqqmpqqqqpqqqmnqqqpqttpmpmpppppppqqqqqqtquqquqqqqtuttuuquuuqtqqpqtqtqqttpppmpmptqqqqqqqumpqqqpppmmllmqtumlmqqpqt",
"pmpmmmmmnqpmmmmqpmqqpmuwmmtqmputmpqtqqpqmmmpmlmpmpmppmpmqpmpmlmmppqttqqpmpmlmpmkmmmlllmpmmlllllhmmiiiihiilpmlihilllmpppmllliilpqqmlilllmlmmqnqqqqqrtquuqqqqrqqquwuuuxuutuuurtrttqquqqquuuuuuuuququvuuuuuutqqqqqqllpppquItqqqpppqqqqpnppqpqtqmlmmtpmlmmpqutqpmmqq",
"qtqqqqppppmmppqqmqmmmpqumpqplptllmpqqppqpppmmppmpmmpmppmpmmpmlmplmpppppmppppppmlmppmlllmplllllllmliihiihimnqmmmmlmmpmmmmpmpmpqtuuqnqqqnqqqruuqqqllmlmmmmlilmlilmmmppmpmmmpmmlmpnlmmmlilmqtqqqqmqpqtqqpqqlllmlmpqmmpmpqtuuuttqqtuuuuuuuuuuuuuutqtuutqtqqquIuqptuu",
"qtquturuuuutuuvxuurqqqqutuuqpuupqqqqpmmmtqqmpqqlpmlmppmlmmomplppppppmppppqqqqtppmmppmmmlppmmpmmmqnmmqqqqqqqqqqqnqttqqpppqqqqpmmmuqqrrqqnmqurqqmmiiilmqqmqqqqmlmplllillllpmlllllpmpqpmlilmmmlmlilillilmliiilllmpqppllmmlipllmmlpqtqtqtutumpqqquuuuquuuutuquuqquuu",
"iillmmpqqqpmpqpqqrtqqquuDutttIIqututttuuDDttuDtpqttqtqtqppqqqpqtqqqqppqqpqtttttqtttttttqtuttqtttvuqqqrqnqmnpqqqpqtqqpmmmllmpppmlmjmmmmiiiimmmiiemmpquvxuuuquqqqrtqpppqqttuuqqpqqqquuuqqpmqmmqmlmlmlmptqpllmmlmmqplhilplhllikhhhhihiillmlmlillilitmlmmlmmlmpmpqpl",
"hlillmpqlliililiilililmpmhlllmplmllmqqqqqtqqtqqqttttttttpqtttqqtqtCtttttDNONMOOHuuuutttutuuttqtuuniiiiiiiimmmmmnmllihhhhhilmmmpmihiiiheemmmmmmmmlmmmpqqmliiliilmplilmppmmpqpmlllmmmppmmmqtqpqqmqpqqqqrtqmmppmmppqqptuuttqtqtqpmqppllmmmmtqqpmlllqlillhhilmlmpmid",
"mmmmmpmqpmmpqqqpqqmmliiilhlllllmlilmqqplhilplhlmlmppmlmmpqtuqpptqCDDDDCtpqtqtqqptqpmlmpqmpqpmlqtrmiiiqqqlmqqmmmmtqpmmpmmppmlllllnmmmmmlmnmmmiimmqqpmnqmiihlillmqmlllmpmllmpqpmlmmlmmnppmqqqmqlillmmllllipqtqqpqqqpqqqppmllpttuuIuuqqpqqpqtqqmmqqqmpuupmmqmpquupm",
"mppppmppmpqqqqpqmpqtqttqqpmlllmpppllkhhhlmlllilllhhhillqhhllpmmphiimqqqqjmqqnnmnmmllmmmpmpnmmpqqmmqqqmmqnnqvvunqqqquuqtqqqqqqququtqqqpmqllhimmihhimmpmmlheeeheilmilmmhehmmmmmlliiiiiliiiihiiimliimmmmmmmimmmmmppqqqqpmlmlmmlmlmmlmppmpmmqppmppppmmpmlimmppmmpqqq",
"ppqqttuuttttppmppqqtqtttqqpqqpppuqqpqpmlllmllllmplhilllpplhihllqmmlliiieimnnqmnqmmmqqqqiqutqqqqqqqrrqqqqqqruuqqntqqqqqquqtqmqqqpqmpqqmlmpmmpttqmpqqqquuqqmmmmpqqqqqquqpqqqqqqmmimmmmmnmmmjlimiieiiiiimmmlilliiihhehiiehhihiihiklhhilllhlhhhhllmlmpqmlillmmlliiih",
"hilliihllmlllikidhhhhhilllmlpmmllllmmppmppppmppqpmlllillilllplmpqpmmlimmmmqqmmmnqqqqtqqqtqqqquqmqmqqnmmnqmmmmmmmmmmlihimmmmliiihillpmlhhillmmqqpnqqqqqqqqqqqqquuqmpqqqqquuuuuuqtqqqqqqqnqqqrqqqqqqqmnqqrqqmqppqqqmqqqpmqhihhikiilllllllihilllllihhiheddeiimlmlli",
"lllllllhihlihhllihlllillehhlihhhhhhllmmpmmmmllmlmpmmpmpmpppqqppmqqqqqqruqurnqmnnmmmlimmmmqmmmqmliiiiiiimmmmjmmmnqqqmmmmqmpmmilihilmppmlihillmpmpmpqmmqqqhiihehimpmmpmmmqrqqmmqqummjmmmmlmmnqqnnqqnmmpnnpmpnpmpqqqtrutqqqqqqqtqqttqqqppmlpplmmllhlmmpmmmmllmmppqq",
"mpmpqqqttuqtqqqqhililhhhmlmlllllmlihikihihhhhhhhhlmpmptuIuqplilmpqtqqmpqqqqmmmmlilqqqqmlmmlmmqmiiheiiilmhiihiiilmmmmllmmmmqmlmlipqqqqqqmpqqqqqqqmqqtuqqmqtqqmquuqmpmqmpqtqqqqqqqmmmmmmmmmqqmmllmmiimmqmmqqpmmlllmimqqnqqqqmqqqtqqqtqqqpmqqqqttuuqqqqqqqqmmpmnmqm",
"pmpmmppmqqtqqqtttqttuuqpqtqqqqqqmmlllmmmpllllilihlmllimpmmliihhiiiliiheeililiiiimmqqqqpqlmllmmmlmmmmqqnqqruruuurqqqqqrtquuvuquuuqqqqqqqqmqqqmmmmmqqqqqqmlnpiilmpqmnpmqqqqtrtqqqmuuqqqtqqqqqqqnmmnqqqqqqqqqqpmpmpnqqqqqqqpmmmqqqpmmppqqpqihhhilllmmmmllllmmmmpqqq",
"qqmpmpmmlmmqppnqqmlmqqpmqqqqqqqtqqqquuxwqqmpqqqqmmlilmmmhhimmlilhlilmlliljlilllilmliilmqmmmmmmmmqmmqqqqnimmmmnmlmmmmmqqmillihilmmpqppqpmlmlmmmllmmqqqqqpmtrpmntrmppmmmmmlmmmmllimmmmmmmiiiimmmmmmmnnmjliillmmmpmqnpnmlmpqqqqquurppnqpqqpuutqqqqqqqpmmmmmllmqqqqq",
"mlllmmpmqqtqqqppqmlmquqmmlmpmpppllmpqqqqmmlmpqqqppmmtxIuutqppmqtqqqqtqqpqqnqqnmmqquuuuuuqutqmpqmmmmnnmjmmmqnquurqpmmpqqmmqqmmmqqmqqqnqmlqmqqqtqqqtqqqqrqtvxqqtuvtrqqqqqmnmmmmmqtmmiiiiiimliiiiheiimmmmmmppmpppmlmmmmmlmqmlilmqpmqqqqqnpmqpnppmliqmmmmmqqmmqqqpmm",
"uqqqqmmmmmmmihimqmpqqtqqqqqqqqqrqutqmqqtqqqqqmllqqpmmmqqqqmmmpmmmmqqrqmlillmmmmmmmpqqqqmmljmqqmimmmmlimmmmnpnmnmmqqmmpqqmqnqmmmmlmmlmllmiiilmmmmqqqqmmiililqqqqqmqqqqqpqpmlilmpnmmmmlmmplmmlhilnlnqqqqqqpnpqppppqqqqqqqqqqqqqqqqqtqqqqpqmqqqqqmmuqmmmmqnmliiiiqu",
"uuqquqqtqqqqpmpqmmmmmqmpqqtqqqqqqqqqqqtqqqnpmmmmqqqqtuuutqqqqqqpqpqqqqqmpqqqqqppqqqqqmmmmmliliihimmmmimmmmmmmmmmmqnmmmmmmmmmmmlmmlmmmmmmmmmmpmpmmmmmlmmmilimqpmpmmmlmmmqnpmmpqnppqqqqtqqmmmqqutqnqqqqqtqpqqqtqmlmmjmnqnnqqnmmnpqmmmmmmnpmmqquuuuruqqqqmmqmqnqqrx",
"qpmqqqqqqtuuuqqquuqtuuuuvxuurtququtquuuqnppmqpqpqqpqqqqqqqqqqqqprrruuurqqqqtqqqquqqqmmmmqmliiliimmqqmmiiijijmmmmnqpmmqqqmqqqqmmmmnmmmmqqmqpnqnqqqqmmmqqqmmqqqqqqutqqqquutqqtrutqnpqruuqmqpqqurqmqqqqmqqpmmpppmllnnpnqqpmmmliliiimmppqqqqqqqqquuuqqqqqnpmmmmqqmqr",
"lilmmpmmqqqqqqqtqqqqquuuqqqqqqqqqqnqtuutqqqqqqqqvurqqutqqqqqqqqqutqqqqqququuutttqqqmpmpmqqmlmmppnqurqqmmmmpmmmmmqqnnqtrqnqqqqqmmpmmmmpnqpmmpmpmqqqqmquqpmmpqqmqqmmmmmpmpnqmqqqqqmmmpqqmlmqqmihlqmqpmmmmmppllllmpqqqqqnmmutrtrquuqqqqqqqqqqqqqpmmmmqqmmqqpmmmmilm",
"qqqqtrqqmmmqqmqrqqnqqqquqpqqqmqnqmmmqqqnuqqqqqqquuqmpmnpqqqqmqqqqqmmjmlmlmmmpmpmqqqqqqpqpmmppmqmmqnqqnqqnqmnmmmqnmmmmnnnmmnnmiifiliiimmmnqmnmmmmpmmmpqmlehiiiiilllmmlliiihiiimmmmlllmmihlmmihhquurqqqqtquqqpmpppnnmmmiihiiiiilmlnqpnpmmmqqqqqnqqqqqqqrruqqqqmmqq",
"rurqqtqqqmmmmmqqquqqqqqqqqrqqqqpqmmmmmllmmmmlimlmihheiimmmmmmlmnqnmliliiillmmmmpmqqnpmmmmmmmmliiiiiimmmnmmmimljljifiiihimmnmjifemmimlimmqnmmliiihiilmmmhehhilhimmmpqqqmmllilmpqqqpmmpmmlmmmmpqquuuuqquuuttttqqpppmmmmmmjmmmmmnqqqqqqqqqqqqqqqpmmnnqrruqnqnmnqqru",
"pqqmmnqmqmmmmmmmqqqmliiiimmqmmliqmqqqmimiliiiiiiilmmimpqmmmmmmmmqqnqnnmmqqqtttttqqqpmmmmmpqpmihhhehiiimliiiiiiimmjijjijmnqrqnnmmqqqqqqqqqqmmlilihlmmpqmmpmmmqqmqmqmqmpmmqqqqqqqqpnqqqqpmqqqpnqqpnqpmqqqpmqpqpollqqqmnqnqmmmmpqqqpnmqqqqqpnqqqmliljlmqqmmmliljmmq",
"mmmmmqqqqmliihiimmmmmiiiimpqqqmmilmqqmlmmmmmpmmmiimmlmqqqqtqqqqqqnqqqqqmmmmqmpmmuqqqqqttqqqqqmliiiiiiiieliiiimmmnnqrqqrvurvurrrrqrrrrrrqqqqqnqqqqquuuuuqrqqqqqqqqqqqqqqqmmmqqqqmmmppnpmpimpmihlqlliiimlimlllllomqnmjmlmmiiiiiiimiilililmmmqqqmmimieimnqmmiiiiiii",
"qnmmqqqnmmmmmmlitqmmmmmlmmmqqnqqqqqqmnqqqmqqqqqqqqqqqqquqtqqpppptqpllllhqqqlhehlmmmmmmmmmmmmmlmpjmmmilmqqnqqqqqqqqpmmmqqqqqqpmllmnmmqqpmqpnqrururtqqqqpqmiiilmmquqqmlillppmmlllliiiimmmmhihehiiljjmimiimmmnmmijmjiiiimnmnmiiijiimmmmmmqnqqmmmpmlmlhimqpmmmppmmmm",
"qnpmnmmmqqqqqnqnrqqquuurqurrqqqnuurrqqqqxJuqnmmiqqqqqmqqmmppmlmlmmmlmmpmllmllmqqxuuuuuqqqqqpmlmmmnmmiijmiiiimmmmmmmmlmmmlmmpmmmmjmmmnqqpqnqqqqrrqquqqqmmpmllihiilliillilnqqqmmllillmqqqmmmmmmpqqmnnqnqqrqqurqqmqmiijmnnnnmiijmjimjmjmmmqmmmppqqtqpmpqqqquuuuqqtq",
"npnqqqqnqrrqmmmmqqqqqqqqmmmqqqqqnqqqqmmmmqqmmtrqmijnqqqqmpmppmpmhlmlmpqpqtqppqtqqlimqqmlqnqmmillmmmliihiiiimmmmilmlmlllmmmmmmlmljmmmpqqpmmmljmmmmnqqqpmmqmmmmllmqqqpnqpmlmqqqmmllmmpqqqpuuuuuuuuvuvruruvqruurqqqmnnqqrqqqnnmnmmjmmmqmnpmqqtqnpqtqmmmmqqmpmmmmmmm",
"mmmmmmnqmnqnieiiiiiiiiilnmmliiiiiimmmmmmmnmiimqmihipquuuqqtuttqtqtuuuwEHEuuqqqplihhimmmmilihhhhemmmmnqnmmmmiijiimmmmmlillmllliilmmmmmqmmmlmiiljjqqmmmqqrqqqqqnqqpmmmpmmllmpqqqqqnqqqqnpmnpqqqqmmuvvrrqqnqruurqqqnnmnnnnnnqnnqqnmmnmnmmmlmqnpmmlmiiehilihmlllmpml",
"iiieeehemmpmiheihiiiilmqqqmmliilmmqqqqmmqpmmmlmmqmnruurqqtuuutqtquutquDEttqpqqqmpmmpmllmmpmlimmliimmqqmmmmiiiliippqmmlliliiiilmmmnmmmmpmmpqqnmmnurqqqqruqnqqnmmnmmmppqpmmpqqtqtuqtqqqpqqpqqqqmmlnqqqmmjlmmmmmmmmmliihhiimmmmmmmliilllihheeghllllihhhhilililmppml",
"miiiilmmnqqqnmmqqqpqpqqqmmmmqqtqqtuqqqqpnmpqqmquqnpquqqqmqpqpppmmpmmmmqqqqmmpqqqqqqnmiimmmmiilliqqqrqqnmqnmmmnqqqqqqqmmmmmmmmpmqnqmmqqqpmqqqqnmmqqqnqnqmqmmnqmmqutqqquqqmmpmmpqqmmmmmmmqmqmqmqmmmmnqqqqqnmmmljmmmjiheeehiiiiiiiihiijmmiiliilqqtppmmmppqpmmmpmmli",
"mqqqqruvqqrqqqqnuqqqqqmmpqpmmmmmqqqqmmmmquqqmllmiiimmmmmllllllllmmmmpqtqqqpmmpqmqqqqqmpquuuqtuvtvvxvuruuqqqqqqqqnnqqqqqqqqpmqmmmmmmmmnpplmqmmliiiilmmmjmmmmmmmmqpmmmqmlhhiiliiillmmmmlmliiiiilmmmnqqqruuuurururummmmiiiliiillilimmmpmmpmqqqtqttqqqppnqqqqttqqqqq",
"qruuuqqqquqqmmmllimqqrqmlimmmmmpmjliiillimpieiieiiimliiliillllmpilllmqmmllliimmpmlillliiimlhiqqmmmqqmmmmmjmmmmihillljlmmliiilmlliiihhihhmpmlieeiiiiiimmqqqmmliiiihilpmmhehhhihiimmqqpmlilillmpqqqqnmmmnqnmpmmpmmmmqmmlmmmmmmmmmnqqpqqqpmlmpppmppmmmmllmmqqqqmpqq",
"mqqqmqrwqqpmpmmmhhhimlllhmlilmlmqlhhhiiilpqpllllnqqqqqqptqqqqppqqpmmmmmpmmqqpmmmmmmmqqqqmlmmmmmmmqnqmmiimmqmjeeihiiiiiiimiiiiiiieihihhlmlmpmllmnqrqmmqqnmmmiiiihimmmmqmimmmqqmmpmppmmmqqqmququutnqqnpnqqmmqmmlmlpmllqqmihhililihliiiilihlllpmllplllllilmpqqpmpmp",
"qqpnqpqqqnqqqpmmmmmlmmmlqqqmmpqqqqmmmlmlmqqqquuquruqquuvqqtttqtuuuuqtqqqqtqqqqtrxuuxvuuuxuqqqqqqruuruqrqqqrqmmmjieiiiiiiimlmmmmnqqqqqqqutuuuqqqqqqqqqrqqnqnmqqqqmquqtuuqqqquqqquqqqtqqpmqmmqmqqmmmmqqmmmmmmmlmmqllililihiliililihlllmmppplmqspllmmpqqpmpmpqppqqq",
"qmllqqmmmpmqqqpmqtqppqpmqutmppmqqtuwuttupmllmqqquurqquvIqppqqpqtqqqqqqqqqnqmqqqqmqqqqqqmuqqmmqqqqqrrqqqrnqnmmmmmmmjlimmmmmmmmqqqnnqnmmqqqqqqqnmjmmmnrurmmmmmnqqnqqqqqqqqmmllmlmqqqmjlmmmqmpmmmmilimmqqmihihhhimmmmmpmmlmmliiiliihlmmlppqppoqtqplllmppmlmlmpmmpmp",
"pmlmqqplpmpmppmppqtmmtqplqplpmlllmpqqtqqqplllppmmmiiimpqqqmlkilpiilmmmmmilmqqmmillmmqqpmqmihilmmmmmmmijmiihiiliimmmiilijljmmjmmmimjmllmplliiiiieiiimmqmiiiiilmmmlmmmiliillljllmmqmhehilmpmmqlilhiiimmmliliihihiliilmmpmmqmmlmmmmmqtqpqtqttttutspqqpmmmqtpqqppmpm",
"qqppqqpmmmllmmmmmqpmlqpipqmllmlmlllmpqqphiihhhlimmmiimmmqqmlihhlilmmmmmlmmqqnpmlimmmqqnpqmliiihhjmmiiiiihiiiijiimiieffiiiiiiiiifhfhieilmqmmiiiiiihhilmiimmqqmmmmnpqpmmiheeehehiiilmqqqmlmmtqmilmiillmqmlqpppmppmmmmpqqqquuqqtuuutDEDtttuHDHDGCDCDDutqtDIDDuDutuu",
"DDuDuDttutqpqqtqqttqqqplttmhlmlptqmpqqqpqttqpqppnqqqqqpmlmppplhhmmmmmmiimmmlmjmmlilmmmmlmliiilihiijljlmmmmmmmliiiieieiiiiijljmjmimmmlmmquutqnmnqqqmqnpqqqquuqqquuruvuqmmqqqqqrtqmpqquuuqpqvxqpqqqqnqtuqquqtuuuttuutruxuuuuutruuuquDtqtttCCDtptCtqtDDuDCqHDCDLDLH",
"NDCCDDDCLDCtCDCCuDuuuuutuuqmpqqqqpmllpmmpmliilihmnqnpmmllmpqqpmpqqqqmmmlmmmmmpnqqqqqtqtqmlillmmmmmmnqnmqnqqqmmmmnnmmmmmnmmnnnqqnrqrrqquEuuuqqqnquqquqqqrqqquuqqqutquuqqqmqqqqqqqqqqqqquvqquuqruuqqqtruuuqqqqqqqqqqmpmqqtqquqqpqqpqqpppplpppopppplmqpmpqmzqqtDttq",
"pmlmqCDCztqqCtCqHuuDHDDIqDuuIIutututtqttuuqqtIIuuvxvvxurutqtttuIuuuuuuqqruuvxvxvququvxvxurqmqqqqqquurqqqqrrqnqruuurqnnnnmmnnqqnnijmiillmmqqqnnqrmmqqmlmpuqmqqqmlqmnqqqmqqqqqmqqqqquqqqqqqmmqmqqpilmmpmmmtqmlmpppmmqmmmquqquuqmmqqtpppppllpolpsplmqqmmpqpqpmpqpmm",
"llmppqpmqqqqqqqpruqqquupptttpppppmquuupmptuuuutqDDtqppppuuIurruquuuurqqquuuuqtqquuuuuuuEvqmmqqqmqqtqppnqqqqqqmmmqnieeimmmmmlmjiiiljmmmqtqplhllpluqpmmmpmmqqpmmmpmppqpppqhmtqqpmmpmlpqpmhpmpppppqpqqppppmtqllpuqpnrrunmmqrtqqtpplqtqpmmmlpquqpmppqpllmpqqtqpqqDtq",
"qqtqqpqpppppqppqqtuqqqqqqqqpppqupmlppmllqmlllmpqpppmmmlmimqqppnqmmqmpmmmmqnmmmpmqnqnnnqqqmmilmmmlmppmlihjiimjiiimmmiilmqqnnqnqmiiimllmmqqqqppqtqqqqpmpnpmqqmlmpqlmllmpmpqqqtqppmmpmppppmlppmmlmpppliipqtqqplmqpljnnrqnqrmmlppppptutttuuttuutqtqqttDuDtqpqpmmqqqm",
"qtqpmmmqtrtqqtqqquvuqqtuppmlmppqqppqqqpputpllpqqpmpmpmpmhlpqnqqpmmmmmmqqmmpmmmqmmmmmlmmmmmmmjlimhilmmmmlmlmmmmjmiiiiimmmmmnqqnmmlmjmmmmpmmlllpmllmmmmllmmmpmmmnppmllpppmppplmmllllmpmmmpmpqpplmmpmlhhlpqllllmppmrrrvvvuItututtuDuHEuuuHuuHuuIOIDOOHMDOEHDDttDDtq",
"DDHDutDOqqqppmppmqqqmlmqppmpsqplllpqtqpmtpmpqpplqqqpppmpmqqqqqqqmmppmqqtmqqqqqqqnmnnmmmmmmmmmmmmllmpquqqmilmmiilmmmllmmljmpqnpnmnnqqqqqqqtqqpqqpqpmmpqnpqtqtqttqutpqqutqppmmppppmppqqqttttttqtqtwvwwuuuutttqtuuuEvvEEuuEuuDutuDHHEwututqtttuDIHuDDqqtqCtDutDIOOD",
"qtutqDIOOOOODHOOPOPIPIIIuutuuHutppqtutppqqqtutmltqpmmmpqppqqpqqqpqqmqpqqqqqqmqqqqtqqqqqqmmmqqqmlmmjjmmlimmmqpmlmqtqpnqqqqqqqqnqqqqurtruuuvutqtutEuqtuvwuuuuvIvuqtquuututquuutqtuuutuuwuuutqtuuttuuDIIutquuqqpppqqnqqnmmqlmpmlpttpqtqtqqpqquuuqpppppqpmlhlllpqtuu",
"lmmmlpqttttqqqDNIvtuEDutOuuuIOOOIHDuDuuDHDHEIIHutttqtuuDtutquuvuuuuuuuuuuuuuuuuxEEvurqqrqqpqqqqmvvuuruvvuuuuuutuqqqmpqqquuqqqqqqmnqqnpqqqtpmlmmmuqmmqtqqpmqtqqpmlppppmmmpqttqpmptqpppqqpqpmmpqpmlllmpmmpqmlllillmmnqnmqunqqpmqtpqtttqtqpqtDIHuDItquuHIDIutqqtqpp",
"qtqqqquDDDDtqtDOEutuuutqutttuHIOHuttqpqtttttttutDDDHDHDDtuuuuIIIDEIEvuuDuIuuuEIIuuuutqtqqqqmqqqqmmnmmmqqqqqqtqpqllmllmppuqqqqpmmmmmmmmmmqtqpmpppmmmmmmmmllmmpmmpmmllmomllmpmmlllmmmlllmpmpppmlmmpppqtttttppqtqtqqqqruruIuIuttHuttuutuuuuuuHIOIOXOIHDIWY2WPOHuttq",
"ttqttDDDuDtqpmqtuqqqtpmpqqqtttttqpqttpppmpptpqttqqtCtqpmpqqqquqqqtqtqqqqmmpmmqqqmmmmmmmqmmmmlimqnnrqnnmqillpmompillllmmlqqpqqqqpruqqpmqqqqtqtqqpqtuutqtqqqquuquIutqqtuttqqqqttutqttqpptutuxuqpqutquIIutuutquutqpuqqqqqqqqqtqtEItqtttuOWXHutqqqtDtqtuuDwtuutqtuuH",
"qqtuuqtqDtuDDDDODDEHDttutttptDtptpptqptOQHuqtpmllpqlpV0QuqqtqpmpqqpmllmpmquutqpqqmmmmmmmllllmplhmmjiiiimillmpptttqqpmppqmpmquuqqqrrruuuuuwuuuuttqquuDuuuuuuuuuIEHuuuHEwuItptuutuIIuuuuuuIuutuwutqtqqtqqtquqpputqrqnqqmmqqtqmquupqqquORIuqpmpppppptuDIItppqqtqppp",
"qtqtDtDutqDDDtppuuuDDuDIIOOHOWXHtttHIDOY0VONDCtqtLOODHDutqqqqppqlmpmppqtutpmmmpmmmmppqpmqqqqtqmlnnnnmmmnmmmlmpmptutqqqqqqqtqqpmmqmmmmmpqqqqtuutquqmmmpqtipqqtrqqlpqtppqutqqtqpmpllllpqttqtuqpmtutqtpppqqtIIupquwqqpqqpnquvtpptuuupmlptDumpqpqqqquuttuDtmmppqtuuq",
"qqqquDHODqtqqquEttqqttqtDHHHNXODODNUUHHOHNHHNHDGLQYYXNCDODDHDuuItuuHIIOROIDHHIDuwDwEIIwutttuuuutvuurqqqqqqmpppqmlmmmlliimqqqmmmpmmmmmqqqqqqqpqqpqqpqquqmmmqqmplipqutqpqumqtqppqtutqqppmpqqppqtqqqtqqmptuptuqlmpmpmqqqqpqtwJIuuuwuwDxDuDHquIDuIIHuDuHOPHttqqtHIut",
"qqttCDDDDtqtqtOYuqpqqqpppttttHHsONNOHtqsqtqpqCCCppCNCtqqtqtDutqututuuuDDtuuDIDtpqqqqpqpmqqtttttuvvrrqrrqrqpmmpmlllmmmmmplmmmmmmmnqmmpqqqtqpllmppiipuuuqlqqqmmmpputpmmplhlpplipuuililmqqqlllptqlhlmmmlmpquutqttqmqpppqqqqtuPQPuuumtIOIuuuuDIHutuupquIIHuqttpqutqp",
"DIODuDtqtDEOHDqtDtqqtuCDptDDDNNCCtCCCCtCNHCppqtpCNONOYWDqtuDDqqqtqqpmpppqmpmmpmpqtpmmpqpqqqpmlmlpmmmqqqquqmlmiihjllllmmnmmliiiiiqmmiiliillillmpqhiiillmmhiihilmqupmllllipqmhhllltppllhhhlpuuqplmpqttqqqtuuutuwupqqqqqtuuqqpqqmmttttqpqHOIHuIuqtItuIOIutttttuuHuw",
"uDODDODtODOOODDuDDuDDDDHtNNNNOOHDDDDDNLDUUHttCDtlpppCNDpCDOOODuDDDtqttutqttttqpmliihhlmlppmllllmmllilmmlmmiimmmiiiheeehimiiimmmimiilmmmmlmpqtqppqpmlmmpqquIxuxuuqttqpqqtqppmmpmlmmpquwwuuuuttqttutuuttqqqttqqpqquuttuxIJIxvIxuvvuuqqptIXutqtqptDutwuttuIuuuwuuuu",
"mqtquDODODtDIOOODDDHDtDDDOOHNONNWUNNNNNGHONCLONNCCCCDNDCtCDODtDHDDuDDDDDuDDEODqmqttqtIIuqpppqttttqpmpmmimmmmmnnqmmmmmmmmmnmqnqqqnmmqqutqquuutqppqqtuuurtqqtqqqmmmpqtqpqtqppqttqqtttttqqptplmptqpqpmpppmltqqtqppqttuqtuIIuqtqqpmmpmommmpplpmllpqpmlllpmptpppmppll",
"lpplmtqpDtqDOECtqtDENDOQNUWONWWOUNOUOUNDNWUNNWUCYUNNLtCODDOOOEOVOOOOOVOOWODDOOOItIDuuOIDIutttuutuuqtuuuuqqqnmmmmnqqqqqqruuvurqrruuuruuqmpmplllmpmmlmqqqqquqqpquutqqtIwqlpllmpmptpqqqqtqqqqutqquxuqqquuuttpllpqmllmplmqtqIvumimpqpmllllmlmEHmpIIpqplpqpppqpmptttq",
"mmmmqqqmimmqmpmjlpqCDCqmDNDCLLNUUOUWUOOOOUVUOLOWONOMNLOUHDCtDHHtHuDHOIDtuuqtuuqqqqqppqppqmmpqqqquqqqpmpqtqqtqppqpmmlllmppqqttqqqutqtttttqqqttqqpmpqqpqtuqqtuutDDOEuqqmpqnqqqqqqqqqqtqqqqDtNOHtqoqlmqqtqmmpliplhtmlmptDDHtHtpsqttqptutmtutuuuqqqqtqppppqqpqqpmmmm",
"mqmmnqrqmmmimmmqlllppmpllpmptCzHCCqCCzCCCDDCqtzCDDCtmpppqtttDHDtqqpmppmlqtuqmilmqmliillitqpmqquuqpmqmlmmllmqtqtuutqqqttuqtutttttuuutuuuDtppmppppqqqqpmmlqmmmpmmlqpmpmllmppqpqpqqmmpmpmqqplpqplplmilmmqqplmqtuqpqtqqtuDHDtDtppppttpqtqptuqttqqppqqqqqmmpmmqqppqpl",
"pqpmppqqqppmlpqqlmpmqpqqlmpmzqCDDDCDDDDMLDDCCztqCLDCtqqtmppqtttpuuttpppqqqpmqqmiqmlhiilluqmlilmmmmpmmliimmpqqqqtqppmpqpppmppmppqmpqpllptqqplllllmppqqpmlppmpquqmqpmppmmpmmmmmmppmmmmlmppqmmpllppqmlmpquqttuHuuHDHIIOOOIOOQOtHHDHODuDuHOHIOOOHIHIOODDDuttqtuqqDtm",
"uuutqqqpllmlmllhpmpmpmppqCpptqqCCqqtzqCCLDCzCDCzpppqpqtCmppqttpppppmlmpqmiimpmlitqpmmlmmqpmhhilhmmmmllilpmpmplmmqmmompmlmppmpmpplmppmlpqppmppmlillimpqpmmihiptqpmmmpqmpqllllmpmmmmmmllmmtplpllllqqqqquIuutDIuHPIPVWVQOWXQYXOXWW0WRWQOWYRYWWWXUXWUWUXOOMOHVUMHOEq",
"DNINDttttDORQOutillmllilqqmlmpmtqpqqtppptqpqqqtqqqqqpppqtttttttqtuuuttuDuOXOuqqvttqtqpqpmpppqtqqpmmlmmmmmpmpppppqplmppllpmmlllmpppqqtqqpqpqtqpppqpmpqqqpqtpmpqqptqtttqqqpmmmppppqqqqmqpqtmqtqtuturuvuJOuutIWIDItHNONHNU0NWTNTWOWOUWUNOWOWONNHNGDOOPUOOODDXYQOOOH",
"HDNOOODDtDHOONHDtCDCtppppqmlptzNDCDLLCqCCzqtCDCCLNLDDDDCHODDtuCtqtttqqqtuIOIqmnquuuuutququuruxIuquqqquutquuuuuuuqqppqqpmqqppmppqtqttuwutIHuuuHIDIuuuuDuDIIIuuIIDPIDEuuuHIDuuuDutEIMIDuDDPDHUODNqpquvDIOuuuIDtuDtDDDDCDQWCONGHNNWNHNOHDNHUNNHDDHCHLHODDDDtLPODDOO",
"CttDNCCCNNNNNNONOUXUMODLqCttDLDODCCDDDCDLNDLLNLMCDCCLDDDDLHttuDtIOIDuuuuuuqquuuquuuuqqtutuqpqtuquuuqtuuuuxxuuuutwuwuuuIxHIIIuwvIIIuDIOIDIHDuwDIHuDDHDDHImtqqtDIuDttqpmpqOIDHEIDuEEDDDuDDODuDtqmlmmqtquupDHtmpqtDttGDDGDNNNHCGNNWUCGNNGNNWWNNNNNNLDLDDCCCCCCLDqCO",
"NtpCHCtCDCCCCtppDDNDCzCDCLDzDCqCOLLLNLOONDLDDDDDDDLDLLHDttCqtttttqqpppppmmqqnmnqmqppmmqqqqmiiqutqqqqqqqmpqqqqtqqqqtttuuHuuuuuuutDttpqtttpqptqqppqqtqqppmlmppqDtpIuqpmmpqppmmtqqpqmmmmmpqDqqDqqplimqqmqqipuqlppmtpqttttspGNCsCCGN1CCNNGNHNCCtGCGCDNDCCCqqODDLDtqD",
"DNUCppCUKspppCCpDpCDmtLpCqmlpqCDlpqptOOLDDCtzpplppCDNDtCqtpppllpmqpiilmmmmpmmmqqqmlmpqpqplllmmpqqqqiimqqpqplimtqmpqpmpqtutpmpppmpqpppqqqpmqqsppqpqttpmpqqplmlmpqqpqpppppmpppqttpmqqqmlmmqppppmllllmmqqtuqtuutqtuDOODsqLWDHNUWNNGCCGNNCCCsCCKCttCDOCzOMCCOzDOLqCz",
"pCCCCCCCpCUNpCLCDpqCpqDqmtNODCDLOUOCqCDCqqqpqpppmppqmpmmtpmtOQHtmpqtqqplpqqqqqqrtqqquqqpmllmpmmmqqqqppqqmmmlllmplmppmppqpmpppqqtmmmpmpppppqqqppqlmpmmlmpmmmppmpppppqpqqqtqqpmpmlmmqnmmmqmpqqqtqqurquuuuuqppqtutqHNLCtDONCCGNHNN0NKNOUNNTXTNNNKNWLLDDLtmCLtztCNDp",
"CCKNLNLNlCKLKNTpCqqCzpqCCDOLCqCNDOOzpqtzqpqqqpqqpqqppCDtqplpuOuppmlmppqqmmmmmmnmihillliimlllmmlmqmmqqqmppmpmppmmlllmpmmmlmmmppptppqpqtqqtqtttqttqqqqqqpppppqtqqqqqqqqqqtpqpmppplrurqqqqutrttqmlhmmllmmmmmllmpqqpqqqlmCCpqzCCppCWCCCKNNCNUNDGDNNUNCLUNqtLOUNzCNCm",
"NUNKCCLTNqCCDUTCDDCDDqmqOLqpqppmpLUOOOUNDCCqppqqpqqlpDDCtttpppqtutmpppquDuuuurqqtttuuuuxuuquuuuwqmpuuqqqqllqqpmpppqtqttptqtqqqqqtuttttttqpqqtttuwuutttqpqpqtutqttqtqtqtquuuuwEIInmmmmmmmmmqqttqqurqqqtttqquttqttDDCqqLDqmtDLpppLCCtCqppCCppCCCCpCmCUCCNLCUUCqzDN",
"ULCzqzCLZNLUKzCLUNDCLCtLNCqCDzmllpqqzCqmLDCDzpqCCLDqqNHqqHODqtHODDDIDqqqEDDDruqnmmqqqpqqmllmpmppmmquqpqupillpllmmmpqqqpmqplllppmtqqtqqppmlmpqqqqtqpqqpmlpmpqqqqtpppmmpmpqqpppmmpmqmmljmmpquuvHuuIvuuuqqqqtttqpqtAOMDrEDqCDLNDzDNOLLDDCDLCqCNOLCqllpCpzLpmsppqppZ",
"CplqNUCpLpzUNCLCUODztDUXDDLOLDDUDLNDNUODODCLHDCDDONLOUODptCttDttqtDqppmmmmmmqmnmlmpqtnllmmqtuqpmhhilihimqmmmmmpplmppppmpplilmpqpqttttqqptpqttqptppmpqqppmpmpqtquqqppqttuuutuqpptrqrqqqqquqqtqppmmmmmmpmmplilqtplmqqqmmmmqqqqqqqDDCDLDCLONDDDLDCDpCLqpCClCCllCplD",
"zqzLUULmmmpzLUMzCzCqpLULLCCDCCNVptCqqDLCOCqLOLCDpppqCDCtmpqpqtphqqpilqqmmqqtrqrupmmtqpmlpmmqqpmmhihhhehhpqqpppqqqqtutqtqttqttutqtqtuutqpttquutqqmmppqtqqpmpqtqtutqqtqtuupppmplmqmmmmnmmmililmpqtqqqqqtuutplpqtqmmmnqnmmmjlimllmqpmptqpqDCqqqqqCDCTUKLCzpTUCmKtlp",
"mDSULzpqhDYLlzNzllDDmDNlCpmDLtmllqDCqCqpLpmCDtmpDqqCDqpmpttqpttppttqDXIlqrDEDruEIuttuuuuIutqqqqtqqqmmqmmimplilmlhlmmllllmpqpmlhhlmpqpppmlllpqppllllmmpmpmlpqtqtqppplmmpppmmmlhlmmmmnqqqqpmmmmpqtqqnpmmmilmlllhhhjijqnlimlmqqmmlmmmpqpmpqmmpqqqDOlCLCNpoKq0LoCCpN",
"qmqqDOOOuMOIuqDICqpCOOCmDCqpCqplmqpmtqqMDqtuqpqHCCCDOOHuOMEDurDEqqqpqtqputqqqqquqrurqnqrqqqnqmmqmqnmuvtqpmqqqmimmmpnmlmqmmmppmllihimqqnmmmmmmmmmnmmnmnnqqqrtqmmqnmjmmmmnlmlllmpqqlmpmimlmlmmpmlmmquuqmmpqmmmpqmhjijimnnmnmmnnmmmlzmlmpDqllmqqlmmlllmmlmphlmmmpmm",
"mmmmmqqnqturqtuDDDCDNODCOMNLOODCHODDDttOIDOOOqDOONCqtDOOqtuqqpnmqqpmmpmlrqqqmlmqmmmmmmqrimmmqqnqimlhmmmliihmmmmmmjmmmmimpqpppmmlunmmnmiimmnmmmmmnnmnmmmnnnqqqmmmjjlmmmmilililmqqmilnmlmmqmmqqmmpqqqqqpmmmlmmqqmlmnnmnruuuruuqnmnqLplllmlqqqmmiiqqmlllmqDIDtmlmmm",
"mqpqpmmmmmqqtDMOmpmpmpmpztztCzqqqpqtqqqqpqCDDpptOODCtqCDqqmqqqpmmpqpqquqpmmqqquEqqqquqmmmnmmqqmmmqmiimmmmieimqqquqquqqqqmpqpmllpnpnqqqqqnqqqnnmqrqnnqnnquqqrqmilimjmmmmjlilmmpqppmptqqqqutuDutqqqqpmqqmmmmmpnpmimpmliiiijmnqmimqlCmpmptmqDDqmmpmllqDDtqqpqqttttq",
"qqqqmmmpllilmqqqpmpppqqpppqqppqqpmqHqqtpmpqDDqqqtCDCtqtDDqpmqqqqhilmmpqtmmmlmimmqnmmnmiemqmimmihmqlehihiqliilmmimjmmpmmmtrtqtqttnqrrqmiiiljmmmmmmmnqqnqqqqqqqqmlmmljmmmpqqqtuuuuqpquqqtpillmmlllqmhehlmlihhhhiedaeeeeiimdeiiiiiihllmqqDqlqDqpqqqpqqqtqqtpquDDDqq",
"qqqqpmpqqmmmmmmpqppqDLCqpqmpmmtCDptDqqqmqqqtDtqqpqqpmtMWODqmqqqmuuDtqpqqutqqqqqqIuqqquuuimpmqnmqimmimlimmlheiihedehjiilmhedhhhhhlmmmiheeddddddeeeeimmmliiheilmmpjiiiiimmimqqmlmplippmmpicdehhhhdlhddeehiiheiilllqqqiheedmlimmihehlhpplmhhqqpimmipmpqqpqqtqmpqqtD",
"mmmmmmmmppmpqqqqpmmpCDqpppplmpzLDqqqppqtCtqtqqpmttCtppqtpmpquuqmllllhedhihiiiimmiljmmmliiqqmmqqqmmpmqqmmliiilmmiimmqmiimliklmpmmimlieiileeeeeddeeeinqmilmilillmpijmmmmmmhlmlihhihhllklmlhlllppmmiiimmllihiehhiildhiilmqqqmmmpmihdlhmplpimtqlilmihlpttqmmplhillmm",
"hhhhhhhhihlillmmpmppqqppqqqpptDDDtmpqttEtDDtqpqqqqtqpliiilmqCDqmllilmlllrqmpmlilimquqmhehmlhiiheililmihhimmlmmqqmmmmlihiililllllurqiheieimmliiiiiimpqpmmqpqpmllmjmnnmmmmmqqtpmmqllllllplhllllpplpqqqrqmmhhhehehelmplillmmllpqpppmmlqDqDqtqqmmmmlmliiilpDDqmlkedc",
"qmmmppmmqqqqmmlllllihhilhhhhlllllmliqlelhlmlhhilmlihhilpmllmmmmlmllmqppqqpmqqqqqnqqmihimqunmmqmlimiimleeelmieimqiiimnqqqlmmpmlllmmmlmmmmiliiiiimlimqqnppmmmpmllpmmmmmimnlmmpmmmmllplllphllplmpppuqqqtqqmqqquEDuuDOEtppppqpqqtquDOOqDCqqlmmmpqqpmllllpllmUtlkilpq",
"qqppqqqmqDCpmqqpmmppppmmppmmllmtqppqpmmllillllllhilpqpqtqpptDDttquDIDuqqqquvuuqqpqqpmqqpuqppqqqmmlimmmilmmiimplhmimqqmmmqqpqppppnmmlmmmmpmmpmllilmqmqqpmmtqmlpplmmmnnmmilpqqmlmpllpppppqppqCCtqpmmmmpqmmlqqmqqqqmmlmmpqqDqtDDtqqODDqqqqqtCDDDDOODDDCqqtCCCLPODqt",
"OMDDMNDDOODuqqqqppqqDDtqqqtDDqtCDqqqqppqqppmqqqqmmpnpmmpqqqDODOOODCqqqqquqqqqqqqqqqqmpmlpmmmqqqqIuqpmllmuuqqqqniqmimmliiiillppqpmlilmmmlrpmmmlmqmqqqmlillllhhllhiiimmmieiihhhilphlpqzCCCpppqzpppihllmmliimpmmmilmlllllmmppqDDqplmpquLDDCqqqCqqCDCLDCqCCDMNDNLCDL",
"ONNLDLONLCCCDLDDDCDDLNLDNCCqqppqqutpqDDDOEDuqqqqqtqDutqqptDDqpqCuqmmppqtqqpmmqqqllllmpmlmpqqqqqtuqnqqnmqnqqmqqqqrqmmmmlmqppmmpmlmppqqqqqqqqqqqmpimqmiiiiquqpmpmhmmjmiiihliliilmmhhlmommmpmpppmmlhiimmllilqqmpmlmlmilmmmqmnquqqleilmqqqqmpmlmpmqCqCLCCDLLNLDCCCKO",
"qzDCCCzDCmpLUOLNUOLDCDLOLtmppqppqCqmpDODDHDtqppmmmqqqnpptDHCqppqDttpmlliiiilmljlllllpqplhilllklihilmqqqmmpnqquuurqqqqmqqqqqtuHIwDuDuDDutqquDuqqmquurqqtqqqqppqpmrqqnmmiipnppqpmlpmllhllpmlmllllllmpmihiimmmmqqlmiiimmmmmmmpimmmiiihhililmllllllmpCCCCCLNCCCLDCDL",
"ptDDCqCzDqCLULCztDDCmpqDppqNUOzpqDDpmqtmpqqqqpmpqnqqqpmlmmpppppqpqqqqpqqpqqqqqqnmllllmlhlllilihhiilmmmlilmmmlmmmmmmmmqqqqqquIIIDODDqqqqntqqppqqqqnnmmmmilmpnqquurqqnmmmmnppqqqlillihllmpmmlllilhnqqmihhlmmiimmhelilmiheeiiiiimqmmmpqqqtuLDDLCzqCmpzqpqCqzCLDCCCC",
"mpzzqqqtztqDDCpmlmCtpmpqCqtDLDqptDtqpqpmmpqtmmlmpmmqqqmmllllmpqpmppqtDIOEuuqqquuuuutuuuqqpppqqqpmmmmmmmlimliiiiheimmmmmmmqpqppppDDqpmlmlmmmlilllqqmmqqqmlmppmpqqmnnnmmnqpmmmpnpmmmmpnqpmtqqqqpmpqqqmlimmqpilqmihmiimjeeelmjlmmmmdhiillilmllmplllpqCpmompCDCppppp",
"pppqztzCqCCzCzCqpqzCCtzCODpppmmpqqqqqtqttqtqqppqjmlmqqqqtDDttHDtODtqqqqpqqmmmmmplmllllllllmmlllmqqqmmqqqmnqmqqqqmmnmmpnpehllmmquDuqqqqpmhlmmmmmhijjjmnmjmmiiihhhiimmmnqrqqqtuDuuEHvDIuuquuuturtqqqqpmmqquqqquqmqqmmnmjmnrnqnnmmjqrturqqtqqqCLLKLzCCCpqCCNLKzppzp",
"LDDDCLOUNUODCLOLOLDCDLNOCqzqCqtqDttttqtDmpqtqtEPIDuEEDDDqtCqpqtztpmptDqmmnqqurqquutplpmpmppllhlpmqqqquqmmmmmmmmjqruqmmmmmmmlllptuzutuuqquuqppqtrqrurqqqnpmmmmmmmimmnmqqrqrDOOOIDurqqqqqqqqqqqqqqqmqmmpmmmqmpqqqEErnnnmmqrqnqrqnuqqqpmqtDODzCCCzCCNLLCTUUNUWUNUUN",
"nDDmpDLDMMLDUOLUCNNLNUUCLKNUNLKNCNULUUULNCCCCppBOErqpqqqmuummqutOuqruuuuIuqqqtrtqrurrquvuEJuqnqqrrqrurqqnqnmmmmmppqpqqplpppppptDKCKKKKCCyyKCCByytqpppqttpppppppppppppmmpqqqqqmquvqqnnqqnnnmnqnmmmmmnqnmmmmnqqqqqmnqqqnmmlqtllllolqCqpliqpmpqzpllmmtqpqqCCDCpoqCC",
"mmmmmmpqztppCzpqplpCCCCyppsCCpqCpypppKCsplopypppmmmmqqqquEIttuDvEuuurqqqqqqquqqmimmmjjmmqruqnmqqmjmnqrrqvuuqnqquqqqqtuqpllmmlmptKLLLLSTSNTTTKByBqpmlllmppqtuDtttKLLCCqtztqqqqmqqruqqqnnnqmmmmmmjmmmmqmmiiljmmjiimjmmmnpplqppoppCqCqqqppCLCzCDCqqOMDDzqqqlmqCqplk",
"DrCDDqzDDCqzLDqCDCCLLpptCqCCCzCCzCCpCNLCCzqCCCzqDDDDDEDDDDutqqttqpqppllmlllmpplhmjmmmmmmmmmmljmiiiiimmmmqqrrqqnnqqqpqqqpuuutqqqqCKLLKCKKCKTKCyCKDCtqtttqqCDDHDDDMNLLDLDOqqmmqpmmnnqnqqqnrqnnnqnqmmmmmmmlmmmilllijijmmmqqpqppqspCLDCzDLDLVNDDLDLDDDCDDDCqDDNCCCCq",
"nqqqzqtzDLLNUOLOUONOKqqCLCCLLCCCHLDDNUUNLNLLDCCCUIDtqttqtqqpmllmilllillmlililmlljiiijmjimmjiiiifliiiimmmiimmnmmjlmmimmpmqtqqpmppzzCCppmppyyyyoyCtqqpqqtqttDCtqtqKKCzCqDDqpmpmmlmimmnnmnqqqnqqruruuuuuuuqqqpqpnmqmnqnpnpmqpmpColBDCpmCDCDNLCCqCqCmpmqqCDCDCqpptCC",
"immlmqmlmqqCDqpCpzzpmqCzqmpqqqnqqqqqzLDqqqCqmmpqpmlimmpqmmlmlillmliilmpmtqmllmmqiiiiliiililillihiiiilmmmqmiehjnqlmmmmpqqhmmmlmpmqqzpmllmCCpoooollllooolopppololpqqppmpqpmmpmliimilllilmmmiiimpmpllllhihlpmmmmpqqqqqqqnmlqplptmklqqmlpmpqCqqqpqppqqtqqppqllpqCqlk",
"muqmmqqihllmpllpmqqilmqmliimmppqilmmpmmlqqqlihiilimppqmplllllmpppmlhlpmlppmlllihmmmmmmmmiiihilliiihiiiiiqmiiiimmimmmmnqqmqtqmppmmpppppplypllomolppomplolplolllppppmmppqqmmpmliimmmmliillmllllmmlqqpmpmppmlllmpppnqqrqpmilmppqpklpCplpppCqCzqpqpmpqzqmlmpllpCCtol",
"nqqmmqmlmmllqplmmpqpmplimllmpmmqmmpqpmmmqzqpmpmlmmlmmllhlmmllpplmmlilmmlilllilhlimmmmiiliimliimlmljiiiiimjmlmiieijmlmmmqqqDpmmmhqpmmpqppplompppppolllllkppppppppqpmpqqppmpmpmlmmppmmomllqpmmpqpmpppplllmppppomlpmnnqqmmlippmppllqqpmpqqLpqCqpppmlmmpmmmpqmllllll",
"qmlmqmmmqqlmCqmlpimqDqlmmlilmmllpqqqmmmqilmmDMDqDqpmlllipttmmpmlmpqpmmpmllllmpqtmmqqmmmmqqqqmqqmmmmnqqqnmmmmmmliiiljimqmmuDqqtqqDqqtqCqmpqtppopppppppspqppqqppompmpmpqqmpmmqqpmppmpqzqpmmmmpqqqppqppllppppppmpolqqqqqppmiqplolllppllpqqCqCzpmmpmillmpqpqDqopppop",
"qnCEqllihlpCCplmqmlmqmmqtmmpqmmqimqqmmmmlnmlmpmmilmmppqqlmmppmptqquDttuqqpmplhmqqmmqmiiilmmqmmlllmmmpqqupqqqqqqqmqrqqqqrqqqqqmqqqpmqDOtmtHDplttplppppomoolloppmlqqqtrqqqqtDqqDDqppmomlmllptCCzppppllpplllpppplmpqpmqDDmllmqqqqqpmpqmpLLmDCqCqqqCuqmpqCqpqqpptDCp",
"ODDDqqztDzqDDDCCDDDLDqtDqqpqqpqqOqmlmpmmmpmmqqmlqqqqqqpputDEDqppplpqqtqppmlmllmtmiileelmmmmmlhhimmpqmlihiheeddeeeeiiijmmqqqqqqpnqqqqtDqplqCqpqplopppptCCCCCCCCGCDqqpqpmllmmlmpmmppqzCCCDqyzzCCCCDDqpCtppDCCCqpppqqDDqlllmpmmlmppqmllipCCqppppppzOOMDDqpmCppCCppt",
"AqqmlmCmDqppzqqqlqLCppmpzCCCCDCCOzqpmmDUqCqqLDqmpqqCqCqzqpllllmpmllpqzqlDCtDDtCDtqDODuDEuDHDuuuHruuuuqqqqqqmpmqqmnmmmmmnmmqqruqtquDuruDtDDutqtDDqtttqtDDqqtCtqtCEuqquDDqtDDtCDDCqCzCCzCzppllmppzlllhllilpmlpqCCtMDCDODDtqAttqDDDDpqtppzDCqqzDCDLqDDDqpmptmptCmpC",
"DDDzqDDqDDDOOLCCzNUNzCCCpzzqpCzpDCDqlhhqmqpmqpmmlllmppmpDqmlptHIODLUNOODCqqDCqmpmhlnpmmlhimllimpmpnqqqquqqquuuuururqqqmmeehmpqmmillillmmqpmmompttqqqpmppppppppqqqpmpqDDDqzCqqzCqppqpppmllllompmlpppptCsthhghllppmhhlqqmillmmpmmlplpzqqCzDCCDLDCDpqDDqqCDMNDLNHKO",
"DDMLDLMmzLUYUOLOKNTNLNNTNUYWTUYUUNLUUNDLCUUUNLNNVUOUULHDDCDHODDtllqqmmpmpllpplilqlillmpmlmpqmllmlmlihillhhllmmmmqnqqrqqqmpnqqqpmiiihimmlilmtqplmmpqpqppqmlilmmplmmpnmmlmmpmllmplppqCqqpppppqtCtClpmpqqqqtqpmlhihhmqqmlilimpmlihhihhehpDppmmpplllmpmmmmmpCDCtCLNC",
"nnpmillimqqCqppDBpoospypsCGCCCCCppppppqClCLLDtmpCqpqCqpqlmpmppllppCDpqCCqqqDDppqqiilmqqipqqqqqppmpqqqmmlliiilllmmmnqqqnmqqqqqtqqurqqquuqpptuuqttqtutqqqpmllimpmlqqutqpmqDDtCqCzCqCtzCtpptqppmpCDqtqtDDqDttqqpmllllmqpmllDDCqqtDDpppllDLlmlllmlhhiihhhlhhlplllCtl",
"qmqqiilmpqqCpmqCBolBBooBBBKCBoBKCUUzhghhpCCCCCppCpmqCqqClllllmppmmqCpqCqtpqCqppqqmqDtDtmqqtquuDulmpqqpqqppmllmmmpmmljliihihiiilmqqmmnqmimmlkilpqtqtqqpmptqqtqtqqqqqrtruDCqqqpppzpppplmplmpmlllpCilihlllpilmpqtqqqppCOODqztqpmqDLDCLDCLDptppqCqpmmmpqrCtqpqtqCNKt",
"qqDDpimpqqCDCtqqCooKColyCCBCBosCpKColppkCKplpCppUzpzzppqlpCtqtqpDtCDtCDtzqtzplmpqpqqlmqqtqmmmpmmmpnpqquuqqqttqqprqmmmmmmmmmlhilliiiiimheeiihhilihiiiilmmillmliliiihhimllmmllllllhihllllpllppmlpqlmlilmmtmllmqqmhllmpmhlmqqqmlilimilllmDUzqqDLDzqqDDLODCqmppCCtCL",
"LDLLDtqCLDUUCqLCLCqttqptDDCDDtCDqCLDCDOUDDDCDLLDuDEHuqqtDOEtqCuqtutqqqmltmlqtmllimmmimqmiilliiilnrnjiifbmnnjjjjijmmqqnieeeeeiiiijjmqqniiedeeehiihilhlilhhhiiliedheeehiiiiiimmmmimiiiheemllmqmeellhddhlliihimttqmpmppqqmllqpmplhpppllhhlmllmpqppqCpmlllqNqqqCLLDC",
"tqpqqppqpmqClmNVqpppmpmpDCtCttDNLDCqpqpmpqCDLDCmDqqqtuqpmpqmpmmilmpqtqtqpmlppmmqpquqqqpmlliihiiinnmjjjnmfiiffiffmjmmmmjijiijnqnqqqqnqrqqmmliiilmqpmihlmmmmpmpmlleeeiiiiiqmimmmidaeiqqmqqmmpqqmpqLqmlmppmtplhheddddddhlhhhmhhihhipqqqqpqCilpqpmlplllmmlillllllmpq",
"ppmplillllqDmlptmmlmmllmmlillllpCplilmlhllllpCqptplmpqqnhlmlmtpmppqtutqqtqpqpmpuquuqqqqqrqqmmlpmmmmiimmmifihijmmjmjjiijmiiiimmnnnnnqnqrrEurtuDEPqqplmmpqpmpqqqqmnqqqrDuujlimqqrrqqDEDmiihlmqppqqDqppquztqqmmmmpqmlllmpmlCDplpplhhhlllhhghlzDqllmpllllmpphlpqpmpq",
"qqqpppmpllzDplhdkhhllllltpllllmpqmllmpqmmlhlmzDCmqqpmpquqqppqDDuqtuutqqquqqpmmpqqqnpmqqquutqqqnpnqrrrrqnnqqnqqrnmmmmiimniieeeeiieiljlijmheeeeillqqqqmlieihiimmmmqmmmqrDErurnjmmqjmmmiedeeilliiilehhlmmmlmpqqppmplmppppppmqqqCODpqqqqqqpmlmtDCpmpplhhlomlDqplhhpL",
"ppqCCCDCCqpppmmqqqqqtpqqCqpqtqptDLCppqtpqCqCDCqlmqqqppqtDtqmpqpmpmmmmmqqqmlmmmllillmmmmmpmmmmliheiimnqnquuurqqnmmnrnmijmiifeeeeeeefieeiijliiheehehilmihhdeddhhhhihedehilqqmmleeeeeeihhiihhlihhhdddddddddddhhhededkmmlilmhlllipmhhhhhllmppmppqpmmCtzDOOCpqqqqqmmp",
"mpqpmpmmppiimppCzqqCzqpqplmpqtqpqCqmlllipmpllmlhmlhlmpmliiilllheiilihilmliilpqpmiilqqmliihillihdeadddeeiijmmmmmiimqnmifiiifeeeeeiieeeehieeeedede#.#dhilmheddeehhhiehehedaddiqqldiiiiiliidhhhihhhlihedhhlehihedhhdipmhhhllllhdhlhlhhhhlmpqpillhhhhhhlpzqpllpCDpll",
"ppplihlhdiklpidllhhhhedhlllqtqqpiilhhihhhihedhlmlihilmlhehlmpmllmmqpmlmmqpqqtuqqpmqruqpmmmmmqqmmqmmilhilhhiilmppmmnmmiiiiiiieeehjiieeijjhfhehiimllhihdddihhehhiieeheiheeeeimmmieadehiilmhehllhhlmmmlllqqDDqmihddhhhhdcddhdilhlCtilhhdhhlCplhhhhhhhdhlqDCmhdddhmC",
"mpmlhppqlDLOUCtUqmlllhhlhhhmqplhlllllmliimpmllllppqpmlmpttuDuqtqtuEIvuuwuuEuuutqvuquuuuvutuuxIxuuttuutqtqqpllmmmqrqqmnqqqqqqmmmmmmjmmnmlnmljimmmmilmmiilihehhlmpihhiimmphlmlhhipqqmiimmmlhlpqmmpilpmmliliihihhhhdhdhhilpqhlmhhlehilllhlmCqmlhehlhllllllehhlpqmlp",
"lllllllllpqqplmmzLLqqmpzqtCCCCDDDMOMEHDDtDLHDqDDEEDuuDEIOOEDDDtqqqtpmqurJIxvuuuutrtqquvIuuqqqqnpqtvIIIuuuuxutqtuxvxvxxvvrqqnqnlinqqqmmmnmqqmmqtmpmpmpmpmmmpmmlilpmimpqmimmqpmlmmnlilmppqqppqtqmpmpqqpmpqppmllmqqqmpqpllmhpqplpqqlllmlmmppmllllpmpppmpllhlllpqppm",
"CDDDCCzCCCDLCCCDCLLKLLDUCDDCqCDLDtCqCqqmqtzqqqpqtqqqqppqqtqqtqmmlmmmmllilmmpqrtqmmqqqqqqqqqqmlllpmlllpqtutmpqtqmurtrqqmmqmmmqqnmnnqrnqqrmnqnqqruqqqqqqqtqqqqmpmqmpmmqqtqqqqqqqpqqnqqqqqqtqqtttqtqqqqpqqqpmpmpqqDqppqqqppqCDCqCCDDDDNDCDNMNDNDDDDCDDDDLDLCDDDCDCD",
"zCCCDqCtztztqzCCqzmpzqmmmmpmmlptqmmpqqqqqqqqqqmmmppmpmmmpmmpmmpmqqtqqpmmiimnqqqmmmmqmmmlmpmmlmljllhimmpqpmllmpmlmmmmnqmmqmmlmmqmmnnnmnmnqmnqmlmqqppmpmpnpmmlmllmqqqqpqqttqmpqqqqpmnqqmmqmlmmmmpmpmmmmmpmqqmpmpqtqqppCDCqqtztzCDCtqtCzqpqtqCCCCzqCzCCDLLOCDLDzqCD",
"ppqpmlmmlllllppmzLzqzpikhlllllmpmmlmpqqqqqmmqqqmpmpqqqqpmppmpppmqqqmlmmpllmmpmilmpmmlmmmmmqmmilmllillmmlhilllllmmmmmqqqnqmmjlmjlmmiimjlimmmmmmmmliiiiillmmliehiltqqppmmmmllllmmpnmiihhmqqqttqmllllilpqpmpmlilmlmlpmlmztmlllmpqqpqpqztpmplpqqqqqpqqpmpppmlmppplpq",
"qqzqpllpllmlmpqmpKzzzpmpmpqqppqqpmlliliiqpmpqqpmqqqpmpqpmpmpmmmpqqnmmmqqiiiiiiiilmmmpqqtmqqqmiiiqmheehiiiimmmmmqqqpqmmlllmmmmmpmieeimmmmimmmnuqmillhiliiqqmliillqqmpmplhhhihhhlmqqiieimuDDDzpmlllilmqqpmllhhhhillmllllpllllmpqpqqpqCqpppmmppppqqCztqplihlllmppmm",
"qCCqpmmpmqqpqCzpmzzzzmlmpqCCqqppmmmlllilpmlmpqqpqqmmlilmmmmllllinqtqqqqqmmiiililmmpqqmpnmmqmmlmmqmmmliihmlilqqqmqqnqqqmmmmpqqqmmmjmmmnnmmqnmpDqillimllllqpmlliimmllmqqmihllmillpnmmiiimmmmihhlpqmmmpqqmliiliililllmlllllpmlppmpmmllmpmmmlllliillDCDCqpllmmppqqpp",
"pqCqplmppCCqpqCqLLLzLCmpmlmmpppmlmpnmmmqmmmmnqqqqpliliilllmllilmmqnqnqqmurqmpmnmpqqqpmmmmmmpmqqqmquuqqmmnmmmqqqmmmmpqqqqmpqqmmmimmmmmmmmqqqmmqmillmmmmmlilmllllllllmppplllpmmmpqmjiiihehhihhiqrCmlllilihlmqqmlllilllllllmlllmlllpllmppppmmpmlllmzqzqpmplmpqqpqpp",
"qCDCqpqCqDDpmpzqKCzpLLpmlillptzqmpqqmllmqmpqqquummmlllpmmpppmmpqqqqnmqquqqpnqqqqqmmmmmqtutqnqqpmqqqqmmqumnqqmmmmmlmmmmmlmmmmmlliifiiimjmqmmmqqqummmppmmmlmmmmpmpmmmmllllmmmmpppmunmiiihiiiliimlhllhhhhhimqHDqlhhlgdlmlhhlhhllhllheghililllmlllllplmllllmlpppmmpq",
"hlyyzKmhlyyzyKKKCLKKCCDLttqtDMONArADEDqDqDttDONCODuuDEuuuurruuqmrrrrqnnnnmnnnnmjiiliiimmmmqqqnnqqnmjmnnnmmmjmiifhiilmmiieiiliihhfeeflmmqquutpttpimqqqmmlqpmqqmmqlplllmllpolllopshlmlhlllmllllhlmpmlmptqlllihhhhlehhlpCqlhhhhilqzqttDtpmlhppmlilqpmllmllpppmpppll",
"zKSLKSKKzKKSLKSSNTONLLNLLDDNDHDuAqzDzqqqCqtqCNDtqnqqqqnpmmqqmmlijiijjjjiiifiimmmmiiiehiiiiimmiimjjiiiiiiiiiieeeieeimqqqqilllihedeeeimmpqxupqwIwsHDDDEIOIDuHEHuDIqqtpqCCpppsspoopLqppqqplpmmppmlpmpmlmpmlmpppppmllmpmlmllmmmllllmlmmmmpqqmmllpmlmpmpppmppqqqqpmpm",
"U0YYLDKCUSUTLLLLLLLLCCqplllmpmllmmmqqqqtmpmlppplllmmmlmmmmqpmliliifeiiiifeeeijmmmlieiiieliiiiheihiiihehinqqmiiimiimmnqqqqnqqpppmnmmnnmmmqtqqspttqpmpqtqpqtDtqqqpzCCCNLCpCLNLCCCCLCqDCpmqpptDCtqqqqtqpqpptqppqqppptCqqqDDCDDDDCqtCtqqtqDDCuqqDDqtDCDDNDCqCLOLDNU0",
"hllppypzKDKzCzypCpppplihmpqttqpmmimmmmlmmmlmomllmlmmlmllmpmmlilimiiijmjiiiiiimnqmmiimmmmmmliieeheiiiiiimmqnmmimmmmnqqqqqrtuuuuutuqnqmmiilmlkhlllmllmqpmhimmmmqpipmmppCplppppolpCmpCqmllqpqCLDDCCDCLqzCDCCqpqpppqqpmpCLLDpqpqpmpppmpppmmmlqqmpmqDCqpqzqmlqqpmlihl",
"hhhmpplhllllllmlppmlpllhmmliheddmmmmmhedhlllllhgllhkllllmllkilkhmiihiilimmmmmpmmmqqqmpqqmiiihehiimmmmmpqmmmqquqqqrqrqqqqtqqqqqpmnjljmllmmlhdlwsdhhlllihhdhhhptqlmlillmmlllllkloplmlhltphlmpppqqzqzppqCqqqpqqpmptmlillmllCCtqppqqhhhiiiliimpmpppDDCCzCCqplllkhhhh",
"pmopCqlhllllllkhlklllpmlttqpmlllqqqDtnlmllmppllhqplmpppltpmmppppmpmmpqqqttuutqqqqquqqnqqmmlmnpnqtrtqqqqquqquuvuqurrqnmnnmmlmmpmlmmimmmmqpqpltIHplmmlihllmllmquplqmmmmomplpppmllllpmhlmphillillmpmpllmpplllpqplllllplkhlmllhhhhllmlihhllplmilqqmmhihhhhllmllmpqpp",
"hhhlqqtqCtqpqppmlmpppppqIDDutqtuDDDMODDDIDHOOututqtCDDDCDDHCDDDDuDDuuuHIuvHIutttruqqqpnqqmmqtruuuuqqqqqqqpmmmlihqqnmmillllllmppmqnmnqnqqmqtuutqttuHuuuuIuuuwDuqqDtqtqpqulllmollhlqCpllmppqqpmlmlommmlmllpikmplhlpppmlhltomllllpqqmlihhililhipplhlmpmlpqpqpmhhhhh",
"ODqtttDNDDDHOOOHLNODDCDDUWPODuqtVUMODCtDtqqtqppqptNOOOONtDNNNCDHDIOEttDOuwDututuqqqmqnmlmmlmnqmmqmllmmpmlillllmmiilmimmqqqpmppmlqpnqqqqqplitulhlhimppmlmpmmtqppqCDDDtnqCDttqCHDCDqqqCDCqDMNCqtqpmptpllliNmhlppppplhhhhllqtppllmpqqqqppmmmtDtDqmpmqCtqqCDzCCtpqDU",
"OHCtCDtqtCDCqtqCtzCLDDDHEDDDqmmqDDDLOEqpmpqqqpmmllpDNCtNqtCttqsppqqpmpqIpquutllpqqqqmlmpmlmmmlililmmihiiilmpqqqpqqqmmqpqmpqtqtqpnmpqruqnqmmllmqtqplptqphlmqtqqppjmqAqilqLqmtqqCqqppqqqpmtpmpqCCtpqCDDDtqtCuqpqDOttuCtttIttttttttDCuDOVOOHMLMUMDMHLNMNNLOLLOMUULC",
"CDCtqttCDtCtqqtqCqmlmmqDDuDtqmpqOOOUUODqtqqqqqttppqHDqpCNCqplppqtDHDtqtDttuDtpppqquEutqmqqqqtqpqpqqqqqpqmpqmqqqnqqqqqnqquutpmmpltqqquuuuqpqqtttqwttuutqquHIIutqqqqDDAqmtDmpqlmppDqmlpqqpDzppqqqqCqqqpqzClpqtqppqppptttqqpqqpqppmqmmpnppmqqqCODqCppqCDDCLDLNDCDCq",
"qDILDqDEODqqppmptqqqplmpmlmmqmquOOVWXOODDIHDuuvIDtCDNtpmpmhhhhlppqDDtqtuHDIIuqqutttqtqqqtqqttqqtnpqqpnqqqrqqqqutrqqqqtqtuuuqpptqqqqqquuuqqpquvtqmppqqqtuuDHIIuutrqquunqquqqtmmmpODqpqCHNDDqqpptqDCpmppqClmptttqqpmpqCqppppqqqpppqqqqpqqpqtqDODpqDqzLLLDDCDLDCCDD",
"tDDDqpqDDtpllilhhhlmllhhlilmmmquLNOUONDDDDDIHDDuNDDLNDqlmplllllmntDEIuDIIIOIHuuIOvttuuwutqtuuutuuurqruurqtrtruuuqtruuuuvtuHuIIutqqmpqqqtuqmmqqqntqqqtqtIqtqplhhdmmmqqqqqEDDEDttqCttqtqCDLHDCqtCDLCztqzDDqpqqCDDHCtqtCttqtttttqpmppqqqqCDqzCDMCqDLCCDNLCzDLNCzDLL",
"qqpmllmpDqmiilhimlmpqqqEqmmmmlmntDNNDtttqqttrtqqtqtDEDqlpmpmmliilmqtqquuuuEIvuwIttquuHtpttuuDutuuuuuurqqqqqqqqnmnnpqqqtuDDEHOHtpuuqqqqquuqmlimmpupppppqqpmpmpmllnmnnrrruDqrODDqmqCNDttDHOODDCDDDDDDLNLNDLDttDDHHCDLLDzqqpmpmmllliilllmmpimqqqpqOLCzLOONNOODqqCqp",
"qqqpmqpqqtqqpqqqlmpmmlllmlllmmmmptCDtqqqqqpmpmtumqqqtDqililiillllmpnmmmmqqqtuqqummlmppmlqmptqppmnnnmmmmijmmjimiiliiimmpquutqquqpuqmmmmpmqqqmliljlhdhilllllmpqttqjimmnnmmqlmqqqplpqDtmlqDCCtqqpppppCDDCztDCDCCtqpmpDULpllhhhhllmmlmmmmllilmmlmlmDCqtDLLDCLCzpCCCq",
"CqqCAtAqCzDDDDDLttuDtmliliimmmqqppttttqpqqnpmqqummmmmqqmmmmmpnqqqqruutqqmmqqqqqqtppmpqtqpmllllllmqqqnmmmimmmimmjlllllmqqpqplppsqtmlhmmmiqqqmmimmlhhlppmpppllihegjmmnmmmmnmmqmmnmlllkhhllqqppppmlmmmpqppmqqtDtppmlmqCCmliehhilmptqqpqqqpmpqmllilqpmlpmllippqqqDCq",
"mmqqqmmmnqDDzqzqqpmlmlpqqqqqqqpqpppqqppplmpmpmmpnqpimqtmpmqqnmliimqqqqnqmmmqqmmmllmpqpmltqppmlmpmnqrqmmmmmmjmqrrqmmmmqtumqqqlpptItmmquqmqqmmimmmqqpqqpmlppmpptqqnrururrnuqqqpqtupptqqpppqppqtutpqqpqppqpptqqqqpppmlmppmltqpmlllmmlmpqqpmlliippmtmpqztpqCmqqpllll",
"hlmppmllhhlillqLmlmtqlimlqmmpmmqpCOUNCqtuHODttuItpqtCtttqtqtttppqqnrrruruqqruuqqqqqqqruuqqmmpnqqmqnmmmiimmiliiihhilllmmmqtqqmmlljimmiiilmqqmllilmllllllltqpmmmpmmliilliihihlqtqDDCDDCpmqtqqtqqtqDCppzCzzzLLCppzqzCDCpqCLtCDCtCDCturuDDuqtDqqDLCqCCCCCDCqCCqpppqq",
"illllllllhhlllhghilqqliilmpqqqmptCCpmlpqpqtqpmqqDtpqqqqqppqqttDDEDuuqqqqqqrtqqqqqquuDIDuDuuuuuuDutuuqqqpmmmmmmmmppqqquuIuuuqtqqmqqnmmjiinqqmpqmlpmppqqtqtututttqqmqqnpmphihmtqpqmllppmplpmlllpppqpmpqqpppmllmDCplllmtDDCzCzqmpmmmmljlllimqpmppqDKppzCpmpqpmmlill",
"pmppmllhhllmtqpmlmpqqpmmmpilpmiilpppolllllmmllllplllmlppqppmlmppqqnmmmmmmqqqmlilmqqqqqpmqqqqqqqpmqmpmmmippqqtutqqqnpmmmpuqqqqqqmnnmmmmmmmmimmqplmppmppmpmqtuuqppmqqqqqmmqttDOHqttqpmpqplllpppllllmpmpmlllpmlllmpqpllllhhqCCqppppliiiilmmhmlmpmpDpplppllmllllllmm",
"llppqpmlpqqpmllmllmlimpmCqmlmllpppCCtppmppqqqqpmpmlpppqtttqplpmmmmmmmqqqquuuqpmqpqqplmmqmmpqpmlmmlmmmmllnmqqqqqqqqqmllllmlilmmmlmljmmmqqqqpquuqplmpmlllllpqtqpmhmmqqmmlmpqmptqmpqqpllmldlllihdhhlmmpmlllmpplihlmhhhhdhlphhhdehilmmihilmphlhlqqlikhllllpmmllllmmp",
"illmqttqCDLCqppqpqqppqqtOOCqtqtOTNDCDCDDHDDDHuutDtDHDDCDDLHDDONHDIHDtDDIDIOOIuutimpmlmqtmpqqqpmmhiillljmmmmmmmlimmllilmqmlllmpmmqnpmqqqpqmqtutpmtuuHuuuImpqtqpllmqqqmmmmlmllqmlqlplllppmDtplhlpqqtqppppqtmhltDqlghhhllquppmllpttqpliiihillhmCphghophlpqltpmlllmm",
"ODtqqDLNtztDUUOLDLOMOMOMOOMOLqmDNNLLNCqpqtqqqqqpqtDOODDDqDDCDDHDDLHqquNDuuDuDtttpquqqqppqpqqqqpqmpmqnqpqqpqpqmmmilililmmqpmqqqqqqqnqqqqnllppmlllillmlllhlpqqqpppqnqqpmpqmqpqDtqtpppmpqttDDDDDDDDtttqqttDDtmtOOCqutqtIHtltttmlpppuqqqpqqqqDDCDpmCpCLtzNLtDDtqtuDI",
"0ULCDLDLCqppqtqpDCqCqpzNLLCCDplpCCNNOLplpmppmommllqDDDCCtDCqptqlmtqpmqDtppttpplpuDIHDuqpuututuDDuuuuuuuuqqqqqtqqqqqqqpqqqqqqqqqpmmpqtuttqmpqtqqttqqtqppmmpqtqqpqqqqqqqqmpqmpqmpqqplllmpmpppqCtppCqpptqtttDHONttttptDWVHqHOHutttttttuDILOLNLOUCCOCLNTOLOLLDMOOUXU",
"qppqCDCqmmpmmqLVUCpppmtVLtqzNDzOUOLNUODtuCutttuupqDNNCtDDOODDLDCtDNtptDDtDHupmptlllilpqmpmmmmpqtmmmmllilmmmmpmqmpqqqpmpmtutqpmmmrtquuvuqqpmpqttxtqtuuuqtuHIIHuuuqquuEuqpuqplmmpDOqlptttqHqlllqttppllptqppmpDDtplklptqpppllppppmlmqmpqppmppmCUCmpplpONppNDDDDDuqq",
"qCDqqCDDNDDNODCCqtDDCDLOCDLOLDDCNTXUOCCCttDDDDHDHDDDOOOLDHNOOOONDOODtqtCuHOHtpppmpmlmpppppppqqqqpqqqmmqqqqqmmmmlqqtqquutJurtrutqqqqqqtuutqptutqlmpqqtquuuDIDuqtquuurpqqqqutqqtqqDCqqtDDDLHCtqtCDDDtqtDHtDppqtqqDutttttpqHOItqtpptqqqtqqCqCDKDzpCCCCLUDCqLUOtqttq",
"tDLCqzCCODLLLCDDCDLDDDNO0OztOUUOLTUWUNDOCuDDuIEHDDNOUVOOOOOONNDDOOONDCDODHIDtlllqqtqtDDDtDDDDtqtuuuuuuuuqqtqtuuqqququuvuEuuuuuuqtqqqqqttppmpptttHutqqtuDDIOOOOIOJIIEuuuuDDDDtqqptttqqtCNtqtqtqqqtttqtCCqtttqtDHCtttDHutDtHtttuHuODuDDDDLpCCCKtpKCCzCCCDLDNDqqtDq",
"DLDDztCDLCqqqqqqCCtzCCCCNCpCNULpsCDCtCtCqppqpptqpqtDHDDCDCCDDNDDDDDqqqtDuDHuqpppptqpqtqpmqDDtqqtuqqqqqqppqqpmmpmmmmmmqqqlmmpqqqquqqpqtqqqplhhllmpmllmpqputuDDIIDEuuurqmqquDDIDtqDLOHCtHVONDNDDHDCNONODOOCONtCOHqDDHODDtDDDtqtCDDIDCttqtCCLNNUTLWLLNUUNLOONDDDDDE",
"qCDCtzCDDqppppppppppqCqqpqCCqpppptCCCpqqqpqmpqquqpptCDtppmmptDDCppppllmmpqqtttqtttqptqpllppppmommmpmpmiilmlihihhilllllmmililmmpmqmlilmpltqpkhhllhehilmliqqpqtqqptmqqpiipilmpqmllppqqllptDCqqppqtpqDDtCttDNDDtCqpqtDHCtptttttqttCtqpmppmpltzKNCCLpBDNLqppCqpqpppq",
"ppqtqpqqCCqpqqqppppqCtpspCCqllsDoppqppplppmpmptDCqpmtCqpqpppqqppqrrrqqqpilmqqquuDDHDIOODIDtqpplkmpqqmlllillllmmmmmmmmmmptpmmlmlluqllmqpmpmpllllplmppmlllqqqqqqpmrtuvqilqqmpqqmlihlllhllptqpppllpmmppzCqmCqCDzpmmkmtzqqqqpqpqqCztqpppqqpolppCNCopCzppmlpqqpmppmpq",
"mpqqpmmpqqppqCqmllpppqpqqqstCtCCmpppqppppppppquIOtqqCDtpttqqttqpqtuDuqqqpqqnqqqqtDDHDNHHNDppppmlmqqqpllmilmlmppmpllmlllmmmmllmmmtqpmpqppmpppllklppmliilmqpqqqqpmqqrtmllqqppqtqppmpmpqqtDCqtDDtpqtqqqLOLqCqqLDppCmpCtztztqpqpqppqtqppqCtppCLNTCopCCCCCpqCpppqqtqq",
"ppqDCppqCqqpqDCppsqsppsCCszCLLqoNNDDCCDDuDDuuuOUUOOHOOLDqqttCCtqqnqqrrqqrqtrtqqqpptppppqqpmppppppqqqpmmlmmmilmllmllmmlilllllmmpqmmiihhhhpppllkkhllihhlmpmpqqqqmmmmpmmiiliehmqplmlllompqqqppCtqptpplmqLCpqqzCCCzDqDDCCCCqCqmppmpqDtqpqCCqptpCKsloppqCCppmmmpmqtqm",
"pqCOLDDONLDtLOOCLNNLCCNUNNCCspsqLCppomppppqpmptupptqqppqppqCtqqtnqqruuuuqqqqqrqqipppmpuDpqptqqqpuqttutqqpqppmpmmpmmqqqpqqqqqqqqqutqpmmllqqppomppqpmpqtqqqtDDuqppqqqqqqqlmlltDqpplmppllmptmlmpmtMpmllpCCqlpCmmqqplpmpqDCqqmlmmpCOOHqppCLCpszCNLCNUCCzCzqqCLIDDOEq",
"qDDDDtCqzCCKDCzyHLCCCDCqDCDLtmllpllmqttqqppqtqppqDDppqDtqqpqppptplpzppzqlmpmmlpqDDDDNOODpmlllhklimmmmmmmimlilmpqmqqpuqlmIumliililllmpqqquuqqnqmmmqqpmlihlmqutmlmmmqqmpqqqquuuquuuuqquuuuIIvuuvuxqutuDOMDDEDHOUODDHHDDNODCCtttDNLuDEIEEIODDDDMLMMCqqpqtttptCqpqCC",
"pqtqqqqtqqqzCzppztqqCCqlpmpqCCDNpplomqqptpptDCuCpqtmmppmttqqmlilllpzpCLDDDDtttquONDCDNDtCtttDtDHEIEuqppqqqqmmmqpqqqqqqqqtqpmppqqpmmllpqqmqmmmmnmimpmlllimmqtqmmppqqqmiilqpqquqqqqqqqmpqqvutqqmmlmmmmqqtqqqqqpqqmllmllpppHODDDNIDqqqmpmmmqqqqquDDmllppqqtqplpqDtm",
"mqqppqCzCpppzCBpmpqqqqmlCqppzLOLOLDDDDNLDDCDLCqqLOUONLDCCDLNCpqtppCDzCDCUNDuCutqODqppqqpONDDtqpqtqqqmmmmmqplllmmllllhillmlmlmmmmpplllilmmmmlmnmmlmmmmmmllmpmpmmqmmpnpqqrqqqquqqqqqmpmmmmtqqqqqqmppmllmmlqtqpmmmpqqtttqtqDIDtuDutuqppnppmmmilmmqpttqpqpqptqppCDtl",
"uDqqpqqqDzptCLCpCDLNLDCqDNDqtDDtDDLCCzCDLDCDDzpppqtpppmlmpqqDtzCCCLNCqzpDCqqqqquCqplmpppqqppqpqqqqqqqqtqppqpmppppmqtmptqpppppppmqppllllmppmpnqqmmpqpqpqpqttDutuDquutqqqquqquuqqqqqqnqqpqqqqtuuuuIODuuDDupqqqqttquttqqqtttttqqqpluuqqtuuqDuDDDILDDDDDDttqCDODDDDu",
"UOODDDDHCtpzCLCpqDDCqCqtpDLCqCCqpqtqppqCqppqCtpmCCCqqqqqtpmpzqtqppCLtztpqttqpqDDtqpppqqtCqttDtqtDuDDDutqquuqtqtquqHIqtIuuuuqqqqpqqqtqpqqqnqqqqqqqqtqqtqqqqutqqtqqqqmmmmmqpmmpmmlmpnpqmqqqmqmqqqqlmmmmmqpmlmpqqqmqmmmmpqqqqqqqqpmmpqtqppqmpmqqppmpptqtCCuqHODttLU",
"qqplhlllqpppCCpplpqmllmplpCCqqppqqqqpqtDtpmqqqppmpmlllmpCqptCCCCppCDypqmpqqqpmqDqqqqtpqqDttCtpllmpqtuqqpuDutqqqpmpqqpqqtqpmmppmmmptqqqpqmmmqrrqrmqpmpnpmmppmpqmmlillmppqpmllllilmmpmqqqmqpmmpqpnqqtqmpmmliimqpmimllmmmqqqqqppqmmllqqpmlmqqtqutqqlmpppqqtpqCtqCHO",
"DDtqppqtmppqCCppqCDtppqCqqqqqpmpppppppqCLzptzqqppmppmpqCmmqzzqzDCCNNCpplmpppmppqttptqpptplmqDtpppqqDLHDDqttqqppmpqpqqttumlklmplklmppmlmmlllqqqqqllmllmmlqqqqqttqqqmmmmmmqmmmmmpqpmqqqpqqmqqqruuuqurqmlihmmmqqpmmlimpqpmqmqqqmmqqptttqpppplmmppppttqqpmppptqpqqtq",
"qtqmlmllpqCCDCzppzDCmpqqDpmpqqqCzqpqqzCDDtqzDCDLqqCqCCDLCNUVNDDOLCUULCtpqpqqttuuCqqttqDDLDHOOLtmDqCDDMDDtDEDuuuttuqpwDuOutqtuHuqilmmlllmmimmqnmnmpmmpqqpmmpmmqqqmpmmpqqtnpqqqqquqqtqqqqqppqqutqqqquqqmmmmlmqqmmqqqtuuqpmqquqnpqqttqqtttqppppqqtuDDDqpppqqDNDplpp",
"qtttuDuDuDDNUONCCqppqDOUUDCDNDDDCDDCqqCLzCCCLONCCCpqCDLNLOOCCDLLNCCNDCtpttqtDIIItDCqtDtqtCDNDtqtLMLDCDDODDHLDutuDDuuDDOOVqtDDDOqqtqtqqqqtqqqtqtuuqttuuuDpqqtDutqpquwuuuuHuuuutuDDuuuIHuDqquHIDuqnquqqqquqquruvvuuuuvuqruuuvxuuvuIwuHIIwDIDuDOPODDUOHOMHODOUICtCD",
"IIDDDDCtDNNNOUUNOLDCDLOUDCDLLDCqmqLLOLNLHDzpmqzqqqqCLOOOCzLOLCCDCCLUHDNDOODDuttqDDDCDNONqDDDtzCDLDtqqqDDDHDDuCuDtqqqqtDDDtqqmtDtpqtDtutuqqquuruuquqtuDtuqtuDuDuquIODuDIIIDuDuuDIIDDIOIIIIIIIOODuvxuEuvEIurqqqqqquruuutquvutqtuvJuuwIIIHwutqtIOIDtOODNNDCNOONDttD",
"IDDuDwDCDDOOUUOULCqqzCDDXLtqCCDOUULCzqqqCLLDztzCqpqzDLLCzpzONqmzppCHpppplllmpqqtllpmpqqqmptqmpptppqCCtmlDCqpppttttttqtDHtDHtltODmmmppqqqqqquuuuutqtrCuAtqqqqqtqtDHDutDHOOIHDutIUOIHOPOOOutqqqqtttqqtrtqmqqqqqqqntqquurtqqquuuuuutsqCIHDDHuttNOOHLOONVODNONOODDCD",
"qpppqqqtptHUONGNqpllqDDCUCmlmpCLLCmlllmpmCLLtzCLMLLLNLDzODCLLqqCCtNUCqtqDtutqqqpmppqtttpltDDtpmppqLOLzppqqppmpqqqtqppppqpqtpmpttqmpmmmtuqpqtqqqqppmmpqqqqqqqqtDDqqqppquDtuDuqqtOutuDDuDDtqppppqqqqqqqmmmmmmmmnpqmmmqqpmmlmqquupmplpttttqtqppqqppqtpptCtDDqqDCplm",
"ppmpppolppCHNCCDCqpqCONMNDDLNDDCCDLLNLCqNMLCpzOYYUOLUUNLUUMLCLCzCtDUHHNDOOIDttqqttqDDDDDDOUODtqtMUNLCqDUpttqpqttqCDqptDDtppqtpmCDDDqqtuDmmmqqmmmlihillmmlllmlmqqmppmpquDqqqtpmpqqqpqtqqtqtqpmpmpmmqnmmjmmlilmmiilhllllllmlllmpppppmpttqtDCppqCqqttqqDCqDDCDODqmp",
"qtttuuttDttDDDNWDCqqDOUULDCDNDDCLMNMLLDLLLDzqpqLpmlmmqzCpzCqzzqllklpmlmlhhklmptuqmlllppDttqplllmCCzCpmqOpqCqtttqpqtpqDHDttqtLtqDqzCDCqmpmmpmpmmmmllllmpplmmmllmptqtqquDCDDHEDtqDDDDDDDHOuttqqmmleimmiilmnnqnqqqqppqqqpqttqpqtuDuutuHOOHDONDDNONLDOOOUHCDOOUUOHCt",
"pqquuHDuutqHNDCNCqmppzDLtmillllmhhhilmzLllmppihelhehhillmmllmlihlkopkhklllllllmpqlkhhlmplhhgdhhkmllmpllpipqpmqpphhhhhomilqlhmplllmmpmmllqmpqqpqqtqqqqqqquuHDuuDEuDDtuDIDOOOODuDDIHDIHDMODLIDttqtnqqqqqqqutruuvvvqtttqptDtttDDHDtCtDOUOLDCqqqqqqppCCttqpDpCtqppqp",
"mpmppmlklllCDpolmllhlmqCpmpqqpmlhlqzpmllzppzLCzqLDzpqqpmDlillhhlhkmpkhmppomlhhlmlkhilhghllhlllmmpihllllphmpllppmhlhdhmlghtpdhpmhmlmllmpqqqqquruuDuuuuqpmmqtqqqtDqtqqtDOOuqqppmmppmmpmmptmpqppmmpurqqqqqnurrqrqqqllmplhlpDqlhklmlllpCDCplqqpppmllpqpmmlqVlqtliptq",
};

Added jni/tkzinc/sandbox/texture-paper.xpm.















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* XPM */
static char *on[] = {
/* width height num_colors chars_per_pixel */
"    32    32       48            1",
/* colors */
". c #f8e0d8",
"# c #f8e0d0",
"a c #f8e0c0",
"b c #f8e0b8",
"c c #f8d4d0",
"d c #f8d4c0",
"e c #f8d4b8",
"f c #f8e0e0",
"g c #f8e0d8",
"h c #f8e0d0",
"i c #f8e0c0",
"j c #f8e0b8",
"k c #f8d4d0",
"l c #f8d4c0",
"m c #f8d4b8",
"n c #f8d4b0",
"o c #f8ccc0",
"p c #f8ccb8",
"q c #f8ccb0",
"r c #f8c4b8",
"s c #f8c4b0",
"t c #f0e0d0",
"u c #f0e0c0",
"v c #f0e0b8",
"w c #f0d4d0",
"x c #f0d4c0",
"y c #f0d4b8",
"z c #f0d4b0",
"A c #f0d4a8",
"B c #f0ccc0",
"C c #f0ccb8",
"D c #f0ccb0",
"E c #f0cca8",
"F c #f0cca0",
"G c #f0c4b8",
"H c #f0c4b0",
"I c #f0c4a8",
"J c #f0c4a0",
"K c #e8e0b8",
"L c #e8d4b8",
"M c #e8ccc0",
"N c #e8ccb8",
"O c #e8ccb0",
"P c #e8cca8",
"Q c #e8c4b8",
"R c #e8c4b0",
"S c #e8c4a8",
"T c #e8c4a0",
/* pixels */
"h#kyGCmmmmvmvyjjyyCpjvjvuhhivjia",
"LmymvvyllyyithLvLyvjvpihjjyli#kg",
"CDCQyyCCGyikyCCCyLyNMxyyyLmulyRS",
"NqmvjyCyvuimLLymmCpmmjmCvyyCOAGm",
"jvliivvyymiyjCCpvmjmjvjjmyyCCvij",
"uvyvCiiujixCGmyjymvmvljyCCCvvuuj",
"yyyllBxmONyjyxukxBlxlBCrCjiljkwK",
"pyCCyQSIDDmymCyyCGCRFIzCLmmyyOTT",
"yyjvmvyjuuvxlijvjmmjjjjeijjyjDmj",
"vyvjuiyjjhllliiixljjullylmLjaivv",
"vihhivuuhiuhwxCGCvhkvvyyCyujvjuj",
"CopCCxCCpmxCQCCmxBmLCCCyyyCpCCxy",
"ypmmyyyyyvyyLCyCCRDmyyvymCyvyjpv",
"vjvjvjlujiiiyyCyDjjKjjmymmvjvyvb",
"jyliiiyyxiijymyCpmymNCBjuKimmliv",
"mwhipyliavjjvyCCvmyyuuxmyijyjvmy",
"yjlDNGvmKmmyNLyyCCCCHRSyylyyCCQG",
"jmCsOyyGymyCyjyQyryDnmCjvmyjmmyy",
"NHHyyCyjyjmyCymyyiiuvvuyxlikyyjy",
"mmCymmyymyrCyvyyyimuyyxhhuCmjyQE",
"GCmCyyjmpmmmmvxxliyylkllCmyDSCmy",
"yyCNNNSPCyCCmyByCyyCMPDDOTTRJRTL",
"yppmyCCmyyylijypjvmymCmmDyvmnmmj",
"vymCymvvjlvjyymmvmmCmmvvjyppmiyy",
"CCvmjpjyxlymyyCyyNmjmyvyCyivyyyv",
"CpyyNNyyyyOOCmyvyvCpmCyyyOyLCCCC",
"pypNmxilypDzppymyxdmCyvymDpyLyyy",
"yydhlxyjmyyluvlltiumjyyymjvvjlku",
"cgljjyvpiilyihxyyjvyyyliiiikjyml",
"xymNpihiLChlyyymmyCylixvxiyCjl.t",
"NPREmxyCGCyGryCCCCyCCCLmCypLyLmm",
"mygfxyzHbypvjvvyjKjrHRbjvLjbtvbe",
};

Added jni/tkzinc/sandbox/trash.xbm.













>
>
>
>
>
>
1
2
3
4
5
6
#define trash_width 16
#define trash_height 16
static char trash_bits[] = {
   0x00, 0x01, 0xe0, 0x0f, 0x10, 0x10, 0xf8, 0x3f, 0x10, 0x10, 0x50, 0x15,
   0x50, 0x15, 0x50, 0x15, 0x50, 0x15, 0x50, 0x15, 0x50, 0x15, 0x50, 0x15,
   0x50, 0x15, 0x10, 0x10, 0xe0, 0x0f, 0x00, 0x00};

Added jni/tkzinc/sandbox/triangles.pl.











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/perl -w

use Tk;
use Tk::Zinc;
use Controls;
use Tk::Photo;
require Tk::PNG;
    
$mw = MainWindow->new();
$logo = $mw->Photo(-file => "logo.gif");
$papier = $mw->Photo(-file => "texture-paper.xpm");
$penguin = $mw->Photo(-format => 'png',
		      -file => "xpenguin.png");

$top = 1;
$zinc = $mw->Zinc(-render => 1,
		  -borderwidth => 0,
		  -highlightthickness => 0,
		  -relief => 'sunken',
		  -takefocus => 1,
		  -tile => $papier);
$zinc->pack(-expand => 1, -fill => 'both');
$zinc->configure(-width => 500, -height => 500);
$gr1 = $zinc->add('group', $top);
$clip = $zinc->add('arc', $gr1, [50, 50, 399, 399],
		   -filled => 1,
		   -fillcolor => 'Pink:40',
#		   -fillpattern => 'AlphaStipple4',
		   -linewidth => 0);
#$zinc->itemconfigure($gr1, -clip => $clip);
$gr2 = $zinc->add('group', $gr1);
$clip2 = $zinc->add('rectangle', $gr2, [200, 200, 450, 300],
		    -filled => 1,
#		    -fillcolor => 'white:100|white:0',
		    -fillcolor => 'white:100 0|black:100 100/90',
#		    -fillcolor => 'white 0 |blue 20|blue 80|black:0 100/270',
		    -linewidth => 0);
#$zinc->itemconfigure($gr2, -clip => $clip2);
$view = $zinc->add('group', $gr2, -tags => "controls");
$zinc->lower($clip);
$zinc->lower($clip2);

new Controls($zinc);

$cv2 = $zinc->add('curve', $view, [],
		  -linewidth => 2);
$cv3 = $zinc->add('curve', $view, [],
		  -linewidth => 2);

$tri2 = $zinc->add('triangles', $view, [50, 50, 300, 50, 150, 150, 300, 150],
		   -colors => ['tan:50', '', '', 'red']);
$zinc->contour($cv2, 'union', $tri2);

$tri3 = $zinc->add('triangles', $view, [150, 150, 50, 50, 150, 50, 300, 50],
		   -colors => ['grey50', 'blue', 'red', 'yellow'],
		   -fan => 1);
$tri4 = $zinc->clone($tri3, -colors => ['grey', 'red']);
$zinc->translate($tri4, 100, 300);

$zinc->contour($cv3, 'union', $tri3);
$zinc->translate($tri3, 0, 300);
$zinc->translate($cv3, 0, 300);

$zinc->monitor(1);
$mw->Tk::bind('<p>', sub { print "perfs: ", join(',', $zinc->monitor()), "\n" });
$mw->Tk::bind('<t>', sub { $zinc->remove($arc); });
$mw->Tk::bind('<q>', sub { exit(0); });
$zinc->focusFollowsMouse();
MainLoop();

Added jni/tkzinc/sandbox/xpenguin.png.

cannot compute difference between binary files

Added jni/tkzinc/sandbox/zinc.tcl.

























































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
lappend auto_path .

package require Tkzinc
package require Img

set top 1

#memory info
#memory trace on
#memory validate on

image create photo logo -file logo.gif
image create photo logosmall -file logo.gif
#image create photo bois -file texture-bois1.xpm

#set r [zinc .r -backcolor gray -relief sunken -tile bois]
set r [zinc .r -backcolor gray -relief sunken]
pack .r -expand t -fill both
set scale 1.0
set centerX 0.0
set centerY 0.0
set zincWidth 800
set zincHeight 500
#.r configure -width $zincWidth -height $zincHeight
#.r configure -drawbboxes t
set view [.r add group $top -tags "controls"]

frame .rc
button .rc.up -text "Up" \
	-command {set centerY [expr $centerY+30.0]; updateTransform .r}
button .rc.down -text "Down" \
	-command {set centerY [expr $centerY-30.0]; updateTransform .r}
button .rc.left -text "Left" \
	-command {set centerX [expr $centerX+30.0]; updateTransform .r}
button .rc.right -text "Right" \
	-command {set centerX [expr $centerX-30.0]; updateTransform .r}
button .rc.expand -text "Expand" \
	-command {set scale [expr $scale*1.1]; updateTransform .r}
button .rc.shrink -text "Shrink" \
	-command {set scale [expr $scale*0.9]; updateTransform .r}
button .rc.reset -text "Reset" \
	-command {set scale 1.0; set centerX 0.0; set centerY 0.0; \
	updateTransform .r}
button .rc.quit -text "Quit" -command "exit"
grid .rc.up -row 0 -column 2 -sticky ew
grid .rc.down -row 2 -column 2 -sticky ew
grid .rc.left -row 1 -column 1
grid .rc.right -row 1 -column 3
grid .rc.expand -row 1 -column 4
grid .rc.shrink -row 1 -column 0
grid .rc.reset -row 1 -column 2 -sticky ew
grid .rc.quit -row 3 -column 2
pack .rc

bind .r <Configure> "ZincStyleConfig %W %w %h"

proc ZincStyleConfig {zinc w h} {
    global zincWidth zincHeight
    
    set bw [$zinc cget -borderwidth]
    set zincWidth [expr $w - 2*$bw]
    set zincHeight [expr $h - 2*$bw]
    updateTransform $zinc
}

proc updateTransform {zinc} {
    global zincWidth zincHeight
    global scale centerX centerY
    global top
    
    $zinc treset $top
    $zinc translate $top [expr -$centerX] [expr -$centerY]
    $zinc scale $top $scale $scale
    $zinc scale $top 1 -1
    $zinc translate $top [expr $zincWidth/2] [expr $zincHeight/2]
}

#
# TRACKS
#
set track [.r add track $view 6 -tags track -leaderanchors "|0|0"]
.r itemconfigure $track -position "1 1"
.r itemconfigure $track -position "10 10"
.r itemconfigure $track -position "20 20"
.r itemconfigure $track -position "30 30"
.r itemconfigure $track -position "40 40"
.r itemconfigure $track -position "50 50"
.r itemconfigure $track -position "55 60"
.r itemconfigure $track -position "60 70"
.r itemconfigure $track -speedvector "20 0"
.r itemconfigure $track -symbolcolor salmon -speedvectorcolor salmon -leadercolor salmon \
	 -labeldistance 20
.r itemconfigure $track -markersize 20 \
	 -filledmarker 1 \
	 -markerfillpattern AlphaStipple4 \
	 -markercolor salmon
.r itemconfigure $track -labelformat "120x40 l0l0+0+0 x80x20+0+0 x40x20+80+0 x40x20+0+20 x20x20>3>2 x60x20>1>1"
.r itemconfigure $track 0 -filled 1 -backcolor gray -bordercolor gray -relief groove
.r itemconfigure $track 1 -filled 1 -backcolor tan -bordercolor tan -relief groove \
	 -font "cenapii-etiquette-m17" -text "AFR451"
.r itemconfigure $track 2 -text "WPY" \
	 -font "cenapii-etiquette-m17"
.r itemconfigure $track 3 -text "400" -filled 1 -backcolor wheat \
	 -font "cenapii-etiquette-m17"
.r itemconfigure $track 4 -text "-" -filled 1 -backcolor wheat \
	 -font "cenapii-etiquette-m17"
.r itemconfigure $track 5 -text "450" -font "cenapii-etiquette-m17"

.r bind $track:speedvector <Enter> ".r itemconfigure $track -speedvectorcolor red"
.r bind $track:speedvector <Leave> ".r itemconfigure $track -speedvectorcolor salmon"

set track2 [.r add track $view 4 -speedvector "-20 0" \
	 -symbolcolor salmon  -speedvectorcolor salmon -leadercolor salmon \
	 -labeldx -20 -labeldy 20 -leaderanchors "%30x30" \
	 -historycolor MistyRose -lastasfirst t ]
.r itemconfigure $track2 -labelformat "a3f110+0+0 a3f110>0^0 a3f110^0>0 a3f110>2>0"
.r itemconfigure $track2 0 -filled 1 -backcolor tan -text "BAW452"
.r itemconfigure $track2 1 -filled 1 -backcolor wheat -text "450"
.r itemconfigure $track2 2 -filled 1 -backcolor wheat -text "KMC"
#.r itemconfigure $track2 3 -filled 1 -backcolor wheat -text ""
.r itemconfigure $track2 -connecteditem $track -connectioncolor green
.r itemconfigure $track2 -position "10 0"
.r itemconfigure $track2 -position "-20 10"
.r itemconfigure $track2 -position "-30 20"
.r itemconfigure $track2 -position "-40 30"
.r itemconfigure $track2 -position "-50 40"
.r itemconfigure $track2 -position "-60 50"
.r itemconfigure $track2 -position "-70 50"
.r itemconfigure $track2 -position "-80 50"
.r itemconfigure $track2 -position "-90 50"

#
# WAY POINTS
#
puts "creating way points"
set wp [.r add waypoint $view 1 -tags borders]
.r itemconfigure $wp -symbolcolor bisque -leadercolor bisque  -position "-100 120" \
	 -labelformat "40x20"
.r itemconfigure $wp 0 -bordercolor bisque -text "NCY" -tile logo -filled t
set wp2 [.r add waypoint $view 1 -tags borders]
.r itemconfigure $wp2 -symbolcolor bisque \
    -leadercolor bisque  \
    -position "50 160" \
    -labelformat "40x20" \
    -connectioncolor bisque \
    -connecteditem $wp
.r itemconfigure $wp2 0 -bordercolor bisque -text "MPW"
set wp3 [.r add waypoint $view 1 -tags borders]
.r itemconfigure $wp3 -symbolcolor bisque \
    -leadercolor bisque \
    -position "200 140" \
    -labelformat "40x20" \
    -connectioncolor bisque \
    -connecteditem $wp2
.r itemconfigure $wp3 0 -bordercolor bisque -text "ART"

#
# MACROS
#
puts "creating macros"
set macro [.r add tabular $view 10 -labelformat "x40x20+0+0 x40x20+40+0" \
	       -tags f0borders -connecteditem $track]
.r itemconfigure $macro 0 -text une
.r itemconfigure $macro 1 -text macro

#
# MINISTRIPS
#
puts "creating ministrips"
set ministrip [.r add tabular $view 1 \
	-labelformat "60x20" -position "10 10"]
.r itemconfigure $ministrip 0 -text "ministrip" -sensitive f
set ministrip2 [.r add tabular $view 1 \
	-labelformat "60x20" -connecteditem $ministrip]
.r itemconfigure $ministrip2 0 -text "ministrip2" -sensitive f
set ministrip3 [.r add tabular $view 1 \
	-labelformat "60x20" -connecteditem $ministrip2]
.r itemconfigure $ministrip3 0 -text "ministrip3" -sensitive f

#
# MAPS
#
puts "creating maps"
videomap load "/usr/share/toccata/maps/videomap_paris-w_90_2" 0 paris-w
videomap load "/usr/share/toccata/maps/videomap_orly" 17 orly
videomap load "/usr/share/toccata/maps/hegias_parouest_TE.vid" 0 paris-ouest

set map [.r add map $view -color darkblue]
.r itemconfigure $map -mapinfo orly

set map2 [.r add map $view -color darkblue -filled 1 -priority 0 -fillpattern AlphaStipple1]
.r itemconfigure $map2 -mapinfo paris-ouest

set map3 [.r add map $view -color orange]

mapinfo mpessai create
mapinfo mpessai add text normal simple 0 200 "Et voilà"
mapinfo mpessai add line simple 5 0 0 100 100
mapinfo mpessai add line simple 0 100 100 0 200
mapinfo mpessai add line simple 2  -100 100 0 0
.r itemconfigure $map3 -mapinfo mpessai

#
# Clip
#
puts "crée les clips"
set clip [.r add rectangle $view "-100 -100 300 200" -filled t \
	      -linewidth 0 -fillcolor darkgray -visible f]
#.r rotate $clip [expr 3.14159 / 4]
.r lower $clip
#.r itemconfigure $view -clip $clip

.r add rectangle $top "-5 -5 5 5"  -filled t -fillcolor red
set topclip [.r add rectangle $top "-400 -400 400 400" \
		 -filled t -fillcolor lightgray -linewidth 0 -visible t]
.r lower $topclip
#.r rotate $topclip [expr 3.14159 / 4]
#.r itemconfigure $top -clip $topclip

#
# CONTROLS
#
proc borders {onoff} {
    set part [.r currentpart]
    puts "part $part $onoff"
    set contour noborder
    if { $onoff == "on" } {
	set contour "contour oblique"
    }
    if { [regexp {^[0-9]+$} $part] } {
	.r itemconfigure current $part -border $contour
    }
}

.r bind borders <Enter> "borders on"
.r bind borders <Leave> "borders off"
.r bind f0borders:0 <Enter> "borders on"
.r bind f0borders:0 <Leave> "borders off"
.r bind track <Enter> {puts "Entre dans item"}
.r bind track <Leave> {puts "Sort d'item"}
.r bind track:0 <Enter> {puts "Entre dans champ 0"}
.r bind track:0 <Leave> {puts "Sort de champ 0"}
.r bind track:1 <Enter> {puts "Entre dans champ 1"}
.r bind track:1 <Leave> {puts "Sort de champ 1"}
.r bind track:2 <Enter> {puts "Entre dans champ 2"}
.r bind track:2 <Leave> {puts "Sort de champ 2"}
.r bind track:3 <Enter> {puts "Entre dans champ 3"}
.r bind track:3 <Leave> {puts "Sort de champ 3"}

bind .r <2> {puts "%x@%y, item: [.r find atpoint %x %y]"}

proc finditems {cornerx cornery} {
    global origx origy

    puts "--- enclosed ---"
    puts "++ [.r find enclosed $origx $origy $cornerx $cornery] ++"
    puts "--- overlapping ---"
    puts "++ [.r find overlapping $origx $origy $cornerx $cornery] ++"
    puts ""
}

bind .r <ButtonPress-1> "set origx %x; set origy %y"
bind .r <ButtonRelease-1> "finditems %x %y"

.r bind all <1> { if {! [catch {.r find withtag current} item] } { \
	puts "<1> in $item" } else { puts "None" } }

#
#for {set j 0} {$j < 20} {incr j} {
#    memory info
#    for {set i 0} {$i < 10} {incr i} {
#	 set a($i) [.r add icon 1 -image logo]
#	 set b($i) [.r add rectangle 1 "10 10 1000 1000" -filled t -tile logosmall]
#	 set c($i) [.r add curve 1 "10 10 10 100 100 100" -filled t -tile logosmall]
#    }
#    for {set i 0} {$i < 10} {incr i} {
#	 .r remove $a($i)
#	 .r remove $b($i)
#	 .r remove $c($i)
#    }
#}
    
source "controls.tcl"

Added jni/tkzinc/sandbox/zinc.test.





















































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#-*- mode:tcl -*-

if {[lsearch [namespace children] ::tcltest] == -1} {
#    package require tcltest
#    namespace import ::tcltest::*
    source [file join [pwd] [file dirname [info script]] defs.tcl]
}

proc setupHier {} {
    set view [.r add group 1]
    .r add rectangle $view "50 -150 100 -50" -tags "poly rectangle"
    set model [.r add group $view]
    .r add curve $model "50 -150 100 -50" -tags "poly foo"
    .r add rectangle $model "50 -150 100 -50" -tags "rectangle"
    .r add text $model -text "UnTexte" -tags "title"
    .r clone $model
    .r clone $model
    .r clone $model
    .r remove $model
}

load tkzinc3.1.so
zinc .r
pack .r
update
setupHier

test FindItems-1.0 {Test subcommand 'all' with no args} {} {
    .r find all
} {2 3 16 19 18 17 12 15 14 13 8 11 10 9}

test FindItems-1.1 {Test subcommand 'all' with top group} {} {
    .r find all 1
} {2 3 16 19 18 17 12 15 14 13 8 11 10 9}

test FindItems-1.2 {Test subcommand 'all' with top group, non-recursive} {} {
    .r find all 1 f
} {2}

test FindItems-1.3 {Test subcommand 'all' with inner group} {} {
    .r find all 2
} {3 16 19 18 17 12 15 14 13 8 11 10 9}

test FindItems-1.4 {Test subcommand 'all' with inner group, non-recursive} {} {
    .r find all 2 f
} {3 16 12 8}

test FindItems-1.5 {Test subcommand 'all' with inner most group} {} {
    .r find all 8
} {11 10 9}

test FindItems-1.6 {Test subcommand 'all' with inner most group, non-recursive} {} {
    .r find all 8 f
} {11 10 9}

test FindItems-2.0 {Test subcommand 'above' with id} {} {
    .r find above 9
} {10}

test FindItems-2.1 {Test subcommand 'above' with tag} {} {
    .r find above foo
} {18}

test FindItems-2.2 {Test subcommand 'above' with tag in group} {} {
    .r find above foo 8
} {10}

test FindItems-2.3 {Test subcommand 'above' with tag in group} {} {
    .r find above foo 2 f
} {}

test FindItems-3.0 {Test subcommand 'below' with id} {} {
    .r find below 10
} {9}

test FindItems-3.1 {Test subcommand 'below' with tag} {} {
    .r find below title
} {10}

test FindItems-3.2 {Test subcommand 'below' with tag in group} {} {
    .r find below title 12
} {14}

test FindItems-3.3 {Test subcommand 'below' with tag in group, non-recursive} {} {
    .r find below title 2 f
} {}

test FindItems-4.0 {Test subcommand 'atpriority'} {} {
    .r find atpriority 2
} {3 19 18 17 15 14 13 11 10 9}

test FindItems-4.1 {Test subcommand 'atpriority' in group} {} {
    .r find atpriority 2 2
} {3 19 18 17 15 14 13 11 10 9}

test FindItems-4.2 {Test subcommand 'atpriority' in group, non-recursive} {} {
    .r find atpriority 2 2 f
} {3}

test FindItems-5.0 {Test subcommand 'withtag'} {} {
    .r find withtag poly
} {3 17 13 9}

test FindItems-5.1 {Test subcommand 'withtag' in group} {} {
    .r find withtag poly 2
} {3 17 13 9}

test FindItems-5.2 {Test subcommand 'withtag' in group, non-recursive} {} {
    .r find withtag poly 2 f
} {3}

test FindItems-6.0 {Test subcommand 'withtype'} {} {
    .r find withtype rectangle
} {3 18 14 10}

test FindItems-6.1 {Test subcommand 'withtype' in group} {} {
    .r find withtype rectangle 2
} {3 18 14 10}

test FindItems-6.2 {Test subcommand 'withtype' in group, non-recursive} {} {
    .r find withtype rectangle 2 f
} {3}

test FindItems-7.0 {Test tag operator '&&'} {} {
    .r find withtag {poly && rectangle}
} {3}

test FindItems-7.1 {Test tag operator '||'} {} {
    .r find withtag {poly || rectangle}
} {3 18 17 14 13 10 9}

test FindItems-7.2 {Test tag operator '!'} {} {
    .r find withtag {!rectangle&&!poly}
} {2 16 19 12 15 8 11}

test FindItems-7.3 {Test tag operator '^'} {} {
    .r find withtag {rectangle^poly}
} {18 17 14 13 10 9}

test FindItems-7.4 {Test tag grouping operator '()'} {} {
    .r find withtag {!(rectangle&&poly)}
} {2 16 19 18 17 12 15 14 13 8 11 10 9}

test FindItems-7.5 {Test not using tag grouping operator '()'} {} {
    .r find withtag {!rectangle&&poly}
} {17 13 9}

catch {destroy .r}
#zinc .r
#pack .r
#update

::tcltest::cleanupTests
return

Added jni/tkzinc/starkit.tcl.in.



































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#
# This script is intended to be run in the top directory
# with: tclsh starkit.tcl.
# It needs a tclkit and the sdx command as a starkit in the path.
#

set MAJOR_VERSION @MAJOR_VERSION@
set MINOR_VERSION @MINOR_VERSION@
set PATCHLEVEL @PATCHLEVEL@


#
# Starkit structure
#
# demo.tcl
# lib
#   tkimg1.3
#     files from the Tkimg starkit
#   TkzincX.Y
#     Copyright
#     demos
#       demos files and sub-directories
#     Linux-x86
#       Tkzinc.so
#     pkgIndex.tcl
#     Windows-x86
#       Tkzinc.dll
#     zincGraphics.tcl
#     zincLogo.tcl
#     zincText.tcl
# main.tcl
#

proc Windows-x86-Compile {} {
  set cwd [pwd]
  puts "Compiling for Windows $cwd..."
  cd win
  if { [catch { exec tclsh package.tcl clean } result] } {
    puts $result
    exit
  }
  if { [catch { exec tclsh package.tcl subst } result] } {
    puts $result
    exit
  }
  if { [catch { exec tclsh package.tcl tcl } result] } {
    puts $result
    exit
  }
  #
  # Copy the dll in the root dir for updateKit.
  file copy -force [glob -directory buildtcl Tkzinc*.dll] [file join $cwd Tkzinc.dll]

  cd $cwd
}

proc Linux-x86-Compile {} {
}

proc updateKit { TkzincVfs } {
  global MAJOR_VERSION MINOR_VERSION PATCHLEVEL

  set zincPath [file join $TkzincVfs lib Tkzinc$MAJOR_VERSION.$MINOR_VERSION]
  set version $MAJOR_VERSION.$MINOR_VERSION.$PATCHLEVEL
  set winVersion $MAJOR_VERSION$MINOR_VERSION$PATCHLEVEL

  file copy -force [file join starkit demo.tcl] [file join starkit main.tcl] $TkzincVfs

  set zincPath [file join $TkzincVfs lib Tkzinc$MAJOR_VERSION.$MINOR_VERSION]
  file mkdir $zincPath
  file copy -force Copyright \
	  [file join library zincGraphics.tcl] \
	  [file join library zincLogo.tcl] \
	  [file join library zincText.tcl] \
	  $zincPath

  set demosPath [file join $zincPath demos]
  file mkdir $demosPath
  foreach f [glob -directory demos *.tcl] {
	  file copy -force $f $demosPath
  }
  file delete -force [file join $demosPath data] [file join $demosPath images]
  file copy -force [file join demos zinc-widget] [file join demos data] [file join demos images] $demosPath

  #
  # Emit a merged pkgIndex.tcl
  #
  set fOut [open [file join $zincPath pkgIndex.tcl] w]
  puts $fOut "proc Platform {} {"
  puts -nonewline $fOut [info body Platform]
  puts $fOut "}"
  set fIn [open [file join library pkgIndex.tcl]]
  foreach line [split [read $fIn] \n] {
  	if {![regexp {^\s*$|^#} $line]} {
	    puts $fOut $line
	  }
  }
  close $fIn
  puts -nonewline $fOut "package ifneeded Tkzinc $version "
  puts $fOut {[list load [file join $dir [Platform] Tkzinc[info sharedlibext]]]}
  close $fOut

  #
  # Copy the platform dependent libraries
  #
  if { [file exists libTkzinc$version.so] } {
	  set platformPath [file join $zincPath Linux-x86]
	  file mkdir $platformPath
	  file copy -force libTkzinc$version.so [file join $platformPath Tkzinc.so]
  }
  if { [file exists Tkzinc.dll] } {
	  set platformPath [file join $zincPath Windows-x86]
	  file mkdir $platformPath
	  file copy -force Tkzinc.dll [file join $platformPath Tkzinc.dll]
  }
}


proc Platform {} {
  global tcl_platform
  set plat [lindex $tcl_platform(os) 0]
  set mach $tcl_platform(machine)
  switch -glob -- $mach {
  	sun4* { set mach sparc }
  	intel -
	  i*86* { set mach x86 }
	  "Power Macintosh" { set mach ppc }
  }
  switch -- $plat {
	  AIX   { set mach ppc }
	  HP-UX { set mach hppa }
  }
  return "$plat-$mach"
}

#
# Build the current platform variant
[Platform]-Compile

set TkzincVfs Tkzinc.vfs
set TkzincKit Tkzinc.kit

set cwd [pwd]
cd ..

if { ! [file exists $TkzincVfs] } {
  if { [file exists $TkzincKit] } {
	  exec sdx unwrap $TkzincKit
  } else {
    puts "Unable to find either Tkzinc.kit or Tkzinc.vfs in .. , giving up."
    exit
  }
}
cd $cwd
updateKit [file join .. $TkzincVfs]

puts "Now wrapping the starkit"

cd ..
exec sdx wrap $TkzincKit

Added jni/tkzinc/starkit/demo.tcl.









>
>
>
>
1
2
3
4

set path [file dirname [info script]]

source [file join [lindex [glob -directory [file join $path lib] Tkzinc*] 0] demos zinc-widget]

Added jni/tkzinc/starkit/main.tcl.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

package require starkit

set method [starkit::startup]
if { $method eq "sourced"} return

array set help {
    demo { Launch a package demo

	Usage: demo package
    }
}

set action [lindex $argv 0]
set path [file dirname [info script]]

set validActions [array names help]
if { $action eq "" ||
     ($action eq "help" && [llength $argv] == 1 &&
      [lsearch $validActions $action] < 0) } {
    puts "Specify one of the following commands:\n"
    foreach c [array names help] {
	puts -nonewline " $c"
    }
    puts "\n\nFor more information, type: $argv0 help ?command?"
    exit
} elseif { $action eq "help" } {
    set cmd [lindex $argv 1]
    puts $help($cmd)
    exit
}

set argv [lrange $argv 1 end]

source [file join $path $action.tcl]

Added jni/tkzinc/tclconfig/README.txt.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
These files comprise the basic building blocks for a Tcl Extension
Architecture (TEA) extension.  For more information on TEA see:

	http://www.tcl.tk/doc/tea/

This package is part of the Tcl project at SourceForge, and latest
sources should be available there:

	http://tcl.sourceforge.net/

This package is a freely available open source package.  You can do
virtually anything you like with it, such as modifying it, redistributing
it, and selling it either in whole or in part.

CONTENTS
========
The following is a short description of the files you will find in
the sample extension.

README.txt	This file

install-sh	Program used for copying binaries and script files
		to their install locations.

tcl.m4		Collection of Tcl autoconf macros.  Included by a package's
		aclocal.m4 to define SC_* macros.

Added jni/tkzinc/tclconfig/install-sh.

































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
#!/bin/sh
# install - install a program, script, or datafile

scriptversion=2011-04-20.01; # UTC

# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.

nl='
'
IFS=" ""	$nl"

# set DOITPROG to echo to test this script

# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
  doit_exec=exec
else
  doit_exec=$doit
fi

# Put in absolute file names if you don't have them in your path;
# or use environment vars.

chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}

posix_glob='?'
initialize_posix_glob='
  test "$posix_glob" != "?" || {
    if (set -f) 2>/dev/null; then
      posix_glob=
    else
      posix_glob=:
    fi
  }
'

posix_mkdir=

# Desired mode of installed file.
mode=0755

chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=

src=
dst=
dir_arg=
dst_arg=

copy_on_change=false
no_target_directory=

usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
   or: $0 [OPTION]... SRCFILES... DIRECTORY
   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
   or: $0 [OPTION]... -d DIRECTORIES...

In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.

Options:
     --help     display this help and exit.
     --version  display version info and exit.

  -c            (ignored)
  -C            install only if different (preserve the last data modification time)
  -d            create directories instead of installing files.
  -g GROUP      $chgrpprog installed files to GROUP.
  -m MODE       $chmodprog installed files to MODE.
  -o USER       $chownprog installed files to USER.
  -s            $stripprog installed files.
  -S            $stripprog installed files.
  -t DIRECTORY  install into DIRECTORY.
  -T            report an error if DSTFILE is a directory.

Environment variables override the default commands:
  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
  RMPROG STRIPPROG
"

while test $# -ne 0; do
  case $1 in
    -c) ;;

    -C) copy_on_change=true;;

    -d) dir_arg=true;;

    -g) chgrpcmd="$chgrpprog $2"
	shift;;

    --help) echo "$usage"; exit $?;;

    -m) mode=$2
	case $mode in
	  *' '* | *'	'* | *'
'*	  | *'*'* | *'?'* | *'['*)
	    echo "$0: invalid mode: $mode" >&2
	    exit 1;;
	esac
	shift;;

    -o) chowncmd="$chownprog $2"
	shift;;

    -s) stripcmd=$stripprog;;

    -S) stripcmd="$stripprog $2"
	shift;;

    -t) dst_arg=$2
	shift;;

    -T) no_target_directory=true;;

    --version) echo "$0 $scriptversion"; exit $?;;

    --)	shift
	break;;

    -*)	echo "$0: invalid option: $1" >&2
	exit 1;;

    *)  break;;
  esac
  shift
done

if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
  # When -d is used, all remaining arguments are directories to create.
  # When -t is used, the destination is already specified.
  # Otherwise, the last argument is the destination.  Remove it from $@.
  for arg
  do
    if test -n "$dst_arg"; then
      # $@ is not empty: it contains at least $arg.
      set fnord "$@" "$dst_arg"
      shift # fnord
    fi
    shift # arg
    dst_arg=$arg
  done
fi

if test $# -eq 0; then
  if test -z "$dir_arg"; then
    echo "$0: no input file specified." >&2
    exit 1
  fi
  # It's OK to call `install-sh -d' without argument.
  # This can happen when creating conditional directories.
  exit 0
fi

if test -z "$dir_arg"; then
  do_exit='(exit $ret); exit $ret'
  trap "ret=129; $do_exit" 1
  trap "ret=130; $do_exit" 2
  trap "ret=141; $do_exit" 13
  trap "ret=143; $do_exit" 15

  # Set umask so as not to create temps with too-generous modes.
  # However, 'strip' requires both read and write access to temps.
  case $mode in
    # Optimize common cases.
    *644) cp_umask=133;;
    *755) cp_umask=22;;

    *[0-7])
      if test -z "$stripcmd"; then
	u_plus_rw=
      else
	u_plus_rw='% 200'
      fi
      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
    *)
      if test -z "$stripcmd"; then
	u_plus_rw=
      else
	u_plus_rw=,u+rw
      fi
      cp_umask=$mode$u_plus_rw;;
  esac
fi

for src
do
  # Protect names starting with `-'.
  case $src in
    -*) src=./$src;;
  esac

  if test -n "$dir_arg"; then
    dst=$src
    dstdir=$dst
    test -d "$dstdir"
    dstdir_status=$?
  else

    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
    # might cause directories to be created, which would be especially bad
    # if $src (and thus $dsttmp) contains '*'.
    if test ! -f "$src" && test ! -d "$src"; then
      echo "$0: $src does not exist." >&2
      exit 1
    fi

    if test -z "$dst_arg"; then
      echo "$0: no destination specified." >&2
      exit 1
    fi

    dst=$dst_arg
    # Protect names starting with `-'.
    case $dst in
      -*) dst=./$dst;;
    esac

    # If destination is a directory, append the input filename; won't work
    # if double slashes aren't ignored.
    if test -d "$dst"; then
      if test -n "$no_target_directory"; then
	echo "$0: $dst_arg: Is a directory" >&2
	exit 1
      fi
      dstdir=$dst
      dst=$dstdir/`basename "$src"`
      dstdir_status=0
    else
      # Prefer dirname, but fall back on a substitute if dirname fails.
      dstdir=`
	(dirname "$dst") 2>/dev/null ||
	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
	     X"$dst" : 'X\(//\)[^/]' \| \
	     X"$dst" : 'X\(//\)$' \| \
	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
	echo X"$dst" |
	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
		   s//\1/
		   q
		 }
		 /^X\(\/\/\)[^/].*/{
		   s//\1/
		   q
		 }
		 /^X\(\/\/\)$/{
		   s//\1/
		   q
		 }
		 /^X\(\/\).*/{
		   s//\1/
		   q
		 }
		 s/.*/./; q'
      `

      test -d "$dstdir"
      dstdir_status=$?
    fi
  fi

  obsolete_mkdir_used=false

  if test $dstdir_status != 0; then
    case $posix_mkdir in
      '')
	# Create intermediate dirs using mode 755 as modified by the umask.
	# This is like FreeBSD 'install' as of 1997-10-28.
	umask=`umask`
	case $stripcmd.$umask in
	  # Optimize common cases.
	  *[2367][2367]) mkdir_umask=$umask;;
	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;

	  *[0-7])
	    mkdir_umask=`expr $umask + 22 \
	      - $umask % 100 % 40 + $umask % 20 \
	      - $umask % 10 % 4 + $umask % 2
	    `;;
	  *) mkdir_umask=$umask,go-w;;
	esac

	# With -d, create the new directory with the user-specified mode.
	# Otherwise, rely on $mkdir_umask.
	if test -n "$dir_arg"; then
	  mkdir_mode=-m$mode
	else
	  mkdir_mode=
	fi

	posix_mkdir=false
	case $umask in
	  *[123567][0-7][0-7])
	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
	    ;;
	  *)
	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0

	    if (umask $mkdir_umask &&
		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
	    then
	      if test -z "$dir_arg" || {
		   # Check for POSIX incompatibilities with -m.
		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
		   # other-writeable bit of parent directory when it shouldn't.
		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
		   case $ls_ld_tmpdir in
		     d????-?r-*) different_mode=700;;
		     d????-?--*) different_mode=755;;
		     *) false;;
		   esac &&
		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
		   }
		 }
	      then posix_mkdir=:
	      fi
	      rmdir "$tmpdir/d" "$tmpdir"
	    else
	      # Remove any dirs left behind by ancient mkdir implementations.
	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
	    fi
	    trap '' 0;;
	esac;;
    esac

    if
      $posix_mkdir && (
	umask $mkdir_umask &&
	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
      )
    then :
    else

      # The umask is ridiculous, or mkdir does not conform to POSIX,
      # or it failed possibly due to a race condition.  Create the
      # directory the slow way, step by step, checking for races as we go.

      case $dstdir in
	/*) prefix='/';;
	-*) prefix='./';;
	*)  prefix='';;
      esac

      eval "$initialize_posix_glob"

      oIFS=$IFS
      IFS=/
      $posix_glob set -f
      set fnord $dstdir
      shift
      $posix_glob set +f
      IFS=$oIFS

      prefixes=

      for d
      do
	test -z "$d" && continue

	prefix=$prefix$d
	if test -d "$prefix"; then
	  prefixes=
	else
	  if $posix_mkdir; then
	    (umask=$mkdir_umask &&
	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
	    # Don't fail if two instances are running concurrently.
	    test -d "$prefix" || exit 1
	  else
	    case $prefix in
	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
	      *) qprefix=$prefix;;
	    esac
	    prefixes="$prefixes '$qprefix'"
	  fi
	fi
	prefix=$prefix/
      done

      if test -n "$prefixes"; then
	# Don't fail if two instances are running concurrently.
	(umask $mkdir_umask &&
	 eval "\$doit_exec \$mkdirprog $prefixes") ||
	  test -d "$dstdir" || exit 1
	obsolete_mkdir_used=true
      fi
    fi
  fi

  if test -n "$dir_arg"; then
    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
  else

    # Make a couple of temp file names in the proper directory.
    dsttmp=$dstdir/_inst.$$_
    rmtmp=$dstdir/_rm.$$_

    # Trap to clean up those temp files at exit.
    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0

    # Copy the file name to the temp name.
    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&

    # and set any options; do chmod last to preserve setuid bits.
    #
    # If any of these fail, we abort the whole thing.  If we want to
    # ignore errors from any of these, just make sure not to ignore
    # errors from the above "$doit $cpprog $src $dsttmp" command.
    #
    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&

    # If -C, don't bother to copy if it wouldn't change the file.
    if $copy_on_change &&
       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&

       eval "$initialize_posix_glob" &&
       $posix_glob set -f &&
       set X $old && old=:$2:$4:$5:$6 &&
       set X $new && new=:$2:$4:$5:$6 &&
       $posix_glob set +f &&

       test "$old" = "$new" &&
       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
    then
      rm -f "$dsttmp"
    else
      # Rename the file to the real destination.
      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||

      # The rename failed, perhaps because mv can't rename something else
      # to itself, or perhaps because mv is so ancient that it does not
      # support -f.
      {
	# Now remove or move aside any old file at destination location.
	# We try this two ways since rm can't unlink itself on some
	# systems and the destination file might be busy for other
	# reasons.  In this case, the final cleanup might fail but the new
	# file should still install successfully.
	{
	  test ! -f "$dst" ||
	  $doit $rmcmd -f "$dst" 2>/dev/null ||
	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
	  } ||
	  { echo "$0: cannot unlink or rename $dst" >&2
	    (exit 1); exit 1
	  }
	} &&

	# Now rename the file to the real destination.
	$doit $mvcmd "$dsttmp" "$dst"
      }
    fi || exit 1

    trap '' 0
  fi
done

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

Added jni/tkzinc/tclconfig/tcl.m4.







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
# tcl.m4 --
#
#	This file provides a set of autoconf macros to help TEA-enable
#	a Tcl extension.
#
# Copyright (c) 1999-2000 Ajuba Solutions.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

AC_PREREQ(2.57)

dnl TEA extensions pass us the version of TEA they think they
dnl are compatible with (must be set in TEA_INIT below)
dnl TEA_VERSION="3.9"

# Possible values for key variables defined:
#
# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem')
# TEA_PLATFORM        - windows unix
#

#------------------------------------------------------------------------
# TEA_PATH_TCLCONFIG --
#
#	Locate the tclConfig.sh file and perform a sanity check on
#	the Tcl compile flags
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-tcl=...
#
#	Defines the following vars:
#		TCL_BIN_DIR	Full path to the directory containing
#				the tclConfig.sh file
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_TCLCONFIG], [
    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_INIT])
    #
    # Ok, lets find the tcl configuration
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-tcl
    #

    if test x"${no_tcl}" = x ; then
	# we reset no_tcl in case something fails here
	no_tcl=true
	AC_ARG_WITH(tcl,
	    AC_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    with_tclconfig="${withval}")
	AC_MSG_CHECKING([for Tcl configuration])
	AC_CACHE_VAL(ac_cv_c_tclconfig,[

	    # First check to see if --with-tcl was specified.
	    if test x"${with_tclconfig}" != x ; then
		case "${with_tclconfig}" in
		    */tclConfig.sh )
			if test -f "${with_tclconfig}"; then
			    AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])
			    with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
			fi ;;
		esac
		if test -f "${with_tclconfig}/tclConfig.sh" ; then
		    ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
		else
		    AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
		fi
	    fi

	    # then check for a private Tcl installation
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in \
			../tcl \
			`ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
			../../tcl \
			`ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
			../../../tcl \
			`ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		done
	    fi

	    # on Darwin, check in Framework installation locations
	    if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
			`ls -d /Library/Frameworks 2>/dev/null` \
			`ls -d /Network/Library/Frameworks 2>/dev/null` \
			`ls -d /System/Library/Frameworks 2>/dev/null` \
			; do
		    if test -f "$i/Tcl.framework/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
			break
		    fi
		done
	    fi

	    # TEA specific: on Windows, check in common installation locations
	    if test "${TEA_PLATFORM}" = "windows" \
		-a x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d C:/Tcl/lib 2>/dev/null` \
			`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few common install locations
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			`ls -d /usr/lib/tcl8.6 2>/dev/null` \
			`ls -d /usr/lib/tcl8.5 2>/dev/null` \
			; do
		    if test -f "$i/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few other private locations
	    if test x"${ac_cv_c_tclconfig}" = x ; then
		for i in \
			${srcdir}/../tcl \
			`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tclConfig.sh" ; then
			ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		done
	    fi
	])

	if test x"${ac_cv_c_tclconfig}" = x ; then
	    TCL_BIN_DIR="# no Tcl configs found"
	    AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])
	else
	    no_tcl=
	    TCL_BIN_DIR="${ac_cv_c_tclconfig}"
	    AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_PATH_TKCONFIG --
#
#	Locate the tkConfig.sh file
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-tk=...
#
#	Defines the following vars:
#		TK_BIN_DIR	Full path to the directory containing
#				the tkConfig.sh file
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_TKCONFIG], [
    #
    # Ok, lets find the tk configuration
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-tk
    #

    if test x"${no_tk}" = x ; then
	# we reset no_tk in case something fails here
	no_tk=true
	AC_ARG_WITH(tk,
	    AC_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    with_tkconfig="${withval}")
	AC_MSG_CHECKING([for Tk configuration])
	AC_CACHE_VAL(ac_cv_c_tkconfig,[

	    # First check to see if --with-tkconfig was specified.
	    if test x"${with_tkconfig}" != x ; then
		case "${with_tkconfig}" in
		    */tkConfig.sh )
			if test -f "${with_tkconfig}"; then
			    AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])
			    with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`"
			fi ;;
		esac
		if test -f "${with_tkconfig}/tkConfig.sh" ; then
		    ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`"
		elif test -f "${with_tkconfig}/sdl2tkConfig.sh" ; then
		    ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`"
		else
		    AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
		fi
	    fi

	    # then check for a private Tk library
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in \
			../tk \
			`ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \
			../../tk \
			`ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \
			../../../tk \
			`ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		    if test -f "$i/sdl/sdl2tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/sdl; pwd)`"
			break
		    fi
		done
	    fi

	    # on Darwin, check in Framework installation locations
	    if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
			`ls -d /Library/Frameworks 2>/dev/null` \
			`ls -d /Network/Library/Frameworks 2>/dev/null` \
			`ls -d /System/Library/Frameworks 2>/dev/null` \
			; do
		    if test -f "$i/Tk.framework/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few common install locations
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # TEA specific: on Windows, check in common installation locations
	    if test "${TEA_PLATFORM}" = "windows" \
		-a x"${ac_cv_c_tkconfig}" = x ; then
		for i in `ls -d C:/Tcl/lib 2>/dev/null` \
			`ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi

	    # check in a few other private locations
	    if test x"${ac_cv_c_tkconfig}" = x ; then
		for i in \
			${srcdir}/../tk \
			`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
			`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
		    if test "${TEA_PLATFORM}" = "windows" \
			    -a -f "$i/win/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
			break
		    fi
		    if test -f "$i/unix/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
			break
		    fi
		    if test -f "$i/sdl/sdl2tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i/sdl; pwd)`"
			break
		    fi
		done
	    fi
	])

	if test x"${ac_cv_c_tkconfig}" = x ; then
	    TK_BIN_DIR="# no Tk configs found"
	    AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])
	else
	    no_tk=
	    TK_BIN_DIR="${ac_cv_c_tkconfig}"
	    AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_LOAD_TCLCONFIG --
#
#	Load the tclConfig.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		TCL_BIN_DIR
#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		TCL_LIB_FILE
#------------------------------------------------------------------------

AC_DEFUN([TEA_LOAD_TCLCONFIG], [
    AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])

    if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
        AC_MSG_RESULT([loading])
	. "${TCL_BIN_DIR}/tclConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
    fi

    # eval is required to do the TCL_DBGX substitution
    eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
    eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""

    # If the TCL_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TCL_LIB_SPEC will be set to the value
    # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
    # instead of TCL_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TCL_BIN_DIR}/Makefile" ; then
        TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
        TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
        TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
    elif test "`uname -s`" = "Darwin"; then
	# If Tcl was built as a framework, attempt to use the libraries
	# from the framework at the given location so that linking works
	# against Tcl.framework installed in an arbitrary location.
	case ${TCL_DEFS} in
	    *TCL_FRAMEWORK*)
		if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
		    for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
			     "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
			if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
			    TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
			    break
			fi
		    done
		fi
		if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
		    TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}"  | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
		    TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
		fi
		;;
	esac
    fi

    # eval is required to do the TCL_DBGX substitution
    eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
    eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
    eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
    eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""

    AC_SUBST(TCL_VERSION)
    AC_SUBST(TCL_PATCH_LEVEL)
    AC_SUBST(TCL_BIN_DIR)
    AC_SUBST(TCL_SRC_DIR)

    AC_SUBST(TCL_LIB_FILE)
    AC_SUBST(TCL_LIB_FLAG)
    AC_SUBST(TCL_LIB_SPEC)

    AC_SUBST(TCL_STUB_LIB_FILE)
    AC_SUBST(TCL_STUB_LIB_FLAG)
    AC_SUBST(TCL_STUB_LIB_SPEC)

    AC_MSG_CHECKING([platform])
    hold_cc=$CC; CC="$TCL_CC"
    AC_TRY_COMPILE(,[
	    #ifdef _WIN32
		#error win32
	    #endif
    ], TEA_PLATFORM="unix",
	    TEA_PLATFORM="windows"
    )
    CC=$hold_cc
    AC_MSG_RESULT($TEA_PLATFORM)

    # The BUILD_$pkg is to define the correct extern storage class
    # handling when making this package
    AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [],
	    [Building extension source?])
    # Do this here as we have fully defined TEA_PLATFORM now
    if test "${TEA_PLATFORM}" = "windows" ; then
	EXEEXT=".exe"
	CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp"
    fi

    # TEA specific:
    AC_SUBST(CLEANFILES)
    AC_SUBST(TCL_LIBS)
    AC_SUBST(TCL_DEFS)
    AC_SUBST(TCL_EXTRA_CFLAGS)
    AC_SUBST(TCL_LD_FLAGS)
    AC_SUBST(TCL_SHLIB_LD_LIBS)
])

#------------------------------------------------------------------------
# TEA_LOAD_TKCONFIG --
#
#	Load the tkConfig.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		TK_BIN_DIR
#
# Results:
#
#	Sets the following vars that should be in tkConfig.sh:
#		TK_BIN_DIR
#------------------------------------------------------------------------

AC_DEFUN([TEA_LOAD_TKCONFIG], [
    AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])

    if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
        AC_MSG_RESULT([loading])
	. "${TK_BIN_DIR}/tkConfig.sh"
    elif test -f "${TK_BIN_DIR}/sdl2tkConfig.sh" ; then
        AC_MSG_RESULT([loading])
	. "${TK_BIN_DIR}/sdl2tkConfig.sh"
    else
        AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
    fi

    # eval is required to do the TK_DBGX substitution
    eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
    eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""

    # If the TK_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable TK_LIB_SPEC will be set to the value
    # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
    # instead of TK_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    if test -f "${TK_BIN_DIR}/Makefile" ; then
        TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
        TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
        TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
    elif test "`uname -s`" = "Darwin"; then
	# If Tk was built as a framework, attempt to use the libraries
	# from the framework at the given location so that linking works
	# against Tk.framework installed in an arbitrary location.
	case ${TK_DEFS} in
	    *TK_FRAMEWORK*)
		if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
		    for i in "`cd "${TK_BIN_DIR}"; pwd`" \
			     "`cd "${TK_BIN_DIR}"/../..; pwd`"; do
			if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then
			    TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}"
			    break
			fi
		    done
		fi
		if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then
		    TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}"  | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
		    TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
		fi
		;;
	esac
    fi

    # eval is required to do the TK_DBGX substitution
    eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
    eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
    eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
    eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""

    # TEA specific: Ensure windowingsystem is defined
    case ${TK_DEFS} in
	*PLATFORM_SDL*)
	    TEA_WINDOWINGSYSTEM="x11"
	    TEA_USE_SDL=yes
	    ;;
    esac
    if test "${TEA_USE_SDL}" = "yes" ; then
	true
    elif test "${TEA_PLATFORM}" = "unix" ; then
	case ${TK_DEFS} in
	    *MAC_OSX_TK*)
		AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?])
		TEA_WINDOWINGSYSTEM="aqua"
		;;
	    *)
		TEA_WINDOWINGSYSTEM="x11"
		;;
	esac
    elif test "${TEA_PLATFORM}" = "windows" ; then
	TEA_WINDOWINGSYSTEM="win32"
    fi

    AC_SUBST(TK_VERSION)
    AC_SUBST(TK_BIN_DIR)
    AC_SUBST(TK_SRC_DIR)

    AC_SUBST(TK_LIB_FILE)
    AC_SUBST(TK_LIB_FLAG)
    AC_SUBST(TK_LIB_SPEC)

    AC_SUBST(TK_STUB_LIB_FILE)
    AC_SUBST(TK_STUB_LIB_FLAG)
    AC_SUBST(TK_STUB_LIB_SPEC)

    # TEA specific:
    AC_SUBST(TK_LIBS)
    AC_SUBST(TK_XINCLUDES)
])

#------------------------------------------------------------------------
# TEA_PROG_TCLSH
#	Determine the fully qualified path name of the tclsh executable
#	in the Tcl build directory or the tclsh installed in a bin
#	directory. This macro will correctly determine the name
#	of the tclsh executable even if tclsh has not yet been
#	built in the build directory. The tclsh found is always
#	associated with a tclConfig.sh file. This tclsh should be used
#	only for running extension test cases. It should never be
#	or generation of files (like pkgIndex.tcl) at build time.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		TCLSH_PROG
#------------------------------------------------------------------------

AC_DEFUN([TEA_PROG_TCLSH], [
    AC_MSG_CHECKING([for tclsh])
    if test -f "${TCL_BIN_DIR}/Makefile" ; then
        # tclConfig.sh is in Tcl build directory
        if test "${TEA_PLATFORM}" = "windows"; then
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
        else
            TCLSH_PROG="${TCL_BIN_DIR}/tclsh"
        fi
    else
        # tclConfig.sh is in install location
        if test "${TEA_PLATFORM}" = "windows"; then
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
        else
            TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}"
        fi
        list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \
              `ls -d ${TCL_BIN_DIR}/..     2>/dev/null` \
              `ls -d ${TCL_PREFIX}/bin     2>/dev/null`"
        for i in $list ; do
            if test -f "$i/${TCLSH_PROG}" ; then
                REAL_TCL_BIN_DIR="`cd "$i"; pwd`/"
                break
            fi
        done
        TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}"
    fi
    AC_MSG_RESULT([${TCLSH_PROG}])
    AC_SUBST(TCLSH_PROG)
])

#------------------------------------------------------------------------
# TEA_PROG_WISH
#	Determine the fully qualified path name of the wish executable
#	in the Tk build directory or the wish installed in a bin
#	directory. This macro will correctly determine the name
#	of the wish executable even if wish has not yet been
#	built in the build directory. The wish found is always
#	associated with a tkConfig.sh file. This wish should be used
#	only for running extension test cases. It should never be
#	or generation of files (like pkgIndex.tcl) at build time.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#		WISH_PROG
#------------------------------------------------------------------------

AC_DEFUN([TEA_PROG_WISH], [
    AC_MSG_CHECKING([for wish])
    if test -f "${TK_BIN_DIR}/Makefile" ; then
        # tkConfig.sh is in Tk build directory
        if test "${TEA_PLATFORM}" = "windows"; then
            WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
        else
            WISH_PROG="${TK_BIN_DIR}/wish"
        fi
    else
        # tkConfig.sh is in install location
        if test "${TEA_PLATFORM}" = "windows"; then
            WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
        else
            WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}"
        fi
        list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \
              `ls -d ${TK_BIN_DIR}/..     2>/dev/null` \
              `ls -d ${TK_PREFIX}/bin     2>/dev/null`"
        for i in $list ; do
            if test -f "$i/${WISH_PROG}" ; then
                REAL_TK_BIN_DIR="`cd "$i"; pwd`/"
                break
            fi
        done
        WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}"
    fi
    AC_MSG_RESULT([${WISH_PROG}])
    AC_SUBST(WISH_PROG)
])

#------------------------------------------------------------------------
# TEA_ENABLE_SHARED --
#
#	Allows the building of shared libraries
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-shared=yes|no
#
#	Defines the following vars:
#		STATIC_BUILD	Used for building import/export libraries
#				on Windows.
#
#	Sets the following vars:
#		SHARED_BUILD	Value of 1 or 0
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_SHARED], [
    AC_MSG_CHECKING([how to build libraries])
    AC_ARG_ENABLE(shared,
	AC_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	AC_MSG_RESULT([shared])
	SHARED_BUILD=1
    else
	AC_MSG_RESULT([static])
	SHARED_BUILD=0
	AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
    fi
    AC_SUBST(SHARED_BUILD)
])

#------------------------------------------------------------------------
# TEA_ENABLE_THREADS --
#
#	Specify if thread support should be enabled.  If "yes" is specified
#	as an arg (optional), threads are enabled by default, "no" means
#	threads are disabled.  "yes" is the default.
#
#	TCL_THREADS is checked so that if you are compiling an extension
#	against a threaded core, your extension must be compiled threaded
#	as well.
#
#	Note that it is legal to have a thread enabled extension run in a
#	threaded or non-threaded Tcl core, but a non-threaded extension may
#	only run in a non-threaded Tcl core.
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-threads
#
#	Sets the following vars:
#		THREADS_LIBS	Thread library(s)
#
#	Defines the following vars:
#		TCL_THREADS
#		_REENTRANT
#		_THREAD_SAFE
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_THREADS], [
    AC_ARG_ENABLE(threads,
	AC_HELP_STRING([--enable-threads],
	    [build with threads]),
	[tcl_ok=$enableval], [tcl_ok=yes])

    if test "${enable_threads+set}" = set; then
	enableval="$enable_threads"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
	TCL_THREADS=1

	if test "${TEA_PLATFORM}" != "windows" ; then
	    # We are always OK on Windows, so check what this platform wants:

	    # USE_THREAD_ALLOC tells us to try the special thread-based
	    # allocator that significantly reduces lock contention
	    AC_DEFINE(USE_THREAD_ALLOC, 1,
		[Do we want to use the threaded memory allocator?])
	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    if test "`uname -s`" = "SunOS" ; then
		AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
			[Do we really want to follow the standard? Yes we do!])
	    fi
	    AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
	    AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
	    if test "$tcl_ok" = "no"; then
		# Check a little harder for __pthread_mutex_init in the same
		# library, as some systems hide it there until pthread.h is
		# defined.  We could alternatively do an AC_TRY_COMPILE with
		# pthread.h, but that will work with libpthread really doesn't
		# exist, like AIX 4.2.  [Bug: 4359]
		AC_CHECK_LIB(pthread, __pthread_mutex_init,
		    tcl_ok=yes, tcl_ok=no)
	    fi

	    if test "$tcl_ok" = "yes"; then
		# The space is needed
		THREADS_LIBS=" -lpthread"
	    else
		AC_CHECK_LIB(pthreads, pthread_mutex_init,
		    tcl_ok=yes, tcl_ok=no)
		if test "$tcl_ok" = "yes"; then
		    # The space is needed
		    THREADS_LIBS=" -lpthreads"
		else
		    AC_CHECK_LIB(c, pthread_mutex_init,
			tcl_ok=yes, tcl_ok=no)
		    if test "$tcl_ok" = "no"; then
			AC_CHECK_LIB(c_r, pthread_mutex_init,
			    tcl_ok=yes, tcl_ok=no)
			if test "$tcl_ok" = "yes"; then
			    # The space is needed
			    THREADS_LIBS=" -pthread"
			else
			    TCL_THREADS=0
			    AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled])
			fi
		    fi
		fi
	    fi
	fi
    else
	TCL_THREADS=0
    fi
    # Do checking message here to not mess up interleaved configure output
    AC_MSG_CHECKING([for building with threads])
    if test "${TCL_THREADS}" = 1; then
	AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
	AC_MSG_RESULT([yes (default)])
    else
	AC_MSG_RESULT([no])
    fi
    # TCL_THREADS sanity checking.  See if our request for building with
    # threads is the same as the way Tcl was built.  If not, warn the user.
    case ${TCL_DEFS} in
	*THREADS=1*)
	    if test "${TCL_THREADS}" = "0"; then
		AC_MSG_WARN([
    Building ${PACKAGE_NAME} without threads enabled, but building against Tcl
    that IS thread-enabled.  It is recommended to use --enable-threads.])
	    fi
	    ;;
	*)
	    if test "${TCL_THREADS}" = "1"; then
		AC_MSG_WARN([
    --enable-threads requested, but building against a Tcl that is NOT
    thread-enabled.  This is an OK configuration that will also run in
    a thread-enabled core.])
	    fi
	    ;;
    esac
    AC_SUBST(TCL_THREADS)
])

#------------------------------------------------------------------------
# TEA_ENABLE_SYMBOLS --
#
#	Specify if debugging symbols should be used.
#	Memory (TCL_MEM_DEBUG) debugging can also be enabled.
#
# Arguments:
#	none
#
#	TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives
#	the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted.
#	Requires the following vars to be set in the Makefile:
#		CFLAGS_DEFAULT
#		LDFLAGS_DEFAULT
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-symbols
#
#	Defines the following vars:
#		CFLAGS_DEFAULT	Sets to $(CFLAGS_DEBUG) if true
#				Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false
#		LDFLAGS_DEFAULT	Sets to $(LDFLAGS_DEBUG) if true
#				Sets to $(LDFLAGS_OPTIMIZE) if false
#		DBGX		Formerly used as debug library extension;
#				always blank now.
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_SYMBOLS], [
    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_CONFIG_CFLAGS])
    AC_MSG_CHECKING([for build with symbols])
    AC_ARG_ENABLE(symbols,
	AC_HELP_STRING([--enable-symbols],
	    [build with debugging symbols (default: off)]),
	[tcl_ok=$enableval], [tcl_ok=no])
    DBGX=""
    if test "$tcl_ok" = "no"; then
	CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG"
	LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}"
	AC_MSG_RESULT([no])
    else
	CFLAGS_DEFAULT="${CFLAGS_DEBUG}"
	LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}"
	if test "$tcl_ok" = "yes"; then
	    AC_MSG_RESULT([yes (standard debugging)])
	fi
    fi
    # TEA specific:
    if test "${TEA_PLATFORM}" != "windows" ; then
	LDFLAGS_DEFAULT="${LDFLAGS}"
    fi
    AC_SUBST(CFLAGS_DEFAULT)
    AC_SUBST(LDFLAGS_DEFAULT)
    AC_SUBST(TCL_DBGX)

    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
	AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
    fi

    if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
	if test "$tcl_ok" = "all"; then
	    AC_MSG_RESULT([enabled symbols mem debugging])
	else
	    AC_MSG_RESULT([enabled $tcl_ok debugging])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_ENABLE_LANGINFO --
#
#	Allows use of modern nl_langinfo check for better l10n.
#	This is only relevant for Unix.
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--enable-langinfo=yes|no (default is yes)
#
#	Defines the following vars:
#		HAVE_LANGINFO	Triggers use of nl_langinfo if defined.
#------------------------------------------------------------------------

AC_DEFUN([TEA_ENABLE_LANGINFO], [
    AC_ARG_ENABLE(langinfo,
	AC_HELP_STRING([--enable-langinfo],
	    [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
	[langinfo_ok=$enableval], [langinfo_ok=yes])

    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; then
	AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
    fi
    AC_MSG_CHECKING([whether to use nl_langinfo])
    if test "$langinfo_ok" = "yes"; then
	AC_CACHE_VAL(tcl_cv_langinfo_h, [
	    AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
		    [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
	AC_MSG_RESULT([$tcl_cv_langinfo_h])
	if test $tcl_cv_langinfo_h = yes; then
	    AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
	fi
    else
	AC_MSG_RESULT([$langinfo_ok])
    fi
])

#--------------------------------------------------------------------
# TEA_CONFIG_SYSTEM
#
#	Determine what the system is (some things cannot be easily checked
#	on a feature-driven basis, alas). This can usually be done via the
#	"uname" command.
#
# Arguments:
#	none
#
# Results:
#	Defines the following var:
#
#	system -	System/platform/version identification code.
#--------------------------------------------------------------------

AC_DEFUN([TEA_CONFIG_SYSTEM], [
    AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
	# TEA specific:
	if test "${TEA_PLATFORM}" = "windows" ; then
	    tcl_cv_sys_version=windows
	else
	    tcl_cv_sys_version=`uname -s`-`uname -r`
	    if test "$?" -ne 0 ; then
		AC_MSG_WARN([can't find uname command])
		tcl_cv_sys_version=unknown
	    else
		if test "`uname -s`" = "AIX" ; then
		    tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
		fi
	    fi
	fi
    ])
    system=$tcl_cv_sys_version
])

#--------------------------------------------------------------------
# TEA_CONFIG_CFLAGS
#
#	Try to determine the proper flags to pass to the compiler
#	for building shared libraries and other such nonsense.
#
# Arguments:
#	none
#
# Results:
#
#	Defines and substitutes the following vars:
#
#	DL_OBJS, DL_LIBS - removed for TEA, only needed by core.
#       LDFLAGS -      Flags to pass to the compiler when linking object
#                       files into an executable application binary such
#                       as tclsh.
#       LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib",
#                       that tell the run-time dynamic linker where to look
#                       for shared libraries such as libtcl.so.  Depends on
#                       the variable LIB_RUNTIME_DIR in the Makefile. Could
#                       be the same as CC_SEARCH_FLAGS if ${CC} is used to link.
#       CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib",
#                       that tell the run-time dynamic linker where to look
#                       for shared libraries such as libtcl.so.  Depends on
#                       the variable LIB_RUNTIME_DIR in the Makefile.
#       SHLIB_CFLAGS -  Flags to pass to cc when compiling the components
#                       of a shared library (may request position-independent
#                       code, among other things).
#       SHLIB_LD -      Base command to use for combining object files
#                       into a shared library.
#       SHLIB_LD_LIBS - Dependent libraries for the linker to scan when
#                       creating shared libraries.  This symbol typically
#                       goes at the end of the "ld" commands that build
#                       shared libraries. The value of the symbol defaults to
#                       "${LIBS}" if all of the dependent libraries should
#                       be specified when creating a shared library.  If
#                       dependent libraries should not be specified (as on
#                       SunOS 4.x, where they cause the link to fail, or in
#                       general if Tcl and Tk aren't themselves shared
#                       libraries), then this symbol has an empty string
#                       as its value.
#       SHLIB_SUFFIX -  Suffix to use for the names of dynamically loadable
#                       extensions.  An empty string means we don't know how
#                       to use shared libraries on this platform.
#       LIB_SUFFIX -    Specifies everything that comes after the "libfoo"
#                       in a static or shared library name, using the $PACKAGE_VERSION variable
#                       to put the version in the right place.  This is used
#                       by platforms that need non-standard library names.
#                       Examples:  ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs
#                       to have a version after the .so, and ${PACKAGE_VERSION}.a
#                       on AIX, since a shared library needs to have
#                       a .a extension whereas shared objects for loadable
#                       extensions have a .so extension.  Defaults to
#                       ${PACKAGE_VERSION}${SHLIB_SUFFIX}.
#	CFLAGS_DEBUG -
#			Flags used when running the compiler in debug mode
#	CFLAGS_OPTIMIZE -
#			Flags used when running the compiler in optimize mode
#	CFLAGS -	Additional CFLAGS added as necessary (usually 64-bit)
#--------------------------------------------------------------------

AC_DEFUN([TEA_CONFIG_CFLAGS], [
    dnl TEA specific: Make sure we are initialized
    AC_REQUIRE([TEA_INIT])

    # Step 0.a: Enable 64 bit support?

    AC_MSG_CHECKING([if 64bit support is requested])
    AC_ARG_ENABLE(64bit,
	AC_HELP_STRING([--enable-64bit],
	    [enable 64bit support (default: off)]),
	[do64bit=$enableval], [do64bit=no])
    AC_MSG_RESULT([$do64bit])

    # Step 0.b: Enable Solaris 64 bit VIS support?

    AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
    AC_ARG_ENABLE(64bit-vis,
	AC_HELP_STRING([--enable-64bit-vis],
	    [enable 64bit Sparc VIS support (default: off)]),
	[do64bitVIS=$enableval], [do64bitVIS=no])
    AC_MSG_RESULT([$do64bitVIS])
    # Force 64bit on with VIS
    AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])

    # Step 0.c: Check if visibility support is available. Do this here so
    # that platform specific alternatives can be used below if this fails.

    AC_CACHE_CHECK([if compiler supports visibility "hidden"],
	tcl_cv_cc_visibility_hidden, [
	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
	AC_TRY_LINK([
	    extern __attribute__((__visibility__("hidden"))) void f(void);
	    void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
	    tcl_cv_cc_visibility_hidden=no)
	CFLAGS=$hold_cflags])
    AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
	AC_DEFINE(MODULE_SCOPE,
	    [extern __attribute__((__visibility__("hidden")))],
	    [Compiler support for module scope symbols])
	AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
    ])

    # Step 0.d: Disable -rpath support?

    AC_MSG_CHECKING([if rpath support is requested])
    AC_ARG_ENABLE(rpath,
	AC_HELP_STRING([--disable-rpath],
	    [disable rpath support (default: on)]),
	[doRpath=$enableval], [doRpath=yes])
    AC_MSG_RESULT([$doRpath])

    # TEA specific: Cross-compiling options for Windows/CE builds?

    AS_IF([test "${TEA_PLATFORM}" = windows], [
	AC_MSG_CHECKING([if Windows/CE build is requested])
	AC_ARG_ENABLE(wince,
	    AC_HELP_STRING([--enable-wince],
		[enable Win/CE support (where applicable)]),
	    [doWince=$enableval], [doWince=no])
	AC_MSG_RESULT([$doWince])
    ])

    # Set the variable "system" to hold the name and version number
    # for the system.

    TEA_CONFIG_SYSTEM

    # Require ranlib early so we can override it in special cases below.

    AC_REQUIRE([AC_PROG_RANLIB])

    # Set configuration options based on system name and version.
    # This is similar to Tcl's unix/tcl.m4 except that we've added a
    # "windows" case and removed some core-only vars.

    do64bit_ok=no
    # default to '{$LIBS}' and set to "" on per-platform necessary basis
    SHLIB_LD_LIBS='${LIBS}'
    # When ld needs options to work in 64-bit mode, put them in
    # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
    # is disabled by the user. [Bug 1016796]
    LDFLAGS_ARCH=""
    UNSHARED_LIB_SUFFIX=""
    # TEA specific: use PACKAGE_VERSION instead of VERSION
    TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'
    ECHO_VERSION='`echo ${PACKAGE_VERSION}`'
    TCL_LIB_VERSIONS_OK=ok
    CFLAGS_DEBUG=-g
    AS_IF([test "$GCC" = yes], [
	CFLAGS_OPTIMIZE=-O2
	CFLAGS_WARNING="-Wall"
    ], [
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""
    ])
    CC_OBJNAME="-o \[$]@"
    AC_CHECK_TOOL(AR, ar)
    STLIB_LD='${AR} cr'
    LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
    AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"])
    case $system in
	# TEA specific:
	windows)
	    # This is a 2-stage check to make sure we have the 64-bit SDK
	    # We have to know where the SDK is installed.
	    # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
	    # MACHINE is IX86 for LINK, but this is used by the manifest,
	    # which requires x86|amd64|ia64.
	    MACHINE="X86"
	    if test "$do64bit" != "no" ; then
		if test "x${MSSDK}x" = "xx" ; then
		    MSSDK="C:/Progra~1/Microsoft Platform SDK"
		fi
		MSSDK=`echo "$MSSDK" | sed -e  's!\\\!/!g'`
		PATH64=""
		case "$do64bit" in
		    amd64|x64|yes)
			MACHINE="AMD64" ; # default to AMD64 64-bit build
			PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
			;;
		    ia64)
			MACHINE="IA64"
			PATH64="${MSSDK}/Bin/Win64"
			;;
		esac
		if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then
		    AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode])
		    AC_MSG_WARN([Ensure latest Platform SDK is installed])
		    do64bit="no"
		else
		    AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		    do64bit_ok="yes"
		fi
	    fi

	    if test "$doWince" != "no" ; then
		if test "$do64bit" != "no" ; then
		    AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible])
		fi
		if test "$GCC" = "yes" ; then
		    AC_MSG_ERROR([Windows/CE and GCC builds incompatible])
		fi
		TEA_PATH_CELIB
		# Set defaults for common evc4/PPC2003 setup
		# Currently Tcl requires 300+, possibly 420+ for sockets
		CEVERSION=420; 		# could be 211 300 301 400 420 ...
		TARGETCPU=ARMV4;	# could be ARMV4 ARM MIPS SH3 X86 ...
		ARCH=ARM;		# could be ARM MIPS X86EM ...
		PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
		if test "$doWince" != "yes"; then
		    # If !yes then the user specified something
		    # Reset ARCH to allow user to skip specifying it
		    ARCH=
		    eval `echo $doWince | awk -F, '{ \
	    if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \
	    if ([$]1 < 400)   { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
	    if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \
	    if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \
	    if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \
		    }'`
		    if test "x${ARCH}" = "x" ; then
			ARCH=$TARGETCPU;
		    fi
		fi
		OSVERSION=WCE$CEVERSION;
	    	if test "x${WCEROOT}" = "x" ; then
			WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
		    if test ! -d "${WCEROOT}" ; then
			WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
		    fi
		fi
		if test "x${SDKROOT}" = "x" ; then
		    SDKROOT="C:/Program Files/Windows CE Tools"
		    if test ! -d "${SDKROOT}" ; then
			SDKROOT="C:/Windows CE Tools"
		    fi
		fi
		WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
		SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
		if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \
		    -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
		    AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])
		    doWince="no"
		else
		    # We could PATH_NOSPACE these, but that's not important,
		    # as long as we quote them when used.
		    CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
		    if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
			CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
		    fi
		    CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
    		fi
	    fi

	    if test "$GCC" != "yes" ; then
	        if test "${SHARED_BUILD}" = "0" ; then
		    runtime=-MT
	        else
		    runtime=-MD
	        fi

                if test "$do64bit" != "no" ; then
		    # All this magic is necessary for the Win64 SDK RC1 - hobbs
		    CC="\"${PATH64}/cl.exe\""
		    CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
		    RC="\"${MSSDK}/bin/rc.exe\""
		    lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
		    LINKBIN="\"${PATH64}/link.exe\""
		    CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d"
		    CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
		    # Avoid 'unresolved external symbol __security_cookie'
		    # errors, c.f. http://support.microsoft.com/?id=894573
		    TEA_ADD_LIBS([bufferoverflowU.lib])
		elif test "$doWince" != "no" ; then
		    CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
		    if test "${TARGETCPU}" = "X86"; then
			CC="\"${CEBINROOT}/cl.exe\""
		    else
			CC="\"${CEBINROOT}/cl${ARCH}.exe\""
		    fi
		    CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
		    RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
		    arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`
		    defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS"
		    if test "${SHARED_BUILD}" = "1" ; then
			# Static CE builds require static celib as well
		    	defs="${defs} _DLL"
		    fi
		    for i in $defs ; do
			AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i)
		    done
		    AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version])
		    AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version])
		    CFLAGS_DEBUG="-nologo -Zi -Od"
		    CFLAGS_OPTIMIZE="-nologo -Ox"
		    lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
		    lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
		    LINKBIN="\"${CEBINROOT}/link.exe\""
		    AC_SUBST(CELIB_DIR)
		else
		    RC="rc"
		    lflags="-nologo"
		    LINKBIN="link"
		    CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d"
		    CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
		fi
	    fi

	    if test "$GCC" = "yes"; then
		# mingw gcc mode
		AC_CHECK_TOOL(RC, windres)
		CFLAGS_DEBUG="-g"
		CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
		SHLIB_LD='${CC} -shared'
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
		LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"

		AC_CACHE_CHECK(for cross-compile version of gcc,
			ac_cv_cross,
			AC_TRY_COMPILE([
			    #ifdef _WIN32
				#error cross-compiler
			    #endif
			], [],
			ac_cv_cross=yes,
			ac_cv_cross=no)
		      )
		      if test "$ac_cv_cross" = "yes"; then
			case "$do64bit" in
			    amd64|x64|yes)
				CC="x86_64-w64-mingw32-gcc"
				LD="x86_64-w64-mingw32-ld"
				AR="x86_64-w64-mingw32-ar"
				RANLIB="x86_64-w64-mingw32-ranlib"
				RC="x86_64-w64-mingw32-windres"
			    ;;
			    *)
				CC="i686-w64-mingw32-gcc"
				LD="i686-w64-mingw32-ld"
				AR="i686-w64-mingw32-ar"
				RANLIB="i686-w64-mingw32-ranlib"
				RC="i686-w64-mingw32-windres"
			    ;;
			esac
		fi

	    else
		SHLIB_LD="${LINKBIN} -dll ${lflags}"
		# link -lib only works when -lib is the first arg
		STLIB_LD="${LINKBIN} -lib ${lflags}"
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'
		PATHTYPE=-w
		# For information on what debugtype is most useful, see:
		# http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
		# and also
		# http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx
		# This essentially turns it all on.
		LDFLAGS_DEBUG="-debug -debugtype:cv"
		LDFLAGS_OPTIMIZE="-release"
		CFLAGS_DEBUG="${CFLAGS_DEBUG} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE"
		CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE"
		CC_OBJNAME="-Fo\[$]@"
		if test "$doWince" != "no" ; then
		    LDFLAGS_CONSOLE="-link ${lflags}"
		    LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
		else
		    LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
		    LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
		fi
	    fi

	    SHLIB_SUFFIX=".dll"
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'

	    TCL_LIB_VERSIONS_OK=nodots
    	    ;;
	AIX-*)
	    AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
		# AIX requires the _r compiler when gcc isn't being used
		case "${CC}" in
		    *_r|*_r\ *)
			# ok ...
			;;
		    *)
			# Make sure only first arg gets _r
		    	CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
			;;
		esac
		AC_MSG_RESULT([Using $CC for compiling with threads])
	    ])
	    LIBS="$LIBS -lc"
	    SHLIB_CFLAGS=""
	    SHLIB_SUFFIX=".so"

	    LD_LIBRARY_PATH_VAR="LIBPATH"

	    # Check to enable 64-bit flags for compiler/linker
	    AS_IF([test "$do64bit" = yes], [
		AS_IF([test "$GCC" = yes], [
		    AC_MSG_WARN([64bit mode not supported with GCC on $system])
		], [
		    do64bit_ok=yes
		    CFLAGS="$CFLAGS -q64"
		    LDFLAGS_ARCH="-q64"
		    RANLIB="${RANLIB} -X64"
		    AR="${AR} -X64"
		    SHLIB_LD_FLAGS="-b64"
		])
	    ])

	    AS_IF([test "`uname -m`" = ia64], [
		# AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		AS_IF([test "$GCC" = yes], [
		    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		], [
		    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
		])
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
	    ], [
		AS_IF([test "$GCC" = yes], [
		    SHLIB_LD='${CC} -shared -Wl,-bexpall'
		], [
		    SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
		    LDFLAGS="$LDFLAGS -brtl"
		])
		SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
		CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ])
	    ;;
	BeOS*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} -nostart'
	    SHLIB_SUFFIX=".so"

	    #-----------------------------------------------------------
	    # Check for inet_ntoa in -lbind, for BeOS (which also needs
	    # -lsocket, even if the network functions are in -lnet which
	    # is always linked to, for compatibility.
	    #-----------------------------------------------------------
	    AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"])
	    ;;
	BSD/OS-4.*)
	    SHLIB_CFLAGS="-export-dynamic -fPIC"
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".so"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD='${CC} -shared'
	    SHLIB_SUFFIX=".dll"
	    EXEEXT=".exe"
	    do64bit_ok=yes
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	Haiku*)
	    LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
	    AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
	    ;;
	HP-UX-*.11.*)
	    # Use updated header definitions where possible
	    AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
	    # TEA specific: Needed by Tcl, but not most extensions
	    #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
	    #LIBS="$LIBS -lxnet"               # Use the XOPEN network library

	    AS_IF([test "`uname -m`" = ia64], [
		SHLIB_SUFFIX=".so"
		# Use newer C++ library for C++ extensions
		#if test "$GCC" != "yes" ; then
		#   CPPFLAGS="-AA"
		#fi
	    ], [
		SHLIB_SUFFIX=".sl"
	    ])
	    AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
	    AS_IF([test "$tcl_ok" = yes], [
		LDFLAGS="$LDFLAGS -Wl,-E"
		CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
		LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
		LD_LIBRARY_PATH_VAR="SHLIB_PATH"
	    ])
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CC} -shared'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ], [
		CFLAGS="$CFLAGS -z"
		# Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
		#CFLAGS="$CFLAGS +DAportable"
		SHLIB_CFLAGS="+z"
		SHLIB_LD="ld -b"
	    ])

	    # Check to enable 64-bit flags for compiler/linker
	    AS_IF([test "$do64bit" = "yes"], [
		AS_IF([test "$GCC" = yes], [
		    case `${CC} -dumpmachine` in
			hppa64*)
			    # 64-bit gcc in use.  Fix flags for GNU ld.
			    do64bit_ok=yes
			    SHLIB_LD='${CC} -shared'
			    AS_IF([test $doRpath = yes], [
				CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
			    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
			    ;;
			*)
			    AC_MSG_WARN([64bit mode not supported with GCC on $system])
			    ;;
		    esac
		], [
		    do64bit_ok=yes
		    CFLAGS="$CFLAGS +DD64"
		    LDFLAGS_ARCH="+DD64"
		])
	    ]) ;;
	IRIX-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "$GCC" = yes], [
		CFLAGS="$CFLAGS -mabi=n32"
		LDFLAGS="$LDFLAGS -mabi=n32"
	    ], [
		case $system in
		    IRIX-6.3)
			# Use to build 6.2 compatible binaries on 6.3.
			CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
			;;
		    *)
			CFLAGS="$CFLAGS -n32"
			;;
		esac
		LDFLAGS="$LDFLAGS -n32"
	    ])
	    ;;
	IRIX64-6.*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="ld -n32 -shared -rdata_shared"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])

	    # Check to enable 64-bit flags for compiler/linker

	    AS_IF([test "$do64bit" = yes], [
	        AS_IF([test "$GCC" = yes], [
	            AC_MSG_WARN([64bit mode not supported by gcc])
	        ], [
	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"
	        ])
	    ])
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"

	    # TEA specific:
	    CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"

	    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
	    SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'
	    # workaround when cross-compiling for Win32: no -fPIC and -Wl,...
	    if test "${TCL_SHLIB_SUFFIX}" = ".dll" ; then
		SHLIB_CFLAGS=""
		SHLIB_SUFFIX=".dll"
		DL_OBJS=""
		DL_LIBS=""
		TCL_LIB_VERSIONS_OK=nodots
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    else	
		LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
	    fi
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
	    AS_IF([test $do64bit = yes], [
		AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
		    CFLAGS=$hold_cflags])
		AS_IF([test $tcl_cv_cc_m64 = yes], [
		    CFLAGS="$CFLAGS -m64"
		    do64bit_ok=yes
		])
	   ])

	    # The combo of gcc + glibc has a bug related to inlining of
	    # functions like strtod(). The -fno-builtin flag should address
	    # this problem but it does not work. The -fno-inline flag is kind
	    # of overkill but it works. Disable inlining only when one of the
	    # files in compat/*.c is being linked in.

	    AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])
	    ;;
	Lynx*)
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_SUFFIX=".so"
	    CFLAGS_OPTIMIZE=-02
	    SHLIB_LD='${CC} -shared'
	    LD_FLAGS="-Wl,--export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    ;;
	OpenBSD-*)
	    arch=`arch -s`
	    case "$arch" in
	    alpha|sparc64)
		SHLIB_CFLAGS="-fPIC"
		;;
	    *)
		SHLIB_CFLAGS="-fpic"
		;;
	    esac
	    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}'
	    LDFLAGS="-Wl,-export-dynamic"
	    CFLAGS_OPTIMIZE="-O2"
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# On OpenBSD:	Compile with -pthread
		#		Don't link with -lpthread
		LIBS=`echo $LIBS | sed s/-lpthread//`
		CFLAGS="$CFLAGS -pthread"
	    ])
	    # OpenBSD doesn't do version numbers with dots.
	    UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
	    TCL_LIB_VERSIONS_OK=nodots
	    ;;
	NetBSD-*)
	    # NetBSD has ELF and can use 'cc -shared' to build shared libs
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
	    SHLIB_SUFFIX=".so"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the CFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS -pthread"
	    	LDFLAGS="$LDFLAGS -pthread"
	    ])
	    ;;
	FreeBSD-*)
	    # This configuration from FreeBSD Ports.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="${CC} -shared"
	    TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]"
	    TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$[@]"
	    SHLIB_SUFFIX=".so"
	    LDFLAGS=""
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
	    AS_IF([test "${TCL_THREADS}" = "1"], [
		# The -pthread needs to go in the LDFLAGS, not LIBS
		LIBS=`echo $LIBS | sed s/-pthread//`
		CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
		LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
	    case $system in
	    FreeBSD-3.*)
		# Version numbers are dot-stripped by system policy.
		TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .`
		UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
		SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so'
		TCL_LIB_VERSIONS_OK=nodots
		;;
	    esac
	    ;;
	Darwin-*)
	    CFLAGS_OPTIMIZE="-Os"
	    SHLIB_CFLAGS="-fno-common"
	    # To avoid discrepancies between what headers configure sees during
	    # preprocessing tests and compiling tests, move any -isysroot and
	    # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
	    CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
	    CFLAGS="`echo " ${CFLAGS}" | \
		awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
		if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
	    AS_IF([test $do64bit = yes], [
		case `arch` in
		    ppc)
			AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
				tcl_cv_cc_arch_ppc64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
				    tcl_cv_cc_arch_ppc64=no)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes
			]);;
		    i386)
			AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
				tcl_cv_cc_arch_x86_64, [
			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"
			    AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
				    tcl_cv_cc_arch_x86_64=no)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
			    CFLAGS="$CFLAGS -arch x86_64"
			    do64bit_ok=yes
			]);;
		    *)
			AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
		esac
	    ], [
		# Check for combined 32-bit and 64-bit fat build
		AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
		    && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
		    fat_32_64=yes])
	    ])
	    # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'
	    AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_single_module = yes], [
		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
	    ])
	    # TEA specific: link shlib with current and compatibility version flags
	    vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d`
	    SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}"
	    SHLIB_SUFFIX=".dylib"
	    # Don't use -prebind when building for Mac OS X 10.4 or later only:
	    AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
		"`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
		LDFLAGS="$LDFLAGS -prebind"])
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
		    tcl_cv_ld_search_paths_first, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
			tcl_cv_ld_search_paths_first=no)
		LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
	    ])
	    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
		AC_DEFINE(MODULE_SCOPE, [__private_extern__],
		    [Compiler support for module scope symbols])
		tcl_cv_cc_visibility_hidden=yes
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
	    # TEA specific: for combined 32 & 64 bit fat builds of Tk
	    # extensions, verify that 64-bit build is possible.
	    AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [
		AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [
		    AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
			LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
			AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();],
			    tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no)
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		])
		AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [
		    AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
			done
			CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}"
			LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}"
			AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);],
			    tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no)
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done])
		])
		# remove 64-bit arch flags from CFLAGS et al. if configuration
		# does not support 64-bit.
		AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [
		    AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags])
		    for v in CFLAGS CPPFLAGS LDFLAGS; do
			eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
		    done])
	    ])
	    ;;
	OS/390-*)
	    CFLAGS_OPTIMIZE=""		# Optimizer is buggy
	    AC_DEFINE(_OE_SOCKETS, 1,	# needed in sys/socket.h
		[Should OS/390 do the right thing with sockets?])
	    ;;
	OSF1-V*)
	    # Digital OSF/1
	    SHLIB_CFLAGS=""
	    AS_IF([test "$SHARED_BUILD" = 1], [
	        SHLIB_LD='ld -shared -expect_unresolved "*"'
	    ], [
	        SHLIB_LD='ld -non_shared -expect_unresolved "*"'
	    ])
	    SHLIB_SUFFIX=".so"
	    AS_IF([test $doRpath = yes], [
		CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
	    AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
		CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
	    # see pthread_intro(3) for pthread support on osf1, k.furukawa
	    AS_IF([test "${TCL_THREADS}" = 1], [
		CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
		CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
		LIBS=`echo $LIBS | sed s/-lpthreads//`
		AS_IF([test "$GCC" = yes], [
		    LIBS="$LIBS -lpthread -lmach -lexc"
		], [
		    CFLAGS="$CFLAGS -pthread"
		    LDFLAGS="$LDFLAGS -pthread"
		])
	    ])
	    ;;
	QNX-6*)
	    # QNX RTP
	    # This may work for all QNX, but it was only reported for v6.
	    SHLIB_CFLAGS="-fPIC"
	    SHLIB_LD="ld -Bshareable -x"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SCO_SV-3.2*)
	    AS_IF([test "$GCC" = yes], [
		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
	    ], [
		SHLIB_CFLAGS="-Kpic -belf"
		LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
	    ])
	    SHLIB_LD="ld -G"
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	SunOS-5.[[0-6]])
	    # Careful to not let 5.10+ fall into this case

	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		[Do we really want to follow the standard? Yes we do!])

	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_SUFFIX=".so"
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ], [
		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    ])
	    ;;
	SunOS-5*)
	    # Note: If _REENTRANT isn't defined, then Solaris
	    # won't define thread-safe library routines.

	    AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
	    AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
		[Do we really want to follow the standard? Yes we do!])

	    SHLIB_CFLAGS="-KPIC"

	    # Check to enable 64-bit flags for compiler/linker
	    AS_IF([test "$do64bit" = yes], [
		arch=`isainfo`
		AS_IF([test "$arch" = "sparcv9 sparc"], [
		    AS_IF([test "$GCC" = yes], [
			AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [
			    AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
			], [
			    do64bit_ok=yes
			    CFLAGS="$CFLAGS -m64 -mcpu=v9"
			    LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
			    SHLIB_CFLAGS="-fPIC"
			])
		    ], [
			do64bit_ok=yes
			AS_IF([test "$do64bitVIS" = yes], [
			    CFLAGS="$CFLAGS -xarch=v9a"
			    LDFLAGS_ARCH="-xarch=v9a"
			], [
			    CFLAGS="$CFLAGS -xarch=v9"
			    LDFLAGS_ARCH="-xarch=v9"
			])
			# Solaris 64 uses this as well
			#LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
		    ])
		], [AS_IF([test "$arch" = "amd64 i386"], [
		    AS_IF([test "$GCC" = yes], [
			case $system in
			    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
				do64bit_ok=yes
				CFLAGS="$CFLAGS -m64"
				LDFLAGS="$LDFLAGS -m64";;
			    *)
				AC_MSG_WARN([64bit mode not supported with GCC on $system]);;
			esac
		    ], [
			do64bit_ok=yes
			case $system in
			    SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
				CFLAGS="$CFLAGS -m64"
				LDFLAGS="$LDFLAGS -m64";;
			    *)
				CFLAGS="$CFLAGS -xarch=amd64"
				LDFLAGS="$LDFLAGS -xarch=amd64";;
			esac
		    ])
		], [AC_MSG_WARN([64bit mode not supported for $arch])])])
	    ])

	    SHLIB_SUFFIX=".so"
	    AS_IF([test "$GCC" = yes], [
		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
		AS_IF([test "$do64bit_ok" = yes], [
		    AS_IF([test "$arch" = "sparcv9 sparc"], [
			# We need to specify -static-libgcc or we need to
			# add the path to the sparv9 libgcc.
			# JH: static-libgcc is necessary for core Tcl, but may
			# not be necessary for extensions.
			SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
			# for finding sparcv9 libgcc, get the regular libgcc
			# path, remove so name and append 'sparcv9'
			#v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
			#CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
		    ], [AS_IF([test "$arch" = "amd64 i386"], [
			# JH: static-libgcc is necessary for core Tcl, but may
			# not be necessary for extensions.
			SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
		    ])])
		])
	    ], [
		case $system in
		    SunOS-5.[[1-9]][[0-9]]*)
			# TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
			SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';;
		    *)
			SHLIB_LD='/usr/ccs/bin/ld -G -z text';;
		esac
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
	    ])
	    ;;
	UNIX_SV* | UnixWare-5*)
	    SHLIB_CFLAGS="-KPIC"
	    SHLIB_LD='${CC} -G'
	    SHLIB_LD_LIBS=""
	    SHLIB_SUFFIX=".so"
	    # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
	    # that don't grok the -Bexport option.  Test that it does.
	    AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
	        LDFLAGS=$hold_ldflags])
	    AS_IF([test $tcl_cv_ld_Bexport = yes], [
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
    esac

    AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [
	AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])
    ])

dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so
dnl # until the end of configure, as configure's compile and link tests use
dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
dnl # preprocessing tests use only CPPFLAGS.
    AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])

    # Add in the arch flags late to ensure it wasn't removed.
    # Not necessary in TEA, but this is aligned with core
    LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"

    # If we're running gcc, then change the C flags for compiling shared
    # libraries to the right flags for gcc, instead of those for the
    # standard manufacturer compiler.

    AS_IF([test "$GCC" = yes], [
	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*) ;;
	    IRIX*) ;;
	    NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
	    Darwin-*) ;;
	    SCO_SV-3.2*) ;;
	    windows) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac])

    AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
	AC_DEFINE(MODULE_SCOPE, [extern],
	    [No Compiler support for module scope symbols])
    ])

    AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
    # TEA specific: use PACKAGE_VERSION instead of VERSION
    SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'])
    AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
    # TEA specific: use PACKAGE_VERSION instead of VERSION
    UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'])

    if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then
	AC_CACHE_CHECK(for SEH support in compiler,
	    tcl_cv_seh,
	AC_TRY_RUN([
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

	    int main(int argc, char** argv) {
		int a, b = 0;
		__try {
		    a = 666 / b;
		}
		__except (EXCEPTION_EXECUTE_HANDLER) {
		    return 0;
		}
		return 1;
	    }
	],
	    tcl_cv_seh=yes,
	    tcl_cv_seh=no,
	    tcl_cv_seh=no)
	)
	if test "$tcl_cv_seh" = "no" ; then
	    AC_DEFINE(HAVE_NO_SEH, 1,
		    [Defined when mingw does not support SEH])
	fi

	#
	# Check to see if the excpt.h include file provided contains the
	# definition for EXCEPTION_DISPOSITION; if not, which is the case
	# with Cygwin's version as of 2002-04-10, define it to be int,
	# sufficient for getting the current code to work.
	#
	AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
	    tcl_cv_eh_disposition,
	    AC_TRY_COMPILE([
#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN
	    ],[
		EXCEPTION_DISPOSITION x;
	    ],
		tcl_cv_eh_disposition=yes,
		tcl_cv_eh_disposition=no)
	)
	if test "$tcl_cv_eh_disposition" = "no" ; then
	AC_DEFINE(EXCEPTION_DISPOSITION, int,
		[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
	fi

	# Check to see if winnt.h defines CHAR, SHORT, and LONG
	# even if VOID has already been #defined. The win32api
	# used by mingw and cygwin is known to do this.

	AC_CACHE_CHECK(for winnt.h that ignores VOID define,
	    tcl_cv_winnt_ignore_void,
	    AC_TRY_COMPILE([
#define VOID void
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
	    ], [
		CHAR c;
		SHORT s;
		LONG l;
	    ],
        tcl_cv_winnt_ignore_void=yes,
        tcl_cv_winnt_ignore_void=no)
	)
	if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
	    AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
		    [Defined when cygwin/mingw ignores VOID define in winnt.h])
	fi
    fi

	# See if the compiler supports casting to a union type.
	# This is used to stop gcc from printing a compiler
	# warning when initializing a union member.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
	    [
		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;
	    ],
	    tcl_cv_cast_to_union=yes,
	    tcl_cv_cast_to_union=no)
	)
	if test "$tcl_cv_cast_to_union" = "yes"; then
	    AC_DEFINE(HAVE_CAST_TO_UNION, 1,
		    [Defined when compiler supports casting to union type.])
	fi

    AC_SUBST(CFLAGS_DEBUG)
    AC_SUBST(CFLAGS_OPTIMIZE)
    AC_SUBST(CFLAGS_WARNING)
    AC_SUBST(CC_OBJNAME)

    AC_SUBST(STLIB_LD)
    AC_SUBST(SHLIB_LD)

    AC_SUBST(SHLIB_LD_LIBS)
    AC_SUBST(SHLIB_CFLAGS)

    AC_SUBST(LD_LIBRARY_PATH_VAR)

    # These must be called after we do the basic CFLAGS checks and
    # verify any possible 64-bit or similar switches are necessary
    TEA_TCL_EARLY_FLAGS
    TEA_TCL_64BIT_FLAGS
])

#--------------------------------------------------------------------
# TEA_SERIAL_PORT
#
#	Determine which interface to use to talk to the serial port.
#	Note that #include lines must begin in leftmost column for
#	some compilers to recognize them as preprocessor directives,
#	and some build environments have stdin not pointing at a
#	pseudo-terminal (usually /dev/null instead.)
#
# Arguments:
#	none
#
# Results:
#
#	Defines only one of the following vars:
#		HAVE_SYS_MODEM_H
#		USE_TERMIOS
#		USE_TERMIO
#		USE_SGTTY
#--------------------------------------------------------------------

AC_DEFUN([TEA_SERIAL_PORT], [
    AC_CHECK_HEADERS(sys/modem.h)
    AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [
    AC_TRY_RUN([
#include <termios.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <termio.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <sgtty.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no ; then
	AC_TRY_RUN([
#include <termios.h>
#include <errno.h>

int main() {
    struct termios t;
    if (tcgetattr(0, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	cfsetospeed(&t, 0);
	t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
#include <termio.h>
#include <errno.h>

int main() {
    struct termio t;
    if (ioctl(0, TCGETA, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
	return 0;
    }
    return 1;
    }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
    fi
    if test $tcl_cv_api_serial = no; then
	AC_TRY_RUN([
#include <sgtty.h>
#include <errno.h>

int main() {
    struct sgttyb t;
    if (ioctl(0, TIOCGETP, &t) == 0
	|| errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
	t.sg_ospeed = 0;
	t.sg_flags |= ODDP | EVENP | RAW;
	return 0;
    }
    return 1;
}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
    fi])
    case $tcl_cv_api_serial in
	termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
	termio)  AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
	sgtty)   AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
    esac
])

#--------------------------------------------------------------------
# TEA_MISSING_POSIX_HEADERS
#
#	Supply substitutes for missing POSIX header files.  Special
#	notes:
#	    - stdlib.h doesn't define strtol, strtoul, or
#	      strtod in some versions of SunOS
#	    - some versions of string.h don't declare procedures such
#	      as strstr
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		NO_DIRENT_H
#		NO_ERRNO_H
#		NO_VALUES_H
#		HAVE_LIMITS_H or NO_LIMITS_H
#		NO_STDLIB_H
#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H
#
#		HAVE_STRING_H ?
#
# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and
# CHECK on limits.h
#--------------------------------------------------------------------

AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [
    AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
    AC_TRY_LINK([#include <sys/types.h>
#include <dirent.h>], [
#ifndef _POSIX_SOURCE
#   ifdef __Lynx__
	/*
	 * Generate compilation error to make the test fail:  Lynx headers
	 * are only valid if really in the POSIX environment.
	 */

	missing_procedure();
#   endif
#endif
DIR *d;
struct dirent *entryPtr;
char *p;
d = opendir("foobar");
entryPtr = readdir(d);
p = entryPtr->d_name;
closedir(d);
], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])

    if test $tcl_cv_dirent_h = no; then
	AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
    fi

    # TEA specific:
    AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
    AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
    AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
    AC_CHECK_HEADER(limits.h,
	[AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])],
	[AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])])
    AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
    AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
    fi
    AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
    AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
    AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)

    # See also memmove check below for a place where NO_STRING_H can be
    # set and why.

    if test $tcl_ok = 0; then
	AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
    fi

    AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
    AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])

    # OS/390 lacks sys/param.h (and doesn't need it, by chance).
    AC_HAVE_HEADERS(sys/param.h)
])

#--------------------------------------------------------------------
# TEA_PATH_X
#
#	Locate the X11 header files and the X11 library archive.  Try
#	the ac_path_x macro first, but if it doesn't find the X stuff
#	(e.g. because there's no xmkmf program) then check through
#	a list of possible directories.  Under some conditions the
#	autoconf macro will return an include directory that contains
#	no include files, so double-check its result just to be safe.
#
#	This should be called after TEA_CONFIG_CFLAGS as setting the
#	LIBS line can confuse some configure macro magic.
#
# Arguments:
#	none
#
# Results:
#
#	Sets the following vars:
#		XINCLUDES
#		XLIBSW
#		PKG_LIBS (appends to)
#--------------------------------------------------------------------

AC_DEFUN([TEA_PATH_X], [
    if test "${TEA_WINDOWINGSYSTEM}" = "x11" -a "${TEA_USE_SDL}" != "yes" ; then
	TEA_PATH_UNIX_X
    fi
])

AC_DEFUN([TEA_PATH_UNIX_X], [
    AC_PATH_X
    not_really_there=""
    if test "$no_x" = ""; then
	if test "$x_includes" = ""; then
	    AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
	else
	    if test ! -r $x_includes/X11/Xlib.h; then
		not_really_there="yes"
	    fi
	fi
    fi
    if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
	AC_MSG_CHECKING([for X11 header files])
	found_xincludes="no"
	AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
	if test "$found_xincludes" = "no"; then
	    dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
	    for i in $dirs ; do
		if test -r $i/X11/Xlib.h; then
		    AC_MSG_RESULT([$i])
		    XINCLUDES=" -I$i"
		    found_xincludes="yes"
		    break
		fi
	    done
	fi
    else
	if test "$x_includes" != ""; then
	    XINCLUDES="-I$x_includes"
	    found_xincludes="yes"
	fi
    fi
    if test "$found_xincludes" = "no"; then
	AC_MSG_RESULT([couldn't find any!])
    fi

    if test "$no_x" = yes; then
	AC_MSG_CHECKING([for X11 libraries])
	XLIBSW=nope
	dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
	for i in $dirs ; do
	    if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then
		AC_MSG_RESULT([$i])
		XLIBSW="-L$i -lX11"
		x_libraries="$i"
		break
	    fi
	done
    else
	if test "$x_libraries" = ""; then
	    XLIBSW=-lX11
	else
	    XLIBSW="-L$x_libraries -lX11"
	fi
    fi
    if test "$XLIBSW" = nope ; then
	AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
    fi
    if test "$XLIBSW" = nope ; then
	AC_MSG_RESULT([could not find any!  Using -lX11.])
	XLIBSW=-lX11
    fi
    # TEA specific:
    if test x"${XLIBSW}" != x ; then
	PKG_LIBS="${PKG_LIBS} ${XLIBSW}"
    fi
])

#--------------------------------------------------------------------
# TEA_BLOCKING_STYLE
#
#	The statements below check for systems where POSIX-style
#	non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
#	On these systems (mostly older ones), use the old BSD-style
#	FIONBIO approach instead.
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		HAVE_SYS_IOCTL_H
#		HAVE_SYS_FILIO_H
#		USE_FIONBIO
#		O_NONBLOCK
#--------------------------------------------------------------------

AC_DEFUN([TEA_BLOCKING_STYLE], [
    AC_CHECK_HEADERS(sys/ioctl.h)
    AC_CHECK_HEADERS(sys/filio.h)
    TEA_CONFIG_SYSTEM
    AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
    case $system in
	OSF*)
	    AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
	    AC_MSG_RESULT([FIONBIO])
	    ;;
	*)
	    AC_MSG_RESULT([O_NONBLOCK])
	    ;;
    esac
])

#--------------------------------------------------------------------
# TEA_TIME_HANDLER
#
#	Checks how the system deals with time.h, what time structures
#	are used on the system, and what fields the structures have.
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:
#		USE_DELTA_FOR_TZ
#		HAVE_TM_GMTOFF
#		HAVE_TM_TZADJ
#		HAVE_TIMEZONE_VAR
#--------------------------------------------------------------------

AC_DEFUN([TEA_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_HEADER_TIME
    AC_STRUCT_TIMEZONE

    AC_CHECK_FUNCS(gmtime_r localtime_r)

    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
	    tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
    if test $tcl_cv_member_tm_tzadj = yes ; then
	AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
    fi

    AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
	AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
	    tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
    if test $tcl_cv_member_tm_gmtoff = yes ; then
	AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
    fi

    #
    # Its important to include time.h in this check, as some systems
    # (like convex) have timezone functions, etc.
    #
    AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
	AC_TRY_COMPILE([#include <time.h>],
	    [extern long timezone;
	    timezone += 1;
	    exit (0);],
	    tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
    if test $tcl_cv_timezone_long = yes ; then
	AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
    else
	#
	# On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
	#
	AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
	    AC_TRY_COMPILE([#include <time.h>],
		[extern time_t timezone;
		timezone += 1;
		exit (0);],
		tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
	if test $tcl_cv_timezone_time = yes ; then
	    AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
	fi
    fi
])

#--------------------------------------------------------------------
# TEA_BUGGY_STRTOD
#
#	Under Solaris 2.4, strtod returns the wrong value for the
#	terminating character under some conditions.  Check for this
#	and if the problem exists use a substitute procedure
#	"fixstrtod" (provided by Tcl) that corrects the error.
#	Also, on Compaq's Tru64 Unix 5.0,
#	strtod(" ") returns 0.0 instead of a failure to convert.
#
# Arguments:
#	none
#
# Results:
#
#	Might defines some of the following vars:
#		strtod (=fixstrtod)
#--------------------------------------------------------------------

AC_DEFUN([TEA_BUGGY_STRTOD], [
    AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
    if test "$tcl_strtod" = 1; then
	AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
	    AC_TRY_RUN([
		extern double strtod();
		int main() {
		    char *infString="Inf", *nanString="NaN", *spaceString=" ";
		    char *term;
		    double value;
		    value = strtod(infString, &term);
		    if ((term != infString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(nanString, &term);
		    if ((term != nanString) && (term[-1] == 0)) {
			exit(1);
		    }
		    value = strtod(spaceString, &term);
		    if (term == (spaceString+1)) {
			exit(1);
		    }
		    exit(0);
		}], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
		    tcl_cv_strtod_buggy=buggy)])
	if test "$tcl_cv_strtod_buggy" = buggy; then
	    AC_LIBOBJ([fixstrtod])
	    USE_COMPAT=1
	    AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
	fi
    fi
])

#--------------------------------------------------------------------
# TEA_TCL_LINK_LIBS
#
#	Search for the libraries needed to link the Tcl shell.
#	Things like the math library (-lm) and socket stuff (-lsocket vs.
#	-lnsl) are dealt with here.
#
# Arguments:
#	Requires the following vars to be set in the Makefile:
#		DL_LIBS (not in TEA, only needed in core)
#		LIBS
#		MATH_LIBS
#
# Results:
#
#	Substitutes the following vars:
#		TCL_LIBS
#		MATH_LIBS
#
#	Might append to the following vars:
#		LIBS
#
#	Might define the following vars:
#		HAVE_NET_ERRNO_H
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_LINK_LIBS], [
    #--------------------------------------------------------------------
    # On a few very rare systems, all of the libm.a stuff is
    # already in libc.a.  Set compiler flags accordingly.
    # Also, Linux requires the "ieee" library for math to work
    # right (and it must appear before "-lm").
    #--------------------------------------------------------------------

    AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm")
    AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"])

    #--------------------------------------------------------------------
    # Interactive UNIX requires -linet instead of -lsocket, plus it
    # needs net/errno.h to define the socket-related error codes.
    #--------------------------------------------------------------------

    AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"])
    AC_CHECK_HEADER(net/errno.h, [
	AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])

    #--------------------------------------------------------------------
    #	Check for the existence of the -lsocket and -lnsl libraries.
    #	The order here is important, so that they end up in the right
    #	order in the command line generated by make.  Here are some
    #	special considerations:
    #	1. Use "connect" and "accept" to check for -lsocket, and
    #	   "gethostbyname" to check for -lnsl.
    #	2. Use each function name only once:  can't redo a check because
    #	   autoconf caches the results of the last check and won't redo it.
    #	3. Use -lnsl and -lsocket only if they supply procedures that
    #	   aren't already present in the normal libraries.  This is because
    #	   IRIX 5.2 has libraries, but they aren't needed and they're
    #	   bogus:  they goof up name resolution if used.
    #	4. On some SVR4 systems, can't use -lsocket without -lnsl too.
    #	   To get around this problem, check for both libraries together
    #	   if -lsocket doesn't work by itself.
    #--------------------------------------------------------------------

    tcl_checkBoth=0
    AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)
    if test "$tcl_checkSocket" = 1; then
	AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,
	    LIBS="$LIBS -lsocket", tcl_checkBoth=1)])
    fi
    if test "$tcl_checkBoth" = 1; then
	tk_oldLibs=$LIBS
	LIBS="$LIBS -lsocket -lnsl"
	AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
    fi
    AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
	    [LIBS="$LIBS -lnsl"])])

    # TEA specific: Don't perform the eval of the libraries here because
    # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS

    TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
    AC_SUBST(TCL_LIBS)
    AC_SUBST(MATH_LIBS)
])

#--------------------------------------------------------------------
# TEA_TCL_EARLY_FLAGS
#
#	Check for what flags are needed to be passed so the correct OS
#	features are available.
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		_ISOC99_SOURCE
#		_LARGEFILE64_SOURCE
#		_LARGEFILE_SOURCE64
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_EARLY_FLAG],[
    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
	AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
	    AC_TRY_COMPILE([[#define ]$1[ 1
]$2], $3,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
		[tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
	AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
	tcl_flags="$tcl_flags $1"
    fi
])

AC_DEFUN([TEA_TCL_EARLY_FLAGS],[
    AC_MSG_CHECKING([for required early compiler flags])
    tcl_flags=""
    TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
	[char *p = (char *)strtoll; char *q = (char *)strtoull;])
    TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
	[struct stat64 buf; int i = stat64("/", &buf);])
    TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
	[char *p = (char *)open64;])
    if test "x${tcl_flags}" = "x" ; then
	AC_MSG_RESULT([none])
    else
	AC_MSG_RESULT([${tcl_flags}])
    fi
])

#--------------------------------------------------------------------
# TEA_TCL_64BIT_FLAGS
#
#	Check for what is defined in the way of 64-bit features.
#
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		TCL_WIDE_INT_IS_LONG
#		TCL_WIDE_INT_TYPE
#		HAVE_STRUCT_DIRENT64
#		HAVE_STRUCT_STAT64
#		HAVE_TYPE_OFF64_T
#--------------------------------------------------------------------

AC_DEFUN([TEA_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    AC_CACHE_VAL(tcl_cv_type_64bit,[
	tcl_cv_type_64bit=none
	# See if the compiler knows natively about __int64
	AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
	    tcl_type_64bit=__int64, tcl_type_64bit="long long")
	# See if we should use long anyway  Note that we substitute in the
	# type that is our current guess for a 64-bit type inside this check
	# program, so it should be modified only carefully...
        AC_TRY_COMPILE(,[switch (0) {
            case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
        }],tcl_cv_type_64bit=${tcl_type_64bit})])
    if test "${tcl_cv_type_64bit}" = none ; then
	AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
	AC_MSG_RESULT([using long])
    elif test "${tcl_cv_type_64bit}" = "__int64" \
		-a "${TEA_PLATFORM}" = "windows" ; then
	# TEA specific: We actually want to use the default tcl.h checks in
	# this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*
	AC_MSG_RESULT([using Tcl header defaults])
    else
	AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
	    [What type should be used to define wide integers?])
	AC_MSG_RESULT([${tcl_cv_type_64bit}])

	# Now check for auxiliary declarations
	AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
	    AC_TRY_COMPILE([#include <sys/types.h>
#include <dirent.h>],[struct dirent64 p;],
		tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
	fi

	AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
	    AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
],
		tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
	if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
	    AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
	fi

	AC_CHECK_FUNCS(open64 lseek64)
	AC_MSG_CHECKING([for off64_t])
	AC_CACHE_VAL(tcl_cv_type_off64_t,[
	    AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
],
		tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
	dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
	dnl functions lseek64 and open64 are defined.
	if test "x${tcl_cv_type_off64_t}" = "xyes" && \
	        test "x${ac_cv_func_lseek64}" = "xyes" && \
	        test "x${ac_cv_func_open64}" = "xyes" ; then
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])
	else
	    AC_MSG_RESULT([no])
	fi
    fi
])

##
## Here ends the standard Tcl configuration bits and starts the
## TEA specific functions
##

#------------------------------------------------------------------------
# TEA_INIT --
#
#	Init various Tcl Extension Architecture (TEA) variables.
#	This should be the first called TEA_* macro.
#
# Arguments:
#	none
#
# Results:
#
#	Defines and substs the following vars:
#		CYGPATH
#		EXEEXT
#	Defines only:
#		TEA_VERSION
#		TEA_INITED
#		TEA_PLATFORM (windows or unix)
#
# "cygpath" is used on windows to generate native path names for include
# files. These variables should only be used with the compiler and linker
# since they generate native path names.
#
# EXEEXT
#	Select the executable extension based on the host type.  This
#	is a lightweight replacement for AC_EXEEXT that doesn't require
#	a compiler.
#------------------------------------------------------------------------

AC_DEFUN([TEA_INIT], [
    # TEA extensions pass this us the version of TEA they think they
    # are compatible with.
    TEA_VERSION="3.9"

    AC_MSG_CHECKING([for correct TEA configuration])
    if test x"${PACKAGE_NAME}" = x ; then
	AC_MSG_ERROR([
The PACKAGE_NAME variable must be defined by your TEA configure.in])
    fi
    if test x"$1" = x ; then
	AC_MSG_ERROR([
TEA version not specified.])
    elif test "$1" != "${TEA_VERSION}" ; then
	AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"])
    else
	AC_MSG_RESULT([ok (TEA ${TEA_VERSION})])
    fi

    # If the user did not set CFLAGS, set it now to keep macros
    # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
    if test "${CFLAGS+set}" != "set" ; then
	CFLAGS=""
    fi

    case "`uname -s`" in
	*win32*|*WIN32*|*MINGW32_*)
	    AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
	    EXEEXT=".exe"
	    TEA_PLATFORM="windows"
	    ;;
	*CYGWIN_*)
	    CYGPATH=echo
	    EXEEXT=".exe"
	    # TEA_PLATFORM is determined later in LOAD_TCLCONFIG
	    ;;
	*)
	    CYGPATH=echo
	    # Maybe we are cross-compiling....
	    case ${host_alias} in
		*mingw32*)
		EXEEXT=".exe"
		TEA_PLATFORM="windows"
		;;
	    *)
		EXEEXT=""
		TEA_PLATFORM="unix"
		;;
	    esac
	    ;;
    esac

    # Check if exec_prefix is set. If not use fall back to prefix.
    # Note when adjusted, so that TEA_PREFIX can correct for this.
    # This is needed for recursive configures, since autoconf propagates
    # $prefix, but not $exec_prefix (doh!).
    if test x$exec_prefix = xNONE ; then
	exec_prefix_default=yes
	exec_prefix=$prefix
    fi

    AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}])

    AC_SUBST(EXEEXT)
    AC_SUBST(CYGPATH)

    # This package name must be replaced statically for AC_SUBST to work
    AC_SUBST(PKG_LIB_FILE)
    # Substitute STUB_LIB_FILE in case package creates a stub library too.
    AC_SUBST(PKG_STUB_LIB_FILE)

    # We AC_SUBST these here to ensure they are subst'ed,
    # in case the user doesn't call TEA_ADD_...
    AC_SUBST(PKG_STUB_SOURCES)
    AC_SUBST(PKG_STUB_OBJECTS)
    AC_SUBST(PKG_TCL_SOURCES)
    AC_SUBST(PKG_HEADERS)
    AC_SUBST(PKG_INCLUDES)
    AC_SUBST(PKG_LIBS)
    AC_SUBST(PKG_CFLAGS)
])

#------------------------------------------------------------------------
# TEA_ADD_SOURCES --
#
#	Specify one or more source files.  Users should check for
#	the right platform before adding to their list.
#	It is not important to specify the directory, as long as it is
#	in the generic, win or unix subdirectory of $(srcdir).
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_SOURCES
#		PKG_OBJECTS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_SOURCES], [
    vars="$@"
    for i in $vars; do
	case $i in
	    [\$]*)
		# allow $-var names
		PKG_SOURCES="$PKG_SOURCES $i"
		PKG_OBJECTS="$PKG_OBJECTS $i"
		;;
	    *)
		# check for existence - allows for generic/win/unix VPATH
		# To add more dirs here (like 'src'), you have to update VPATH
		# in Makefile.in as well
		if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
		    -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
		    -a ! -f "${srcdir}/macosx/$i" -a ! -f "${srcdir}/sdl/$i" \
		    ; then
		    AC_MSG_ERROR([could not find source file '$i'])
		fi
		PKG_SOURCES="$PKG_SOURCES $i"
		# this assumes it is in a VPATH dir
		i=`basename $i`
		# handle user calling this before or after TEA_SETUP_COMPILER
		if test x"${OBJEXT}" != x ; then
		    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
		else
		    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
		fi
		PKG_OBJECTS="$PKG_OBJECTS $j"
		;;
	esac
    done
    AC_SUBST(PKG_SOURCES)
    AC_SUBST(PKG_OBJECTS)
])

#------------------------------------------------------------------------
# TEA_ADD_STUB_SOURCES --
#
#	Specify one or more source files.  Users should check for
#	the right platform before adding to their list.
#	It is not important to specify the directory, as long as it is
#	in the generic, win or unix subdirectory of $(srcdir).
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_STUB_SOURCES
#		PKG_STUB_OBJECTS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_STUB_SOURCES], [
    vars="$@"
    for i in $vars; do
	# check for existence - allows for generic/win/unix VPATH
	if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
	    -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
	    -a ! -f "${srcdir}/macosx/$i" -a ! -f "${srcdir}/sdl/$i" \
	    ; then
	    AC_MSG_ERROR([could not find stub source file '$i'])
	fi
	PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i"
	# this assumes it is in a VPATH dir
	i=`basename $i`
	# handle user calling this before or after TEA_SETUP_COMPILER
	if test x"${OBJEXT}" != x ; then
	    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
	else
	    j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
	fi
	PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j"
    done
    AC_SUBST(PKG_STUB_SOURCES)
    AC_SUBST(PKG_STUB_OBJECTS)
])

#------------------------------------------------------------------------
# TEA_ADD_TCL_SOURCES --
#
#	Specify one or more Tcl source files.  These should be platform
#	independent runtime files.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_TCL_SOURCES
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_TCL_SOURCES], [
    vars="$@"
    for i in $vars; do
	# check for existence, be strict because it is installed
	if test ! -f "${srcdir}/$i" ; then
	    AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i'])
	fi
	PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
    done
    AC_SUBST(PKG_TCL_SOURCES)
])

#------------------------------------------------------------------------
# TEA_ADD_HEADERS --
#
#	Specify one or more source headers.  Users should check for
#	the right platform before adding to their list.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_HEADERS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_HEADERS], [
    vars="$@"
    for i in $vars; do
	# check for existence, be strict because it is installed
	if test ! -f "${srcdir}/$i" ; then
	    AC_MSG_ERROR([could not find header file '${srcdir}/$i'])
	fi
	PKG_HEADERS="$PKG_HEADERS $i"
    done
    AC_SUBST(PKG_HEADERS)
])

#------------------------------------------------------------------------
# TEA_ADD_INCLUDES --
#
#	Specify one or more include dirs.  Users should check for
#	the right platform before adding to their list.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_INCLUDES
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_INCLUDES], [
    vars="$@"
    for i in $vars; do
	PKG_INCLUDES="$PKG_INCLUDES $i"
    done
    AC_SUBST(PKG_INCLUDES)
])

#------------------------------------------------------------------------
# TEA_ADD_LIBS --
#
#	Specify one or more libraries.  Users should check for
#	the right platform before adding to their list.  For Windows,
#	libraries provided in "foo.lib" format will be converted to
#	"-lfoo" when using GCC (mingw).
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_LIBS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_LIBS], [
    vars="$@"
    for i in $vars; do
	if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
	    # Convert foo.lib to -lfoo for GCC.  No-op if not *.lib
	    i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'`
	fi
	PKG_LIBS="$PKG_LIBS $i"
    done
    AC_SUBST(PKG_LIBS)
])

#------------------------------------------------------------------------
# TEA_ADD_CFLAGS --
#
#	Specify one or more CFLAGS.  Users should check for
#	the right platform before adding to their list.
#
# Arguments:
#	one or more file names
#
# Results:
#
#	Defines and substs the following vars:
#		PKG_CFLAGS
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_CFLAGS], [
    PKG_CFLAGS="$PKG_CFLAGS $@"
    AC_SUBST(PKG_CFLAGS)
])

#------------------------------------------------------------------------
# TEA_ADD_CLEANFILES --
#
#	Specify one or more CLEANFILES.
#
# Arguments:
#	one or more file names to clean target
#
# Results:
#
#	Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG
#------------------------------------------------------------------------
AC_DEFUN([TEA_ADD_CLEANFILES], [
    CLEANFILES="$CLEANFILES $@"
])

#------------------------------------------------------------------------
# TEA_PREFIX --
#
#	Handle the --prefix=... option by defaulting to what Tcl gave
#
# Arguments:
#	none
#
# Results:
#
#	If --prefix or --exec-prefix was not specified, $prefix and
#	$exec_prefix will be set to the values given to Tcl when it was
#	configured.
#------------------------------------------------------------------------
AC_DEFUN([TEA_PREFIX], [
    if test "${prefix}" = "NONE"; then
	prefix_default=yes
	if test x"${TCL_PREFIX}" != x; then
	    AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}])
	    prefix=${TCL_PREFIX}
	else
	    AC_MSG_NOTICE([--prefix defaulting to /usr/local])
	    prefix=/usr/local
	fi
    fi
    if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \
	-o x"${exec_prefix_default}" = x"yes" ; then
	if test x"${TCL_EXEC_PREFIX}" != x; then
	    AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}])
	    exec_prefix=${TCL_EXEC_PREFIX}
	else
	    AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}])
	    exec_prefix=$prefix
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_SETUP_COMPILER_CC --
#
#	Do compiler checks the way we want.  This is just a replacement
#	for AC_PROG_CC in TEA configure.in files to make them cleaner.
#
# Arguments:
#	none
#
# Results:
#
#	Sets up CC var and other standard bits we need to make executables.
#------------------------------------------------------------------------
AC_DEFUN([TEA_SETUP_COMPILER_CC], [
    # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)
    # in this macro, they need to go into TEA_SETUP_COMPILER instead.

    AC_PROG_CC
    AC_PROG_CPP

    INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c"
    AC_SUBST(INSTALL)
    INSTALL_DATA="\${INSTALL} -m 644"
    AC_SUBST(INSTALL_DATA)
    INSTALL_PROGRAM="\${INSTALL}"
    AC_SUBST(INSTALL_PROGRAM)
    INSTALL_SCRIPT="\${INSTALL}"
    AC_SUBST(INSTALL_SCRIPT)

    #--------------------------------------------------------------------
    # Checks to see if the make program sets the $MAKE variable.
    #--------------------------------------------------------------------

    AC_PROG_MAKE_SET

    #--------------------------------------------------------------------
    # Find ranlib
    #--------------------------------------------------------------------

    AC_CHECK_TOOL(RANLIB, ranlib)

    #--------------------------------------------------------------------
    # Determines the correct binary file extension (.o, .obj, .exe etc.)
    #--------------------------------------------------------------------

    AC_OBJEXT
    AC_EXEEXT
])

#------------------------------------------------------------------------
# TEA_SETUP_COMPILER --
#
#	Do compiler checks that use the compiler.  This must go after
#	TEA_SETUP_COMPILER_CC, which does the actual compiler check.
#
# Arguments:
#	none
#
# Results:
#
#	Sets up CC var and other standard bits we need to make executables.
#------------------------------------------------------------------------
AC_DEFUN([TEA_SETUP_COMPILER], [
    # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.
    AC_REQUIRE([TEA_SETUP_COMPILER_CC])

    #------------------------------------------------------------------------
    # If we're using GCC, see if the compiler understands -pipe. If so, use it.
    # It makes compiling go faster.  (This is only a performance feature.)
    #------------------------------------------------------------------------

    if test -z "$no_pipe" -a -n "$GCC"; then
	AC_CACHE_CHECK([if the compiler understands -pipe],
	    tcl_cv_cc_pipe, [
	    hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	    AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
	    CFLAGS=$hold_cflags])
	if test $tcl_cv_cc_pipe = yes; then
	    CFLAGS="$CFLAGS -pipe"
	fi
    fi

    #--------------------------------------------------------------------
    # Common compiler flag setup
    #--------------------------------------------------------------------

    AC_C_BIGENDIAN
    if test "${TEA_PLATFORM}" = "unix" ; then
	TEA_TCL_LINK_LIBS
	TEA_MISSING_POSIX_HEADERS
	# Let the user call this, because if it triggers, they will
	# need a compat/strtod.c that is correct.  Users can also
	# use Tcl_GetDouble(FromObj) instead.
	#TEA_BUGGY_STRTOD
    fi
])

#------------------------------------------------------------------------
# TEA_MAKE_LIB --
#
#	Generate a line that can be used to build a shared/unshared library
#	in a platform independent manner.
#
# Arguments:
#	none
#
#	Requires:
#
# Results:
#
#	Defines the following vars:
#	CFLAGS -	Done late here to note disturb other AC macros
#       MAKE_LIB -      Command to execute to build the Tcl library;
#                       differs depending on whether or not Tcl is being
#                       compiled as a shared library.
#	MAKE_SHARED_LIB	Makefile rule for building a shared library
#	MAKE_STATIC_LIB	Makefile rule for building a static library
#	MAKE_STUB_LIB	Makefile rule for building a stub library
#	VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL
#	VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE
#------------------------------------------------------------------------

AC_DEFUN([TEA_MAKE_LIB], [
    if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
	MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
	MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
	AC_EGREP_CPP([manifest needed], [
#if defined(_MSC_VER) && _MSC_VER >= 1400
print("manifest needed")
#endif
	], [
	# Could do a CHECK_PROG for mt, but should always be with MSVC8+
	VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi"
	MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"

	# Don't clean .manifest provided by the package (see TEA_ADD_MANIFEST)
	# or one created by Makefile or configure.  Could use the /manifest:filename
	# linker option to explicitly set the linker-generated filename.
	eval eval "manifest=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}.manifest"
	TEA_ADD_CLEANFILES([$manifest])
	])
	MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\[$]@ \$(PKG_STUB_OBJECTS)"
    else
	MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
	MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
	MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
    fi

    if test "${SHARED_BUILD}" = "1" ; then
	MAKE_LIB="${MAKE_SHARED_LIB} "
    else
	MAKE_LIB="${MAKE_STATIC_LIB} "
    fi

    #--------------------------------------------------------------------
    # Shared libraries and static libraries have different names.
    # Use the double eval to make sure any variables in the suffix is
    # substituted. (@@@ Might not be necessary anymore)
    #--------------------------------------------------------------------

    if test "${TEA_PLATFORM}" = "windows" ; then
	if test "${SHARED_BUILD}" = "1" ; then
	    # We force the unresolved linking of symbols that are really in
	    # the private libraries of Tcl and Tk.
	    if test x"${TK_BIN_DIR}" != x ; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
	    fi
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
	    if test "$GCC" = "yes"; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc"
	    fi
	    eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	else
	    eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	    if test "$GCC" = "yes"; then
		PKG_LIB_FILE=lib${PKG_LIB_FILE}
	    fi
	fi
	# Some packages build their own stubs libraries
	eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
	if test "$GCC" = "yes"; then
	    PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
	fi
	# These aren't needed on Windows (either MSVC or gcc)
	RANLIB=:
	RANLIB_STUB=:
    else
	RANLIB_STUB="${RANLIB}"
	if test "${SHARED_BUILD}" = "1" ; then
	    SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
	    if test x"${TK_BIN_DIR}" != x ; then
		SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
	    fi
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
	    RANLIB=:
	else
	    eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
	fi
	# Some packages build their own stubs libraries
	eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
    fi

    # These are escaped so that only CFLAGS is picked up at configure time.
    # The other values will be substituted at make time.
    CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
    if test "${SHARED_BUILD}" = "1" ; then
	CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
    fi

    AC_SUBST(MAKE_LIB)
    AC_SUBST(MAKE_SHARED_LIB)
    AC_SUBST(MAKE_STATIC_LIB)
    AC_SUBST(MAKE_STUB_LIB)
    AC_SUBST(RANLIB_STUB)
    AC_SUBST(VC_MANIFEST_EMBED_DLL)
    AC_SUBST(VC_MANIFEST_EMBED_EXE)
])

#------------------------------------------------------------------------
# TEA_LIB_SPEC --
#
#	Compute the name of an existing object library located in libdir
#	from the given base name and produce the appropriate linker flags.
#
# Arguments:
#	basename	The base name of the library without version
#			numbers, extensions, or "lib" prefixes.
#	extra_dir	Extra directory in which to search for the
#			library.  This location is used first, then
#			$prefix/$exec-prefix, then some defaults.
#
# Requires:
#	TEA_INIT and TEA_PREFIX must be called first.
#
# Results:
#
#	Defines the following vars:
#		${basename}_LIB_NAME	The computed library name.
#		${basename}_LIB_SPEC	The computed linker flags.
#------------------------------------------------------------------------

AC_DEFUN([TEA_LIB_SPEC], [
    AC_MSG_CHECKING([for $1 library])

    # Look in exec-prefix for the library (defined by TEA_PREFIX).

    tea_lib_name_dir="${exec_prefix}/lib"

    # Or in a user-specified location.

    if test x"$2" != x ; then
	tea_extra_lib_dir=$2
    else
	tea_extra_lib_dir=NONE
    fi

    for i in \
	    `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \
	    `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \
	    `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do
	if test -f "$i" ; then
	    tea_lib_name_dir=`dirname $i`
	    $1_LIB_NAME=`basename $i`
	    $1_LIB_PATH_NAME=$i
	    break
	fi
    done

    if test "${TEA_PLATFORM}" = "windows"; then
	$1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\"
    else
	# Strip off the leading "lib" and trailing ".a" or ".so"

	tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'`
	$1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}"
    fi

    if test "x${$1_LIB_NAME}" = x ; then
	AC_MSG_ERROR([not found])
    else
	AC_MSG_RESULT([${$1_LIB_SPEC}])
    fi
])

#------------------------------------------------------------------------
# TEA_PRIVATE_TCL_HEADERS --
#
#	Locate the private Tcl include files
#
# Arguments:
#
#	Requires:
#		TCL_SRC_DIR	Assumes that TEA_LOAD_TCLCONFIG has
#				already been called.
#
# Results:
#
#	Substitutes the following vars:
#		TCL_TOP_DIR_NATIVE
#		TCL_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [
    # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh}
    AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS])
    AC_MSG_CHECKING([for Tcl private include files])

    TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}`
    TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\"

    # Check to see if tcl<Plat>Port.h isn't already with the public headers
    # Don't look for tclInt.h because that resides with tcl.h in the core
    # sources, but the <plat>Port headers are in a different directory
    if test "${TEA_PLATFORM}" = "windows" -a \
	-f "${ac_cv_c_tclh}/tclWinPort.h"; then
	result="private headers found with public headers"
    elif test "${TEA_PLATFORM}" = "unix" -a \
	-f "${ac_cv_c_tclh}/tclUnixPort.h"; then
	result="private headers found with public headers"
    else
	TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\"
	if test "${TEA_PLATFORM}" = "windows"; then
	    TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\"
	else
	    TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\"
	fi
	# Overwrite the previous TCL_INCLUDES as this should capture both
	# public and private headers in the same set.
	# We want to ensure these are substituted so as not to require
	# any *_NATIVE vars be defined in the Makefile
	TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}"
	if test "`uname -s`" = "Darwin"; then
            # If Tcl was built as a framework, attempt to use
            # the framework's Headers and PrivateHeaders directories
            case ${TCL_DEFS} in
	    	*TCL_FRAMEWORK*)
		    if test -d "${TCL_BIN_DIR}/Headers" -a \
			    -d "${TCL_BIN_DIR}/PrivateHeaders"; then
			TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}"
		    else
			TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
		    fi
	            ;;
	    esac
	    result="Using ${TCL_INCLUDES}"
	else
	    if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then
		AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}])
	    fi
	    result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}"
	fi
    fi

    AC_SUBST(TCL_TOP_DIR_NATIVE)

    AC_SUBST(TCL_INCLUDES)
    AC_MSG_RESULT([${result}])
])

#------------------------------------------------------------------------
# TEA_PUBLIC_TCL_HEADERS --
#
#	Locate the installed public Tcl header files
#
# Arguments:
#	None.
#
# Requires:
#	CYGPATH must be set
#
# Results:
#
#	Adds a --with-tclinclude switch to configure.
#	Result is cached.
#
#	Substitutes the following vars:
#		TCL_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [
    AC_MSG_CHECKING([for Tcl public headers])

    AC_ARG_WITH(tclinclude, [  --with-tclinclude       directory containing the public Tcl header files], with_tclinclude=${withval})

    AC_CACHE_VAL(ac_cv_c_tclh, [
	# Use the value from --with-tclinclude, if it was given

	if test x"${with_tclinclude}" != x ; then
	    if test -f "${with_tclinclude}/tcl.h" ; then
		ac_cv_c_tclh=${with_tclinclude}
	    else
		AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h])
	    fi
	else
	    list=""
	    if test "`uname -s`" = "Darwin"; then
		# If Tcl was built as a framework, attempt to use
		# the framework's Headers directory
		case ${TCL_DEFS} in
		    *TCL_FRAMEWORK*)
			list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`"
			;;
		esac
	    fi

	    # Look in the source dir only if Tcl is not installed,
	    # and in that situation, look there before installed locations.
	    if test -f "${TCL_BIN_DIR}/Makefile" ; then
		list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`"
	    fi

	    # Check order: pkg --prefix location, Tcl's --prefix location,
	    # relative to directory of tclConfig.sh.

	    eval "temp_includedir=${includedir}"
	    list="$list \
		`ls -d ${temp_includedir}        2>/dev/null` \
		`ls -d ${TCL_PREFIX}/include     2>/dev/null` \
		`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
	    if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
		list="$list /usr/local/include /usr/include"
		if test x"${TCL_INCLUDE_SPEC}" != x ; then
		    d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'`
		    list="$list `ls -d ${d} 2>/dev/null`"
		fi
	    fi
	    for i in $list ; do
		if test -f "$i/tcl.h" ; then
		    ac_cv_c_tclh=$i
		    break
		fi
	    done
	fi
    ])

    # Print a message based on how we determined the include path

    if test x"${ac_cv_c_tclh}" = x ; then
	AC_MSG_ERROR([tcl.h not found.  Please specify its location with --with-tclinclude])
    else
	AC_MSG_RESULT([${ac_cv_c_tclh}])
    fi

    # Convert to a native path and substitute into the output files.

    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`

    TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"

    AC_SUBST(TCL_INCLUDES)
])

#------------------------------------------------------------------------
# TEA_PRIVATE_TK_HEADERS --
#
#	Locate the private Tk include files
#
# Arguments:
#
#	Requires:
#		TK_SRC_DIR	Assumes that TEA_LOAD_TKCONFIG has
#				 already been called.
#
# Results:
#
#	Substitutes the following vars:
#		TK_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [
    # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh}
    AC_REQUIRE([TEA_PUBLIC_TK_HEADERS])
    AC_MSG_CHECKING([for Tk private include files])

    TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}`
    TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\"

    # Check to see if tk<Plat>Port.h isn't already with the public headers
    # Don't look for tkInt.h because that resides with tk.h in the core
    # sources, but the <plat>Port headers are in a different directory
    if test -f "${ac_cv_c_tkh}/tkSDLPort.h"; then
	result="private headers found with public headers"
    elif test "${TEA_PLATFORM}" = "windows" -a \
	-f "${ac_cv_c_tkh}/tkWinPort.h"; then
	result="private headers found with public headers"
    elif test "${TEA_PLATFORM}" = "unix" -a \
	-f "${ac_cv_c_tkh}/tkUnixPort.h"; then
	result="private headers found with public headers"
    else
	TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\"
	TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\"
	if test "${TEA_PLATFORM}" = "windows"; then
	    TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\"
	else
	    TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\"
	fi
	case ${TK_DEFS} in
	    *PLATFORM_SDL*)
		TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/sdl\"
		;;
	esac
	# Overwrite the previous TK_INCLUDES as this should capture both
	# public and private headers in the same set.
	# We want to ensure these are substituted so as not to require
	# any *_NATIVE vars be defined in the Makefile
	TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}"
	# Detect and add ttk subdir
	if test -d "${TK_SRC_DIR}/generic/ttk"; then
	   TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\""
	fi
	if test "${TEA_WINDOWINGSYSTEM}" != "x11" -o "${TEA_USE_SDL}" = "yes" ; then
	   TK_INCLUDES="${TK_INCLUDES} -I${TK_XLIB_DIR_NATIVE}"
	fi
	if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then
	   TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\""
	fi
	if test "`uname -s`" = "Darwin"; then
	    # If Tk was built as a framework, attempt to use
	    # the framework's Headers and PrivateHeaders directories
	    case ${TK_DEFS} in
		*TK_FRAMEWORK*)
			if test -d "${TK_BIN_DIR}/Headers" -a \
				-d "${TK_BIN_DIR}/PrivateHeaders"; then
			    TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}"
			else
			    TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
			fi
			;;
	    esac
	    result="Using ${TK_INCLUDES}"
	else
	    if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then
	       AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}])
	    fi
	    result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}"
	fi
    fi

    AC_SUBST(TK_TOP_DIR_NATIVE)
    AC_SUBST(TK_XLIB_DIR_NATIVE)

    AC_SUBST(TK_INCLUDES)
    AC_MSG_RESULT([${result}])
])

#------------------------------------------------------------------------
# TEA_PUBLIC_TK_HEADERS --
#
#	Locate the installed public Tk header files
#
# Arguments:
#	None.
#
# Requires:
#	CYGPATH must be set
#
# Results:
#
#	Adds a --with-tkinclude switch to configure.
#	Result is cached.
#
#	Substitutes the following vars:
#		TK_INCLUDES
#------------------------------------------------------------------------

AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [
    AC_MSG_CHECKING([for Tk public headers])

    AC_ARG_WITH(tkinclude, [  --with-tkinclude        directory containing the public Tk header files], with_tkinclude=${withval})

    AC_CACHE_VAL(ac_cv_c_tkh, [
	# Use the value from --with-tkinclude, if it was given

	if test x"${with_tkinclude}" != x ; then
	    if test -f "${with_tkinclude}/tk.h" ; then
		ac_cv_c_tkh=${with_tkinclude}
	    else
		AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h])
	    fi
	else
	    list=""
	    if test "`uname -s`" = "Darwin"; then
		# If Tk was built as a framework, attempt to use
		# the framework's Headers directory.
		case ${TK_DEFS} in
		    *TK_FRAMEWORK*)
			list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`"
			;;
		esac
	    fi

	    # Look in the source dir only if Tk is not installed,
	    # and in that situation, look there before installed locations.
	    if test -f "${TK_BIN_DIR}/Makefile" ; then
		list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`"
	    fi

	    # Check order: pkg --prefix location, Tk's --prefix location,
	    # relative to directory of tkConfig.sh, Tcl's --prefix location,
	    # relative to directory of tclConfig.sh.

	    eval "temp_includedir=${includedir}"
	    list="$list \
		`ls -d ${temp_includedir}        2>/dev/null` \
		`ls -d ${TK_PREFIX}/include      2>/dev/null` \
		`ls -d ${TK_BIN_DIR}/../include  2>/dev/null` \
		`ls -d ${TCL_PREFIX}/include     2>/dev/null` \
		`ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
	    if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
		list="$list /usr/local/include /usr/include"
		if test x"${TK_INCLUDE_SPEC}" != x ; then
		    d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'`
		    list="$list `ls -d ${d} 2>/dev/null`"
		fi
	    fi
	    for i in $list ; do
		if test -f "$i/tk.h" ; then
		    ac_cv_c_tkh=$i
		    break
		fi
	    done
	fi
    ])

    # Print a message based on how we determined the include path

    if test x"${ac_cv_c_tkh}" = x ; then
	AC_MSG_ERROR([tk.h not found.  Please specify its location with --with-tkinclude])
    else
	AC_MSG_RESULT([${ac_cv_c_tkh}])
    fi

    # Convert to a native path and substitute into the output files.

    INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`

    TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"

    AC_SUBST(TK_INCLUDES)

    if test "${TEA_WINDOWINGSYSTEM}" != "x11" -o "${TEA_USE_SDL}" = "yes" ; then
	# On Windows and Aqua, we need the X compat headers
	AC_MSG_CHECKING([for X11 header files])
	if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then
	    INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`"
	    TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
	    AC_SUBST(TK_XINCLUDES)
	fi
	AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}])
    fi
])

#------------------------------------------------------------------------
# TEA_PATH_CONFIG --
#
#	Locate the ${1}Config.sh file and perform a sanity check on
#	the ${1} compile flags.  These are used by packages like
#	[incr Tk] that load *Config.sh files from more than Tcl and Tk.
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-$1=...
#
#	Defines the following vars:
#		$1_BIN_DIR	Full path to the directory containing
#				the $1Config.sh file
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_CONFIG], [
    #
    # Ok, lets find the $1 configuration
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-$1
    #

    if test x"${no_$1}" = x ; then
	# we reset no_$1 in case something fails here
	no_$1=true
	AC_ARG_WITH($1, [  --with-$1              directory containing $1 configuration ($1Config.sh)], with_$1config=${withval})
	AC_MSG_CHECKING([for $1 configuration])
	AC_CACHE_VAL(ac_cv_c_$1config,[

	    # First check to see if --with-$1 was specified.
	    if test x"${with_$1config}" != x ; then
		case ${with_$1config} in
		    */$1Config.sh )
			if test -f ${with_$1config}; then
			    AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself])
			    with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'`
			fi;;
		esac
		if test -f "${with_$1config}/$1Config.sh" ; then
		    ac_cv_c_$1config=`(cd ${with_$1config}; pwd)`
		else
		    AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh])
		fi
	    fi

	    # then check for a private $1 installation
	    if test x"${ac_cv_c_$1config}" = x ; then
		for i in \
			../$1 \
			`ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			../../$1 \
			`ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			../../../$1 \
			`ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			${srcdir}/../$1 \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \
			`ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
			; do
		    if test -f "$i/$1Config.sh" ; then
			ac_cv_c_$1config=`(cd $i; pwd)`
			break
		    fi
		    if test -f "$i/unix/$1Config.sh" ; then
			ac_cv_c_$1config=`(cd $i/unix; pwd)`
			break
		    fi
		done
	    fi

	    # check in a few common install locations
	    if test x"${ac_cv_c_$1config}" = x ; then
		for i in `ls -d ${libdir} 2>/dev/null` \
			`ls -d ${exec_prefix}/lib 2>/dev/null` \
			`ls -d ${prefix}/lib 2>/dev/null` \
			`ls -d /usr/local/lib 2>/dev/null` \
			`ls -d /usr/contrib/lib 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 2>/dev/null` \
			; do
		    if test -f "$i/$1Config.sh" ; then
			ac_cv_c_$1config=`(cd $i; pwd)`
			break
		    fi
		done
	    fi
	])

	if test x"${ac_cv_c_$1config}" = x ; then
	    $1_BIN_DIR="# no $1 configs found"
	    AC_MSG_WARN([Cannot find $1 configuration definitions])
	    exit 0
	else
	    no_$1=
	    $1_BIN_DIR=${ac_cv_c_$1config}
	    AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh])
	fi
    fi
])

#------------------------------------------------------------------------
# TEA_LOAD_CONFIG --
#
#	Load the $1Config.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		$1_BIN_DIR
#
# Results:
#
#	Substitutes the following vars:
#		$1_SRC_DIR
#		$1_LIB_FILE
#		$1_LIB_SPEC
#------------------------------------------------------------------------

AC_DEFUN([TEA_LOAD_CONFIG], [
    AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh])

    if test -f "${$1_BIN_DIR}/$1Config.sh" ; then
        AC_MSG_RESULT([loading])
	. "${$1_BIN_DIR}/$1Config.sh"
    else
        AC_MSG_RESULT([file not found])
    fi

    #
    # If the $1_BIN_DIR is the build directory (not the install directory),
    # then set the common variable name to the value of the build variables.
    # For example, the variable $1_LIB_SPEC will be set to the value
    # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC
    # instead of $1_BUILD_LIB_SPEC since it will work with both an
    # installed and uninstalled version of Tcl.
    #

    if test -f "${$1_BIN_DIR}/Makefile" ; then
	AC_MSG_WARN([Found Makefile - using build library specs for $1])
        $1_LIB_SPEC=${$1_BUILD_LIB_SPEC}
        $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC}
        $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH}
        $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC}
        $1_LIBRARY_PATH=${$1_LIBRARY_PATH}
    fi

    AC_SUBST($1_VERSION)
    AC_SUBST($1_BIN_DIR)
    AC_SUBST($1_SRC_DIR)

    AC_SUBST($1_LIB_FILE)
    AC_SUBST($1_LIB_SPEC)

    AC_SUBST($1_STUB_LIB_FILE)
    AC_SUBST($1_STUB_LIB_SPEC)
    AC_SUBST($1_STUB_LIB_PATH)

    # Allow the caller to prevent this auto-check by specifying any 2nd arg
    AS_IF([test "x$2" = x], [
	# Check both upper and lower-case variants
	# If a dev wanted non-stubs libs, this function could take an option
	# to not use _STUB in the paths below
	AS_IF([test "x${$1_STUB_LIB_SPEC}" = x],
	    [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)],
	    [TEA_LOAD_CONFIG_LIB($1_STUB)])
    ])
])

#------------------------------------------------------------------------
# TEA_LOAD_CONFIG_LIB --
#
#	Helper function to load correct library from another extension's
#	${PACKAGE}Config.sh.
#
# Results:
#	Adds to LIBS the appropriate extension library
#------------------------------------------------------------------------
AC_DEFUN([TEA_LOAD_CONFIG_LIB], [
    AC_MSG_CHECKING([For $1 library for LIBS])
    # This simplifies the use of stub libraries by automatically adding
    # the stub lib to your path.  Normally this would add to SHLIB_LD_LIBS,
    # but this is called before CONFIG_CFLAGS.  More importantly, this adds
    # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD.
    if test "x${$1_LIB_SPEC}" != "x" ; then
	if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then
	    TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"])
	    AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}])
	else
	    TEA_ADD_LIBS([${$1_LIB_SPEC}])
	    AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}])
	fi
    else
	AC_MSG_RESULT([file not found])
    fi
])

#------------------------------------------------------------------------
# TEA_EXPORT_CONFIG --
#
#	Define the data to insert into the ${PACKAGE}Config.sh file
#
# Arguments:
#
#	Requires the following vars to be set:
#		$1
#
# Results:
#	Substitutes the following vars:
#------------------------------------------------------------------------

AC_DEFUN([TEA_EXPORT_CONFIG], [
    #--------------------------------------------------------------------
    # These are for $1Config.sh
    #--------------------------------------------------------------------

    # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib)
    eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}"
    if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
	eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}"
	eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}"
    else
	eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
	eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
    fi
    $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}"
    $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}"
    $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}"
    $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}"
    $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}"
    $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}"

    AC_SUBST($1_BUILD_LIB_SPEC)
    AC_SUBST($1_LIB_SPEC)
    AC_SUBST($1_BUILD_STUB_LIB_SPEC)
    AC_SUBST($1_STUB_LIB_SPEC)
    AC_SUBST($1_BUILD_STUB_LIB_PATH)
    AC_SUBST($1_STUB_LIB_PATH)

    AC_SUBST(MAJOR_VERSION)
    AC_SUBST(MINOR_VERSION)
    AC_SUBST(PATCHLEVEL)
])


#------------------------------------------------------------------------
# TEA_PATH_CELIB --
#
#	Locate Keuchel's celib emulation layer for targeting Win/CE
#
# Arguments:
#	none
#
# Results:
#
#	Adds the following arguments to configure:
#		--with-celib=...
#
#	Defines the following vars:
#		CELIB_DIR	Full path to the directory containing
#				the include and platform lib files
#------------------------------------------------------------------------

AC_DEFUN([TEA_PATH_CELIB], [
    # First, look for one uninstalled.
    # the alternative search directory is invoked by --with-celib

    if test x"${no_celib}" = x ; then
	# we reset no_celib in case something fails here
	no_celib=true
	AC_ARG_WITH(celib,[  --with-celib=DIR        use Windows/CE support library from DIR], with_celibconfig=${withval})
	AC_MSG_CHECKING([for Windows/CE celib directory])
	AC_CACHE_VAL(ac_cv_c_celibconfig,[
	    # First check to see if --with-celibconfig was specified.
	    if test x"${with_celibconfig}" != x ; then
		if test -d "${with_celibconfig}/inc" ; then
		    ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`
		else
		    AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory])
		fi
	    fi

	    # then check for a celib library
	    if test x"${ac_cv_c_celibconfig}" = x ; then
		for i in \
			../celib-palm-3.0 \
			../celib \
			../../celib-palm-3.0 \
			../../celib \
			`ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \
			${srcdir}/../celib-palm-3.0 \
			${srcdir}/../celib \
			`ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \
			; do
		    if test -d "$i/inc" ; then
			ac_cv_c_celibconfig=`(cd $i; pwd)`
			break
		    fi
		done
	    fi
	])
	if test x"${ac_cv_c_celibconfig}" = x ; then
	    AC_MSG_ERROR([Cannot find celib support library directory])
	else
	    no_celib=
	    CELIB_DIR=${ac_cv_c_celibconfig}
	    CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
	    AC_MSG_RESULT([found $CELIB_DIR])
	fi
    fi
])

#--------------------------------------------------------------------
# TEA_EMBED_MANIFEST
#
#	Figure out if we can embed the manifest where necessary
#
# Arguments:
#	An optional manifest to merge into DLL/EXE.
#
# Results:
#	Will define the following vars:
#		VC_MANIFEST_EMBED_DLL
#		VC_MANIFEST_EMBED_EXE
#
#--------------------------------------------------------------------

AC_DEFUN([TEA_EMBED_MANIFEST], [
    AC_MSG_CHECKING(whether to embed manifest)
    AC_ARG_ENABLE(embedded-manifest,
	AC_HELP_STRING([--enable-embedded-manifest],
		[embed manifest if possible (default: yes)]),
	[embed_ok=$enableval], [embed_ok=yes])

    VC_MANIFEST_EMBED_DLL=
    VC_MANIFEST_EMBED_EXE=
    result=no
    if test "$embed_ok" = "yes" -a "${SHARED_BUILD}" = "1" \
       -a "$GCC" != "yes" ; then
	# Add the magic to embed the manifest into the dll/exe
	AC_EGREP_CPP([manifest needed], [
#if defined(_MSC_VER) && _MSC_VER >= 1400
print("manifest needed")
#endif
	], [
	# Could do a CHECK_PROG for mt, but should always be with MSVC8+
	# Could add 'if test -f' check, but manifest should be created
	# in this compiler case
	# Add in a manifest argument that may be specified
	VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest $1 -outputresource:\[$]@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest $1 -outputresource:\[$]@\;1 ; fi"
	result=yes
	if test "x$1" != x ; then
	    result="yes ($1)"
	fi
	])
    fi
    AC_MSG_RESULT([$result])
    AC_SUBST(VC_MANIFEST_EMBED_DLL)
    AC_SUBST(VC_MANIFEST_EMBED_EXE)
])

# Local Variables:
# mode: autoconf
# End:

Added jni/tkzinc/tests/all.tcl.

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8

package require Tcl 8.4
package require tcltest 2.2

tcltest::configure -testdir [file dir [file normalize [info script]]]
eval tcltest::configure $argv

tcltest::runAllTests

Added jni/tkzinc/tests/rectangle.test.

































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# -*- tcl -*-
# This file is part of the Tkzinc test suite.
# It tests the code in Rectangle.c which implements
# the rectangle item.
#

package require tcltest 2.2
eval tcltest::configure $argv

lappend auto_path [file join [file dirname [info script]] ..]
package require Tkzinc

zinc .z -width 400 -height 300 -borderwidth 2 -relief sunken
pack .z
bind .z <1> {
    puts "button down at (%x,%y)"
}
update

namespace eval ::rectangle::test {
    namespace import ::tcltest::*

#    testConstraint X [expr {...}]

    variable SETUP {
	#common setup code
    }
    variable CLEANUP {
	#common cleanup code
    }

    test example-1 {} -setup $SETUP {
	set i 1
    } -cleanup $CLEANUP

#     test example-2 {} -constraints emptyTest -setup $SETUP {
# 	# Second test; constrained
#     } -cleanup $CLEANUP -result {...}

#     test example-3 {} {
# 	# Third test; no context required
#     } {...}

    cleanupTests
}

namespace delete ::rectangle::test
	

Added jni/tkzinc/tkzinc.m4.

























































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#
# Include the TEA standard macro set
#

builtin(include,tclconfig/tcl.m4)

#
# Zinc specific macros below.
#
#
# ALL the new macros here need to be modified to
# detect the various packages needed and to get their paths.
# Right now all this is statically defined in the macros.
#
#------------------------------------------------------------------------
# ZINC_ENABLE_GL --
#
#	Specify if openGL support should be used.
#	Code for managing a damage area can also be enabled.
#
# Arguments:
#	none
#	
# Results:
#
#	Adds the following arguments to configure:
#		--enable-gl=[yes,no,damage]
#
#	Defines the following vars:
#		GL_INCLUDES	OpenGL include files path
#		GL_LIBS		additional libraries needed for GL
#		LIBS		Modified to reflect the need of new
#				libraries
#		GL		Defined if GL support is enabled
#		GL_DAMAGE	Defined if damage support has been
#				requested
#
#------------------------------------------------------------------------

AC_DEFUN(ZINC_ENABLE_GL, [
     AC_MSG_CHECKING([for build with GL])
     AC_ARG_ENABLE(gl,
 		  [  --enable-gl             build with openGL support (yes,no,damage) [[no]]],
 		  [tcl_ok=$enableval], [tcl_ok=no])

     if test "$tcl_ok" = "no"; then
 	GL_LIBS=
 	GL_INCLUDES=
 	AC_MSG_RESULT([no])
     else
	if test "${TEA_PLATFORM}" = "windows" ; then
	    GL_LIBS="-lglu32 -lopengl32"
	elif test "${TEA_WINDOWINGSYSTEM}" = "aqua" ; then
	    GL_LIBS="-framework AGL -framework OpenGL"
 	    GL_INCLUDES="${GL_INCLUDES}"
	elif test `uname -s` = "Darwin" ; then
	    GL_LIBS="-framework OpenGL"
 	    GL_INCLUDES="${GL_INCLUDES}"
        else
 	    GL_LIBS="-lGL"
 	    GL_INCLUDES="${GL_INCLUDES} -I/usr/include"
        fi

 	AC_DEFINE(GL)
 	if test "$tcl_ok" = "damage"; then
 	    AC_DEFINE(GL_DAMAGE)
        fi

 	LIBS="$LIBS $GL_LIBS"

 	if test "$tcl_ok" = "yes"; then
 	    AC_MSG_RESULT([yes (standard)])
 	else
 	    AC_MSG_RESULT([yes (with damage support)])
 	fi
     fi

     AC_SUBST(GL_LIBS)
     AC_SUBST(GL_INCLUDES)
])

#------------------------------------------------------------------------
# ZINC_ENABLE_ATC --
#
#	Specify if the Atc code should be included.
#
# Arguments:
#	none
#	
# Results:
#
#	Adds the following arguments to configure:
#		--enable-atc=[yes,no]
#
#	Defines the following vars:
#		ATC		Defined if ATC support is enabled
#
#------------------------------------------------------------------------

 AC_DEFUN(ZINC_ENABLE_ATC, [
     AC_MSG_CHECKING([for build with the ATC extensions])
     AC_ARG_ENABLE(atc,
 		  [  --enable-atc            build with ATC extensions [[yes]]],
 		  [tcl_ok=$enableval], [tcl_ok=yes])
     if test "$tcl_ok" = "no"; then
 	AC_MSG_RESULT([no])
     else
 	AC_DEFINE(ATC)
        TEA_ADD_SOURCES([OverlapMan.c])
        TEA_ADD_SOURCES([Track.c])
        TEA_ADD_SOURCES([Reticle.c])
        TEA_ADD_SOURCES([Map.c])
        TEA_ADD_SOURCES([MapInfo.c])
 	AC_MSG_RESULT([yes])
     fi
])

#------------------------------------------------------------------------
# ZINC_ENABLE_SHAPE --
#
#	Specify if the X shape extension support should be included.
#
# Arguments:
#	none
#	
# Results:
#
#	Adds the following arguments to configure:
#		--enable-shape=[yes,no]
#
#	Defines the following vars:
#		SHAPE		Defined if shape support is enabled
#
#	Adjust LIBS to include the X extension library
#
#------------------------------------------------------------------------

AC_DEFUN(ZINC_ENABLE_SHAPE, [
     AC_MSG_CHECKING([for build with X shape support])
     AC_ARG_ENABLE(shape,
 		  [  --enable-shape          build with X shape support (if applicable) [[yes]]],
 		  [tcl_ok=$enableval], [tcl_ok=yes])
     if test "$tcl_ok" = "no"; then
 	AC_MSG_RESULT([no])
     else
         if test "${TEA_PLATFORM}" = "windows" ; then
 	    AC_MSG_RESULT([no (not available on windows)])
	elif test "${TEA_WINDOWINGSYSTEM}" = "aqua" ; then
 	    AC_MSG_RESULT([no (not available on windows)])
        else
 	    AC_DEFINE(SHAPE)
 	    AC_MSG_RESULT([yes])
	    LIBS="${LIBS} -lXext"
 	fi
     fi
])

Added jni/tkzinc/win/Copyright.rtf.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1036\deflangfe1036{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;}
{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}{\f172\froman\fcharset238\fprq2 Times New Roman CE;}{\f173\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f175\froman\fcharset161\fprq2 Times New Roman Greek;}
{\f176\froman\fcharset162\fprq2 Times New Roman Tur;}{\f177\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f178\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f179\froman\fcharset186\fprq2 Times New Roman Baltic;}
{\f180\froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f182\fswiss\fcharset238\fprq2 Arial CE;}{\f183\fswiss\fcharset204\fprq2 Arial Cyr;}{\f185\fswiss\fcharset161\fprq2 Arial Greek;}{\f186\fswiss\fcharset162\fprq2 Arial Tur;}
{\f187\fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f188\fswiss\fcharset178\fprq2 Arial (Arabic);}{\f189\fswiss\fcharset186\fprq2 Arial Baltic;}{\f190\fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f192\fmodern\fcharset238\fprq1 Courier New CE;}
{\f193\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f195\fmodern\fcharset161\fprq1 Courier New Greek;}{\f196\fmodern\fcharset162\fprq1 Courier New Tur;}{\f197\fmodern\fcharset177\fprq1 Courier New (Hebrew);}
{\f198\fmodern\fcharset178\fprq1 Courier New (Arabic);}{\f199\fmodern\fcharset186\fprq1 Courier New Baltic;}{\f200\fmodern\fcharset163\fprq1 Courier New (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;
\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;
\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1036\langfe1036\cgrid\langnp1036\langfenp1036 \snext0 Normal;}{\*\cs10 \additive \ssemihidden 
Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv 
\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}{\s15\ql \li0\ri0\widctlpar
\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f2\fs20\lang1036\langfe1036\cgrid\langnp1036\langfenp1036 
\sbasedon0 \snext15 \styrsid9046091 HTML Preformatted;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid9046091\rsid11037878\rsid11602808\rsid13259699\rsid16008859}{\*\generator Microsoft Word 10.0.3416;}{\info
{\title This software is copyrighted by the Centre d\'92\'e9tude de la Navigation}{\author Lecoanet}{\operator Lecoanet}{\creatim\yr2005\mo3\dy23\hr17\min11}{\revtim\yr2005\mo6\dy10\hr9\min49}{\version6}{\edmins9}{\nofpages1}{\nofwords123}{\nofchars679}
{\*\company CENA}{\nofcharsws801}{\vern16453}}\margl1417\margr1417\margt1417\margb1417 \widowctrl\ftnbj\aenddoc\hyphhotz425\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984
\dghshow0\dgvshow3\jcompress\viewkind4\viewscale100\nolnhtadjtbl\rsidroot11037878 \fet0\sectd \linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}
{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}
{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain 
\ql \li0\ri50\nowidctlpar\faauto\rin50\lin0\itap0\pararsid11602808 \fs24\lang1036\langfe1036\cgrid\langnp1036\langfenp1036 {\f1\fs20\insrsid16008859\charrsid16008859 Copyright (c) 2005, Centre d'\'e9tudes de la Navigation A\'e9rienne, Patrick Lecoanet

\par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0\pararsid16008859 {\f1\fs20\lang1033\langfe1036\langnp1033\insrsid16008859\charrsid16008859 All rights reserved.}{\f1\fs20\lang1033\langfe1036\langnp1033\insrsid16008859 
\par }{\f1\fs20\lang1033\langfe1036\langnp1033\insrsid13259699\charrsid16008859 
\par }\pard\plain \s15\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9046091 
\f2\fs20\lang1036\langfe1036\cgrid\langnp1036\langfenp1036 {\f1\lang2057\langfe1036\langnp2057\insrsid9046091\charrsid9046091 This library is free software; you can redistribute it and/or
\par }\pard \s15\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9046091 {
\f1\lang2057\langfe1036\langnp2057\insrsid9046091\charrsid9046091 modify it under the terms of the GNU Lesser General Public
\par License as published by the Free Software Foundation; either
\par version 2.1 of the License, or (at your option) any later version.
\par 
\par This library is distributed in the hope that it will be useful,
\par but WITHOUT ANY WARRANTY; without even the implied warranty of
\par MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
\par }\pard \s15\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9046091 {
\f1\lang2057\langfe1036\langnp2057\insrsid9046091\charrsid9046091 Lesser General Public License for more details.
\par }\pard \s15\ql \li0\ri0\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid9046091 {
\f1\lang2057\langfe1036\langnp2057\insrsid9046091\charrsid9046091 
\par You should have received a copy of the GNU Lesser General Public
\par License along with this library; if not, write to the Free Software
\par Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA}{\f1\lang2057\langfe1036\langnp2057\insrsid16008859\charrsid9046091 
\par }}

Added jni/tkzinc/win/InstallerIcons/Banner.bmp.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Complete.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Custom.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Dialog.bmp.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Exclam.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Info.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/New.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Remove.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Repair.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Typical.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/InstallerIcons/Up.ico.

cannot compute difference between binary files

Added jni/tkzinc/win/Tkzinc.iss.













































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#define TkzincVersion "3.3.4"
#define TkzincWinVersion "334"

[Setup]
AppName=Tkzinc
AppVersion={#TkzincVersion}
AppVerName=Tkzinc {#TkzincVersion}
LicenseFile="Copyright.rtf"
;;
;; No default directory really exist. Use ActiveTcl default location
;; as a fallback. In all cases the documentation will be installed
;; in this location.
DefaultDirName={pf}\Tkzinc
DisableProgramGroupPage=yes
OutputBaseFilename=Tkzinc{#TkzincWinVersion}

[Messages]
WelcomeLabel2=This will install [name/ver] on your computer.
SelectDirDesc=Where should [name] documentation be installed?
SelectDirLabel3=Setup will install [name] documentation into the following folder.

[Components]
Name: "Tcl"; Description: "Tkzinc Tcl support"; Types: full compact custom; Check: ActiveTcl
Name: "Tcl\Main"; Description: "Tcl component"; Types: full compact custom; Check: ActiveTcl
Name: "Tcl\Demo"; Description: "Tcl demos"; Types: full custom; Check: ActiveTcl
Name: "Perl"; Description: "Perl support files"; Types: full compact custom; Check: ActivePerl
Name: "Perl\Main"; Description: "Perl component"; Types: full compact custom; Check: ActivePerl
Name: "Perl\Demo"; Description: "Perl demos"; Types: full custom; Check: ActivePerl
Name: "Python"; Description: "Python support files"; Types: full compact custom; Check: ActivePython
Name: "Python\Main"; Description: "Python component"; Types: full compact custom; Check: ActivePython
Name: "Python\Demo"; Description: "Python demos"; Types: full custom; Check: ActivePython
Name: "Doc"; Description: "Tkzinc documentation"; Types: full custom

[Files]
;;
;; Tcl component files
Source: "buildtcl\Tkzinc{#TkzincWinVersion}.dll"; DestDir: "{code:TclDir}\lib\Tkzinc{#TkzincVersion}"; Components: Tcl\Main
Source: "buildtcl\pkgIndex.tcl"; DestDir: "{code:TclDir}\lib\Tkzinc{#TkzincVersion}"; Components: Tcl\Main
Source: "buildtcl\zincGraphics.tcl"; DestDir: "{code:TclDir}\lib\Tkzinc{#TkzincVersion}"; Components: Tcl\Main
Source: "buildtcl\zincText.tcl"; DestDir: "{code:TclDir}\lib\Tkzinc{#TkzincVersion}"; Components: Tcl\Main
Source: "buildtcl\zincLogo.tcl"; DestDir: "{code:TclDir}\lib\Tkzinc{#TkzincVersion}"; Components: Tcl\Main
Source: "..\README"; DestDir: "{code:TclDir}\lib\Tkzinc{#TkzincVersion}"; Components: Tcl\Main
Source: "..\BUGS"; DestDir: "{code:TclDir}\lib\Tkzinc{#TkzincVersion}"; Components: Tcl\Main
;;
;; Tcl demo files
Source: "..\demos\*.tcl"; DestDir: "{code:TclDir}\demos\Tkzinc"; Components: Tcl\Demo
Source: "buildtcl\zinc-widget.tcl"; DestDir: "{code:TclDir}\demos\Tkzinc"; Components: Tcl\Demo
Source: "..\demos\images\*.gif"; DestDir: "{code:TclDir}\demos\Tkzinc\images"; Components: Tcl\Demo
Source: "..\demos\images\*.png"; DestDir: "{code:TclDir}\demos\Tkzinc\images"; Components: Tcl\Demo
Source: "..\demos\data\hegias_parouest_TE.vid"; DestDir: "{code:TclDir}\demos\Tkzinc\data"; Components: Tcl\Demo
Source: "..\demos\data\videomap_orly"; DestDir: "{code:TclDir}\demos\Tkzinc\data"; Components: Tcl\Demo
Source: "..\demos\data\videomap_paris-w_90_2"; DestDir: "{code:TclDir}\demos\Tkzinc\data"; Components: Tcl\Demo
;;
;; Documentation files
Source: "..\doc\refman.pdf"; DestDir: "{app}"; Components: Doc
Source: "..\doc\index.html"; DestDir: "{app}"; Components: Doc
Source: "..\doc\refman.html"; DestDir: "{app}"; Components: Doc
Source: "..\doc\refmanch*.html"; DestDir: "{app}"; Components: Doc
Source: "..\doc\refmanli*.html"; DestDir: "{app}"; Components: Doc
Source: "..\doc\*.png"; DestDir: "{app}"; Components: Doc
;;
;; Perl component files
Source: "buildperl\blib\arch\auto\Tk\Zinc\Zinc.dll"; DestDir: "{code:PerlDir}\site\lib\auto\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\arch\auto\Tk\Zinc\Zinc.exp"; DestDir: "{code:PerlDir}\site\lib\auto\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\arch\auto\Tk\Zinc\Zinc.lib"; DestDir: "{code:PerlDir}\site\lib\auto\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\arch\auto\Tk\Zinc\Zinc.bs"; DestDir: "{code:PerlDir}\site\lib\auto\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc.pm"; DestDir: "{code:PerlDir}\site\lib\Tk"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\Debug.pm"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\Graphics.pm"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\Graphics.pod"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\Logo.pm"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\Text.pm"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\Trace.pm"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\TraceErrors.pm"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
Source: "buildperl\blib\lib\Tk\Zinc\TraceUtils.pm"; DestDir: "{code:PerlDir}\site\lib\Tk\Zinc"; Components: Perl\Main
;;
;; Perl demo files
Source: "buildperl\blib\script\zinc-demos.bat"; DestDir: "{code:PerlDir}\bin"; Components: Perl\Demo
Source: "buildperl\blib\lib\Tk\demos\zinc_contrib_lib\*"; DestDir: "{code:PerlDir}\site\lib\Tk\demos\zinc_contrib_lib"; Components: Perl\Demo
Source: "buildperl\blib\lib\Tk\demos\zinc_data\*"; DestDir: "{code:PerlDir}\site\lib\Tk\demos\zinc_data"; Components: Perl\Demo
Source: "buildperl\blib\lib\Tk\demos\zinc_lib\*"; DestDir: "{code:PerlDir}\site\lib\Tk\demos\zinc_lib"; Components: Perl\Demo
Source: "buildperl\blib\lib\Tk\demos\zinc_pm\*"; DestDir: "{code:PerlDir}\site\lib\Tk\demos\zinc_pm"; Components: Perl\Demo
;;
;; Python component files
Source: "buildtcl\Tkzinc{#TkzincWinVersion}.dll"; DestDir: "{code:PythonDir}\tcl\Tkzinc{#TkzincVersion}"; Components: Python\Main
Source: "buildtcl\pkgIndex.tcl"; DestDir: "{code:PythonDir}\tcl\Tkzinc{#TkzincVersion}"; Components: Python\Main
Source: "buildtcl\zincGraphics.tcl"; DestDir: "{code:PythonDir}\tcl\Tkzinc{#TkzincVersion}"; Components: Python\Main
Source: "buildtcl\zincText.tcl"; DestDir: "{code:PythonDir}\tcl\Tkzinc{#TkzincVersion}"; Components: Python\Main
Source: "buildtcl\zincLogo.tcl"; DestDir: "{code:PythonDir}\tcl\Tkzinc{#TkzincVersion}"; Components: Python\Main
Source: "..\Python\library\Zinc.py"; DestDir: "{code:PythonDir}\Lib\Zinc"; Components: Python\Main
Source: "..\Python\library\__init__.py"; DestDir: "{code:PythonDir}\Lib\Zinc"; Components: Python\Main
Source: "..\Python\library\graphics.py"; DestDir: "{code:PythonDir}\Lib\Zinc"; Components: Python\Main
Source: "..\Python\library\geometry.py"; DestDir: "{code:PythonDir}\Lib\Zinc"; Components: Python\Main
Source: "..\Python\library\pictorial.py"; DestDir: "{code:PythonDir}\Lib\Zinc"; Components: Python\Main
;;
;; Python demo files
Source: "..\Python\demos\testGraphics.py"; DestDir: "{code:PythonDir}\ZincDemo"; Components: Python\Demo
Source: "..\Python\demos\paper.gif"; DestDir: "{code:PythonDir}\ZincDemo"; Components: Python\Demo


[Code]
var
  TclVersion: String;
  TclPath: String;
  PerlVersion: String;
  PerlPath: String;
  PythonVersion: String;
  PythonPath: String;

  InfoPage: TOutputMsgWizardPage;

function InitializeSetup() : Boolean;
begin
  if RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\ActiveState\ActiveTcl', 'CurrentVersion', TclVersion) then begin
    RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\ActiveState\ActiveTcl\' + TclVersion, '', TclPath)
  end else begin
    TclVersion := '';
  end;
  if RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\ActiveState\ActivePerl', 'CurrentVersion', PerlVersion) then begin
    RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\ActiveState\ActivePerl\' + PerlVersion, '', PerlPath)
  end else begin
    PerlVersion := '';
  end;
  if RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\ActiveState\ActivePython', 'CurrentVersion', PythonVersion) then begin
    RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\ActiveState\ActivePython\' + PythonVersion, '', PythonPath)
  end else begin
    PythonVersion := '';
  end;
  Result := True;
end;

procedure InitializeWizard;
var
  Info: String;
begin
  Info := '';
  if (TclVersion <> '') or (PerlVersion <> '') or (PythonVersion <> '') then begin
    Info := Info + 'The following languages have been detected: '#13#13;
    if TclVersion <> '' then begin
      Info := Info + '  - ActiveTcl version ' + TclVersion + '  in:  ' + TclPath + ''#13;
    end;
    if PerlVersion <> '' then begin
      Info := Info + '  - ActivePerl version ' + PerlVersion + '  in:  ' + PerlPath + ''#13;
    end;
    if PythonVersion <> '' then begin
      Info := Info + '  - ActivePython version ' + PythonVersion + '  in:  ' + PythonPath + ''#13;
    end;
    Info := Info + #13'The relevant Tkzinc files will be installed in the detected locations.'#13;
  end;
  if (TclVersion = '') or (PerlVersion = '') or (PythonVersion = '') then begin
    Info := Info + #13'Setup failed to detect:'#13#13;
    if TclVersion = '' then begin
      Info := Info + '  - ActiveTcl'#13;
    end;
    if PerlVersion = '' then begin
      Info := Info + '  - ActivePerl'#13;
    end;
    if PythonVersion = '' then begin
      Info := Info + '  - ActivePython'#13;
    end;
    Info := Info + #13'Tkzinc will not be available for those environments.'#13#13;
    Info := Info + 'Please, install the ActiveState packages before the Tkzinc package.'
  end;

  InfoPage := CreateOutputMsgPage(wpLicense, 'Installed Languages',
                                  'Auto detected ActiveState packages', Info);
end;

function ActiveTcl() : Boolean;
begin
  Result := TclVersion <> '';
end;

function ActivePerl() : Boolean;
begin
  Result := PerlVersion <> '';
end;

function ActivePython() : Boolean;
begin
  Result := PythonVersion <> '';
end;

function TclDir(param: String) : String;
begin
  Result := TclPath;
end;

function PerlDir(param: String) : String;
begin
  Result := PerlPath;
end;

function PythonDir(param: String) : String;
begin
  Result := PythonPath;
end;

Added jni/tkzinc/win/Tkzinc.wxs.in.





































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
  <Product Name='Tkzinc' Id='918B6AC6-82C9-497F-B87C-498475CDC6ED'
    Language='1033' Codepage='1252' Version='@MAJOR_VERSION@.@MINOR_VERSION@.@PATCHLEVEL@' Manufacturer='CENA'>

    <Package Id='????????-????-????-????-????????????' Keywords='Installer'
      Description="Tkzinc Installer for Active Tcl/Perl/Python"
      Comments='Tkzinc is copyright CENA and Patrick Lecoanet' Manufacturer='CENA'
      InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />

    <Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
    <Property Id='DiskPrompt' Value="Tkzinc Installation [1]" />

    <!-- Get the version and install location of the various Active products -->
    <!-- from the registry -->

    <Property Id="RequiredTclVersion">8.4</Property>
    <Property Id="RequiredPerlVersion">811</Property>

    <Property Id="TkzincLongVersion">@MAJOR_VERSION@.@MINOR_VERSION@.@PATCHLEVEL@</Property>
    <Property Id="TkzincShortVersion">@MAJOR_VERSION@@MINOR_VERSION@</Property>
    <Property Id="TkzincDLLVersion">@MAJOR_VERSION@@MINOR_VERSION@@PATCHLEVEL@</Property>

    <Property Id='ACTIVE_TCL_VERSION'>
      <RegistrySearch Id='ActiveTclRegVersion' Type='registry'
        Root="HKLM" Key='SOFTWARE\ActiveState\ActiveTcl' Name='CurrentVersion' />
    </Property>
    <Property Id='ACTIVE_PERL_VERSION'>
      <RegistrySearch Id='ActivePerlRegVersion' Type='registry'
        Root="HKLM" Key='SOFTWARE\ActiveState\ActivePerl' Name='CurrentVersion' />
    </Property>
    <Property Id='ACTIVE_PYTHON_VERSION'>
      <RegistrySearch Id='ActivePythonRegVersion' Type='registry'
        Root="HKLM" Key='SOFTWARE\ActiveState\ActivePython' Name='CurrentVersion' />
    </Property>
    <Property Id='ACTIVE_TCL_DIR'>
      <RegistrySearch Id='ActiveTclRegDir' Type='registry'
        Root="HKLM" Key="SOFTWARE\ActiveState\ActiveTcl\[ACTIVE_TCL_VERSION]" />
    </Property>
    <Property Id='ACTIVE_PERL_DIR'>
      <RegistrySearch Id='ActivePerlRegDir' Type='registry'
        Root="HKLM" Key="SOFTWARE\ActiveState\ActivePerl\[ACTIVE_PERL_VERSION]" />
    </Property>
    <Property Id='ACTIVE_PYTHON_DIR'>
      <RegistrySearch Id='ActivePythonRegDir' Type='registry'
        Root="HKLM" Key="SOFTWARE\ActiveState\ActivePython\[ACTIVE_PYTHON_VERSION]" />
    </Property>
 
    <!-- Assembly of the various components in selectable features and sub-features -->

    <!-- This feature tree is a dummy used to force a proper order in the registry
         searches (AppSearch table insert order) so that ACTIVE_TCL_VERSION is
         available when ACTIVE_TCL_DIR is looked up, etc. I'd love to know how
         to do it canonically. -->
    <Feature Id='Dummy' Title="Dummy" Description='Dummy feature set.' Level='0' Display='hidden'>
      <Feature Id='ACTIVE_TCL_VERSION' Title='DummySub' Level='0' />
      <Feature Id='ACTIVE_PERL_VERSION' Title='DummySub' Level='0' />
      <Feature Id='ACTIVE_PYTHON_VERSION' Title='DummySub' Level='0' />
    </Feature>

    <Feature Id='Complete' Title="Tkzinc" Description='The complete package.'
      TypicalDefault='install' Display='expand' Level='1'>
      <Feature Id='ActiveTclZinc' Title='Tkzinc for Tcl'
        Description='The Tkzinc package for ActiveTcl.' TypicalDefault='install' Level='1'
        ConfigurableDirectory='ACTIVE_TCL_DIR'>
        <!-- <Condition Level='0'><![CDATA[NOT (ACTIVE_TCL_VERSION << RequiredTclVersion)]]></Condition> -->
        <Feature Id='ActiveTclZincLib' Title='Tkzinc Tcl module'
          Description='The Tkzinc library files and dll.' TypicalDefault='install' Level='1'>
          <ComponentRef Id='TclDll' />
        </Feature>
        <Feature Id='ActiveTclZincDemo' Title='Tkzinc Tcl demos' Description='The Tkzinc demo suite in Tcl.'
          TypicalDefault='install' Level='1'>
          <ComponentRef Id='TclDemos' />
          <ComponentRef Id='TclDemoImages' />
          <ComponentRef Id='TclDemoData' />
        </Feature>
        <Feature Id='ActiveTclZincDoc' Title='Tkzinc documentation'
          Description='The Tkzinc manual in HTML and pdf formats.' TypicalDefault='install' Level='1'>
          <ComponentRef Id='TkzincDoc' />
        </Feature>
      </Feature>
      <Feature Id='ActivePerlZinc' Title='Tkzinc for Perl'
        Description='The Tkzinc package for ActivePerl.' TypicalDefault='install' Level='1'
        ConfigurableDirectory='ACTIVE_PERL_DIR'>
        <!-- <Condition Level='0'><![CDATA[ACTIVE_PERL_VERSION < RequiredPerlVersion]]></Condition> -->
        <Feature Id='ActivePerlZincLib' Title='Tkzinc Perl module'
          Description='The Tkzinc library files and dll.' TypicalDefault='install' Level='1'>
          <ComponentRef Id='PerlDll' />
          <ComponentRef Id='PerlLib1' />
          <ComponentRef Id='PerlLib2' />
        </Feature>
        <Feature Id='ActivePerlZincDemos' Title='Tkzinc Perl demos'
          Description='The Tkzinc demo suite in Perl.' TypicalDefault='install' Level='1'>
          <ComponentRef Id='PerlDemosBin' />
          <ComponentRef Id='PerlDemosContrib' />
          <ComponentRef Id='PerlDemosData' />
          <ComponentRef Id='PerlDemosScripts' />
          <ComponentRef Id='PerlDemosModules' />
        </Feature>
      </Feature>
      <Feature Id='ActivePythonZinc' Title='Tkzinc for Python'
        Description='The Tkzinc package for ActivePython.' TypicalDefault='install' Level='1'
        ConfigurableDirectory='ACTIVE_PYTHON_DIR'>
        <ComponentRef Id='PythonTcl' />
        <ComponentRef Id='PythonGlue' />
        <ComponentRef Id='PythonDemo' />
      </Feature>
    </Feature>

    <!-- Description of the files into components -->
    <Directory Id='TARGETDIR' Name='SourceDir'>
      <Directory Id='ACTIVE_TCL_DIR' Name='Tcl'>
        <Directory Id='ActiveTclLib' Name='lib'>
          <Directory Id='TkzincLibDir' Name='Tkzinc@MAJOR_VERSION@@MINOR_VERSION@' LongName='Tkzinc@MAJOR_VERSION@.@MINOR_VERSION@.@PATCHLEVEL@'>
            <Component Id='TclDll' Guid='51BE30A0-A2EA-4514-B84E-43AC2CC19075'>
              <File Id='TkzincDll' Name='Tkzinc@MAJOR_VERSION@@MINOR_VERSION@.dll' LongName='Tkzinc@MAJOR_VERSION@@MINOR_VERSION@@PATCHLEVEL@.dll'
                DiskId='1' src='buildtcl/Tkzinc@MAJOR_VERSION@@MINOR_VERSION@@PATCHLEVEL@.dll' Vital='yes' />
              <File Id='pkgIndexTcl' Name='pkgIndex.tcl' DiskId='1' src='buildtcl/pkgIndex.tcl' Vital='yes' />
              <File Id='zincGraphicsTcl' Name='znGraph.tcl' LongName='zincGraphics.tcl' DiskId='1'
                src='buildtcl\zincGraphics.tcl' />
              <File Id='zincTextTcl' Name='znText.tcl' LongName='zincText.tcl' DiskId='1' src='buildtcl\zincText.tcl' />
              <File Id='zincLogoTcl' Name='znLogo.tcl' LongName='zincLogo.tcl' DiskId='1' src='buildtcl\zincLogo.tcl' />
              <File Id='Readme' Name='README' DiskId='1' src='..\README' />
              <File Id='Bugs' Name='BUGS' DiskId='1' src='..\BUGS' />
            </Component>
          </Directory>
        </Directory>
        <Directory Id='ActiveTclDemos' Name='demos'>
          <Directory Id='TkzincDemoDir' Name='Tkzinc'>
            <Component Id='TclDemos' Guid='AA8CCFAB-CB2C-48E3-B8CD-B0088875513B'>
              <File Id='allOptionsTcl' Name='allOpts.tcl' LongName='allOptions.tcl'
                DiskId='1' src='..\demos\allOptions.tcl' />
              <File Id='atomicGroupsTcl' Name='atmgrps.tcl' LongName='atomicGroups.tcl'
                DiskId='1' src='..\demos\atomicGroups.tcl' />
              <File Id='clippingTcl' Name='clipping.tcl' DiskId='1' src='..\demos\clipping.tcl' />
              <File Id='colorCircularTcl' Name='colcirc.tcl' LongName='colorCircular.tcl'
                DiskId='1' src='..\demos\colorCircular.tcl' />
              <File Id='colorXTcl' Name='colorX.tcl' DiskId='1' src='..\demos\colorX.tcl' />
              <File Id='colorYTcl' Name='colorY.tcl' DiskId='1' src='..\demos\colorY.tcl' />
              <File Id='contoursTcl' Name='contours.tcl' DiskId='1' src='..\demos\contours.tcl' />
              <File Id='curveBezierTcl' Name='curvbez.tcl' LongName='curveBezier.tcl'
                DiskId='1' src='..\demos\curveBezier.tcl' />
              <File Id='fillRuleTcl' Name='fillRule.tcl' DiskId='1' src='..\demos\fillRule.tcl' />
              <File Id='groupsInAtcStripsTcl' Name='grpstrps.tcl' LongName='groupsInAtcStrips.tcl'
                DiskId='1' src='..\demos\groupsInAtcStrips.tcl' />
              <File Id='groupsPriorityTcl' Name='grppri.tcl' LongName='groupsPriority.tcl'
                DiskId='1' src='..\demos\groupsPriority.tcl' />
              <File Id='iconTransformTcl' Name='iconxfm.tcl' LongName='iconTransform.tcl'
                DiskId='1' src='..\demos\iconTransform.tcl' />
              <File Id='itemsTcl' Name='items.tcl' DiskId='1' src='..\demos\items.tcl' />
              <File Id='labelformatTcl' Name='lblfmt.tcl' LongName='labelformat.tcl'
                DiskId='1' src='..\demos\labelformat.tcl' />
              <File Id='linesTcl' Name='lines.tcl' DiskId='1' src='..\demos\lines.tcl' />
              <File Id='magicLensTcl' Name='magclens.tcl' LongName='magicLens.tcl'
                DiskId='1' src='..\demos\magicLens.tcl' />
              <File Id='pathTagsTcl' Name='pathTags.tcl' DiskId='1' src='..\demos\pathTags.tcl' />
              <File Id='photoAlphaTcl' Name='photalph.tcl' LongName='photoAlpha.tcl'
                DiskId='1' src='..\demos\photoAlpha.tcl' />
              <File Id='reliefsTcl' Name='reliefs.tcl' DiskId='1' src='..\demos\reliefs.tcl' />
              <File Id='simpleInteractionTrackTcl' Name='sinttrck.tcl' LongName='simpleInteractionTrack.tcl'
                DiskId='1' src='..\demos\simpleInteractionTrack.tcl' />
              <File Id='simpleRadarTcl' Name='smplradr.tcl' LongName='simpleRadar.tcl'
                DiskId='1' src='..\demos\simpleRadar.tcl' />
              <File Id='testGraphicsTcl' Name='tstgraph.tcl' LongName='testGraphics.tcl'
                DiskId='1' src='..\demos\testGraphics.tcl' />
              <File Id='textInputTcl' Name='txtinput.tcl' LongName='textInput.tcl'
                DiskId='1' src='..\demos\textInput.tcl' />
              <File Id='tigerTcl' Name='tiger.tcl' DiskId='1' src='..\demos\tiger.tcl' />
              <File Id='tkZincLogoTcl' Name='tkznlogo.tcl' LongName='tkZincLogo.tcl'
                DiskId='1' src='..\demos\tkzinclogo.tcl' />
              <File Id='transformsTcl' Name='xforms.tcl' LongName='transforms.tcl'
                DiskId='1' src='..\demos\transforms.tcl' />
              <File Id='trianglesTcl' Name='triangle.tcl' LongName='triangles.tcl' DiskId='1' src='..\demos\triangles.tcl' />
              <File Id='windowContoursTcl' Name='wincont.tcl' LongName='windowContours.tcl'
                DiskId='1' src='..\demos\windowContours.tcl' />
              <File Id='zincWidgetTcl' Name='znwidgt.tcl' LongName='zinc-widget.tcl'
                DiskId='1' src='buildtcl\zinc-widget.tcl' />
            </Component>
            <Directory Id='TkzincImagesDir' Name='images'>
              <Component Id='TclDemoImages' Guid='AE428767-370A-4BC7-938E-8BD148C457CF'>
                <File Id='backTexGif' Name='backTex.gif' LongName='background_texture.gif'
                  DiskId='1' src='..\demos\images\background_texture.gif' />
                <File Id='TclPaperGif' Name='paper.gif' DiskId='1' src='..\demos\images\paper.gif' />
                <File Id='PaperGrey1Gif' Name='paperG1.gif' LongName='paper-grey1.gif'
                  DiskId='1' src='..\demos\images\paper-grey1.gif' />
                <File Id='PaperGreyGif' Name='paperG.gif' LongName='paper-grey.gif'
                  DiskId='1' src='..\demos\images\paper-grey.gif' />
                <File Id='PhotoAlphaPng' Name='pAlpha.png' LongName='photoAlpha.png'
                  DiskId='1' src='..\demos\images\photoAlpha.png' />
                <File Id='StrippedTexGif' Name='stripTex.gif' LongName='stripped_texture.gif'
                  DiskId='1' src='..\demos\images\stripped_texture.gif' />
                <File Id='ZincGif' Name='zinc.gif' LongName='zinc.gif'
                  DiskId='1' src='..\demos\images\zinc.gif' />
              </Component>
            </Directory>
            <Directory Id='TkzincDataDir' Name='data'>
              <Component Id='TclDemoData' Guid='C00CC878-C0BE-4579-A864-47818C75FCC3'>
                <File Id='parOuestVid' Name='parOuest.vid' LongName='hegias_parouest_TE.vid'
                  DiskId='1' src='..\demos\data\hegias_parouest_TE.vid' />
                <File Id='orlyVid' Name='orly.vid' LongName='videomap_orly'
                  DiskId='1' src='..\demos\data\videomap_orly' />
                <File Id='parisW902Vid' Name='parisW.vid' LongName='videomap_paris-w_90_2'
                  DiskId='1' src='..\demos\data\videomap_paris-w_90_2' />
              </Component>
            </Directory>
          </Directory>
        </Directory>
        <Directory Id='ActiveTclDoc' Name='doc'>
          <Component Id='TkzincDoc' Guid='08317BAD-DC99-40BA-8CF6-653C59012251'>
            <File Id='RefmanPdf' Name='refman.pdf' DiskId='1' src='..\doc\refman.pdf' />
            <File Id='RefmanHtml' Name='refman.htm' LongName='refman.html'
              DiskId='1' src='..\doc\refman.html' />
            <File Id='RefmanCss' Name='refman.css' DiskId='1' src='..\doc\refman.html' />
            <File Id='RefmanCh1Html' Name='refmnc1.htm' LongName='refmanch1.html'
              DiskId='1' src='..\doc\refmanch1.html' />
            <File Id='RefmanCh2Html' Name='refmnc2.htm' LongName='refmanch2.html'
              DiskId='1' src='..\doc\refmanch2.html' />
            <File Id='RefmanCh3Html' Name='refmnc3.htm' LongName='refmanch3.html'
              DiskId='1' src='..\doc\refmanch3.html' />
            <File Id='RefmanCh4Html' Name='refmnc4.htm' LongName='refmanch4.html'
              DiskId='1' src='..\doc\refmanch4.html' />
            <File Id='RefmanCh5Html' Name='refmnc5.htm' LongName='refmanch5.html'
              DiskId='1' src='..\doc\refmanch5.html' />
            <File Id='RefmanCh6Html' Name='refmnc6.htm' LongName='refmanch6.html'
              DiskId='1' src='..\doc\refmanch6.html' />
            <File Id='RefmanCh7Html' Name='refmnc7.htm' LongName='refmanch7.html'
              DiskId='1' src='..\doc\refmanch7.html' />
            <File Id='RefmanCh8Html' Name='refmnc8.htm' LongName='refmanch8.html'
              DiskId='1' src='..\doc\refmanch8.html' />
            <File Id='RefmanCh9Html' Name='refmnc9.htm' LongName='refmanch9.html'
              DiskId='1' src='..\doc\refmanch9.html' />
            <File Id='RefmanCh10Html' Name='refmnc10.htm' LongName='refmanch10.html'
              DiskId='1' src='..\doc\refmanch10.html' />
            <File Id='Refmanli1Html' Name='refmnli1.htm' LongName='refmanli1.html'
              DiskId='1' src='..\doc\refmanli1.html' />
            <File Id='Refmanli2Html' Name='refmnli2.htm' LongName='refmanli2.html'
              DiskId='1' src='..\doc\refmanli2.html' />
            <File Id='Refmanli3Html' Name='refmnli3.htm' LongName='refmanli3.html'
              DiskId='1' src='..\doc\refmanli3.html' />
            <File Id='Tmp1Png' Name='nayk0a01.png' DiskId='1' src='..\doc\nayk0a01.png' />
            <File Id='AllEdgesPng' Name='alledges.png' DiskId='1' src='..\doc\alledges.png' />
            <File Id='AllReliefsPng' Name='allrelfs.png' LongName='allreliefs.png'
              DiskId='1' src='..\doc\allreliefs.png' />
            <File Id='AllGradientsPng' Name='allgrdts.png' LongName='allgradients.png'
              DiskId='1' src='..\doc\allgradients.png' />
            <File Id='AllLineShapesPng' Name='allnshps.png' LongName='alllineshapes.png'
              DiskId='1' src='..\doc\alllineshapes.png' />
            <File Id='AlphaStipPng' Name='alphstip.png' LongName='alphastip.png'
              DiskId='1' src='..\doc\alphastip.png' />
            <File Id='AtcSymbPng' Name='atcsymb.png' DiskId='1' src='..\doc\atcsymb.png' />
            <File Id='FillRulePng' Name='fillrule.png' DiskId='1' src='..\doc\fillrule.png' />
            <File Id='TabularExamplePng' Name='tabex.png' LongName='tabularexample.png'
              DiskId='1' src='..\doc\tabularexample.png' />
            <File Id='TextThroughHolesPng' Name='txtholes.png' LongName='textthroughholes.png'
              DiskId='1' src='..\doc\textthroughholes.png' />
            <File Id='TkZincLogo' Name='tkznlogo.png' LongName='tkzinclogo.png'
              DiskId='1' src='..\doc\tkzinclogo.png' />
            <File Id='TrackExamplePng' Name='trackex.png' LongName='trackexample.png'
              DiskId='1' src='..\doc\trackexample.png' />
            <File Id='WayPointExamplePng' Name='wpex.png' LongName='waypointexample.png'
              DiskId='1' src='..\doc\waypointexample.png' />
          </Component>
        </Directory>
      </Directory>
      
      <Directory Id='ACTIVE_PERL_DIR' Name='Perl'>
        <Directory Id='ActivePerlBin' Name='bin'>
          <Component Id='PerlDemosBin' Guid='84098519-77E4-4525-A900-F8684670E7F1'>
            <File Id='PerlDemosBat' Name='zincdemo.bat' LongName='zinc-demos.bat'
              DiskId='1' src='buildperl\blib\script\zinc-demos.bat' />
          </Component>
        </Directory>
        <Directory Id='ActivePerlSite' Name='site'>
          <Directory Id='ActivePerlSiteLib' Name='lib'>
            <Directory Id='ActivePerlSiteLibAuto' Name='auto'>
              <Directory Id='ActivePerlSiteLibAutoTk' Name='Tk'>
                <Directory Id='ActivePerlSiteLibAutoTkZinc' Name='Zinc'>
                  <Component Id='PerlDll' Guid='B543E6D9-73AF-415C-97E0-524110749FBD'>
                    <File Id='ZincDll' Name='Zinc.dll' DiskId='1' src='buildperl\blib\arch\auto\Tk\Zinc\Zinc.dll' />
                    <File Id='ZincExp' Name='Zinc.exp' DiskId='1' src='buildperl\blib\arch\auto\Tk\Zinc\Zinc.exp' />
                    <File Id='ZincLib' Name='Zinc.lib' DiskId='1' src='buildperl\blib\arch\auto\Tk\Zinc\Zinc.lib' />
                    <File Id='ZincBs' Name='Zinc.bs' DiskId='1' src='buildperl\blib\arch\auto\Tk\Zinc\Zinc.bs' />
                  </Component>
                </Directory>
              </Directory>
            </Directory>
            <Directory Id='ActivePerlSiteLibTk' Name='Tk'>
              <Component Id='PerlLib1' Guid='FD5D3656-E705-4BDC-A6D2-6ED3FB1CD53D'>
                <File Id='ZincPm' Name='Zinc.pm' DiskId='1' src='buildperl\blib\lib\Tk\Zinc.pm' />
              </Component>
              <Directory Id='ActivePerlSiteLibTkZinc' Name='Zinc'>
                <Component Id='PerlLib2' Guid='C79304DC-D841-4950-A822-077521687155'>
                  <File Id='DebugPm' Name='Debug.pm' DiskId='1' src='buildperl\blib\lib\Tk\Zinc\Debug.pm' />
                  <File Id='GraphicsPm' Name='Graphics.pm' DiskId='1' src='buildperl\blib\lib\Tk\Zinc\Graphics.pm' />
                  <File Id='GraphicsPod' Name='Graphics.pod' DiskId='1' src='buildperl\blib\lib\Tk\Zinc\Graphics.pod' />
                  <File Id='LogoPm' Name='Logo.pm' DiskId='1' src='buildperl\blib\lib\Tk\Zinc\Logo.pm' />
                  <File Id='TextPm' Name='Text.pm' DiskId='1' src='buildperl\blib\lib\Tk\Zinc\Text.pm' />
                  <File Id='TracePm' Name='Trace.pm' DiskId='1' src='buildperl\blib\lib\Tk\Zinc\Trace.pm' />
                  <File Id='TraceErrorsPm' Name='TraceErr.pl' LongName='TraceErrors.pm'
                    DiskId='1' src='buildperl\blib\lib\Tk\Zinc\TraceErrors.pm' />
                  <File Id='TraceUtilsPm' Name='TraceUtl.pm' LongName='TraceUtils.pm'
                    DiskId='1' src='buildperl\blib\lib\Tk\Zinc\TraceUtils.pm' />
                </Component>
              </Directory>
              <Directory Id='ActivePerlSiteLibTkDemos' Name='demos'>
                <Directory Id='ActivePerlSiteLibTkDemosContrib' Name='zinccont' LongName='zinc_contrib_lib'>
                  <Component Id='PerlDemosContrib' Guid='E90F7FDD-5A0D-4CF1-88E4-43C344E2C235'>
                    <File Id='ContribReadme' Name='README' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_contrib_lib\README' />
                    <File Id='TRWheel' Name='trwheel.pl' LongName='TripleRotatingWheel.pl'
                      DiskId='1' src='buildperl\blib\lib\Tk\demos\zinc_contrib_lib\TripleRotatingWheel.pl' />
                  </Component>
                </Directory>
                <Directory Id='ActivePerlSiteLibTkDemosData' Name='zincdata' LongName='zinc_data'>
                  <Component Id='PerlDemosData' Guid='E90F7FDD-5A0D-4CF1-88E4-43C344E2C235'>
                    <File Id='BTexGif' Name='btex.gif' LongName='background_texture.gif' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\background_texture.gif' />
                    <File Id='PerlPaperGif' Name='paper.gif' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\paper.gif' />
                    <File Id='PapergGif' Name='paperg.gif' LongName='paper-grey.gif' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\paper-grey.gif' />
                    <File Id='Paperg1Gif' Name='paperg1.gif' LongName='paper-grey1.gif' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\paper-grey1.gif' />
                    <File Id='STex' Name='stex.gif' LongName='stripped_texture.gif' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\stripped_texture.gif' />
                    <File Id='VidOrly' Name='vidorly' LongName='videomap_orly' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\videomap_orly' />
                    <File Id='VidParis' Name='vidparis' LongName='videomap_paris-w_90_2' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\videomap_paris-w_90_2' />
                    <File Id='Zinc2Gif' Name='zinc.gif' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\zinc.gif' />
                    <File Id='ZincAGif' Name='zinca.gif' LongName='zinc_anti.gif' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_data\zinc_anti.gif' />
                  </Component>
                </Directory>
                <Directory Id='ActivePerlSiteLibTkDemosLib' Name='zinc_lib'>
                  <Component Id='PerlDemosScripts' Guid='17C6461E-1589-4025-9878-D246DBD24ED5'>
                    <File Id='AllOptPl' Name='allopt.pl' LongName='all_options.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\all_options.pl' />
                    <File Id='AtomGrpPl' Name='atomgrp.pl' LongName='atomic-groups.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\atomic-groups.pl' />
                    <File Id='ClippingPl' Name='clipping.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\clipping.pl' />
                    <File Id='ColorCircPl' Name='colorc.pl' LongName='color-circular.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\color-circular.pl' />
                    <File Id='ColorPathPl' Name='colorp.pl' LongName='color-path-and-conic.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\color-path-and-conic.pl' />
                    <File Id='ColorXPl' Name='color-x.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\color-x.pl' />
                    <File Id='ColorYPl' Name='color-y.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\color-y.pl' />
                    <File Id='ContoursPl' Name='contours.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\contours.pl' />
                    <File Id='CounterPl' Name='counter.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\counter.pl' />
                    <File Id='CurveBezierPl' Name='curveb.pl' LongName='curve_bezier.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\curve_bezier.pl' />
                    <File Id='FillRulePl' Name='fillrule.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\fillrule.pl' />
                    <File Id='StripsGroupsPl' Name='gatcstrp.pl' LongName='groups_in_ATC_strips.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\groups_in_ATC_strips.pl' />
                    <File Id='GroupsPriorityPl' Name='grppri.pl' LongName='groups_priority.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\groups_priority.pl' />
                    <File Id='IconZoomResizePl' Name='iconzr.pl' LongName='icon_zoom_resize.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\icon_zoom_resize.pl' />
                    <File Id='ItemsPl' Name='items.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\items.pl' />
                    <File Id='LabelFormatPl' Name='lblformt.pl' DiskId='1' LongName='labelformat.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\labelformat.pl' />
                    <File Id='linesPl' Name='lines.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\lines.pl' />
                    <File Id='MapInfoPl' Name='mapinfo.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\mapinfo.pl' />
                    <File Id='MagicLensPl' Name='magiclns.pl' DiskId='1' LongName='MagicLens.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\MagicLens.pl' />
                    <File Id='PathTagsPl' Name='pathtags.pl' DiskId='1' LongName='path_tags.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\path_tags.pl' />
                    <File Id='RotationPl' Name='rotation.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\rotation.pl' />
                    <File Id='InteractionPl' Name='smplintr.pl' DiskId='1' LongName='simple_interaction_track.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\simple_interaction_track.pl' />
                    <File Id='SimpleRadarPl' Name='smplradr.pl' DiskId='1' LongName='simpleradar.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\simpleradar.pl' />
                    <File Id='TestGraphicsPl' Name='tstgraph.pl' DiskId='1' LongName='testGraphics.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\testGraphics.pl' />
                    <File Id='TextInputPl' Name='txtinput.pl' DiskId='1' LongName='textInput.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\textInput.pl' />
                    <File Id='TigerPl' Name='tiger.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\tiger.pl' />
                    <File Id='TkZincLogoPl' Name='tkznlogo.pl' DiskId='1' LongName='tkZincLogo.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\tkZincLogo.pl' />
                    <File Id='TransformsPl' Name='transfo.pl' DiskId='1' LongName='transforms.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\transforms.pl' />
                    <File Id='TranslationPl' Name='transltn.pl' DiskId='1' LongName='translation.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\translation.pl' />
                    <File Id='TrianglesPl' Name='triangle.pl' DiskId='1' LongName='triangles.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\triangles.pl' />
                    <File Id='WheelFortunePl' Name='wheelfor.pl' DiskId='1' LongName='WheelOfFortune.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\WheelOfFortune.pl' />
                    <File Id='WinContoursPl' Name='wincont.pl' DiskId='1' LongName='window-contours.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\window-contours.pl' />
                    <File Id='ZetrisPl' Name='zetris.pl' DiskId='1' LongName='Zetris.pl'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\Zetris.pl' />
                    <File Id='ZoomPl' Name='zoom.pl' DiskId='1'
                      src='buildperl\blib\lib\Tk\demos\zinc_lib\zoom.pl' />
                  </Component>
                </Directory>
                <Directory Id='ActivePerlSiteLibTkDemosPm' Name='zinc_pm'>
                  <Component Id='PerlDemosModules' Guid='1C7D6E9D-E841-48F9-896A-274C43C6204F'>
                    <File Id='SRadCtrl' Name='sradctrl.pm' LongName='SimpleRadarControls.pm'
                      DiskId='1' src='buildperl\blib\lib\Tk\demos\zinc_pm\SimpleRadarControls.pm' />
                  </Component>
                </Directory>
              </Directory>
            </Directory>
          </Directory>
        </Directory>
      </Directory>

      <Directory Id='ACTIVE_PYTHON_DIR' Name='Python'>
        <Directory Id='ActivePythonTcl' Name='tcl'>
          <Directory Id='ActivePythonTclTkzinc' Name='Tkzinc@MAJOR_VERSION@@MINOR_VERSION@' LongName='Tkzinc@MAJOR_VERSION@.@MINOR_VERSION@.@PATCHLEVEL@'>
            <Component Id='PythonTcl' Guid='B1CF5C82-CE79-4EE2-91BB-49E3D808E6B9'>
              <File Id='TkzincPythonDll' Name='Tkzinc@MAJOR_VERSION@@MINOR_VERSION@.dll' LongName='Tkzinc@MAJOR_VERSION@@MINOR_VERSION@@PATCHLEVEL@.dll'
                DiskId='1' src='buildtcl/Tkzinc@MAJOR_VERSION@@MINOR_VERSION@@PATCHLEVEL@.dll' Vital='yes' />
              <File Id='PythonpkgIndexTcl' Name='pkgIndex.tcl' DiskId='1' src='buildtcl/pkgIndex.tcl' Vital='yes' />
              <File Id='PythonZincGraphicsTcl' Name='znGraph.tcl' LongName='zincGraphics.tcl' DiskId='1'
                src='buildtcl\zincGraphics.tcl' />
              <File Id='PythonZincTextTcl' Name='znText.tcl' LongName='zincText.tcl' DiskId='1' src='buildtcl\zincText.tcl' />
              <File Id='PythonZincLogoTcl' Name='znLogo.tcl' LongName='zincLogo.tcl' DiskId='1' src='buildtcl\zincLogo.tcl' />
            </Component>
          </Directory>
        </Directory>
        <Directory Id='PythonTclLib' Name='Lib'>
	        <Directory Id='PythonTclLibZinc' Name='Zinc'>
            <Component Id='PythonGlue' Guid='E2A2296C-0C53-40AB-9118-85706B5C2C42'>
	            <File Id='ZincPy' Name='Zinc.py' DiskId='1' src='..\Python\library\Zinc.py' Vital='yes' />
	            <File Id='ZincPkg' Name='__init__.py' DiskId='1' src='..\Python\library\__init__.py' Vital='yes' />
	            <File Id='GraphicsPy' Name='graphics.py' DiskId='1' src='..\Python\library\graphics.py' Vital='yes' />
	            <File Id='GeometryPy' Name='geometry.py' DiskId='1' src='..\Python\library\geometry.py' Vital='yes' />
	            <File Id='PictorialPy' Name='pictorl.py' LongName='pictorial.py' DiskId='1' src='..\Python\library\pictorial.py' Vital='yes' />
            </Component>
	        </Directory>
	      </Directory>
        <Directory Id='PythonZincDemo' Name='ZincDemo'>
          <Component Id='PythonDemo' Guid='0BA2AABC-005C-4FFE-88A2-881F624E9C63'>
	          <File Id='TestGraphicsPy' Name='testGrph.py' LongName='testGraphics.py' DiskId='1' src='..\Python\demos\testGraphics.py' Vital='yes' />
	          <File Id='PaperGif' Name='paper.gif' DiskId='1' src='..\Python\demos\paper.gif' Vital='yes' />
          </Component>
	      </Directory>
      </Directory>
    </Directory>
    
    <!-- Icon used in the installer UI -->

    <Binary Id="Up" src="InstallerIcons\Up.ico" />
    <Binary Id="New" src="InstallerIcons\New.ico" />
    <Binary Id="custicon" src="InstallerIcons\Custom.ico" />
    <Binary Id="repairic" src="InstallerIcons\Repair.ico" />
    <Binary Id="exclamic" src="InstallerIcons\Exclam.ico" />
    <Binary Id="removico" src="InstallerIcons\Remove.ico" />
    <Binary Id="completi" src="InstallerIcons\Complete.ico" />
    <Binary Id="insticon" src="InstallerIcons\Typical.ico" />
    <Binary Id="info" src="InstallerIcons\Info.ico" />
    <Binary Id="bannrbmp" src="InstallerIcons\Banner.bmp" />
    <Binary Id="dlgbmp" src="InstallerIcons\Dialog.bmp" />

    <!-- Properties -->

    <Property Id="ALLUSERS">2</Property>
    <Property Id="ROOTDRIVE"><![CDATA[C:\]]></Property>
    <Property Id="ButtonText_No">&amp;No</Property>
    <Property Id="ButtonText_Install">&amp;Install</Property>
    <Property Id="Setup">Setup</Property>
    <Property Id="ButtonText_Browse">Br&amp;owse</Property>
    <Property Id="CustomSetupIcon">custicon</Property>
    <Property Id="ButtonText_Next">&amp;Next &gt;</Property>
    <Property Id="ButtonText_Back">&lt; &amp;Back</Property>
    <Property Id="InstallMode">Typical</Property>
    <Property Id="Progress2">installs</Property>
    <Property Id="IAgree">No</Property>
    <Property Id="Wizard">Setup Wizard</Property>
    <Property Id="RemoveIcon">removico</Property>
    <Property Id="ExclamationIcon">exclamic</Property>
    <Property Id="ProductID">none</Property>
    <Property Id="ButtonText_Reset">&amp;Reset</Property>
    <Property Id="ButtonText_Remove">&amp;Remove</Property>
    <Property Id="CompleteSetupIcon">completi</Property>
    <Property Id="ButtonText_Yes">&amp;Yes</Property>
    <Property Id="ButtonText_Exit">&amp;Exit</Property>
    <Property Id="ButtonText_Return">&amp;Return</Property>
    <Property Id="DialogBitmap">dlgbmp</Property>
    <Property Id="DlgTitleFont">{&amp;DlgFontBold8}</Property>
    <Property Id="ButtonText_Ignore">&amp;Ignore</Property>
    <Property Id="RepairIcon">repairic</Property>
    <Property Id="ButtonText_Resume">&amp;Resume</Property>
    <Property Id="InstallerIcon">insticon</Property>
    <Property Id="ButtonText_Finish">&amp;Finish</Property>
    <Property Id="PROMPTROLLBACKCOST">P</Property>
    <Property Id="PIDTemplate"><![CDATA[12345<#######>@@@@@]]></Property>
    <Property Id="Progress1">Installing</Property>
    <Property Id="ButtonText_Cancel">Cancel</Property>
    <Property Id="INSTALLLEVEL">3</Property>
    <Property Id="InfoIcon">info</Property>
    <Property Id="ButtonText_Repair">&amp;Repair</Property>
    <Property Id="ButtonText_Retry">&amp;Retry</Property>
    <Property Id="BannerBitmap">bannrbmp</Property>
    <Property Id="ButtonText_OK">OK</Property>

    <!-- The "standard" installer UI starts here. Customized code is commented as such. -->

    <UI>
      <Property Id="DefaultUIFont">DlgFont8</Property>
      <Property Id="ErrorDialog">ErrorDlg</Property>

      <Dialog Id="AdminWelcomeDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Property="InstallMode" Value="Server Image">1</Publish>
          <Publish Event="NewDialog" Value="AdminRegistrationDlg">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="30" Transparent="yes" NoPrefix="yes">
          <Text>The [Wizard] will create a server image of [ProductName] [ProductVersion], at a specified network location. Click Next to continue or Cancel to exit the [Wizard].</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}Welcome to the [ProductName] [ProductVersion] [Wizard]</Text>
        </Control>
      </Dialog>

      <Dialog Id="PrepareDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" Modeless="yes">
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="ActionText" Type="Text" X="135" Y="100" Width="220" Height="20" Transparent="yes" NoPrefix="yes">
          <Subscribe Event="ActionText" Attribute="Text" />
        </Control>
        <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Please wait while the [Wizard] prepares to guide you through the installation.</Text>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" TabSkip="yes" Text="[ButtonText_Next]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" TabSkip="yes" Text="[ButtonText_Back]" />
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}Welcome to the [ProductName] [ProductVersion] [Wizard]</Text>
        </Control>
        <Control Id="ActionData" Type="Text" X="135" Y="125" Width="220" Height="30" Transparent="yes" NoPrefix="yes">
          <Subscribe Event="ActionData" Attribute="Text" />
        </Control>
      </Dialog>

      <Dialog Id="ProgressDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" Modeless="yes">
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Next]" />
        <Control Id="ActionText" Type="Text" X="70" Y="100" Width="265" Height="10">
          <Subscribe Event="ActionText" Attribute="Text" />
        </Control>
        <Control Id="Text" Type="Text" X="35" Y="65" Width="300" Height="20">
          <Text>Please wait while the [Wizard] [Progress2] [ProductName] [ProductVersion]. This may take several minutes.</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="20" Y="15" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont][Progress1] [ProductName] [ProductVersion]</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="ProgressBar" Type="ProgressBar" X="35" Y="115" Width="300" Height="10" ProgressBlocks="yes" Text="Progress done">
          <Subscribe Event="SetProgress" Attribute="Progress" />
        </Control>
        <Control Id="StatusLabel" Type="Text" X="35" Y="100" Width="35" Height="10" Text="Status:" />
      </Dialog>

      <Dialog Id="UserExit" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Finish]">
          <Publish Event="EndDialog" Value="Exit">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Cancel]" />
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}[ProductName] [ProductVersion] [Wizard] was interrupted</Text>
        </Control>
        <Control Id="Description1" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes">
          <Text>[ProductName] [ProductVersion] setup was interrupted. Your system has not been modified. To install this program at a later time, please run the installation again.</Text>
        </Control>
        <Control Id="Description2" Type="Text" X="135" Y="115" Width="220" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Click the Finish button to exit the [Wizard].</Text>
        </Control>
      </Dialog>

      <Dialog Id="FatalError" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Finish]">
          <Publish Event="EndDialog" Value="Exit">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Cancel]" />
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}[ProductName] [ProductVersion] [Wizard] ended prematurely</Text>
        </Control>
        <Control Id="Description1" Type="Text" X="135" Y="70" Width="220" Height="40" Transparent="yes" NoPrefix="yes">
          <Text>[ProductName] [ProductVersion] setup ended prematurely because of an error. Your system has not been modified. To install this program at a later time, please run the installation again.</Text>
        </Control>
        <Control Id="Description2" Type="Text" X="135" Y="115" Width="220" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Click the Finish button to exit the [Wizard].</Text>
        </Control>
      </Dialog>

      <Dialog Id="ExitDialog" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Finish" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Finish]">
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Cancel]" />
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Click the Finish button to exit the [Wizard].</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}Completing the [ProductName] [ProductVersion] [Wizard]</Text>
        </Control>
      </Dialog>

      <Dialog Id="AdminBrowseDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="17" Property="TARGETDIR" />
        <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_OK]">
          <Publish Event="SetTargetPath" Value="TARGETDIR">1</Publish>
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="Reset" Value="0">1</Publish>
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="ComboLabel" Type="Text" X="25" Y="58" Width="44" Height="10" TabSkip="no" Text="&amp;Look in:" />
        <Control Id="DirectoryCombo" Type="DirectoryCombo" X="70" Y="55" Width="220" Height="80" Property="TARGETDIR" Removable="yes" Fixed="yes" Remote="yes">
          <Subscribe Event="IgnoreChange" Attribute="IgnoreChange" />
        </Control>
        <Control Id="Up" Type="PushButton" X="298" Y="55" Width="19" Height="19" ToolTip="Up One Level" Icon="yes" FixedSize="yes" IconSize="16" Text="Up">
          <Publish Event="DirectoryListUp" Value="0">1</Publish>
        </Control>
        <Control Id="NewFolder" Type="PushButton" X="325" Y="55" Width="19" Height="19" ToolTip="Create A New Folder" Icon="yes" FixedSize="yes" IconSize="16" Text="New">
          <Publish Event="DirectoryListNew" Value="0">1</Publish>
        </Control>
        <Control Id="DirectoryList" Type="DirectoryList" X="25" Y="83" Width="320" Height="110" Property="TARGETDIR" Sunken="yes" TabSkip="no" />
        <Control Id="PathLabel" Type="Text" X="25" Y="205" Width="59" Height="10" TabSkip="no" Text="&amp;Folder name:" />
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Browse to the destination folder</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Change current destination folder</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="AdminInstallPointDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Text" Type="Text" X="25" Y="80" Width="320" Height="10" TabSkip="no">
          <Text>&amp;Enter a new network location or click Browse to browse to one.</Text>
        </Control>
        <Control Id="PathEdit" Type="PathEdit" X="25" Y="93" Width="320" Height="18" Property="TARGETDIR" />
        <Control Id="Browse" Type="PushButton" X="289" Y="119" Width="56" Height="17" Text="[ButtonText_Browse]">
          <Publish Event="SpawnDialog" Value="AdminBrowseDlg">1</Publish>
        </Control>
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="AdminRegistrationDlg">1</Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Event="SetTargetPath" Value="TARGETDIR">1</Publish>
          <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Please specify a network location for the server image of [ProductName] [ProductVersion] product</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Network Location</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="AdminRegistrationDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="OrganizationLabel" Type="Text" X="45" Y="71" Width="285" Height="30" TabSkip="no">
          <Text>&amp;Please enter the name of your organization in the box below. This will be used as default company name for subsequent installations of [ProductName] [ProductVersion]:</Text>
        </Control>
        <Control Id="OrganizationEdit" Type="Edit" X="45" Y="105" Width="220" Height="18" Property="COMPANYNAME" Text="{80}" />
        <Control Id="CDKeyLabel" Type="Text" X="45" Y="130" Width="50" Height="10" TabSkip="no">
          <Text>CD &amp;Key:</Text>
        </Control>
        <Control Id="CDKeyEdit" Type="MaskedEdit" X="45" Y="143" Width="250" Height="16" Property="PIDKEY" Text="[PIDTemplate]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Image="yes" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="AdminWelcomeDlg">1</Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Event="ValidateProductID" Value="0">0</Publish>
          <Publish Event="NewDialog" Value="AdminInstallPointDlg">ProductID</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Please enter your company information</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Company Information</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="BrowseDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="18" Property="_BrowseProperty" Indirect="yes" />
        <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_OK]">
          <Publish Event="SetTargetPath" Value="[_BrowseProperty]">1</Publish>
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="Reset" Value="0">1</Publish>
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="ComboLabel" Type="Text" X="25" Y="58" Width="44" Height="10" TabSkip="no" Text="&amp;Look in:" />
        <Control Id="DirectoryCombo" Type="DirectoryCombo" X="70" Y="55" Width="220" Height="80" Property="_BrowseProperty" Indirect="yes" Fixed="yes" Remote="yes">
          <Subscribe Event="IgnoreChange" Attribute="IgnoreChange" />
        </Control>
        <Control Id="Up" Type="PushButton" X="298" Y="55" Width="19" Height="19" ToolTip="Up One Level" Icon="yes" FixedSize="yes" IconSize="16" Text="Up">
          <Publish Event="DirectoryListUp" Value="0">1</Publish>
        </Control>
        <Control Id="NewFolder" Type="PushButton" X="325" Y="55" Width="19" Height="19" ToolTip="Create A New Folder" Icon="yes" FixedSize="yes" IconSize="16" Text="New">
          <Publish Event="DirectoryListNew" Value="0">1</Publish>
        </Control>
        <Control Id="DirectoryList" Type="DirectoryList" X="25" Y="83" Width="320" Height="110" Property="_BrowseProperty" Sunken="yes" Indirect="yes" TabSkip="no" />
        <Control Id="PathLabel" Type="Text" X="25" Y="205" Width="59" Height="10" TabSkip="no" Text="&amp;Folder name:" />
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Browse to the destination folder</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Change current destination folder</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="CancelDlg" Width="260" Height="85" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="No" Type="PushButton" X="132" Y="57" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_No]">
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="Yes" Type="PushButton" X="72" Y="57" Width="56" Height="17" Text="[ButtonText_Yes]">
          <Publish Event="EndDialog" Value="Exit">1</Publish>
        </Control>
        <Control Id="Text" Type="Text" X="48" Y="15" Width="194" Height="30">
          <Text>Are you sure you want to cancel [ProductName] [ProductVersion] installation?</Text>
        </Control>
        <Control Id="Icon" Type="Icon" X="15" Y="15" Width="24" Height="24" ToolTip="Information icon" FixedSize="yes" IconSize="32" Text="[InfoIcon]" />
      </Dialog>

      <Dialog Id="CustomizeDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes" TrackDiskSpace="yes">
        <Control Id="Tree" Type="SelectionTree" X="25" Y="85" Width="175" Height="95" Property="_BrowseProperty" Sunken="yes" TabSkip="no" Text="Tree of selections" />
        <Control Id="Browse" Type="PushButton" X="304" Y="200" Width="56" Height="17" Text="[ButtonText_Browse]">
          <Publish Event="SelectionBrowse" Value="BrowseDlg">1</Publish>
          <!-- <Condition Action="hide">Installed</Condition> -->
          <Condition Action="enable">1</Condition>
        </Control>
        <Control Id="Reset" Type="PushButton" X="42" Y="243" Width="56" Height="17" Text="[ButtonText_Reset]">
          <Publish Event="Reset" Value="0">1</Publish>
          <Subscribe Event="SelectionNoItems" Attribute="Enabled" />
        </Control>
        <Control Id="DiskCost" Type="PushButton" X="111" Y="243" Width="56" Height="17">
          <Text>Disk &amp;Usage</Text>
          <Publish Event="SpawnDialog" Value="DiskCostDlg">1</Publish>
          <Subscribe Event="SelectionNoItems" Attribute="Enabled" />
        </Control>
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="MaintenanceTypeDlg"><![CDATA[InstallMode = "Change"]]></Publish>
          <Publish Event="NewDialog" Value="SetupTypeDlg"><![CDATA[InstallMode = "Custom"]]></Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
          <Subscribe Event="SelectionNoItems" Attribute="Enabled" />
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Select the way you want features to be installed.</Text>
        </Control>
        <Control Id="Text" Type="Text" X="25" Y="55" Width="320" Height="20">
          <Text>Click on the icons in the tree below to change the way features will be installed.</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Custom Setup</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="Box" Type="GroupBox" X="210" Y="81" Width="140" Height="98" />
        <Control Id="ItemDescription" Type="Text" X="215" Y="90" Width="131" Height="30">
          <Text>Multiline description of the currently selected item.</Text>
          <Subscribe Event="SelectionDescription" Attribute="Text" />
        </Control>
        <Control Id="ItemSize" Type="Text" X="215" Y="130" Width="131" Height="45">
          <Text>The size of the currently selected item.</Text>
          <Subscribe Event="SelectionSize" Attribute="Text" />
        </Control>
        <Control Id="Location" Type="Text" X="75" Y="200" Width="215" Height="20">
          <Text>&lt;The selection's path&gt;</Text>
          <Subscribe Event="SelectionPath" Attribute="Text" />
          <Subscribe Event="SelectionPathOn" Attribute="Visible" />
          <!-- <Condition Action="hide">Installed</Condition> -->
        </Control>
        <Control Id="LocationLabel" Type="Text" X="25" Y="200" Width="50" Height="10" Text="Location:">
          <Subscribe Event="SelectionPathOn" Attribute="Visible" />
          <!-- <Condition Action="hide">Installed</Condition> -->
        </Control>
      </Dialog>

      <Dialog Id="DiskCostDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_OK]">
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="20" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>The disk space required for the installation of the selected features.</Text>
        </Control>
        <Control Id="Text" Type="Text" X="20" Y="53" Width="330" Height="40">
          <Text>The highlighted volumes (if any) do not have enough disk space available for the currently selected features. You can either remove some files from the highlighted volumes, or choose to install less features onto local drive(s), or select different destination drive(s).</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Disk Space Requirements</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="VolumeList" Type="VolumeCostList" X="20" Y="100" Width="330" Height="120" Sunken="yes" Fixed="yes" Remote="yes">
          <Text>{120}{70}{70}{70}{70}</Text>
        </Control>
      </Dialog>

      <Dialog Id="ErrorDlg" Width="270" Height="105" Title="Installer Information" ErrorDialog="yes" NoMinimize="yes">
        <Control Id="ErrorText" Type="Text" X="48" Y="15" Width="205" Height="60" TabSkip="no" Text="Information text" />
        <Control Id="Y" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Yes]">
          <Publish Event="EndDialog" Value="ErrorYes">1</Publish>
        </Control>
        <Control Id="A" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Cancel]">
          <Publish Event="EndDialog" Value="ErrorAbort">1</Publish>
        </Control>
        <Control Id="C" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Cancel]">
          <Publish Event="EndDialog" Value="ErrorCancel">1</Publish>
        </Control>
        <Control Id="ErrorIcon" Type="Icon" X="15" Y="15" Width="24" Height="24" ToolTip="Information icon" FixedSize="yes" IconSize="32" Text="[InfoIcon]" />
        <Control Id="I" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Ignore]">
          <Publish Event="EndDialog" Value="ErrorIgnore">1</Publish>
        </Control>
        <Control Id="N" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_No]">
          <Publish Event="EndDialog" Value="ErrorNo">1</Publish>
        </Control>
        <Control Id="O" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_OK]">
          <Publish Event="EndDialog" Value="ErrorOk">1</Publish>
        </Control>
        <Control Id="R" Type="PushButton" X="100" Y="80" Width="56" Height="17" TabSkip="yes" Text="[ButtonText_Retry]">
          <Publish Event="EndDialog" Value="ErrorRetry">1</Publish>
        </Control>
      </Dialog>

      <Dialog Id="FilesInUse" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes" KeepModeless="yes">
        <Control Id="Retry" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Retry]">
          <Publish Event="EndDialog" Value="Retry">1</Publish>
        </Control>
        <Control Id="Ignore" Type="PushButton" X="235" Y="243" Width="56" Height="17" Text="[ButtonText_Ignore]">
          <Publish Event="EndDialog" Value="Ignore">1</Publish>
        </Control>
        <Control Id="Exit" Type="PushButton" X="166" Y="243" Width="56" Height="17" Text="[ButtonText_Exit]">
          <Publish Event="EndDialog" Value="Exit">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="20" Y="23" Width="280" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Some files that need to be updated are currently in use.</Text>
        </Control>
        <Control Id="Text" Type="Text" X="20" Y="55" Width="330" Height="30">
          <Text>The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Files in Use</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="List" Type="ListBox" X="20" Y="87" Width="330" Height="130" Property="FileInUseProcess" Sunken="yes" TabSkip="yes" />
      </Dialog>

      <Dialog Id="LicenseAgreementDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] License Agreement" NoMinimize="yes">
        <Control Id="Buttons" Type="RadioButtonGroup" X="20" Y="187" Width="330" Height="40" Property="IAgree" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="WelcomeDlg">1</Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Event="NewDialog" Value="NotAvailDlg"><![CDATA[IAgree = "Yes" AND (NOT (ACTIVE_TCL_VERSION << RequiredTclVersion) OR (ACTIVE_PERL_VERSION < RequiredPerlVersion))]]></Publish>
          <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish>
          <Publish Event="NewDialog" Value="SetupTypeDlg"><![CDATA[IAgree = "Yes" AND (ACTIVE_TCL_VERSION << RequiredTclVersion) AND (ACTIVE_PERL_VERSION >= RequiredPerlVersion)]]></Publish>
          <Condition Action="disable"><![CDATA[IAgree <> "Yes"]]></Condition>
          <Condition Action="enable">IAgree = "Yes"</Condition>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="AgreementText" Type="ScrollableText" X="20" Y="60" Width="330" Height="120" Sunken="yes" TabSkip="no">
          <Text src="Copyright.rtf" />
        </Control>
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Please read the following license agreement carefully</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]End-User License Agreement</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>
      
      <!-- Just to tell the user that something will be missing and asking if it is ok to continue -->

      <Dialog Id="NotAvailDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="TclWarning" Type="Text" X="45" Y="100" Width="300" Height="20">
          <Text>Active Tcl not found or not at the right version: [ACTIVE_TCL_VERSION] ([RequiredTclVersion] or greater needed)</Text>
          <Condition Action="hide"><![CDATA[ACTIVE_TCL_VERSION << RequiredTclVersion]]></Condition>
        </Control>
        <Control Id="PerlWarning" Type="Text" X="45" Y="150" Width="300" Height="15">
          <Text>Active Perl not found or not at the right version: [ACTIVE_PERL_VERSION] ([RequiredPerlVersion] or greater needed)</Text>
          <Condition Action="hide"><![CDATA[ACTIVE_PERL_VERSION >= RequiredPerlVersion]]></Condition>
        </Control>
        <Control Id="PythonWarning" Type="Text" X="45" Y="125" Width="300" Height="20">
          <Text>Active Python not found</Text>
        </Control>
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Event="ValidateProductID" Value="0">0</Publish>
          <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish>
          <Publish Event="NewDialog" Value="SetupTypeDlg">ProductID</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Please enter your customer information</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Customer Information</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="MaintenanceTypeDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="ChangeLabel" Type="Text" X="105" Y="65" Width="100" Height="10" TabSkip="no">
          <Text>[DlgTitleFont]&amp;Modify</Text>
        </Control>
        <Control Id="ChangeButton" Type="PushButton" X="50" Y="65" Width="38" Height="38" ToolTip="Modify Installation" Default="yes" Icon="yes" FixedSize="yes" IconSize="32" Text="[CustomSetupIcon]">
          <Publish Property="InstallMode" Value="Change">1</Publish>
          <Publish Property="Progress1" Value="Changing">1</Publish>
          <Publish Property="Progress2" Value="changes">1</Publish>
          <Publish Event="NewDialog" Value="CustomizeDlg">1</Publish>
        </Control>
        <Control Id="RepairLabel" Type="Text" X="105" Y="114" Width="100" Height="10" TabSkip="no">
          <Text>[DlgTitleFont]Re&amp;pair</Text>
        </Control>
        <Control Id="RepairButton" Type="PushButton" X="50" Y="114" Width="38" Height="38" ToolTip="Repair Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[RepairIcon]">
          <Publish Property="InstallMode" Value="Repair">1</Publish>
          <Publish Property="Progress1" Value="Repairing">1</Publish>
          <Publish Property="Progress2" Value="repaires">1</Publish>
          <Publish Event="NewDialog" Value="VerifyRepairDlg">1</Publish>
        </Control>
        <Control Id="RemoveLabel" Type="Text" X="105" Y="163" Width="100" Height="10" TabSkip="no">
          <Text>[DlgTitleFont]&amp;Remove</Text>
        </Control>
        <Control Id="RemoveButton" Type="PushButton" X="50" Y="163" Width="38" Height="38" ToolTip="Remove Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[RemoveIcon]">
          <Publish Property="InstallMode" Value="Remove">1</Publish>
          <Publish Property="Progress1" Value="Removing">1</Publish>
          <Publish Property="Progress2" Value="removes">1</Publish>
          <Publish Event="NewDialog" Value="VerifyRemoveDlg">1</Publish>
        </Control>
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Next]" />
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Select the operation you wish to perform.</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="240" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Modify, Repair or Remove installation</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="ChangeText" Type="Text" X="105" Y="78" Width="230" Height="20">
          <Text>Allows users to change the way features are installed.</Text>
        </Control>
        <Control Id="RemoveText" Type="Text" X="105" Y="176" Width="230" Height="20">
          <Text>Removes [ProductName] [ProductVersion] from your computer.</Text>
        </Control>
        <Control Id="RepairText" Type="Text" X="105" Y="127" Width="230" Height="30">
          <Text>Repairs errors in the most recent installation state - fixes missing or corrupt files, shortcuts and registry entries.</Text>
        </Control>
      </Dialog>

      <Dialog Id="MaintenanceWelcomeDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish>
          <Publish Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>The [Wizard] will allow you to change the way [ProductName] [ProductVersion] features are installed on your computer or even to remove [ProductName] from your computer. Click Next to continue or Cancel to exit the [Wizard].</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}Welcome to the [ProductName] [ProductVersion] [Wizard]</Text>
        </Control>
      </Dialog>

      <Dialog Id="OutOfDiskDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_OK]">
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="20" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Disk space required for the installation exceeds available disk space.</Text>
        </Control>
        <Control Id="Text" Type="Text" X="20" Y="53" Width="330" Height="40">
          <Text>The highlighted volumes do not have enough disk space available for the currently selected features. You can either remove some files from the highlighted volumes, or choose to install less features onto local drive(s), or select different destination drive(s).</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Out of Disk Space</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="VolumeList" Type="VolumeCostList" X="20" Y="100" Width="330" Height="120" Sunken="yes" Fixed="yes" Remote="yes">
          <Text>{120}{70}{70}{70}{70}</Text>
        </Control>
      </Dialog>

      <Dialog Id="OutOfRbDiskDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="No" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_No]">
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="Yes" Type="PushButton" X="240" Y="243" Width="56" Height="17" Text="[ButtonText_Yes]">
          <Publish Event="EnableRollback" Value="False">1</Publish>
          <Publish Event="EndDialog" Value="Return">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="20" Y="20" Width="280" Height="20" Transparent="yes" NoPrefix="yes">
          <Text>Disk space required for the installation exceeds available disk space.</Text>
        </Control>
        <Control Id="Text" Type="Text" X="20" Y="53" Width="330" Height="40">
          <Text>The highlighted volumes do not have enough disk space available for the currently selected features. You can either remove some files from the highlighted volumes, or choose to install less features onto local drive(s), or select different destination drive(s).</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Out of Disk Space</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="VolumeList" Type="VolumeCostList" X="20" Y="140" Width="330" Height="80" Sunken="yes" Fixed="yes" Remote="yes" ShowRollbackCost="yes">
          <Text>{120}{70}{70}{70}{70}</Text>
        </Control>
        <Control Id="Text2" Type="Text" X="20" Y="94" Width="330" Height="40">
          <Text>Alternatively, you may choose to disable the installer's rollback functionality. This allows the installer to restore your computer's original state should the installation be interrupted in any way. Click Yes if you wish to take the risk to disable rollback.</Text>
        </Control>
      </Dialog>

      <Dialog Id="ResumeDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Install" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Install]">
          <Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish>
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)]]></Publish>
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="EnableRollback" Value="False"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfDiskDlg"><![CDATA[(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")]]></Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="30" Transparent="yes" NoPrefix="yes">
          <Text>The [Wizard] will complete the installation of [ProductName] [ProductVersion] on your computer. Click Install to continue or Cancel to exit the [Wizard].</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}Resuming the [ProductName] [ProductVersion] [Wizard]</Text>
        </Control>
      </Dialog>

      <Dialog Id="SetupTypeDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="TypicalLabel" Type="Text" X="105" Y="65" Width="100" Height="10" TabSkip="no">
          <Text>[DlgTitleFont]&amp;Typical</Text>
        </Control>
        <Control Id="TypicalButton" Type="PushButton" X="50" Y="65" Width="38" Height="38" ToolTip="Typical Installation" Default="yes" Icon="yes" FixedSize="yes" IconSize="32" Text="[InstallerIcon]">
          <Publish Property="InstallMode" Value="Typical">1</Publish>
          <Publish Event="SetInstallLevel" Value="3">1</Publish>
          <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
        </Control>
        <Control Id="CustomLabel" Type="Text" X="105" Y="118" Width="100" Height="10" TabSkip="no">
          <Text>[DlgTitleFont]C&amp;ustom</Text>
        </Control>
        <Control Id="CustomButton" Type="PushButton" X="50" Y="118" Width="38" Height="38" ToolTip="Custom Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[CustomSetupIcon]">
          <Publish Property="InstallMode" Value="Custom">1</Publish>
          <Publish Event="NewDialog" Value="CustomizeDlg">1</Publish>
        </Control>
        <Control Id="CompleteLabel" Type="Text" X="105" Y="171" Width="100" Height="10" TabSkip="no">
          <Text>[DlgTitleFont]C&amp;omplete</Text>
        </Control>
        <Control Id="CompleteButton" Type="PushButton" X="50" Y="171" Width="38" Height="38" ToolTip="Complete Installation" Icon="yes" FixedSize="yes" IconSize="32" Text="[CompleteSetupIcon]">
          <Publish Property="InstallMode" Value="Complete">1</Publish>
          <Publish Event="SetInstallLevel" Value="1000">1</Publish>
          <Publish Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
        </Control>
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
        </Control>
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Next]" />
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>Choose the setup type that best suits your needs</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Choose Setup Type</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
        <Control Id="CompleteText" Type="Text" X="105" Y="184" Width="230" Height="20">
          <Text>All program features will be installed. (Requires most disk space)</Text>
        </Control>
        <Control Id="CustomText" Type="Text" X="105" Y="131" Width="230" Height="30">
          <Text>Allows users to choose which program features will be installed and where they will be installed. Recommended for advanced users.</Text>
        </Control>
        <Control Id="TypicalText" Type="Text" X="105" Y="78" Width="230" Height="20">
          <Text>Installs the most common program features. Recommended for most users.</Text>
        </Control>
      </Dialog>

      <Dialog Id="VerifyReadyDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes" TrackDiskSpace="yes">
        <Control Id="Install" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Install]">
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)]]></Publish>
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="EnableRollback" Value="False"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfDiskDlg"><![CDATA[(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")]]></Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="AdminInstallPointDlg"><![CDATA[InstallMode = "Server Image"]]></Publish>
          <Publish Event="NewDialog" Value="CustomizeDlg"><![CDATA[InstallMode = "Custom" OR InstallMode = "Change"]]></Publish>
          <Publish Event="NewDialog" Value="MaintenanceTypeDlg"><![CDATA[InstallMode = "Repair"]]></Publish>
          <Publish Event="NewDialog" Value="SetupTypeDlg"><![CDATA[InstallMode = "Typical" OR InstallMode = "Complete"]]></Publish>
        </Control>
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>The [Wizard] is ready to begin the [InstallMode] installation</Text>
        </Control>
        <Control Id="Text" Type="Text" X="25" Y="70" Width="320" Height="20">
          <Text>Click Install to begin the installation. If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Ready to Install</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="VerifyRemoveDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes" TrackDiskSpace="yes">
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
        </Control>
        <Control Id="Remove" Type="PushButton" X="236" Y="243" Width="56" Height="17" Text="[ButtonText_Remove]">
          <Publish Event="Remove" Value="All"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)]]></Publish>
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="EnableRollback" Value="False"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfDiskDlg"><![CDATA[(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")]]></Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>You have chosen to remove the program from your computer.</Text>
        </Control>
        <Control Id="Text" Type="Text" X="25" Y="70" Width="320" Height="30">
          <Text>Click Remove to remove [ProductName] [ProductVersion] from your computer. If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Remove [ProductName] [ProductVersion]</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="VerifyRepairDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes" TrackDiskSpace="yes">
        <Control Id="Repair" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Repair]">
          <Publish Event="ReinstallMode" Value="ecmus"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
          <Publish Event="Reinstall" Value="All"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace <> 1]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfRbDiskDlg"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND (PROMPTROLLBACKCOST="P" OR NOT PROMPTROLLBACKCOST)]]></Publish>
          <Publish Event="EndDialog" Value="Return"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="EnableRollback" Value="False"><![CDATA[OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 0 AND PROMPTROLLBACKCOST="D"]]></Publish>
          <Publish Event="SpawnDialog" Value="OutOfDiskDlg"><![CDATA[(OutOfDiskSpace = 1 AND OutOfNoRbDiskSpace = 1) OR (OutOfDiskSpace = 1 AND PROMPTROLLBACKCOST="F")]]></Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="[ButtonText_Back]">
          <Publish Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
        </Control>
        <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>The [Wizard] is ready to begin the repair of [ProductName] [ProductVersion].</Text>
        </Control>
        <Control Id="Text" Type="Text" X="25" Y="70" Width="320" Height="30">
          <Text>Click Repair to repair the installation of [ProductName] [ProductVersion]. If you want to review or change any of your installation settings, click Back. Click Cancel to exit the wizard.</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes">
          <Text>[DlgTitleFont]Repair [ProductName] [ProductVersion]</Text>
        </Control>
        <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
      </Dialog>

      <Dialog Id="WaitForCostingDlg" Width="260" Height="85" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Return" Type="PushButton" X="102" Y="57" Width="56" Height="17" Default="yes" Cancel="yes" Text="[ButtonText_Return]">
          <Publish Event="EndDialog" Value="Exit">1</Publish>
        </Control>
        <Control Id="Text" Type="Text" X="48" Y="15" Width="194" Height="30">
          <Text>Please wait while the installer finishes determining your disk space requirements.</Text>
        </Control>
        <Control Id="Icon" Type="Icon" X="15" Y="15" Width="24" Height="24" ToolTip="Exclamation icon" FixedSize="yes" IconSize="32" Text="[ExclamationIcon]" />
      </Dialog>

      <Dialog Id="WelcomeDlg" Width="370" Height="270" Title="[ProductName] [ProductVersion] [Setup]" NoMinimize="yes">
        <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="[ButtonText_Next]">
          <Publish Event="NewDialog" Value="LicenseAgreementDlg">1</Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="[ButtonText_Cancel]">
          <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
        </Control>
        <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" />
        <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="[ButtonText_Back]" />
        <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="30" Transparent="yes" NoPrefix="yes">
          <Text>The [Wizard] will install [ProductName] [ProductVersion] on your computer. Click Next to continue or Cancel to exit the [Wizard].</Text>
        </Control>
        <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
        <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
          <Text>{\VerdanaBold13}Welcome to the [ProductName] [ProductVersion] [Wizard]</Text>
        </Control>
      </Dialog>

      <RadioButtonGroup Property="IAgree">
        <RadioButton Text="{\DlgFont8}I &amp;accept the terms in the License Agreement" Value="Yes" X="5" Y="0" Width="250" Height="15" />
        <RadioButton Text="{\DlgFont8}I &amp;do not accept the terms in the License Agreement" Value="No" X="5" Y="20" Width="250" Height="15" />
      </RadioButtonGroup>

      <TextStyle Id="DlgFont8" FaceName="Tahoma" Size="8" />
      <TextStyle Id="DlgFontBold8" FaceName="Tahoma" Size="8" Bold="yes" />
      <TextStyle Id="VerdanaBold13" FaceName="Verdana" Size="13" Bold="yes" />

      <UIText Id="AbsentPath" />
      <UIText Id="bytes">bytes</UIText>
      <UIText Id="GB">GB</UIText>
      <UIText Id="KB">KB</UIText>
      <UIText Id="MB">MB</UIText>
      <UIText Id="MenuAbsent">Entire feature will be unavailable</UIText>
      <UIText Id="MenuAdvertise">Feature will be installed when required</UIText>
      <UIText Id="MenuAllCD">Entire feature will be installed to run from CD</UIText>
      <UIText Id="MenuAllLocal">Entire feature will be installed on local hard drive</UIText>
      <UIText Id="MenuAllNetwork">Entire feature will be installed to run from network</UIText>
      <UIText Id="MenuCD">Will be installed to run from CD</UIText>
      <UIText Id="MenuLocal">Will be installed on local hard drive</UIText>
      <UIText Id="MenuNetwork">Will be installed to run from network</UIText>
      <UIText Id="ScriptInProgress">Gathering required information...</UIText>
      <UIText Id="SelAbsentAbsent">This feature will remain uninstalled</UIText>
      <UIText Id="SelAbsentAdvertise">This feature will be set to be installed when required</UIText>
      <UIText Id="SelAbsentCD">This feature will be installed to run from CD</UIText>
      <UIText Id="SelAbsentLocal">This feature will be installed on the local hard drive</UIText>
      <UIText Id="SelAbsentNetwork">This feature will be installed to run from the network</UIText>
      <UIText Id="SelAdvertiseAbsent">This feature will become unavailable</UIText>
      <UIText Id="SelAdvertiseAdvertise">Will be installed when required</UIText>
      <UIText Id="SelAdvertiseCD">This feature will be available to run from CD</UIText>
      <UIText Id="SelAdvertiseLocal">This feature will be installed on your local hard drive</UIText>
      <UIText Id="SelAdvertiseNetwork">This feature will be available to run from the network</UIText>
      <UIText Id="SelCDAbsent">This feature will be uninstalled completely, you won't be able to run it from CD</UIText>
      <UIText Id="SelCDAdvertise">This feature will change from run from CD state to set to be installed when required</UIText>
      <UIText Id="SelCDCD">This feature will remain to be run from CD</UIText>
      <UIText Id="SelCDLocal">This feature will change from run from CD state to be installed on the local hard drive</UIText>
      <UIText Id="SelChildCostNeg">This feature frees up [1] on your hard drive.</UIText>
      <UIText Id="SelChildCostPos">This feature requires [1] on your hard drive.</UIText>
      <UIText Id="SelCostPending">Compiling cost for this feature...</UIText>
      <UIText Id="SelLocalAbsent">This feature will be completely removed</UIText>
      <UIText Id="SelLocalAdvertise">This feature will be removed from your local hard drive, but will be set to be installed when required</UIText>
      <UIText Id="SelLocalCD">This feature will be removed from your local hard drive, but will be still available to run from CD</UIText>
      <UIText Id="SelLocalLocal">This feature will remain on you local hard drive</UIText>
      <UIText Id="SelLocalNetwork">This feature will be removed from your local hard drive, but will be still available to run from the network</UIText>
      <UIText Id="SelNetworkAbsent">This feature will be uninstalled completely, you won't be able to run it from the network</UIText>
      <UIText Id="SelNetworkAdvertise">This feature will change from run from network state to set to be installed when required</UIText>
      <UIText Id="SelNetworkLocal">This feature will change from run from network state to be installed on the local hard drive</UIText>
      <UIText Id="SelNetworkNetwork">This feature will remain to be run from the network</UIText>
      <UIText Id="SelParentCostNegNeg">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</UIText>
      <UIText Id="SelParentCostNegPos">This feature frees up [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</UIText>
      <UIText Id="SelParentCostPosNeg">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures free up [4] on your hard drive.</UIText>
      <UIText Id="SelParentCostPosPos">This feature requires [1] on your hard drive. It has [2] of [3] subfeatures selected. The subfeatures require [4] on your hard drive.</UIText>
      <UIText Id="TimeRemaining">Time remaining: {[1] minutes }{[2] seconds}</UIText>
      <UIText Id="VolumeCostAvailable">Available</UIText>
      <UIText Id="VolumeCostDifference">Difference</UIText>
      <UIText Id="VolumeCostRequired">Required</UIText>
      <UIText Id="VolumeCostSize">Disk Size</UIText>
      <UIText Id="VolumeCostVolume">Volume</UIText>
      <ProgressText Action="CostFinalize">Computing space requirements</ProgressText>
      <ProgressText Action="CostInitialize">Computing space requirements</ProgressText>
      <ProgressText Action="FileCost">Computing space requirements</ProgressText>
      <ProgressText Action="InstallValidate">Validating install</ProgressText>
      <ProgressText Action="InstallFiles" Template="File: [1],  Directory: [9],  Size: [6]">Copying new files</ProgressText>
      <ProgressText Action="InstallAdminPackage" Template="File: [1], Directory: [9], Size: [6]">Copying network install files</ProgressText>
      <ProgressText Action="CreateShortcuts" Template="Shortcut: [1]">Creating shortcuts</ProgressText>
      <ProgressText Action="PublishComponents" Template="Component ID: [1], Qualifier: [2]">Publishing Qualified Components</ProgressText>
      <ProgressText Action="PublishFeatures" Template="Feature: [1]">Publishing Product Features</ProgressText>
      <ProgressText Action="PublishProduct">Publishing product information</ProgressText>
      <ProgressText Action="RegisterClassInfo" Template="Class Id: [1]">Registering Class servers</ProgressText>
      <ProgressText Action="RegisterExtensionInfo" Template="Extension: [1]">Registering extension servers</ProgressText>
      <ProgressText Action="RegisterMIMEInfo" Template="MIME Content Type: [1], Extension: [2]">Registering MIME info</ProgressText>
      <ProgressText Action="RegisterProgIdInfo" Template="ProgId: [1]">Registering program identifiers</ProgressText>
      <ProgressText Action="AllocateRegistrySpace" Template="Free space: [1]">Allocating registry space</ProgressText>
      <ProgressText Action="AppSearch" Template="Property: [1], Signature: [2]">Searching for installed applications</ProgressText>
      <ProgressText Action="BindImage" Template="File: [1]">Binding executables</ProgressText>
      <ProgressText Action="CCPSearch">Searching for qualifying products</ProgressText>
      <ProgressText Action="CreateFolders" Template="Folder: [1]">Creating folders</ProgressText>
      <ProgressText Action="DeleteServices" Template="Service: [1]">Deleting services</ProgressText>
      <ProgressText Action="DuplicateFiles" Template="File: [1],  Directory: [9],  Size: [6]">Creating duplicate files</ProgressText>
      <ProgressText Action="FindRelatedProducts" Template="Found application: [1]">Searching for related applications</ProgressText>
      <ProgressText Action="InstallODBC">Installing ODBC components</ProgressText>
      <ProgressText Action="InstallServices" Template="Service: [2]">Installing new services</ProgressText>
      <ProgressText Action="LaunchConditions">Evaluating launch conditions</ProgressText>
      <ProgressText Action="MigrateFeatureStates" Template="Application: [1]">Migrating feature states from related applications</ProgressText>
      <ProgressText Action="MoveFiles" Template="File: [1],  Directory: [9],  Size: [6]">Moving files</ProgressText>
      <ProgressText Action="PatchFiles" Template="File: [1],  Directory: [2],  Size: [3]">Patching files</ProgressText>
      <ProgressText Action="ProcessComponents">Updating component registration</ProgressText>
      <ProgressText Action="RegisterComPlus" Template="AppId: [1]{{, AppType: [2], Users: [3], RSN: [4]}}">Registering COM+ Applications and Components</ProgressText>
      <ProgressText Action="RegisterFonts" Template="Font: [1]">Registering fonts</ProgressText>
      <ProgressText Action="RegisterProduct" Template="[1]">Registering product</ProgressText>
      <ProgressText Action="RegisterTypeLibraries" Template="LibID: [1]">Registering type libraries</ProgressText>
      <ProgressText Action="RegisterUser" Template="[1]">Registering user</ProgressText>
      <ProgressText Action="RemoveDuplicateFiles" Template="File: [1], Directory: [9]">Removing duplicated files</ProgressText>
      <ProgressText Action="RemoveEnvironmentStrings" Template="Name: [1], Value: [2], Action [3]">Updating environment strings</ProgressText>
      <ProgressText Action="RemoveExistingProducts" Template="Application: [1], Command line: [2]">Removing applications</ProgressText>
      <ProgressText Action="RemoveFiles" Template="File: [1], Directory: [9]">Removing files</ProgressText>
      <ProgressText Action="RemoveFolders" Template="Folder: [1]">Removing folders</ProgressText>
      <ProgressText Action="RemoveIniValues" Template="File: [1],  Section: [2],  Key: [3], Value: [4]">Removing INI files entries</ProgressText>
      <ProgressText Action="RemoveODBC">Removing ODBC components</ProgressText>
      <ProgressText Action="RemoveRegistryValues" Template="Key: [1], Name: [2]">Removing system registry values</ProgressText>
      <ProgressText Action="RemoveShortcuts" Template="Shortcut: [1]">Removing shortcuts</ProgressText>
      <ProgressText Action="RMCCPSearch">Searching for qualifying products</ProgressText>
      <ProgressText Action="SelfRegModules" Template="File: [1], Folder: [2]">Registering modules</ProgressText>
      <ProgressText Action="SelfUnregModules" Template="File: [1], Folder: [2]">Unregistering modules</ProgressText>
      <ProgressText Action="SetODBCFolders">Initializing ODBC directories</ProgressText>
      <ProgressText Action="StartServices" Template="Service: [1]">Starting services</ProgressText>
      <ProgressText Action="StopServices" Template="Service: [1]">Stopping services</ProgressText>
      <ProgressText Action="UnpublishComponents" Template="Component ID: [1], Qualifier: [2]">Unpublishing Qualified Components</ProgressText>
      <ProgressText Action="UnpublishFeatures" Template="Feature: [1]">Unpublishing Product Features</ProgressText>
      <ProgressText Action="UnregisterClassInfo" Template="Class Id: [1]">Unregister Class servers</ProgressText>
      <ProgressText Action="UnregisterComPlus" Template="AppId: [1]{{, AppType: [2]}}">Unregistering COM+ Applications and Components</ProgressText>
      <ProgressText Action="UnregisterExtensionInfo" Template="Extension: [1]">Unregistering extension servers</ProgressText>
      <ProgressText Action="UnregisterFonts" Template="Font: [1]">Unregistering fonts</ProgressText>
      <ProgressText Action="UnregisterMIMEInfo" Template="MIME Content Type: [1], Extension: [2]">Unregistering MIME info</ProgressText>
      <ProgressText Action="UnregisterProgIdInfo" Template="ProgId: [1]">Unregistering program identifiers</ProgressText>
      <ProgressText Action="UnregisterTypeLibraries" Template="LibID: [1]">Unregistering type libraries</ProgressText>
      <ProgressText Action="WriteEnvironmentStrings" Template="Name: [1], Value: [2], Action [3]">Updating environment strings</ProgressText>
      <ProgressText Action="WriteIniValues" Template="File: [1],  Section: [2],  Key: [3], Value: [4]">Writing INI files values</ProgressText>
      <ProgressText Action="WriteRegistryValues" Template="Key: [1], Name: [2], Value: [3]">Writing system registry values</ProgressText>
      <ProgressText Action="Advertise">Advertising application</ProgressText>
      <ProgressText Action="GenerateScript" Template="[1]">Generating script operations for action:</ProgressText>
      <ProgressText Action="InstallSFPCatalogFile" Template="File: [1],  Dependencies: [2]">Installing system catalog</ProgressText>
      <ProgressText Action="MsiPublishAssemblies" Template="Application Context:[1], Assembly Name:[2]">Publishing assembly information</ProgressText>
      <ProgressText Action="MsiUnpublishAssemblies" Template="Application Context:[1], Assembly Name:[2]">Unpublishing assembly information</ProgressText>
      <ProgressText Action="Rollback" Template="[1]">Rolling back action:</ProgressText>
      <ProgressText Action="RollbackCleanup" Template="File: [1]">Removing backup files</ProgressText>
      <ProgressText Action="UnmoveFiles" Template="File: [1], Directory: [9]">Removing moved files</ProgressText>
      <ProgressText Action="UnpublishProduct">Unpublishing product information</ProgressText>
      <Error Id="0">{{Fatal error: }}</Error>
      <Error Id="1">{{Error [1]. }}</Error>
      <Error Id="2">Warning [1]. </Error>
      <Error Id="3" />
      <Error Id="4">Info [1]. </Error>
      <Error Id="5">The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is [1]. {{The arguments are: [2], [3], [4]}}</Error>
      <Error Id="6" />
      <Error Id="7">{{Disk full: }}</Error>
      <Error Id="8">Action [Time]: [1]. [2]</Error>
      <Error Id="9">[ProductName] [ProductVersion]</Error>
      <Error Id="10">{[2]}{, [3]}{, [4]}</Error>
      <Error Id="11">Message type: [1], Argument: [2]</Error>
      <Error Id="12">=== Logging started: [Date]  [Time] ===</Error>
      <Error Id="13">=== Logging stopped: [Date]  [Time] ===</Error>
      <Error Id="14">Action start [Time]: [1].</Error>
      <Error Id="15">Action ended [Time]: [1]. Return value [2].</Error>
      <Error Id="16">Time remaining: {[1] minutes }{[2] seconds}</Error>
      <Error Id="17">Out of memory. Shut down other applications before retrying.</Error>
      <Error Id="18">Installer is no longer responding.</Error>
      <Error Id="19">Installer stopped prematurely.</Error>
      <Error Id="20">Please wait while Windows configures [ProductName] [ProductVersion]</Error>
      <Error Id="21">Gathering required information...</Error>
      <Error Id="22">Removing older versions of this application...</Error>
      <Error Id="23">Preparing to remove older versions of this application...</Error>
      <Error Id="32">{[ProductName] [ProductVersion] }Setup completed successfully.</Error>
      <Error Id="33">{[ProductName] [ProductVersion] }Setup failed.</Error>
      <Error Id="1101">Error reading from file: [2]. {{ System error [3].}}  Verify that the file exists and that you can access it.</Error>
      <Error Id="1301">Cannot create the file '[2]'. A directory with this name already exists. Cancel the install and try installing to a different location.</Error>
      <Error Id="1302">Please insert the disk: [2]</Error>
      <Error Id="1303">The installer has insufficient privileges to access this directory: [2]. The installation cannot continue. Log on as administrator or contact your system administrator.</Error>
      <Error Id="1304">Error writing to file: [2]. Verify that you have access to that directory.</Error>
      <Error Id="1305">Error reading from file [2]. {{ System error [3].}} Verify that the file exists and that you can access it.</Error>
      <Error Id="1306">Another application has exclusive access to the file '[2]'. Please shut down all other applications, then click Retry.</Error>
      <Error Id="1307">There is not enough disk space to install this file: [2]. Free some disk space and click Retry, or click Cancel to exit.</Error>
      <Error Id="1308">Source file not found: [2]. Verify that the file exists and that you can access it.</Error>
      <Error Id="1309">Error reading from file: [3]. {{ System error [2].}}  Verify that the file exists and that you can access it.</Error>
      <Error Id="1310">Error writing to file: [3]. {{ System error [2].}}  Verify that you have access to that directory.</Error>
      <Error Id="1311">Source file not found{{(cabinet)}}: [2]. Verify that the file exists and that you can access it.</Error>
      <Error Id="1312">Cannot create the directory '[2]'. A file with this name already exists. Please rename or remove the file and click retry, or click Cancel to exit.</Error>
      <Error Id="1313">The volume [2] is currently unavailable. Please select another.</Error>
      <Error Id="1314">The specified path '[2]' is unavailable.</Error>
      <Error Id="1315">Unable to write to the specified folder: [2].</Error>
      <Error Id="1316">A network error occurred while attempting to read from the file: [2]</Error>
      <Error Id="1317">An error occurred while attempting to create the directory: [2]</Error>
      <Error Id="1318">A network error occurred while attempting to create the directory: [2]</Error>
      <Error Id="1319">A network error occurred while attempting to open the source file cabinet: [2]</Error>
      <Error Id="1320">The specified path is too long: [2]</Error>
      <Error Id="1321">The Installer has insufficient privileges to modify this file: [2].</Error>
      <Error Id="1322">A portion of the folder path '[2]' is invalid. It is either empty or exceeds the length allowed by the system.</Error>
      <Error Id="1323">The folder path '[2]' contains words that are not valid in folder paths.</Error>
      <Error Id="1324">The folder path '[2]' contains an invalid character.</Error>
      <Error Id="1325">'[2]' is not a valid short file name.</Error>
      <Error Id="1326">Error getting file security: [3] GetLastError: [2]</Error>
      <Error Id="1327">Invalid Drive: [2]</Error>
      <Error Id="1328">Error applying patch to file [2]. It has probably been updated by other means, and can no longer be modified by this patch. For more information contact your patch vendor. {{System Error: [3]}}</Error>
      <Error Id="1329">A file that is required cannot be installed because the cabinet file [2] is not digitally signed. This may indicate that the cabinet file is corrupt.</Error>
      <Error Id="1330">A file that is required cannot be installed because the cabinet file [2] has an invalid digital signature. This may indicate that the cabinet file is corrupt.{{  Error [3] was returned by WinVerifyTrust.}}</Error>
      <Error Id="1331">Failed to correctly copy [2] file: CRC error.</Error>
      <Error Id="1332">Failed to correctly move [2] file: CRC error.</Error>
      <Error Id="1333">Failed to correctly patch [2] file: CRC error.</Error>
      <Error Id="1334">The file '[2]' cannot be installed because the file cannot be found in cabinet file '[3]'. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package.</Error>
      <Error Id="1335">The cabinet file '[2]' required for this installation is corrupt and cannot be used. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package.</Error>
      <Error Id="1336">There was an error creating a temporary file that is needed to complete this installation.{{  Folder: [3]. System error code: [2]}}</Error>
      <Error Id="1401">Could not create key: [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel. </Error>
      <Error Id="1402">Could not open key: [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel. </Error>
      <Error Id="1403">Could not delete value [2] from key [3]. {{ System error [4].}}  Verify that you have sufficient access to that key, or contact your support personnel. </Error>
      <Error Id="1404">Could not delete key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel. </Error>
      <Error Id="1405">Could not read value [2] from key [3]. {{ System error [4].}}  Verify that you have sufficient access to that key, or contact your support personnel. </Error>
      <Error Id="1406">Could not write value [2] to key [3]. {{ System error [4].}}  Verify that you have sufficient access to that key, or contact your support personnel.</Error>
      <Error Id="1407">Could not get value names for key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.</Error>
      <Error Id="1408">Could not get sub key names for key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.</Error>
      <Error Id="1409">Could not read security information for key [2]. {{ System error [3].}}  Verify that you have sufficient access to that key, or contact your support personnel.</Error>
      <Error Id="1410">Could not increase the available registry space. [2] KB of free registry space is required for the installation of this application.</Error>
      <Error Id="1500">Another installation is in progress. You must complete that installation before continuing this one.</Error>
      <Error Id="1501">Error accessing secured data. Please make sure the Windows Installer is configured properly and try the install again.</Error>
      <Error Id="1502">User '[2]' has previously initiated an install for product '[3]'. That user will need to run that install again before they can use that product. Your current install will now continue.</Error>
      <Error Id="1503">User '[2]' has previously initiated an install for product '[3]'. That user will need to run that install again before they can use that product.</Error>
      <Error Id="1601">Out of disk space -- Volume: '[2]'; required space: [3] KB; available space: [4] KB. Free some disk space and retry.</Error>
      <Error Id="1602">Are you sure you want to cancel?</Error>
      <Error Id="1603">The file [2][3] is being held in use{ by the following process: Name: [4], Id: [5], Window Title: '[6]'}. Close that application and retry.</Error>
      <Error Id="1604">The product '[2]' is already installed, preventing the installation of this product. The two products are incompatible.</Error>
      <Error Id="1605">There is not enough disk space on the volume '[2]' to continue the install with recovery enabled. [3] KB are required, but only [4] KB are available. Click Ignore to continue the install without saving recovery information, click Retry to check for available space again, or click Cancel to quit the installation.</Error>
      <Error Id="1606">Could not access network location [2].</Error>
      <Error Id="1607">The following applications should be closed before continuing the install:</Error>
      <Error Id="1608">Could not find any previously installed compliant products on the machine for installing this product.</Error>
      <Error Id="1609">An error occurred while applying security settings. [2] is not a valid user or group. This could be a problem with the package, or a problem connecting to a domain controller on the network. Check your network connection and click Retry, or Cancel to end the install. {{Unable to locate the user's SID, system error [3]}}</Error>
      <Error Id="1701">The key [2] is not valid. Verify that you entered the correct key.</Error>
      <Error Id="1702">The installer must restart your system before configuration of [2] can continue. Click Yes to restart now or No if you plan to manually restart later.</Error>
      <Error Id="1703">You must restart your system for the configuration changes made to [2] to take effect. Click Yes to restart now or No if you plan to manually restart later.</Error>
      <Error Id="1704">An installation for [2] is currently suspended. You must undo the changes made by that installation to continue. Do you want to undo those changes?</Error>
      <Error Id="1705">A previous installation for this product is in progress. You must undo the changes made by that installation to continue. Do you want to undo those changes?</Error>
      <Error Id="1706">An installation package for the product [2] cannot be found. Try the installation again using a valid copy of the installation package '[3]'.</Error>
      <Error Id="1707">Installation completed successfully.</Error>
      <Error Id="1708">Installation failed.</Error>
      <Error Id="1709">Product: [2] -- [3]</Error>
      <Error Id="1710">You may either restore your computer to its previous state or continue the install later. Would you like to restore?</Error>
      <Error Id="1711">An error occurred while writing installation information to disk. Check to make sure enough disk space is available, and click Retry, or Cancel to end the install.</Error>
      <Error Id="1712">One or more of the files required to restore your computer to its previous state could not be found. Restoration will not be possible.</Error>
      <Error Id="1713">[2] cannot install one of its required products. Contact your technical support group. {{System Error: [3].}}</Error>
      <Error Id="1714">The older version of [2] cannot be removed. Contact your technical support group. {{System Error [3].}}</Error>
      <Error Id="1715">Installed [2]</Error>
      <Error Id="1716">Configured [2]</Error>
      <Error Id="1717">Removed [2]</Error>
      <Error Id="1718">File [2] was rejected by digital signature policy.</Error>
      <Error Id="1719">The Windows Installer Service could not be accessed. This can occur if you are running Windows in safe mode, or if the Windows Installer is not correctly installed. Contact your support personnel for assistance.</Error>
      <Error Id="1720">There is a problem with this Windows Installer package. A script required for this install to complete could not be run. Contact your support personnel or package vendor. {{Custom action [2] script error [3], [4]: [5] Line [6], Column [7], [8] }}</Error>
      <Error Id="1721">There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. {{Action: [2], location: [3], command: [4] }}</Error>
      <Error Id="1722">There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. {{Action [2], location: [3], command: [4] }}</Error>
      <Error Id="1723">There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor. {{Action [2], entry: [3], library: [4] }}</Error>
      <Error Id="1724">Removal completed successfully.</Error>
      <Error Id="1725">Removal failed.</Error>
      <Error Id="1726">Advertisement completed successfully.</Error>
      <Error Id="1727">Advertisement failed.</Error>
      <Error Id="1728">Configuration completed successfully.</Error>
      <Error Id="1729">Configuration failed.</Error>
      <Error Id="1730">You must be an Administrator to remove this application. To remove this application, you can log on as an Administrator, or contact your technical support group for assistance.</Error>
      <Error Id="1801">The path [2] is not valid. Please specify a valid path.</Error>
      <Error Id="1802">Out of memory. Shut down other applications before retrying.</Error>
      <Error Id="1803">There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to go back to the previously selected volume.</Error>
      <Error Id="1804">There is no disk in drive [2]. Please insert one and click Retry, or click Cancel to return to the browse dialog and select a different volume.</Error>
      <Error Id="1805">The folder [2] does not exist. Please enter a path to an existing folder.</Error>
      <Error Id="1806">You have insufficient privileges to read this folder.</Error>
      <Error Id="1807">A valid destination folder for the install could not be determined.</Error>
      <Error Id="1901">Error attempting to read from the source install database: [2].</Error>
      <Error Id="1902">Scheduling reboot operation: Renaming file [2] to [3]. Must reboot to complete operation.</Error>
      <Error Id="1903">Scheduling reboot operation: Deleting file [2]. Must reboot to complete operation.</Error>
      <Error Id="1904">Module [2] failed to register. HRESULT [3]. Contact your support personnel.</Error>
      <Error Id="1905">Module [2] failed to unregister. HRESULT [3]. Contact your support personnel.</Error>
      <Error Id="1906">Failed to cache package [2]. Error: [3]. Contact your support personnel.</Error>
      <Error Id="1907">Could not register font [2]. Verify that you have sufficient permissions to install fonts, and that the system supports this font.</Error>
      <Error Id="1908">Could not unregister font [2]. Verify that you that you have sufficient permissions to remove fonts.</Error>
      <Error Id="1909">Could not create Shortcut [2]. Verify that the destination folder exists and that you can access it.</Error>
      <Error Id="1910">Could not remove Shortcut [2]. Verify that the shortcut file exists and that you can access it.</Error>
      <Error Id="1911">Could not register type library for file [2]. Contact your support personnel.</Error>
      <Error Id="1912">Could not unregister type library for file [2]. Contact your support personnel.</Error>
      <Error Id="1913">Could not update the ini file [2][3]. Verify that the file exists and that you can access it.</Error>
      <Error Id="1914">Could not schedule file [2] to replace file [3] on reboot. Verify that you have write permissions to file [3].</Error>
      <Error Id="1915">Error removing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.</Error>
      <Error Id="1916">Error installing ODBC driver manager, ODBC error [2]: [3]. Contact your support personnel.</Error>
      <Error Id="1917">Error removing ODBC driver: [4], ODBC error [2]: [3]. Verify that you have sufficient privileges to remove ODBC drivers.</Error>
      <Error Id="1918">Error installing ODBC driver: [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.</Error>
      <Error Id="1919">Error configuring ODBC data source: [4], ODBC error [2]: [3]. Verify that the file [4] exists and that you can access it.</Error>
      <Error Id="1920">Service '[2]' ([3]) failed to start. Verify that you have sufficient privileges to start system services.</Error>
      <Error Id="1921">Service '[2]' ([3]) could not be stopped. Verify that you have sufficient privileges to stop system services.</Error>
      <Error Id="1922">Service '[2]' ([3]) could not be deleted. Verify that you have sufficient privileges to remove system services.</Error>
      <Error Id="1923">Service '[2]' ([3]) could not be installed. Verify that you have sufficient privileges to install system services.</Error>
      <Error Id="1924">Could not update environment variable '[2]'. Verify that you have sufficient privileges to modify environment variables.</Error>
      <Error Id="1925">You do not have sufficient privileges to complete this installation for all users of the machine. Log on as administrator and then retry this installation.</Error>
      <Error Id="1926">Could not set file security for file '[3]'. Error: [2]. Verify that you have sufficient privileges to modify the security permissions for this file.</Error>
      <Error Id="1927">Component Services (COM+ 1.0) are not installed on this computer. This installation requires Component Services in order to complete successfully. Component Services are available on Windows 2000.</Error>
      <Error Id="1928">Error registering COM+ Application. Contact your support personnel for more information.</Error>
      <Error Id="1929">Error unregistering COM+ Application. Contact your support personnel for more information.</Error>
      <Error Id="1930">The description for service '[2]' ([3]) could not be changed.</Error>
      <Error Id="1931">The Windows Installer service cannot update the system file [2] because the file is protected by Windows. You may need to update your operating system for this program to work correctly. {{Package version: [3], OS Protected version: [4]}}</Error>
      <Error Id="1932">The Windows Installer service cannot update the protected Windows file [2]. {{Package version: [3], OS Protected version: [4], SFP Error: [5]}}</Error>
      <Error Id="1933">The Windows Installer service cannot update one or more protected Windows files. {{SFP Error: [2]. List of protected files:\r\n[3]}}</Error>
      <Error Id="1934">User installations are disabled via policy on the machine.</Error>
      <Error Id="1935">An error occured during the installation of assembly component [2]. HRESULT: [3]. {{assembly interface: [4], function: [5], assembly name: [6]}}</Error>

      <AdminUISequence>
        <Show Dialog="FatalError" OnExit="error" />
        <Show Dialog="UserExit" OnExit="cancel" />
        <Show Dialog="ExitDialog" OnExit="success" />
        <Show Dialog="PrepareDlg" Before="CostInitialize"></Show>
        <Show Dialog="AdminWelcomeDlg" After="CostFinalize" />
        <Show Dialog="ProgressDlg" After="AdminWelcomeDlg" />
      </AdminUISequence>

      <InstallUISequence>
        <Show Dialog="FatalError" OnExit="error" />
        <Show Dialog="UserExit" OnExit="cancel" />
        <Show Dialog="ExitDialog" OnExit="success" />
        <Show Dialog="PrepareDlg" After="LaunchConditions" />
        <Show Dialog="WelcomeDlg" After="MigrateFeatureStates">NOT Installed</Show>
        <Show Dialog="ResumeDlg" After="WelcomeDlg">Installed AND (RESUME OR Preselected)</Show>
        <Show Dialog="MaintenanceWelcomeDlg" After="ResumeDlg">Installed AND NOT RESUME AND NOT Preselected</Show>
        <Show Dialog="ProgressDlg" After="MaintenanceWelcomeDlg" />
      </InstallUISequence>
    </UI>


    <AdminExecuteSequence />

    <InstallExecuteSequence>
      <RemoveExistingProducts After='InstallFinalize' />
    </InstallExecuteSequence>

  </Product>
</Wix>

Added jni/tkzinc/win/WinPort.c.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
/*
 * WinPort.c -- Compatibility layer for Windows 2k
 *
 * Authors		: Patrick Lecoanet.
 * Creation date	:
 *
 * $Id$
 */

/*
 *  Copyright (c) 2003 - 2005 CENA, Patrick Lecoanet --
 *
 * See the file "Copyright" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 */

#ifdef _WIN32

#include "Types.h"

#include <tkInt.h>
#include <tkWinInt.h>
#ifdef PTK
#include <tkIntPlatDecls.m>
#endif

static const char rcsid[] = "$Id";
static const char compile_id[]="$Compile$";

#ifndef MIN
#define MIN(a, b) 	((a) <= (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) 	((a) >= (b) ? (a) : (b))
#endif


/*
 *----------------------------------------------------------------------
 *
 * ZnPointInRegion --
 *
 *	Test whether the specified point is inside a region.
 *
 * Results:
 *	Returns the boolean result of the test.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
int
ZnPointInRegion(TkRegion reg,
		int	 x,
		int	 y)
{
  return PtInRegion((HRGN) reg, x, y);
}

/*
 *----------------------------------------------------------------------
 *
 * ZnUnionRegion --
 *
 *	Compute the union of two regions.
 *
 * Results:
 *	Returns the result in the dr_return region.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
void
ZnUnionRegion(TkRegion	sra,
	      TkRegion	srb,
	      TkRegion	dr_return)
{
  CombineRgn((HRGN) dr_return, (HRGN) sra, (HRGN) srb, RGN_OR);
}

/*
 *----------------------------------------------------------------------
 *
 * ZnOffsetRegion --
 *
 *	Offset a region by the specified pixel offsets.
 *
 * Results:
 *	Returns the result in the dr_return region.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
void
ZnOffsetRegion(TkRegion	reg,
	       int	dx,
	       int	dy)
{
  OffsetRgn((HRGN) reg, dx, dy);
}

/*
 *----------------------------------------------------------------------
 *
 * ZnPolygonRegion --
 *
 *	Compute a region from a polygon.
 *
 * Results:
 *	Returns the result in the dr_return region.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
TkRegion
ZnPolygonRegion(XPoint	*points,
		int	n,
		int	fill_rule)
{
  POINT	*pts;
  HRGN reg;
  int	i;

  pts = (POINT *) ckalloc(n*sizeof(POINT));
  for (i = 0; i < n; i++, points++) {
    pts[i].x = points->x;
    pts[i].y = points->y;
  }

  reg = CreatePolygonRgn(pts, n,
			 fill_rule==EvenOddRule?ALTERNATE:WINDING);
  if (!reg) {
    fprintf(stderr, "Polygon region failed: %ld, n: %d\n", GetLastError(), n);
  }
  ckfree((char *) pts);
  return (TkRegion) reg;
}

#define PI 3.14159265358979
#define XAngleToRadians(a) ((double)(a) / 64 * PI / 180);

/*
 * Translation table between X gc functions and Win32 raster op modes.
 */

CONST int tkpWinRopModes[] = {
    R2_BLACK,			/* GXclear */
    R2_MASKPEN,			/* GXand */
    R2_MASKPENNOT,		/* GXandReverse */
    R2_COPYPEN,			/* GXcopy */
    R2_MASKNOTPEN,		/* GXandInverted */
    R2_NOT,			/* GXnoop */
    R2_XORPEN,			/* GXxor */
    R2_MERGEPEN,		/* GXor */
    R2_NOTMERGEPEN,		/* GXnor */
    R2_NOTXORPEN,		/* GXequiv */
    R2_NOT,			/* GXinvert */
    R2_MERGEPENNOT,		/* GXorReverse */
    R2_NOTCOPYPEN,		/* GXcopyInverted */
    R2_MERGENOTPEN,		/* GXorInverted */
    R2_NOTMASKPEN,		/* GXnand */
    R2_WHITE			/* GXset */
};

/*
 * The following two raster ops are used to copy the foreground and background
 * bits of a source pattern as defined by a stipple used as the pattern.
 */

#define COPYFG		0x00CA0749 /* dest = (pat & src) | (!pat & dst) */
#define COPYBG		0x00AC0744 /* dest = (!pat & src) | (pat & dst) */

/*
 * The followng typedef is used to pass Windows GDI drawing functions.
 */

typedef BOOL (CALLBACK *WinDrawFunc) _ANSI_ARGS_((HDC dc,
			    CONST POINT* points, int npoints));

typedef struct ThreadSpecificData {
    POINT *winPoints;    /* Array of points that is reused. */
    int nWinPoints;	/* Current size of point array. */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;

/*
 *----------------------------------------------------------------------
 *
 * SetUpGraphicsPort --
 *
 *	Set up the graphics port from the given GC.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The current port is adjusted.
 *
 *----------------------------------------------------------------------
 */

static HPEN
SetUpGraphicsPort(gc)
    GC gc;
{
    DWORD style;

    if (gc->line_style == LineOnOffDash) {
	unsigned char *p = (unsigned char *) &(gc->dashes);
				/* pointer to the dash-list */

	/*
	 * Below is a simple translation of serveral dash patterns
	 * to valid windows pen types. Far from complete,
	 * but I don't know how to do it better.
	 * Any ideas: <mailto:j.nijtmans@chello.nl>
	 */

	if (p[1] && p[2]) {
	    if (!p[3] || p[4]) {
		style = PS_DASHDOTDOT;		/*	-..	*/
	    } else {
		style = PS_DASHDOT;		/*	-.	*/
	    }
	} else {
	    if (p[0] > (4 * gc->line_width)) {
		style = PS_DASH;		/*	-	*/
	    } else {
		style = PS_DOT;			/*	.	*/
	    }
	}
    } else {
	style = PS_SOLID;
    }
    if (gc->line_width < 2) {
	return CreatePen(style, gc->line_width, gc->foreground);
    } else {
	LOGBRUSH lb;

	lb.lbStyle = BS_SOLID;
	lb.lbColor = gc->foreground;
	lb.lbHatch = 0;

	style |= PS_GEOMETRIC;
	switch (gc->cap_style) {
	    case CapNotLast:
	    case CapButt:
		style |= PS_ENDCAP_FLAT; 
		break;
	    case CapRound:
		style |= PS_ENDCAP_ROUND; 
		break;
	    default:
		style |= PS_ENDCAP_SQUARE; 
		break;
	}
	switch (gc->join_style) {
	    case JoinMiter: 
		style |= PS_JOIN_MITER; 
		break;
	    case JoinRound:
		style |= PS_JOIN_ROUND; 
		break;
	    default:
		style |= PS_JOIN_BEVEL; 
		break;
	}
	return ExtCreatePen(style, gc->line_width, &lb, 0, NULL);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertPoints --
 *
 *	Convert an array of X points to an array of Win32 points.
 *
 * Results:
 *	Returns the converted array of POINTs.
 *
 * Side effects:
 *	Allocates a block of memory in thread local storage that 
 *      should not be freed.
 *
 *----------------------------------------------------------------------
 */

static POINT *
ConvertPoints(points, npoints, mode, bbox)
    XPoint *points;
    int npoints;
    int mode;			/* CoordModeOrigin or CoordModePrevious. */
    RECT *bbox;			/* Bounding box of points. */
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) 
            Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
    int i;

    /*
     * To avoid paying the cost of a malloc on every drawing routine,
     * we reuse the last array if it is large enough.
     */

    if (npoints > tsdPtr->nWinPoints) {
	if (tsdPtr->winPoints != NULL) {
	    ckfree((char *) tsdPtr->winPoints);
	}
	tsdPtr->winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints);
	if (tsdPtr->winPoints == NULL) {
	    tsdPtr->nWinPoints = -1;
	    return NULL;
	}
	tsdPtr->nWinPoints = npoints;
    }

    bbox->left = bbox->right = points[0].x;
    bbox->top = bbox->bottom = points[0].y;
    
    if (mode == CoordModeOrigin) {
	for (i = 0; i < npoints; i++) {
	    tsdPtr->winPoints[i].x = points[i].x;
	    tsdPtr->winPoints[i].y = points[i].y;
	    bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
	    bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
	    bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
	    bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
	}
    } else {
	tsdPtr->winPoints[0].x = points[0].x;
	tsdPtr->winPoints[0].y = points[0].y;
	for (i = 1; i < npoints; i++) {
	    tsdPtr->winPoints[i].x = tsdPtr->winPoints[i-1].x + points[i].x;
	    tsdPtr->winPoints[i].y = tsdPtr->winPoints[i-1].y + points[i].y;
	    bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x);
	    bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x);
	    bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y);
	    bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y);
	}
    }
    return tsdPtr->winPoints;
}

/*
 *----------------------------------------------------------------------
 *
 * XFillRectangles --
 *
 *	Fill multiple rectangular areas in the given drawable.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws onto the specified drawable.
 *
 *----------------------------------------------------------------------
 */
void
ZnXFillRectangles(display, d, gc, rectangles, nrectangles)
    Display* display;
    Drawable d;
    GC gc;
    XRectangle* rectangles;
    int nrectangles;
{
    HDC dc;
    int i;
    RECT rect;
    TkWinDCState state;
    HBRUSH brush;
    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;

    if (d == None) {
	return;
    }

    dc = TkWinGetDrawableDC(display, d, &state);
    SetROP2(dc, tkpWinRopModes[gc->function]);
    brush = CreateSolidBrush(gc->foreground);

    if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
	SelectClipRgn(dc, (HRGN) clipPtr->value.region);
	OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
    }
    if ((gc->fill_style == FillStippled
	    || gc->fill_style == FillOpaqueStippled)
	    && gc->stipple != None) {
	TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
	HBRUSH oldBrush, stipple;
	HBITMAP oldBitmap, bitmap;
	HDC dcMem;
	HBRUSH bgBrush = CreateSolidBrush(gc->background);

	if (twdPtr->type != TWD_BITMAP) {
	    Tcl_Panic("unexpected drawable type in stipple");
	}

	/*
	 * Select stipple pattern into destination dc.
	 */
	
	stipple = CreatePatternBrush(twdPtr->bitmap.handle);
	SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
	oldBrush = SelectObject(dc, stipple);
	dcMem = CreateCompatibleDC(dc);

	/*
	 * For each rectangle, create a drawing surface which is the size of
	 * the rectangle and fill it with the background color.  Then merge the
	 * result with the stipple pattern.
	 */
	for (i = 0; i < nrectangles; i++) {
	    bitmap = CreateCompatibleBitmap(dc, rectangles[i].width,
		    rectangles[i].height);
	    oldBitmap = SelectObject(dcMem, bitmap);
	    rect.left = 0;
	    rect.top = 0;
	    rect.right = rectangles[i].width;
	    rect.bottom = rectangles[i].height;
	    FillRect(dcMem, &rect, brush);
	    BitBlt(dc, rectangles[i].x, rectangles[i].y, rectangles[i].width,
		    rectangles[i].height, dcMem, 0, 0, COPYFG);
	    if (gc->fill_style == FillOpaqueStippled) {
		FillRect(dcMem, &rect, bgBrush);
		BitBlt(dc, rectangles[i].x, rectangles[i].y,
			rectangles[i].width, rectangles[i].height, dcMem,
			0, 0, COPYBG);
	    }
	    SelectObject(dcMem, oldBitmap);
	    DeleteObject(bitmap);
	}
	
	DeleteDC(dcMem);
	SelectObject(dc, oldBrush);
	DeleteObject(stipple);
	DeleteObject(bgBrush);
    } else {
	for (i = 0; i < nrectangles; i++) {
	    TkWinFillRect(dc, rectangles[i].x, rectangles[i].y,
		    rectangles[i].width, rectangles[i].height, gc->foreground);
	}
    }
    DeleteObject(brush);
    TkWinReleaseDrawableDC(d, dc, &state);
}


/*
 *----------------------------------------------------------------------
 *
 * XFillRectangle --
 *
 *	Fills a rectangular area in the given drawable.  This procedure
 *	is implemented as a call to XFillRectangles.
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Fills the specified rectangle.
 *
 *----------------------------------------------------------------------
 */

void
ZnXFillRectangle(display, d, gc, x, y, width, height)
    Display* display;
    Drawable d;
    GC gc;
    int x;
    int y;
    unsigned int width;
    unsigned int height;
{
    XRectangle rectangle;
    rectangle.x = x;
    rectangle.y = y;
    rectangle.width = width;
    rectangle.height = height;
    XFillRectangles(display, d, gc, &rectangle, 1);
}

/*
 *----------------------------------------------------------------------
 *
 * RenderObject --
 *
 *	This function draws a shape using a list of points, a
 *	stipple pattern, and the specified drawing function.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
RenderObject(dc, gc, points, npoints, mode, pen, func)
    HDC dc;
    GC gc;
    XPoint* points;
    int npoints;
    int mode;
    HPEN pen;
    WinDrawFunc func;
{
    RECT rect;
    HPEN oldPen;
    HBRUSH oldBrush;
    POINT *winPoints = ConvertPoints(points, npoints, mode, &rect);
    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
    
    if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
	SelectClipRgn(dc, (HRGN) clipPtr->value.region);
	OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
    }
    if ((gc->fill_style == FillStippled
	    || gc->fill_style == FillOpaqueStippled)
	    && gc->stipple != None) {

	TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
	HDC dcMem;
	LONG width, height;
	HBITMAP oldBitmap;
	int i;
	HBRUSH oldMemBrush;
	
	if (twdPtr->type != TWD_BITMAP) {
	    Tcl_Panic("unexpected drawable type in stipple");
	}

	/*
	 * Grow the bounding box enough to account for line width.
	 */

	rect.left -= gc->line_width;
	rect.top -= gc->line_width;
	rect.right += gc->line_width;
	rect.bottom += gc->line_width;

	width = rect.right - rect.left;
	height = rect.bottom - rect.top;

	/*
	 * Select stipple pattern into destination dc.
	 */
	
	SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
	oldBrush = SelectObject(dc, CreatePatternBrush(twdPtr->bitmap.handle));

	/*
	 * Create temporary drawing surface containing a copy of the
	 * destination equal in size to the bounding box of the object.
	 */
	
	dcMem = CreateCompatibleDC(dc);
	oldBitmap = SelectObject(dcMem, CreateCompatibleBitmap(dc, width,
		height));
	oldPen = SelectObject(dcMem, pen);
	BitBlt(dcMem, 0, 0, width, height, dc, rect.left, rect.top, SRCCOPY);

	/*
	 * Translate the object for rendering in the temporary drawing
	 * surface. 
	 */

	for (i = 0; i < npoints; i++) {
	    winPoints[i].x -= rect.left;
	    winPoints[i].y -= rect.top;
	}

	/*
	 * Draw the object in the foreground color and copy it to the
	 * destination wherever the pattern is set.
	 */

	SetPolyFillMode(dcMem, (gc->fill_rule == EvenOddRule) ? ALTERNATE
		: WINDING);
	oldMemBrush = SelectObject(dcMem, CreateSolidBrush(gc->foreground));
	(*func)(dcMem, winPoints, npoints);
	BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0, COPYFG);

	/*
	 * If we are rendering an opaque stipple, then draw the polygon in the
	 * background color and copy it to the destination wherever the pattern
	 * is clear.
	 */

	if (gc->fill_style == FillOpaqueStippled) {
	    DeleteObject(SelectObject(dcMem,
		    CreateSolidBrush(gc->background)));
	    (*func)(dcMem, winPoints, npoints);
	    BitBlt(dc, rect.left, rect.top, width, height, dcMem, 0, 0,
		    COPYBG);
	}

	SelectObject(dcMem, oldPen);
	DeleteObject(SelectObject(dcMem, oldMemBrush));
	DeleteObject(SelectObject(dcMem, oldBitmap));
	DeleteDC(dcMem);
    } else {
	oldPen = SelectObject(dc, pen);
	oldBrush = SelectObject(dc, CreateSolidBrush(gc->foreground));
	SetROP2(dc, tkpWinRopModes[gc->function]);

	SetPolyFillMode(dc, (gc->fill_rule == EvenOddRule) ? ALTERNATE
		: WINDING);

	(*func)(dc, winPoints, npoints);

	SelectObject(dc, oldPen);
    }
    DeleteObject(SelectObject(dc, oldBrush));
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawLines --
 *
 *	Draw connected lines.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Renders a series of connected lines.
 *
 *----------------------------------------------------------------------
 */

void
ZnXDrawLines(display, d, gc, points, npoints, mode)
    Display* display;
    Drawable d;
    GC gc;
    XPoint* points;
    int npoints;
    int mode;
{
    HPEN pen;
    TkWinDCState state;
    HDC dc;
    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;
    
    if (d == None) {
	return;
    }

    dc = TkWinGetDrawableDC(display, d, &state);

    if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
	SelectClipRgn(dc, (HRGN) clipPtr->value.region);
	OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
    }
    pen = SetUpGraphicsPort(gc);
    SetBkMode(dc, TRANSPARENT);
    RenderObject(dc, gc, points, npoints, mode, pen, Polyline);
    DeleteObject(pen);
    
    TkWinReleaseDrawableDC(d, dc, &state);
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawLine --
 *
 *	Draw a single line between two points in a given drawable. 
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a single line segment.
 *
 *----------------------------------------------------------------------
 */

void
ZnXDrawLine(display, d, gc, x1, y1, x2, y2)
    Display* display;
    Drawable d;
    GC gc;
    int x1, y1, x2, y2;		/* Coordinates of line segment. */
{
    XPoint points[2];

    points[0].x = x1;
    points[0].y = y1;
    points[1].x = x2;
    points[1].y = y2;
    XDrawLines(display, d, gc, points, 2, CoordModeOrigin);
}

/*
 *----------------------------------------------------------------------
 *
 * XFillPolygon --
 *
 *	Draws a filled polygon.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a filled polygon on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

void
ZnXFillPolygon(display, d, gc, points, npoints, shape, mode)
    Display* display;
    Drawable d;
    GC gc;
    XPoint* points;
    int npoints;
    int shape;
    int mode;
{
    HPEN pen;
    TkWinDCState state;
    HDC dc;

    if (d == None) {
	return;
    }

    dc = TkWinGetDrawableDC(display, d, &state);

    pen = GetStockObject(NULL_PEN);
    RenderObject(dc, gc, points, npoints, mode, pen, Polygon);

    TkWinReleaseDrawableDC(d, dc, &state);
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawRectangle --
 *
 *	Draws a rectangle.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a rectangle on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

void
ZnXDrawRectangle(display, d, gc, x, y, width, height)
    Display* display;
    Drawable d;
    GC gc;
    int x;
    int y;
    unsigned int width;
    unsigned int height;
{
    HPEN pen, oldPen;
    TkWinDCState state;
    HBRUSH oldBrush;
    HDC dc;
    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;

    if (d == None) {
	return;
    }

    dc = TkWinGetDrawableDC(display, d, &state);

    if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
	SelectClipRgn(dc, (HRGN) clipPtr->value.region);
	OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
    }
    pen = SetUpGraphicsPort(gc);
    SetBkMode(dc, TRANSPARENT);
    oldPen = SelectObject(dc, pen);
    oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH));
    SetROP2(dc, tkpWinRopModes[gc->function]);

    Rectangle(dc, x, y, x+width+1, y+height+1);

    DeleteObject(SelectObject(dc, oldPen));
    SelectObject(dc, oldBrush);
    TkWinReleaseDrawableDC(d, dc, &state);
}

/*
 *----------------------------------------------------------------------
 *
 * DrawOrFillArc --
 *
 *	This procedure handles the rendering of drawn or filled
 *	arcs and chords.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Renders the requested arc.
 *
 *----------------------------------------------------------------------
 */

static void
DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill)
    Display *display;
    Drawable d;
    GC gc;
    int x, y;			/* left top */
    unsigned int width, height;
    int start;			/* start: three-o'clock (deg*64) */
    int extent;			/* extent: relative (deg*64) */
    int fill;			/* ==0 draw, !=0 fill */
{
    HDC dc;
    HBRUSH brush, oldBrush;
    HPEN pen, oldPen;
    TkWinDCState state;
    int clockwise = (extent < 0); /* non-zero if clockwise */
    int xstart, ystart, xend, yend;
    double radian_start, radian_end, xr, yr;
    TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask;

    if (d == None) {
	return;
    }

    dc = TkWinGetDrawableDC(display, d, &state);

    if (clipPtr && clipPtr->type == TKP_CLIP_REGION) {
	SelectClipRgn(dc, (HRGN) clipPtr->value.region);
	OffsetClipRgn(dc, gc->clip_x_origin, gc->clip_y_origin);
    }
    SetROP2(dc, tkpWinRopModes[gc->function]);

    /*
     * Compute the absolute starting and ending angles in normalized radians.
     * Swap the start and end if drawing clockwise.
     */

    start = start % (64*360);
    if (start < 0) {
	start += (64*360);
    }
    extent = (start+extent) % (64*360);
    if (extent < 0) {
	extent += (64*360);
    }
    if (clockwise) {
	int tmp = start;
	start = extent;
	extent = tmp;
    }
    radian_start = XAngleToRadians(start);
    radian_end = XAngleToRadians(extent);

    /*
     * Now compute points on the radial lines that define the starting and
     * ending angles.  Be sure to take into account that the y-coordinate
     * system is inverted.
     */

    if (gc->fill_style == FillStippled && gc->stipple != None) {
      xr = width / 2.0;
      yr = height / 2.0;
    }
    else {
      xr = x + width / 2.0;
      yr = y + height / 2.0;
    }
    xstart = (int)((xr + cos(radian_start)*width/2.0) + 0.5);
    ystart = (int)((yr + sin(-radian_start)*height/2.0) + 0.5);
    xend = (int)((xr + cos(radian_end)*width/2.0) + 0.5);
    yend = (int)((yr + sin(-radian_end)*height/2.0) + 0.5);

    /*
     * Now draw a filled or open figure.  Note that we have to
     * increase the size of the bounding box by one to account for the
     * difference in pixel definitions between X and Windows.
     */

    pen = SetUpGraphicsPort(gc);
    oldPen = SelectObject(dc, pen);
    if (!fill) {
	/*
	 * Note that this call will leave a gap of one pixel at the
	 * end of the arc for thin arcs.  We can't use ArcTo because
	 * it's only supported under Windows NT.
	 */

	SetBkMode(dc, TRANSPARENT);
	Arc(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
    } else {
      brush = CreateSolidBrush(gc->foreground);

      if (gc->fill_style == FillStippled && gc->stipple != None) {
	TkWinDrawable *twdPtr = (TkWinDrawable *)gc->stipple;
	HBITMAP oldBitmap;
	HDC dcMem;
	HBRUSH oldMemBrush;
	
	if (twdPtr->type != TWD_BITMAP) {
	  Tcl_Panic("unexpected drawable type in stipple");
	}
	
	/*
	 * Select stipple pattern into destination dc.
	 */
	SetBrushOrgEx(dc, gc->ts_x_origin, gc->ts_y_origin, NULL);
	oldBrush = SelectObject(dc,
				CreatePatternBrush(twdPtr->bitmap.handle));
	
	/*
	 * Create temporary drawing surface containing a copy of the
	 * destination equal in size to the bounding box of the object.
	 */
	dcMem = CreateCompatibleDC(dc);
	oldBitmap = SelectObject(dcMem,
				 CreateCompatibleBitmap(dc, width, height));
	BitBlt(dcMem, 0, 0, width, height, dc, x, y, SRCCOPY);
	oldMemBrush = SelectObject(dcMem, brush);
	if (gc->arc_mode == ArcChord) {
	  Chord(dcMem, 0, 0, width+1, height+1, xstart, ystart, xend, yend);
	} else if ( gc->arc_mode == ArcPieSlice ) {
	  Pie(dcMem, 0, 0, width+1, height+1, xstart, ystart, xend, yend);
	}
	
	BitBlt(dc, x, y, width, height, dcMem, 0, 0, COPYFG);
	DeleteObject(SelectObject(dcMem, oldBitmap));
	DeleteObject(SelectObject(dcMem, oldMemBrush));
	DeleteObject(SelectObject(dc, oldBrush));
	DeleteDC(dcMem);
      } else {
	oldBrush = SelectObject(dc, brush);
	if (gc->arc_mode == ArcChord) {
	  Chord(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
	} else if ( gc->arc_mode == ArcPieSlice ) {
	  Pie(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend);
	}
	DeleteObject(SelectObject(dc, oldBrush));
      }
    }
    DeleteObject(SelectObject(dc, oldPen));
    TkWinReleaseDrawableDC(d, dc, &state);
}

/*
 *----------------------------------------------------------------------
 *
 * XDrawArc --
 *
 *	Draw an arc.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws an arc on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

void
ZnXDrawArc(display, d, gc, x, y, width, height, start, extent)
    Display* display;
    Drawable d;
    GC gc;
    int x;
    int y;
    unsigned int width;
    unsigned int height;
    int start;
    int extent;
{
    display->request++;

    DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 0);
}

/*
 *----------------------------------------------------------------------
 *
 * XFillArc --
 *
 *	Draw a filled arc.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Draws a filled arc on the specified drawable.
 *
 *----------------------------------------------------------------------
 */

void
ZnXFillArc(display, d, gc, x, y, width, height, start, extent)
    Display* display;
    Drawable d;
    GC gc;
    int x;
    int y;
    unsigned int width;
    unsigned int height;
    int start;
    int extent;
{
    display->request++;

    DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, 1);
}

#endif /* _WIN32 */

Added jni/tkzinc/win/makefile.vc.in.

























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Generated automatically from Makefile.in by configure.
#  Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
#
# See the file "Copyright" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# $Revision$
#
srcdir = ..
TCLTK_FULL_VER = 8.4.14
TCLTK_LIB_VER = 84
TKZINC_MAJOR = @MAJOR_VERSION@
TKZINC_MINOR = @MINOR_VERSION@
TKZINC_PATCHLVL = @PATCHLEVEL@

CC		= cl
LD		= link
CP		= copy
RM		= del
#
# The SDK lib path should be available in the
# environment variable %LIB%
libpath32	= /LIBPATH:"$(LIB)"
#
# The SDK include path should be available in the
# environment variable %INCLUDE%
include32	= /I"$(INCLUDE)" /I"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\include\GL"

#
# Default location for ActiveTcl
prefix = c:\Tcl
exec_prefix = $(prefix)

bindir = $(exec_prefix)\bin
libdir = $(exec_prefix)\lib
incdir = $(prefix)\include
mandir = $(prefix)\man\man3

windir = $(srcdir)\win
genericdir = $(srcdir)\generic
tmpdir = buildtcl

tcl_inc_dir = $(srcdir)\..\tcl$(TCLTK_FULL_VER)
tk_inc_dir = $(srcdir)\..\tk$(TCLTK_FULL_VER)
INCLUDES    = $(include32) /I$(incdir) /I$(srcdir)/generic \
              /I$(tk_inc_dir)/generic /I$(tk_inc_dir)/win /I$(tcl_inc_dir)/generic \
              /I$(tcl_inc_dir)/win /I$(tk_inc_dir)/xlib

# Assume that WISH is already INSTALLED
TCLSH		= $(bindir)\tclsh$(TCLTK_LIB_VER)
WISH		= $(bindir)\wish$(TCLTK_LIB_VER)
WIN_LIBS	= user32.lib gdi32.lib ws2_32.lib
GL_LIBS		= glu32.lib opengl32.lib
TKLIBS		= $(libdir)\tclstub$(TCLTK_LIB_VER).lib $(libdir)\tkstub$(TCLTK_LIB_VER).lib \
		        $(GL_LIBS) $(WIN_LIBS)

VERSION = \"$(TKZINC_MAJOR).$(TKZINC_MINOR).$(TKZINC_PATCHLVL)\"

#
# Recognized compilation time flags are :
#
#	PROFILE			ask for profile support
#	ATC			include code for atc specific items
#	GL			include code that need GL support.
#	GL_PRINT_CONFIG	display the detected hardware capabilities
#	GL_DAMAGE		redraw only modified areas
#	SHAPE			include code for reshaping windows.
#
DFLAGS= /DATC /DGL /DGL_PRINT_CONFIG
#DFLAGS = /DTCL_MEM_DEBUG

# Max speed
#CDEBUG = /O2 /G6 /Gs
# Debug
CDEBUG = /Zi -Od
CFLAGS = /c /W3 /nologo /YX $(CDEBUG) /D__STDC__ /DPACKAGE_VERSION=$(VERSION) /DDLL_BUILD /DBUILD_Tkzinc $(DFLAGS)
TKCPPFLAGS = /Fp$(tmpdir)\ $(INCLUDES) /DTCL_THREADS=1 /DUSE_TCL_STUBS /DUSE_TK_STUBS /D__STDC__

#LFLAGS	= /DEBUG /nologo /machine:IX86 $(libpath32) /FORCE:MULTIPLE /NODEFAULTLIB:uuid.lib /NODEFAULTLIB:OLDNAMES.lib
LFLAGS	= /DEBUG /nologo /machine:IX86 $(libpath32) /FORCE:MULTIPLE \
          /NODEFAULTLIB:uuid.lib /NODEFAULTLIB:OLDNAMES.lib

DLLENTRY = @12
DLLLFLAGS = $(LFLAGS) /entry:_DllMainCRTStartup$(DLLENTRY) /dll

TKDLLOBJS = $(tmpdir)\Track.obj $(tmpdir)\Tabular.obj \
	$(tmpdir)\Reticle.obj $(tmpdir)\Map.obj \
	$(tmpdir)\Rectangle.obj $(tmpdir)\Arc.obj \
	$(tmpdir)\Curve.obj $(tmpdir)\Item.obj  \
  $(tmpdir)\PostScript.obj \
# $(tmpdir)\perfos.obj \
	$(tmpdir)\MapInfo.obj $(tmpdir)\Attrs.obj \
	$(tmpdir)\Draw.obj $(tmpdir)\Geo.obj \
	$(tmpdir)\List.obj $(tmpdir)\Transfo.obj \
	$(tmpdir)\Group.obj $(tmpdir)\Icon.obj \
	$(tmpdir)\Text.obj $(tmpdir)\Color.obj \
	$(tmpdir)\Field.obj $(tmpdir)\Triangles.obj \
	$(tmpdir)\Window.obj $(tmpdir)\tkZinc.obj \
	$(tmpdir)\OverlapMan.obj $(tmpdir)\WinPort.obj \
	$(tmpdir)\Image.obj

DLL=Tkzinc$(TKZINC_MAJOR)$(TKZINC_MINOR)$(TKZINC_PATCHLVL).dll

$(tmpdir)/$(DLL): $(tmpdir) $(TKDLLOBJS)
	$(LD) $(DLLLFLAGS) $(TKLIBS) /OUT:$@ $(TKDLLOBJS)
	@"$(WISH)" <<
	package require Tk
	pkg_mkIndex -load Tk $(tmpdir) $(DLL)
	exit
<<

$(tmpdir):
  mkdir $(tmpdir)

{$(windir)}.c{$(tmpdir)}.obj:
	$(CC) $(TKCPPFLAGS) $(CFLAGS) -Fo$(tmpdir)\ $<

{$(genericdir)}.c{$(tmpdir)}.obj:
	$(CC) $(TKCPPFLAGS) $(CFLAGS) -Fo$(tmpdir)\ $<

mostlyclean:
	$(RM) *.bak *~ $(tmpdir)\*.obj
clean:
	$(RM) $(tmpdir)\*.obj $(tmpdir)\*.dll $(tmpdir)\*.lib $(tmpdir)\*.exp $(tmpdir)\pkgIndex.tcl $(tmpdir)\*.pch

Added jni/tkzinc/win/package.tcl.























































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
#
# This script is intended to be run in the win sub-directory
# with: tclsh build.tcl
# actions include: subst, tcl, perl, doc, wrap, clean. If nothing
# is specified all actions are performed in order.

set todo [lindex $argv 0]

set root [file join [file dirname [info script]] ..]

#
# First get the configure variable values.
#
set fid [open [file join $root configure.in]]
while { ! [eof $fid] } {
  set line [gets $fid]
  if { [regexp {^MAJOR_VERSION=(.*)$} $line dummy major] } {
    continue
  }
  if { [regexp {^MINOR_VERSION=(.*)$} $line dummy minor] } {
    continue
  }
  if { [regexp {^PATCHLEVEL=(.*)$} $line dummy patchlevel] } {
    continue
  }
}
close $fid

if { $todo eq "subst" || $todo eq "" } {
  #
  # Substitute @variables@ in the .in registred files
  # producing their expanded equivalent into files
  # without the .in extension.
  #
  puts "Performing configuration variables substitution..."

  set registredFiles {
    { . starkit.tcl }
    { win makefile.vc }
    { win Tkzinc.wxs }
  }

  set libFile "Tkzinc${major}${minor}.dll"
  set stubLibFile "Tkzincstub${major}${minor}.dll"

  #
  # Then substitute all occurences in known files
  #
  foreach t $registredFiles {
    set fid [open [file join $root [lindex $t 0] [lindex $t 1].in]]
    set fod [open [file join $root [lindex $t 0] [lindex $t 1]] w]

    while { ! [eof $fid] } {
      set line [gets $fid]
      regsub -all {@MAJOR_VERSION@} $line $major line
      regsub -all {@MINOR_VERSION@} $line $minor line
      regsub -all {@PATCHLEVEL@} $line $patchlevel line
      puts $fod $line
    }

    close $fid
    close $fod
  }
}

if { $todo eq "tcl" || $todo eq "" } {
  #
  # Make the Tcl library
  #
  set tmpdir buildtcl

  puts "Compiling the tcl variant..."

  if { [catch {exec nmake -f makefile.vc 2>log} result] } {
    puts $result
    exit
  }

  #
  # Copy the library files, it makes it easier to test in situ.
  #
  foreach f [glob -directory [file join $root library] zinc*.tcl] {
    file copy -force $f $tmpdir
  }
  #
  # Build a merged pkgIndex.tcl
  #
  set fout [open [file join $tmpdir pkgIndex.tcl] a]
  set fin [open [file join $root library pkgIndex.tcl]]
  foreach line [split [read $fin] \n] {
    if {![regexp {^\s*$|^#} $line]} {
	    puts $fout $line
    }
  }
  close $fin
  close $fout

  #
  # Create a demo script ending in .tcl
  #
  file copy -force [file join $root demos zinc-widget] [file join $tmpdir zinc-widget.tcl]
}

if { $todo eq "perl" || $todo eq "" } {
  #
  # Make the Tkzinc Perl library for windows
  #
  puts "Compiling the perl variant..."

  #
  # Create a perl build directory and copy the relevant
  # files in it.
  #
  set wd [pwd]
  set buildDir buildperl
  set make nmake

  puts "Creating temporary build structure for Tkzinc perl variant"

  if { [file exists $buildDir] } {
      file delete -force $buildDir
  }
  file mkdir $buildDir

  foreach f {t Zinc.xs demos README Zinc} {
    file copy -force [file join $root Perl $f] $buildDir
  }
  #
  # Add the version in Zinc.pm and Makefile.PL
  foreach f {Zinc.pm Makefile.PL} {
    set fid [open [file join $root Perl $f]]
    set fod [open [file join $buildDir $f] w]

    while { ! [eof $fid] } {
      set line [gets $fid]
      regsub -all SEEexport2cpan $line [format "%d.%d%02d" $major $minor $patchlevel] line
      puts $fod $line
    }

    close $fid
    close $fod
  }
  foreach f [glob -nocomplain [file join $root generic *.c] [file join $root generic *.h] \
                              [file join $root win *.c] [file join $root debian changelog] \
                              [file join $root debian copyright]] {
    file copy -force $f $buildDir
  }

  #
  # Build a .bat script for the Perl demos.
  #
  set fout [open [file join $buildDir demos zinc-demos.bat] w]
  set fin [open [file join $buildDir demos zinc-demos]]
  puts $fout {@rem = '--*-Perl-*--
@echo off
if "%OS%" == "Windows_NT" goto WinNT
perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
perl -x -S %0 %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
if %errorlevel% == 9009 echo You do not have Perl in your PATH.
if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
goto endofperl
@rem ';}
  puts $fout [read $fin]
  puts $fout {__END__
:endofperl}
  close $fin
  close $fout

  #
  # Call the perl setup and then make it.
  #
  puts "Compiling the perl variant"

  cd $buildDir
  if { [catch {exec perl Makefile.PL 2>log} result] } {
    puts $result
    exit
  }
  if { [catch {exec $make 2>log} result] } {
    puts $result
    exit
  }
  cd $wd
}


proc dochtml { root } {
  #
  # Making of the html version
  #
  set cwd [pwd]
  cd [file join $root doc]

  DocClean
  puts "First pass through htlatex."
  if { [catch {exec htlatex refman.tex refman 2>log} result] } {
    puts $result
    exit
  }
  puts "Preparing the index."
  if { [catch {exec tex {\def\filename{{refman}{idx}{4dx}{ind}}} {\input} idxmake.4ht 2>log} result] } {
    puts $result
    exit
  }
  puts "Running makeindex."
  if { [catch {exec makeindex -o refman.ind refman.4dx 2>log} result] } {
    puts $result
    exit
  }
  puts "Second pass through htlatex."
  if { [catch {exec htlatex refman.tex refman 2>log} result] } {
    puts $result
    exit
  }

  cd $cwd
}

proc docpdf { root } {
  #
  # Making of the pdf version
  #
  set cwd [pwd]
  cd [file join $root doc]

  DocClean
  puts "First pass through pdflatex."
  if { [catch {exec pdflatex refman.tex 2>log} result] } {
    puts $result
    exit
  }
  puts "Running makeindex."
  if { [catch {exec makeindex -o refman.ind refman.idx 2>log} result] } {
    puts $result
    exit
  }
  puts "Second pass through pdflatex."
  if { [catch {exec pdflatex refman.tex 2>log} result] } {
    puts $result
    exit
  }
  puts "Third pass through pdflatex."
  if { [catch {exec pdflatex refman.tex 2>log} result] } {
    puts $result
    exit
  }

  cd $cwd
}

proc DocClean { } {
  #
  # Need to get rid of some temporary files.
  #
  file delete -force log refman.aux refman.idx refman.ind refman.lof
  file delete -force refman.log refman.out refman.toc texput.log
  file delete -force idxmake.dvi idxmake.log refman.4ct refman.4dx refman.4ix
  file delete -force refman.4tc refman.dvi refman.idx refman.ilg refman.ind
  file delete -force refman.log refman.tmp refman.xref refman.lg refman.idv
}

if { $todo eq "doc" || $todo eq "" } {
  #
  # Make the pdf manual. Run the command
  # three time to make the crossrefs ok.
  #
  puts "Building the documentation..."
  docpdf $root
  dochtml $root
  DocClean
}

if { $todo eq "docpdf" } {
  docpdf $root
}

if { $todo eq "dochtml" } {
  dochtml $root
}

if { $todo eq "wrap" || $todo eq "" } {
  #
  # Wrap up the msi package.
  #
  puts "Wrapping the msi package..."

  if { [catch {exec candle Tkzinc.wxs 2>log} result] } {
    puts $result
    exit
  }
  if { [catch {exec light Tkzinc.wixobj 2>log} result] } {
    puts $result
    exit
  }
}

if { $todo eq "clean" || $todo eq "" } {
  #
  # Clean up after messing around
  #
  puts "Cleaning up..."

  file delete -force log pkgIndex.tcl zinc-widget.tcl zinc-demos.bat Tkzinc.wixobj
  file delete -force buildtcl
  file delete -force buildperl
  set cwd [pwd]
  cd [file join $root doc]
  file delete -force refman.pdf refman.css nayk0a01.png
  file delete -force [glob refman*.html]
  cd $cwd
}

Added jni/tkzinc/zinclib.d/Copyright.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
This software is the property of IntuiLab SA, France.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
  3. The name of the author may not be used to endorse or promote products
     derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Added jni/tkzinc/zinclib.d/INSTALL.































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Zinclib compilation and installation
====================================

If you want to use zinclib in your application, compile it and
read the 'README'


Compilation
-----------
A Makefile is provided for unix, macosX and mingw. A makefile.vc
is provided to compile with visual C++.
Before compiling zinclib, you need Tcl and Tk headers installed.
They must be in a standard include path (/usr/include).
All compilation is done into a tmp directory. Compilation produces
a zinclib.o file. This file can then be used in your application
as described into 'REAMDE'

To compile zinclib :
  make


Installation
------------
Installing zinclib consists in copying headers and object files into
the IntuiKit source hierarchy in order to use it in IntuiKit.

To install zinclib into Intuikit sources to use it as a library :
  make install


Tests
-----
Tests check that zinclib doesn't containy any know bug.
Tests consist in using zinclib to display items. There is not yet
any automated check. This means that tests will display their window
and closing them will go to next test.
Before compiling tests you need :

- tcl/tk >= 8.4
- TkZinc compiled for tcl usage and installed as done by IntuiKit's ThirdParty
- Tkimg compiled and installed on your system, see ThirdParty/README for more informations

To run tests :
  make test



Added jni/tkzinc/zinclib.d/Makefile.



























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
########################################
#      Makefile for zinclib            #
########################################

# default
all: zinclib





######################################################################
#           IntuiKit common Makefile                                 #
#                                                                    #
#     This software is the property of IntuiLab SA, France.          #
#                                                                    #
#     Contributors:                                                  #
#         Benoit Peccatte <peccatte@intuilab.com>                    #
#                                                                    #
######################################################################

## remove when no more in development
DEBUG :=1

##################################
# Default GNU compilation options
##################################
CXX      := g++
GCC      := g++
LIBEXT   := .so
EXE      :=
DELFILES :=

PROFILE     =
MACRO       =
LIBDIR      = ./lib
INCLUDE     = -isystem ./include
LDFLAGS     = $(PROFILE) -L$(LIBDIR)
CXXFLAGS    = -Wall -fpermissive $(MACRO) $(PROFILE) $(INCLUDE)
INCLUDES    = -fno-rtti
LIBLDFLAGS  = -shared $(LDFLAGS) -Wl,-export-dynamic
LIBCXXFLAGS = -fPIC $(CXXFLAGS)


###################################
# Automatic architecture detection
###################################
ifndef ARCH
ARCH := $(shell uname -s)
endif

# linux
ifeq ($(ARCH),Linux)
LIBEXT  := .so
MACRO   += -DLINUX
LDFLAGS += -ldl
endif

# MacOSX
ifeq ($(ARCH),Darwin)
LIBEXT  := .dylib
MACRO   += -DMACOSX_BSD
LDFLAGS += -ldl
LIBLDFLAGS  = -Wl,-single_module -dynamiclib $(LDFLAGS)
endif

# Windows cross compile
ifeq ($(ARCH),win32)
CXX     := i386-mingw32msvc-g++
GCC     := i386-mingw32msvc-gcc
LIBEXT  := .dll
EXE     := .exe
MACRO   += -DWIN32
LDFLAGS += -L$(EXPAT_HOME)
endif

# native windows 2K, XP
ifeq ($(ARCH),MINGW32_NT-5.1)
LIBEXT  := .dll
EXE     := .exe
MACRO   += -DWIN32
endif



###################
# Options handling
###################

##### DEBUG options
ifdef DEBUG
CXXFLAGS += -g
endif

##### Profiling options
ifdef PROF
PROFILE    = -pg -fprofile-arcs -ftest-coverage
DELFILES  += *.gcov *.bb *.bbg *.da gmon.out
endif

##### Purify coverage options
ifdef COV
GCC := purecov $(GCC)
DELFILES  += *.pcv
endif

##### Purify options
ifdef PURIFY
GCC := purify -view-file=pure.pv $(GCC)
DELFILES  += .pure* *_pure_* pure.pv
endif

##### Options to display more warnings
ifdef VERBOSE
CXXFLAGS += -Wctor-dtor-privacy -Wnon-virtual-dtor
CXXFLAGS += -Wold-style-cast -Woverloaded-virtual
CXXFLAGS += -Wsign-promo -Wsynth -Wsynth -pedantic -Wchar-subscripts
CXXFLAGS += -Wcomment -Wimplicit -Wmissing-braces -Wparentheses
CXXFLAGS += -Wreturn-type -Wswitch -Wtrigraphs -Wunused
CXXFLAGS += -Wreorder -Wunknown-pragmas -W -Wsign-compare
CXXFLAGS += -Wfloat-equal -Wundef -Wlarger-than-1000
CXXFLAGS += -Wpointer-arith -Wcast-qual -Wcast-align
CXXFLAGS += -Wstrict-prototypes -Wmissing-prototypes
CXXFLAGS += -Wmissing-noreturn -Wmissing-format-attribute -Wpacked
CXXFLAGS += -Wredundant-decls -Wunreachable-code -Winline
CXXFLAGS += -Wdisabled-optimization -Wconversion -Wshadow 
CXXFLAGS += -O0
ifeq ($(VERBOSE),2)
CXXFLAGS += -Wpadded -Wabi -Weffc++ -Waggregate-return -Wwrite-strings
endif
endif

##### Optimization options
ifdef OPTIMIZE
CXXFLAGS += -O$(OPTIMIZE) -Wuninitialized
endif

#########################################################
#     END  OF IntuiKit Common                           #
#########################################################

# specific options
LDFLAGS += -ltcl8.4 -ltk8.4 -lTkZinc

# easy target
zinclib: tmp/zinclib.o

tmp/zinclib.o: tmp/ZincObjects.o tmp/ZincPath.o tmp/Zinc.o
	ld -r -o $@ $^

# generic target
tmp/%.o: src/%.cpp
	@mkdir -p tmp
	$(CXX) $(LIBCXXFLAGS) -o $@ -c $<

clean:
	rm -f tmp/*.o $(PROFFILES)

# documentation
doc:
	cd src; doxygen ../doxyConfig
	mkdir -p doc
	rm -rf doc/html
	mv src/docs/* doc
	rmdir src/docs

# tests
test:
	cd test; $(MAKE)
	cd test; ./runtests.sh

.PHONY: test doc

Added jni/tkzinc/zinclib.d/README.



























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Zinclib
=======

Zinclib is a library that is made to use TkZinc into C++ code. It is
a .o file that can be included directly into your executable.

Zinclib has been contributed by IntuiLab (www.intuilab.com) to the open software 
community and is available as open software under the same licence as Zinc.


Directory structure
-------------------

- src : contains C++ sources of Zinclib

- tmp : will contain temporary compilation file and the final zinclib.o

- test : contains Zinclib tests' sources

- doc : contains doxygen generated documentation and some examples of
  Zinclib usage

- gen.pl is a file that have been used to generate some of the c++
source from TkZinc source.


Code
----

API documentation is available into the doc directory as doxygen
files. To use Zinclib in your own code, the 'HOWTO' file explains the
basic on getting Zinclib working.


Compilation with zinclib
------------------------

Before using zinclib into your application you need :

- tcl/tk >= 8.4
- TkZinc compiled for tcl usage and installed
- zinclib.o made as described into 'INSTALL'

zinclib is a .o file because this is the easiest way to compile and
use. This may change. To use a .o file just add it to your link
command during the compilation of your applicaion.

To link with zinklib you will need to add these option to your linker :

  -ltcl -ltk -lTkZinc zinclib.o


Notes :

- On some plateforms it can be -ltcl8.4 and -ltk8.4 if the linker
  doesn't find tcl and tk.
- You need to have tkzinc compiled for TCL under the name libTkZinc.<ext>
  in your library search path. 

- this software is still in its first release, e.g. this installation process 
  is still incomplete.

Added jni/tkzinc/zinclib.d/doc/HOWTO.

















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
How to use zinclib
==================

Required lines
--------------

To use zinclib in you code you need to include zinclib :

 #include "Zinc.hpp"

Then you must load the tcl interpreter and the zinc library :

 Zinc::load (argv[0]);


Zinc usage
----------

First create a zinc widget. Each widget has its own windows and
instantly visible. 

  Zinc* zn = new Zinc (ZINC_BACKEND_OPENGL);


All available functions are in Zinc.hpp and ZincPath.hpp
You can change and read properties of the widget with set and get
commands. Ex :

  zn->setWidth (640);


To draw in the widget, you need to create items uning itemCreate
functions. The parent group can be NULL, in which case, the default
one will be used.

  ZincItem* item = zn->itemCreateRectangle (NULL, 10, 10, 100, 100);

To change item property, use itemSet functions.

  zn->itemSetFilled (item, true);

To remove an item use itemRemove

  zn->itemRemove (item);

Don't forget do delete item returned by itemCreate. This is different
from removing it from zinc. Usualy, delete item is called after
removing it, but you can delete it whenever you want.


Many zinc function can take a tag as an argument. To use such a tag,
create it using createTag.

  ZincItem* tag = zn->createTag ("tag");
  zn->itemSetFilled (tag, true);

Added jni/tkzinc/zinclib.d/doc/html/ZincExtern_8hpp-source.html.



























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincExtern.hpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincExtern.hpp</h1><a href="ZincExtern_8hpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 
00015 <span class="preprocessor">#include &lt;tcl.h&gt;</span>
00016 
00017 <span class="preprocessor">#ifndef ZINC_EXTERN</span>
00018 <span class="preprocessor"></span><span class="preprocessor">#define ZINC_EXTERN</span>
00019 <span class="preprocessor"></span>
00020 
00021 <span class="comment">// those are function have been created within a C compiler</span>
00022 <span class="keyword">extern</span> <span class="stringliteral">"C"</span>
00023 {
00024 
00025   <span class="comment">//The TkZinc function that initialises tkzinc</span>
00026   <span class="keywordtype">int</span> <a class="code" href="ZincExtern_8hpp.html#a1">Tkzinc_Init</a>(Tcl_Interp *interp);
00027 
00028   <span class="comment">//The TkZinc function that creates a zinc object</span>
00029   <span class="keywordtype">int</span> <a class="code" href="ZincExtern_8hpp.html#a2">ZincObjCmd</a>(ClientData client_data,    <span class="comment">// Main window associated with interpreter.</span>
00030                  Tcl_Interp *interp,        <span class="comment">// Current interpreter. </span>
00031                  <span class="keywordtype">int</span>        argc,           <span class="comment">// Number of arguments.</span>
00032                  Tcl_Obj   *CONST  args[]); <span class="comment">// Argument objects.</span>
00033 
00034   <span class="comment">//The TkZinc function that is called by tcl when calling ".zinc fct ..."</span>
00035   <span class="keyword">typedef</span> int (*WidgetObjCmd)
<a name="l00036"></a><a class="code" href="ZincExtern_8hpp.html#a0">00036</a>                    (ClientData client_data,   <span class="comment">// Information about the widget.</span>
00037                     Tcl_Interp *interp,       <span class="comment">// Current interpreter.</span>
00038                     <span class="keywordtype">int</span>        argc,          <span class="comment">// Number of arguments.</span>
00039                     Tcl_Obj    *CONST args[]) <span class="comment">// Argument objects.</span>
00040           __attribute__((cdecl));
00041 
00042 }
00043 
00044 <span class="preprocessor">#endif</span>
00045 <span class="preprocessor"></span>
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincExtern_8hpp.html.

















































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincExtern.hpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincExtern.hpp File Reference</h1>
<p>
<code>#include &lt;tcl.h&gt;</code><br>

<p>
<a href="ZincExtern_8hpp-source.html">Go to the source code of this file.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Typedefs</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>typedef int(*&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincExtern_8hpp.html#a0">WidgetObjCmd</a> )(ClientData client_data, Tcl_Interp *interp, int argc, Tcl_Obj *CONST args[]) __attribute__((cdecl))</td></tr>

<tr><td colspan=2><br><h2>Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincExtern_8hpp.html#a1">Tkzinc_Init</a> (Tcl_Interp *interp)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincExtern_8hpp.html#a2">ZincObjCmd</a> (ClientData client_data, Tcl_Interp *interp, int argc, Tcl_Obj *CONST args[])</td></tr>

</table>
<hr><h2>Typedef Documentation</h2>
<a name="a0" doxytag="ZincExtern.hpp::WidgetObjCmd"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> typedef int(* <a class="el" href="ZincExtern_8hpp.html#a0">WidgetObjCmd</a>)(ClientData client_data, Tcl_Interp *interp, int argc, Tcl_Obj *CONST args[]) __attribute__((cdecl))
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr><h2>Function Documentation</h2>
<a name="a1" doxytag="ZincExtern.hpp::Tkzinc_Init"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Tkzinc_Init </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">Tcl_Interp *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>interp</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<a class="el" href="ZincExtern_8hpp.html">ZincExtern.hpp</a> zinclib<p>
This software is the property of IntuiLab SA, France. See at the end of the file for the complete copyright notice<p>
Here we create TkZinc library headers since they don't exist<p>
08/03/05<p>
Contributors: Benoit Peccatte &lt;<a href="mailto:peccatte@intuilab.com">peccatte@intuilab.com</a>&gt;     </td>
  </tr>
</table>
<a name="a2" doxytag="ZincExtern.hpp::ZincObjCmd"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int ZincObjCmd </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">ClientData&nbsp;</td>
          <td class="mdname" nowrap> <em>client_data</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>Tcl_Interp *&nbsp;</td>
          <td class="mdname" nowrap> <em>interp</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>argc</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>Tcl_Obj *CONST&nbsp;</td>
          <td class="mdname" nowrap> <em>args</em>[]</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincInternal_8hpp-source.html.













































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincInternal.hpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincInternal.hpp</h1><a href="ZincInternal_8hpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 
00017 <span class="preprocessor">#include &lt;string&gt;</span>
00018 
00019 <span class="preprocessor">#include "<a class="code" href="ZincObjects_8hpp.html">ZincObjects.hpp</a>"</span>
00020 <span class="preprocessor">#ifndef BAZAR</span>
00021 <span class="preprocessor"></span><span class="preprocessor">#define BAZAR</span>
00022 <span class="preprocessor"></span>
<a name="l00023"></a><a class="code" href="ZincInternal_8hpp.html#a0">00023</a> <span class="preprocessor">#define MAX_NUM_LENGTH 32</span>
00024 <span class="preprocessor"></span>
00025 <span class="comment">// The base name of the TCL function that serve for callbacks</span>
<a name="l00026"></a><a class="code" href="ZincInternal_8hpp.html#a1">00026</a> <span class="preprocessor">#define Z_TCLCB "zincTclCb"</span>
00027 <span class="preprocessor"></span>
00038 <span class="comment">// make a boolean object</span>
<a name="l00039"></a><a class="code" href="ZincInternal_8hpp.html#a2">00039</a> <span class="preprocessor">#define Z_BOO_POOL(no, value) ( Tcl_SetBooleanObj (pool[no], value), pool[no] )</span>
00040 <span class="preprocessor"></span><span class="comment">// make an integer object</span>
<a name="l00041"></a><a class="code" href="ZincInternal_8hpp.html#a3">00041</a> <span class="preprocessor">#define Z_INT_POOL(no, value) ( Tcl_SetIntObj (pool[no], value), pool[no] )</span>
00042 <span class="preprocessor"></span><span class="comment">// make a double object</span>
<a name="l00043"></a><a class="code" href="ZincInternal_8hpp.html#a4">00043</a> <span class="preprocessor">#define Z_DBL_POOL(no, value) ( Tcl_SetDoubleObj (pool[no], value), pool[no] )</span>
00044 <span class="preprocessor"></span><span class="comment">// make a string object</span>
<a name="l00045"></a><a class="code" href="ZincInternal_8hpp.html#a5">00045</a> <span class="preprocessor">#define Z_STR_POOL(no, value, length) ( Tcl_SetStringObj (pool[no],       \</span>
00046 <span class="preprocessor">                                                          value, length), \</span>
00047 <span class="preprocessor">                                        pool[no] )</span>
00048 <span class="preprocessor"></span>
<a name="l00057"></a><a class="code" href="ZincInternal_8hpp.html#a6">00057</a> <span class="preprocessor">#define Z_LST_POOL(no, value, size) ( Tcl_SetListObj (pool[no], size, value),\</span>
00058 <span class="preprocessor">                                      pool[no] )</span>
00059 <span class="preprocessor"></span>
<a name="l00068"></a><a class="code" href="ZincInternal_8hpp.html#a7">00068</a> <span class="preprocessor">#define Z_CLEANLIST(no) Tcl_SetIntObj (pool[no], 0)</span>
00069 <span class="preprocessor"></span>
00070 
00076 <span class="comment">//create an option object (value prefixed by '-')</span>
<a name="l00077"></a><a class="code" href="ZincInternal_8hpp.html#a8">00077</a> <span class="preprocessor">#define Z_DEFINE_ZOPT(string) Tcl_Obj* ZOPT_##string = Tcl_NewStringObj ("-" #string, -1);</span>
00078 <span class="preprocessor"></span><span class="comment">//create a function object</span>
<a name="l00079"></a><a class="code" href="ZincInternal_8hpp.html#a9">00079</a> <span class="preprocessor">#define Z_DEFINE_ZFCT(string) Tcl_Obj* ZFCT_##string = Tcl_NewStringObj (#string, -1);</span>
00080 <span class="preprocessor"></span><span class="comment">//create an item object</span>
<a name="l00081"></a><a class="code" href="ZincInternal_8hpp.html#a10">00081</a> <span class="preprocessor">#define Z_DEFINE_ZITM(string) Tcl_Obj* ZITM_##string = Tcl_NewStringObj (#string, -1);</span>
00082 <span class="preprocessor"></span>
<a name="l00089"></a><a class="code" href="ZincInternal_8hpp.html#a11">00089</a> <span class="preprocessor">#define Z_PARENTGROUP(parentGroup)  \</span>
00090 <span class="preprocessor">  ( (parentGroup != NULL) ? parentGroup-&gt;object : DEFAULT_GROUP_OBJ );</span>
00091 <span class="preprocessor"></span>
<a name="l00097"></a><a class="code" href="ZincInternal_8hpp.html#a12">00097</a> <span class="keyword">inline</span> std::string <a class="code" href="ZincInternal_8hpp.html#a12">itos</a> (<span class="keywordtype">int</span> integer)
00098 {
00099   <span class="keywordtype">char</span> tmp[<a class="code" href="ZincInternal_8hpp.html#a0">MAX_NUM_LENGTH</a>];
00100   <span class="comment">// use standard function to convert</span>
00101   <span class="keywordflow">if</span> (snprintf (tmp, <a class="code" href="ZincInternal_8hpp.html#a0">MAX_NUM_LENGTH</a>, <span class="stringliteral">"%d"</span>, integer) &lt; 0)
00102   {
00103     <span class="keywordflow">throw</span> <a class="code" href="classZincException.html">ZincException</a> (<span class="stringliteral">"Error converting integer"</span>, __FILE__, __LINE__ );
00104   }
00105   <span class="keywordflow">return</span> std::string (tmp);
00106 }
00107 
<a name="l00113"></a><a class="code" href="ZincInternal_8hpp.html#a13">00113</a> <span class="keyword">inline</span> std::string <a class="code" href="ZincInternal_8hpp.html#a13">ltos</a> (<span class="keywordtype">long</span> l)
00114 {
00115   <span class="keywordtype">char</span> tmp[<a class="code" href="ZincInternal_8hpp.html#a0">MAX_NUM_LENGTH</a>];
00116   <span class="comment">// use standard function to convert</span>
00117   <span class="keywordflow">if</span> (snprintf (tmp, <a class="code" href="ZincInternal_8hpp.html#a0">MAX_NUM_LENGTH</a>, <span class="stringliteral">"%ld"</span>, l) &lt; 0)
00118   {
00119     <span class="keywordflow">throw</span> <a class="code" href="classZincException.html">ZincException</a> (<span class="stringliteral">"Error converting long"</span>, __FILE__, __LINE__ );
00120   }
00121   <span class="keywordflow">return</span> std::string (tmp);
00122 }
00123 
<a name="l00129"></a><a class="code" href="ZincInternal_8hpp.html#a14">00129</a> <span class="keyword">inline</span> std::string <a class="code" href="ZincInternal_8hpp.html#a14">dtos</a> (<span class="keywordtype">double</span> d)
00130 {
00131   <span class="keywordtype">char</span> tmp[<a class="code" href="ZincInternal_8hpp.html#a0">MAX_NUM_LENGTH</a>];
00132   <span class="comment">// use standard function to convert</span>
00133   <span class="keywordflow">if</span> (snprintf (tmp, <a class="code" href="ZincInternal_8hpp.html#a0">MAX_NUM_LENGTH</a>, <span class="stringliteral">"%f"</span>, d) &lt; 0)
00134   {
00135     <span class="keywordflow">throw</span> <a class="code" href="classZincException.html">ZincException</a> (<span class="stringliteral">"Error converting double"</span>, __FILE__, __LINE__ );
00136   }
00137   <span class="keywordflow">return</span> std::string (tmp);
00138 }
00139 
00156 <span class="preprocessor">#endif</span>
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincInternal_8hpp.html.















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincInternal.hpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincInternal.hpp File Reference</h1>
<p>
<code>#include &lt;string&gt;</code><br>
<code>#include "<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>"</code><br>

<p>
<a href="ZincInternal_8hpp-source.html">Go to the source code of this file.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Defines</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a0">MAX_NUM_LENGTH</a>&nbsp;&nbsp;&nbsp;32</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a1">Z_TCLCB</a>&nbsp;&nbsp;&nbsp;"zincTclCb"</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a2">Z_BOO_POOL</a>(no, value)&nbsp;&nbsp;&nbsp;( Tcl_SetBooleanObj (pool[no], value), pool[no] )</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a3">Z_INT_POOL</a>(no, value)&nbsp;&nbsp;&nbsp;( Tcl_SetIntObj (pool[no], value), pool[no] )</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a4">Z_DBL_POOL</a>(no, value)&nbsp;&nbsp;&nbsp;( Tcl_SetDoubleObj (pool[no], value), pool[no] )</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a5">Z_STR_POOL</a>(no, value, length)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a6">Z_LST_POOL</a>(no, value, size)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a7">Z_CLEANLIST</a>(no)&nbsp;&nbsp;&nbsp;Tcl_SetIntObj (pool[no], 0)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a8">Z_DEFINE_ZOPT</a>(string)&nbsp;&nbsp;&nbsp;Tcl_Obj* ZOPT_##string = Tcl_NewStringObj ("-" #string, -1);</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a9">Z_DEFINE_ZFCT</a>(string)&nbsp;&nbsp;&nbsp;Tcl_Obj* ZFCT_##string = Tcl_NewStringObj (#string, -1);</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a10">Z_DEFINE_ZITM</a>(string)&nbsp;&nbsp;&nbsp;Tcl_Obj* ZITM_##string = Tcl_NewStringObj (#string, -1);</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a11">Z_PARENTGROUP</a>(parentGroup)&nbsp;&nbsp;&nbsp;( (parentGroup != NULL) ? parentGroup-&gt;object : <a class="el" href="Zinc_8cpp.html#a4">DEFAULT_GROUP_OBJ</a> );</td></tr>

<tr><td colspan=2><br><h2>Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>std::string&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a12">itos</a> (int integer)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>std::string&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a13">ltos</a> (long l)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>std::string&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincInternal_8hpp.html#a14">dtos</a> (double d)</td></tr>

</table>
<hr><h2>Define Documentation</h2>
<a name="a0" doxytag="ZincInternal.hpp::MAX_NUM_LENGTH"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define MAX_NUM_LENGTH&nbsp;&nbsp;&nbsp;32
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<a class="el" href="ZincInternal_8hpp.html">ZincInternal.hpp</a> zinclib<p>
This software is the property of IntuiLab SA, France. See at the end of the file for the complete copyright notice<p>
Here we defines macros and constants that are only used within Zinclib code<p>
08/03/05<p>
Contributors: Benoit Peccatte &lt;<a href="mailto:peccatte@intuilab.com">peccatte@intuilab.com</a>&gt; David Thevenin &lt;<a href="mailto:thevenin@intuilab.com">thevenin@intuilab.com</a>&gt;     </td>
  </tr>
</table>
<a name="a2" doxytag="ZincInternal.hpp::Z_BOO_POOL"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_BOO_POOL</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">no,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>value&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;( Tcl_SetBooleanObj (pool[no], value), pool[no] )
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
These are macro for shortness and readability of code. They take one Tcl_Obj from the pool and put one value into it. This object is returned. They all have the same signature.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>no</em>&nbsp;</td><td>the id of the Tcl_Obj to take within the pool (max is ZINC_POOL_COUNT-1) </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the value to put in the extracted object </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the object from the pool </dd></dl>
    </td>
  </tr>
</table>
<a name="a7" doxytag="ZincInternal.hpp::Z_CLEANLIST"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_CLEANLIST</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">no&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;Tcl_SetIntObj (pool[no], 0)
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Clear a list object. Tcl_Obj used in a list object have a refcount incremented and as such can't be reused for anything else. To free those object you need to clean the list object after use.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>no</em>&nbsp;</td><td>the id of a Tcl_Obj within the pool which contains a list to clear </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a4" doxytag="ZincInternal.hpp::Z_DBL_POOL"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_DBL_POOL</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">no,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>value&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;( Tcl_SetDoubleObj (pool[no], value), pool[no] )
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a9" doxytag="ZincInternal.hpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_DEFINE_ZFCT</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">string&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;Tcl_Obj* ZFCT_##string = Tcl_NewStringObj (#string, -1);
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a10" doxytag="ZincInternal.hpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_DEFINE_ZITM</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">string&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;Tcl_Obj* ZITM_##string = Tcl_NewStringObj (#string, -1);
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a8" doxytag="ZincInternal.hpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_DEFINE_ZOPT</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">string&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;Tcl_Obj* ZOPT_##string = Tcl_NewStringObj ("-" #string, -1);
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a constant Tcl_Obj that can be reused as a parameter later<p>
string define the name and the value ov the object     </td>
  </tr>
</table>
<a name="a3" doxytag="ZincInternal.hpp::Z_INT_POOL"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_INT_POOL</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">no,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>value&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;( Tcl_SetIntObj (pool[no], value), pool[no] )
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a6" doxytag="ZincInternal.hpp::Z_LST_POOL"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_LST_POOL</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">no,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>value,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>size&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Value:</b><div class="fragment"><pre>( Tcl_SetListObj (pool[no], size, value),\
                                      pool[no] )
</pre></div>Make a list object<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>no</em>&nbsp;</td><td>the id of the Tcl_Obj to take within the pool </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>a table of pointer to Tcl_Obj to put in the list </td></tr>
    <tr><td valign=top><em>size</em>&nbsp;</td><td>the number objects in the table </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the list object from the pool </dd></dl>
    </td>
  </tr>
</table>
<a name="a11" doxytag="ZincInternal.hpp::Z_PARENTGROUP"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_PARENTGROUP</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">parentGroup&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>&nbsp;&nbsp;&nbsp;( (parentGroup != NULL) ? parentGroup-&gt;object : <a class="el" href="Zinc_8cpp.html#a4">DEFAULT_GROUP_OBJ</a> );
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Macro to return a parentGroup Tcl_Obj. If a NULL is group given, it returns the default one.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>the parent group to take </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a5" doxytag="ZincInternal.hpp::Z_STR_POOL"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_STR_POOL</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">no,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>value,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>length&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Value:</b><div class="fragment"><pre>( Tcl_SetStringObj (pool[no],       \
                                                          value, length), \
                                        pool[no] )
</pre></div>    </td>
  </tr>
</table>
<a name="a1" doxytag="ZincInternal.hpp::Z_TCLCB"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define Z_TCLCB&nbsp;&nbsp;&nbsp;"zincTclCb"
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr><h2>Function Documentation</h2>
<a name="a14" doxytag="ZincInternal.hpp::dtos"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> std::string dtos </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>d</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [inline]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Convert a double to a string<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>double</em>&nbsp;</td><td>the integer to convert </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a12" doxytag="ZincInternal.hpp::itos"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> std::string itos </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>integer</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [inline]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Convert an integer to a string<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>integer</em>&nbsp;</td><td>the integer to convert </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a13" doxytag="ZincInternal.hpp::ltos"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> std::string ltos </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">long&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>l</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [inline]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Convert a long to a string<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>l</em>&nbsp;</td><td>the long to convert </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincObjects_8cpp.html.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincObjects.cpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincObjects.cpp File Reference</h1>
<p>
<code>#include "<a class="el" href="ZincInternal_8hpp-source.html">ZincInternal.hpp</a>"</code><br>
<code>#include "<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>"</code><br>
<code>#include "<a class="el" href="Zinc_8hpp-source.html">Zinc.hpp</a>"</code><br>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincObjects_8hpp-source.html.









































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincObjects.hpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincObjects.hpp</h1><a href="ZincObjects_8hpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 
00016 <span class="preprocessor">#include "<a class="code" href="ZincTypes_8hpp.html">ZincTypes.hpp</a>"</span>
00017 
00018 <span class="preprocessor">#include &lt;exception&gt;</span>
00019 <span class="preprocessor">#include &lt;string&gt;</span>
00020 <span class="preprocessor">#include &lt;tcl.h&gt;</span>
00021 
00022 <span class="preprocessor">#ifndef ZINC_OBJECTS</span>
00023 <span class="preprocessor"></span><span class="preprocessor">#define ZINC_OBJECTS</span>
00024 <span class="preprocessor"></span>
00025 <span class="comment">// Object representing a zinc item</span>
<a name="l00026"></a><a class="code" href="classZincItem.html">00026</a> <span class="keyword">class </span><a class="code" href="classZincItem.html">ZincItem</a>
00027 {
00028 <span class="keyword">protected</span>:
00032   <a class="code" href="classZincItem.html#b0">ZincItem</a> ();
00033 
00034 <span class="keyword">public</span>:
<a name="l00035"></a><a class="code" href="classZincItem.html#o0">00035</a>   Tcl_Obj *<a class="code" href="classZincItem.html#o0">object</a>;  <span class="comment">//the object we are storing</span>
00036 
00042   <a class="code" href="classZincItem.html#b0">ZincItem</a> (Tcl_Obj *obj);
00043 
00047   <span class="keyword">virtual</span> <a class="code" href="classZincItem.html#a1">~ZincItem</a> ();
00048 };
00049 
00050 <span class="comment">// Object representing a zinc image</span>
<a name="l00051"></a><a class="code" href="classZincImage.html">00051</a> <span class="keyword">class </span><a class="code" href="classZincImage.html">ZincImage</a> : <span class="keyword">public</span> <a class="code" href="classZincItem.html">ZincItem</a>
00052 {
00056   <a class="code" href="classZincImage.html#a0">ZincImage</a> ();
00057 
00058   <span class="keywordtype">bool</span> madeFromInternal;
00059 
00060 <span class="keyword">public</span>:
00066   <a class="code" href="classZincImage.html#a0">ZincImage</a> (Tcl_Obj *obj);
00067 
00073   <a class="code" href="classZincImage.html#a0">ZincImage</a> (Tcl_Obj *obj, <span class="keywordtype">bool</span> internal);
00074 
00078   <span class="keyword">virtual</span> <a class="code" href="classZincImage.html#a2">~ZincImage</a> ();
00079 };
00080 
00081 <span class="comment">// Object representing a zinc bitmap</span>
<a name="l00082"></a><a class="code" href="classZincBitmap.html">00082</a> <span class="keyword">class </span><a class="code" href="classZincBitmap.html">ZincBitmap</a> : <span class="keyword">public</span> <a class="code" href="classZincItem.html">ZincItem</a>
00083 {
00087   <a class="code" href="classZincBitmap.html#a0">ZincBitmap</a> ();
00088 
00089   <span class="keywordtype">bool</span> madeFromInternal;
00090 
00091 <span class="keyword">public</span>:
00097   <a class="code" href="classZincBitmap.html#a0">ZincBitmap</a> (Tcl_Obj *obj);
00098 
00104   <a class="code" href="classZincBitmap.html#a0">ZincBitmap</a> (Tcl_Obj *obj, <span class="keywordtype">bool</span> internal);
00105 
00111   <a class="code" href="classZincBitmap.html#a0">ZincBitmap</a> (<a class="code" href="ZincTypes_8hpp.html#a0">String</a> name);
00112   
00116   <span class="keyword">virtual</span> <a class="code" href="classZincBitmap.html#a3">~ZincBitmap</a> ();
00117 };
00118 
00119 <span class="comment">// Object representing a zinc font</span>
<a name="l00120"></a><a class="code" href="classZincFont.html">00120</a> <span class="keyword">class </span><a class="code" href="classZincFont.html">ZincFont</a>
00121 {
00125   <a class="code" href="classZincFont.html#a0">ZincFont</a> ();
00126 
00127 <span class="keyword">public</span>:
<a name="l00128"></a><a class="code" href="classZincFont.html#o0">00128</a>   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZincFont.html#o0">name</a>;
00129 
00133   <a class="code" href="classZincFont.html#a0">ZincFont</a> (<span class="keyword">const</span> <span class="keywordtype">char</span> *font);
00134 
00135 };
00136 
<a name="l00140"></a><a class="code" href="classZincException.html">00140</a> <span class="keyword">class </span><a class="code" href="classZincException.html">ZincException</a> : <span class="keyword">public</span> std::exception
00141 {
00142 
00143 <span class="keyword">private</span>:
00144   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> msg;   <span class="comment">// the exception message</span>
00145   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> file;  <span class="comment">// file where exception have been caught</span>
00146   <span class="keywordtype">int</span> line;     <span class="comment">// line where exception have been caught</span>
00147 
00148 <span class="keyword">public</span>:
00154   <a class="code" href="classZincException.html#a0">ZincException</a> (<a class="code" href="ZincTypes_8hpp.html#a0">String</a> msg, <span class="keywordtype">char</span> *file, <span class="keywordtype">int</span> lineNo);
00155 
00161   <a class="code" href="classZincException.html#a0">ZincException</a> (<span class="keyword">const</span> <a class="code" href="classZincException.html">ZincException</a> &amp;exception);
00162 
00166   <span class="keyword">virtual</span> <a class="code" href="classZincException.html#a2">~ZincException</a> () <span class="keywordflow">throw</span>();
00167 
00173   <span class="keyword">const</span> <span class="keywordtype">char</span>* <a class="code" href="classZincException.html#a3">what</a> () <span class="keyword">const</span> <span class="keywordflow">throw</span> ();
00174 };
00175 
00176 <span class="preprocessor">#endif</span>
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincObjects_8hpp.html.







































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincObjects.hpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincObjects.hpp File Reference</h1>
<p>
<code>#include "<a class="el" href="ZincTypes_8hpp-source.html">ZincTypes.hpp</a>"</code><br>
<code>#include &lt;exception&gt;</code><br>
<code>#include &lt;string&gt;</code><br>
<code>#include &lt;tcl.h&gt;</code><br>

<p>
<a href="ZincObjects_8hpp-source.html">Go to the source code of this file.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Compounds</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>class &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincBitmap.html">ZincBitmap</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>class &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincException.html">ZincException</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>class &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincFont.html">ZincFont</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>class &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincImage.html">ZincImage</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>class &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincItem.html">ZincItem</a></td></tr>

</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincPath_8cpp.html.



























































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincPath.cpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincPath.cpp File Reference</h1>
<p>
<code>#include "<a class="el" href="Zinc_8hpp-source.html">Zinc.hpp</a>"</code><br>
<code>#include "<a class="el" href="ZincInternal_8hpp-source.html">ZincInternal.hpp</a>"</code><br>
<code>#include &lt;math.h&gt;</code><br>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>double&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincPath_8cpp.html#a1">modulo</a> (double d, double m)</td></tr>

<tr><td colspan=2><br><h2>Variables</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>const double&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincPath_8cpp.html#a0">convertRatio</a> = atan2 (1., 1.) * 4. / 180.</td></tr>

</table>
<hr><h2>Function Documentation</h2>
<a name="a1" doxytag="ZincPath.cpp::modulo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> double modulo </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname" nowrap> <em>d</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>m</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"><code> [inline]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Calculate d  m for doubles this is because the C  works only for integers     </td>
  </tr>
</table>
<hr><h2>Variable Documentation</h2>
<a name="a0" doxytag="ZincPath.cpp::convertRatio"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const double <a class="el" href="ZincPath_8cpp.html#a0">convertRatio</a> = atan2 (1., 1.) * 4. / 180.
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Path.cpp zinclib<p>
This software is the property of IntuiLab SA, France. See at the end of the file for the complete copyright notice<p>
Here we defines The <a class="el" href="classZincPath.html">ZincPath</a> object<p>
08/03/05<p>
Contributors: Benoit Peccatte &lt;<a href="mailto:peccatte@intuilab.com">peccatte@intuilab.com</a>&gt;     </td>
  </tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincPath_8hpp-source.html.

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincPath.hpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincPath.hpp</h1><a href="ZincPath_8hpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 
00015 <span class="preprocessor">#include "<a class="code" href="ZincTypes_8hpp.html">ZincTypes.hpp</a>"</span>
00016 
00017 <span class="preprocessor">#include &lt;list&gt;</span>
00018 <span class="preprocessor">#include &lt;tcl.h&gt;</span>
00019 
00020 <span class="preprocessor">#ifndef ZINC_PATH</span>
00021 <span class="preprocessor"></span><span class="preprocessor">#define ZINC_PATH</span>
00022 <span class="preprocessor"></span>
<a name="l00023"></a><a class="code" href="classZincPath.html">00023</a> <span class="keyword">class </span><a class="code" href="classZincPath.html">ZincPath</a>
00024 {
00025   <span class="keywordtype">double</span> firstX, firstY;     <span class="comment">//first point's coordinate</span>
00026   <span class="keywordtype">double</span> lastX, lastY;       <span class="comment">//last point's coordinate</span>
00027   Tcl_Obj* path;             <span class="comment">//list of points</span>
00028 
00035   <span class="keyword">inline</span> <span class="keywordtype">void</span> addPoint (<span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y, <span class="keywordtype">bool</span> c);
00036 
00051   <span class="keywordtype">void</span> convertFromSvg (<span class="keywordtype">double</span> x0, <span class="keywordtype">double</span> y0, <span class="keywordtype">double</span> &amp;rx, <span class="keywordtype">double</span> &amp;ry, <span class="keywordtype">double</span> &amp;phi,
00052                        <span class="keywordtype">bool</span> larcgeArc, <span class="keywordtype">bool</span> sweep, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y,
00053                        <span class="keywordtype">double</span> &amp;cx, <span class="keywordtype">double</span> &amp;cy, <span class="keywordtype">double</span> &amp;theta, <span class="keywordtype">double</span> &amp;delta);
00054 
00055 
00056 <span class="keyword">public</span>:
00062   <a class="code" href="classZincPath.html#a0">ZincPath</a> (<span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
00063 
00069   <a class="code" href="classZincPath.html#a1">~ZincPath</a> ();
00070 
00071   <span class="comment">/******************************************</span>
00072 <span class="comment">       ZincPath manipulation</span>
00073 <span class="comment">  ******************************************/</span>
00077   <span class="keywordtype">void</span> <a class="code" href="classZincPath.html#a2">close</a> ();
00078 
00084   <span class="keywordtype">void</span> <a class="code" href="classZincPath.html#a3">lineTo</a> (<span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
00085 
00094   <span class="keywordtype">void</span> <a class="code" href="classZincPath.html#a4">curveTo</a> (<span class="keywordtype">double</span> cx1, <span class="keywordtype">double</span> cy1, <span class="keywordtype">double</span> cx2, <span class="keywordtype">double</span> cy2,
00095                 <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
00096 
00104   <span class="keywordtype">void</span> <a class="code" href="classZincPath.html#a5">cubicBezierTo</a> (<span class="keywordtype">double</span> cx1, <span class="keywordtype">double</span> cy1, <span class="keywordtype">double</span> cx2, <span class="keywordtype">double</span> cy2,
00105                       <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
00106 
00114   <span class="keywordtype">void</span> <a class="code" href="classZincPath.html#a6">quadraticBezierTo</a> (<span class="keywordtype">double</span> cx, <span class="keywordtype">double</span> cy, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
00115 
00126   <span class="keywordtype">void</span> <a class="code" href="classZincPath.html#a7">arcTo</a> (<span class="keywordtype">double</span> rx, <span class="keywordtype">double</span> ry, <span class="keywordtype">double</span> xAxisRotation, <span class="keywordtype">bool</span> largeArc,
00127               <span class="keywordtype">bool</span> sweepFlag, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
00128   
00135   Tcl_Obj* <a class="code" href="classZincPath.html#a8">getTable</a> ();
00136 
00137 };
00138 
00139 <span class="preprocessor">#endif</span>
00140 <span class="preprocessor"></span>
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincPath_8hpp.html.





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincPath.hpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincPath.hpp File Reference</h1>
<p>
<code>#include "<a class="el" href="ZincTypes_8hpp-source.html">ZincTypes.hpp</a>"</code><br>
<code>#include &lt;list&gt;</code><br>
<code>#include &lt;tcl.h&gt;</code><br>

<p>
<a href="ZincPath_8hpp-source.html">Go to the source code of this file.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Compounds</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>class &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html">ZincPath</a></td></tr>

</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincTypes_8hpp-source.html.







































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincTypes.hpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincTypes.hpp</h1><a href="ZincTypes_8hpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 
00015 <span class="preprocessor">#include &lt;string&gt;</span>
00016 
00017 <span class="preprocessor">#ifndef ZINC_TYPES</span>
00018 <span class="preprocessor"></span><span class="preprocessor">#define ZINC_TYPES</span>
00019 <span class="preprocessor"></span>
<a name="l00020"></a><a class="code" href="ZincTypes_8hpp.html#a0">00020</a> <span class="keyword">typedef</span> std::string <a class="code" href="ZincTypes_8hpp.html#a0">String</a>;
00021 
00022 <span class="comment">/**********************************</span>
00023 <span class="comment">   Predeclaration of Zinc types</span>
00024 <span class="comment">**********************************/</span>
00025 <span class="keyword">class </span><a class="code" href="classZinc.html">Zinc</a>;
00026 <span class="keyword">class </span><a class="code" href="classZincPath.html">ZincPath</a>;
00027 <span class="keyword">class </span><a class="code" href="classZincItem.html">ZincItem</a>;
00028 <span class="keyword">class </span><a class="code" href="classZincImage.html">ZincImage</a>;
00029 <span class="keyword">class </span><a class="code" href="classZincFont.html">ZincFont</a>;
00030 <span class="keyword">struct </span><a class="code" href="structZincEvent.html">ZincEvent</a>;
00031 
00032 <span class="comment">/*******************************************************</span>
00033 <span class="comment">     Signature to use when binding with a callback</span>
00034 <span class="comment">*******************************************************/</span>
00035 <span class="keyword">typedef</span> void (*ZincItemCallback)
<a name="l00036"></a><a class="code" href="ZincTypes_8hpp.html#a1">00036</a>              (<a class="code" href="classZinc.html">Zinc</a> *zinc,        <span class="comment">// Information about the widget.</span>
00037               <a class="code" href="classZincItem.html">ZincItem</a> *item,    <span class="comment">// the item being evented</span>
00038               <a class="code" href="structZincEvent.html">ZincEvent</a> *event,  <span class="comment">// event information</span>
00039               <span class="keywordtype">void</span> *userData);   <span class="comment">// user data provided with bind</span>
00040 
00041 <span class="keyword">typedef</span> void (*ZincWidgetCallback)
<a name="l00042"></a><a class="code" href="ZincTypes_8hpp.html#a2">00042</a>              (<a class="code" href="classZinc.html">Zinc</a> *zinc,        <span class="comment">// Information about the widget.</span>
00043               <a class="code" href="structZincEvent.html">ZincEvent</a> *event,  <span class="comment">// event information</span>
00044               <span class="keywordtype">void</span> *userData);   <span class="comment">// user data provided with bind</span>
00045 
00046 
00047 <span class="comment">/***********************************</span>
00048 <span class="comment">       Library constants</span>
00049 <span class="comment">***********************************/</span>
00050 
00051 <span class="comment">// Rendering model</span>
<a name="l00052"></a><a class="code" href="ZincTypes_8hpp.html#a3">00052</a> <span class="keyword">const</span> <span class="keywordtype">int</span> <a class="code" href="ZincTypes_8hpp.html#a3">ZINC_BACKEND_X11</a> = 0;
<a name="l00053"></a><a class="code" href="ZincTypes_8hpp.html#a4">00053</a> <span class="keyword">const</span> <span class="keywordtype">int</span> <a class="code" href="ZincTypes_8hpp.html#a4">ZINC_BACKEND_OPENGL</a> = 1;
00054 
00055 
00056 <span class="comment">/***********************************</span>
00057 <span class="comment">       Library enums</span>
00058 <span class="comment">***********************************/</span>
00059 
00060 <span class="comment">//Styles for line items</span>
<a name="l00061"></a><a class="code" href="ZincTypes_8hpp.html#a52">00061</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00062 {
00063   <a class="code" href="ZincTypes_8hpp.html#a52a5">lineStyle_simple</a> = 0,  
00064   <a class="code" href="ZincTypes_8hpp.html#a52a6">lineStyle_dashed</a>,
00065   <a class="code" href="ZincTypes_8hpp.html#a52a7">lineStyle_mixed</a>,
00066   <a class="code" href="ZincTypes_8hpp.html#a52a8">lineStyle_dotted</a>
00067 } <a class="code" href="ZincTypes_8hpp.html#a52">lineStyle</a>;
00068 
00069 <span class="comment">//Styles for line cap</span>
<a name="l00070"></a><a class="code" href="ZincTypes_8hpp.html#a53">00070</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00071 {
00072   <a class="code" href="ZincTypes_8hpp.html#a53a9">capStyle_butt</a> = 0,
00073   <a class="code" href="ZincTypes_8hpp.html#a53a10">capStyle_projecting</a>,
00074   <a class="code" href="ZincTypes_8hpp.html#a53a11">capStyle_round</a>
00075 } <a class="code" href="ZincTypes_8hpp.html#a53">capStyle</a>;
00076 
00077 <span class="comment">//List of fill rules</span>
<a name="l00078"></a><a class="code" href="ZincTypes_8hpp.html#a54">00078</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00079 {
00080   <a class="code" href="ZincTypes_8hpp.html#a54a12">fillRule_odd</a> = 0 ,
00081   <a class="code" href="ZincTypes_8hpp.html#a54a13">fillRule_nonzero</a>,
00082   <a class="code" href="ZincTypes_8hpp.html#a54a14">fillRule_positive</a>,
00083   <a class="code" href="ZincTypes_8hpp.html#a54a15">fillRule_negative</a>,
00084   <a class="code" href="ZincTypes_8hpp.html#a54a16">fillRule_abs_geq_2</a>
00085 } <a class="code" href="ZincTypes_8hpp.html#a54">fillRule</a>;
00086 
00087 <span class="comment">//list of join style</span>
<a name="l00088"></a><a class="code" href="ZincTypes_8hpp.html#a55">00088</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00089 {
00090   <a class="code" href="ZincTypes_8hpp.html#a55a17">joinStyle_bevel</a> = 0,
00091   <a class="code" href="ZincTypes_8hpp.html#a55a18">joinStyle_miter</a>,
00092   <a class="code" href="ZincTypes_8hpp.html#a55a19">joinStyle_round</a>
00093 } <a class="code" href="ZincTypes_8hpp.html#a55">joinStyle</a>;
00094 
00095 <span class="comment">//list of reliefs</span>
<a name="l00096"></a><a class="code" href="ZincTypes_8hpp.html#a56">00096</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00097 {
00098   <a class="code" href="ZincTypes_8hpp.html#a56a20">relief_flat</a> = 0,
00099   <a class="code" href="ZincTypes_8hpp.html#a56a21">relief_raised</a>,
00100   <a class="code" href="ZincTypes_8hpp.html#a56a22">relief_sunken</a>,
00101   <a class="code" href="ZincTypes_8hpp.html#a56a23">relief_ridge</a>,
00102   <a class="code" href="ZincTypes_8hpp.html#a56a24">relief_groove</a>,
00103   <a class="code" href="ZincTypes_8hpp.html#a56a25">relief_roundraised</a>,
00104   <a class="code" href="ZincTypes_8hpp.html#a56a26">relief_roundsunken</a>,
00105   <a class="code" href="ZincTypes_8hpp.html#a56a27">relief_roundridge</a>,
00106   <a class="code" href="ZincTypes_8hpp.html#a56a28">relief_roundgroove</a>,
00107   <a class="code" href="ZincTypes_8hpp.html#a56a29">relief_raisedrule</a>,
00108   <a class="code" href="ZincTypes_8hpp.html#a56a30">relief_sunkenrule</a>
00109 } <a class="code" href="ZincTypes_8hpp.html#a56">relief</a>;
00110 
00111 <span class="comment">//List of alignments</span>
<a name="l00112"></a><a class="code" href="ZincTypes_8hpp.html#a57">00112</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00113 {
00114   <a class="code" href="ZincTypes_8hpp.html#a57a31">alignment_left</a> = 0,
00115   <a class="code" href="ZincTypes_8hpp.html#a57a32">alignment_right</a>,
00116   <a class="code" href="ZincTypes_8hpp.html#a57a33">alignment_center</a>
00117 } <a class="code" href="ZincTypes_8hpp.html#a57">alignment</a>;
00118 
00119 <span class="comment">//list of anchors</span>
<a name="l00120"></a><a class="code" href="ZincTypes_8hpp.html#a58">00120</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00121 {
00122   <a class="code" href="ZincTypes_8hpp.html#a58a34">anchor_nw</a> = 0,
00123   <a class="code" href="ZincTypes_8hpp.html#a58a35">anchor_n</a>,
00124   <a class="code" href="ZincTypes_8hpp.html#a58a36">anchor_ne</a>,
00125   <a class="code" href="ZincTypes_8hpp.html#a58a37">anchor_e</a>,
00126   <a class="code" href="ZincTypes_8hpp.html#a58a38">anchor_se</a>,
00127   <a class="code" href="ZincTypes_8hpp.html#a58a39">anchor_s</a>,
00128   <a class="code" href="ZincTypes_8hpp.html#a58a40">anchor_sw</a>,
00129   <a class="code" href="ZincTypes_8hpp.html#a58a41">anchor_w</a>,
00130   <a class="code" href="ZincTypes_8hpp.html#a58a42">anchor_center</a>
00131 } <a class="code" href="ZincTypes_8hpp.html#a58">anchor</a>;
00132 
00133 <span class="comment">//actions to take when calling contour</span>
<a name="l00134"></a><a class="code" href="ZincTypes_8hpp.html#a59">00134</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00135 {
00136   <a class="code" href="ZincTypes_8hpp.html#a59a43">item_add_clockwise</a>,
00137   <a class="code" href="ZincTypes_8hpp.html#a59a44">item_add_counterclockwise</a>,
00138   <a class="code" href="ZincTypes_8hpp.html#a59a45">item_remove</a>
00139 } <a class="code" href="ZincTypes_8hpp.html#a59">itemOperator</a>;
00140 
00141 <span class="comment">//list of possible itemtypes</span>
<a name="l00142"></a><a class="code" href="ZincTypes_8hpp.html#a60">00142</a> <span class="keyword">typedef</span> <span class="keyword">enum</span>
00143 {
00144   <a class="code" href="ZincTypes_8hpp.html#a60a46">item_group</a>,
00145   <a class="code" href="ZincTypes_8hpp.html#a60a47">item_arc</a>,
00146   <a class="code" href="ZincTypes_8hpp.html#a60a48">item_text</a>,
00147   <a class="code" href="ZincTypes_8hpp.html#a60a49">item_rectangle</a>,
00148   <a class="code" href="ZincTypes_8hpp.html#a60a50">item_curve</a>,
00149   <a class="code" href="ZincTypes_8hpp.html#a60a51">item_icon</a>
00150 } <a class="code" href="ZincTypes_8hpp.html#a60">itemType</a>;
00151 
00152 <span class="comment">//informations contained in an event</span>
<a name="l00153"></a><a class="code" href="structZincEvent.html">00153</a> <span class="keyword">struct </span><a class="code" href="structZincEvent.html">ZincEvent</a>
00154 {
<a name="l00155"></a><a class="code" href="structZincEvent.html#o1">00155</a>   <span class="keywordtype">int</span> <a class="code" href="structZincEvent.html#o0">x</a>,<a class="code" href="structZincEvent.html#o1">y</a>;  <span class="comment">// pointer position  none -&gt; 0</span>
<a name="l00156"></a><a class="code" href="structZincEvent.html#o2">00156</a>   <span class="keywordtype">int</span> <a class="code" href="structZincEvent.html#o2">k</a>;    <span class="comment">// keycode           none -&gt; 0</span>
<a name="l00157"></a><a class="code" href="structZincEvent.html#o3">00157</a>   <span class="keywordtype">long</span> <a class="code" href="structZincEvent.html#o3">t</a>;   <span class="comment">// timestamp         none -&gt; 0</span>
<a name="l00158"></a><a class="code" href="structZincEvent.html#o4">00158</a>   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="structZincEvent.html#o4">K</a>; <span class="comment">// keysym            none -&gt; "??"</span>
00159 };
00160 
00161 
00162 
00163 <span class="preprocessor">#endif</span>
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/ZincTypes_8hpp.html.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincTypes.hpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincTypes.hpp File Reference</h1>
<p>
<code>#include &lt;string&gt;</code><br>

<p>
<a href="ZincTypes_8hpp-source.html">Go to the source code of this file.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Compounds</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>struct &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="structZincEvent.html">ZincEvent</a></td></tr>

<tr><td colspan=2><br><h2>Typedefs</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>typedef std::string&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a0">String</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>typedef void(*&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a1">ZincItemCallback</a> )(<a class="el" href="classZinc.html">Zinc</a> *zinc, <a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="structZincEvent.html">ZincEvent</a> *event, void *userData)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>typedef void(*&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a2">ZincWidgetCallback</a> )(<a class="el" href="classZinc.html">Zinc</a> *zinc, <a class="el" href="structZincEvent.html">ZincEvent</a> *event, void *userData)</td></tr>

<tr><td colspan=2><br><h2>Enumerations</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a52">lineStyle</a> { <a class="el" href="ZincTypes_8hpp.html#a52a5">lineStyle_simple</a> =  0, 
<a class="el" href="ZincTypes_8hpp.html#a52a6">lineStyle_dashed</a>, 
<a class="el" href="ZincTypes_8hpp.html#a52a7">lineStyle_mixed</a>, 
<a class="el" href="ZincTypes_8hpp.html#a52a8">lineStyle_dotted</a>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a53">capStyle</a> { <a class="el" href="ZincTypes_8hpp.html#a53a9">capStyle_butt</a> =  0, 
<a class="el" href="ZincTypes_8hpp.html#a53a10">capStyle_projecting</a>, 
<a class="el" href="ZincTypes_8hpp.html#a53a11">capStyle_round</a>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a54">fillRule</a> { <br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a54a12">fillRule_odd</a> =  0, 
<a class="el" href="ZincTypes_8hpp.html#a54a13">fillRule_nonzero</a>, 
<a class="el" href="ZincTypes_8hpp.html#a54a14">fillRule_positive</a>, 
<a class="el" href="ZincTypes_8hpp.html#a54a15">fillRule_negative</a>, 
<br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a54a16">fillRule_abs_geq_2</a>
<br>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a55">joinStyle</a> { <a class="el" href="ZincTypes_8hpp.html#a55a17">joinStyle_bevel</a> =  0, 
<a class="el" href="ZincTypes_8hpp.html#a55a18">joinStyle_miter</a>, 
<a class="el" href="ZincTypes_8hpp.html#a55a19">joinStyle_round</a>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a56">relief</a> { <br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a56a20">relief_flat</a> =  0, 
<a class="el" href="ZincTypes_8hpp.html#a56a21">relief_raised</a>, 
<a class="el" href="ZincTypes_8hpp.html#a56a22">relief_sunken</a>, 
<a class="el" href="ZincTypes_8hpp.html#a56a23">relief_ridge</a>, 
<br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a56a24">relief_groove</a>, 
<a class="el" href="ZincTypes_8hpp.html#a56a25">relief_roundraised</a>, 
<a class="el" href="ZincTypes_8hpp.html#a56a26">relief_roundsunken</a>, 
<a class="el" href="ZincTypes_8hpp.html#a56a27">relief_roundridge</a>, 
<br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a56a28">relief_roundgroove</a>, 
<a class="el" href="ZincTypes_8hpp.html#a56a29">relief_raisedrule</a>, 
<a class="el" href="ZincTypes_8hpp.html#a56a30">relief_sunkenrule</a>
<br>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a57">alignment</a> { <a class="el" href="ZincTypes_8hpp.html#a57a31">alignment_left</a> =  0, 
<a class="el" href="ZincTypes_8hpp.html#a57a32">alignment_right</a>, 
<a class="el" href="ZincTypes_8hpp.html#a57a33">alignment_center</a>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a58">anchor</a> { <br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a58a34">anchor_nw</a> =  0, 
<a class="el" href="ZincTypes_8hpp.html#a58a35">anchor_n</a>, 
<a class="el" href="ZincTypes_8hpp.html#a58a36">anchor_ne</a>, 
<a class="el" href="ZincTypes_8hpp.html#a58a37">anchor_e</a>, 
<br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a58a38">anchor_se</a>, 
<a class="el" href="ZincTypes_8hpp.html#a58a39">anchor_s</a>, 
<a class="el" href="ZincTypes_8hpp.html#a58a40">anchor_sw</a>, 
<a class="el" href="ZincTypes_8hpp.html#a58a41">anchor_w</a>, 
<br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a58a42">anchor_center</a>
<br>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a59">itemOperator</a> { <a class="el" href="ZincTypes_8hpp.html#a59a43">item_add_clockwise</a>, 
<a class="el" href="ZincTypes_8hpp.html#a59a44">item_add_counterclockwise</a>, 
<a class="el" href="ZincTypes_8hpp.html#a59a45">item_remove</a>
 }</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>enum &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a60">itemType</a> { <br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a60a46">item_group</a>, 
<a class="el" href="ZincTypes_8hpp.html#a60a47">item_arc</a>, 
<a class="el" href="ZincTypes_8hpp.html#a60a48">item_text</a>, 
<a class="el" href="ZincTypes_8hpp.html#a60a49">item_rectangle</a>, 
<br>
&nbsp;&nbsp;<a class="el" href="ZincTypes_8hpp.html#a60a50">item_curve</a>, 
<a class="el" href="ZincTypes_8hpp.html#a60a51">item_icon</a>
<br>
 }</td></tr>

<tr><td colspan=2><br><h2>Variables</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>const int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a3">ZINC_BACKEND_X11</a> = 0</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="ZincTypes_8hpp.html#a4">ZINC_BACKEND_OPENGL</a> = 1</td></tr>

</table>
<hr><h2>Typedef Documentation</h2>
<a name="a0" doxytag="ZincTypes.hpp::String"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> typedef std::string <a class="el" href="ZincTypes_8hpp.html#a0">String</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<a class="el" href="ZincTypes_8hpp.html">ZincTypes.hpp</a> zinclib<p>
This software is the property of IntuiLab SA, France. See at the end of the file for the complete copyright notice<p>
Here we defines types and constants that may be usefull for a zinclib user<p>
08/03/05<p>
Contributors: Benoit Peccatte &lt;<a href="mailto:peccatte@intuilab.com">peccatte@intuilab.com</a>&gt;     </td>
  </tr>
</table>
<a name="a1" doxytag="ZincTypes.hpp::ZincItemCallback"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> typedef void(* <a class="el" href="ZincTypes_8hpp.html#a1">ZincItemCallback</a>)(<a class="el" href="classZinc.html">Zinc</a> *zinc, <a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="structZincEvent.html">ZincEvent</a> *event, void *userData)
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a2" doxytag="ZincTypes.hpp::ZincWidgetCallback"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> typedef void(* <a class="el" href="ZincTypes_8hpp.html#a2">ZincWidgetCallback</a>)(<a class="el" href="classZinc.html">Zinc</a> *zinc, <a class="el" href="structZincEvent.html">ZincEvent</a> *event, void *userData)
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr><h2>Enumeration Type Documentation</h2>
<a name="a57" doxytag="ZincTypes.hpp::alignment"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a57">alignment</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a57a31" doxytag="alignment_left"></a><em>alignment_left</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a57a32" doxytag="alignment_right"></a><em>alignment_right</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a57a33" doxytag="alignment_center"></a><em>alignment_center</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a58" doxytag="ZincTypes.hpp::anchor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a58">anchor</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a58a34" doxytag="anchor_nw"></a><em>anchor_nw</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a35" doxytag="anchor_n"></a><em>anchor_n</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a36" doxytag="anchor_ne"></a><em>anchor_ne</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a37" doxytag="anchor_e"></a><em>anchor_e</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a38" doxytag="anchor_se"></a><em>anchor_se</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a39" doxytag="anchor_s"></a><em>anchor_s</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a40" doxytag="anchor_sw"></a><em>anchor_sw</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a41" doxytag="anchor_w"></a><em>anchor_w</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a58a42" doxytag="anchor_center"></a><em>anchor_center</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a53" doxytag="ZincTypes.hpp::capStyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a53">capStyle</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a53a9" doxytag="capStyle_butt"></a><em>capStyle_butt</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a53a10" doxytag="capStyle_projecting"></a><em>capStyle_projecting</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a53a11" doxytag="capStyle_round"></a><em>capStyle_round</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a54" doxytag="ZincTypes.hpp::fillRule"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a54">fillRule</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a54a12" doxytag="fillRule_odd"></a><em>fillRule_odd</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a54a13" doxytag="fillRule_nonzero"></a><em>fillRule_nonzero</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a54a14" doxytag="fillRule_positive"></a><em>fillRule_positive</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a54a15" doxytag="fillRule_negative"></a><em>fillRule_negative</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a54a16" doxytag="fillRule_abs_geq_2"></a><em>fillRule_abs_geq_2</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a59" doxytag="ZincTypes.hpp::itemOperator"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a59">itemOperator</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a59a43" doxytag="item_add_clockwise"></a><em>item_add_clockwise</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a59a44" doxytag="item_add_counterclockwise"></a><em>item_add_counterclockwise</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a59a45" doxytag="item_remove"></a><em>item_remove</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a60" doxytag="ZincTypes.hpp::itemType"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a60">itemType</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a60a46" doxytag="item_group"></a><em>item_group</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a60a47" doxytag="item_arc"></a><em>item_arc</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a60a48" doxytag="item_text"></a><em>item_text</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a60a49" doxytag="item_rectangle"></a><em>item_rectangle</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a60a50" doxytag="item_curve"></a><em>item_curve</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a60a51" doxytag="item_icon"></a><em>item_icon</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a55" doxytag="ZincTypes.hpp::joinStyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a55">joinStyle</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a55a17" doxytag="joinStyle_bevel"></a><em>joinStyle_bevel</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a55a18" doxytag="joinStyle_miter"></a><em>joinStyle_miter</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a55a19" doxytag="joinStyle_round"></a><em>joinStyle_round</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a52" doxytag="ZincTypes.hpp::lineStyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a52">lineStyle</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a52a5" doxytag="lineStyle_simple"></a><em>lineStyle_simple</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a52a6" doxytag="lineStyle_dashed"></a><em>lineStyle_dashed</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a52a7" doxytag="lineStyle_mixed"></a><em>lineStyle_mixed</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a52a8" doxytag="lineStyle_dotted"></a><em>lineStyle_dotted</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<a name="a56" doxytag="ZincTypes.hpp::relief"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> enum <a class="el" href="ZincTypes_8hpp.html#a56">relief</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<dl compact><dt><b>Enumeration values: </b></dt><dd>
<table border=0 cellspacing=2 cellpadding=0>
<tr><td valign=top><em><a name="a56a20" doxytag="relief_flat"></a><em>relief_flat</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a21" doxytag="relief_raised"></a><em>relief_raised</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a22" doxytag="relief_sunken"></a><em>relief_sunken</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a23" doxytag="relief_ridge"></a><em>relief_ridge</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a24" doxytag="relief_groove"></a><em>relief_groove</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a25" doxytag="relief_roundraised"></a><em>relief_roundraised</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a26" doxytag="relief_roundsunken"></a><em>relief_roundsunken</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a27" doxytag="relief_roundridge"></a><em>relief_roundridge</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a28" doxytag="relief_roundgroove"></a><em>relief_roundgroove</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a29" doxytag="relief_raisedrule"></a><em>relief_raisedrule</em></em>&nbsp;</td><td>
</td></tr>
<tr><td valign=top><em><a name="a56a30" doxytag="relief_sunkenrule"></a><em>relief_sunkenrule</em></em>&nbsp;</td><td>
</td></tr>
</table>
</dl>
    </td>
  </tr>
</table>
<hr><h2>Variable Documentation</h2>
<a name="a4" doxytag="ZincTypes.hpp::ZINC_BACKEND_OPENGL"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const int <a class="el" href="ZincTypes_8hpp.html#a4">ZINC_BACKEND_OPENGL</a> = 1
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a3" doxytag="ZincTypes.hpp::ZINC_BACKEND_X11"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const int <a class="el" href="ZincTypes_8hpp.html#a3">ZINC_BACKEND_X11</a> = 0
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/Zinc_8cpp.html.























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Zinc.cpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>Zinc.cpp File Reference</h1>
<p>
<code>#include "<a class="el" href="Zinc_8hpp-source.html">Zinc.hpp</a>"</code><br>
<code>#include "<a class="el" href="ZincInternal_8hpp-source.html">ZincInternal.hpp</a>"</code><br>
<code>#include &lt;iostream&gt;</code><br>
<code>#include &lt;sstream&gt;</code><br>
<code>#include &lt;tk.h&gt;</code><br>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Defines</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a0">EVENT_COUNT</a>&nbsp;&nbsp;&nbsp;5</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a1">WIDGETCB_COUNT</a>&nbsp;&nbsp;&nbsp;3</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a2">ITEMCB_COUNT</a>&nbsp;&nbsp;&nbsp;4</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>#define&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a3">z_tcl_call2</a>(fct, msg)</td></tr>

<tr><td colspan=2><br><h2>Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a20">tclCallback</a> (ClientData client_data, Tcl_Interp *interp, int argc, Tcl_Obj *CONST args[]) __attribute__((cdecl))</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a21">Z_DEFINE_ZOPT</a> (render)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-render" option </em> <a href="#a21"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a22">Z_DEFINE_ZOPT</a> (firstend)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-firstend" option </em> <a href="#a22"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a23">Z_DEFINE_ZOPT</a> (lastend)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-lastend" option </em> <a href="#a23"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a24">Z_DEFINE_ZOPT</a> (position)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-position" option </em> <a href="#a24"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a25">Z_DEFINE_ZOPT</a> (tags)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-tags" option </em> <a href="#a25"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a26">Z_DEFINE_ZOPT</a> (backcolor)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-backcolor" option </em> <a href="#a26"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a27">Z_DEFINE_ZOPT</a> (forecolor)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-forecolor" option </em> <a href="#a27"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a28">Z_DEFINE_ZOPT</a> (height)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-height" option </em> <a href="#a28"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a29">Z_DEFINE_ZOPT</a> (borderwidth)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-borderwidth" option </em> <a href="#a29"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a30">Z_DEFINE_ZOPT</a> (closed)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-closed" option </em> <a href="#a30"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a31">Z_DEFINE_ZOPT</a> (composealpha)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-composealpha" option </em> <a href="#a31"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a32">Z_DEFINE_ZOPT</a> (composerotation)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-composerotation" option </em> <a href="#a32"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a33">Z_DEFINE_ZOPT</a> (composescale)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-composescale" option </em> <a href="#a33"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a34">Z_DEFINE_ZOPT</a> (extent)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-extent" option </em> <a href="#a34"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a35">Z_DEFINE_ZOPT</a> (fillcolor)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-fillcolor" option </em> <a href="#a35"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a36">Z_DEFINE_ZOPT</a> (filled)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-filled" option </em> <a href="#a36"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a37">Z_DEFINE_ZOPT</a> (fillpattern)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-fillpattern" option </em> <a href="#a37"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a38">Z_DEFINE_ZOPT</a> (linecolor)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-linecolor" option </em> <a href="#a38"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a39">Z_DEFINE_ZOPT</a> (linepattern)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-linepattern" option </em> <a href="#a39"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a40">Z_DEFINE_ZOPT</a> (linestyle)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-linestyle" option </em> <a href="#a40"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a41">Z_DEFINE_ZOPT</a> (linewidth)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-linewidth" option </em> <a href="#a41"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a42">Z_DEFINE_ZOPT</a> (pieslice)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-pieslice" option </em> <a href="#a42"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a43">Z_DEFINE_ZOPT</a> (priority)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-priority" option </em> <a href="#a43"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a44">Z_DEFINE_ZOPT</a> (sensitive)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-sensitive" option </em> <a href="#a44"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a45">Z_DEFINE_ZOPT</a> (startangle)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-startangle" option </em> <a href="#a45"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a46">Z_DEFINE_ZOPT</a> (tile)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-tile" option </em> <a href="#a46"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a47">Z_DEFINE_ZOPT</a> (visible)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-visible" option </em> <a href="#a47"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a48">Z_DEFINE_ZOPT</a> (capstyle)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-capstyle" option </em> <a href="#a48"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a49">Z_DEFINE_ZOPT</a> (fillrule)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-fillrule" option </em> <a href="#a49"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a50">Z_DEFINE_ZOPT</a> (joinstyle)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-joinstyle" option </em> <a href="#a50"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a51">Z_DEFINE_ZOPT</a> (marker)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-marker" option </em> <a href="#a51"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a52">Z_DEFINE_ZOPT</a> (<a class="el" href="ZincTypes_8hpp.html#a56">relief</a>)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-relief" option </em> <a href="#a52"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a53">Z_DEFINE_ZOPT</a> (smoothrelief)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-smoothrelief" option </em> <a href="#a53"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a54">Z_DEFINE_ZOPT</a> (alpha)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-alpha" option </em> <a href="#a54"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a55">Z_DEFINE_ZOPT</a> (atomic)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-atomic" option </em> <a href="#a55"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a56">Z_DEFINE_ZOPT</a> (clip)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-clip" option </em> <a href="#a56"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a57">Z_DEFINE_ZOPT</a> (<a class="el" href="ZincTypes_8hpp.html#a58">anchor</a>)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-anchor" option </em> <a href="#a57"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a58">Z_DEFINE_ZOPT</a> (color)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-color" option </em> <a href="#a58"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a59">Z_DEFINE_ZOPT</a> (connecteditem)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-connecteditem" option </em> <a href="#a59"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a60">Z_DEFINE_ZOPT</a> (connectionanchor)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-connectionanchor" option </em> <a href="#a60"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a61">Z_DEFINE_ZOPT</a> (image)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-image" option </em> <a href="#a61"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a62">Z_DEFINE_ZOPT</a> (mask)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-mask" option </em> <a href="#a62"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a63">Z_DEFINE_ZOPT</a> (<a class="el" href="ZincTypes_8hpp.html#a57">alignment</a>)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-alignment" option </em> <a href="#a63"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a64">Z_DEFINE_ZOPT</a> (font)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-font" option </em> <a href="#a64"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a65">Z_DEFINE_ZOPT</a> (overstriked)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-overstriked" option </em> <a href="#a65"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a66">Z_DEFINE_ZOPT</a> (spacing)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-spacing" option </em> <a href="#a66"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a67">Z_DEFINE_ZOPT</a> (text)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-text" option </em> <a href="#a67"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a68">Z_DEFINE_ZOPT</a> (underlined)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-underlined" option </em> <a href="#a68"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a69">Z_DEFINE_ZOPT</a> (width)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "-width" option </em> <a href="#a69"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a70">Z_DEFINE_ZFCT</a> (device)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">function constants </em> <a href="#a70"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a71">Z_DEFINE_ZFCT</a> (add)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "add" function </em> <a href="#a71"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a72">Z_DEFINE_ZFCT</a> (bind)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "bind" function </em> <a href="#a72"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a73">Z_DEFINE_ZFCT</a> (bbox)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "bbox" function </em> <a href="#a73"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a74">Z_DEFINE_ZFCT</a> (cget)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "cget" function </em> <a href="#a74"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a75">Z_DEFINE_ZFCT</a> (chggroup)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "chggroup" function </em> <a href="#a75"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a76">Z_DEFINE_ZFCT</a> (clone)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "clone" function </em> <a href="#a76"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a77">Z_DEFINE_ZFCT</a> (configure)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "configure" function </em> <a href="#a77"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a78">Z_DEFINE_ZFCT</a> (contour)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "contour" function </em> <a href="#a78"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a79">Z_DEFINE_ZFCT</a> (coords)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "coords" function </em> <a href="#a79"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a80">Z_DEFINE_ZFCT</a> (dtag)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "dtag" function </em> <a href="#a80"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a81">Z_DEFINE_ZFCT</a> (focus)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "focus" function </em> <a href="#a81"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a82">Z_DEFINE_ZFCT</a> (gettags)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "gettags" function </em> <a href="#a82"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a83">Z_DEFINE_ZFCT</a> (gname)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "gname" function </em> <a href="#a83"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a84">Z_DEFINE_ZFCT</a> (group)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "group" function </em> <a href="#a84"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a85">Z_DEFINE_ZFCT</a> (itemconfigure)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "itemconfigure" function </em> <a href="#a85"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a86">Z_DEFINE_ZFCT</a> (itemcget)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "itemcget" function </em> <a href="#a86"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a87">Z_DEFINE_ZFCT</a> (lower)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "lower" function </em> <a href="#a87"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a88">Z_DEFINE_ZFCT</a> (raise)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "raise" function </em> <a href="#a88"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a89">Z_DEFINE_ZFCT</a> (remove)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "remove" function </em> <a href="#a89"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a90">Z_DEFINE_ZFCT</a> (rotate)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "rotate" function </em> <a href="#a90"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a91">Z_DEFINE_ZFCT</a> (scale)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "scale" function </em> <a href="#a91"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a92">Z_DEFINE_ZFCT</a> (skew)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "skew" function </em> <a href="#a92"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a93">Z_DEFINE_ZFCT</a> (tget)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "tget" function </em> <a href="#a93"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a94">Z_DEFINE_ZFCT</a> (translate)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "translate" function </em> <a href="#a94"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a95">Z_DEFINE_ZFCT</a> (transform)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "transform" function </em> <a href="#a95"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a96">Z_DEFINE_ZFCT</a> (treset)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "treset" function </em> <a href="#a96"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a97">Z_DEFINE_ZFCT</a> (tset)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "tset" function </em> <a href="#a97"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a98">Z_DEFINE_ZFCT</a> (type)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "type" function </em> <a href="#a98"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a99">Z_DEFINE_ZITM</a> (add)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "add" constant </em> <a href="#a99"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a100">Z_DEFINE_ZITM</a> (arc)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "arc" constant </em> <a href="#a100"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a101">Z_DEFINE_ZITM</a> (curve)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "curve" constant </em> <a href="#a101"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a102">Z_DEFINE_ZITM</a> (icon)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "icon" constant </em> <a href="#a102"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a103">Z_DEFINE_ZITM</a> (group)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "group" constant </em> <a href="#a103"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a104">Z_DEFINE_ZITM</a> (rectangle)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "rectangle" constant </em> <a href="#a104"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a105">Z_DEFINE_ZITM</a> (text)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "text" constant </em> <a href="#a105"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a106">Z_DEFINE_ZITM</a> (withtag)</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the "withtag" constant </em> <a href="#a106"></a><em><br><br></td></tr>
<tr><td colspan=2><br><h2>Variables</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a4">DEFAULT_GROUP_OBJ</a> = Tcl_NewIntObj (<a class="el" href="Zinc_8hpp.html#a2">DEFAULT_GROUP</a>)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a5">lineStylesStrings</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a6">lineStyles</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a7">capStylesStrings</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a8">capStyles</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a9">fillRulesStrings</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a10">fillRules</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a11">joinStylesStrings</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a12">joinStyles</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a13">reliefsStrings</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a14">reliefs</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a15">alignmentsStrings</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a16">alignments</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a17">anchorsStrings</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a18">anchors</a> []</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8cpp.html#a19">itemTypeStrings</a> []</td></tr>

</table>
<hr><h2>Define Documentation</h2>
<a name="a0" doxytag="Zinc.cpp::EVENT_COUNT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define EVENT_COUNT&nbsp;&nbsp;&nbsp;5
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
How To call <a class="el" href="classZinc.html">Zinc</a> or Tcl functions:<p>
All arguments of the function are Tcl_Obj. To accelerate their call, there is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj. p1 and p2 are tables of pointers to be used for arguments. Fill p1 using either predefined objects like ZITM_* or a pool objet that you can fill with the value you want. Ex : p1[1] = ZFCT_add; Macros have been defined to fill and use a pool object Ex : p1[2] = <a class="el" href="ZincInternal_8hpp.html#a3">Z_INT_POOL(1, 200)</a>; Do not use twice the same pool index for the same function call. p2 is used to construct and argument which is a list of Tcl_Obj. To call the function use z_tcl_call which automaticly handle error return codes or z_command to call a <a class="el" href="classZinc.html">Zinc</a> command which handle all arguments too.     </td>
  </tr>
</table>
<a name="a2" doxytag="Zinc.cpp::ITEMCB_COUNT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define ITEMCB_COUNT&nbsp;&nbsp;&nbsp;4
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a1" doxytag="Zinc.cpp::WIDGETCB_COUNT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define WIDGETCB_COUNT&nbsp;&nbsp;&nbsp;3
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a3" doxytag="Zinc.cpp::z_tcl_call2"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> #define z_tcl_call2</td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">fct,         <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>msg&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Value:</b><div class="fragment"><pre>{                          \
    <span class="keywordtype">int</span> result = (fct);      \
    <span class="keywordflow">if</span> (result != TCL_OK)    \
    {                        \
      Tcl_AppendResult (Zinc::interp, msg, NULL); \
      <span class="keywordflow">return</span> TCL_ERROR;      \
    }                        \
  }
</pre></div>    </td>
  </tr>
</table>
<hr><h2>Function Documentation</h2>
<a name="a20" doxytag="Zinc.cpp::tclCallback"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int tclCallback </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">ClientData&nbsp;</td>
          <td class="mdname" nowrap> <em>client_data</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>Tcl_Interp *&nbsp;</td>
          <td class="mdname" nowrap> <em>interp</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>argc</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>Tcl_Obj *CONST&nbsp;</td>
          <td class="mdname" nowrap> <em>args</em>[]</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Real callback used by zinc TCL<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>client_data</em>&nbsp;</td><td>the <a class="el" href="classZinc.html">Zinc</a> object </td></tr>
    <tr><td valign=top><em>interp</em>&nbsp;</td><td>current interpreter </td></tr>
    <tr><td valign=top><em>argc</em>&nbsp;</td><td>number of arguments </td></tr>
    <tr><td valign=top><em>args</em>&nbsp;</td><td>table of arguments </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a98" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">type&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "type" function 
<p>
    </td>
  </tr>
</table>
<a name="a97" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">tset&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "tset" function 
<p>
    </td>
  </tr>
</table>
<a name="a96" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">treset&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "treset" function 
<p>
    </td>
  </tr>
</table>
<a name="a95" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">transform&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "transform" function 
<p>
    </td>
  </tr>
</table>
<a name="a94" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">translate&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "translate" function 
<p>
    </td>
  </tr>
</table>
<a name="a93" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">tget&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "tget" function 
<p>
    </td>
  </tr>
</table>
<a name="a92" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">skew&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "skew" function 
<p>
    </td>
  </tr>
</table>
<a name="a91" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">scale&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "scale" function 
<p>
    </td>
  </tr>
</table>
<a name="a90" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">rotate&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "rotate" function 
<p>
    </td>
  </tr>
</table>
<a name="a89" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">remove&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "remove" function 
<p>
    </td>
  </tr>
</table>
<a name="a88" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">raise&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "raise" function 
<p>
    </td>
  </tr>
</table>
<a name="a87" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">lower&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "lower" function 
<p>
    </td>
  </tr>
</table>
<a name="a86" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">itemcget&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "itemcget" function 
<p>
    </td>
  </tr>
</table>
<a name="a85" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">itemconfigure&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "itemconfigure" function 
<p>
    </td>
  </tr>
</table>
<a name="a84" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">group&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "group" function 
<p>
    </td>
  </tr>
</table>
<a name="a83" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">gname&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "gname" function 
<p>
    </td>
  </tr>
</table>
<a name="a82" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">gettags&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "gettags" function 
<p>
    </td>
  </tr>
</table>
<a name="a81" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">focus&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "focus" function 
<p>
    </td>
  </tr>
</table>
<a name="a80" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">dtag&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "dtag" function 
<p>
    </td>
  </tr>
</table>
<a name="a79" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">coords&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "coords" function 
<p>
    </td>
  </tr>
</table>
<a name="a78" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">contour&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "contour" function 
<p>
    </td>
  </tr>
</table>
<a name="a77" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">configure&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "configure" function 
<p>
    </td>
  </tr>
</table>
<a name="a76" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">clone&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "clone" function 
<p>
    </td>
  </tr>
</table>
<a name="a75" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">chggroup&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "chggroup" function 
<p>
    </td>
  </tr>
</table>
<a name="a74" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">cget&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "cget" function 
<p>
    </td>
  </tr>
</table>
<a name="a73" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">bbox&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "bbox" function 
<p>
    </td>
  </tr>
</table>
<a name="a72" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">bind&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "bind" function 
<p>
    </td>
  </tr>
</table>
<a name="a71" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">add&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "add" function 
<p>
    </td>
  </tr>
</table>
<a name="a70" doxytag="Zinc.cpp::Z_DEFINE_ZFCT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZFCT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">device&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
function constants 
<p>
    </td>
  </tr>
</table>
<a name="a106" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">withtag&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "withtag" constant 
<p>
    </td>
  </tr>
</table>
<a name="a105" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">text&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "text" constant 
<p>
    </td>
  </tr>
</table>
<a name="a104" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">rectangle&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "rectangle" constant 
<p>
    </td>
  </tr>
</table>
<a name="a103" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">group&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "group" constant 
<p>
    </td>
  </tr>
</table>
<a name="a102" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">icon&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "icon" constant 
<p>
    </td>
  </tr>
</table>
<a name="a101" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">curve&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "curve" constant 
<p>
    </td>
  </tr>
</table>
<a name="a100" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">arc&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "arc" constant 
<p>
    </td>
  </tr>
</table>
<a name="a99" doxytag="Zinc.cpp::Z_DEFINE_ZITM"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZITM </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">add&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "add" constant 
<p>
    </td>
  </tr>
</table>
<a name="a69" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">width&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-width" option 
<p>
    </td>
  </tr>
</table>
<a name="a68" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">underlined&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-underlined" option 
<p>
    </td>
  </tr>
</table>
<a name="a67" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">text&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-text" option 
<p>
    </td>
  </tr>
</table>
<a name="a66" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">spacing&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-spacing" option 
<p>
    </td>
  </tr>
</table>
<a name="a65" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">overstriked&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-overstriked" option 
<p>
    </td>
  </tr>
</table>
<a name="a64" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">font&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-font" option 
<p>
    </td>
  </tr>
</table>
<a name="a63" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a57">alignment</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-alignment" option 
<p>
    </td>
  </tr>
</table>
<a name="a62" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">mask&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-mask" option 
<p>
    </td>
  </tr>
</table>
<a name="a61" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">image&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-image" option 
<p>
    </td>
  </tr>
</table>
<a name="a60" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">connectionanchor&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-connectionanchor" option 
<p>
    </td>
  </tr>
</table>
<a name="a59" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">connecteditem&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-connecteditem" option 
<p>
    </td>
  </tr>
</table>
<a name="a58" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">color&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-color" option 
<p>
    </td>
  </tr>
</table>
<a name="a57" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a58">anchor</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-anchor" option 
<p>
    </td>
  </tr>
</table>
<a name="a56" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">clip&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-clip" option 
<p>
    </td>
  </tr>
</table>
<a name="a55" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">atomic&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-atomic" option 
<p>
    </td>
  </tr>
</table>
<a name="a54" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">alpha&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-alpha" option 
<p>
    </td>
  </tr>
</table>
<a name="a53" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">smoothrelief&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-smoothrelief" option 
<p>
    </td>
  </tr>
</table>
<a name="a52" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a56">relief</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-relief" option 
<p>
    </td>
  </tr>
</table>
<a name="a51" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">marker&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-marker" option 
<p>
    </td>
  </tr>
</table>
<a name="a50" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">joinstyle&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-joinstyle" option 
<p>
    </td>
  </tr>
</table>
<a name="a49" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">fillrule&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-fillrule" option 
<p>
    </td>
  </tr>
</table>
<a name="a48" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">capstyle&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-capstyle" option 
<p>
    </td>
  </tr>
</table>
<a name="a47" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">visible&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-visible" option 
<p>
    </td>
  </tr>
</table>
<a name="a46" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">tile&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-tile" option 
<p>
    </td>
  </tr>
</table>
<a name="a45" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">startangle&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-startangle" option 
<p>
    </td>
  </tr>
</table>
<a name="a44" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">sensitive&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-sensitive" option 
<p>
    </td>
  </tr>
</table>
<a name="a43" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">priority&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-priority" option 
<p>
    </td>
  </tr>
</table>
<a name="a42" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">pieslice&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-pieslice" option 
<p>
    </td>
  </tr>
</table>
<a name="a41" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">linewidth&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-linewidth" option 
<p>
    </td>
  </tr>
</table>
<a name="a40" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">linestyle&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-linestyle" option 
<p>
    </td>
  </tr>
</table>
<a name="a39" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">linepattern&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-linepattern" option 
<p>
    </td>
  </tr>
</table>
<a name="a38" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">linecolor&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-linecolor" option 
<p>
    </td>
  </tr>
</table>
<a name="a37" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">fillpattern&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-fillpattern" option 
<p>
    </td>
  </tr>
</table>
<a name="a36" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">filled&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-filled" option 
<p>
    </td>
  </tr>
</table>
<a name="a35" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">fillcolor&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-fillcolor" option 
<p>
    </td>
  </tr>
</table>
<a name="a34" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">extent&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-extent" option 
<p>
    </td>
  </tr>
</table>
<a name="a33" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">composescale&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-composescale" option 
<p>
    </td>
  </tr>
</table>
<a name="a32" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">composerotation&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-composerotation" option 
<p>
    </td>
  </tr>
</table>
<a name="a31" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">composealpha&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-composealpha" option 
<p>
    </td>
  </tr>
</table>
<a name="a30" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">closed&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-closed" option 
<p>
    </td>
  </tr>
</table>
<a name="a29" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">borderwidth&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-borderwidth" option 
<p>
    </td>
  </tr>
</table>
<a name="a28" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">height&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-height" option 
<p>
    </td>
  </tr>
</table>
<a name="a27" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">forecolor&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-forecolor" option 
<p>
    </td>
  </tr>
</table>
<a name="a26" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">backcolor&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-backcolor" option 
<p>
    </td>
  </tr>
</table>
<a name="a25" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">tags&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-tags" option 
<p>
    </td>
  </tr>
</table>
<a name="a24" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">position&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-position" option 
<p>
    </td>
  </tr>
</table>
<a name="a23" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">lastend&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-lastend" option 
<p>
    </td>
  </tr>
</table>
<a name="a22" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">firstend&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-firstend" option 
<p>
    </td>
  </tr>
</table>
<a name="a21" doxytag="Zinc.cpp::Z_DEFINE_ZOPT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Z_DEFINE_ZOPT </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">render&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the "-render" option 
<p>
    </td>
  </tr>
</table>
<hr><h2>Variable Documentation</h2>
<a name="a16" doxytag="Zinc.cpp::alignments"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a16">alignments</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  Tcl_NewStringObj (<span class="stringliteral">"left"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"right"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"center"</span>, -1),
}
</pre></div>    </td>
  </tr>
</table>
<a name="a15" doxytag="Zinc.cpp::alignmentsStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a15">alignmentsStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{ <span class="stringliteral">"left"</span>, <span class="stringliteral">"right"</span>, <span class="stringliteral">"center"</span> }
</pre></div>    </td>
  </tr>
</table>
<a name="a18" doxytag="Zinc.cpp::anchors"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a18">anchors</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  Tcl_NewStringObj (<span class="stringliteral">"nw"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"n"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"ne"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"e"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"se"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"s"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"sw"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"w"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"center"</span>, -1),
}
</pre></div>    </td>
  </tr>
</table>
<a name="a17" doxytag="Zinc.cpp::anchorsStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a17">anchorsStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{ <span class="stringliteral">"nw"</span>, <span class="stringliteral">"n"</span>, <span class="stringliteral">"ne"</span>, <span class="stringliteral">"e"</span>, <span class="stringliteral">"se"</span>, <span class="stringliteral">"s"</span>, <span class="stringliteral">"sw"</span>, <span class="stringliteral">"w"</span>, <span class="stringliteral">"center"</span> }
</pre></div>    </td>
  </tr>
</table>
<a name="a8" doxytag="Zinc.cpp::capStyles"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a8">capStyles</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  Tcl_NewStringObj (<span class="stringliteral">"butt"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"projecting"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"round"</span>, -1),
}
</pre></div>    </td>
  </tr>
</table>
<a name="a7" doxytag="Zinc.cpp::capStylesStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a7">capStylesStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{ <span class="stringliteral">"butt"</span>, <span class="stringliteral">"projecting"</span>, <span class="stringliteral">"round"</span> }
</pre></div>    </td>
  </tr>
</table>
<a name="a4" doxytag="Zinc.cpp::DEFAULT_GROUP_OBJ"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a4">DEFAULT_GROUP_OBJ</a> = Tcl_NewIntObj (<a class="el" href="Zinc_8hpp.html#a2">DEFAULT_GROUP</a>)<code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="a10" doxytag="Zinc.cpp::fillRules"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a10">fillRules</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  Tcl_NewStringObj (<span class="stringliteral">"odd"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"nonzero"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"positive"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"negative"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"abs_geq_2"</span>, -1),
}
</pre></div>    </td>
  </tr>
</table>
<a name="a9" doxytag="Zinc.cpp::fillRulesStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a9">fillRulesStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{ <span class="stringliteral">"odd"</span>, <span class="stringliteral">"nonzero"</span>, <span class="stringliteral">"positive"</span>, <span class="stringliteral">"negative"</span>, <span class="stringliteral">"abs_geq_2"</span> }
</pre></div>    </td>
  </tr>
</table>
<a name="a19" doxytag="Zinc.cpp::itemTypeStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a19">itemTypeStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  <span class="stringliteral">"group"</span>,
  <span class="stringliteral">"arc"</span>,
  <span class="stringliteral">"text"</span>,
  <span class="stringliteral">"rectangle"</span>,
  <span class="stringliteral">"curve"</span>,
  <span class="stringliteral">"icon"</span>,
  NULL
}
</pre></div>    </td>
  </tr>
</table>
<a name="a12" doxytag="Zinc.cpp::joinStyles"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a12">joinStyles</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  Tcl_NewStringObj (<span class="stringliteral">"bevel"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"miter"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"round"</span>, -1),
}
</pre></div>    </td>
  </tr>
</table>
<a name="a11" doxytag="Zinc.cpp::joinStylesStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a11">joinStylesStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{ <span class="stringliteral">"bevel"</span>, <span class="stringliteral">"miter"</span>, <span class="stringliteral">"round"</span> }
</pre></div>    </td>
  </tr>
</table>
<a name="a6" doxytag="Zinc.cpp::lineStyles"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a6">lineStyles</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  Tcl_NewStringObj (<span class="stringliteral">"simple"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"dashed"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"mixed"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"dotted"</span>, -1),
}
</pre></div>    </td>
  </tr>
</table>
<a name="a5" doxytag="Zinc.cpp::lineStylesStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a5">lineStylesStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{ <span class="stringliteral">"simple"</span>, <span class="stringliteral">"dashed"</span>, <span class="stringliteral">"mixed"</span>, <span class="stringliteral">"dotted"</span> }
</pre></div>    </td>
  </tr>
</table>
<a name="a14" doxytag="Zinc.cpp::reliefs"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="Zinc_8cpp.html#a14">reliefs</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{
  Tcl_NewStringObj (<span class="stringliteral">"flat"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"raised"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"sunken"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"ridge"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"groove"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"roundraised"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"roundsunken"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"roundridge"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"roundgroove"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"raisedrule"</span>, -1),
  Tcl_NewStringObj (<span class="stringliteral">"sunkenrule"</span>, -1),
}
</pre></div>    </td>
  </tr>
</table>
<a name="a13" doxytag="Zinc.cpp::reliefsStrings"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char* <a class="el" href="Zinc_8cpp.html#a13">reliefsStrings</a>[]
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
<b>Initial value:</b><div class="fragment"><pre>
{ <span class="stringliteral">"flat"</span>, <span class="stringliteral">"raised"</span>, <span class="stringliteral">"sunken"</span>, <span class="stringliteral">"ridge"</span>, <span class="stringliteral">"groove"</span>, <span class="stringliteral">"roundraised"</span>,
  <span class="stringliteral">"roundsunken"</span>, <span class="stringliteral">"roundridge"</span>, <span class="stringliteral">"roundgroove"</span>, <span class="stringliteral">"raisedrule"</span>, <span class="stringliteral">"sunkenrule"</span> }
</pre></div>    </td>
  </tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/Zinc_8hpp-source.html.





































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Zinc.hpp Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>Zinc.hpp</h1><a href="Zinc_8hpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 
00016 <span class="preprocessor">#include "<a class="code" href="ZincTypes_8hpp.html">ZincTypes.hpp</a>"</span>
00017 <span class="preprocessor">#include "<a class="code" href="ZincObjects_8hpp.html">ZincObjects.hpp</a>"</span>
00018 <span class="preprocessor">#include "<a class="code" href="ZincPath_8hpp.html">ZincPath.hpp</a>"</span>
00019 <span class="preprocessor">#include "<a class="code" href="ZincExtern_8hpp.html">ZincExtern.hpp</a>"</span>
00020 <span class="preprocessor">#include &lt;tcl.h&gt;</span>
00021 
00022 <span class="preprocessor">#ifndef ZINC_HEADER</span>
00023 <span class="preprocessor"></span><span class="preprocessor">#define ZINC_HEADER</span>
00024 <span class="preprocessor"></span>
00025 
<a name="l00027"></a><a class="code" href="Zinc_8hpp.html#a0">00027</a> <span class="keyword">const</span> <span class="keywordtype">int</span> <a class="code" href="Zinc_8hpp.html#a0">ZINC_POOL_COUNT</a>   = 7;
<a name="l00029"></a><a class="code" href="Zinc_8hpp.html#a1">00029</a> <span class="keyword">const</span> <span class="keywordtype">int</span>  <a class="code" href="Zinc_8hpp.html#a1">ZINC_PARAM_COUNT</a> = 10;
00030 
<a name="l00032"></a><a class="code" href="Zinc_8hpp.html#a2">00032</a> <span class="keyword">const</span> <span class="keywordtype">int</span> <a class="code" href="Zinc_8hpp.html#a2">DEFAULT_GROUP</a> = 1;
00033 
<a name="l00037"></a><a class="code" href="classZinc.html">00037</a> <span class="keyword">class </span><a class="code" href="classZinc.html">Zinc</a>
00038 {
<a name="l00039"></a><a class="code" href="classZinc.html#n0">00039</a>   <span class="keyword">friend</span> <span class="keyword">class </span><a class="code" href="classZincPath.html">ZincPath</a>;
00040   
00041 <span class="keyword">public</span>:
<a name="l00042"></a><a class="code" href="classZinc.html#o0">00042</a>   Tcl_Obj *<a class="code" href="classZinc.html#o0">id</a>;           
<a name="l00043"></a><a class="code" href="classZinc.html#o1">00043</a>   <a class="code" href="ZincExtern_8hpp.html#a0">WidgetObjCmd</a> <a class="code" href="classZinc.html#o1">objCmd</a>;   
<a name="l00044"></a><a class="code" href="classZinc.html#o2">00044</a>   ClientData <a class="code" href="classZinc.html#o2">wi</a>;         
<a name="l00045"></a><a class="code" href="classZinc.html#o3">00045</a>   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#o3">tclCb</a>;          
<a name="l00046"></a><a class="code" href="classZinc.html#o4">00046</a>   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#o4">znId</a>;              
<a name="l00047"></a><a class="code" href="classZinc.html#o5">00047</a>   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#o5">window</a>;         
00048 
00049   <span class="keyword">static</span> <span class="keywordtype">int</span> <a class="code" href="classZinc.html#s0">znCount</a>;                   
00050   <span class="keyword">static</span> Tcl_CmdInfo <a class="code" href="classZinc.html#s1">imgCmdInfo</a>;        
00051   <span class="keyword">static</span> Tcl_CmdInfo <a class="code" href="classZinc.html#s2">fntCmdInfo</a>;        
00052   <span class="keyword">static</span> Tcl_CmdInfo <a class="code" href="classZinc.html#s3">focCmdInfo</a>;        
00053   <span class="keyword">static</span> Tcl_CmdInfo <a class="code" href="classZinc.html#s4">bndCmdInfo</a>;        
00054   <span class="keyword">static</span> Tcl_Obj* <a class="code" href="classZinc.html#s5">pool</a>[<a class="code" href="Zinc_8hpp.html#a0">ZINC_POOL_COUNT</a>];
00055   <span class="keyword">static</span> Tcl_Obj* <a class="code" href="classZinc.html#s6">p1</a>[<a class="code" href="Zinc_8hpp.html#a1">ZINC_PARAM_COUNT</a>]; 
00056   <span class="keyword">static</span> Tcl_Obj* <a class="code" href="classZinc.html#s7">p2</a>[<a class="code" href="Zinc_8hpp.html#a1">ZINC_PARAM_COUNT</a>]; 
00057 
00058 <span class="keyword">public</span>:
00059   <span class="keyword">static</span> Tcl_Interp *<a class="code" href="classZinc.html#s8">interp</a>;            
00060 
00066   <a class="code" href="classZinc.html#a0">Zinc</a> (<span class="keywordtype">int</span> renderingMode);
00067 
00071   <a class="code" href="classZinc.html#a1">~Zinc</a> ();
00072 
00078   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a2">setTitle</a> (String title);
00079 
00080 <span class="comment">/*****************************************</span>
00081 <span class="comment">          WIDGET PROPERTIES</span>
00082 <span class="comment">*****************************************/</span>
00083   
00089   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a3">setBackcolor</a> (String value);
00090 
00096   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#a4">getBackcolor</a> ();
00097 
00103   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a5">setForecolor</a> (String value);
00104 
00110   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#a6">getForecolor</a> ();
00111 
00117   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a7">setWidth</a> (<span class="keywordtype">int</span> value);
00118 
00124   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a8">getWidth</a> ();
00125 
00131   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a9">setHeight</a> (<span class="keywordtype">int</span> value);
00132 
00138   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a10">getHeight</a> ();
00139 
00145   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a11">setBorderwidth</a> (<span class="keywordtype">int</span> value);
00146 
00152   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a12">getBorderwidth</a> ();
00153 
00159   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a13">setFont</a> (<a class="code" href="classZincFont.html">ZincFont</a>* value);
00160 
00166   <a class="code" href="classZincFont.html">ZincFont</a>* <a class="code" href="classZinc.html#a14">getFont</a> ();
00167 
00168 <span class="comment">/*****************************************</span>
00169 <span class="comment">          WIDGET METHODS</span>
00170 <span class="comment">*****************************************/</span>
00171 
00179   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a15">bbox</a> (<a class="code" href="classZincItem.html">ZincItem</a>* item, <span class="keywordtype">double</span> bbox[4]);
00180 
00188   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a16">relativeBbox</a> (<a class="code" href="classZincItem.html">ZincItem</a>* item, <span class="keywordtype">double</span> bbox[4]);
00189 
00190 
00197   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a17">chggroup</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, <a class="code" href="classZincItem.html">ZincItem</a> *parentGroup);
00198 
00205   <a class="code" href="classZincItem.html">ZincItem</a>* <a class="code" href="classZinc.html#a18">clone</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00206 
00212   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a19">contour</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00213 
00222   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a19">contour</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, itemOperator flag, <a class="code" href="classZincItem.html">ZincItem</a> *reference);
00223 
00232   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a19">contour</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, <span class="keywordtype">bool</span> add, <a class="code" href="classZincPath.html">ZincPath</a> *contour);
00233 
00244   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a22">coords</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, <a class="code" href="classZincPath.html">ZincPath</a> *contour, <span class="keywordtype">bool</span> add,
00245                <span class="keywordtype">int</span> contourIndex = -1, <span class="keywordtype">int</span> coordIndex = -1);
00246 
00254   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a23">coordsRemove</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, <span class="keywordtype">int</span> coordIndex, <span class="keywordtype">int</span> contourIndex = -1);
00255 
00262   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a24">addTag</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, String tag);
00263 
00270   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a25">dTag</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, String tag = <a class="code" href="ZincTypes_8hpp.html#a0">String</a>(<span class="stringliteral">""</span>));
00271 
00280   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a26">getTags</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, String*** tagList);
00281 
00287   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a27">focus</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00288 
00295   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a28">isGname</a> (String gname);
00296 
00303   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a29">gname</a> (String gradient, String gname);
00304 
00311   <a class="code" href="classZincItem.html">ZincItem</a>* <a class="code" href="classZinc.html#a30">group</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00312 
00318   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a31">lower</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00319 
00326   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a31">lower</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, <a class="code" href="classZincItem.html">ZincItem</a> *belowThis);
00327 
00333   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a33">raise</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00334 
00341   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a33">raise</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, <a class="code" href="classZincItem.html">ZincItem</a> *aboveThis);
00342 
00349    <a class="code" href="ZincTypes_8hpp.html#a60">itemType</a> <a class="code" href="classZinc.html#a35">type</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00350 
00358   <a class="code" href="classZincItem.html">ZincItem</a>* <a class="code" href="classZinc.html#a36">createTag</a>(String tag);
00359 
00360 <span class="comment">/*****************************************</span>
00361 <span class="comment">          ITEMS MANIPULATION</span>
00362 <span class="comment">*****************************************/</span>
00368   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a37">itemRemove</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item);
00369 
00377   <a class="code" href="classZincItem.html">ZincItem</a> *<a class="code" href="classZinc.html#a38">itemCreateGroup</a> (<a class="code" href="classZincItem.html">ZincItem</a> *parentGroup);
00378 
00386   <a class="code" href="classZincItem.html">ZincItem</a> *<a class="code" href="classZinc.html#a39">itemCreateRectangle</a> (<a class="code" href="classZincItem.html">ZincItem</a> *parentGroup, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y,
00387                                 <span class="keywordtype">double</span> width, <span class="keywordtype">double</span> height);
00388 
00396   <a class="code" href="classZincItem.html">ZincItem</a> *<a class="code" href="classZinc.html#a40">itemCreateArc</a> (<a class="code" href="classZincItem.html">ZincItem</a> *parentGroup, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y,
00397                            <span class="keywordtype">double</span> width, <span class="keywordtype">double</span> height);
00398 
00405   <a class="code" href="classZincItem.html">ZincItem</a> *<a class="code" href="classZinc.html#a41">itemCreateText</a> (<a class="code" href="classZincItem.html">ZincItem</a> *parentGroup);
00406 
00414   <a class="code" href="classZincItem.html">ZincItem</a> *<a class="code" href="classZinc.html#a42">itemCreateCurve</a> (<a class="code" href="classZincItem.html">ZincItem</a> *parentGroup, <a class="code" href="classZincPath.html">ZincPath</a> *path);
00415 
00423   <a class="code" href="classZincItem.html">ZincItem</a> *<a class="code" href="classZinc.html#a43">itemCreateIcon</a> (<a class="code" href="classZincItem.html">ZincItem</a> *parentGroup, <a class="code" href="classZincImage.html">ZincImage</a>* image);
00424 
00425 
00426 <span class="comment">/**************************************************</span>
00427 <span class="comment">                    BINDING</span>
00428 <span class="comment">**************************************************/</span>
00429 
00438   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a44">bind</a> (String eventSpecification,
00439              ZincWidgetCallback callBack, <span class="keywordtype">void</span> *userData, <span class="keywordtype">bool</span> add = <span class="keyword">false</span>);
00440 
00446   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a45">unbind</a> (String eventSpecification);
00447   
00457   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a46">itemBind</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, String eventSpecification,
00458                  ZincItemCallback callBack, <span class="keywordtype">void</span> *userData, <span class="keywordtype">bool</span> add = <span class="keyword">false</span>);
00459 
00466   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a47">itemUnbind</a> (<a class="code" href="classZincItem.html">ZincItem</a> *item, String eventSpecification);
00467 
00468 <span class="comment">/**************************************************</span>
00469 <span class="comment">           TRANSFORMATION METHODS</span>
00470 <span class="comment">**************************************************/</span>
00471 
00478   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a48">itemTranslate</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> dx, <span class="keywordtype">double</span> dy);
00479 
00487   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a48">itemTranslate</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y, <span class="keywordtype">bool</span> absolute);
00488 
00495   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a50">itemRotate</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> angle);
00496 
00504   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a50">itemRotate</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> angle, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
00505 
00513   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a50">itemRotate</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> angle, <span class="keywordtype">bool</span> degree);
00514 
00523   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a50">itemRotate</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> angle, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y,
00524                    <span class="keywordtype">bool</span> degree);
00525 
00533   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a54">itemScale</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> ax, <span class="keywordtype">double</span> ay);
00534 
00543   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a54">itemScale</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> ax, <span class="keywordtype">double</span> ay, <span class="keywordtype">double</span> cx, <span class="keywordtype">double</span> cy);
00544 
00545   
00553   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a56">itemSkew</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> sx, <span class="keywordtype">double</span> sy);
00554 
00561   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a57">itemSkewX</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> sx);
00562 
00569   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a58">itemSkewY</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> sy);
00570 
00576   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a59">itemResetTransformation</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00577 
00584   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a60">itemSetTransformation</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item,
00585                               <span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> c,
00586                               <span class="keywordtype">double</span> d, <span class="keywordtype">double</span> e, <span class="keywordtype">double</span> f);
00587 
00594   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a61">itemGetTransformation</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item,
00595                               <span class="keywordtype">double</span> *a, <span class="keywordtype">double</span> *b, <span class="keywordtype">double</span> *c,
00596                               <span class="keywordtype">double</span> *d, <span class="keywordtype">double</span> *e, <span class="keywordtype">double</span> *f);
00597 
00604   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a62">itemMatrix</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item,
00605                    <span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> c,
00606                    <span class="keywordtype">double</span> d, <span class="keywordtype">double</span> e, <span class="keywordtype">double</span> f);
00607 
00608 <span class="comment">/*******************************************************</span>
00609 <span class="comment">             AUTOGENERATED METHODS (itemconfigure)</span>
00610 <span class="comment">"code.hpp" in Tkzins/generic source from :</span>
00611 <span class="comment">   ./gen.pl Arc.c Attrs.c Color.c Curve.c Draw.c  Group.c</span>
00612 <span class="comment">        Image.c List.c Item.c Icon.c Rectangle.c tkZinc.c Text.c</span>
00613 <span class="comment">*******************************************************/</span>
00614 
00620   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a63">itemSetClosed</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00621 
00627   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a64">itemGetClosed</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00628 
00634   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a65">itemSetComposealpha</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00635 
00641   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a66">itemGetComposealpha</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00642 
00648   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a67">itemSetComposerotation</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00649 
00655   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a68">itemGetComposerotation</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00656 
00662   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a69">itemSetComposescale</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00663 
00669   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a70">itemGetComposescale</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00670 
00676   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a71">itemSetExtent</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> value);
00677 
00683   <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a72">itemGetExtent</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00684 
00690   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a73">itemSetFillcolor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, String value);
00691 
00697   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#a74">itemGetFillcolor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00698 
00704   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a75">itemSetFilled</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00705 
00711   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a76">itemGetFilled</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00712 
00718   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a77">itemSetFillpattern</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincBitmap.html">ZincBitmap</a> * value);
00719 
00725   <a class="code" href="classZincBitmap.html">ZincBitmap</a> * <a class="code" href="classZinc.html#a78">itemGetFillpattern</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00726 
00732   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a79">itemSetLinecolor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, String value);
00733 
00739   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#a80">itemGetLinecolor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00740 
00746   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a81">itemSetLinepattern</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincBitmap.html">ZincBitmap</a> * value);
00747 
00753   <a class="code" href="classZincBitmap.html">ZincBitmap</a> * <a class="code" href="classZinc.html#a82">itemGetLinepattern</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00754 
00760   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a83">itemSetLinestyle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, lineStyle value);
00761 
00767   <a class="code" href="ZincTypes_8hpp.html#a52">lineStyle</a> <a class="code" href="classZinc.html#a84">itemGetLinestyle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00768 
00774   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a85">itemSetLinewidth</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> value);
00775 
00781   <span class="keywordtype">double</span> <a class="code" href="classZinc.html#a86">itemGetLinewidth</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00782 
00788   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a87">itemSetPieslice</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00789 
00795   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a88">itemGetPieslice</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00796 
00802   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a89">itemSetPriority</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> value);
00803 
00809   <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a90">itemGetPriority</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00810 
00816   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a91">itemSetSensitive</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00817 
00823   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a92">itemGetSensitive</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00824 
00830   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a93">itemSetStartangle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> value);
00831 
00837   <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a94">itemGetStartangle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00838 
00844   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a95">itemSetTile</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincBitmap.html">ZincBitmap</a> * value);
00845 
00851   <a class="code" href="classZincBitmap.html">ZincBitmap</a> * <a class="code" href="classZinc.html#a96">itemGetTile</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00852 
00858   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a97">itemSetVisible</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00859 
00865   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a98">itemGetVisible</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00866 
00872   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a99">itemSetCapstyle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, capStyle value);
00873 
00879   <a class="code" href="ZincTypes_8hpp.html#a53">capStyle</a> <a class="code" href="classZinc.html#a100">itemGetCapstyle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00880 
00886   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a101">itemSetFillrule</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, fillRule value);
00887 
00893   <a class="code" href="ZincTypes_8hpp.html#a54">fillRule</a> <a class="code" href="classZinc.html#a102">itemGetFillrule</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00894 
00900   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a103">itemSetJoinstyle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, joinStyle value);
00901 
00907   <a class="code" href="ZincTypes_8hpp.html#a55">joinStyle</a> <a class="code" href="classZinc.html#a104">itemGetJoinstyle</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00908 
00914   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a105">itemSetRelief</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, relief value);
00915 
00921   <a class="code" href="ZincTypes_8hpp.html#a56">relief</a> <a class="code" href="classZinc.html#a106">itemGetRelief</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00922 
00928   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a107">itemSetSmoothrelief</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00929 
00935   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a108">itemGetSmoothrelief</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00936 
00942   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a109">itemSetAlpha</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> value);
00943 
00949   <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a110">itemGetAlpha</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00950 
00956   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a111">itemSetAtomic</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
00957 
00963   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a112">itemGetAtomic</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00964 
00970   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a113">itemSetClip</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincItem.html">ZincItem</a> * value);
00971 
00977   <a class="code" href="classZincItem.html">ZincItem</a> * <a class="code" href="classZinc.html#a114">itemGetClip</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00978 
00984   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a115">itemSetAnchor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, anchor value);
00985 
00991   <a class="code" href="ZincTypes_8hpp.html#a58">anchor</a> <a class="code" href="classZinc.html#a116">itemGetAnchor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
00992 
00998   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a117">itemSetColor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, String value);
00999 
01005   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#a118">itemGetColor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01006 
01012   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a119">itemSetConnecteditem</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincItem.html">ZincItem</a> * value);
01013 
01019   <a class="code" href="classZincItem.html">ZincItem</a> * <a class="code" href="classZinc.html#a120">itemGetConnecteditem</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01020 
01026   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a121">itemSetConnectionanchor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, anchor value);
01027 
01033   <a class="code" href="ZincTypes_8hpp.html#a58">anchor</a> <a class="code" href="classZinc.html#a122">itemGetConnectionanchor</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01034 
01040   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a123">itemSetImage</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincImage.html">ZincImage</a> * value);
01041 
01047   <a class="code" href="classZincImage.html">ZincImage</a> * <a class="code" href="classZinc.html#a124">itemGetImage</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01048 
01054   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a125">itemSetMask</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincBitmap.html">ZincBitmap</a> * value);
01055 
01061   <a class="code" href="classZincBitmap.html">ZincBitmap</a> * <a class="code" href="classZinc.html#a126">itemGetMask</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01062 
01068   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a127">itemSetAlignment</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, alignment value);
01069 
01075   <a class="code" href="ZincTypes_8hpp.html#a57">alignment</a> <a class="code" href="classZinc.html#a128">itemGetAlignment</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01076 
01082   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a129">itemSetFont</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <a class="code" href="classZincFont.html">ZincFont</a> * value);
01083 
01089   <a class="code" href="classZincFont.html">ZincFont</a> * <a class="code" href="classZinc.html#a130">itemGetFont</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01090 
01096   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a131">itemSetOverstriked</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
01097 
01103   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a132">itemGetOverstriked</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01104 
01110   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a133">itemSetSpacing</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">short</span> value);
01111 
01117   <span class="keywordtype">short</span> <a class="code" href="classZinc.html#a134">itemGetSpacing</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01118 
01124   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a135">itemSetText</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, String value);
01125 
01131   <a class="code" href="ZincTypes_8hpp.html#a0">String</a> <a class="code" href="classZinc.html#a136">itemGetText</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01132 
01138   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a137">itemSetUnderlined</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">bool</span> value);
01139 
01145   <span class="keywordtype">bool</span> <a class="code" href="classZinc.html#a138">itemGetUnderlined</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01146 
01152   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a139">itemSetWidth</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> value);
01153 
01159   <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> <a class="code" href="classZinc.html#a140">itemGetWidth</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item);
01160 
01161 
01162 <span class="comment">/*******************************************************</span>
01163 <span class="comment">             END OF AUTOGENERATED METHODS</span>
01164 <span class="comment">*******************************************************/</span>
01165 
01172   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a141">itemSetFirstend</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> c);
01173   
01180   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a142">itemGetFirstend</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> *a, <span class="keywordtype">double</span> *b, <span class="keywordtype">double</span> *c);
01181 
01188   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a143">itemSetLastend</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> c);
01189 
01196   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a144">itemGetLastend</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> *a, <span class="keywordtype">double</span> *b, <span class="keywordtype">double</span> *c);
01197 
01204   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a145">itemSetPosition</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> x, <span class="keywordtype">double</span> y);
01205 
01212   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a146">itemGetPosition</a> (<a class="code" href="classZincItem.html">ZincItem</a> * item, <span class="keywordtype">double</span> *x, <span class="keywordtype">double</span> *y);
01213 
01219   <a class="code" href="classZincImage.html">ZincImage</a>* <a class="code" href="classZinc.html#a147">createImageFromFile</a> (String image);
01220 
01226   <a class="code" href="classZincImage.html">ZincImage</a>* <a class="code" href="classZinc.html#a148">createImageFromData</a> (String image);
01227 
01233   <a class="code" href="classZincBitmap.html">ZincBitmap</a>* <a class="code" href="classZinc.html#a149">createBitmapFromFile</a> (String image);
01234 
01240   <a class="code" href="classZincBitmap.html">ZincBitmap</a>* <a class="code" href="classZinc.html#a150">createBitmapFromData</a> (String image);
01241 
01247   <a class="code" href="classZincBitmap.html">ZincBitmap</a>* <a class="code" href="classZinc.html#a151">createBitmapFromName</a> (String image);
01248 
01256   <a class="code" href="classZincImage.html">ZincImage</a>* <a class="code" href="classZinc.html#a152">createImageFromAGGBuffer</a> (<span class="keywordtype">int</span> width, <span class="keywordtype">int</span> height, <span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> *aggBuffer);
01257 
01258 
01271   <a class="code" href="classZincFont.html">ZincFont</a>* <a class="code" href="classZinc.html#a153">createFont</a> (String family, <span class="keywordtype">int</span> size, <span class="keywordtype">int</span> bold = -1,
01272                         <span class="keywordtype">int</span> italic = -1, <span class="keywordtype">int</span> underline = -1,
01273                         <span class="keywordtype">int</span> overstrike = -1);
01274  
01281   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a154">getFontAscent</a> (<a class="code" href="classZincFont.html">ZincFont</a>* font);
01282 
01289   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a155">getImageWidth</a> (<a class="code" href="classZincImage.html">ZincImage</a> *image);
01290   
01297   <span class="keywordtype">int</span> <a class="code" href="classZinc.html#a156">getImageHeight</a> (<a class="code" href="classZincImage.html">ZincImage</a> *image);
01298   
01299 <span class="comment">/*******************************************************</span>
01300 <span class="comment">                STATIC PROCEDURES</span>
01301 <span class="comment">*******************************************************/</span>
01302 
01308   <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classZinc.html#e0">loadZinc</a> (<span class="keywordtype">char</span> *argv0) <span class="keywordflow">throw</span> (<a class="code" href="classZincException.html">ZincException</a>);
01309 
01313   <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classZinc.html#e1">zincMainLoop</a> ();
01314 
01315 <span class="comment">/*******************************************************</span>
01316 <span class="comment">               errors management</span>
01317 <span class="comment">*******************************************************/</span>
01325   <span class="keyword">static</span> <span class="keywordtype">void</span> <a class="code" href="classZinc.html#e2">z_tcl_call</a> (<span class="keywordtype">int</span> result, <span class="keywordtype">char</span>* p_msg) <span class="keywordflow">throw</span> (<a class="code" href="classZincException.html">ZincException</a>);
01326 
01337   <span class="keywordtype">void</span> <a class="code" href="classZinc.html#a157">z_command</a> (<span class="keywordtype">int</span> count, <span class="keywordtype">char</span>* p_msg) <span class="keywordflow">throw</span> (<a class="code" href="classZincException.html">ZincException</a>);
01338 
01339 };
01340 
01341 <span class="preprocessor">#endif</span>
</pre></div><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/Zinc_8hpp.html.













































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Zinc.hpp File Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>Zinc.hpp File Reference</h1>
<p>
<code>#include "<a class="el" href="ZincTypes_8hpp-source.html">ZincTypes.hpp</a>"</code><br>
<code>#include "<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>"</code><br>
<code>#include "<a class="el" href="ZincPath_8hpp-source.html">ZincPath.hpp</a>"</code><br>
<code>#include "<a class="el" href="ZincExtern_8hpp-source.html">ZincExtern.hpp</a>"</code><br>
<code>#include &lt;tcl.h&gt;</code><br>

<p>
<a href="Zinc_8hpp-source.html">Go to the source code of this file.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Compounds</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>class &nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html">Zinc</a></td></tr>

<tr><td colspan=2><br><h2>Variables</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>const int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8hpp.html#a0">ZINC_POOL_COUNT</a> = 7</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8hpp.html#a1">ZINC_PARAM_COUNT</a> = 10</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="Zinc_8hpp.html#a2">DEFAULT_GROUP</a> = 1</td></tr>

</table>
<hr><h2>Variable Documentation</h2>
<a name="a2" doxytag="Zinc.hpp::DEFAULT_GROUP"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const int <a class="el" href="Zinc_8hpp.html#a2">DEFAULT_GROUP</a> = 1
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Defaults zinc group     </td>
  </tr>
</table>
<a name="a1" doxytag="Zinc.hpp::ZINC_PARAM_COUNT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const int <a class="el" href="Zinc_8hpp.html#a1">ZINC_PARAM_COUNT</a> = 10
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
maximum number of parameter in a zinc function     </td>
  </tr>
</table>
<a name="a0" doxytag="Zinc.hpp::ZINC_POOL_COUNT"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const int <a class="el" href="Zinc_8hpp.html#a0">ZINC_POOL_COUNT</a> = 7
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Number of objects in the pool     </td>
  </tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/annotated.html.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Annotated Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindexHL" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>IntuiKit Compound List</h1>Here are the classes, structs, unions and interfaces with brief descriptions:<table>
  <tr><td class="indexkey"><a class="el" href="classZinc.html">Zinc</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="classZincBitmap.html">ZincBitmap</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="structZincEvent.html">ZincEvent</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="classZincException.html">ZincException</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="classZincFont.html">ZincFont</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="classZincImage.html">ZincImage</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="classZincItem.html">ZincItem</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="classZincPath.html">ZincPath</a></td><td class="indexvalue"></td></tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZinc-members.html.































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>Zinc Member List</h1>This is the complete list of members for <a class="el" href="classZinc.html">Zinc</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a24">addTag</a>(ZincItem *item, String tag)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a15">bbox</a>(ZincItem *item, double bbox[4])</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a44">bind</a>(String eventSpecification, ZincWidgetCallback callBack, void *userData, bool add=false)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s4">bndCmdInfo</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a17">chggroup</a>(ZincItem *item, ZincItem *parentGroup)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a18">clone</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a19">contour</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a20">contour</a>(ZincItem *item, itemOperator flag, ZincItem *reference)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a21">contour</a>(ZincItem *item, bool add, ZincPath *contour)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a22">coords</a>(ZincItem *item, ZincPath *contour, bool add, int contourIndex=-1, int coordIndex=-1)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a23">coordsRemove</a>(ZincItem *item, int coordIndex, int contourIndex=-1)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a150">createBitmapFromData</a>(String image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a149">createBitmapFromFile</a>(String image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a151">createBitmapFromName</a>(String image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a153">createFont</a>(String family, int size, int bold=-1, int italic=-1, int underline=-1, int overstrike=-1)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a152">createImageFromAGGBuffer</a>(int width, int height, unsigned char *aggBuffer)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a148">createImageFromData</a>(String image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a147">createImageFromFile</a>(String image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a36">createTag</a>(String tag)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a25">dTag</a>(ZincItem *item, String tag=String(""))</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s2">fntCmdInfo</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s3">focCmdInfo</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a27">focus</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a4">getBackcolor</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a12">getBorderwidth</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a14">getFont</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a154">getFontAscent</a>(ZincFont *font)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a6">getForecolor</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a10">getHeight</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a156">getImageHeight</a>(ZincImage *image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a155">getImageWidth</a>(ZincImage *image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a26">getTags</a>(ZincItem *item, String ***tagList)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a8">getWidth</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a29">gname</a>(String gradient, String gname)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a30">group</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#o0">id</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s1">imgCmdInfo</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s8">interp</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a28">isGname</a>(String gname)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a46">itemBind</a>(ZincItem *item, String eventSpecification, ZincItemCallback callBack, void *userData, bool add=false)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a40">itemCreateArc</a>(ZincItem *parentGroup, double x, double y, double width, double height)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a42">itemCreateCurve</a>(ZincItem *parentGroup, ZincPath *path)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a38">itemCreateGroup</a>(ZincItem *parentGroup)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a43">itemCreateIcon</a>(ZincItem *parentGroup, ZincImage *image)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a39">itemCreateRectangle</a>(ZincItem *parentGroup, double x, double y, double width, double height)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a41">itemCreateText</a>(ZincItem *parentGroup)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a128">itemGetAlignment</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a110">itemGetAlpha</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a116">itemGetAnchor</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a112">itemGetAtomic</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a100">itemGetCapstyle</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a114">itemGetClip</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a64">itemGetClosed</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a118">itemGetColor</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a66">itemGetComposealpha</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a68">itemGetComposerotation</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a70">itemGetComposescale</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a120">itemGetConnecteditem</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a122">itemGetConnectionanchor</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a72">itemGetExtent</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a74">itemGetFillcolor</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a76">itemGetFilled</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a78">itemGetFillpattern</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a102">itemGetFillrule</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a142">itemGetFirstend</a>(ZincItem *item, double *a, double *b, double *c)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a130">itemGetFont</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a124">itemGetImage</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a104">itemGetJoinstyle</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a144">itemGetLastend</a>(ZincItem *item, double *a, double *b, double *c)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a80">itemGetLinecolor</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a82">itemGetLinepattern</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a84">itemGetLinestyle</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a86">itemGetLinewidth</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a126">itemGetMask</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a132">itemGetOverstriked</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a88">itemGetPieslice</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a146">itemGetPosition</a>(ZincItem *item, double *x, double *y)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a90">itemGetPriority</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a106">itemGetRelief</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a92">itemGetSensitive</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a108">itemGetSmoothrelief</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a134">itemGetSpacing</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a94">itemGetStartangle</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a136">itemGetText</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a96">itemGetTile</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a61">itemGetTransformation</a>(ZincItem *item, double *a, double *b, double *c, double *d, double *e, double *f)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a138">itemGetUnderlined</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a98">itemGetVisible</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a140">itemGetWidth</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a62">itemMatrix</a>(ZincItem *item, double a, double b, double c, double d, double e, double f)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a37">itemRemove</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a59">itemResetTransformation</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a50">itemRotate</a>(ZincItem *item, double angle)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a51">itemRotate</a>(ZincItem *item, double angle, double x, double y)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a52">itemRotate</a>(ZincItem *item, double angle, bool degree)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a53">itemRotate</a>(ZincItem *item, double angle, double x, double y, bool degree)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a54">itemScale</a>(ZincItem *item, double ax, double ay)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a55">itemScale</a>(ZincItem *item, double ax, double ay, double cx, double cy)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a127">itemSetAlignment</a>(ZincItem *item, alignment value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a109">itemSetAlpha</a>(ZincItem *item, unsigned int value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a115">itemSetAnchor</a>(ZincItem *item, anchor value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a111">itemSetAtomic</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a99">itemSetCapstyle</a>(ZincItem *item, capStyle value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a113">itemSetClip</a>(ZincItem *item, ZincItem *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a63">itemSetClosed</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a117">itemSetColor</a>(ZincItem *item, String value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a65">itemSetComposealpha</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a67">itemSetComposerotation</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a69">itemSetComposescale</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a119">itemSetConnecteditem</a>(ZincItem *item, ZincItem *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a121">itemSetConnectionanchor</a>(ZincItem *item, anchor value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a71">itemSetExtent</a>(ZincItem *item, unsigned int value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a73">itemSetFillcolor</a>(ZincItem *item, String value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a75">itemSetFilled</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a77">itemSetFillpattern</a>(ZincItem *item, ZincBitmap *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a101">itemSetFillrule</a>(ZincItem *item, fillRule value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a141">itemSetFirstend</a>(ZincItem *item, double a, double b, double c)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a129">itemSetFont</a>(ZincItem *item, ZincFont *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a123">itemSetImage</a>(ZincItem *item, ZincImage *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a103">itemSetJoinstyle</a>(ZincItem *item, joinStyle value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a143">itemSetLastend</a>(ZincItem *item, double a, double b, double c)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a79">itemSetLinecolor</a>(ZincItem *item, String value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a81">itemSetLinepattern</a>(ZincItem *item, ZincBitmap *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a83">itemSetLinestyle</a>(ZincItem *item, lineStyle value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a85">itemSetLinewidth</a>(ZincItem *item, double value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a125">itemSetMask</a>(ZincItem *item, ZincBitmap *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a131">itemSetOverstriked</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a87">itemSetPieslice</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a145">itemSetPosition</a>(ZincItem *item, double x, double y)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a89">itemSetPriority</a>(ZincItem *item, unsigned int value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a105">itemSetRelief</a>(ZincItem *item, relief value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a91">itemSetSensitive</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a107">itemSetSmoothrelief</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a133">itemSetSpacing</a>(ZincItem *item, short value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a93">itemSetStartangle</a>(ZincItem *item, unsigned int value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a135">itemSetText</a>(ZincItem *item, String value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a95">itemSetTile</a>(ZincItem *item, ZincBitmap *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a60">itemSetTransformation</a>(ZincItem *item, double a, double b, double c, double d, double e, double f)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a137">itemSetUnderlined</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a97">itemSetVisible</a>(ZincItem *item, bool value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a139">itemSetWidth</a>(ZincItem *item, unsigned short value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a56">itemSkew</a>(ZincItem *item, double sx, double sy)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a57">itemSkewX</a>(ZincItem *item, double sx)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a58">itemSkewY</a>(ZincItem *item, double sy)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a48">itemTranslate</a>(ZincItem *item, double dx, double dy)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a49">itemTranslate</a>(ZincItem *item, double x, double y, bool absolute)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a47">itemUnbind</a>(ZincItem *item, String eventSpecification)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#e0">loadZinc</a>(char *argv0)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a31">lower</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a32">lower</a>(ZincItem *item, ZincItem *belowThis)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#o1">objCmd</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s6">p1</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s7">p2</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s5">pool</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a33">raise</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a34">raise</a>(ZincItem *item, ZincItem *aboveThis)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a16">relativeBbox</a>(ZincItem *item, double bbox[4])</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a3">setBackcolor</a>(String value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a11">setBorderwidth</a>(int value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a13">setFont</a>(ZincFont *value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a5">setForecolor</a>(String value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a9">setHeight</a>(int value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a2">setTitle</a>(String title)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a7">setWidth</a>(int value)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#o3">tclCb</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a35">type</a>(ZincItem *item)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a45">unbind</a>(String eventSpecification)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#o2">wi</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#o5">window</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a157">z_command</a>(int count, char *p_msg)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#e2">z_tcl_call</a>(int result, char *p_msg)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a0">Zinc</a>(int renderingMode)</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#e1">zincMainLoop</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#n0">ZincPath</a> class</td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [friend]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#s0">znCount</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td><code> [static]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#o4">znId</a></td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZinc.html#a1">~Zinc</a>()</td><td><a class="el" href="classZinc.html">Zinc</a></td><td></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZinc.html.



































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Zinc class Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>Zinc Class Reference</h1><code>#include &lt;<a class="el" href="Zinc_8hpp-source.html">Zinc.hpp</a>&gt;</code>
<p>
<a href="classZinc-members.html">List of all members.</a><hr><a name="_details"></a><h2>Detailed Description</h2>
This class contains a zinc widget and members to create and modify items 
<p>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a0">Zinc</a> (int renderingMode)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a1">~Zinc</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a2">setTitle</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> title)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a3">setBackcolor</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a4">getBackcolor</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a5">setForecolor</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a6">getForecolor</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a7">setWidth</a> (int value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a8">getWidth</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a9">setHeight</a> (int value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a10">getHeight</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a11">setBorderwidth</a> (int value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a12">getBorderwidth</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a13">setFont</a> (<a class="el" href="classZincFont.html">ZincFont</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincFont.html">ZincFont</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a14">getFont</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a15">bbox</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double bbox[4])</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a16">relativeBbox</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double bbox[4])</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a17">chggroup</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincItem.html">ZincItem</a> *parentGroup)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a18">clone</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a19">contour</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a20">contour</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a59">itemOperator</a> flag, <a class="el" href="classZincItem.html">ZincItem</a> *reference)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a21">contour</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool add, <a class="el" href="classZincPath.html">ZincPath</a> *contour)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a22">coords</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincPath.html">ZincPath</a> *contour, bool add, int contourIndex=-1, int coordIndex=-1)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a23">coordsRemove</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, int coordIndex, int contourIndex=-1)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a24">addTag</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> tag)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a25">dTag</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> tag=<a class="el" href="ZincTypes_8hpp.html#a0">String</a>(""))</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a26">getTags</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> ***tagList)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a27">focus</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a28">isGname</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> gname)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a29">gname</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> gradient, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> gname)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a30">group</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a31">lower</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a32">lower</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincItem.html">ZincItem</a> *belowThis)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a33">raise</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a34">raise</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincItem.html">ZincItem</a> *aboveThis)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a60">itemType</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a35">type</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a36">createTag</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> tag)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a37">itemRemove</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a38">itemCreateGroup</a> (<a class="el" href="classZincItem.html">ZincItem</a> *parentGroup)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a39">itemCreateRectangle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *parentGroup, double x, double y, double width, double height)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a40">itemCreateArc</a> (<a class="el" href="classZincItem.html">ZincItem</a> *parentGroup, double x, double y, double width, double height)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a41">itemCreateText</a> (<a class="el" href="classZincItem.html">ZincItem</a> *parentGroup)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a42">itemCreateCurve</a> (<a class="el" href="classZincItem.html">ZincItem</a> *parentGroup, <a class="el" href="classZincPath.html">ZincPath</a> *path)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a43">itemCreateIcon</a> (<a class="el" href="classZincItem.html">ZincItem</a> *parentGroup, <a class="el" href="classZincImage.html">ZincImage</a> *image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a44">bind</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> eventSpecification, <a class="el" href="ZincTypes_8hpp.html#a2">ZincWidgetCallback</a> callBack, void *userData, bool add=false)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a45">unbind</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> eventSpecification)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a46">itemBind</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> eventSpecification, <a class="el" href="ZincTypes_8hpp.html#a1">ZincItemCallback</a> callBack, void *userData, bool add=false)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a47">itemUnbind</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> eventSpecification)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a48">itemTranslate</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double dx, double dy)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a49">itemTranslate</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double x, double y, bool absolute)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a50">itemRotate</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double angle)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a51">itemRotate</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double angle, double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a52">itemRotate</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double angle, bool degree)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a53">itemRotate</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double angle, double x, double y, bool degree)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a54">itemScale</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double ax, double ay)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a55">itemScale</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double ax, double ay, double cx, double cy)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a56">itemSkew</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double sx, double sy)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a57">itemSkewX</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double sx)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a58">itemSkewY</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double sy)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a59">itemResetTransformation</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a60">itemSetTransformation</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double a, double b, double c, double d, double e, double f)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a61">itemGetTransformation</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double *a, double *b, double *c, double *d, double *e, double *f)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a62">itemMatrix</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double a, double b, double c, double d, double e, double f)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a63">itemSetClosed</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a64">itemGetClosed</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a65">itemSetComposealpha</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a66">itemGetComposealpha</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a67">itemSetComposerotation</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a68">itemGetComposerotation</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a69">itemSetComposescale</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a70">itemGetComposescale</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a71">itemSetExtent</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, unsigned int value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>unsigned int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a72">itemGetExtent</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a73">itemSetFillcolor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a74">itemGetFillcolor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a75">itemSetFilled</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a76">itemGetFilled</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a77">itemSetFillpattern</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincBitmap.html">ZincBitmap</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a78">itemGetFillpattern</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a79">itemSetLinecolor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a80">itemGetLinecolor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a81">itemSetLinepattern</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincBitmap.html">ZincBitmap</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a82">itemGetLinepattern</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a83">itemSetLinestyle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a52">lineStyle</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a52">lineStyle</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a84">itemGetLinestyle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a85">itemSetLinewidth</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>double&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a86">itemGetLinewidth</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a87">itemSetPieslice</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a88">itemGetPieslice</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a89">itemSetPriority</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, unsigned int value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>unsigned int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a90">itemGetPriority</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a91">itemSetSensitive</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a92">itemGetSensitive</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a93">itemSetStartangle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, unsigned int value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>unsigned int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a94">itemGetStartangle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a95">itemSetTile</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincBitmap.html">ZincBitmap</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a96">itemGetTile</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a97">itemSetVisible</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a98">itemGetVisible</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a99">itemSetCapstyle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a53">capStyle</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a53">capStyle</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a100">itemGetCapstyle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a101">itemSetFillrule</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a54">fillRule</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a54">fillRule</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a102">itemGetFillrule</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a103">itemSetJoinstyle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a55">joinStyle</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a55">joinStyle</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a104">itemGetJoinstyle</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a105">itemSetRelief</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a56">relief</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a56">relief</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a106">itemGetRelief</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a107">itemSetSmoothrelief</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a108">itemGetSmoothrelief</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a109">itemSetAlpha</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, unsigned int value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>unsigned int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a110">itemGetAlpha</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a111">itemSetAtomic</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a112">itemGetAtomic</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a113">itemSetClip</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincItem.html">ZincItem</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a114">itemGetClip</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a115">itemSetAnchor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a58">anchor</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a58">anchor</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a116">itemGetAnchor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a117">itemSetColor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a118">itemGetColor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a119">itemSetConnecteditem</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincItem.html">ZincItem</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a120">itemGetConnecteditem</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a121">itemSetConnectionanchor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a58">anchor</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a58">anchor</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a122">itemGetConnectionanchor</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a123">itemSetImage</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincImage.html">ZincImage</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a124">itemGetImage</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a125">itemSetMask</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincBitmap.html">ZincBitmap</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a126">itemGetMask</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a127">itemSetAlignment</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a57">alignment</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a57">alignment</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a128">itemGetAlignment</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a129">itemSetFont</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="classZincFont.html">ZincFont</a> *value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincFont.html">ZincFont</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a130">itemGetFont</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a131">itemSetOverstriked</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a132">itemGetOverstriked</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a133">itemSetSpacing</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, short value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>short&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a134">itemGetSpacing</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a135">itemSetText</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, <a class="el" href="ZincTypes_8hpp.html#a0">String</a> value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a136">itemGetText</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a137">itemSetUnderlined</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, bool value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>bool&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a138">itemGetUnderlined</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a139">itemSetWidth</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, unsigned short value)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>unsigned short&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a140">itemGetWidth</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a141">itemSetFirstend</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double a, double b, double c)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a142">itemGetFirstend</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double *a, double *b, double *c)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a143">itemSetLastend</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double a, double b, double c)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a144">itemGetLastend</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double *a, double *b, double *c)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a145">itemSetPosition</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a146">itemGetPosition</a> (<a class="el" href="classZincItem.html">ZincItem</a> *item, double *x, double *y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a147">createImageFromFile</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a148">createImageFromData</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a149">createBitmapFromFile</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a150">createBitmapFromData</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a151">createBitmapFromName</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a152">createImageFromAGGBuffer</a> (int width, int height, unsigned char *aggBuffer)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="classZincFont.html">ZincFont</a> *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a153">createFont</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> family, int size, int bold=-1, int italic=-1, int underline=-1, int overstrike=-1)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a154">getFontAscent</a> (<a class="el" href="classZincFont.html">ZincFont</a> *font)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a155">getImageWidth</a> (<a class="el" href="classZincImage.html">ZincImage</a> *image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a156">getImageHeight</a> (<a class="el" href="classZincImage.html">ZincImage</a> *image)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#a157">z_command</a> (int count, char *p_msg)  throw (ZincException)</td></tr>

<tr><td colspan=2><br><h2>Static Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#e0">loadZinc</a> (char *argv0)  throw (ZincException)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#e1">zincMainLoop</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#e2">z_tcl_call</a> (int result, char *p_msg)  throw (ZincException)</td></tr>

<tr><td colspan=2><br><h2>Public Attributes</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#o0">id</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the id of this object </em> <a href="#o0"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincExtern_8hpp.html#a0">WidgetObjCmd</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#o1">objCmd</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the command associated with this object </em> <a href="#o1"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>ClientData&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#o2">wi</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the zinc object itself </em> <a href="#o2"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#o3">tclCb</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">name of the binding callback </em> <a href="#o3"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#o4">znId</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the znCount at creation time </em> <a href="#o4"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#o5">window</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the window which contains the widget </em> <a href="#o5"></a><em><br><br></td></tr>
<tr><td colspan=2><br><h2>Static Public Attributes</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s0">znCount</a> = 0</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">count to create unique ids </em> <a href="#s0"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_CmdInfo&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s1">imgCmdInfo</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the command associated with image </em> <a href="#s1"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_CmdInfo&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s2">fntCmdInfo</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the command associated with font </em> <a href="#s2"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_CmdInfo&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s3">focCmdInfo</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the command associated with fous </em> <a href="#s3"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_CmdInfo&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s4">bndCmdInfo</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the command associated with bind </em> <a href="#s4"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s5">pool</a> [<a class="el" href="Zinc_8hpp.html#a0">ZINC_POOL_COUNT</a>]</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">a pool of tclobj ready to be used </em> <a href="#s5"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s6">p1</a> [<a class="el" href="Zinc_8hpp.html#a1">ZINC_PARAM_COUNT</a>]</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">table of pointeur use for parameters </em> <a href="#s6"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s7">p2</a> [<a class="el" href="Zinc_8hpp.html#a1">ZINC_PARAM_COUNT</a>]</td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">table of pointeur use for parameters </em> <a href="#s7"></a><em><br><br></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Interp *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#s8">interp</a></td></tr>

<tr><td class="mdescLeft">&nbsp;</td><td class="mdescRight">the tcl interpreter </em> <a href="#s8"></a><em><br><br></td></tr>
<tr><td colspan=2><br><h2>Friends</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>class&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZinc.html#n0">ZincPath</a></td></tr>

</table>
<hr><h2>Constructor &amp; Destructor Documentation</h2>
<a name="a0" doxytag="Zinc::Zinc"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Zinc::Zinc </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>renderingMode</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>renderingMode</em>&nbsp;</td><td>ZINC_BACKEND_X11 or ZINC_BACKEND_OPENGL </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a1" doxytag="Zinc::~Zinc"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Zinc::~<a class="el" href="classZinc.html">Zinc</a> </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public destructor     </td>
  </tr>
</table>
<hr><h2>Member Function Documentation</h2>
<a name="a24" doxytag="Zinc::addTag"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::addTag </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>tag</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Add a tag to an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to add tag to </td></tr>
    <tr><td valign=top><em>tag</em>&nbsp;</td><td>a tag to add </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a15" doxytag="Zinc::bbox"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::bbox </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>bbox</em>[4]</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Get the bounding box of an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get bbox </td></tr>
    <tr><td valign=top><em>bbox</em>&nbsp;</td><td>a table where we'll put the bounding box bbox[0] = x0, bbox[1] = y0, bbox[2] = xc, bbox[3] = yc </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a44" doxytag="Zinc::bind"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::bind </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>eventSpecification</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a2">ZincWidgetCallback</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>callBack</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>void *&nbsp;</td>
          <td class="mdname" nowrap> <em>userData</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>add</em> = false</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Bind a function to an event on the zinc widget<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>eventSpecification</em>&nbsp;</td><td>tcl style event specicication </td></tr>
    <tr><td valign=top><em>callBack</em>&nbsp;</td><td>the function which will be called back </td></tr>
    <tr><td valign=top><em>userData</em>&nbsp;</td><td>data we will give back to the callback when called </td></tr>
    <tr><td valign=top><em>add</em>&nbsp;</td><td>false to replace existing bind or true to add </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a17" doxytag="Zinc::chggroup"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::chggroup </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>parentGroup</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Change the group of an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to move </td></tr>
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>new group for the item </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a18" doxytag="Zinc::clone"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::clone </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Clone an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to clone </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the cloned item </dd></dl>
    </td>
  </tr>
</table>
<a name="a21" doxytag="Zinc::contour"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::contour </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>add</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincPath.html">ZincPath</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>contour</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Set the contour of an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item on which we set the contour </td></tr>
    <tr><td valign=top><em>add</em>&nbsp;</td><td>true to add a path, false to remove </td></tr>
    <tr><td valign=top><em>reference</em>&nbsp;</td><td>the new contour </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the number of contour </dd></dl>
    </td>
  </tr>
</table>
<a name="a20" doxytag="Zinc::contour"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::contour </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a59">itemOperator</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>flag</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>reference</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Set the contour of an item to the one of an other<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item on which we set the contour </td></tr>
    <tr><td valign=top><em>flag</em>&nbsp;</td><td>the operation to do on the contour </td></tr>
    <tr><td valign=top><em>reference</em>&nbsp;</td><td>the item to set contour from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the number of contour </dd></dl>
    </td>
  </tr>
</table>
<a name="a19" doxytag="Zinc::contour"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::contour </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Get the number of contour of an item<p>
<dl compact><dt><b>Returns:</b></dt><dd>number of contour </dd></dl>
    </td>
  </tr>
</table>
<a name="a22" doxytag="Zinc::coords"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::coords </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincPath.html">ZincPath</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>contour</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>add</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>contourIndex</em> = -1, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>coordIndex</em> = -1</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Set or modify the coordinates of an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to modify </td></tr>
    <tr><td valign=top><em>contour</em>&nbsp;</td><td>new coords for the item </td></tr>
    <tr><td valign=top><em>add</em>&nbsp;</td><td>true to add coords, false to replace </td></tr>
    <tr><td valign=top><em>contourIndex</em>&nbsp;</td><td>the contour do modify </td></tr>
    <tr><td valign=top><em>coordIndex</em>&nbsp;</td><td>the coordinate to modify (WARNING, path must be one point if the is not the default) </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a23" doxytag="Zinc::coordsRemove"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::coordsRemove </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>coordIndex</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>contourIndex</em> = -1</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Remove coords of an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to modify </td></tr>
    <tr><td valign=top><em>coordIndex</em>&nbsp;</td><td>the coordinate to rmove </td></tr>
    <tr><td valign=top><em>contourIndex</em>&nbsp;</td><td>the contour on which we remove </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a150" doxytag="Zinc::createBitmapFromData"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincBitmap.html">ZincBitmap</a> * Zinc::createBitmapFromData </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>image</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a bitmap object base64 data<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>image</em>&nbsp;</td><td>the bitmap reference (a base64 String or binary data) </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a149" doxytag="Zinc::createBitmapFromFile"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincBitmap.html">ZincBitmap</a> * Zinc::createBitmapFromFile </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>image</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a bitmap object from a file<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>image</em>&nbsp;</td><td>the bitmap reference (a file name) </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a151" doxytag="Zinc::createBitmapFromName"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincBitmap.html">ZincBitmap</a> * Zinc::createBitmapFromName </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>image</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a bitmap object using a predefined name<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>image</em>&nbsp;</td><td>the bitmap reference (a name) </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a153" doxytag="Zinc::createFont"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincFont.html">ZincFont</a> * Zinc::createFont </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>family</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>size</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>bold</em> = -1, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>italic</em> = -1, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>underline</em> = -1, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>overstrike</em> = -1</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a font object<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>family</em>&nbsp;</td><td>the font mamily </td></tr>
    <tr><td valign=top><em>size</em>&nbsp;</td><td>if a positive number, it is in points, if a negative number, its absolute value is a size in pixels. </td></tr>
    <tr><td valign=top><em>bold</em>&nbsp;</td><td>1 for a bold font, 0 for a normal font, -1 for unspecified </td></tr>
    <tr><td valign=top><em>italic</em>&nbsp;</td><td>1 an italic font, 0 for a roman font, -1 for unspecified </td></tr>
    <tr><td valign=top><em>underline</em>&nbsp;</td><td>1 for an underlined, 0 for a normal font, -1 for unspecified </td></tr>
    <tr><td valign=top><em>overstrike</em>&nbsp;</td><td>1 for an overstriked font, 0 for a normal font, -1 for unspecified </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a152" doxytag="Zinc::createImageFromAGGBuffer"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincImage.html">ZincImage</a> * Zinc::createImageFromAGGBuffer </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname" nowrap> <em>width</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>height</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>unsigned char *&nbsp;</td>
          <td class="mdname" nowrap> <em>aggBuffer</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create an image object<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>width</em>&nbsp;</td><td>Width of image </td></tr>
    <tr><td valign=top><em>height</em>&nbsp;</td><td>Height of image </td></tr>
    <tr><td valign=top><em>aggBuffer</em>&nbsp;</td><td>An AGG buffer </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a148" doxytag="Zinc::createImageFromData"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincImage.html">ZincImage</a> * Zinc::createImageFromData </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>image</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create an image object using base64 data<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>image</em>&nbsp;</td><td>the image reference (a base64 String or binary data) </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a147" doxytag="Zinc::createImageFromFile"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincImage.html">ZincImage</a> * Zinc::createImageFromFile </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>image</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create an image object from a file<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>image</em>&nbsp;</td><td>the image reference (a file name) </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a36" doxytag="Zinc::createTag"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::createTag </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>tag</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a Zinc Tag that can be used in place of any item for zinc functions that must be called using tagOrId<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>tag</em>&nbsp;</td><td>the text of the tag </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>a tag item </dd></dl>
    </td>
  </tr>
</table>
<a name="a25" doxytag="Zinc::dTag"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::dTag </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>tag</em> = <a class="el" href="ZincTypes_8hpp.html#a0">String</a>("")</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Remove a tag from an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to remove tag from </td></tr>
    <tr><td valign=top><em>tag</em>&nbsp;</td><td>a tag to remove (nothing to remove all tags) </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a27" doxytag="Zinc::focus"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::focus </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Set the focus to an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to set the focus to </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a4" doxytag="Zinc::getBackcolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> Zinc::getBackcolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;cget ( -backcolor )<p>
<dl compact><dt><b>Returns:</b></dt><dd>backcolor value </dd></dl>
    </td>
  </tr>
</table>
<a name="a12" doxytag="Zinc::getBorderwidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::getBorderwidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;cget ( -borderwidth )<p>
<dl compact><dt><b>Returns:</b></dt><dd>borderwidth value </dd></dl>
    </td>
  </tr>
</table>
<a name="a14" doxytag="Zinc::getFont"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincFont.html">ZincFont</a> * Zinc::getFont </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;cget ( -font )<p>
<dl compact><dt><b>Returns:</b></dt><dd>font value </dd></dl>
    </td>
  </tr>
</table>
<a name="a154" doxytag="Zinc::getFontAscent"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::getFontAscent </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincFont.html">ZincFont</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>font</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Get font ascent<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>font</em>&nbsp;</td><td>the font </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the font ascent </dd></dl>
    </td>
  </tr>
</table>
<a name="a6" doxytag="Zinc::getForecolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> Zinc::getForecolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;cget ( -forecolor )<p>
<dl compact><dt><b>Returns:</b></dt><dd>forecolor value </dd></dl>
    </td>
  </tr>
</table>
<a name="a10" doxytag="Zinc::getHeight"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::getHeight </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;cget ( -height )<p>
<dl compact><dt><b>Returns:</b></dt><dd>height value </dd></dl>
    </td>
  </tr>
</table>
<a name="a156" doxytag="Zinc::getImageHeight"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::getImageHeight </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>image</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Get Image height<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>ZincImage</em>&nbsp;</td><td>the image to get height from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the height of the image </dd></dl>
    </td>
  </tr>
</table>
<a name="a155" doxytag="Zinc::getImageWidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::getImageWidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>image</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Get Image width<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>ZincImage</em>&nbsp;</td><td>the image to get width from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the width of the image </dd></dl>
    </td>
  </tr>
</table>
<a name="a26" doxytag="Zinc::getTags"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::getTags </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a> ***&nbsp;</td>
          <td class="mdname" nowrap> <em>tagList</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
List all tags of an item It's up to the caller to delete the resulting table and strings<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to list tag from </td></tr>
    <tr><td valign=top><em>lagList</em>&nbsp;</td><td>a pointer to a table of String containing tags </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the number of tags </dd></dl>
    </td>
  </tr>
</table>
<a name="a8" doxytag="Zinc::getWidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int Zinc::getWidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;cget ( -width )<p>
<dl compact><dt><b>Returns:</b></dt><dd>width value </dd></dl>
    </td>
  </tr>
</table>
<a name="a29" doxytag="Zinc::gname"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::gname </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>gradient</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>gname</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a named gradient<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>gradient</em>&nbsp;</td><td>a gradient </td></tr>
    <tr><td valign=top><em>gname</em>&nbsp;</td><td>a gradient name </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a30" doxytag="Zinc::group"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::group </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Retreive the group of an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get the group from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the group </dd></dl>
    </td>
  </tr>
</table>
<a name="a28" doxytag="Zinc::isGname"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::isGname </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>gname</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Tell if the name is a gradient name<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>gname</em>&nbsp;</td><td>a gradient name </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>true if the name is a gradient name, false otherwise </dd></dl>
    </td>
  </tr>
</table>
<a name="a46" doxytag="Zinc::itemBind"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemBind </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>eventSpecification</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a1">ZincItemCallback</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>callBack</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>void *&nbsp;</td>
          <td class="mdname" nowrap> <em>userData</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>add</em> = false</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Bind a function to an event on an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item on which to bind </td></tr>
    <tr><td valign=top><em>eventSpecification</em>&nbsp;</td><td>tcl style event specicication </td></tr>
    <tr><td valign=top><em>callBack</em>&nbsp;</td><td>the function which will be called back </td></tr>
    <tr><td valign=top><em>userData</em>&nbsp;</td><td>data we will give back to the callback when called </td></tr>
    <tr><td valign=top><em>add</em>&nbsp;</td><td>false to replace existing bind or true to add </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a40" doxytag="Zinc::itemCreateArc"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemCreateArc </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>parentGroup</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>width</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>height</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create an arc item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>group where we'll put it </td></tr>
    <tr><td valign=top><em>x</em>&nbsp;</td><td>y width height the coordinates of the new rectangle </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the arc item </dd></dl>
    </td>
  </tr>
</table>
<a name="a42" doxytag="Zinc::itemCreateCurve"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemCreateCurve </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>parentGroup</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincPath.html">ZincPath</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>path</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a curve item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>group where we'll put it </td></tr>
    <tr><td valign=top><em>path</em>&nbsp;</td><td>the path to display </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the curve item </dd></dl>
    </td>
  </tr>
</table>
<a name="a38" doxytag="Zinc::itemCreateGroup"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemCreateGroup </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>parentGroup</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a group item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>group where we'll put the new group, if NULL we create in the defaults group </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the group item </dd></dl>
    </td>
  </tr>
</table>
<a name="a43" doxytag="Zinc::itemCreateIcon"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemCreateIcon </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>parentGroup</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>image</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create an icon item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>group where we'll put it </td></tr>
    <tr><td valign=top><em>image</em>&nbsp;</td><td>a zincImage to display </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the icon item </dd></dl>
    </td>
  </tr>
</table>
<a name="a39" doxytag="Zinc::itemCreateRectangle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemCreateRectangle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>parentGroup</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>width</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>height</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a rectangle item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>group where we'll put it </td></tr>
    <tr><td valign=top><em>x</em>&nbsp;</td><td>y width height the coordinates of the new rectangle </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the rectangle item </dd></dl>
    </td>
  </tr>
</table>
<a name="a41" doxytag="Zinc::itemCreateText"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemCreateText </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>parentGroup</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Create a text item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>parentGroup</em>&nbsp;</td><td>group where we'll put it </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the text item </dd></dl>
    </td>
  </tr>
</table>
<a name="a128" doxytag="Zinc::itemGetAlignment"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a57">alignment</a> Zinc::itemGetAlignment </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -alignment ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get alignment from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>alignment value </dd></dl>
    </td>
  </tr>
</table>
<a name="a110" doxytag="Zinc::itemGetAlpha"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> unsigned int Zinc::itemGetAlpha </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -alpha ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get alpha from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>alpha value </dd></dl>
    </td>
  </tr>
</table>
<a name="a116" doxytag="Zinc::itemGetAnchor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a58">anchor</a> Zinc::itemGetAnchor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -anchor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get anchor from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>anchor value </dd></dl>
    </td>
  </tr>
</table>
<a name="a112" doxytag="Zinc::itemGetAtomic"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetAtomic </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -atomic ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get atomic from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>atomic value </dd></dl>
    </td>
  </tr>
</table>
<a name="a100" doxytag="Zinc::itemGetCapstyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a53">capStyle</a> Zinc::itemGetCapstyle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -capstyle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get capstyle from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>capstyle value </dd></dl>
    </td>
  </tr>
</table>
<a name="a114" doxytag="Zinc::itemGetClip"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemGetClip </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -clip ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get clip from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>clip value </dd></dl>
    </td>
  </tr>
</table>
<a name="a64" doxytag="Zinc::itemGetClosed"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetClosed </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -closed ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get closed from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>closed value </dd></dl>
    </td>
  </tr>
</table>
<a name="a118" doxytag="Zinc::itemGetColor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> Zinc::itemGetColor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -color ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get color from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>color value </dd></dl>
    </td>
  </tr>
</table>
<a name="a66" doxytag="Zinc::itemGetComposealpha"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetComposealpha </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -composealpha ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get composealpha from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>composealpha value </dd></dl>
    </td>
  </tr>
</table>
<a name="a68" doxytag="Zinc::itemGetComposerotation"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetComposerotation </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -composerotation ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get composerotation from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>composerotation value </dd></dl>
    </td>
  </tr>
</table>
<a name="a70" doxytag="Zinc::itemGetComposescale"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetComposescale </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -composescale ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get composescale from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>composescale value </dd></dl>
    </td>
  </tr>
</table>
<a name="a120" doxytag="Zinc::itemGetConnecteditem"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincItem.html">ZincItem</a> * Zinc::itemGetConnecteditem </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -connecteditem ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get connecteditem from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>connecteditem value </dd></dl>
    </td>
  </tr>
</table>
<a name="a122" doxytag="Zinc::itemGetConnectionanchor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a58">anchor</a> Zinc::itemGetConnectionanchor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -connectionanchor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get connectionanchor from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>connectionanchor value </dd></dl>
    </td>
  </tr>
</table>
<a name="a72" doxytag="Zinc::itemGetExtent"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> unsigned int Zinc::itemGetExtent </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -extent ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get extent from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>extent value </dd></dl>
    </td>
  </tr>
</table>
<a name="a74" doxytag="Zinc::itemGetFillcolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> Zinc::itemGetFillcolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -fillcolor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get fillcolor from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>fillcolor value </dd></dl>
    </td>
  </tr>
</table>
<a name="a76" doxytag="Zinc::itemGetFilled"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetFilled </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -filled ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get filled from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>filled value </dd></dl>
    </td>
  </tr>
</table>
<a name="a78" doxytag="Zinc::itemGetFillpattern"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincBitmap.html">ZincBitmap</a> * Zinc::itemGetFillpattern </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -fillpattern ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get fillpattern from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>fillpattern value </dd></dl>
    </td>
  </tr>
</table>
<a name="a102" doxytag="Zinc::itemGetFillrule"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a54">fillRule</a> Zinc::itemGetFillrule </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -fillrule ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get fillrule from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>fillrule value </dd></dl>
    </td>
  </tr>
</table>
<a name="a142" doxytag="Zinc::itemGetFirstend"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemGetFirstend </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>a</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>b</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>c</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -firstend )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get firstend from </td></tr>
    <tr><td valign=top><em>a,b,c</em>&nbsp;</td><td>values used to sedwhere we'll put end </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a130" doxytag="Zinc::itemGetFont"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincFont.html">ZincFont</a> * Zinc::itemGetFont </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -font ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get font from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>font value </dd></dl>
    </td>
  </tr>
</table>
<a name="a124" doxytag="Zinc::itemGetImage"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincImage.html">ZincImage</a> * Zinc::itemGetImage </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -image ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get image from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>image value </dd></dl>
    </td>
  </tr>
</table>
<a name="a104" doxytag="Zinc::itemGetJoinstyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a55">joinStyle</a> Zinc::itemGetJoinstyle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -joinstyle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get joinstyle from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>joinstyle value </dd></dl>
    </td>
  </tr>
</table>
<a name="a144" doxytag="Zinc::itemGetLastend"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemGetLastend </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>a</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>b</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>c</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -lastend )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get lastend from </td></tr>
    <tr><td valign=top><em>a,b,c</em>&nbsp;</td><td>values used to sedwhere we'll put end </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a80" doxytag="Zinc::itemGetLinecolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> Zinc::itemGetLinecolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -linecolor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get linecolor from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>linecolor value </dd></dl>
    </td>
  </tr>
</table>
<a name="a82" doxytag="Zinc::itemGetLinepattern"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincBitmap.html">ZincBitmap</a> * Zinc::itemGetLinepattern </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -linepattern ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get linepattern from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>linepattern value </dd></dl>
    </td>
  </tr>
</table>
<a name="a84" doxytag="Zinc::itemGetLinestyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a52">lineStyle</a> Zinc::itemGetLinestyle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -linestyle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get linestyle from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>linestyle value </dd></dl>
    </td>
  </tr>
</table>
<a name="a86" doxytag="Zinc::itemGetLinewidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> double Zinc::itemGetLinewidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -linewidth ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get linewidth from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>linewidth value </dd></dl>
    </td>
  </tr>
</table>
<a name="a126" doxytag="Zinc::itemGetMask"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincBitmap.html">ZincBitmap</a> * Zinc::itemGetMask </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -mask ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get mask from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>mask value </dd></dl>
    </td>
  </tr>
</table>
<a name="a132" doxytag="Zinc::itemGetOverstriked"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetOverstriked </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -overstriked ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get overstriked from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>overstriked value </dd></dl>
    </td>
  </tr>
</table>
<a name="a88" doxytag="Zinc::itemGetPieslice"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetPieslice </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -pieslice ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get pieslice from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>pieslice value </dd></dl>
    </td>
  </tr>
</table>
<a name="a146" doxytag="Zinc::itemGetPosition"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemGetPosition </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -position )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get position from </td></tr>
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>position </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a90" doxytag="Zinc::itemGetPriority"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> unsigned int Zinc::itemGetPriority </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -priority ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get priority from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>priority value </dd></dl>
    </td>
  </tr>
</table>
<a name="a106" doxytag="Zinc::itemGetRelief"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a56">relief</a> Zinc::itemGetRelief </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -relief ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get relief from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>relief value </dd></dl>
    </td>
  </tr>
</table>
<a name="a92" doxytag="Zinc::itemGetSensitive"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetSensitive </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -sensitive ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get sensitive from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>sensitive value </dd></dl>
    </td>
  </tr>
</table>
<a name="a108" doxytag="Zinc::itemGetSmoothrelief"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetSmoothrelief </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -smoothrelief ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get smoothrelief from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>smoothrelief value </dd></dl>
    </td>
  </tr>
</table>
<a name="a134" doxytag="Zinc::itemGetSpacing"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> short Zinc::itemGetSpacing </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -spacing ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get spacing from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>spacing value </dd></dl>
    </td>
  </tr>
</table>
<a name="a94" doxytag="Zinc::itemGetStartangle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> unsigned int Zinc::itemGetStartangle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -startangle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get startangle from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>startangle value </dd></dl>
    </td>
  </tr>
</table>
<a name="a136" doxytag="Zinc::itemGetText"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> Zinc::itemGetText </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -text ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get text from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>text value </dd></dl>
    </td>
  </tr>
</table>
<a name="a96" doxytag="Zinc::itemGetTile"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="classZincBitmap.html">ZincBitmap</a> * Zinc::itemGetTile </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -tile ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get tile from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>tile value </dd></dl>
    </td>
  </tr>
</table>
<a name="a61" doxytag="Zinc::itemGetTransformation"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemGetTransformation </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>a</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>b</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>c</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>d</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>e</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double *&nbsp;</td>
          <td class="mdname" nowrap> <em>f</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Get current transform matrix<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>a,b,c,d,e,f</em>&nbsp;</td><td>places where we'll put the transform matrix </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a138" doxytag="Zinc::itemGetUnderlined"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetUnderlined </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -underlined ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get underlined from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>underlined value </dd></dl>
    </td>
  </tr>
</table>
<a name="a98" doxytag="Zinc::itemGetVisible"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> bool Zinc::itemGetVisible </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -visible ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get visible from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>visible value </dd></dl>
    </td>
  </tr>
</table>
<a name="a140" doxytag="Zinc::itemGetWidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> unsigned short Zinc::itemGetWidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemcget ( -width ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get width from </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>width value </dd></dl>
    </td>
  </tr>
</table>
<a name="a62" doxytag="Zinc::itemMatrix"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemMatrix </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>a</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>b</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>c</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>d</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>e</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>f</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Multiply current transform by a matrix<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>a,b,c,d,e,f</em>&nbsp;</td><td>the new transform matrix </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a37" doxytag="Zinc::itemRemove"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemRemove </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Suppress an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to suppress </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a59" doxytag="Zinc::itemResetTransformation"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemResetTransformation </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Reset all transformations associated with the item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a53" doxytag="Zinc::itemRotate"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemRotate </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>angle</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>degree</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Rotate an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>angle</em>&nbsp;</td><td>the angle to rotate in radian </td></tr>
    <tr><td valign=top><em>x</em>&nbsp;</td><td>y the center of the rotation </td></tr>
    <tr><td valign=top><em>degree</em>&nbsp;</td><td>true for an angle in degree, false for an angle in radians </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a52" doxytag="Zinc::itemRotate"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemRotate </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>angle</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>degree</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Rotate an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>angle</em>&nbsp;</td><td>the angle to rotate </td></tr>
    <tr><td valign=top><em>degree</em>&nbsp;</td><td>true for an angle in degree, false for an angle in radians </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a51" doxytag="Zinc::itemRotate"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemRotate </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>angle</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Rotate an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>angle</em>&nbsp;</td><td>the angle to rotate in radian </td></tr>
    <tr><td valign=top><em>x</em>&nbsp;</td><td>y the center of the rotation </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a50" doxytag="Zinc::itemRotate"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemRotate </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>angle</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Rotate an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>angle</em>&nbsp;</td><td>the angle to rotate in radian </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a55" doxytag="Zinc::itemScale"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemScale </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>ax</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>ay</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cx</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cy</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Scale an item using a specified center<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>ax</em>&nbsp;</td><td>horizontal scale </td></tr>
    <tr><td valign=top><em>ay</em>&nbsp;</td><td>vertical scale </td></tr>
    <tr><td valign=top><em>cx</em>&nbsp;</td><td>cy center of the scale </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a54" doxytag="Zinc::itemScale"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemScale </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>ax</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>ay</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Scale an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>ax</em>&nbsp;</td><td>horizontal scale </td></tr>
    <tr><td valign=top><em>ay</em>&nbsp;</td><td>vertical scale </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a127" doxytag="Zinc::itemSetAlignment"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetAlignment </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a57">alignment</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -alignment ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the alignment to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a109" doxytag="Zinc::itemSetAlpha"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetAlpha </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>unsigned int&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -alpha ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the alpha to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a115" doxytag="Zinc::itemSetAnchor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetAnchor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a58">anchor</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -anchor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the anchor to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a111" doxytag="Zinc::itemSetAtomic"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetAtomic </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -atomic ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the atomic to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a99" doxytag="Zinc::itemSetCapstyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetCapstyle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a53">capStyle</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -capstyle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the capstyle to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a113" doxytag="Zinc::itemSetClip"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetClip </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -clip ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the clip to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a63" doxytag="Zinc::itemSetClosed"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetClosed </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -closed ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the closed to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a117" doxytag="Zinc::itemSetColor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetColor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -color ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the color to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a65" doxytag="Zinc::itemSetComposealpha"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetComposealpha </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -composealpha ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the composealpha to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a67" doxytag="Zinc::itemSetComposerotation"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetComposerotation </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -composerotation ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the composerotation to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a69" doxytag="Zinc::itemSetComposescale"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetComposescale </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -composescale ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the composescale to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a119" doxytag="Zinc::itemSetConnecteditem"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetConnecteditem </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -connecteditem ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the connecteditem to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a121" doxytag="Zinc::itemSetConnectionanchor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetConnectionanchor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a58">anchor</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -connectionanchor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the connectionanchor to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a71" doxytag="Zinc::itemSetExtent"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetExtent </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>unsigned int&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -extent ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the extent to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a73" doxytag="Zinc::itemSetFillcolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetFillcolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -fillcolor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the fillcolor to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a75" doxytag="Zinc::itemSetFilled"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetFilled </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -filled ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the filled to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a77" doxytag="Zinc::itemSetFillpattern"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetFillpattern </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -fillpattern ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the fillpattern to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a101" doxytag="Zinc::itemSetFillrule"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetFillrule </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a54">fillRule</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -fillrule ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the fillrule to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a141" doxytag="Zinc::itemSetFirstend"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetFirstend </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>a</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>b</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>c</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -firstend )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to set firstend to </td></tr>
    <tr><td valign=top><em>a,b,c</em>&nbsp;</td><td>values used to set end </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a129" doxytag="Zinc::itemSetFont"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetFont </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincFont.html">ZincFont</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -font ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the font to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a123" doxytag="Zinc::itemSetImage"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetImage </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincImage.html">ZincImage</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -image ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the image to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a103" doxytag="Zinc::itemSetJoinstyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetJoinstyle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a55">joinStyle</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -joinstyle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the joinstyle to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a143" doxytag="Zinc::itemSetLastend"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetLastend </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>a</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>b</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>c</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -lastend )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to set lastend to </td></tr>
    <tr><td valign=top><em>a,b,c</em>&nbsp;</td><td>values used to set end </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a79" doxytag="Zinc::itemSetLinecolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetLinecolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -linecolor ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the linecolor to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a81" doxytag="Zinc::itemSetLinepattern"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetLinepattern </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -linepattern ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the linepattern to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a83" doxytag="Zinc::itemSetLinestyle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetLinestyle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a52">lineStyle</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -linestyle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the linestyle to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a85" doxytag="Zinc::itemSetLinewidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetLinewidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -linewidth ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the linewidth to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a125" doxytag="Zinc::itemSetMask"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetMask </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -mask ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the mask to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a131" doxytag="Zinc::itemSetOverstriked"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetOverstriked </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -overstriked ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the overstriked to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a87" doxytag="Zinc::itemSetPieslice"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetPieslice </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -pieslice ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the pieslice to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a145" doxytag="Zinc::itemSetPosition"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetPosition </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -position )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get width fromset position to </td></tr>
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>position </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a89" doxytag="Zinc::itemSetPriority"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetPriority </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>unsigned int&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -priority ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the priority to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a105" doxytag="Zinc::itemSetRelief"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetRelief </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a56">relief</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -relief ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the relief to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a91" doxytag="Zinc::itemSetSensitive"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetSensitive </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -sensitive ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the sensitive to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a107" doxytag="Zinc::itemSetSmoothrelief"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetSmoothrelief </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -smoothrelief ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the smoothrelief to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a133" doxytag="Zinc::itemSetSpacing"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetSpacing </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>short&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -spacing ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the spacing to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a93" doxytag="Zinc::itemSetStartangle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetStartangle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>unsigned int&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -startangle ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the startangle to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a135" doxytag="Zinc::itemSetText"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetText </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -text ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the text to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a95" doxytag="Zinc::itemSetTile"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetTile </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincBitmap.html">ZincBitmap</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -tile ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the tile to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a60" doxytag="Zinc::itemSetTransformation"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetTransformation </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>a</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>b</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>c</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>d</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>e</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>f</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Replace current transform by a matrix<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>a,b,c,d,e,f</em>&nbsp;</td><td>the new transform matrix </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a137" doxytag="Zinc::itemSetUnderlined"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetUnderlined </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -underlined ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the underlined to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a97" doxytag="Zinc::itemSetVisible"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetVisible </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -visible ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the visible to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a139" doxytag="Zinc::itemSetWidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSetWidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>unsigned short&nbsp;</td>
          <td class="mdname" nowrap> <em>value</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;itemconfigure ( -width ) <dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to configure </td></tr>
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the width to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a56" doxytag="Zinc::itemSkew"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSkew </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>sx</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>sy</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Skew an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>sx</em>&nbsp;</td><td>horizontal skew </td></tr>
    <tr><td valign=top><em>sy</em>&nbsp;</td><td>vertical skew </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a57" doxytag="Zinc::itemSkewX"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSkewX </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>sx</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Skew an item horizontaly<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>sx</em>&nbsp;</td><td>horizontal skew </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a58" doxytag="Zinc::itemSkewY"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemSkewY </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>sy</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Skew an item verticaly<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>sy</em>&nbsp;</td><td>vertical skew </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a49" doxytag="Zinc::itemTranslate"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemTranslate </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>absolute</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Translate the item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>x</em>&nbsp;</td><td>y translation vector </td></tr>
    <tr><td valign=top><em>absolute</em>&nbsp;</td><td>true if the translation is absolute </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a48" doxytag="Zinc::itemTranslate"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemTranslate </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>dx</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>dy</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Translate the item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to which we apply the transform </td></tr>
    <tr><td valign=top><em>dx</em>&nbsp;</td><td>dy translation vector </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a47" doxytag="Zinc::itemUnbind"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::itemUnbind </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>eventSpecification</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Annulate a binding<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item on which to unbind </td></tr>
    <tr><td valign=top><em>eventSpecification</em>&nbsp;</td><td>tcl style event specicication </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="e0" doxytag="Zinc::loadZinc"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::loadZinc </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">char *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>argv0</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>  throw (<a class="el" href="classZincException.html">ZincException</a>)<code> [static]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Loads the zinc library and initialize tcl and tk<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>argv0</em>&nbsp;</td><td>the name of the execytable as passed in argv[0] </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a32" doxytag="Zinc::lower"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::lower </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>belowThis</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Reorder items to lower one<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to lower </td></tr>
    <tr><td valign=top><em>belowThis</em>&nbsp;</td><td>and item that will be over item </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a31" doxytag="Zinc::lower"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::lower </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Reorder items to lower one<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to lower </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a34" doxytag="Zinc::raise"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::raise </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>aboveThis</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Reorder items to raise one<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to raise </td></tr>
    <tr><td valign=top><em>aboveThis</em>&nbsp;</td><td>an item that will be under item </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a33" doxytag="Zinc::raise"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::raise </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Reorder items to raise one<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to raise </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a16" doxytag="Zinc::relativeBbox"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::relativeBbox </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname" nowrap> <em>item</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>bbox</em>[4]</td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Get the bounding box of an item in its parent group<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>the item to get bbox in its parent group </td></tr>
    <tr><td valign=top><em>bbox</em>&nbsp;</td><td>a table where we'll put the bounding box bbox[0] = x0, bbox[1] = y0, bbox[2] = xc, bbox[3] = yc </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a3" doxytag="Zinc::setBackcolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::setBackcolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>value</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;configure ( -backcolor )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the backcolor to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a11" doxytag="Zinc::setBorderwidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::setBorderwidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>value</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;configure ( -borderwidth )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the borderwidth to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a13" doxytag="Zinc::setFont"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::setFont </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincFont.html">ZincFont</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>value</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;configure ( -font )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the font to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a5" doxytag="Zinc::setForecolor"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::setForecolor </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>value</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;configure ( -forecolor )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the forecolor to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a9" doxytag="Zinc::setHeight"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::setHeight </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>value</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;configure ( -height )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the height to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a2" doxytag="Zinc::setTitle"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::setTitle </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>title</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Change window title<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>title</em>&nbsp;</td><td>the title string </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a7" doxytag="Zinc::setWidth"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::setWidth </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>value</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Call zinc-&gt;configure ( -width )<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>value</em>&nbsp;</td><td>the width to set </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a35" doxytag="Zinc::type"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a60">itemType</a> Zinc::type </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="classZincItem.html">ZincItem</a> *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>item</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Return the type of an item<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>item</em>&nbsp;</td><td>an item </td></tr>
  </table>
</dl>
<dl compact><dt><b>Returns:</b></dt><dd>the type of the item </dd></dl>
    </td>
  </tr>
</table>
<a name="a45" doxytag="Zinc::unbind"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::unbind </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>eventSpecification</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Annulate a binding<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>eventSpecification</em>&nbsp;</td><td>tcl style event specicication </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a157" doxytag="Zinc::z_command"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::z_command </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname" nowrap> <em>count</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>char *&nbsp;</td>
          <td class="mdname" nowrap> <em>p_msg</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2">  throw (<a class="el" href="classZincException.html">ZincException</a>)</td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
This is a inline because it is called frequently and needs to be optimized Use this to call the zinObjectCommand fuction. The call is made using the pre allocated table p1, it must contain Tcl_Obj thar are parameters to the zinObjectCommand function. A parameter indicate how many parameters are passed to the zinObjectCommand function.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>count</em>&nbsp;</td><td>the number of parameters in p1 </td></tr>
    <tr><td valign=top><em>msg</em>&nbsp;</td><td>the error message to throw in case of error </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="e2" doxytag="Zinc::z_tcl_call"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::z_tcl_call </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">int&nbsp;</td>
          <td class="mdname" nowrap> <em>result</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>char *&nbsp;</td>
          <td class="mdname" nowrap> <em>p_msg</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2">  throw (<a class="el" href="classZincException.html">ZincException</a>)<code> [static]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
This is inline because it is called frequently and needs to be optimized Use this when you need to call a function that can return a TCL error code.<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>fct</em>&nbsp;</td><td>the full function call </td></tr>
    <tr><td valign=top><em>msg</em>&nbsp;</td><td>the error message to throw in case of error </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="e1" doxytag="Zinc::zincMainLoop"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void Zinc::zincMainLoop </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [static]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Run tk mainloop and returns when there is no more Tk window     </td>
  </tr>
</table>
<hr><h2>Friends And Related Function Documentation</h2>
<a name="n0" doxytag="Zinc::ZincPath"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> friend class <a class="el" href="classZincPath.html">ZincPath</a><code> [friend]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr><h2>Member Data Documentation</h2>
<a name="s4" doxytag="Zinc::bndCmdInfo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_CmdInfo <a class="el" href="classZinc.html#s4">Zinc::bndCmdInfo</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the command associated with bind 
<p>
    </td>
  </tr>
</table>
<a name="s2" doxytag="Zinc::fntCmdInfo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_CmdInfo <a class="el" href="classZinc.html#s2">Zinc::fntCmdInfo</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the command associated with font 
<p>
    </td>
  </tr>
</table>
<a name="s3" doxytag="Zinc::focCmdInfo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_CmdInfo <a class="el" href="classZinc.html#s3">Zinc::focCmdInfo</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the command associated with fous 
<p>
    </td>
  </tr>
</table>
<a name="o0" doxytag="Zinc::id"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="classZinc.html#o0">Zinc::id</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the id of this object 
<p>
    </td>
  </tr>
</table>
<a name="s1" doxytag="Zinc::imgCmdInfo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_CmdInfo <a class="el" href="classZinc.html#s1">Zinc::imgCmdInfo</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the command associated with image 
<p>
    </td>
  </tr>
</table>
<a name="s8" doxytag="Zinc::interp"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Interp * <a class="el" href="classZinc.html#s8">Zinc::interp</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the tcl interpreter 
<p>
    </td>
  </tr>
</table>
<a name="o1" doxytag="Zinc::objCmd"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincExtern_8hpp.html#a0">WidgetObjCmd</a> <a class="el" href="classZinc.html#o1">Zinc::objCmd</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the command associated with this object 
<p>
    </td>
  </tr>
</table>
<a name="s6" doxytag="Zinc::p1"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj * <a class="el" href="classZinc.html#s6">Zinc::p1</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
table of pointeur use for parameters 
<p>
    </td>
  </tr>
</table>
<a name="s7" doxytag="Zinc::p2"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj * <a class="el" href="classZinc.html#s7">Zinc::p2</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
table of pointeur use for parameters 
<p>
    </td>
  </tr>
</table>
<a name="s5" doxytag="Zinc::pool"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj * <a class="el" href="classZinc.html#s5">Zinc::pool</a><code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
a pool of tclobj ready to be used 
<p>
    </td>
  </tr>
</table>
<a name="o3" doxytag="Zinc::tclCb"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> <a class="el" href="classZinc.html#o3">Zinc::tclCb</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
name of the binding callback 
<p>
    </td>
  </tr>
</table>
<a name="o2" doxytag="Zinc::wi"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ClientData <a class="el" href="classZinc.html#o2">Zinc::wi</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the zinc object itself 
<p>
    </td>
  </tr>
</table>
<a name="o5" doxytag="Zinc::window"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> <a class="el" href="classZinc.html#o5">Zinc::window</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the window which contains the widget 
<p>
    </td>
  </tr>
</table>
<a name="s0" doxytag="Zinc::znCount"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int <a class="el" href="classZinc.html#s0">Zinc::znCount</a> = 0<code> [static]</code>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
count to create unique ids 
<p>
    </td>
  </tr>
</table>
<a name="o4" doxytag="Zinc::znId"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int <a class="el" href="classZinc.html#o4">Zinc::znId</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
the znCount at creation time 
<p>
    </td>
  </tr>
</table>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="Zinc_8hpp-source.html">Zinc.hpp</a><li><a class="el" href="Zinc_8cpp.html">Zinc.cpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincBitmap-members.html.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincBitmap Member List</h1>This is the complete list of members for <a class="el" href="classZincBitmap.html">ZincBitmap</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#o0">object</a></td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincBitmap.html#a0">ZincBitmap</a>(Tcl_Obj *obj)</td><td><a class="el" href="classZincBitmap.html">ZincBitmap</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincBitmap.html#a1">ZincBitmap</a>(Tcl_Obj *obj, bool internal)</td><td><a class="el" href="classZincBitmap.html">ZincBitmap</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincBitmap.html#a2">ZincBitmap</a>(String name)</td><td><a class="el" href="classZincBitmap.html">ZincBitmap</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#b0">ZincItem</a>()</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td><code> [protected]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#a0">ZincItem</a>(Tcl_Obj *obj)</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincBitmap.html#a3">~ZincBitmap</a>()</td><td><a class="el" href="classZincBitmap.html">ZincBitmap</a></td><td><code> [virtual]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#a1">~ZincItem</a>()</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td><code> [virtual]</code></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincBitmap.html.



































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincBitmap class Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincBitmap Class Reference</h1><code>#include &lt;<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>&gt;</code>
<p>
<p>Inheritance diagram for ZincBitmap:
<p><center><img src="classZincBitmap.png" usemap="#ZincBitmap_map" border="0" alt=""></center>
<map name="ZincBitmap_map">
<area href="classZincItem.html" alt="ZincItem" shape="rect" coords="0,0,75,24">
</map>
<a href="classZincBitmap-members.html">List of all members.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincBitmap.html#a0">ZincBitmap</a> (Tcl_Obj *obj)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincBitmap.html#a1">ZincBitmap</a> (Tcl_Obj *obj, bool internal)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincBitmap.html#a2">ZincBitmap</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> name)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>virtual&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincBitmap.html#a3">~ZincBitmap</a> ()</td></tr>

</table>
<hr><h2>Constructor &amp; Destructor Documentation</h2>
<a name="a0" doxytag="ZincBitmap::ZincBitmap"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincBitmap::ZincBitmap </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">Tcl_Obj *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>obj</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor (redefine the inherited one)<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>obj</em>&nbsp;</td><td>the object we want to store </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a1" doxytag="ZincBitmap::ZincBitmap"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincBitmap::ZincBitmap </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">Tcl_Obj *&nbsp;</td>
          <td class="mdname" nowrap> <em>obj</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>internal</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor (redefine the inherited one)<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>obj</em>&nbsp;</td><td>the object we want to store </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a2" doxytag="ZincBitmap::ZincBitmap"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincBitmap::ZincBitmap </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>name</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor (redefine the inherited one)<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>name</em>&nbsp;</td><td>the name of a predefined bitmap </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a3" doxytag="ZincBitmap::~ZincBitmap"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincBitmap::~<a class="el" href="classZincBitmap.html">ZincBitmap</a> </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [virtual]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public destructor     </td>
  </tr>
</table>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a><li><a class="el" href="ZincObjects_8cpp.html">ZincObjects.cpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincBitmap.png.

cannot compute difference between binary files

Added jni/tkzinc/zinclib.d/doc/html/classZincException-members.html.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincException Member List</h1>This is the complete list of members for <a class="el" href="classZincException.html">ZincException</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="classZincException.html#a3">what</a>() const</td><td><a class="el" href="classZincException.html">ZincException</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincException.html#a0">ZincException</a>(String msg, char *file, int lineNo)</td><td><a class="el" href="classZincException.html">ZincException</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincException.html#a1">ZincException</a>(const ZincException &amp;exception)</td><td><a class="el" href="classZincException.html">ZincException</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincException.html#a2">~ZincException</a>()</td><td><a class="el" href="classZincException.html">ZincException</a></td><td><code> [virtual]</code></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincException.html.



































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincException class Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincException Class Reference</h1><code>#include &lt;<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>&gt;</code>
<p>
<a href="classZincException-members.html">List of all members.</a><hr><a name="_details"></a><h2>Detailed Description</h2>
Exceptions that are throwed by zinclib 
<p>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincException.html#a0">ZincException</a> (<a class="el" href="ZincTypes_8hpp.html#a0">String</a> msg, char *file, int lineNo)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincException.html#a1">ZincException</a> (const <a class="el" href="classZincException.html">ZincException</a> &amp;exception)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>virtual&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincException.html#a2">~ZincException</a> ()  throw ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>const char *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincException.html#a3">what</a> () const  throw ()</td></tr>

</table>
<hr><h2>Constructor &amp; Destructor Documentation</h2>
<a name="a0" doxytag="ZincException::ZincException"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincException::ZincException </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top"><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td>
          <td class="mdname" nowrap> <em>msg</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>char *&nbsp;</td>
          <td class="mdname" nowrap> <em>file</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>int&nbsp;</td>
          <td class="mdname" nowrap> <em>lineNo</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
A public constructor with a String parameter<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>msg</em>&nbsp;</td><td>the error message </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a1" doxytag="ZincException::ZincException"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincException::ZincException </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">const <a class="el" href="classZincException.html">ZincException</a> &amp;&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>exception</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Copy constructor<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>exception</em>&nbsp;</td><td>the original exception </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a2" doxytag="ZincException::~ZincException"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincException::~<a class="el" href="classZincException.html">ZincException</a> </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap>  throw ()<code> [virtual]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Public destructor     </td>
  </tr>
</table>
<hr><h2>Member Function Documentation</h2>
<a name="a3" doxytag="ZincException::what"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> const char * ZincException::what </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap> const  throw ()</td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Retreive the exception message<p>
<dl compact><dt><b>Returns:</b></dt><dd>the message </dd></dl>
    </td>
  </tr>
</table>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a><li><a class="el" href="ZincObjects_8cpp.html">ZincObjects.cpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincFont-members.html.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincFont Member List</h1>This is the complete list of members for <a class="el" href="classZincFont.html">ZincFont</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="classZincFont.html#o0">name</a></td><td><a class="el" href="classZincFont.html">ZincFont</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincFont.html#a0">ZincFont</a>(const char *font)</td><td><a class="el" href="classZincFont.html">ZincFont</a></td><td></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincFont.html.































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincFont class Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincFont Class Reference</h1><code>#include &lt;<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>&gt;</code>
<p>
<a href="classZincFont-members.html">List of all members.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincFont.html#a0">ZincFont</a> (const char *font)</td></tr>

<tr><td colspan=2><br><h2>Public Attributes</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincFont.html#o0">name</a></td></tr>

</table>
<hr><h2>Constructor &amp; Destructor Documentation</h2>
<a name="a0" doxytag="ZincFont::ZincFont"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincFont::ZincFont </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">const char *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>font</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor     </td>
  </tr>
</table>
<hr><h2>Member Data Documentation</h2>
<a name="o0" doxytag="ZincFont::name"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> <a class="el" href="classZincFont.html#o0">ZincFont::name</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a><li><a class="el" href="ZincObjects_8cpp.html">ZincObjects.cpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincImage-members.html.











































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincImage Member List</h1>This is the complete list of members for <a class="el" href="classZincImage.html">ZincImage</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#o0">object</a></td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincImage.html#a0">ZincImage</a>(Tcl_Obj *obj)</td><td><a class="el" href="classZincImage.html">ZincImage</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincImage.html#a1">ZincImage</a>(Tcl_Obj *obj, bool internal)</td><td><a class="el" href="classZincImage.html">ZincImage</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#b0">ZincItem</a>()</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td><code> [protected]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#a0">ZincItem</a>(Tcl_Obj *obj)</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincImage.html#a2">~ZincImage</a>()</td><td><a class="el" href="classZincImage.html">ZincImage</a></td><td><code> [virtual]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#a1">~ZincItem</a>()</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td><code> [virtual]</code></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincImage.html.

























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincImage class Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincImage Class Reference</h1><code>#include &lt;<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>&gt;</code>
<p>
<p>Inheritance diagram for ZincImage:
<p><center><img src="classZincImage.png" usemap="#ZincImage_map" border="0" alt=""></center>
<map name="ZincImage_map">
<area href="classZincItem.html" alt="ZincItem" shape="rect" coords="0,0,71,24">
</map>
<a href="classZincImage-members.html">List of all members.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincImage.html#a0">ZincImage</a> (Tcl_Obj *obj)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincImage.html#a1">ZincImage</a> (Tcl_Obj *obj, bool internal)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>virtual&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincImage.html#a2">~ZincImage</a> ()</td></tr>

</table>
<hr><h2>Constructor &amp; Destructor Documentation</h2>
<a name="a0" doxytag="ZincImage::ZincImage"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincImage::ZincImage </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">Tcl_Obj *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>obj</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor (redefine the inherited one)<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>obj</em>&nbsp;</td><td>the object we want to store </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a1" doxytag="ZincImage::ZincImage"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincImage::ZincImage </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">Tcl_Obj *&nbsp;</td>
          <td class="mdname" nowrap> <em>obj</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>internal</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor (redefine the inherited one)<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>obj</em>&nbsp;</td><td>the object we want to store </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a2" doxytag="ZincImage::~ZincImage"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincImage::~<a class="el" href="classZincImage.html">ZincImage</a> </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [virtual]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public destructor     </td>
  </tr>
</table>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a><li><a class="el" href="ZincObjects_8cpp.html">ZincObjects.cpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincImage.png.

cannot compute difference between binary files

Added jni/tkzinc/zinclib.d/doc/html/classZincItem-members.html.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincItem Member List</h1>This is the complete list of members for <a class="el" href="classZincItem.html">ZincItem</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#o0">object</a></td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#b0">ZincItem</a>()</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td><code> [protected]</code></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#a0">ZincItem</a>(Tcl_Obj *obj)</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincItem.html#a1">~ZincItem</a>()</td><td><a class="el" href="classZincItem.html">ZincItem</a></td><td><code> [virtual]</code></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincItem.html.































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincItem class Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincItem Class Reference</h1><code>#include &lt;<a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a>&gt;</code>
<p>
<p>Inheritance diagram for ZincItem:
<p><center><img src="classZincItem.png" usemap="#ZincItem_map" border="0" alt=""></center>
<map name="ZincItem_map">
<area href="classZincBitmap.html" alt="ZincBitmap" shape="rect" coords="0,56,75,80">
<area href="classZincImage.html" alt="ZincImage" shape="rect" coords="85,56,160,80">
</map>
<a href="classZincItem-members.html">List of all members.</a><hr><a name="_details"></a><h2>Detailed Description</h2>
<a class="el" href="ZincObjects_8hpp.html">ZincObjects.hpp</a> zinclib<p>
This software is the property of IntuiLab SA, France. See at the end of the file for the complete copyright notice<p>
Here we defines classes that are items in zinc<p>
08/03/05<p>
Contributors: Benoit Peccatte &lt;<a href="mailto:peccatte@intuilab.com">peccatte@intuilab.com</a>&gt; David Thevenin &lt;<a href="mailto:thevenin@intuilab.com">thevenin@intuilab.com</a>&gt; 
<p>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincItem.html#a0">ZincItem</a> (Tcl_Obj *obj)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>virtual&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincItem.html#a1">~ZincItem</a> ()</td></tr>

<tr><td colspan=2><br><h2>Public Attributes</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincItem.html#o0">object</a></td></tr>

<tr><td colspan=2><br><h2>Protected Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincItem.html#b0">ZincItem</a> ()</td></tr>

</table>
<hr><h2>Constructor &amp; Destructor Documentation</h2>
<a name="b0" doxytag="ZincItem::ZincItem"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincItem::ZincItem </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [protected]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The protected default constructor     </td>
  </tr>
</table>
<a name="a0" doxytag="ZincItem::ZincItem"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincItem::ZincItem </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">Tcl_Obj *&nbsp;</td>
          <td class="mdname1" valign="top" nowrap> <em>obj</em>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>obj</em>&nbsp;</td><td>the object we want to store </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a1" doxytag="ZincItem::~ZincItem"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincItem::~<a class="el" href="classZincItem.html">ZincItem</a> </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap><code> [virtual]</code></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public destructor     </td>
  </tr>
</table>
<hr><h2>Member Data Documentation</h2>
<a name="o0" doxytag="ZincItem::object"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj* <a class="el" href="classZincItem.html#o0">ZincItem::object</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="ZincObjects_8hpp-source.html">ZincObjects.hpp</a><li><a class="el" href="ZincObjects_8cpp.html">ZincObjects.cpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincItem.png.

cannot compute difference between binary files

Added jni/tkzinc/zinclib.d/doc/html/classZincPath-members.html.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincPath Member List</h1>This is the complete list of members for <a class="el" href="classZincPath.html">ZincPath</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a7">arcTo</a>(double rx, double ry, double xAxisRotation, bool largeArc, bool sweepFlag, double x, double y)</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a2">close</a>()</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a5">cubicBezierTo</a>(double cx1, double cy1, double cx2, double cy2, double x, double y)</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a4">curveTo</a>(double cx1, double cy1, double cx2, double cy2, double x, double y)</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a8">getTable</a>()</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a3">lineTo</a>(double x, double y)</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a6">quadraticBezierTo</a>(double cx, double cy, double x, double y)</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a0">ZincPath</a>(double x, double y)</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="classZincPath.html#a1">~ZincPath</a>()</td><td><a class="el" href="classZincPath.html">ZincPath</a></td><td></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classZincPath.html.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincPath class Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincPath Class Reference</h1><code>#include &lt;<a class="el" href="ZincPath_8hpp-source.html">ZincPath.hpp</a>&gt;</code>
<p>
<a href="classZincPath-members.html">List of all members.</a><hr><a name="_details"></a><h2>Detailed Description</h2>
Path.hpp zinclib<p>
This software is the property of IntuiLab SA, France. See at the end of the file for the complete copyright notice<p>
Here we defines The ZincPath object<p>
08/03/05<p>
Contributors: Benoit Peccatte &lt;<a href="mailto:peccatte@intuilab.com">peccatte@intuilab.com</a>&gt; 
<p>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Member Functions</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a0">ZincPath</a> (double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a1">~ZincPath</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a2">close</a> ()</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a3">lineTo</a> (double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a4">curveTo</a> (double cx1, double cy1, double cx2, double cy2, double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a5">cubicBezierTo</a> (double cx1, double cy1, double cx2, double cy2, double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a6">quadraticBezierTo</a> (double cx, double cy, double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>void&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a7">arcTo</a> (double rx, double ry, double xAxisRotation, bool largeArc, bool sweepFlag, double x, double y)</td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>Tcl_Obj *&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="classZincPath.html#a8">getTable</a> ()</td></tr>

</table>
<hr><h2>Constructor &amp; Destructor Documentation</h2>
<a name="a0" doxytag="ZincPath::ZincPath"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincPath::ZincPath </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public constructor<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>the initial point </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a1" doxytag="ZincPath::~ZincPath"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> ZincPath::~<a class="el" href="classZincPath.html">ZincPath</a> </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
The public destructor<p>
<dl compact><dt><b>Warning:</b></dt><dd>Do not destroy a ZincPath if <a class="el" href="classZinc.html">Zinc</a> is not loaded </dd></dl>
    </td>
  </tr>
</table>
<hr><h2>Member Function Documentation</h2>
<a name="a7" doxytag="ZincPath::arcTo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void ZincPath::arcTo </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname" nowrap> <em>rx</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>ry</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>xAxisRotation</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>largeArc</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>bool&nbsp;</td>
          <td class="mdname" nowrap> <em>sweepFlag</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Draw an arc from current point to x,y<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>rx</em>&nbsp;</td><td>x-radius of ellipse </td></tr>
    <tr><td valign=top><em>ry</em>&nbsp;</td><td>y-radius of ellipse </td></tr>
    <tr><td valign=top><em>xAxisRotation</em>&nbsp;</td><td>rotation of ellipse </td></tr>
    <tr><td valign=top><em>largeArc</em>&nbsp;</td><td>true if the large part of the ellipse </td></tr>
    <tr><td valign=top><em>sweepFlag</em>&nbsp;</td><td>true for a positive angle direction for the drawing </td></tr>
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>destination point </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a2" doxytag="ZincPath::close"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void ZincPath::close </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Close current path     </td>
  </tr>
</table>
<a name="a5" doxytag="ZincPath::cubicBezierTo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void ZincPath::cubicBezierTo </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname" nowrap> <em>cx1</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cy1</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cx2</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cy2</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Draw a cubic bezier using specified control and destination points<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>cx1,cy1</em>&nbsp;</td><td>first control point </td></tr>
    <tr><td valign=top><em>cx2,cy2</em>&nbsp;</td><td>second control point </td></tr>
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>destination point </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a4" doxytag="ZincPath::curveTo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void ZincPath::curveTo </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname" nowrap> <em>cx1</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cy1</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cx2</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cy2</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Draw a cubic bezier using specified control and destination points call cubicBezierTo<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>cx1,cy1</em>&nbsp;</td><td>first control point </td></tr>
    <tr><td valign=top><em>cx2,cy2</em>&nbsp;</td><td>second control point </td></tr>
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>destination point </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a8" doxytag="ZincPath::getTable"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> Tcl_Obj * ZincPath::getTable </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="mdname1" valign="top" nowrap>          </td>
          <td class="md" valign="top">&nbsp;)&nbsp;</td>
          <td class="md" nowrap></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Return a Tcl_Obj* containing a list of coords points It's up to the caller to delete the resulting table<p>
<dl compact><dt><b>Returns:</b></dt><dd>a Tcl_Obj* of type list </dd></dl>
    </td>
  </tr>
</table>
<a name="a3" doxytag="ZincPath::lineTo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void ZincPath::lineTo </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Draw a line from current point to next point<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>next point </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<a name="a6" doxytag="ZincPath::quadraticBezierTo"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> void ZincPath::quadraticBezierTo </td>
          <td class="md" valign="top">(&nbsp;</td>
          <td class="md" nowrap valign="top">double&nbsp;</td>
          <td class="mdname" nowrap> <em>cx</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>cy</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>x</em>, </td>
        </tr>
        <tr>
          <td></td>
          <td></td>
          <td class="md" nowrap>double&nbsp;</td>
          <td class="mdname" nowrap> <em>y</em></td>
        </tr>
        <tr>
          <td></td>
          <td class="md">)&nbsp;</td>
          <td class="md" colspan="2"></td>
        </tr>

      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
Draw a quadratic bezier using specified control and destination point<p>
<dl compact><dt><b>Parameters:</b></dt><dd>
  <table border="0" cellspacing="2" cellpadding="0">
    <tr><td valign=top><em>cx1,cy1</em>&nbsp;</td><td>first control point </td></tr>
    <tr><td valign=top><em>cx2,cy2</em>&nbsp;</td><td>second control point </td></tr>
    <tr><td valign=top><em>x,y</em>&nbsp;</td><td>destination point </td></tr>
  </table>
</dl>
    </td>
  </tr>
</table>
<hr>The documentation for this class was generated from the following files:<ul>
<li><a class="el" href="ZincPath_8hpp-source.html">ZincPath.hpp</a><li><a class="el" href="ZincPath_8cpp.html">ZincPath.cpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/classes.html.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Alphabetical index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindexHL" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>IntuiKit Compound Index</h1><table align=center width="95%" border="0" cellspacing="0" cellpadding="0">
<tr><td><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah">&nbsp;&nbsp;Z&nbsp;&nbsp;</div></td></tr></table>
</td><td><a class="el" href="classZincBitmap.html">ZincBitmap</a>&nbsp;&nbsp;&nbsp;</td><td><a class="el" href="classZincException.html">ZincException</a>&nbsp;&nbsp;&nbsp;</td><td><a class="el" href="classZincImage.html">ZincImage</a>&nbsp;&nbsp;&nbsp;</td><td><a class="el" href="classZincPath.html">ZincPath</a>&nbsp;&nbsp;&nbsp;</td></tr><tr><td><a class="el" href="classZinc.html">Zinc</a>&nbsp;&nbsp;&nbsp;</td><td><a class="el" href="structZincEvent.html">ZincEvent</a>&nbsp;&nbsp;&nbsp;</td><td><a class="el" href="classZincFont.html">ZincFont</a>&nbsp;&nbsp;&nbsp;</td><td><a class="el" href="classZincItem.html">ZincItem</a>&nbsp;&nbsp;&nbsp;</td></tr></table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/doxygen.css.

































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
H1 {
	text-align: center;
	font-family: Arial, Helvetica, sans-serif;
}
H2 {
	font-family: Geneva, Arial, Helvetica, sans-serif;
}
CAPTION { font-weight: bold }
DIV.qindex { width: 100%;
             background-color: #eeeeff;
             border: 4px solid #eeeeff;
             text-align: center;
             margin-bottom: 2px
}
A.qindex { text-decoration: none; font-weight: bold; }
A.qindex:hover { text-decoration: none; background-color: #ddddff }
A.qindexHL { text-decoration: none; font-weight: bold;
             background-color: #6666cc;
             color: #ffffff
           }
A.qindexHL:hover { text-decoration: none; background-color: #6666cc }
A.qindexRef { text-decoration: none; font-weight: bold; }
A.qindexRef:hover { text-decoration: none; background-color: #ddddff }
A.qindexRefHL { text-decoration: none; font-weight: bold;
             background-color: #6666cc;
             color: #ffffff
           }
A.qindexRefHL:hover { text-decoration: none; background-color: #6666cc }
A.el { text-decoration: none; font-weight: bold }
A.elRef { font-weight: bold }
A.code { text-decoration: none; font-weight: normal; color: #4444ee }
A.codeRef { font-weight: normal; color: #4444ee }
A:hover { text-decoration: none; background-color: #f2f2ff }
DL.el { margin-left: -1cm }
DIV.fragment {
	width: 98%;
	border: 1px solid #CCCCCC;
	background-color: #f5f5f5;
	padding-left: 4px;
	margin: 4px;
}
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
TD.md { background-color: #f2f2ff; font-weight: bold; }
TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; }
TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; }
DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold }
DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller }
BODY {
	background: white;
	color: black;
	margin-right: 20px;
	margin-left: 20px;
}
TD.indexkey { 
   background-color: #eeeeff; 
   font-weight: bold; 
   padding-right  : 10px; 
   padding-top    : 2px; 
   padding-left   : 10px; 
   padding-bottom : 2px; 
   margin-left    : 0px; 
   margin-right   : 0px; 
   margin-top     : 2px; 
   margin-bottom  : 2px  
}
TD.indexvalue { 
   background-color: #eeeeff; 
   font-style: italic; 
   padding-right  : 10px; 
   padding-top    : 2px; 
   padding-left   : 10px; 
   padding-bottom : 2px; 
   margin-left    : 0px; 
   margin-right   : 0px; 
   margin-top     : 2px; 
   margin-bottom  : 2px  
}
TR.memlist {
   background-color: #f0f0f0; 
}
P.formulaDsp { text-align: center; }
IMG.formulaDsp { }
IMG.formulaInl { vertical-align: middle; }
SPAN.keyword       { color: #008000 }
SPAN.keywordtype   { color: #604020 }
SPAN.keywordflow   { color: #e08000 }
SPAN.comment       { color: #800000 }
SPAN.preprocessor  { color: #806020 }
SPAN.stringliteral { color: #002080 }
SPAN.charliteral   { color: #008080 }
.mdTable {
	border: 1px solid #868686;
	background-color: #f2f2ff;
}
.mdRow {
	padding: 8px 20px;
}
.mdescLeft {
	font-size: smaller;
	font-family: Arial, Helvetica, sans-serif;
	background-color: #FAFAFA;
	padding-left: 8px;
	border-top: 1px none #E0E0E0;
	border-right: 1px none #E0E0E0;
	border-bottom: 1px none #E0E0E0;
	border-left: 1px none #E0E0E0;
	margin: 0px;
}
.mdescRight {
	font-size: smaller;
	font-family: Arial, Helvetica, sans-serif;
	font-style: italic;
	background-color: #FAFAFA;
	padding-left: 4px;
	border-top: 1px none #E0E0E0;
	border-right: 1px none #E0E0E0;
	border-bottom: 1px none #E0E0E0;
	border-left: 1px none #E0E0E0;
	margin: 0px;
	padding-bottom: 0px;
	padding-right: 8px;
}
.memItemLeft {
	padding: 1px 0px 0px 8px;
	margin: 4px;
	border-top-width: 1px;
	border-right-width: 1px;
	border-bottom-width: 1px;
	border-left-width: 1px;
	border-top-style: solid;
	border-top-color: #E0E0E0;
	border-right-color: #E0E0E0;
	border-bottom-color: #E0E0E0;
	border-left-color: #E0E0E0;
	border-right-style: none;
	border-bottom-style: none;
	border-left-style: none;
	background-color: #FAFAFA;
	font-family: Geneva, Arial, Helvetica, sans-serif;
	font-size: 12px;
}
.memItemRight {
	padding: 1px 0px 0px 8px;
	margin: 4px;
	border-top-width: 1px;
	border-right-width: 1px;
	border-bottom-width: 1px;
	border-left-width: 1px;
	border-top-style: solid;
	border-top-color: #E0E0E0;
	border-right-color: #E0E0E0;
	border-bottom-color: #E0E0E0;
	border-left-color: #E0E0E0;
	border-right-style: none;
	border-bottom-style: none;
	border-left-style: none;
	background-color: #FAFAFA;
	font-family: Geneva, Arial, Helvetica, sans-serif;
	font-size: 13px;
}

Added jni/tkzinc/zinclib.d/doc/html/doxygen.png.

cannot compute difference between binary files

Added jni/tkzinc/zinclib.d/doc/html/files.html.

















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindexHL" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>IntuiKit File List</h1>Here is a list of all files with brief descriptions:<table>
  <tr><td class="indexkey"><a class="el" href="Zinc_8cpp.html">Zinc.cpp</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="Zinc_8hpp.html">Zinc.hpp</a> <a href="Zinc_8hpp-source.html">[code]</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="ZincExtern_8hpp.html">ZincExtern.hpp</a> <a href="ZincExtern_8hpp-source.html">[code]</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="ZincInternal_8hpp.html">ZincInternal.hpp</a> <a href="ZincInternal_8hpp-source.html">[code]</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="ZincObjects_8cpp.html">ZincObjects.cpp</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="ZincObjects_8hpp.html">ZincObjects.hpp</a> <a href="ZincObjects_8hpp-source.html">[code]</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="ZincPath_8cpp.html">ZincPath.cpp</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="ZincPath_8hpp.html">ZincPath.hpp</a> <a href="ZincPath_8hpp-source.html">[code]</a></td><td class="indexvalue"></td></tr>
  <tr><td class="indexkey"><a class="el" href="ZincTypes_8hpp.html">ZincTypes.hpp</a> <a href="ZincTypes_8hpp-source.html">[code]</a></td><td class="indexvalue"></td></tr>
</table>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/functions.html.













































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Compound Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindexHL" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindexHL" href="functions.html">All</a> | <a class="qindex" href="functions_func.html">Functions</a> | <a class="qindex" href="functions_vars.html">Variables</a> | <a class="qindex" href="functions_rela.html">Related&nbsp;Functions</a></div>
<div class="qindex"><a class="qindex" href="#index_a">a</a> | <a class="qindex" href="#index_b">b</a> | <a class="qindex" href="#index_c">c</a> | <a class="qindex" href="#index_d">d</a> | <a class="qindex" href="#index_f">f</a> | <a class="qindex" href="#index_g">g</a> | <a class="qindex" href="#index_i">i</a> | <a class="qindex" href="#index_k">k</a> | <a class="qindex" href="#index_l">l</a> | <a class="qindex" href="#index_n">n</a> | <a class="qindex" href="#index_o">o</a> | <a class="qindex" href="#index_p">p</a> | <a class="qindex" href="#index_q">q</a> | <a class="qindex" href="#index_r">r</a> | <a class="qindex" href="#index_s">s</a> | <a class="qindex" href="#index_t">t</a> | <a class="qindex" href="#index_u">u</a> | <a class="qindex" href="#index_w">w</a> | <a class="qindex" href="#index_x">x</a> | <a class="qindex" href="#index_y">y</a> | <a class="qindex" href="#index_z">z</a> | <a class="qindex" href="#index_~">~</a></div>

<p>

<p>
Here is a list of all class members with links to the classes they belong to:<h3><a name="index_a">- a -</a>
</h3><ul>
<li>addTag()
: <a class="el" href="classZinc.html#a24">Zinc</a><li>arcTo()
: <a class="el" href="classZincPath.html#a7">ZincPath</a></ul>
<h3><a name="index_b">- b -</a>
</h3><ul>
<li>bbox()
: <a class="el" href="classZinc.html#a15">Zinc</a><li>bind()
: <a class="el" href="classZinc.html#a44">Zinc</a><li>bndCmdInfo
: <a class="el" href="classZinc.html#s4">Zinc</a></ul>
<h3><a name="index_c">- c -</a>
</h3><ul>
<li>chggroup()
: <a class="el" href="classZinc.html#a17">Zinc</a><li>clone()
: <a class="el" href="classZinc.html#a18">Zinc</a><li>close()
: <a class="el" href="classZincPath.html#a2">ZincPath</a><li>contour()
: <a class="el" href="classZinc.html#a21">Zinc</a><li>coords()
: <a class="el" href="classZinc.html#a22">Zinc</a><li>coordsRemove()
: <a class="el" href="classZinc.html#a23">Zinc</a><li>createBitmapFromData()
: <a class="el" href="classZinc.html#a150">Zinc</a><li>createBitmapFromFile()
: <a class="el" href="classZinc.html#a149">Zinc</a><li>createBitmapFromName()
: <a class="el" href="classZinc.html#a151">Zinc</a><li>createFont()
: <a class="el" href="classZinc.html#a153">Zinc</a><li>createImageFromAGGBuffer()
: <a class="el" href="classZinc.html#a152">Zinc</a><li>createImageFromData()
: <a class="el" href="classZinc.html#a148">Zinc</a><li>createImageFromFile()
: <a class="el" href="classZinc.html#a147">Zinc</a><li>createTag()
: <a class="el" href="classZinc.html#a36">Zinc</a><li>cubicBezierTo()
: <a class="el" href="classZincPath.html#a5">ZincPath</a><li>curveTo()
: <a class="el" href="classZincPath.html#a4">ZincPath</a></ul>
<h3><a name="index_d">- d -</a>
</h3><ul>
<li>dTag()
: <a class="el" href="classZinc.html#a25">Zinc</a></ul>
<h3><a name="index_f">- f -</a>
</h3><ul>
<li>fntCmdInfo
: <a class="el" href="classZinc.html#s2">Zinc</a><li>focCmdInfo
: <a class="el" href="classZinc.html#s3">Zinc</a><li>focus()
: <a class="el" href="classZinc.html#a27">Zinc</a></ul>
<h3><a name="index_g">- g -</a>
</h3><ul>
<li>getBackcolor()
: <a class="el" href="classZinc.html#a4">Zinc</a><li>getBorderwidth()
: <a class="el" href="classZinc.html#a12">Zinc</a><li>getFont()
: <a class="el" href="classZinc.html#a14">Zinc</a><li>getFontAscent()
: <a class="el" href="classZinc.html#a154">Zinc</a><li>getForecolor()
: <a class="el" href="classZinc.html#a6">Zinc</a><li>getHeight()
: <a class="el" href="classZinc.html#a10">Zinc</a><li>getImageHeight()
: <a class="el" href="classZinc.html#a156">Zinc</a><li>getImageWidth()
: <a class="el" href="classZinc.html#a155">Zinc</a><li>getTable()
: <a class="el" href="classZincPath.html#a8">ZincPath</a><li>getTags()
: <a class="el" href="classZinc.html#a26">Zinc</a><li>getWidth()
: <a class="el" href="classZinc.html#a8">Zinc</a><li>gname()
: <a class="el" href="classZinc.html#a29">Zinc</a><li>group()
: <a class="el" href="classZinc.html#a30">Zinc</a></ul>
<h3><a name="index_i">- i -</a>
</h3><ul>
<li>id
: <a class="el" href="classZinc.html#o0">Zinc</a><li>imgCmdInfo
: <a class="el" href="classZinc.html#s1">Zinc</a><li>interp
: <a class="el" href="classZinc.html#s8">Zinc</a><li>isGname()
: <a class="el" href="classZinc.html#a28">Zinc</a><li>itemBind()
: <a class="el" href="classZinc.html#a46">Zinc</a><li>itemCreateArc()
: <a class="el" href="classZinc.html#a40">Zinc</a><li>itemCreateCurve()
: <a class="el" href="classZinc.html#a42">Zinc</a><li>itemCreateGroup()
: <a class="el" href="classZinc.html#a38">Zinc</a><li>itemCreateIcon()
: <a class="el" href="classZinc.html#a43">Zinc</a><li>itemCreateRectangle()
: <a class="el" href="classZinc.html#a39">Zinc</a><li>itemCreateText()
: <a class="el" href="classZinc.html#a41">Zinc</a><li>itemGetAlignment()
: <a class="el" href="classZinc.html#a128">Zinc</a><li>itemGetAlpha()
: <a class="el" href="classZinc.html#a110">Zinc</a><li>itemGetAnchor()
: <a class="el" href="classZinc.html#a116">Zinc</a><li>itemGetAtomic()
: <a class="el" href="classZinc.html#a112">Zinc</a><li>itemGetCapstyle()
: <a class="el" href="classZinc.html#a100">Zinc</a><li>itemGetClip()
: <a class="el" href="classZinc.html#a114">Zinc</a><li>itemGetClosed()
: <a class="el" href="classZinc.html#a64">Zinc</a><li>itemGetColor()
: <a class="el" href="classZinc.html#a118">Zinc</a><li>itemGetComposealpha()
: <a class="el" href="classZinc.html#a66">Zinc</a><li>itemGetComposerotation()
: <a class="el" href="classZinc.html#a68">Zinc</a><li>itemGetComposescale()
: <a class="el" href="classZinc.html#a70">Zinc</a><li>itemGetConnecteditem()
: <a class="el" href="classZinc.html#a120">Zinc</a><li>itemGetConnectionanchor()
: <a class="el" href="classZinc.html#a122">Zinc</a><li>itemGetExtent()
: <a class="el" href="classZinc.html#a72">Zinc</a><li>itemGetFillcolor()
: <a class="el" href="classZinc.html#a74">Zinc</a><li>itemGetFilled()
: <a class="el" href="classZinc.html#a76">Zinc</a><li>itemGetFillpattern()
: <a class="el" href="classZinc.html#a78">Zinc</a><li>itemGetFillrule()
: <a class="el" href="classZinc.html#a102">Zinc</a><li>itemGetFirstend()
: <a class="el" href="classZinc.html#a142">Zinc</a><li>itemGetFont()
: <a class="el" href="classZinc.html#a130">Zinc</a><li>itemGetImage()
: <a class="el" href="classZinc.html#a124">Zinc</a><li>itemGetJoinstyle()
: <a class="el" href="classZinc.html#a104">Zinc</a><li>itemGetLastend()
: <a class="el" href="classZinc.html#a144">Zinc</a><li>itemGetLinecolor()
: <a class="el" href="classZinc.html#a80">Zinc</a><li>itemGetLinepattern()
: <a class="el" href="classZinc.html#a82">Zinc</a><li>itemGetLinestyle()
: <a class="el" href="classZinc.html#a84">Zinc</a><li>itemGetLinewidth()
: <a class="el" href="classZinc.html#a86">Zinc</a><li>itemGetMask()
: <a class="el" href="classZinc.html#a126">Zinc</a><li>itemGetOverstriked()
: <a class="el" href="classZinc.html#a132">Zinc</a><li>itemGetPieslice()
: <a class="el" href="classZinc.html#a88">Zinc</a><li>itemGetPosition()
: <a class="el" href="classZinc.html#a146">Zinc</a><li>itemGetPriority()
: <a class="el" href="classZinc.html#a90">Zinc</a><li>itemGetRelief()
: <a class="el" href="classZinc.html#a106">Zinc</a><li>itemGetSensitive()
: <a class="el" href="classZinc.html#a92">Zinc</a><li>itemGetSmoothrelief()
: <a class="el" href="classZinc.html#a108">Zinc</a><li>itemGetSpacing()
: <a class="el" href="classZinc.html#a134">Zinc</a><li>itemGetStartangle()
: <a class="el" href="classZinc.html#a94">Zinc</a><li>itemGetText()
: <a class="el" href="classZinc.html#a136">Zinc</a><li>itemGetTile()
: <a class="el" href="classZinc.html#a96">Zinc</a><li>itemGetTransformation()
: <a class="el" href="classZinc.html#a61">Zinc</a><li>itemGetUnderlined()
: <a class="el" href="classZinc.html#a138">Zinc</a><li>itemGetVisible()
: <a class="el" href="classZinc.html#a98">Zinc</a><li>itemGetWidth()
: <a class="el" href="classZinc.html#a140">Zinc</a><li>itemMatrix()
: <a class="el" href="classZinc.html#a62">Zinc</a><li>itemRemove()
: <a class="el" href="classZinc.html#a37">Zinc</a><li>itemResetTransformation()
: <a class="el" href="classZinc.html#a59">Zinc</a><li>itemRotate()
: <a class="el" href="classZinc.html#a53">Zinc</a><li>itemScale()
: <a class="el" href="classZinc.html#a55">Zinc</a><li>itemSetAlignment()
: <a class="el" href="classZinc.html#a127">Zinc</a><li>itemSetAlpha()
: <a class="el" href="classZinc.html#a109">Zinc</a><li>itemSetAnchor()
: <a class="el" href="classZinc.html#a115">Zinc</a><li>itemSetAtomic()
: <a class="el" href="classZinc.html#a111">Zinc</a><li>itemSetCapstyle()
: <a class="el" href="classZinc.html#a99">Zinc</a><li>itemSetClip()
: <a class="el" href="classZinc.html#a113">Zinc</a><li>itemSetClosed()
: <a class="el" href="classZinc.html#a63">Zinc</a><li>itemSetColor()
: <a class="el" href="classZinc.html#a117">Zinc</a><li>itemSetComposealpha()
: <a class="el" href="classZinc.html#a65">Zinc</a><li>itemSetComposerotation()
: <a class="el" href="classZinc.html#a67">Zinc</a><li>itemSetComposescale()
: <a class="el" href="classZinc.html#a69">Zinc</a><li>itemSetConnecteditem()
: <a class="el" href="classZinc.html#a119">Zinc</a><li>itemSetConnectionanchor()
: <a class="el" href="classZinc.html#a121">Zinc</a><li>itemSetExtent()
: <a class="el" href="classZinc.html#a71">Zinc</a><li>itemSetFillcolor()
: <a class="el" href="classZinc.html#a73">Zinc</a><li>itemSetFilled()
: <a class="el" href="classZinc.html#a75">Zinc</a><li>itemSetFillpattern()
: <a class="el" href="classZinc.html#a77">Zinc</a><li>itemSetFillrule()
: <a class="el" href="classZinc.html#a101">Zinc</a><li>itemSetFirstend()
: <a class="el" href="classZinc.html#a141">Zinc</a><li>itemSetFont()
: <a class="el" href="classZinc.html#a129">Zinc</a><li>itemSetImage()
: <a class="el" href="classZinc.html#a123">Zinc</a><li>itemSetJoinstyle()
: <a class="el" href="classZinc.html#a103">Zinc</a><li>itemSetLastend()
: <a class="el" href="classZinc.html#a143">Zinc</a><li>itemSetLinecolor()
: <a class="el" href="classZinc.html#a79">Zinc</a><li>itemSetLinepattern()
: <a class="el" href="classZinc.html#a81">Zinc</a><li>itemSetLinestyle()
: <a class="el" href="classZinc.html#a83">Zinc</a><li>itemSetLinewidth()
: <a class="el" href="classZinc.html#a85">Zinc</a><li>itemSetMask()
: <a class="el" href="classZinc.html#a125">Zinc</a><li>itemSetOverstriked()
: <a class="el" href="classZinc.html#a131">Zinc</a><li>itemSetPieslice()
: <a class="el" href="classZinc.html#a87">Zinc</a><li>itemSetPosition()
: <a class="el" href="classZinc.html#a145">Zinc</a><li>itemSetPriority()
: <a class="el" href="classZinc.html#a89">Zinc</a><li>itemSetRelief()
: <a class="el" href="classZinc.html#a105">Zinc</a><li>itemSetSensitive()
: <a class="el" href="classZinc.html#a91">Zinc</a><li>itemSetSmoothrelief()
: <a class="el" href="classZinc.html#a107">Zinc</a><li>itemSetSpacing()
: <a class="el" href="classZinc.html#a133">Zinc</a><li>itemSetStartangle()
: <a class="el" href="classZinc.html#a93">Zinc</a><li>itemSetText()
: <a class="el" href="classZinc.html#a135">Zinc</a><li>itemSetTile()
: <a class="el" href="classZinc.html#a95">Zinc</a><li>itemSetTransformation()
: <a class="el" href="classZinc.html#a60">Zinc</a><li>itemSetUnderlined()
: <a class="el" href="classZinc.html#a137">Zinc</a><li>itemSetVisible()
: <a class="el" href="classZinc.html#a97">Zinc</a><li>itemSetWidth()
: <a class="el" href="classZinc.html#a139">Zinc</a><li>itemSkew()
: <a class="el" href="classZinc.html#a56">Zinc</a><li>itemSkewX()
: <a class="el" href="classZinc.html#a57">Zinc</a><li>itemSkewY()
: <a class="el" href="classZinc.html#a58">Zinc</a><li>itemTranslate()
: <a class="el" href="classZinc.html#a49">Zinc</a><li>itemUnbind()
: <a class="el" href="classZinc.html#a47">Zinc</a></ul>
<h3><a name="index_k">- k -</a>
</h3><ul>
<li>K
: <a class="el" href="structZincEvent.html#o4">ZincEvent</a><li>k
: <a class="el" href="structZincEvent.html#o2">ZincEvent</a></ul>
<h3><a name="index_l">- l -</a>
</h3><ul>
<li>lineTo()
: <a class="el" href="classZincPath.html#a3">ZincPath</a><li>loadZinc()
: <a class="el" href="classZinc.html#e0">Zinc</a><li>lower()
: <a class="el" href="classZinc.html#a32">Zinc</a></ul>
<h3><a name="index_n">- n -</a>
</h3><ul>
<li>name
: <a class="el" href="classZincFont.html#o0">ZincFont</a></ul>
<h3><a name="index_o">- o -</a>
</h3><ul>
<li>objCmd
: <a class="el" href="classZinc.html#o1">Zinc</a><li>object
: <a class="el" href="classZincItem.html#o0">ZincItem</a></ul>
<h3><a name="index_p">- p -</a>
</h3><ul>
<li>p1
: <a class="el" href="classZinc.html#s6">Zinc</a><li>p2
: <a class="el" href="classZinc.html#s7">Zinc</a><li>pool
: <a class="el" href="classZinc.html#s5">Zinc</a></ul>
<h3><a name="index_q">- q -</a>
</h3><ul>
<li>quadraticBezierTo()
: <a class="el" href="classZincPath.html#a6">ZincPath</a></ul>
<h3><a name="index_r">- r -</a>
</h3><ul>
<li>raise()
: <a class="el" href="classZinc.html#a34">Zinc</a><li>relativeBbox()
: <a class="el" href="classZinc.html#a16">Zinc</a></ul>
<h3><a name="index_s">- s -</a>
</h3><ul>
<li>setBackcolor()
: <a class="el" href="classZinc.html#a3">Zinc</a><li>setBorderwidth()
: <a class="el" href="classZinc.html#a11">Zinc</a><li>setFont()
: <a class="el" href="classZinc.html#a13">Zinc</a><li>setForecolor()
: <a class="el" href="classZinc.html#a5">Zinc</a><li>setHeight()
: <a class="el" href="classZinc.html#a9">Zinc</a><li>setTitle()
: <a class="el" href="classZinc.html#a2">Zinc</a><li>setWidth()
: <a class="el" href="classZinc.html#a7">Zinc</a></ul>
<h3><a name="index_t">- t -</a>
</h3><ul>
<li>t
: <a class="el" href="structZincEvent.html#o3">ZincEvent</a><li>tclCb
: <a class="el" href="classZinc.html#o3">Zinc</a><li>type()
: <a class="el" href="classZinc.html#a35">Zinc</a></ul>
<h3><a name="index_u">- u -</a>
</h3><ul>
<li>unbind()
: <a class="el" href="classZinc.html#a45">Zinc</a></ul>
<h3><a name="index_w">- w -</a>
</h3><ul>
<li>what()
: <a class="el" href="classZincException.html#a3">ZincException</a><li>wi
: <a class="el" href="classZinc.html#o2">Zinc</a><li>window
: <a class="el" href="classZinc.html#o5">Zinc</a></ul>
<h3><a name="index_x">- x -</a>
</h3><ul>
<li>x
: <a class="el" href="structZincEvent.html#o0">ZincEvent</a></ul>
<h3><a name="index_y">- y -</a>
</h3><ul>
<li>y
: <a class="el" href="structZincEvent.html#o1">ZincEvent</a></ul>
<h3><a name="index_z">- z -</a>
</h3><ul>
<li>z_command()
: <a class="el" href="classZinc.html#a157">Zinc</a><li>z_tcl_call()
: <a class="el" href="classZinc.html#e2">Zinc</a><li>Zinc()
: <a class="el" href="classZinc.html#a0">Zinc</a><li>ZincBitmap()
: <a class="el" href="classZincBitmap.html#a2">ZincBitmap</a><li>ZincException()
: <a class="el" href="classZincException.html#a1">ZincException</a><li>ZincFont()
: <a class="el" href="classZincFont.html#a0">ZincFont</a><li>ZincImage()
: <a class="el" href="classZincImage.html#a1">ZincImage</a><li>ZincItem()
: <a class="el" href="classZincItem.html#a0">ZincItem</a><li>zincMainLoop()
: <a class="el" href="classZinc.html#e1">Zinc</a><li>ZincPath
: <a class="el" href="classZincPath.html#a0">ZincPath</a>, <a class="el" href="classZinc.html#n0">Zinc</a><li>znCount
: <a class="el" href="classZinc.html#s0">Zinc</a><li>znId
: <a class="el" href="classZinc.html#o4">Zinc</a></ul>
<h3><a name="index_~">- ~ -</a>
</h3><ul>
<li>~Zinc()
: <a class="el" href="classZinc.html#a1">Zinc</a><li>~ZincBitmap()
: <a class="el" href="classZincBitmap.html#a3">ZincBitmap</a><li>~ZincException()
: <a class="el" href="classZincException.html#a2">ZincException</a><li>~ZincImage()
: <a class="el" href="classZincImage.html#a2">ZincImage</a><li>~ZincItem()
: <a class="el" href="classZincItem.html#a1">ZincItem</a><li>~ZincPath()
: <a class="el" href="classZincPath.html#a1">ZincPath</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/functions_func.html.





























































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Compound Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindexHL" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="functions.html">All</a> | <a class="qindexHL" href="functions_func.html">Functions</a> | <a class="qindex" href="functions_vars.html">Variables</a> | <a class="qindex" href="functions_rela.html">Related&nbsp;Functions</a></div>
<div class="qindex"><a class="qindex" href="#index_a">a</a> | <a class="qindex" href="#index_b">b</a> | <a class="qindex" href="#index_c">c</a> | <a class="qindex" href="#index_d">d</a> | <a class="qindex" href="#index_f">f</a> | <a class="qindex" href="#index_g">g</a> | <a class="qindex" href="#index_i">i</a> | <a class="qindex" href="#index_l">l</a> | <a class="qindex" href="#index_q">q</a> | <a class="qindex" href="#index_r">r</a> | <a class="qindex" href="#index_s">s</a> | <a class="qindex" href="#index_t">t</a> | <a class="qindex" href="#index_u">u</a> | <a class="qindex" href="#index_w">w</a> | <a class="qindex" href="#index_z">z</a> | <a class="qindex" href="#index_~">~</a></div>

<p>

<p>
<h3><a name="index_a">- a -</a>
</h3><ul>
<li>addTag()
: <a class="el" href="classZinc.html#a24">Zinc</a><li>arcTo()
: <a class="el" href="classZincPath.html#a7">ZincPath</a></ul>
<h3><a name="index_b">- b -</a>
</h3><ul>
<li>bbox()
: <a class="el" href="classZinc.html#a15">Zinc</a><li>bind()
: <a class="el" href="classZinc.html#a44">Zinc</a></ul>
<h3><a name="index_c">- c -</a>
</h3><ul>
<li>chggroup()
: <a class="el" href="classZinc.html#a17">Zinc</a><li>clone()
: <a class="el" href="classZinc.html#a18">Zinc</a><li>close()
: <a class="el" href="classZincPath.html#a2">ZincPath</a><li>contour()
: <a class="el" href="classZinc.html#a21">Zinc</a><li>coords()
: <a class="el" href="classZinc.html#a22">Zinc</a><li>coordsRemove()
: <a class="el" href="classZinc.html#a23">Zinc</a><li>createBitmapFromData()
: <a class="el" href="classZinc.html#a150">Zinc</a><li>createBitmapFromFile()
: <a class="el" href="classZinc.html#a149">Zinc</a><li>createBitmapFromName()
: <a class="el" href="classZinc.html#a151">Zinc</a><li>createFont()
: <a class="el" href="classZinc.html#a153">Zinc</a><li>createImageFromAGGBuffer()
: <a class="el" href="classZinc.html#a152">Zinc</a><li>createImageFromData()
: <a class="el" href="classZinc.html#a148">Zinc</a><li>createImageFromFile()
: <a class="el" href="classZinc.html#a147">Zinc</a><li>createTag()
: <a class="el" href="classZinc.html#a36">Zinc</a><li>cubicBezierTo()
: <a class="el" href="classZincPath.html#a5">ZincPath</a><li>curveTo()
: <a class="el" href="classZincPath.html#a4">ZincPath</a></ul>
<h3><a name="index_d">- d -</a>
</h3><ul>
<li>dTag()
: <a class="el" href="classZinc.html#a25">Zinc</a></ul>
<h3><a name="index_f">- f -</a>
</h3><ul>
<li>focus()
: <a class="el" href="classZinc.html#a27">Zinc</a></ul>
<h3><a name="index_g">- g -</a>
</h3><ul>
<li>getBackcolor()
: <a class="el" href="classZinc.html#a4">Zinc</a><li>getBorderwidth()
: <a class="el" href="classZinc.html#a12">Zinc</a><li>getFont()
: <a class="el" href="classZinc.html#a14">Zinc</a><li>getFontAscent()
: <a class="el" href="classZinc.html#a154">Zinc</a><li>getForecolor()
: <a class="el" href="classZinc.html#a6">Zinc</a><li>getHeight()
: <a class="el" href="classZinc.html#a10">Zinc</a><li>getImageHeight()
: <a class="el" href="classZinc.html#a156">Zinc</a><li>getImageWidth()
: <a class="el" href="classZinc.html#a155">Zinc</a><li>getTable()
: <a class="el" href="classZincPath.html#a8">ZincPath</a><li>getTags()
: <a class="el" href="classZinc.html#a26">Zinc</a><li>getWidth()
: <a class="el" href="classZinc.html#a8">Zinc</a><li>gname()
: <a class="el" href="classZinc.html#a29">Zinc</a><li>group()
: <a class="el" href="classZinc.html#a30">Zinc</a></ul>
<h3><a name="index_i">- i -</a>
</h3><ul>
<li>isGname()
: <a class="el" href="classZinc.html#a28">Zinc</a><li>itemBind()
: <a class="el" href="classZinc.html#a46">Zinc</a><li>itemCreateArc()
: <a class="el" href="classZinc.html#a40">Zinc</a><li>itemCreateCurve()
: <a class="el" href="classZinc.html#a42">Zinc</a><li>itemCreateGroup()
: <a class="el" href="classZinc.html#a38">Zinc</a><li>itemCreateIcon()
: <a class="el" href="classZinc.html#a43">Zinc</a><li>itemCreateRectangle()
: <a class="el" href="classZinc.html#a39">Zinc</a><li>itemCreateText()
: <a class="el" href="classZinc.html#a41">Zinc</a><li>itemGetAlignment()
: <a class="el" href="classZinc.html#a128">Zinc</a><li>itemGetAlpha()
: <a class="el" href="classZinc.html#a110">Zinc</a><li>itemGetAnchor()
: <a class="el" href="classZinc.html#a116">Zinc</a><li>itemGetAtomic()
: <a class="el" href="classZinc.html#a112">Zinc</a><li>itemGetCapstyle()
: <a class="el" href="classZinc.html#a100">Zinc</a><li>itemGetClip()
: <a class="el" href="classZinc.html#a114">Zinc</a><li>itemGetClosed()
: <a class="el" href="classZinc.html#a64">Zinc</a><li>itemGetColor()
: <a class="el" href="classZinc.html#a118">Zinc</a><li>itemGetComposealpha()
: <a class="el" href="classZinc.html#a66">Zinc</a><li>itemGetComposerotation()
: <a class="el" href="classZinc.html#a68">Zinc</a><li>itemGetComposescale()
: <a class="el" href="classZinc.html#a70">Zinc</a><li>itemGetConnecteditem()
: <a class="el" href="classZinc.html#a120">Zinc</a><li>itemGetConnectionanchor()
: <a class="el" href="classZinc.html#a122">Zinc</a><li>itemGetExtent()
: <a class="el" href="classZinc.html#a72">Zinc</a><li>itemGetFillcolor()
: <a class="el" href="classZinc.html#a74">Zinc</a><li>itemGetFilled()
: <a class="el" href="classZinc.html#a76">Zinc</a><li>itemGetFillpattern()
: <a class="el" href="classZinc.html#a78">Zinc</a><li>itemGetFillrule()
: <a class="el" href="classZinc.html#a102">Zinc</a><li>itemGetFirstend()
: <a class="el" href="classZinc.html#a142">Zinc</a><li>itemGetFont()
: <a class="el" href="classZinc.html#a130">Zinc</a><li>itemGetImage()
: <a class="el" href="classZinc.html#a124">Zinc</a><li>itemGetJoinstyle()
: <a class="el" href="classZinc.html#a104">Zinc</a><li>itemGetLastend()
: <a class="el" href="classZinc.html#a144">Zinc</a><li>itemGetLinecolor()
: <a class="el" href="classZinc.html#a80">Zinc</a><li>itemGetLinepattern()
: <a class="el" href="classZinc.html#a82">Zinc</a><li>itemGetLinestyle()
: <a class="el" href="classZinc.html#a84">Zinc</a><li>itemGetLinewidth()
: <a class="el" href="classZinc.html#a86">Zinc</a><li>itemGetMask()
: <a class="el" href="classZinc.html#a126">Zinc</a><li>itemGetOverstriked()
: <a class="el" href="classZinc.html#a132">Zinc</a><li>itemGetPieslice()
: <a class="el" href="classZinc.html#a88">Zinc</a><li>itemGetPosition()
: <a class="el" href="classZinc.html#a146">Zinc</a><li>itemGetPriority()
: <a class="el" href="classZinc.html#a90">Zinc</a><li>itemGetRelief()
: <a class="el" href="classZinc.html#a106">Zinc</a><li>itemGetSensitive()
: <a class="el" href="classZinc.html#a92">Zinc</a><li>itemGetSmoothrelief()
: <a class="el" href="classZinc.html#a108">Zinc</a><li>itemGetSpacing()
: <a class="el" href="classZinc.html#a134">Zinc</a><li>itemGetStartangle()
: <a class="el" href="classZinc.html#a94">Zinc</a><li>itemGetText()
: <a class="el" href="classZinc.html#a136">Zinc</a><li>itemGetTile()
: <a class="el" href="classZinc.html#a96">Zinc</a><li>itemGetTransformation()
: <a class="el" href="classZinc.html#a61">Zinc</a><li>itemGetUnderlined()
: <a class="el" href="classZinc.html#a138">Zinc</a><li>itemGetVisible()
: <a class="el" href="classZinc.html#a98">Zinc</a><li>itemGetWidth()
: <a class="el" href="classZinc.html#a140">Zinc</a><li>itemMatrix()
: <a class="el" href="classZinc.html#a62">Zinc</a><li>itemRemove()
: <a class="el" href="classZinc.html#a37">Zinc</a><li>itemResetTransformation()
: <a class="el" href="classZinc.html#a59">Zinc</a><li>itemRotate()
: <a class="el" href="classZinc.html#a53">Zinc</a><li>itemScale()
: <a class="el" href="classZinc.html#a55">Zinc</a><li>itemSetAlignment()
: <a class="el" href="classZinc.html#a127">Zinc</a><li>itemSetAlpha()
: <a class="el" href="classZinc.html#a109">Zinc</a><li>itemSetAnchor()
: <a class="el" href="classZinc.html#a115">Zinc</a><li>itemSetAtomic()
: <a class="el" href="classZinc.html#a111">Zinc</a><li>itemSetCapstyle()
: <a class="el" href="classZinc.html#a99">Zinc</a><li>itemSetClip()
: <a class="el" href="classZinc.html#a113">Zinc</a><li>itemSetClosed()
: <a class="el" href="classZinc.html#a63">Zinc</a><li>itemSetColor()
: <a class="el" href="classZinc.html#a117">Zinc</a><li>itemSetComposealpha()
: <a class="el" href="classZinc.html#a65">Zinc</a><li>itemSetComposerotation()
: <a class="el" href="classZinc.html#a67">Zinc</a><li>itemSetComposescale()
: <a class="el" href="classZinc.html#a69">Zinc</a><li>itemSetConnecteditem()
: <a class="el" href="classZinc.html#a119">Zinc</a><li>itemSetConnectionanchor()
: <a class="el" href="classZinc.html#a121">Zinc</a><li>itemSetExtent()
: <a class="el" href="classZinc.html#a71">Zinc</a><li>itemSetFillcolor()
: <a class="el" href="classZinc.html#a73">Zinc</a><li>itemSetFilled()
: <a class="el" href="classZinc.html#a75">Zinc</a><li>itemSetFillpattern()
: <a class="el" href="classZinc.html#a77">Zinc</a><li>itemSetFillrule()
: <a class="el" href="classZinc.html#a101">Zinc</a><li>itemSetFirstend()
: <a class="el" href="classZinc.html#a141">Zinc</a><li>itemSetFont()
: <a class="el" href="classZinc.html#a129">Zinc</a><li>itemSetImage()
: <a class="el" href="classZinc.html#a123">Zinc</a><li>itemSetJoinstyle()
: <a class="el" href="classZinc.html#a103">Zinc</a><li>itemSetLastend()
: <a class="el" href="classZinc.html#a143">Zinc</a><li>itemSetLinecolor()
: <a class="el" href="classZinc.html#a79">Zinc</a><li>itemSetLinepattern()
: <a class="el" href="classZinc.html#a81">Zinc</a><li>itemSetLinestyle()
: <a class="el" href="classZinc.html#a83">Zinc</a><li>itemSetLinewidth()
: <a class="el" href="classZinc.html#a85">Zinc</a><li>itemSetMask()
: <a class="el" href="classZinc.html#a125">Zinc</a><li>itemSetOverstriked()
: <a class="el" href="classZinc.html#a131">Zinc</a><li>itemSetPieslice()
: <a class="el" href="classZinc.html#a87">Zinc</a><li>itemSetPosition()
: <a class="el" href="classZinc.html#a145">Zinc</a><li>itemSetPriority()
: <a class="el" href="classZinc.html#a89">Zinc</a><li>itemSetRelief()
: <a class="el" href="classZinc.html#a105">Zinc</a><li>itemSetSensitive()
: <a class="el" href="classZinc.html#a91">Zinc</a><li>itemSetSmoothrelief()
: <a class="el" href="classZinc.html#a107">Zinc</a><li>itemSetSpacing()
: <a class="el" href="classZinc.html#a133">Zinc</a><li>itemSetStartangle()
: <a class="el" href="classZinc.html#a93">Zinc</a><li>itemSetText()
: <a class="el" href="classZinc.html#a135">Zinc</a><li>itemSetTile()
: <a class="el" href="classZinc.html#a95">Zinc</a><li>itemSetTransformation()
: <a class="el" href="classZinc.html#a60">Zinc</a><li>itemSetUnderlined()
: <a class="el" href="classZinc.html#a137">Zinc</a><li>itemSetVisible()
: <a class="el" href="classZinc.html#a97">Zinc</a><li>itemSetWidth()
: <a class="el" href="classZinc.html#a139">Zinc</a><li>itemSkew()
: <a class="el" href="classZinc.html#a56">Zinc</a><li>itemSkewX()
: <a class="el" href="classZinc.html#a57">Zinc</a><li>itemSkewY()
: <a class="el" href="classZinc.html#a58">Zinc</a><li>itemTranslate()
: <a class="el" href="classZinc.html#a49">Zinc</a><li>itemUnbind()
: <a class="el" href="classZinc.html#a47">Zinc</a></ul>
<h3><a name="index_l">- l -</a>
</h3><ul>
<li>lineTo()
: <a class="el" href="classZincPath.html#a3">ZincPath</a><li>loadZinc()
: <a class="el" href="classZinc.html#e0">Zinc</a><li>lower()
: <a class="el" href="classZinc.html#a32">Zinc</a></ul>
<h3><a name="index_q">- q -</a>
</h3><ul>
<li>quadraticBezierTo()
: <a class="el" href="classZincPath.html#a6">ZincPath</a></ul>
<h3><a name="index_r">- r -</a>
</h3><ul>
<li>raise()
: <a class="el" href="classZinc.html#a34">Zinc</a><li>relativeBbox()
: <a class="el" href="classZinc.html#a16">Zinc</a></ul>
<h3><a name="index_s">- s -</a>
</h3><ul>
<li>setBackcolor()
: <a class="el" href="classZinc.html#a3">Zinc</a><li>setBorderwidth()
: <a class="el" href="classZinc.html#a11">Zinc</a><li>setFont()
: <a class="el" href="classZinc.html#a13">Zinc</a><li>setForecolor()
: <a class="el" href="classZinc.html#a5">Zinc</a><li>setHeight()
: <a class="el" href="classZinc.html#a9">Zinc</a><li>setTitle()
: <a class="el" href="classZinc.html#a2">Zinc</a><li>setWidth()
: <a class="el" href="classZinc.html#a7">Zinc</a></ul>
<h3><a name="index_t">- t -</a>
</h3><ul>
<li>type()
: <a class="el" href="classZinc.html#a35">Zinc</a></ul>
<h3><a name="index_u">- u -</a>
</h3><ul>
<li>unbind()
: <a class="el" href="classZinc.html#a45">Zinc</a></ul>
<h3><a name="index_w">- w -</a>
</h3><ul>
<li>what()
: <a class="el" href="classZincException.html#a3">ZincException</a></ul>
<h3><a name="index_z">- z -</a>
</h3><ul>
<li>z_command()
: <a class="el" href="classZinc.html#a157">Zinc</a><li>z_tcl_call()
: <a class="el" href="classZinc.html#e2">Zinc</a><li>Zinc()
: <a class="el" href="classZinc.html#a0">Zinc</a><li>ZincBitmap()
: <a class="el" href="classZincBitmap.html#a2">ZincBitmap</a><li>ZincException()
: <a class="el" href="classZincException.html#a1">ZincException</a><li>ZincFont()
: <a class="el" href="classZincFont.html#a0">ZincFont</a><li>ZincImage()
: <a class="el" href="classZincImage.html#a1">ZincImage</a><li>ZincItem()
: <a class="el" href="classZincItem.html#a0">ZincItem</a><li>zincMainLoop()
: <a class="el" href="classZinc.html#e1">Zinc</a><li>ZincPath()
: <a class="el" href="classZincPath.html#a0">ZincPath</a>, <a class="el" href="classZinc.html#n0">Zinc</a></ul>
<h3><a name="index_~">- ~ -</a>
</h3><ul>
<li>~Zinc()
: <a class="el" href="classZinc.html#a1">Zinc</a><li>~ZincBitmap()
: <a class="el" href="classZincBitmap.html#a3">ZincBitmap</a><li>~ZincException()
: <a class="el" href="classZincException.html#a2">ZincException</a><li>~ZincImage()
: <a class="el" href="classZincImage.html#a2">ZincImage</a><li>~ZincItem()
: <a class="el" href="classZincItem.html#a1">ZincItem</a><li>~ZincPath()
: <a class="el" href="classZincPath.html#a1">ZincPath</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/functions_rela.html.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Compound Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindexHL" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="functions.html">All</a> | <a class="qindex" href="functions_func.html">Functions</a> | <a class="qindex" href="functions_vars.html">Variables</a> | <a class="qindexHL" href="functions_rela.html">Related&nbsp;Functions</a></div>

<p>
<ul>
<li>ZincPath
: <a class="el" href="classZincPath.html#a0">ZincPath</a>, <a class="el" href="classZinc.html#n0">Zinc</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/functions_vars.html.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Compound Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindexHL" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="functions.html">All</a> | <a class="qindex" href="functions_func.html">Functions</a> | <a class="qindexHL" href="functions_vars.html">Variables</a> | <a class="qindex" href="functions_rela.html">Related&nbsp;Functions</a></div>

<p>
<ul>
<li>bndCmdInfo
: <a class="el" href="classZinc.html#s4">Zinc</a><li>fntCmdInfo
: <a class="el" href="classZinc.html#s2">Zinc</a><li>focCmdInfo
: <a class="el" href="classZinc.html#s3">Zinc</a><li>id
: <a class="el" href="classZinc.html#o0">Zinc</a><li>imgCmdInfo
: <a class="el" href="classZinc.html#s1">Zinc</a><li>interp
: <a class="el" href="classZinc.html#s8">Zinc</a><li>K
: <a class="el" href="structZincEvent.html#o4">ZincEvent</a><li>k
: <a class="el" href="structZincEvent.html#o2">ZincEvent</a><li>name
: <a class="el" href="classZincFont.html#o0">ZincFont</a><li>objCmd
: <a class="el" href="classZinc.html#o1">Zinc</a><li>object
: <a class="el" href="classZincItem.html#o0">ZincItem</a><li>p1
: <a class="el" href="classZinc.html#s6">Zinc</a><li>p2
: <a class="el" href="classZinc.html#s7">Zinc</a><li>pool
: <a class="el" href="classZinc.html#s5">Zinc</a><li>t
: <a class="el" href="structZincEvent.html#o3">ZincEvent</a><li>tclCb
: <a class="el" href="classZinc.html#o3">Zinc</a><li>wi
: <a class="el" href="classZinc.html#o2">Zinc</a><li>window
: <a class="el" href="classZinc.html#o5">Zinc</a><li>x
: <a class="el" href="structZincEvent.html#o0">ZincEvent</a><li>y
: <a class="el" href="structZincEvent.html#o1">ZincEvent</a><li>znCount
: <a class="el" href="classZinc.html#s0">Zinc</a><li>znId
: <a class="el" href="classZinc.html#o4">Zinc</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/globals.html.













































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindexHL" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindexHL" href="globals.html">All</a> | <a class="qindex" href="globals_func.html">Functions</a> | <a class="qindex" href="globals_vars.html">Variables</a> | <a class="qindex" href="globals_type.html">Typedefs</a> | <a class="qindex" href="globals_enum.html">Enumerations</a> | <a class="qindex" href="globals_eval.html">Enumeration&nbsp;values</a> | <a class="qindex" href="globals_defs.html">Defines</a></div>
<div class="qindex"><a class="qindex" href="#index_a">a</a> | <a class="qindex" href="#index_c">c</a> | <a class="qindex" href="#index_d">d</a> | <a class="qindex" href="#index_e">e</a> | <a class="qindex" href="#index_f">f</a> | <a class="qindex" href="#index_i">i</a> | <a class="qindex" href="#index_j">j</a> | <a class="qindex" href="#index_l">l</a> | <a class="qindex" href="#index_m">m</a> | <a class="qindex" href="#index_r">r</a> | <a class="qindex" href="#index_s">s</a> | <a class="qindex" href="#index_t">t</a> | <a class="qindex" href="#index_w">w</a> | <a class="qindex" href="#index_z">z</a></div>

<p>

<p>
Here is a list of all file members with links to the files they belong to:<h3><a name="index_a">- a -</a>
</h3><ul>
<li>alignment
: <a class="el" href="ZincTypes_8hpp.html#a57">ZincTypes.hpp</a><li>alignment_center
: <a class="el" href="ZincTypes_8hpp.html#a57a33">ZincTypes.hpp</a><li>alignment_left
: <a class="el" href="ZincTypes_8hpp.html#a57a31">ZincTypes.hpp</a><li>alignment_right
: <a class="el" href="ZincTypes_8hpp.html#a57a32">ZincTypes.hpp</a><li>alignments
: <a class="el" href="Zinc_8cpp.html#a16">Zinc.cpp</a><li>alignmentsStrings
: <a class="el" href="Zinc_8cpp.html#a15">Zinc.cpp</a><li>anchor
: <a class="el" href="ZincTypes_8hpp.html#a58">ZincTypes.hpp</a><li>anchor_center
: <a class="el" href="ZincTypes_8hpp.html#a58a42">ZincTypes.hpp</a><li>anchor_e
: <a class="el" href="ZincTypes_8hpp.html#a58a37">ZincTypes.hpp</a><li>anchor_n
: <a class="el" href="ZincTypes_8hpp.html#a58a35">ZincTypes.hpp</a><li>anchor_ne
: <a class="el" href="ZincTypes_8hpp.html#a58a36">ZincTypes.hpp</a><li>anchor_nw
: <a class="el" href="ZincTypes_8hpp.html#a58a34">ZincTypes.hpp</a><li>anchor_s
: <a class="el" href="ZincTypes_8hpp.html#a58a39">ZincTypes.hpp</a><li>anchor_se
: <a class="el" href="ZincTypes_8hpp.html#a58a38">ZincTypes.hpp</a><li>anchor_sw
: <a class="el" href="ZincTypes_8hpp.html#a58a40">ZincTypes.hpp</a><li>anchor_w
: <a class="el" href="ZincTypes_8hpp.html#a58a41">ZincTypes.hpp</a><li>anchors
: <a class="el" href="Zinc_8cpp.html#a18">Zinc.cpp</a><li>anchorsStrings
: <a class="el" href="Zinc_8cpp.html#a17">Zinc.cpp</a></ul>
<h3><a name="index_c">- c -</a>
</h3><ul>
<li>capStyle
: <a class="el" href="ZincTypes_8hpp.html#a53">ZincTypes.hpp</a><li>capStyle_butt
: <a class="el" href="ZincTypes_8hpp.html#a53a9">ZincTypes.hpp</a><li>capStyle_projecting
: <a class="el" href="ZincTypes_8hpp.html#a53a10">ZincTypes.hpp</a><li>capStyle_round
: <a class="el" href="ZincTypes_8hpp.html#a53a11">ZincTypes.hpp</a><li>capStyles
: <a class="el" href="Zinc_8cpp.html#a8">Zinc.cpp</a><li>capStylesStrings
: <a class="el" href="Zinc_8cpp.html#a7">Zinc.cpp</a><li>convertRatio
: <a class="el" href="ZincPath_8cpp.html#a0">ZincPath.cpp</a></ul>
<h3><a name="index_d">- d -</a>
</h3><ul>
<li>DEFAULT_GROUP
: <a class="el" href="Zinc_8hpp.html#a2">Zinc.hpp</a><li>DEFAULT_GROUP_OBJ
: <a class="el" href="Zinc_8cpp.html#a4">Zinc.cpp</a><li>dtos()
: <a class="el" href="ZincInternal_8hpp.html#a14">ZincInternal.hpp</a></ul>
<h3><a name="index_e">- e -</a>
</h3><ul>
<li>EVENT_COUNT
: <a class="el" href="Zinc_8cpp.html#a0">Zinc.cpp</a></ul>
<h3><a name="index_f">- f -</a>
</h3><ul>
<li>fillRule
: <a class="el" href="ZincTypes_8hpp.html#a54">ZincTypes.hpp</a><li>fillRule_abs_geq_2
: <a class="el" href="ZincTypes_8hpp.html#a54a16">ZincTypes.hpp</a><li>fillRule_negative
: <a class="el" href="ZincTypes_8hpp.html#a54a15">ZincTypes.hpp</a><li>fillRule_nonzero
: <a class="el" href="ZincTypes_8hpp.html#a54a13">ZincTypes.hpp</a><li>fillRule_odd
: <a class="el" href="ZincTypes_8hpp.html#a54a12">ZincTypes.hpp</a><li>fillRule_positive
: <a class="el" href="ZincTypes_8hpp.html#a54a14">ZincTypes.hpp</a><li>fillRules
: <a class="el" href="Zinc_8cpp.html#a10">Zinc.cpp</a><li>fillRulesStrings
: <a class="el" href="Zinc_8cpp.html#a9">Zinc.cpp</a></ul>
<h3><a name="index_i">- i -</a>
</h3><ul>
<li>item_add_clockwise
: <a class="el" href="ZincTypes_8hpp.html#a59a43">ZincTypes.hpp</a><li>item_add_counterclockwise
: <a class="el" href="ZincTypes_8hpp.html#a59a44">ZincTypes.hpp</a><li>item_arc
: <a class="el" href="ZincTypes_8hpp.html#a60a47">ZincTypes.hpp</a><li>item_curve
: <a class="el" href="ZincTypes_8hpp.html#a60a50">ZincTypes.hpp</a><li>item_group
: <a class="el" href="ZincTypes_8hpp.html#a60a46">ZincTypes.hpp</a><li>item_icon
: <a class="el" href="ZincTypes_8hpp.html#a60a51">ZincTypes.hpp</a><li>item_rectangle
: <a class="el" href="ZincTypes_8hpp.html#a60a49">ZincTypes.hpp</a><li>item_remove
: <a class="el" href="ZincTypes_8hpp.html#a59a45">ZincTypes.hpp</a><li>item_text
: <a class="el" href="ZincTypes_8hpp.html#a60a48">ZincTypes.hpp</a><li>ITEMCB_COUNT
: <a class="el" href="Zinc_8cpp.html#a2">Zinc.cpp</a><li>itemOperator
: <a class="el" href="ZincTypes_8hpp.html#a59">ZincTypes.hpp</a><li>itemType
: <a class="el" href="ZincTypes_8hpp.html#a60">ZincTypes.hpp</a><li>itemTypeStrings
: <a class="el" href="Zinc_8cpp.html#a19">Zinc.cpp</a><li>itos()
: <a class="el" href="ZincInternal_8hpp.html#a12">ZincInternal.hpp</a></ul>
<h3><a name="index_j">- j -</a>
</h3><ul>
<li>joinStyle
: <a class="el" href="ZincTypes_8hpp.html#a55">ZincTypes.hpp</a><li>joinStyle_bevel
: <a class="el" href="ZincTypes_8hpp.html#a55a17">ZincTypes.hpp</a><li>joinStyle_miter
: <a class="el" href="ZincTypes_8hpp.html#a55a18">ZincTypes.hpp</a><li>joinStyle_round
: <a class="el" href="ZincTypes_8hpp.html#a55a19">ZincTypes.hpp</a><li>joinStyles
: <a class="el" href="Zinc_8cpp.html#a12">Zinc.cpp</a><li>joinStylesStrings
: <a class="el" href="Zinc_8cpp.html#a11">Zinc.cpp</a></ul>
<h3><a name="index_l">- l -</a>
</h3><ul>
<li>lineStyle
: <a class="el" href="ZincTypes_8hpp.html#a52">ZincTypes.hpp</a><li>lineStyle_dashed
: <a class="el" href="ZincTypes_8hpp.html#a52a6">ZincTypes.hpp</a><li>lineStyle_dotted
: <a class="el" href="ZincTypes_8hpp.html#a52a8">ZincTypes.hpp</a><li>lineStyle_mixed
: <a class="el" href="ZincTypes_8hpp.html#a52a7">ZincTypes.hpp</a><li>lineStyle_simple
: <a class="el" href="ZincTypes_8hpp.html#a52a5">ZincTypes.hpp</a><li>lineStyles
: <a class="el" href="Zinc_8cpp.html#a6">Zinc.cpp</a><li>lineStylesStrings
: <a class="el" href="Zinc_8cpp.html#a5">Zinc.cpp</a><li>ltos()
: <a class="el" href="ZincInternal_8hpp.html#a13">ZincInternal.hpp</a></ul>
<h3><a name="index_m">- m -</a>
</h3><ul>
<li>MAX_NUM_LENGTH
: <a class="el" href="ZincInternal_8hpp.html#a0">ZincInternal.hpp</a><li>modulo()
: <a class="el" href="ZincPath_8cpp.html#a1">ZincPath.cpp</a></ul>
<h3><a name="index_r">- r -</a>
</h3><ul>
<li>relief
: <a class="el" href="ZincTypes_8hpp.html#a56">ZincTypes.hpp</a><li>relief_flat
: <a class="el" href="ZincTypes_8hpp.html#a56a20">ZincTypes.hpp</a><li>relief_groove
: <a class="el" href="ZincTypes_8hpp.html#a56a24">ZincTypes.hpp</a><li>relief_raised
: <a class="el" href="ZincTypes_8hpp.html#a56a21">ZincTypes.hpp</a><li>relief_raisedrule
: <a class="el" href="ZincTypes_8hpp.html#a56a29">ZincTypes.hpp</a><li>relief_ridge
: <a class="el" href="ZincTypes_8hpp.html#a56a23">ZincTypes.hpp</a><li>relief_roundgroove
: <a class="el" href="ZincTypes_8hpp.html#a56a28">ZincTypes.hpp</a><li>relief_roundraised
: <a class="el" href="ZincTypes_8hpp.html#a56a25">ZincTypes.hpp</a><li>relief_roundridge
: <a class="el" href="ZincTypes_8hpp.html#a56a27">ZincTypes.hpp</a><li>relief_roundsunken
: <a class="el" href="ZincTypes_8hpp.html#a56a26">ZincTypes.hpp</a><li>relief_sunken
: <a class="el" href="ZincTypes_8hpp.html#a56a22">ZincTypes.hpp</a><li>relief_sunkenrule
: <a class="el" href="ZincTypes_8hpp.html#a56a30">ZincTypes.hpp</a><li>reliefs
: <a class="el" href="Zinc_8cpp.html#a14">Zinc.cpp</a><li>reliefsStrings
: <a class="el" href="Zinc_8cpp.html#a13">Zinc.cpp</a></ul>
<h3><a name="index_s">- s -</a>
</h3><ul>
<li>String
: <a class="el" href="ZincTypes_8hpp.html#a0">ZincTypes.hpp</a></ul>
<h3><a name="index_t">- t -</a>
</h3><ul>
<li>tclCallback()
: <a class="el" href="Zinc_8cpp.html#a20">Zinc.cpp</a><li>Tkzinc_Init()
: <a class="el" href="ZincExtern_8hpp.html#a1">ZincExtern.hpp</a></ul>
<h3><a name="index_w">- w -</a>
</h3><ul>
<li>WIDGETCB_COUNT
: <a class="el" href="Zinc_8cpp.html#a1">Zinc.cpp</a><li>WidgetObjCmd
: <a class="el" href="ZincExtern_8hpp.html#a0">ZincExtern.hpp</a></ul>
<h3><a name="index_z">- z -</a>
</h3><ul>
<li>Z_BOO_POOL
: <a class="el" href="ZincInternal_8hpp.html#a2">ZincInternal.hpp</a><li>Z_CLEANLIST
: <a class="el" href="ZincInternal_8hpp.html#a7">ZincInternal.hpp</a><li>Z_DBL_POOL
: <a class="el" href="ZincInternal_8hpp.html#a4">ZincInternal.hpp</a><li>Z_DEFINE_ZFCT
: <a class="el" href="Zinc_8cpp.html#a98">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a9">ZincInternal.hpp</a><li>Z_DEFINE_ZITM
: <a class="el" href="Zinc_8cpp.html#a106">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a10">ZincInternal.hpp</a><li>Z_DEFINE_ZOPT
: <a class="el" href="Zinc_8cpp.html#a69">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a8">ZincInternal.hpp</a><li>Z_INT_POOL
: <a class="el" href="ZincInternal_8hpp.html#a3">ZincInternal.hpp</a><li>Z_LST_POOL
: <a class="el" href="ZincInternal_8hpp.html#a6">ZincInternal.hpp</a><li>Z_PARENTGROUP
: <a class="el" href="ZincInternal_8hpp.html#a11">ZincInternal.hpp</a><li>Z_STR_POOL
: <a class="el" href="ZincInternal_8hpp.html#a5">ZincInternal.hpp</a><li>z_tcl_call2
: <a class="el" href="Zinc_8cpp.html#a3">Zinc.cpp</a><li>Z_TCLCB
: <a class="el" href="ZincInternal_8hpp.html#a1">ZincInternal.hpp</a><li>ZINC_BACKEND_OPENGL
: <a class="el" href="ZincTypes_8hpp.html#a4">ZincTypes.hpp</a><li>ZINC_BACKEND_X11
: <a class="el" href="ZincTypes_8hpp.html#a3">ZincTypes.hpp</a><li>ZINC_PARAM_COUNT
: <a class="el" href="Zinc_8hpp.html#a1">Zinc.hpp</a><li>ZINC_POOL_COUNT
: <a class="el" href="Zinc_8hpp.html#a0">Zinc.hpp</a><li>ZincItemCallback
: <a class="el" href="ZincTypes_8hpp.html#a1">ZincTypes.hpp</a><li>ZincObjCmd()
: <a class="el" href="ZincExtern_8hpp.html#a2">ZincExtern.hpp</a><li>ZincWidgetCallback
: <a class="el" href="ZincTypes_8hpp.html#a2">ZincTypes.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/globals_defs.html.





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindexHL" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="globals.html">All</a> | <a class="qindex" href="globals_func.html">Functions</a> | <a class="qindex" href="globals_vars.html">Variables</a> | <a class="qindex" href="globals_type.html">Typedefs</a> | <a class="qindex" href="globals_enum.html">Enumerations</a> | <a class="qindex" href="globals_eval.html">Enumeration&nbsp;values</a> | <a class="qindexHL" href="globals_defs.html">Defines</a></div>

<p>
<ul>
<li>EVENT_COUNT
: <a class="el" href="Zinc_8cpp.html#a0">Zinc.cpp</a><li>ITEMCB_COUNT
: <a class="el" href="Zinc_8cpp.html#a2">Zinc.cpp</a><li>MAX_NUM_LENGTH
: <a class="el" href="ZincInternal_8hpp.html#a0">ZincInternal.hpp</a><li>WIDGETCB_COUNT
: <a class="el" href="Zinc_8cpp.html#a1">Zinc.cpp</a><li>Z_BOO_POOL
: <a class="el" href="ZincInternal_8hpp.html#a2">ZincInternal.hpp</a><li>Z_CLEANLIST
: <a class="el" href="ZincInternal_8hpp.html#a7">ZincInternal.hpp</a><li>Z_DBL_POOL
: <a class="el" href="ZincInternal_8hpp.html#a4">ZincInternal.hpp</a><li>Z_DEFINE_ZFCT
: <a class="el" href="Zinc_8cpp.html#a98">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a9">ZincInternal.hpp</a><li>Z_DEFINE_ZITM
: <a class="el" href="Zinc_8cpp.html#a106">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a10">ZincInternal.hpp</a><li>Z_DEFINE_ZOPT
: <a class="el" href="Zinc_8cpp.html#a69">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a8">ZincInternal.hpp</a><li>Z_INT_POOL
: <a class="el" href="ZincInternal_8hpp.html#a3">ZincInternal.hpp</a><li>Z_LST_POOL
: <a class="el" href="ZincInternal_8hpp.html#a6">ZincInternal.hpp</a><li>Z_PARENTGROUP
: <a class="el" href="ZincInternal_8hpp.html#a11">ZincInternal.hpp</a><li>Z_STR_POOL
: <a class="el" href="ZincInternal_8hpp.html#a5">ZincInternal.hpp</a><li>z_tcl_call2
: <a class="el" href="Zinc_8cpp.html#a3">Zinc.cpp</a><li>Z_TCLCB
: <a class="el" href="ZincInternal_8hpp.html#a1">ZincInternal.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/globals_enum.html.























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindexHL" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="globals.html">All</a> | <a class="qindex" href="globals_func.html">Functions</a> | <a class="qindex" href="globals_vars.html">Variables</a> | <a class="qindex" href="globals_type.html">Typedefs</a> | <a class="qindexHL" href="globals_enum.html">Enumerations</a> | <a class="qindex" href="globals_eval.html">Enumeration&nbsp;values</a> | <a class="qindex" href="globals_defs.html">Defines</a></div>

<p>
<ul>
<li>alignment
: <a class="el" href="ZincTypes_8hpp.html#a57">ZincTypes.hpp</a><li>anchor
: <a class="el" href="ZincTypes_8hpp.html#a58">ZincTypes.hpp</a><li>capStyle
: <a class="el" href="ZincTypes_8hpp.html#a53">ZincTypes.hpp</a><li>fillRule
: <a class="el" href="ZincTypes_8hpp.html#a54">ZincTypes.hpp</a><li>itemOperator
: <a class="el" href="ZincTypes_8hpp.html#a59">ZincTypes.hpp</a><li>itemType
: <a class="el" href="ZincTypes_8hpp.html#a60">ZincTypes.hpp</a><li>joinStyle
: <a class="el" href="ZincTypes_8hpp.html#a55">ZincTypes.hpp</a><li>lineStyle
: <a class="el" href="ZincTypes_8hpp.html#a52">ZincTypes.hpp</a><li>relief
: <a class="el" href="ZincTypes_8hpp.html#a56">ZincTypes.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/globals_eval.html.















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindexHL" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="globals.html">All</a> | <a class="qindex" href="globals_func.html">Functions</a> | <a class="qindex" href="globals_vars.html">Variables</a> | <a class="qindex" href="globals_type.html">Typedefs</a> | <a class="qindex" href="globals_enum.html">Enumerations</a> | <a class="qindexHL" href="globals_eval.html">Enumeration&nbsp;values</a> | <a class="qindex" href="globals_defs.html">Defines</a></div>
<div class="qindex"><a class="qindex" href="#index_a">a</a> | <a class="qindex" href="#index_c">c</a> | <a class="qindex" href="#index_f">f</a> | <a class="qindex" href="#index_i">i</a> | <a class="qindex" href="#index_j">j</a> | <a class="qindex" href="#index_l">l</a> | <a class="qindex" href="#index_r">r</a></div>

<p>

<p>
<h3><a name="index_a">- a -</a>
</h3><ul>
<li>alignment_center
: <a class="el" href="ZincTypes_8hpp.html#a57a33">ZincTypes.hpp</a><li>alignment_left
: <a class="el" href="ZincTypes_8hpp.html#a57a31">ZincTypes.hpp</a><li>alignment_right
: <a class="el" href="ZincTypes_8hpp.html#a57a32">ZincTypes.hpp</a><li>anchor_center
: <a class="el" href="ZincTypes_8hpp.html#a58a42">ZincTypes.hpp</a><li>anchor_e
: <a class="el" href="ZincTypes_8hpp.html#a58a37">ZincTypes.hpp</a><li>anchor_n
: <a class="el" href="ZincTypes_8hpp.html#a58a35">ZincTypes.hpp</a><li>anchor_ne
: <a class="el" href="ZincTypes_8hpp.html#a58a36">ZincTypes.hpp</a><li>anchor_nw
: <a class="el" href="ZincTypes_8hpp.html#a58a34">ZincTypes.hpp</a><li>anchor_s
: <a class="el" href="ZincTypes_8hpp.html#a58a39">ZincTypes.hpp</a><li>anchor_se
: <a class="el" href="ZincTypes_8hpp.html#a58a38">ZincTypes.hpp</a><li>anchor_sw
: <a class="el" href="ZincTypes_8hpp.html#a58a40">ZincTypes.hpp</a><li>anchor_w
: <a class="el" href="ZincTypes_8hpp.html#a58a41">ZincTypes.hpp</a></ul>
<h3><a name="index_c">- c -</a>
</h3><ul>
<li>capStyle_butt
: <a class="el" href="ZincTypes_8hpp.html#a53a9">ZincTypes.hpp</a><li>capStyle_projecting
: <a class="el" href="ZincTypes_8hpp.html#a53a10">ZincTypes.hpp</a><li>capStyle_round
: <a class="el" href="ZincTypes_8hpp.html#a53a11">ZincTypes.hpp</a></ul>
<h3><a name="index_f">- f -</a>
</h3><ul>
<li>fillRule_abs_geq_2
: <a class="el" href="ZincTypes_8hpp.html#a54a16">ZincTypes.hpp</a><li>fillRule_negative
: <a class="el" href="ZincTypes_8hpp.html#a54a15">ZincTypes.hpp</a><li>fillRule_nonzero
: <a class="el" href="ZincTypes_8hpp.html#a54a13">ZincTypes.hpp</a><li>fillRule_odd
: <a class="el" href="ZincTypes_8hpp.html#a54a12">ZincTypes.hpp</a><li>fillRule_positive
: <a class="el" href="ZincTypes_8hpp.html#a54a14">ZincTypes.hpp</a></ul>
<h3><a name="index_i">- i -</a>
</h3><ul>
<li>item_add_clockwise
: <a class="el" href="ZincTypes_8hpp.html#a59a43">ZincTypes.hpp</a><li>item_add_counterclockwise
: <a class="el" href="ZincTypes_8hpp.html#a59a44">ZincTypes.hpp</a><li>item_arc
: <a class="el" href="ZincTypes_8hpp.html#a60a47">ZincTypes.hpp</a><li>item_curve
: <a class="el" href="ZincTypes_8hpp.html#a60a50">ZincTypes.hpp</a><li>item_group
: <a class="el" href="ZincTypes_8hpp.html#a60a46">ZincTypes.hpp</a><li>item_icon
: <a class="el" href="ZincTypes_8hpp.html#a60a51">ZincTypes.hpp</a><li>item_rectangle
: <a class="el" href="ZincTypes_8hpp.html#a60a49">ZincTypes.hpp</a><li>item_remove
: <a class="el" href="ZincTypes_8hpp.html#a59a45">ZincTypes.hpp</a><li>item_text
: <a class="el" href="ZincTypes_8hpp.html#a60a48">ZincTypes.hpp</a></ul>
<h3><a name="index_j">- j -</a>
</h3><ul>
<li>joinStyle_bevel
: <a class="el" href="ZincTypes_8hpp.html#a55a17">ZincTypes.hpp</a><li>joinStyle_miter
: <a class="el" href="ZincTypes_8hpp.html#a55a18">ZincTypes.hpp</a><li>joinStyle_round
: <a class="el" href="ZincTypes_8hpp.html#a55a19">ZincTypes.hpp</a></ul>
<h3><a name="index_l">- l -</a>
</h3><ul>
<li>lineStyle_dashed
: <a class="el" href="ZincTypes_8hpp.html#a52a6">ZincTypes.hpp</a><li>lineStyle_dotted
: <a class="el" href="ZincTypes_8hpp.html#a52a8">ZincTypes.hpp</a><li>lineStyle_mixed
: <a class="el" href="ZincTypes_8hpp.html#a52a7">ZincTypes.hpp</a><li>lineStyle_simple
: <a class="el" href="ZincTypes_8hpp.html#a52a5">ZincTypes.hpp</a></ul>
<h3><a name="index_r">- r -</a>
</h3><ul>
<li>relief_flat
: <a class="el" href="ZincTypes_8hpp.html#a56a20">ZincTypes.hpp</a><li>relief_groove
: <a class="el" href="ZincTypes_8hpp.html#a56a24">ZincTypes.hpp</a><li>relief_raised
: <a class="el" href="ZincTypes_8hpp.html#a56a21">ZincTypes.hpp</a><li>relief_raisedrule
: <a class="el" href="ZincTypes_8hpp.html#a56a29">ZincTypes.hpp</a><li>relief_ridge
: <a class="el" href="ZincTypes_8hpp.html#a56a23">ZincTypes.hpp</a><li>relief_roundgroove
: <a class="el" href="ZincTypes_8hpp.html#a56a28">ZincTypes.hpp</a><li>relief_roundraised
: <a class="el" href="ZincTypes_8hpp.html#a56a25">ZincTypes.hpp</a><li>relief_roundridge
: <a class="el" href="ZincTypes_8hpp.html#a56a27">ZincTypes.hpp</a><li>relief_roundsunken
: <a class="el" href="ZincTypes_8hpp.html#a56a26">ZincTypes.hpp</a><li>relief_sunken
: <a class="el" href="ZincTypes_8hpp.html#a56a22">ZincTypes.hpp</a><li>relief_sunkenrule
: <a class="el" href="ZincTypes_8hpp.html#a56a30">ZincTypes.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/globals_func.html.

























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindexHL" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="globals.html">All</a> | <a class="qindexHL" href="globals_func.html">Functions</a> | <a class="qindex" href="globals_vars.html">Variables</a> | <a class="qindex" href="globals_type.html">Typedefs</a> | <a class="qindex" href="globals_enum.html">Enumerations</a> | <a class="qindex" href="globals_eval.html">Enumeration&nbsp;values</a> | <a class="qindex" href="globals_defs.html">Defines</a></div>

<p>
<ul>
<li>dtos()
: <a class="el" href="ZincInternal_8hpp.html#a14">ZincInternal.hpp</a><li>itos()
: <a class="el" href="ZincInternal_8hpp.html#a12">ZincInternal.hpp</a><li>ltos()
: <a class="el" href="ZincInternal_8hpp.html#a13">ZincInternal.hpp</a><li>modulo()
: <a class="el" href="ZincPath_8cpp.html#a1">ZincPath.cpp</a><li>tclCallback()
: <a class="el" href="Zinc_8cpp.html#a20">Zinc.cpp</a><li>Tkzinc_Init()
: <a class="el" href="ZincExtern_8hpp.html#a1">ZincExtern.hpp</a><li>Z_DEFINE_ZFCT()
: <a class="el" href="Zinc_8cpp.html#a98">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a9">ZincInternal.hpp</a><li>Z_DEFINE_ZITM()
: <a class="el" href="Zinc_8cpp.html#a106">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a10">ZincInternal.hpp</a><li>Z_DEFINE_ZOPT()
: <a class="el" href="Zinc_8cpp.html#a69">Zinc.cpp</a>, <a class="el" href="ZincInternal_8hpp.html#a8">ZincInternal.hpp</a><li>ZincObjCmd()
: <a class="el" href="ZincExtern_8hpp.html#a2">ZincExtern.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/globals_type.html.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindexHL" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="globals.html">All</a> | <a class="qindex" href="globals_func.html">Functions</a> | <a class="qindex" href="globals_vars.html">Variables</a> | <a class="qindexHL" href="globals_type.html">Typedefs</a> | <a class="qindex" href="globals_enum.html">Enumerations</a> | <a class="qindex" href="globals_eval.html">Enumeration&nbsp;values</a> | <a class="qindex" href="globals_defs.html">Defines</a></div>

<p>
<ul>
<li>String
: <a class="el" href="ZincTypes_8hpp.html#a0">ZincTypes.hpp</a><li>WidgetObjCmd
: <a class="el" href="ZincExtern_8hpp.html#a0">ZincExtern.hpp</a><li>ZincItemCallback
: <a class="el" href="ZincTypes_8hpp.html#a1">ZincTypes.hpp</a><li>ZincWidgetCallback
: <a class="el" href="ZincTypes_8hpp.html#a2">ZincTypes.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/globals_vars.html.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: File Member Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindexHL" href="globals.html">File&nbsp;Members</a></div>
<div class="qindex"><a class="qindex" href="globals.html">All</a> | <a class="qindex" href="globals_func.html">Functions</a> | <a class="qindexHL" href="globals_vars.html">Variables</a> | <a class="qindex" href="globals_type.html">Typedefs</a> | <a class="qindex" href="globals_enum.html">Enumerations</a> | <a class="qindex" href="globals_eval.html">Enumeration&nbsp;values</a> | <a class="qindex" href="globals_defs.html">Defines</a></div>

<p>
<ul>
<li>alignments
: <a class="el" href="Zinc_8cpp.html#a16">Zinc.cpp</a><li>alignmentsStrings
: <a class="el" href="Zinc_8cpp.html#a15">Zinc.cpp</a><li>anchors
: <a class="el" href="Zinc_8cpp.html#a18">Zinc.cpp</a><li>anchorsStrings
: <a class="el" href="Zinc_8cpp.html#a17">Zinc.cpp</a><li>capStyles
: <a class="el" href="Zinc_8cpp.html#a8">Zinc.cpp</a><li>capStylesStrings
: <a class="el" href="Zinc_8cpp.html#a7">Zinc.cpp</a><li>convertRatio
: <a class="el" href="ZincPath_8cpp.html#a0">ZincPath.cpp</a><li>DEFAULT_GROUP
: <a class="el" href="Zinc_8hpp.html#a2">Zinc.hpp</a><li>DEFAULT_GROUP_OBJ
: <a class="el" href="Zinc_8cpp.html#a4">Zinc.cpp</a><li>fillRules
: <a class="el" href="Zinc_8cpp.html#a10">Zinc.cpp</a><li>fillRulesStrings
: <a class="el" href="Zinc_8cpp.html#a9">Zinc.cpp</a><li>itemTypeStrings
: <a class="el" href="Zinc_8cpp.html#a19">Zinc.cpp</a><li>joinStyles
: <a class="el" href="Zinc_8cpp.html#a12">Zinc.cpp</a><li>joinStylesStrings
: <a class="el" href="Zinc_8cpp.html#a11">Zinc.cpp</a><li>lineStyles
: <a class="el" href="Zinc_8cpp.html#a6">Zinc.cpp</a><li>lineStylesStrings
: <a class="el" href="Zinc_8cpp.html#a5">Zinc.cpp</a><li>reliefs
: <a class="el" href="Zinc_8cpp.html#a14">Zinc.cpp</a><li>reliefsStrings
: <a class="el" href="Zinc_8cpp.html#a13">Zinc.cpp</a><li>ZINC_BACKEND_OPENGL
: <a class="el" href="ZincTypes_8hpp.html#a4">ZincTypes.hpp</a><li>ZINC_BACKEND_X11
: <a class="el" href="ZincTypes_8hpp.html#a3">ZincTypes.hpp</a><li>ZINC_PARAM_COUNT
: <a class="el" href="Zinc_8hpp.html#a1">Zinc.hpp</a><li>ZINC_POOL_COUNT
: <a class="el" href="Zinc_8hpp.html#a0">Zinc.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/hierarchy.html.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Hierarchical Index</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindexHL" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>IntuiKit Class Hierarchy</h1>This inheritance list is sorted roughly, but not completely, alphabetically:<ul>
<li><a class="el" href="classZinc.html">Zinc</a>
<li><a class="el" href="structZincEvent.html">ZincEvent</a>
<li><a class="el" href="classZincException.html">ZincException</a>
<li><a class="el" href="classZincFont.html">ZincFont</a>
<li><a class="el" href="classZincItem.html">ZincItem</a>
<ul>
<li><a class="el" href="classZincBitmap.html">ZincBitmap</a>
<li><a class="el" href="classZincImage.html">ZincImage</a>
</ul>
<li><a class="el" href="classZincPath.html">ZincPath</a>
</ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/index.html.































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Main Page</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindexHL" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>IntuiKit Documentation</h1>
<p>
<h3 align="center">1.0 </h3><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:44 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/structZincEvent-members.html.







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: Member List</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincEvent Member List</h1>This is the complete list of members for <a class="el" href="structZincEvent.html">ZincEvent</a>, including all inherited members.<table>
  <tr class="memlist"><td><a class="el" href="structZincEvent.html#o2">k</a></td><td><a class="el" href="structZincEvent.html">ZincEvent</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="structZincEvent.html#o4">K</a></td><td><a class="el" href="structZincEvent.html">ZincEvent</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="structZincEvent.html#o3">t</a></td><td><a class="el" href="structZincEvent.html">ZincEvent</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="structZincEvent.html#o0">x</a></td><td><a class="el" href="structZincEvent.html">ZincEvent</a></td><td></td></tr>
  <tr class="memlist"><td><a class="el" href="structZincEvent.html#o1">y</a></td><td><a class="el" href="structZincEvent.html">ZincEvent</a></td><td></td></tr>
</table><hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doc/html/structZincEvent.html.





























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>IntuiKit: ZincEvent struct Reference</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.3.3 -->
<div class="qindex"><a class="qindex" href="index.html">Main&nbsp;Page</a> | <a class="qindex" href="hierarchy.html">Class&nbsp;Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical&nbsp;List</a> | <a class="qindex" href="annotated.html">Compound&nbsp;List</a> | <a class="qindex" href="files.html">File&nbsp;List</a> | <a class="qindex" href="functions.html">Compound&nbsp;Members</a> | <a class="qindex" href="globals.html">File&nbsp;Members</a></div>
<h1>ZincEvent Struct Reference</h1><code>#include &lt;<a class="el" href="ZincTypes_8hpp-source.html">ZincTypes.hpp</a>&gt;</code>
<p>
<a href="structZincEvent-members.html">List of all members.</a><table border=0 cellpadding=0 cellspacing=0>
<tr><td></td></tr>
<tr><td colspan=2><br><h2>Public Attributes</h2></td></tr>
<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="structZincEvent.html#o0">x</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="structZincEvent.html#o1">y</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>int&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="structZincEvent.html#o2">k</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top>long&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="structZincEvent.html#o3">t</a></td></tr>

<tr><td class="memItemLeft" nowrap align=right valign=top><a class="el" href="ZincTypes_8hpp.html#a0">String</a>&nbsp;</td><td class="memItemRight" valign=bottom><a class="el" href="structZincEvent.html#o4">K</a></td></tr>

</table>
<hr><h2>Member Data Documentation</h2>
<a name="o4" doxytag="ZincEvent::K"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> <a class="el" href="ZincTypes_8hpp.html#a0">String</a> <a class="el" href="structZincEvent.html#o4">ZincEvent::K</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="o2" doxytag="ZincEvent::k"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int <a class="el" href="structZincEvent.html#o2">ZincEvent::k</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="o3" doxytag="ZincEvent::t"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> long <a class="el" href="structZincEvent.html#o3">ZincEvent::t</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="o0" doxytag="ZincEvent::x"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int <a class="el" href="structZincEvent.html#o0">ZincEvent::x</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<a name="o1" doxytag="ZincEvent::y"></a><p>
<table class="mdTable" width="100%" cellpadding="2" cellspacing="0">
  <tr>
    <td class="mdRow">
      <table cellpadding="0" cellspacing="0" border="0">
        <tr>
          <td class="md" nowrap valign="top"> int <a class="el" href="structZincEvent.html#o1">ZincEvent::y</a>
      </table>
    </td>
  </tr>
</table>
<table cellspacing=5 cellpadding=0 border=0>
  <tr>
    <td>
      &nbsp;
    </td>
    <td>

<p>
    </td>
  </tr>
</table>
<hr>The documentation for this struct was generated from the following file:<ul>
<li><a class="el" href="ZincTypes_8hpp-source.html">ZincTypes.hpp</a></ul>
<hr size="1"><address style="align: right;"><small>Generated on Mon Apr 18 17:40:45 2005 for IntuiKit by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 > 
</a>1.3.3 </small></address>
</body>
</html>

Added jni/tkzinc/zinclib.d/doxyConfig.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
# Doxyfile 1.3.3

# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
#       TAG = value [value, ...]
# For lists items can also be appended using:
#       TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")

#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------

# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
# by quotes) that should identify the project.

PROJECT_NAME           = IntuiKit

# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
# This could be handy for archiving the generated documentation or 
# if some version control system is used.

PROJECT_NUMBER         = 1.0

# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
# base path where the generated documentation will be put. 
# If a relative path is entered, it will be relative to the location 
# where doxygen was started. If left blank the current directory will be used.

OUTPUT_DIRECTORY       = docs

# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
# documentation generated by doxygen is written. Doxygen will use this 
# information to generate all constant output in the proper language. 
# The default language is English, other supported languages are: 
# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese, 
# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.

OUTPUT_LANGUAGE        = English

# This tag can be used to specify the encoding used in the generated output. 
# The encoding is not always determined by the language that is chosen, 
# but also whether or not the output is meant for Windows or non-Windows users. 
# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
# forces the Windows encoding (this is the default for the Windows binary), 
# whereas setting the tag to NO uses a Unix-style encoding (the default for 
# all platforms other than Windows).

USE_WINDOWS_ENCODING   = NO

# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
# documentation are documented, even if no documentation was available. 
# Private class members and static file members will be hidden unless 
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES

EXTRACT_ALL            = YES

# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
# will be included in the documentation.

EXTRACT_PRIVATE        = NO

# If the EXTRACT_STATIC tag is set to YES all static members of a file 
# will be included in the documentation.

EXTRACT_STATIC         = YES

# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
# defined locally in source files will be included in the documentation. 
# If set to NO only classes defined in header files are included.

EXTRACT_LOCAL_CLASSES  = YES

# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
# undocumented members of documented classes, files or namespaces. 
# If set to NO (the default) these members will be included in the 
# various overviews, but no documentation section is generated. 
# This option has no effect if EXTRACT_ALL is enabled.

HIDE_UNDOC_MEMBERS     = NO

# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
# undocumented classes that are normally visible in the class hierarchy. 
# If set to NO (the default) these classes will be included in the various 
# overviews. This option has no effect if EXTRACT_ALL is enabled.

HIDE_UNDOC_CLASSES     = NO

# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
# friend (class|struct|union) declarations. 
# If set to NO (the default) these declarations will be included in the 
# documentation.

HIDE_FRIEND_COMPOUNDS  = NO

# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
# documentation blocks found inside the body of a function. 
# If set to NO (the default) these blocks will be appended to the 
# function's detailed documentation block.

HIDE_IN_BODY_DOCS      = NO

# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
# include brief member descriptions after the members that are listed in 
# the file and class documentation (similar to JavaDoc). 
# Set to NO to disable this.

BRIEF_MEMBER_DESC      = YES

# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
# the brief description of a member or function before the detailed description. 
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
# brief descriptions will be completely suppressed.

REPEAT_BRIEF           = YES

# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
# Doxygen will generate a detailed section even if there is only a brief 
# description.

ALWAYS_DETAILED_SEC    = NO

# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
# members of a class in the documentation of that class as if those members were 
# ordinary class members. Constructors, destructors and assignment operators of 
# the base classes will not be shown.

INLINE_INHERITED_MEMB  = NO

# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
# path before files name in the file list and in the header files. If set 
# to NO the shortest path that makes the file name unique will be used.

FULL_PATH_NAMES        = NO

# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
# can be used to strip a user-defined part of the path. Stripping is 
# only done if one of the specified strings matches the left-hand part of 
# the path. It is allowed to use relative paths in the argument list.

STRIP_FROM_PATH        = 

# The INTERNAL_DOCS tag determines if documentation 
# that is typed after a \internal command is included. If the tag is set 
# to NO (the default) then the documentation will be excluded. 
# Set it to YES to include the internal documentation.

INTERNAL_DOCS          = NO

# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
# file names in lower-case letters. If set to YES upper-case letters are also 
# allowed. This is useful if you have classes or files whose names only differ 
# in case and if your file system supports case sensitive file names. Windows 
# users are advised to set this option to NO.

CASE_SENSE_NAMES       = YES

# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
# (but less readable) file names. This can be useful is your file systems 
# doesn't support long names like on DOS, Mac, or CD-ROM.

SHORT_NAMES            = NO

# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
# will show members with their full class and namespace scopes in the 
# documentation. If set to YES the scope will be hidden.

HIDE_SCOPE_NAMES       = NO

# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
# will put a list of the files that are included by a file in the documentation 
# of that file.

SHOW_INCLUDE_FILES     = YES

# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
# will interpret the first line (until the first dot) of a JavaDoc-style 
# comment as the brief description. If set to NO, the JavaDoc 
# comments will behave just like the Qt-style comments (thus requiring an 
# explict @brief command for a brief description.

JAVADOC_AUTOBRIEF      = NO

# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
# comments) as a brief description. This used to be the default behaviour. 
# The new default is to treat a multi-line C++ comment block as a detailed 
# description. Set this tag to YES if you prefer the old behaviour instead.

MULTILINE_CPP_IS_BRIEF = NO

# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
# will output the detailed description near the top, like JavaDoc.
# If set to NO, the detailed description appears after the member 
# documentation.

DETAILS_AT_TOP         = YES

# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
# member inherits the documentation from any documented member that it 
# reimplements.

INHERIT_DOCS           = YES

# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
# is inserted in the documentation for inline members.

INLINE_INFO            = YES

# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
# will sort the (detailed) documentation of file and class members 
# alphabetically by member name. If set to NO the members will appear in 
# declaration order.

SORT_MEMBER_DOCS       = YES

# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
# tag is set to YES, then doxygen will reuse the documentation of the first 
# member in the group (if any) for the other members of the group. By default 
# all members of a group must be documented explicitly.

DISTRIBUTE_GROUP_DOC   = NO

# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
# Doxygen uses this value to replace tabs by spaces in code fragments.

TAB_SIZE               = 8

# The GENERATE_TODOLIST tag can be used to enable (YES) or 
# disable (NO) the todo list. This list is created by putting \todo 
# commands in the documentation.

GENERATE_TODOLIST      = YES

# The GENERATE_TESTLIST tag can be used to enable (YES) or 
# disable (NO) the test list. This list is created by putting \test 
# commands in the documentation.

GENERATE_TESTLIST      = YES

# The GENERATE_BUGLIST tag can be used to enable (YES) or 
# disable (NO) the bug list. This list is created by putting \bug 
# commands in the documentation.

GENERATE_BUGLIST       = YES

# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
# disable (NO) the deprecated list. This list is created by putting 
# \deprecated commands in the documentation.

GENERATE_DEPRECATEDLIST= YES

# This tag can be used to specify a number of aliases that acts 
# as commands in the documentation. An alias has the form "name=value". 
# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
# put the command \sideeffect (or @sideeffect) in the documentation, which 
# will result in a user-defined paragraph with heading "Side Effects:". 
# You can put \n's in the value part of an alias to insert newlines.

ALIASES                = 

# The ENABLED_SECTIONS tag can be used to enable conditional 
# documentation sections, marked by \if sectionname ... \endif.

ENABLED_SECTIONS       = 

# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
# the initial value of a variable or define consists of for it to appear in 
# the documentation. If the initializer consists of more lines than specified 
# here it will be hidden. Use a value of 0 to hide initializers completely. 
# The appearance of the initializer of individual variables and defines in the 
# documentation can be controlled using \showinitializer or \hideinitializer 
# command in the documentation regardless of this setting.

MAX_INITIALIZER_LINES  = 30

# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
# only. Doxygen will then generate output that is more tailored for C. 
# For instance, some of the names that are used will be different. The list 
# of all members will be omitted, etc.

OPTIMIZE_OUTPUT_FOR_C  = NO

# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
# only. Doxygen will then generate output that is more tailored for Java. 
# For instance, namespaces will be presented as packages, qualified scopes 
# will look different, etc.

OPTIMIZE_OUTPUT_JAVA   = NO

# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
# at the bottom of the documentation of classes and structs. If set to YES the 
# list will mention the files that were used to generate the documentation.

SHOW_USED_FILES        = YES

# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
# the same type (for instance a group of public functions) to be put as a 
# subgroup of that type (e.g. under the Public Functions section). Set it to 
# NO to prevent subgrouping. Alternatively, this can be done per class using 
# the \nosubgrouping command.

SUBGROUPING            = YES

#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------

# The QUIET tag can be used to turn on/off the messages that are generated 
# by doxygen. Possible values are YES and NO. If left blank NO is used.

QUIET                  = NO

# The WARNINGS tag can be used to turn on/off the warning messages that are 
# generated by doxygen. Possible values are YES and NO. If left blank 
# NO is used.

WARNINGS               = YES

# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
# automatically be disabled.

WARN_IF_UNDOCUMENTED   = YES

# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
# potential errors in the documentation, such as not documenting some 
# parameters in a documented function, or documenting parameters that 
# don't exist or using markup commands wrongly.

WARN_IF_DOC_ERROR      = YES

# The WARN_FORMAT tag determines the format of the warning messages that 
# doxygen can produce. The string should contain the $file, $line, and $text 
# tags, which will be replaced by the file and line number from which the 
# warning originated and the warning text.

WARN_FORMAT            = "$file:$line: $text"

# The WARN_LOGFILE tag can be used to specify a file to which warning 
# and error messages should be written. If left blank the output is written 
# to stderr.

WARN_LOGFILE           = 

#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------

# The INPUT tag can be used to specify the files and/or directories that contain 
# documented source files. You may enter file names like "myfile.cpp" or 
# directories like "/usr/src/myproject". Separate the files or directories 
# with spaces.

INPUT                  = 

# If the value of the INPUT tag contains directories, you can use the 
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
# and *.h) to filter out the source-files in the directories. If left 
# blank the following patterns are tested: 
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
# *.h++ *.idl *.odl *.cs

FILE_PATTERNS          = 

# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
# should be searched for input files as well. Possible values are YES and NO. 
# If left blank NO is used.

RECURSIVE              = NO

# The EXCLUDE tag can be used to specify files and/or directories that should 
# excluded from the INPUT source files. This way you can easily exclude a 
# subdirectory from a directory tree whose root is specified with the INPUT tag.

EXCLUDE                = 

# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
# that are symbolic links (a Unix filesystem feature) are excluded from the input.

EXCLUDE_SYMLINKS       = NO

# If the value of the INPUT tag contains directories, you can use the 
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
# certain files from those directories.

EXCLUDE_PATTERNS       = 

# The EXAMPLE_PATH tag can be used to specify one or more files or 
# directories that contain example code fragments that are included (see 
# the \include command).

EXAMPLE_PATH           = 

# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
# and *.h) to filter out the source-files in the directories. If left 
# blank all files are included.

EXAMPLE_PATTERNS       = 

# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
# searched for input files to be used with the \include or \dontinclude 
# commands irrespective of the value of the RECURSIVE tag. 
# Possible values are YES and NO. If left blank NO is used.

EXAMPLE_RECURSIVE      = NO

# The IMAGE_PATH tag can be used to specify one or more files or 
# directories that contain image that are included in the documentation (see 
# the \image command).

IMAGE_PATH             = 

# The INPUT_FILTER tag can be used to specify a program that doxygen should 
# invoke to filter for each input file. Doxygen will invoke the filter program 
# by executing (via popen()) the command <filter> <input-file>, where <filter> 
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
# input file. Doxygen will then use the output that the filter program writes 
# to standard output.

INPUT_FILTER           = 

# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
# INPUT_FILTER) will be used to filter the input files when producing source 
# files to browse (i.e. when SOURCE_BROWSER is set to YES).

FILTER_SOURCE_FILES    = NO

#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------

# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
# be generated. Documented entities will be cross-referenced with these sources.

SOURCE_BROWSER         = NO

# Setting the INLINE_SOURCES tag to YES will include the body 
# of functions and classes directly in the documentation.

INLINE_SOURCES         = NO

# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
# doxygen to hide any special comment blocks from generated source code 
# fragments. Normal C and C++ comments will always remain visible.

STRIP_CODE_COMMENTS    = YES

# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
# then for each documented function all documented 
# functions referencing it will be listed.

REFERENCED_BY_RELATION = YES

# If the REFERENCES_RELATION tag is set to YES (the default) 
# then for each documented function all documented entities 
# called/used by that function will be listed.

REFERENCES_RELATION    = YES

# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
# will generate a verbatim copy of the header file for each class for 
# which an include is specified. Set to NO to disable this.

VERBATIM_HEADERS       = YES

#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------

# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
# of all compounds will be generated. Enable this if the project 
# contains a lot of classes, structs, unions or interfaces.

ALPHABETICAL_INDEX     = YES

# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
# in which this list will be split (can be a number in the range [1..20])

COLS_IN_ALPHA_INDEX    = 5

# In case all classes in a project start with a common prefix, all 
# classes will be put under the same header in the alphabetical index. 
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
# should be ignored while generating the index headers.

IGNORE_PREFIX          = 

#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------

# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
# generate HTML output.

GENERATE_HTML          = YES

# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
# put in front of it. If left blank `html' will be used as the default path.

HTML_OUTPUT            = html

# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
# doxygen will generate files with .html extension.

HTML_FILE_EXTENSION    = .html

# The HTML_HEADER tag can be used to specify a personal HTML header for 
# each generated HTML page. If it is left blank doxygen will generate a 
# standard header.

HTML_HEADER            = 

# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
# each generated HTML page. If it is left blank doxygen will generate a 
# standard footer.

HTML_FOOTER            = 

# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
# style sheet that is used by each HTML page. It can be used to 
# fine-tune the look of the HTML output. If the tag is left blank doxygen 
# will generate a default style sheet

HTML_STYLESHEET        = 

# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
# files or namespaces will be aligned in HTML using tables. If set to 
# NO a bullet list will be used.

HTML_ALIGN_MEMBERS     = YES

# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
# will be generated that can be used as input for tools like the 
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
# of the generated HTML documentation.

GENERATE_HTMLHELP      = NO

# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
# be used to specify the file name of the resulting .chm file. You 
# can add a path in front of the file if the result should not be 
# written to the html output dir.

CHM_FILE               = 

# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
# be used to specify the location (absolute path including file name) of 
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
# the HTML help compiler on the generated index.hhp.

HHC_LOCATION           = 

# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
# controls if a separate .chi index file is generated (YES) or that 
# it should be included in the master .chm file (NO).

GENERATE_CHI           = NO

# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
# controls whether a binary table of contents is generated (YES) or a 
# normal table of contents (NO) in the .chm file.

BINARY_TOC             = NO

# The TOC_EXPAND flag can be set to YES to add extra items for group members 
# to the contents of the HTML help documentation and to the tree view.

TOC_EXPAND             = YES

# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
# top of each HTML page. The value NO (the default) enables the index and 
# the value YES disables it.

DISABLE_INDEX          = NO

# This tag can be used to set the number of enum values (range [1..20]) 
# that doxygen will group on one line in the generated HTML documentation.

ENUM_VALUES_PER_LINE   = 4

# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
# generated containing a tree-like index structure (just like the one that 
# is generated for HTML Help). For this to work a browser that supports 
# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
# probably better off using the HTML help feature.

GENERATE_TREEVIEW      = NO

# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
# used to set the initial width (in pixels) of the frame in which the tree 
# is shown.

TREEVIEW_WIDTH         = 250

#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------

# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
# generate Latex output.

GENERATE_LATEX         = NO

# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
# put in front of it. If left blank `latex' will be used as the default path.

LATEX_OUTPUT           = latex

# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
# invoked. If left blank `latex' will be used as the default command name.

LATEX_CMD_NAME         = latex

# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
# generate index for LaTeX. If left blank `makeindex' will be used as the 
# default command name.

MAKEINDEX_CMD_NAME     = makeindex

# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
# LaTeX documents. This may be useful for small projects and may help to 
# save some trees in general.

COMPACT_LATEX          = NO

# The PAPER_TYPE tag can be used to set the paper type that is used 
# by the printer. Possible values are: a4, a4wide, letter, legal and 
# executive. If left blank a4wide will be used.

PAPER_TYPE             = a4wide

# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
# packages that should be included in the LaTeX output.

EXTRA_PACKAGES         = 

# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
# the generated latex document. The header should contain everything until 
# the first chapter. If it is left blank doxygen will generate a 
# standard header. Notice: only use this tag if you know what you are doing!

LATEX_HEADER           = 

# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
# contain links (just like the HTML output) instead of page references 
# This makes the output suitable for online browsing using a pdf viewer.

PDF_HYPERLINKS         = NO

# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
# plain latex in the generated Makefile. Set this option to YES to get a 
# higher quality PDF documentation.

USE_PDFLATEX           = NO

# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
# command to the generated LaTeX files. This will instruct LaTeX to keep 
# running if errors occur, instead of asking the user for help. 
# This option is also used when generating formulas in HTML.

LATEX_BATCHMODE        = NO

# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
# include the index chapters (such as File Index, Compound Index, etc.) 
# in the output.

LATEX_HIDE_INDICES     = NO

#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------

# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
# The RTF output is optimised for Word 97 and may not look very pretty with 
# other RTF readers or editors.

GENERATE_RTF           = NO

# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
# put in front of it. If left blank `rtf' will be used as the default path.

RTF_OUTPUT             = rtf

# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
# RTF documents. This may be useful for small projects and may help to 
# save some trees in general.

COMPACT_RTF            = NO

# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
# will contain hyperlink fields. The RTF file will 
# contain links (just like the HTML output) instead of page references. 
# This makes the output suitable for online browsing using WORD or other 
# programs which support those fields. 
# Note: wordpad (write) and others do not support links.

RTF_HYPERLINKS         = NO

# Load stylesheet definitions from file. Syntax is similar to doxygen's 
# config file, i.e. a series of assigments. You only have to provide 
# replacements, missing definitions are set to their default value.

RTF_STYLESHEET_FILE    = 

# Set optional variables used in the generation of an rtf document. 
# Syntax is similar to doxygen's config file.

RTF_EXTENSIONS_FILE    = 

#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------

# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
# generate man pages

GENERATE_MAN           = NO

# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
# put in front of it. If left blank `man' will be used as the default path.

MAN_OUTPUT             = man

# The MAN_EXTENSION tag determines the extension that is added to 
# the generated man pages (default is the subroutine's section .3)

MAN_EXTENSION          = .3

# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
# then it will generate one additional man file for each entity 
# documented in the real man page(s). These additional files 
# only source the real man page, but without them the man command 
# would be unable to find the correct page. The default is NO.

MAN_LINKS              = NO

#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------

# If the GENERATE_XML tag is set to YES Doxygen will 
# generate an XML file that captures the structure of 
# the code including all documentation. Note that this 
# feature is still experimental and incomplete at the 
# moment.

GENERATE_XML           = NO

# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
# put in front of it. If left blank `xml' will be used as the default path.

XML_OUTPUT             = xml

# The XML_SCHEMA tag can be used to specify an XML schema, 
# which can be used by a validating XML parser to check the 
# syntax of the XML files.

XML_SCHEMA             = 

# The XML_DTD tag can be used to specify an XML DTD, 
# which can be used by a validating XML parser to check the 
# syntax of the XML files.

XML_DTD                = 

#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------

# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
# generate an AutoGen Definitions (see autogen.sf.net) file 
# that captures the structure of the code including all 
# documentation. Note that this feature is still experimental 
# and incomplete at the moment.

GENERATE_AUTOGEN_DEF   = NO

#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------

# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
# generate a Perl module file that captures the structure of 
# the code including all documentation. Note that this 
# feature is still experimental and incomplete at the 
# moment.

GENERATE_PERLMOD       = NO

# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
# to generate PDF and DVI output from the Perl module output.

PERLMOD_LATEX          = NO

# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
# nicely formatted so it can be parsed by a human reader.  This is useful 
# if you want to understand what is going on.  On the other hand, if this 
# tag is set to NO the size of the Perl module output will be much smaller 
# and Perl will parse it just the same.

PERLMOD_PRETTY         = YES

# The names of the make variables in the generated doxyrules.make file 
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
# This is useful so different doxyrules.make files included by the same 
# Makefile don't overwrite each other's variables.

PERLMOD_MAKEVAR_PREFIX = 

#---------------------------------------------------------------------------
# Configuration options related to the preprocessor   
#---------------------------------------------------------------------------

# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
# evaluate all C-preprocessor directives found in the sources and include 
# files.

ENABLE_PREPROCESSING   = YES

# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
# names in the source code. If set to NO (the default) only conditional 
# compilation will be performed. Macro expansion can be done in a controlled 
# way by setting EXPAND_ONLY_PREDEF to YES.

MACRO_EXPANSION        = NO

# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
# then the macro expansion is limited to the macros specified with the 
# PREDEFINED and EXPAND_AS_PREDEFINED tags.

EXPAND_ONLY_PREDEF     = NO

# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
# in the INCLUDE_PATH (see below) will be search if a #include is found.

SEARCH_INCLUDES        = YES

# The INCLUDE_PATH tag can be used to specify one or more directories that 
# contain include files that are not input files but should be processed by 
# the preprocessor.

INCLUDE_PATH           = 

# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
# patterns (like *.h and *.hpp) to filter out the header-files in the 
# directories. If left blank, the patterns specified with FILE_PATTERNS will 
# be used.

INCLUDE_FILE_PATTERNS  = 

# The PREDEFINED tag can be used to specify one or more macro names that 
# are defined before the preprocessor is started (similar to the -D option of 
# gcc). The argument of the tag is a list of macros of the form: name 
# or name=definition (no spaces). If the definition and the = are 
# omitted =1 is assumed.

PREDEFINED             = 

# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
# this tag can be used to specify a list of macro names that should be expanded. 
# The macro definition that is found in the sources will be used. 
# Use the PREDEFINED tag if you want to use a different macro definition.

EXPAND_AS_DEFINED      = 

# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
# doxygen's preprocessor will remove all function-like macros that are alone 
# on a line, have an all uppercase name, and do not end with a semicolon. Such 
# function macros are typically used for boiler-plate code, and will confuse the 
# parser if not removed.

SKIP_FUNCTION_MACROS   = YES

#---------------------------------------------------------------------------
# Configuration::addtions related to external references   
#---------------------------------------------------------------------------

# The TAGFILES option can be used to specify one or more tagfiles. 
# Optionally an initial location of the external documentation 
# can be added for each tagfile. The format of a tag file without 
# this location is as follows: 
#   TAGFILES = file1 file2 ... 
# Adding location for the tag files is done as follows: 
#   TAGFILES = file1=loc1 "file2 = loc2" ... 
# where "loc1" and "loc2" can be relative or absolute paths or 
# URLs. If a location is present for each tag, the installdox tool 
# does not have to be run to correct the links.
# Note that each tag file must have a unique name
# (where the name does NOT include the path)
# If a tag file is not located in the directory in which doxygen 
# is run, you must also specify the path to the tagfile here.

TAGFILES               = 

# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
# a tag file that is based on the input files it reads.

GENERATE_TAGFILE       = 

# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
# in the class index. If set to NO only the inherited external classes 
# will be listed.

ALLEXTERNALS           = NO

# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
# in the modules index. If set to NO, only the current project's groups will 
# be listed.

EXTERNAL_GROUPS        = YES

# The PERL_PATH should be the absolute path and name of the perl script 
# interpreter (i.e. the result of `which perl').

PERL_PATH              = /usr/bin/perl

#---------------------------------------------------------------------------
# Configuration options related to the dot tool   
#---------------------------------------------------------------------------

# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
# super classes. Setting the tag to NO turns the diagrams off. Note that this 
# option is superceded by the HAVE_DOT option below. This is only a fallback. It is 
# recommended to install and use dot, since it yields more powerful graphs.

CLASS_DIAGRAMS         = YES

# If set to YES, the inheritance and collaboration graphs will hide 
# inheritance and usage relations if the target is undocumented 
# or is not a class.

HIDE_UNDOC_RELATIONS   = YES

# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
# available from the path. This tool is part of Graphviz, a graph visualization 
# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
# have no effect if this option is set to NO (the default)

HAVE_DOT               = NO

# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
# will generate a graph for each documented class showing the direct and 
# indirect inheritance relations. Setting this tag to YES will force the 
# the CLASS_DIAGRAMS tag to NO.

CLASS_GRAPH            = YES

# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
# will generate a graph for each documented class showing the direct and 
# indirect implementation dependencies (inheritance, containment, and 
# class references variables) of the class with other documented classes.

COLLABORATION_GRAPH    = YES

# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
# collaboration diagrams in a style similiar to the OMG's Unified Modeling 
# Language.

UML_LOOK               = NO

# If set to YES, the inheritance and collaboration graphs will show the 
# relations between templates and their instances.

TEMPLATE_RELATIONS     = NO

# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
# tags are set to YES then doxygen will generate a graph for each documented 
# file showing the direct and indirect include dependencies of the file with 
# other documented files.

INCLUDE_GRAPH          = YES

# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
# documented header file showing the documented files that directly or 
# indirectly include this file.

INCLUDED_BY_GRAPH      = YES

# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
# generate a call dependency graph for every global function or class method. 
# Note that enabling this option will significantly increase the time of a run. 
# So in most cases it will be better to enable call graphs for selected 
# functions only using the \callgraph command.

CALL_GRAPH             = NO

# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
# will graphical hierarchy of all classes instead of a textual one.

GRAPHICAL_HIERARCHY    = YES

# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
# generated by dot. Possible values are png, jpg, or gif
# If left blank png will be used.

DOT_IMAGE_FORMAT       = png

# The tag DOT_PATH can be used to specify the path where the dot tool can be 
# found. If left blank, it is assumed the dot tool can be found on the path.

DOT_PATH               = 

# The DOTFILE_DIRS tag can be used to specify one or more directories that 
# contain dot files that are included in the documentation (see the 
# \dotfile command).

DOTFILE_DIRS           = 

# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
# this value, doxygen will try to truncate the graph, so that it fits within 
# the specified constraint. Beware that most browsers cannot cope with very 
# large images.

MAX_DOT_GRAPH_WIDTH    = 1024

# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
# this value, doxygen will try to truncate the graph, so that it fits within 
# the specified constraint. Beware that most browsers cannot cope with very 
# large images.

MAX_DOT_GRAPH_HEIGHT   = 1024

# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
# graphs generated by dot. A depth value of 3 means that only nodes reachable 
# from the root by following a path via at most 3 edges will be shown. Nodes that 
# lay further from the root node will be omitted. Note that setting this option to 
# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
# note that a graph may be further truncated if the graph's image dimensions are 
# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
# If 0 is used for the depth value (the default), the graph is not depth-constrained.

MAX_DOT_GRAPH_DEPTH    = 0

# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
# generate a legend page explaining the meaning of the various boxes and 
# arrows in the dot generated graphs.

GENERATE_LEGEND        = YES

# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
# remove the intermediate dot files that are used to generate 
# the various graphs.

DOT_CLEANUP            = YES

#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine   
#---------------------------------------------------------------------------

# The SEARCHENGINE tag specifies whether or not a search engine should be 
# used. If set to NO the values of all tags below this one will be ignored.

SEARCHENGINE           = NO

# The CGI_NAME tag should be the name of the CGI script that 
# starts the search engine (doxysearch) with the correct parameters. 
# A script with this name will be generated by doxygen.

CGI_NAME               = search.cgi

# The CGI_URL tag should be the absolute URL to the directory where the 
# cgi binaries are located. See the documentation of your http daemon for 
# details.

CGI_URL                = 

# The DOC_URL tag should be the absolute URL to the directory where the 
# documentation is located. If left blank the absolute path to the 
# documentation, with file:// prepended to it, will be used.

DOC_URL                = 

# The DOC_ABSPATH tag should be the absolute path to the directory where the 
# documentation is located. If left blank the directory on the local machine 
# will be used.

DOC_ABSPATH            = 

# The BIN_ABSPATH tag must point to the directory where the doxysearch binary 
# is installed.

BIN_ABSPATH            = /usr/local/bin/

# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
# documentation generated for other projects. This allows doxysearch to search 
# the documentation for these projects as well.

EXT_DOC_PATHS          = 

Added jni/tkzinc/zinclib.d/gen.pl.







































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#!/usr/bin/perl

#   This software is the property of IntuiLab SA, France.
#   All rights reserved.
#
#   Redistribution and use in source and binary forms, with or without
#   modification, are permitted provided that the following conditions
#   are met:
#   1. Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#   2. Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#   3. The name of the author may not be used to endorse or promote products
#      derived from this software without specific prior written permission.
# 
#   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
#   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
#   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
#   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
#   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
#   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


$a="";

$res = "";
$undone = "";
$enum = "";
$enum2 = "";
open CODE,">code.cpp";
open HPP,">code.hpp";
while (<>)
{
  if( /{ ZN_CONFIG_(\w+), "-(\w+)"/ )
  {
	if(defined $opt{$2})
	{
	   next if($opt{$2} == $1);
	   die("ERROR different TYPE\n");
	}
	$opt{$2} = $1;
        if( $1 eq "BOOL" )
        { $e = 0; $t = "bool"; $T = "BOO"; }
        elsif( $1 eq "FLAG" )
        { $e = 0; $t = "int"; $T= "INT"; }
	elsif( $1 eq "GRADIENT" )
	{ $e = 0; $t = "String"; $T= "STR"; }
	elsif( $1 eq "UINT" )
	{ $e = 0; $t = "unsigned int"; $T= "INT"; }
	elsif( $1 eq "INT" )
	{ $e = 0; $t = "int"; $T= "INT"; }
	elsif( $1 eq "LINE_STYLE" )
	{ $e = 1; $t = "ineStyle"; $T="lineStyles"; }
	elsif( $1 eq "DIM" )
	{ $e = 0; $t = "double"; $T= "DBL"; }
	elsif( $1 eq "ANGLE" )
	{ $e = 0; $t = "unsigned int"; $T= "INT"; }
	elsif( $1 eq "PRI" )
	{ $e = 0; $t = "unsigned int"; $T= "INT"; }
	elsif( $1 eq "RELIEF" )
	{ $e = 1; $t = "relief"; $T="reliefs"; }
	elsif( $1 eq "ALPHA" )
	{ $e = 0; $t = "unsigned int"; $T= "INT"; }
	elsif( $1 eq "TEXT" )
	{ $e = 0; $t = "String"; $T= "STR"; }
	elsif( $1 eq "ALIGNMENT" )
	{ $e = 1; $t = "alignment"; $T="alignments"; }
	elsif( $1 eq "USHORT" )
	{ $e = 0; $t = "unsigned short"; $T= "INT"; }
	elsif( $1 eq "SHORT" )
	{ $e = 0; $t = "short"; $T= "INT"; }
	elsif( $1 eq "STRING" )
	{ $e = 0; $t = "String"; $T= "STR"; }
	elsif( $1 eq "FONT" )
	{ $e = 0; $t = "ZincFont *"; $T= "PSTR"; }
	elsif( $1 eq "ITEM" )
	{ $e = 0; $t = "ZincItem *"; $T= "PTR"; }
	elsif( $1 eq "BITMAP" )
	{ $e = 0; $t = "ZincBitmap *"; $T= "PTR"; }
	elsif( $1 eq "IMAGE" )
	{ $e = 0; $t = "ZincImage *"; $T= "PTR"; }
	elsif( $1 eq "ANCHOR" )
	{ $e = 1; $t = "anchor"; $T="anchors"; }
	elsif( $1 eq "LINE_SHAPE" )
	{ $e = 1; $t = "lineShape"; $T="lineShapes"; }
	elsif( $1 eq "CAP_STYLE" )
	{ $e = 1; $t = "capStyle"; $T="capStyles"; }
	elsif( $1 eq "JOIN_STYLE" )
	{ $e = 1; $t = "joinStyle"; $T="joinStyles"; }
	elsif( $1 eq "FILL_RULE" )
	{ $e = 1; $t = "fillRule"; $T="fillRules"; }
	elsif( $1 eq "EDGE_LIST" )
	{ $e = 1; $t = "edgeList"; $T="edgeLists"; }
	else
	{
	   $undone .= "$2: $1\n";
	   next;
        }

	$t2 = $2;
	substr($t2,0,1) =~ tr/[a-z]/[A-Z]/;
	if($e==1)
	{
	  if($en{$1}!=1)
	  {
	    $enum .= "$t { t_$T };\n";
	    $enum2.= "const char* $T"."Strings [1] = { \"t$T\" };\n";
	    $enum2.= "Tcl_Obj* $T [1] = { Tcl_NewStringObj (\"t$T\", -1) };\n";
	    $en{$1}=1;
	  }
	}
        print HPP "  /**\n";
        print HPP "   * Call zinc->itemconfigure ( -$2 )\n";
	print HPP "   * \@param item the item to configure\n";
	print HPP "   * \@param value the $2 to set\n";
        print HPP "   */\n";
	print HPP "  void itemSet$t2 (ZincItem * item, $t value);\n\n";
        print HPP "  /**\n";
        print HPP "   * Call zinc->itemcget ( -$2 )\n";
	print HPP "   * \@param item the item to get $2 from\n";
	print HPP "   * \@return $2 value\n";
        print HPP "   */\n";
	if ($t eq "String")
	{
	  print HPP "  String itemGet$t2 (ZincItem * item);\n\n";
	}
	else
	{
	  print HPP "  $t itemGet$t2 (ZincItem * item);\n\n";
	}
	$res .= "Z_DEFINE_ZOPT ($2);   //the \"-$2\" option\n";
	
        print CODE "/**\n";
        print CODE " * Call zinc->itemconfigure ( -$2 )\n";
	print CODE " *\n";
	print CODE " * \@param item the item to configure\n";
	print CODE " * \@param value the $2 to set\n";
        print CODE " */\n";
        print CODE "void Zinc::itemSet$t2 (ZincItem * item, $t value)\n";
        print CODE "{\n";
	print CODE "  //prepare arguments : .zinc itemconfigure item attribute value\n";
        print CODE "  p1[0] = id;\n";
	print CODE "  p1[1] = ZFCT_itemconfigure;\n";
	print CODE "  p1[2] = item->object;\n";
        print CODE "  p1[3] = ZOPT_$2;\n";
	if( $e==1 )
	{
	   print CODE "  p1[4] = ".$T."[value];\n";
	}
	elsif ($T eq "PTR")
	{
	  print CODE "  p1[4] = value->object;\n";
	}
	elsif ($T eq "PSTR")
	{
	  print CODE "  p1[4] = Z_STR_POOL (0, value->name.c_str(), value->name.length());\n";
        }
	elsif ($T eq "STR")
	{
	    print CODE "  p1[4] = Z_".$T."_POOL (1, value.c_str (), value.length ());\n";
        }
	else
	{
	    print CODE "  p1[4] = Z_".$T."_POOL (1, value);\n";
        }
	print CODE "  //call the zinc function with 5 arguments in internal form\n";
        print CODE "  z_command (5, \"itemSet$t2 Failed : \");\n";
        print CODE "}\n\n";
	
	print CODE "/**\n";
	print CODE " * Call zinc->itemcget ( -$2 )\n";
	print CODE " *\n";
	print CODE " * \@param item the item to get $2 from\n";
	print CODE " * \@return $2 value\n";
	print CODE " */\n";
	if ($t eq "String")
	{
	  print CODE "String Zinc::itemGet$t2 (ZincItem * item)\n";
	}
	else
	{
	  print CODE "$t Zinc::itemGet$t2 (ZincItem * item)\n";
	}
	print CODE "{\n";
        print CODE "  Tcl_Obj* tmp;\n";
	print CODE "  //discard all old results\n";
	print CODE "  Tcl_ResetResult (interp);\n";
	print CODE "  //prepare arguments : .zinc itemcget item \n";
        print CODE "  p1[0] = id;\n";
	print CODE "  p1[1] = ZFCT_itemcget;\n";
	print CODE "  p1[2] = item->object;\n";
        print CODE "  p1[3] = ZOPT_$2;\n";	
	print CODE "  //call the zinc function with 4 arguments in internal form\n";
        print CODE "  z_command (4, \"itemGet$t2 Failed : \");\n\n";
	print CODE "  //retreive the result trough the tcl interpreter and convert it\n";
	print CODE "  tmp = Tcl_GetObjResult (interp);\n";
	if($e == 1)
	{
	  print CODE "  int value;\n";
	  print CODE "  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,\n";
	  print CODE "                                   $T"."Strings, \n";
	  print CODE "                                   \"$T\",\n";
	  print CODE "                                   0, &value),\n";
	  print CODE "              \"itemGet$t2 Failed : \")\n";
	  print CODE "  return $t (value);\n";
	}
	elsif ( $T eq "STR")
	{
	  print CODE "  return String (Tcl_GetStringFromObj (tmp, NULL));\n";
	}
	elsif ( $T eq "PSTR")
	{
	  print CODE "  return new ZincFont (String (Tcl_GetStringResult (interp)));\n";
	}
	elsif ( $T eq "PTR" )
	{
	  if( $t =~ /ZincItem/ )
	  {
	    print CODE "  return new ZincItem(tmp);\n";
	  }
	  else if ( $t =~ /ZincImage/ )
	  {
	    print CODE "  return new ZincImage(tmp);\n";
	  }
	  else
	  {
	    print CODE "  return new ZincBitmap(tmp);\n";
	  }
	}
	elsif ( $T eq "INT" )
	{
	  print CODE "  int value;\n";
	  print CODE "  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),\n";
	  print CODE "              \"itemGet$t2 Failed : \");\n";
	  print CODE "  return ($t)value;\n";
	}
	elsif ( $T eq "DBL" )
	{
	  print CODE "  double value;\n";
	  print CODE "  z_tcl_call (Tcl_GetDoubleFromObj (interp, tmp, &value),\n";
	  print CODE "              \"itemGet$t2 Failed : \");\n";
	  print CODE "  return ($t)value;\n";
	}
	elsif ( $T eq "BOO" )
	{
	  print CODE "  int value;\n";
	  print CODE "  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),\n";
	  print CODE "              \"itemGet$t2 Failed : \");\n";
	  print CODE "  return ($t)value;\n";
	}
	else
	{
	  die("generationg error\n");
        }
	print CODE "}\n\n";

	$done .= "$2: $1\n";
  }
}

print "--- CONSTANTES\n";
print $res;
print "--- ENUMS.h\n";
print $enum;
print "--- ENUMS.c\n";
print $enum2;
print "--- FAIT\n";
print $done;
print "--- PAS FAIT\n";
print $undone;

Added jni/tkzinc/zinclib.d/makefile.vc.



















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

TCLTK_FULL_VER = 8.4.9
TCLTK_LIB_VER = 84
TKZINC_MAJOR = 3
TKZINC_MINOR = 3
TKZINC_PATCHLVL = 0

CC		= cl
LD		= link
CP		= copy
RM		= del
#
# The SDK lib path should be available in the
# environment variable %LIB%
libpath32	= /LIBPATH:"$(LIB)"
#
# The SDK include path should be available in the
# environment variable %INCLUDE%
include32	= /I"$(INCLUDE)" /I"C:\Program Files\Microsoft Platform SDK for Windows XP SP2\include\GL"

#
# Default location for ActiveTcl
prefix = c:\Tcl
exec_prefix = $(prefix)

bindir = $(exec_prefix)\bin
libdir = $(exec_prefix)\lib
incdir = $(prefix)\include
mandir = $(prefix)\man\man3

rootdir = .
srcdir = $(rootdir)\src
testdir = $(rootdir)\test
tmpdir = $(rootdir)\tmp

INCLUDES    = /I"$(incdir)" /I$(srcdir) $(include32)

# Assume that WISH is already INSTALLED
TCLSH		= $(bindir)\tclsh$(TCLTK_LIB_VER)
WISH		= $(bindir)\wish$(TCLTK_LIB_VER)
WIN_LIBS	= user32.lib gdi32.lib ws2_32.lib
GL_LIBS		= glu32.lib opengl32.lib
TK_LIBS		= $(libdir)\tcl$(TCLTK_LIB_VER).lib \
		  $(libdir)\tk$(TCLTK_LIB_VER).lib \
      $(libdir)\Tkzinc$(TKZINC_MAJOR).$(TKZINC_MINOR).$(TKZINC_PATCHLVL)\Tkzinc$(TKZINC_MAJOR)$(TKZINC_MINOR)$(TKZINC_PATCHLVL).lib
LIBS = $(WIN_LIBS) $(GL_LIBS) $(TK_LIBS) $(tmpdir)/zinclib.lib

VERSION = \"$(TKZINC_MAJOR).$(TKZINC_MINOR).$(TKZINC_PATCHLVL)\"

CDEBUG = /Z7 -Od
CFLAGS = /c /W3 /nologo /YX $(CDEBUG)
CPPFLAGS = /Fp$(tmpdir)\ $(INCLUDES) /DBUILD_zinclib

LFLAGS	= /nologo /machine:IX86 $(libpath32) /FORCE:MULTIPLE /NODEFAULTLIB:uuid.lib /NODEFAULTLIB:OLDNAMES.lib

OBJS = $(tmpdir)\ZincObjects.obj $(tmpdir)\ZincPath.obj $(tmpdir)\Zinc.obj

$(tmpdir)\zinclib.lib: $(tmpdir) $(OBJS)
  lib /OUT:$@ $(OBJS)

$(tmpdir):
  mkdir $(tmpdir)

{$(srcdir)}.cpp{$(tmpdir)}.obj:
	$(CC) $(CPPFLAGS) $(CFLAGS) -Fo$(tmpdir)\ $<

demos: $(testdir)/items.exe $(testdir)/widget.exe $(testdir)/test.exe $(testdir)/itemconf.exe

$(testdir)/items.exe: $(tmpdir)/items.obj $(tmpdir)\zinclib.lib
	$(LD) $(LFLAGS) $(LIBS) /OUT:$@ $**

$(testdir)/widget.exe: $(tmpdir)/widget.obj $(tmpdir)\zinclib.lib
	$(LD) $(LFLAGS) $(LIBS) /OUT:$@ $**

$(testdir)/test.exe: $(tmpdir)/test.obj $(tmpdir)\zinclib.lib
	$(LD) $(LFLAGS) $(LIBS) /OUT:$@ $**

$(testdir)/itemconf.exe: $(tmpdir)/itemconf.obj $(tmpdir)\zinclib.lib
	$(LD) $(LFLAGS) $(LIBS) /OUT:$@ $**


{$(testdir)}.cpp{$(tmpdir)}.obj:
	$(CC) $(CPPFLAGS) $(CFLAGS) -Fo$(tmpdir)\ $<

mostlyclean:
	$(RM) *.bak *~ $(tmpdir)\*.obj
clean:
	$(RM) $(tmpdir)\*.obj $(tmpdir)\*.dll $(tmpdir)\*.lib $(tmpdir)\*.exp $(tmpdir)\*.pch

Added jni/tkzinc/zinclib.d/src/Zinc.cpp.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
/**       Zinc.cpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *   Here is the definition of the Zinc object
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *           David Thevenin <thevenin@intuilab.com>
 *
 */
#include "Zinc.hpp"
#include "ZincInternal.hpp"
#include <iostream>
#include <sstream>
#include <tk.h>

/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL (1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

//predeclare private function
#ifdef _WIN32
int __cdecl tclCallback (ClientData client_data, Tcl_Interp *interp,
                  int argc, Tcl_Obj *CONST args[]);
#else
int tclCallback (ClientData client_data, Tcl_Interp *interp,
                  int argc, Tcl_Obj *CONST args[]) __attribute__((cdecl));
#endif

/*******************************************************
                     ZINC OBJECT
*******************************************************/


int Zinc::znCount = 0;               ///< count to create unique ids
Tcl_Interp *Zinc::interp;            ///< the tcl interpreter
Tcl_CmdInfo Zinc::topCmdInfo;       ///< the command associated with toplevel
Tcl_CmdInfo Zinc::zncCmdInfo;       ///< the command associated with zinc
Tcl_CmdInfo Zinc::imgCmdInfo;       ///< the command associated with image
Tcl_CmdInfo Zinc::fntCmdInfo;       ///< the command associated with font
Tcl_CmdInfo Zinc::focCmdInfo;       ///< the command associated with focus
Tcl_CmdInfo Zinc::bndCmdInfo;       ///< the command associated with bind
Tcl_Obj* Zinc::pool[ZINC_POOL_COUNT];///<  a pool of tclobj ready to be used
Tcl_Obj* Zinc::p1[ZINC_PARAM_COUNT]; ///<  a table of pointeurs use for parameters
Tcl_Obj* Zinc::p2[ZINC_PARAM_COUNT]; ///<  a table of pointeurs use for parameters

static Tcl_Obj *DEFAULT_GROUP_OBJ = Tcl_NewIntObj (DEFAULT_GROUP);

//option constants
//Tcl_Obj* Z_render = Tcl_NewStringObj ("-render", -1);
Z_DEFINE_ZOPT (render);             ///< the "-render" option
Z_DEFINE_ZOPT (firstend);           ///< the "-firstend" option
Z_DEFINE_ZOPT (lastend);            ///< the "-lastend" option
Z_DEFINE_ZOPT (position);           ///< the "-position" option
Z_DEFINE_ZOPT (tags);               ///< the "-tags" option
Z_DEFINE_ZOPT (backcolor);          ///< the "-backcolor" option
Z_DEFINE_ZOPT (forecolor);          ///< the "-forecolor" option
Z_DEFINE_ZOPT (height);             ///< the "-height" option
Z_DEFINE_ZOPT (borderwidth);        ///< the "-borderwidth" option


//autogenerated constants
Z_DEFINE_ZOPT (closed);            ///< the "-closed" option
Z_DEFINE_ZOPT (composealpha);      ///< the "-composealpha" option
Z_DEFINE_ZOPT (composerotation);   ///< the "-composerotation" option
Z_DEFINE_ZOPT (composescale);      ///< the "-composescale" option
Z_DEFINE_ZOPT (extent);            ///< the "-extent" option
Z_DEFINE_ZOPT (fillcolor);         ///< the "-fillcolor" option
Z_DEFINE_ZOPT (filled);            ///< the "-filled" option
Z_DEFINE_ZOPT (fillpattern);       ///< the "-fillpattern" option
Z_DEFINE_ZOPT (linecolor);         ///< the "-linecolor" option
Z_DEFINE_ZOPT (linepattern);       ///< the "-linepattern" option
Z_DEFINE_ZOPT (linestyle);         ///< the "-linestyle" option
Z_DEFINE_ZOPT (linewidth);         ///< the "-linewidth" option
Z_DEFINE_ZOPT (pieslice);          ///< the "-pieslice" option
Z_DEFINE_ZOPT (priority);          ///< the "-priority" option
Z_DEFINE_ZOPT (sensitive);         ///< the "-sensitive" option
Z_DEFINE_ZOPT (startangle);        ///< the "-startangle" option
Z_DEFINE_ZOPT (tile);              ///< the "-tile" option
Z_DEFINE_ZOPT (visible);           ///< the "-visible" option
Z_DEFINE_ZOPT (capstyle);          ///< the "-capstyle" option
Z_DEFINE_ZOPT (fillrule);          ///< the "-fillrule" option
Z_DEFINE_ZOPT (joinstyle);         ///< the "-joinstyle" option
Z_DEFINE_ZOPT (marker);            ///< the "-marker" option
Z_DEFINE_ZOPT (markercolor);       ///< the "-markercolor" option
Z_DEFINE_ZOPT (relief);            ///< the "-relief" option
Z_DEFINE_ZOPT (smoothrelief);      ///< the "-smoothrelief" option
Z_DEFINE_ZOPT (alpha);             ///< the "-alpha" option
Z_DEFINE_ZOPT (atomic);            ///< the "-atomic" option
Z_DEFINE_ZOPT (clip);              ///< the "-clip" option
Z_DEFINE_ZOPT (anchor);            ///< the "-anchor" option
Z_DEFINE_ZOPT (color);             ///< the "-color" option
Z_DEFINE_ZOPT (connecteditem);     ///< the "-connecteditem" option
Z_DEFINE_ZOPT (connectionanchor);  ///< the "-connectionanchor" option
Z_DEFINE_ZOPT (image);             ///< the "-image" option
Z_DEFINE_ZOPT (mask);              ///< the "-mask" option
Z_DEFINE_ZOPT (alignment);         ///< the "-alignment" option
Z_DEFINE_ZOPT (font);              ///< the "-font" option
Z_DEFINE_ZOPT (overstriked);       ///< the "-overstriked" option
Z_DEFINE_ZOPT (spacing);           ///< the "-spacing" option
Z_DEFINE_ZOPT (text);              ///< the "-text" option
Z_DEFINE_ZOPT (underlined);        ///< the "-underlined" option
Z_DEFINE_ZOPT (width);             ///< the "-width" option

//other constants
Z_DEFINE_ZFCT (device);            ///< the "device" keyword

///< function constants
Z_DEFINE_ZFCT (add);           ///< the "add" function
Z_DEFINE_ZFCT (addtag);        ///< the "addtag" function
Z_DEFINE_ZFCT (bind);          ///< the "bind" function
Z_DEFINE_ZFCT (bbox);          ///< the "bbox" function
Z_DEFINE_ZFCT (cget);          ///< the "cget" function
Z_DEFINE_ZFCT (chggroup);      ///< the "chggroup" function
Z_DEFINE_ZFCT (clone);         ///< the "clone" function
Z_DEFINE_ZFCT (configure);     ///< the "configure" function
Z_DEFINE_ZFCT (contour);       ///< the "contour" function
Z_DEFINE_ZFCT (coords);        ///< the "coords" function
Z_DEFINE_ZFCT (dtag);          ///< the "dtag" function
Z_DEFINE_ZFCT (focus);         ///< the "focus" function
Z_DEFINE_ZFCT (gettags);       ///< the "gettags" function
Z_DEFINE_ZFCT (gname);         ///< the "gname" function
Z_DEFINE_ZFCT (group);         ///< the "group" function
Z_DEFINE_ZFCT (itemconfigure); ///< the "itemconfigure" function
Z_DEFINE_ZFCT (itemcget);      ///< the "itemcget" function
Z_DEFINE_ZFCT (lower);         ///< the "lower" function
Z_DEFINE_ZFCT (raise);         ///< the "raise" function
Z_DEFINE_ZFCT (remove);        ///< the "remove" function
Z_DEFINE_ZFCT (rotate);        ///< the "rotate" function
Z_DEFINE_ZFCT (scale);         ///< the "scale" function
Z_DEFINE_ZFCT (skew);          ///< the "skew" function
Z_DEFINE_ZFCT (tget);          ///< the "tget" function
Z_DEFINE_ZFCT (translate);     ///< the "translate" function
Z_DEFINE_ZFCT (transform);     ///< the "transform" function
Z_DEFINE_ZFCT (treset);        ///< the "treset" function
Z_DEFINE_ZFCT (tset);          ///< the "tset" function
Z_DEFINE_ZFCT (type);          ///< the "type" function

//Item constants
Z_DEFINE_ZITM (add);           ///< the "add" constant
Z_DEFINE_ZITM (arc);           ///< the "arc" constant
Z_DEFINE_ZITM (curve);         ///< the "curve" constant
Z_DEFINE_ZITM (icon);          ///< the "icon" constant
Z_DEFINE_ZITM (group);         ///< the "group" constant
Z_DEFINE_ZITM (rectangle);     ///< the "rectangle" constant
Z_DEFINE_ZITM (text);          ///< the "text" constant
Z_DEFINE_ZITM (withtag);       ///< the "withtag" constant

/*********************************************
           Prepare enum Tcl_Obj
*********************************************/

//lineStyles strings
const char* lineStylesStrings [] =
{ "simple", "dashed", "mixed", "dotted" };
//lineStyles Tcl_Obj
Tcl_Obj* lineStyles [] =
{
  Tcl_NewStringObj ("simple", -1),
  Tcl_NewStringObj ("dashed", -1),
  Tcl_NewStringObj ("mixed", -1),
  Tcl_NewStringObj ("dotted", -1),
};

//capStyles strings
const char* capStylesStrings [] =
{ "butt", "projecting", "round" };
//capStyles Tcl_Obj
Tcl_Obj* capStyles [] =
{
  Tcl_NewStringObj ("butt", -1),
  Tcl_NewStringObj ("projecting", -1),
  Tcl_NewStringObj ("round", -1),
};

// fillRules strings
const char* fillRulesStrings [] =
{ "odd", "nonzero", "positive", "negative", "abs_geq_2" };
//fillRules Tcl_Obj
Tcl_Obj* fillRules [] =
{
  Tcl_NewStringObj ("odd", -1),
  Tcl_NewStringObj ("nonzero", -1),
  Tcl_NewStringObj ("positive", -1),
  Tcl_NewStringObj ("negative", -1),
  Tcl_NewStringObj ("abs_geq_2", -1),
};

// joinStyle strings
const char* joinStylesStrings [] =
{ "bevel", "miter", "round" };
// joinStyles Tcl_Obj
Tcl_Obj* joinStyles [] =
{
  Tcl_NewStringObj ("bevel", -1),
  Tcl_NewStringObj ("miter", -1),
  Tcl_NewStringObj ("round", -1),
};

// reliefs strings
const char* reliefsStrings [] =
{ "flat", "raised", "sunken", "ridge", "groove", "roundraised",
  "roundsunken", "roundridge", "roundgroove", "raisedrule", "sunkenrule" };
// reliefs Tcl_Obj
Tcl_Obj* reliefs [] =
{
  Tcl_NewStringObj ("flat", -1),
  Tcl_NewStringObj ("raised", -1),
  Tcl_NewStringObj ("sunken", -1),
  Tcl_NewStringObj ("ridge", -1),
  Tcl_NewStringObj ("groove", -1),
  Tcl_NewStringObj ("roundraised", -1),
  Tcl_NewStringObj ("roundsunken", -1),
  Tcl_NewStringObj ("roundridge", -1),
  Tcl_NewStringObj ("roundgroove", -1),
  Tcl_NewStringObj ("raisedrule", -1),
  Tcl_NewStringObj ("sunkenrule", -1),
};

// alignments strings
const char* alignmentsStrings [] =
{ "left", "right", "center" };
// alignments Tcl_obj
Tcl_Obj* alignments [] =
{
  Tcl_NewStringObj ("left", -1),
  Tcl_NewStringObj ("right", -1),
  Tcl_NewStringObj ("center", -1),
};

// anchors strings
const char* anchorsStrings [] =
{ "nw", "n", "ne", "e", "se", "s", "sw", "w", "center" };
// anchors Tcl_Obj
Tcl_Obj* anchors [] =
{
  Tcl_NewStringObj ("nw", -1),
  Tcl_NewStringObj ("n", -1),
  Tcl_NewStringObj ("ne", -1),
  Tcl_NewStringObj ("e", -1),
  Tcl_NewStringObj ("se", -1),
  Tcl_NewStringObj ("s", -1),
  Tcl_NewStringObj ("sw", -1),
  Tcl_NewStringObj ("w", -1),
  Tcl_NewStringObj ("center", -1),
};

// itemType strings
const char* itemTypeStrings [] =
{
  "group",
  "arc",
  "text",
  "rectangle",
  "curve",
  "icon",
  NULL
};
//no need for Tcl_Objs because they are only used as return values


/**********************************
         Zinc Object
**********************************/

/**
 * The public constructor
   *
   * @param renderingMode ZINC_BACKEND_X11 or ZINC_BACKEND_OPENGL
 */
Zinc::Zinc (int renderingMode)
{
  String theId;

  //preparating id (.zn and a unique number)
  znCount++;
  theId = ".zn";
  theId += itos(znCount);
  window = ".";

  //create a new window for each other widget
  if (znCount != 1)
  {
    window  = ".zwin";
    window += itos (znCount);

    //create a new toplevel window
    const char* para[2];
    para[0] = "toplevel";
    para[1] = window.c_str();
    //call the toplevel Tk function with 2 arguments
    z_tcl_call ((*topCmdInfo.proc)(topCmdInfo.clientData, interp, 2, para),
                "toplevel Failed : ");

    //adapt the zinc id to the window path
    theId = window + theId;
  }

  //  String noResizeCommand = String ("wm resizable ") + window + " 0 0";
  //Tcl_Eval (interp, noResizeCommand.c_str ());

  //use a tcl_obj for the id
  id = Tcl_NewStringObj (theId.c_str (), theId.length ());
  Tcl_IncrRefCount (id);

  //get top windows for zinc widget
  Tk_Window top_w = Tk_MainWindow (interp);

  //creation of the zinc item
  //  call  "Zinc id -render mode
  Tcl_ResetResult (interp);
  p1[0] = NULL;
  p1[1] = id;
  p1[2] = ZOPT_render;
  p1[3] = Z_INT_POOL (0, renderingMode);
  // call the function with 4 arguments and check non error
  z_tcl_call ((*zncCmdInfo.objProc) (ClientData (top_w), interp, 4, p1),
               "ZincObjCmd failed :");

  // get back ZnWInfo *wi and WidgetObjCmd
  Tcl_CmdInfo cmdInfo;
  int result = Tcl_GetCommandInfo (interp, theId.c_str (), &cmdInfo);
  if (!result)
  {
    throw ZincException (String ("zinclib: Tcl command not found") +
                         Tcl_GetStringResult (interp), __FILE__, __LINE__);
  }

  //get informations necessary to call WidgetObjCmd
  wi = cmdInfo.objClientData;
  objCmd = (WidgetObjCmd)cmdInfo.objProc;

  //call the Tk function pack
  String packCmd = String ("pack ") + theId + " -expand 1 -fill both";
  Tcl_Eval (interp, packCmd.c_str ());

  // Prepare for binding with callback (create a Tcl function)
  tclCb = String (Z_TCLCB) + itos(znCount);
  Tcl_CreateObjCommand(interp, tclCb.c_str (), tclCallback,
                       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);

  //give focus to the window
  const char* para[2];
  para[0] = "focus";
  para[1] = theId.c_str();
  // call the function with 4 arguments
  z_tcl_call ((*focCmdInfo.proc)(focCmdInfo.clientData, interp, 2, para),
              "focus Failed : ");
}

/**
 * The public destructor
 */
Zinc::~Zinc ()
{
  //delete the Tcl function
  Tcl_DeleteCommand (interp, tclCb.c_str ());
  // delete the tcl_obj
  Tcl_DecrRefCount (id);
}

/**
 * Change window title
 *
 * @param title the title string
 */
void Zinc::setTitle (String title)
{
  //use tcl interpreter directly since this won't be called often
  String command = String ("wm title ") + window + " \"" + title + "\"";
  Tcl_Eval (interp, command.c_str ());
}

/*****************************************
          WIDGET PROPERTIES
*****************************************/
/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

/**
 * Call zinc->configure ( -backcolor )
 *
 * @param value the backcolor to set
 */
void Zinc::setBackcolor (String value)
{
  //call .zinc configure -backcolor value
  p1[0] = id;
  p1[1] = ZFCT_configure;
  p1[2] = ZOPT_backcolor;
  p1[3] = Z_STR_POOL (0, value.c_str(), value.length());
  // call the function with 4 arguments
  z_command (4, "setBackcolor Failed : ");
}

/**
 * Call zinc->cget ( -backcolor )
 *
 * @return backcolor value
 */
String Zinc::getBackcolor ()
{
  Tcl_Obj* tmp;
  //discard old results
  Tcl_ResetResult (interp);
  //call .zinc cget -backcolor
  p1[0] = id;
  p1[1] = ZFCT_cget;
  p1[2] = ZOPT_backcolor;
  // call the function with 3 arguments
  z_command (3, "getBackcolor Failed : ");

  //retreive the result as a string
  tmp = Tcl_GetObjResult (interp);
  return String (Tcl_GetStringFromObj (tmp, NULL));
}

/**
 * Call zinc->configure ( -forecolor )
 *
 * @param value the forecolor to set
 */
void Zinc::setForecolor (String value)
{
  //call .zinc configure -forecolor value
  p1[0] = id;
  p1[1] = ZFCT_configure;
  p1[2] = ZOPT_forecolor;
  p1[3] = Z_STR_POOL (0, value.c_str(), value.length());
  // call the function with 4 arguments
  z_command (4, "setForecolor Failed : ");
}

/**
 * Call zinc->cget ( -forecolor )
 *
 * @return forecolor value
 */
String Zinc::getForecolor ()
{
  Tcl_Obj* tmp;
  //discard old results
  Tcl_ResetResult (interp);
  //call .zinc cget -forecolor
  p1[0] = id;
  p1[1] = ZFCT_cget;
  p1[2] = ZOPT_forecolor;
  // call the function with 3 arguments
  z_command (3, "getForecolor Failed : ");

  //retreive the result as a string
  tmp = Tcl_GetObjResult (interp);
  return String (Tcl_GetStringFromObj (tmp, NULL));
}

/**
 * Call zinc->configure ( -width )
 *
 * @param value the width to set
 */
void Zinc::setWidth (int value)
{
  //call .zinc configure -width value
  p1[0] = id;
  p1[1] = ZFCT_configure;
  p1[2] = ZOPT_width;
  p1[3] = Z_INT_POOL (0, value);
  // call the function with 4 arguments
  z_command (4, "setWidth Failed : ");

  char *strid = Tcl_GetString(id);
  //call the Tk function pack
  String packCmd = String ("pack ") + strid + " -expand 1 -fill both";
  Tcl_Eval (interp, packCmd.c_str ());
}

/**
 * Call zinc->cget ( -width )
 *
 * @return width value
 */
int Zinc::getWidth ()
{
  Tcl_Obj* tmp;
  //discard old results
  Tcl_ResetResult (interp);
  //call .zinc cget -width
  p1[0] = id;
  p1[1] = ZFCT_cget;
  p1[2] = ZOPT_width;
  // call the function with 3 arguments
  z_command (3, "getWidth Failed : ");

  //retreive the result as an integer
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "getWidth Failed : ");
  return value;
}

/**
 * Call zinc->configure ( -height )
 *
 * @param value the height to set
 */
void Zinc::setHeight (int value)
{
  //call .zinc configure -height value
  p1[0] = id;
  p1[1] = ZFCT_configure;
  p1[2] = ZOPT_height;
  p1[3] = Z_INT_POOL (0, value);
  // call the function with 4 arguments
  z_command (4, "setHeight Failed : ");

  char *strid = Tcl_GetString(id);
  //call the Tk function pack
  String packCmd = String ("pack ") + strid + " -expand 1 -fill both";
  Tcl_Eval (interp, packCmd.c_str ());
}

/**
 * Call zinc->cget ( -height )
 *
 * @return height value
 */
int Zinc::getHeight ()
{
  Tcl_Obj* tmp;
  //discard old results
  Tcl_ResetResult (interp);
  //call .zinc cget -height
  p1[0] = id;
  p1[1] = ZFCT_cget;
  p1[2] = ZOPT_height;
  // call the function with 3 arguments
  z_command (3, "getHeight Failed : ");

  //retreive the result as an integer
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "getHeight Failed : ");
  return value;
}

/**
 * Call zinc->configure ( -borderwidth )
 *
 * @param value the borderwidth to set
 */
void Zinc::setBorderwidth (int value)
{
  //call .zinc configure -borderwidth value
  p1[0] = id;
  p1[1] = ZFCT_configure;
  p1[2] = ZOPT_borderwidth;
  p1[3] = Z_INT_POOL (0, value);
  // call the function with 4 arguments
  z_command (4, "setBorderwidth Failed : ");
}

/**
 * Call zinc->cget ( -borderwidth )
 *
 * @return borderwidth value
 */
int Zinc::getBorderwidth ()
{
  Tcl_Obj* tmp;
  //discard old results
  Tcl_ResetResult (interp);
  //call .zinc cget -borderwidth
  p1[0] = id;
  p1[1] = ZFCT_cget;
  p1[2] = ZOPT_borderwidth;
  // call the function with 3 arguments
  z_command (3, "getBorderwidth Failed : ");

  //retreive the result as an integer
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "getBorderwidth Failed : ");
  return value;
}

/**
 * Call zinc->configure ( -font )
 *
 * @param value the font to set
 */
void Zinc::setFont (ZincFont* value)
{
  //call .zinc configure -font value
  p1[0] = id;
  p1[1] = ZFCT_configure;
  p1[2] = ZOPT_font;
  p1[3] = Z_STR_POOL (0, value->name.c_str(), value->name.length());
  // call the function with 4 arguments
  z_command (4, "setFont Failed : ");
}

/**
 * Call zinc->cget ( -font )
 *
 * @return font value
 */
ZincFont* Zinc::getFont ()
{
  //discard old results
  Tcl_ResetResult (interp);
  //call .zinc cget -font
  p1[0] = id;
  p1[1] = ZFCT_cget;
  p1[2] = ZOPT_font;
  // call the function with 3 arguments
  z_command (3, "getFont Failed : ");

  //retreive the result as a string
  return new ZincFont (Tcl_GetStringResult (interp));
}


/*****************************************
          WIDGET METHODS
*****************************************/
/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

/**
 * Get the bounding box of an item
 *
 * @param item the item to get bbox
 * @param bbox a table where we'll put the bounding box
 *             bbox[0] = x0, bbox[1] = y0, bbox[2] = xc, bbox[3] = yc
 */
void Zinc::bbox (ZincItem* item, double _bbox[4])
{
  Tcl_Obj* tmp;
  Tcl_Obj** list;
  int count;
  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc bbox item
  p1[0] = id;
  p1[1] = ZFCT_bbox;
  p1[2] = item->object;

  // call the function with 3 arguments
  z_command (3, "bbox Failed : ");

  //retreive the result as a list
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_ListObjGetElements (interp, tmp, &count, &list),
              "bbox Failed : ");
  //extract 4 double from the list
  if (count != 4)
  {
    throw  ZincException (String ("bbox Failed count=") + itos(count),
                          __FILE__, __LINE__);
  }
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[0], &_bbox[0]),
              "bbox Failed");
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[1], &_bbox[1]),
              "bbox Failed");
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[2], &_bbox[2]),
              "bbox Failed");
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[3], &_bbox[3]),
              "bbox Failed");
}


/**
 * Get the bounding box of an item in its parent group
 *
 * @param item the item to get bbox in its parent group
 * @param bbox a table where we'll put the bounding box
 *             bbox[0] = x0, bbox[1] = y0, bbox[2] = xc, bbox[3] = yc
 */
void Zinc::relativeBbox (ZincItem* item, double _bbox[4])
{
  //1) get bounding bbox
  double tempBbox[4];
  this->bbox (item, tempBbox);
  
  //2) call transform
  Tcl_Obj* tmp;
  Tcl_Obj** list;
  int count;
  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc transform device parentGroup {_bbox[0] _bbox[1] _bbox[2] _bbox[3]}
  p1[0] = id;
  p1[1] = ZFCT_transform;
  p1[2] = ZFCT_device;
  p1[3] = item->object;

  //coordinates as a list
  p2[0] = Z_DBL_POOL (0, tempBbox[0]);
  p2[1] = Z_DBL_POOL (1, tempBbox[1]);
  p2[2] = Z_DBL_POOL (2, tempBbox[2]);
  p2[3] = Z_DBL_POOL (3, tempBbox[3]);
  p1[4] = Z_LST_POOL (4, p2, 4);

  // call the function with 5 arguments
  z_command (5, "relativeBbox z_command Failed : ");
  //free the list in pool No 4
  Z_CLEANLIST (4);

  //retreive the result as a list
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_ListObjGetElements (interp, tmp, &count, &list),
              "relativeBbox z_tcl_call Failed : ");

  //3) extract 4 double from the list
  if (count != 4)
  {
    throw  ZincException (String ("relativeBbox Failed count=") + itos(count),
                          __FILE__, __LINE__);
  }
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[0], &_bbox[0]),
              "relativeBbox Failed");
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[1], &_bbox[1]),
              "relativeBbox Failed");
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[2], &_bbox[2]),
              "relativeBbox Failed");
  z_tcl_call (Tcl_GetDoubleFromObj (interp, list[3], &_bbox[3]),
              "bbox Failed");
}




/**
 * Change the group of an item
 *
 * @param item the item to move
 * @param parentGroup new group for the item
 */
void Zinc::chggroup (ZincItem *item, ZincItem *parentGroup)
{
  // call .zinc chggroup item parentGroup
  p1[0] = id;
  p1[1] = ZFCT_chggroup;
  p1[2] = item->object;
  p1[3] = Z_PARENTGROUP (parentGroup);
  // call the function with 4 arguments
  z_command (4, "chggroup Failed : ");
}

/**
 * Clone an item
 *
 * @param item the item to clone
 * @return the cloned item
 */
ZincItem* Zinc::clone (ZincItem *item)
{
  // call .zinc clone item
  p1[0] = id;
  p1[1] = ZFCT_clone;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "clone Failed: ");

  //retreive the result as a tcl_obj
  return new ZincItem (Tcl_GetObjResult (interp));
}

/**
 * Get the number of contour of an item
 *
 * @return number of contour
 */
int Zinc::contour (ZincItem *item)
{
  Tcl_Obj* tmp;
  int result;
  // call .zinc contour item
  p1[0] = id;
  p1[1] = ZFCT_contour;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "contour Failed: ");

  //retreive the result as an int
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &result),
              "contour Failed: ");
  return result;
}

/**
 * Set the contour of an item to the one of an other
 *
 * @param item the item on which we set the contour
 * @param flag the operation to do on the contour
 * @param reference the item to set contour from
 * @return the number of contour
 */
int Zinc::contour (ZincItem *item, itemOperator flag, ZincItem *reference)
{
  Tcl_Obj* tmp;
  int result;
  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc contour item flag reference
  p1[0] = id;
  p1[1] = ZFCT_contour;
  p1[2] = item->object;

  //different possible actions depending on the flag
  switch (flag)
  {
  case item_add_clockwise:
    p1[3] = ZFCT_add;
    p1[4] = Z_INT_POOL (0, -1); //add clockwise (-1)
    break;
  case item_add_counterclockwise:
    p1[3] = ZFCT_add;
    p1[4] = Z_INT_POOL (0, 1); //add counterclockwise (1)
    break;
  default:
    p1[3] = ZFCT_remove;
    p1[4] = Z_INT_POOL (0, 0); //no meaning (0)
  }
  // contour index (0)
  p1[5] = Z_INT_POOL (1, 0);
  // item reference
  p1[6] = reference->object;

  // call the function with 7 arguments
  z_command (7, "contour Failed: ");

  // retreive the result as an int
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &result),
              "contour Failed: ");
  return result;
}

/**
 * Set the contour of an item
 *
 * @param item the item on which we set the contour
 * @param add true to add a path, false to remove
 * @param reference the new contour
 * @return the number of contour
 */
int Zinc::contour (ZincItem *item, bool add, ZincPath *_contour)
{
  Tcl_Obj* tmp;
  int result;
  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc contour item flag contour
  p1[0] = id;
  p1[1] = ZFCT_contour;
  p1[2] = item->object;

  //different possible actions depending on the add flag
  if (add)
  {
    p1[3] = ZFCT_add;
    p1[4] = Z_INT_POOL (0, 0); //add contour (0)
  }
  else
  {
    p1[3] = ZFCT_remove;
    p1[4] = Z_INT_POOL (0, 0); //no meaning (0)
  }
  // contour index
  p1[5] = Z_INT_POOL (1, 0);
  //contour
  p1[6] = _contour->getTable ();

  // call the function with 7 arguments
  z_command (7, "contour Failed: ");

  // retreive the result as an integer
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &result),
              "contour Failed: ");
  return result;
}

/**
 * Set or modify the coordinates of an item
 *
 * @param item the item to modify
 * @param contour new coords for the item
 * @param add true to add coords, false to replace
 * @param contourIndex the contour do modify
 * @param coordIndex the coordinate to modify (WARNING, path must be one
 *                   point if the is not the default)
 */
void Zinc::coords (ZincItem *item, ZincPath *_contour, bool add,
                   int contourIndex, int coordIndex)
{
  int i;
  // call .zinc contour item ?flag? ?contourIndex? ?coordIndex? _contour
  p1[0] = id;
  p1[1] = ZFCT_coords;
  p1[2] = item->object;

  // use i as a variable index for parameters
  i = 3; // last parameter is p1[2]
  // do we add or not
  if (add)
  {
    p1[i++] = ZFCT_add;
  }

  //ith there a contour
  if (contourIndex != -1)
  {
    p1[i++] = Z_INT_POOL (1, contourIndex);

    //is there a coord index
    if (coordIndex != -1)
    {
      p1[i++] = Z_INT_POOL (1, coordIndex);
    }
  }

  p1[i++] = _contour->getTable ();

  // call the function with i arguments
  z_command (i, "coords Failed: ");
}

/**
 * Remove coords of an item
 *
 * @param item the item to modify
 * @param coordIndex the coordinate to rmove
 * @param contourIndex the contour on which we remove
 */
void Zinc::coordsRemove (ZincItem *item, int coordIndex, int contourIndex)
{
  int i;
  // call .zinc coords item remove ?contourIndex?
  p1[0] = id;
  p1[1] = ZFCT_coords;
  p1[2] = item->object;
  p1[3] = ZFCT_remove;

  i = 4;
  // is there a contourIndex
  if (contourIndex != -1)
  {
    p1[i++] = Z_INT_POOL (1, contourIndex);
  }
  p1[i++] = Z_INT_POOL (1, coordIndex);

  // call the function with i arguments
  z_command (i, "coordsRemove Failed: ");
}

/**
 * Add a tag to an item
 *
 * @param item the item to add tag to
 * @param tag a tag to add
 */
void Zinc::addTag (ZincItem *item, String tag)
{
  // call .zinc addtag tag withtag
  p1[0] = id;
  p1[1] = ZFCT_addtag;
  p1[2] = Z_STR_POOL (0, tag.c_str (), tag.length ());
  p1[3] = ZITM_withtag;
  p1[4] = item->object;
  // call the function with 5 arguments
  z_command (5, "addTag Failed: ");
}

/**
 * Remove a tag from an item
 *
 * @param item the item to remove tag from
 * @param tag a tag to remove
 */  
void Zinc::dTag (ZincItem *item, String tag)
{
  // call .zinc dtag item tag
  p1[0] = id;
  p1[1] = ZFCT_dtag;
  p1[2] = item->object;

  int i = 3;
  //create a tg if nexessary
  if (tag != "")
  {
    p1[i++] = Z_STR_POOL (0, tag.c_str (), tag.length ());
  }

  // call the function with i arguments
  z_command (i, "dTag Failed: ");
}

/**
 * List all tags of an item
 * It's up to the caller to delete the resulting table
 *
 * @param item the item to list tag from
 * @param lagList a pointer to a table of String containing tags
 * @return the number of tags
 */
int Zinc::getTags (ZincItem *item, String*** tagList)
{
  Tcl_Obj* tmp;
  Tcl_Obj** list;
  int count;

  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc gettags item  
  p1[0] = id;
  p1[1] = ZFCT_gettags;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "getTags Failed : ");

  //retreive the result as a list
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_ListObjGetElements (interp, tmp, &count, &list),
              "bbox Failed : ");

  // put strings into a new table 
  char *str;
  //store the table into tagList
  (*tagList) = new String* [count];

  // fill the table
  for (int i (0) ; i < count ; i++)
  {
    str = Tcl_GetString (list[i]);
    (*tagList)[i] = new String (str);
  }
  return count;
}

/**
 * Set the focus to an item
 *
 * @param item the item to set the focus to
 */
void Zinc::focus (ZincItem *item)
{
  // .zinc focus item
  p1[0] = id;
  p1[1] = ZFCT_focus;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "focus Failed: ");
}

/**
 * Tell if the name is a gradient name
 *
 * @param gname a gradient name
 * @return true if the name is a gradient name, false otherwise
 */
bool Zinc::isGname (String _gname)
{
  Tcl_Obj* tmp;
  int result;
  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc gname _gname
  p1[0] = id;
  p1[1] = ZFCT_gname;
  p1[2] = Z_STR_POOL (0, _gname.c_str (), _gname.length ());
  // call the function with 3 arguments
  z_command (3, "isGname Failed: ");

  //retreive the result as a boolean
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &result),
              "isGname Failed: ");
  return bool (result);
}

/**
 * Create a named gradient
 *
 * @param gradient a gradient
 * @param gname a gradient name
 */
void Zinc::gname (String gradient, String _gname)
{
  // call .zinc gname gradient gname
  p1[0] = id;
  p1[1] = ZFCT_gname;
  p1[2] = Z_STR_POOL (0, gradient.c_str (), gradient.length ());
  p1[3] = Z_STR_POOL (1, _gname.c_str (), _gname.length ());
  // call the function with 4 arguments
  z_command (4, "gname Failed: ");
}

/**
 * Retreive the group of an item
 *
 * @param item the item to get the group from
 * @return the group
 */
ZincItem* Zinc::group (ZincItem *item)
{
  Tcl_Obj* tmp;
  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc group item
  p1[0] = id;
  p1[1] = ZFCT_group;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "group Failed: ");

  //retreive the result as a tcl_obj
  tmp = Tcl_GetObjResult (interp);
  return new ZincItem (tmp);
}

/**
 * Reorder items to lower one
 *
 * @param item the item to lower
 */
void Zinc::lower (ZincItem *item)
{
  // call .zinc lower item
  p1[0] = id;
  p1[1] = ZFCT_lower;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "lower Failed: ");
}

/**
 * Reorder items to lower one
 *
 * @param item the item to lower
 * @param belowThis and item that will be over item
 */
void Zinc::lower (ZincItem *item, ZincItem *belowThis)
{
  // call .zinc lower item belowThis
  p1[0] = id;
  p1[1] = ZFCT_lower;
  p1[2] = item->object;
  p1[3] = belowThis->object;
  // call the function with 4 arguments
  z_command (4, "lower Failed: ");
}

/**
 * Reorder items to raise one
 *
 * @param item the item to raise
 */
void Zinc::raise (ZincItem *item)
{
  // call .zinc raise item
  p1[0] = id;
  p1[1] = ZFCT_raise;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "raise Failed: ");
}

/**
 * Reorder items to raise one
 *
 * @param item the item to raise
 * @param aboveThis an item that will be under item
 */
void Zinc::raise (ZincItem *item, ZincItem *aboveThis)
{
  // call .zinc raise item aboveThis
  p1[0] = id;
  p1[1] = ZFCT_raise;
  p1[2] = item->object;
  p1[3] = aboveThis->object;
  // call the function with 4 arguments
  z_command (4, "raise Failed: ");
}

/**
 * Return the type of an item
 *
 * @param item an item
 * @return the type of the item
 */
itemType Zinc::type (ZincItem *item)
{
  Tcl_Obj *tmp;
  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc type item
  p1[0] = id;
  p1[1] = ZFCT_type;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "type Failed: ");

  //retreive the result as a string
  tmp = Tcl_GetObjResult (interp);

  // convert the string to the right enum value
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   itemTypeStrings, 
                                   "itemType",
                                   0, &value),
              "type Failed : ");
  return itemType (value);
}

/**
 * Create a Zinc Tag that can be used in place of any item
 *  for zinc functions that must be called using tagOrId
 *
 * @param tag the text of the tag
 * @return a tag item
 */
ZincItem* Zinc::createTag(String tag)
{
  //just create an item
  return new ZincItem (Tcl_NewStringObj (tag.c_str (), tag.length ()));
}

/*******************************************************
                ITEM MANIPULATION
*******************************************************/
/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

/**
 * Suppress an item
 *
 * @param item the item to suppress
 */
void Zinc::itemRemove (ZincItem *item)
{
  //call .zinc remove item
  p1[0] = id;
  p1[1] = ZFCT_remove;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "itemRemove failed :");
}

/**
 * Create a group item
 *
 * @param parentGroup group where we'll put the new group, if NULL we create
 * in the defaults group
 * @return the group item
 */
ZincItem *Zinc::itemCreateGroup (ZincItem *parentGroup)
{
  //call .zinc add group parentGroup
  p1[0] = id;
  p1[1] = ZFCT_add;
  p1[2] = ZITM_group;
  p1[3] = Z_PARENTGROUP (parentGroup);
  // call the function with 4 arguments
  z_command (4, "itemCreateGroup failed :");

  return new ZincItem (Tcl_GetObjResult (interp));
}

/**
 * Create a rectangle item
 *
 * @param parentGroup group where we'll put it
 * @param x y width height the coordinates of the new rectangle
 * @return the rectangle item
 */
ZincItem* Zinc::itemCreateRectangle (ZincItem *parentGroup, double x, double y,
                                     double width, double height)
{
  //call .zinc add rectangle parentGroup {coords}
  p1[0] = id;
  p1[1] = ZFCT_add;
  p1[2] = ZITM_rectangle;
  p1[3] = Z_PARENTGROUP (parentGroup);
  //coordinates as a list
  p2[0] = Z_DBL_POOL (0, x);
  p2[1] = Z_DBL_POOL (1, y);
  p2[2] = Z_DBL_POOL (2, width + x);
  p2[3] = Z_DBL_POOL (3, height + y);
  p1[4] = Z_LST_POOL (4, p2, 4); // a list with 4 items
  // call the function with 4 arguments
  z_command (5, "itemCreateRectangle failed :");

  //clear the list in the pool No 4
  Z_CLEANLIST (4);
  
  return new ZincItem (Tcl_GetObjResult (interp));
}

/**
 * Create an arc item
 *
 * @param parentGroup group where we'll put it
 * @param x y width height the coordinates of the new rectangle
 * @return the arc item
 */
ZincItem *Zinc::itemCreateArc (ZincItem *parentGroup, double x, double y,
                               double width, double height)
{
  //call .zinc add arc parentGroup {coords}
  p1[0] = id;
  p1[1] = ZFCT_add;
  p1[2] = ZITM_arc;
  p1[3] = Z_PARENTGROUP (parentGroup);
  //coordinates as a list
  p2[0] = Z_DBL_POOL (0, x);
  p2[1] = Z_DBL_POOL (1, y);
  p2[2] = Z_DBL_POOL (2, width + x);
  p2[3] = Z_DBL_POOL (3, height + y);
  p1[4] = Z_LST_POOL (4, p2, 4);
  // call the function with 5 arguments
  z_command (5, "itemCreateArc failed :");

  //clear the list in the pool No 4 to reuse it later
  Z_CLEANLIST (4);

  return new ZincItem (Tcl_GetObjResult (interp));  
}

/**
 * Create a text item
 *
 * @param parentGroup group where we'll put it
 * @return the text item
 */
ZincItem *Zinc::itemCreateText (ZincItem *parentGroup)
{
  //call .zinc add text parentGroup
  p1[0] = id;
  p1[1] = ZFCT_add;
  p1[2] = ZITM_text;
  p1[3] = Z_PARENTGROUP (parentGroup);
  // call the function with 4 arguments
  z_command (4, "itemCreateText failed :");

  return new ZincItem (Tcl_GetObjResult (interp));
}

/**
 * Create a curve item
 *
 * @param parentGroup group where we'll put it
 * @param path the path to display
 * @return the curve item
 */
ZincItem *Zinc::itemCreateCurve (ZincItem *parentGroup, ZincPath *path)
{
  Tcl_Obj *table;
  table = path->getTable ();
  //call .zinc add curve parentGroup {path}
  p1[0] = id;
  p1[1] = ZFCT_add;
  p1[2] = ZITM_curve;
  p1[3] = Z_PARENTGROUP (parentGroup);
  p1[4] = table;
  // call the function with 5 arguments
  z_command (5, "itemCreateCurve failed :");
  return new ZincItem (Tcl_GetObjResult (interp));
}


/**
 * Create an icon item
 *
 * @param parentGroup group where we'll put it
 * @param image a zincImage to display
 * @return the icon item
 */
ZincItem *Zinc::itemCreateIcon (ZincItem *parentGroup, ZincImage* image)
{
  //call .zinc add icon parentGroup
  p1[0] = id;
  p1[1] = ZFCT_add;
  p1[2] = ZITM_icon;
  p1[3] = Z_PARENTGROUP (parentGroup);
  // call the function with 4 arguments
  z_command (4, "itemCreateIcon failed :");

  //retreive the result
  ZincItem *result = new ZincItem (Tcl_GetObjResult (interp));
  //to be able to set the image
  itemSetImage (result, image);
  
  return result;  
}

/**************************************************
           TRANSFORMATION METHODS
**************************************************/

/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

/**
 * Translate the item
 *
 * @param item the item to which we apply the transform
 * @param dx dy translation vector
 */
void Zinc::itemTranslate (ZincItem * item, double dx, double dy)
{
  // call .zinc translate item dx dy
  p1[0] = id;
  p1[1] = ZFCT_translate;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, dx);
  p1[4] = Z_DBL_POOL (1, dy);
  // call the function with 5 arguments
  z_command (5, "itemTranslateRelative Failed : ");
}

/**
 * Translate the item 
 *
 * @param item the item to which we apply the transform
 * @param x y translation vector
 * @param absolute true if the translation is absolute
 */
void Zinc::itemTranslate (ZincItem * item, double x, double y, bool absolute)
{
  // call .zinc translate item x y absolute
  p1[0] = id;
  p1[1] = ZFCT_translate;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, x);
  p1[4] = Z_DBL_POOL (1, y);
  p1[5] = Z_BOO_POOL (2, absolute);
  // call the function with 6 arguments
  z_command (6, "itemTranslateAbsolute Failed : ");
}

/**
 * Rotate an item
 *
 * @param item the item to which we apply the transform
 * @param angle the angle to rotate in radian
 */
void Zinc::itemRotate (ZincItem * item, double angle)
{
  // call .zinc rotate item angle
  p1[0] = id;
  p1[1] = ZFCT_rotate;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, angle);
  // call the function with 4 arguments
  z_command (4, "itemRotate (angle) Failed : ");
}

/**
 * Rotate an item
 *
 * @param item the item to which we apply the transform
 * @param angle the angle to rotate in radian
 * @param x y the center of the rotation
 */
void Zinc::itemRotate (ZincItem * item, double angle, double x, double y)
{
  // call .zinc rotate item angle x y
  p1[0] = id;
  p1[1] = ZFCT_rotate;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, angle);
  p1[4] = Z_DBL_POOL (1, x);
  p1[5] = Z_DBL_POOL (2, y);  
  // call the function with 6 arguments
  z_command (6, "itemRotateDegree (angle,center) Failed : ");
}

/**
 * Rotate an item
 *
 * @param item the item to which we apply the transform
 * @param angle the angle to rotate
 * @param degree true for an angle in degree, false for an angle in radians
 */
void Zinc::itemRotate (ZincItem * item, double angle, bool degree)
{
  // call .zinc rotate item angle degree
  p1[0] = id;
  p1[1] = ZFCT_rotate;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, angle);
  p1[4] = Z_BOO_POOL (1, degree);
  // call the function with 5 arguments
  z_command (5, "itemRotate (angle,degree) Failed : ");
}

/**
 * Rotate an item
 *
 * @param item the item to which we apply the transform
 * @param angle the angle to rotate in radian
 * @param x y the center of the rotation
 * @param degree true for an angle in degree, false for an angle in radians
 */
void Zinc::itemRotate (ZincItem * item, double angle, double x, double y,
                       bool degree)
{
  // call .zinc rotate item angle degree x y
  p1[0] = id;
  p1[1] = ZFCT_rotate;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, angle);
  p1[4] = Z_BOO_POOL (1, degree);
  p1[5] = Z_DBL_POOL (2, x);
  p1[6] = Z_DBL_POOL (3, y);  
  // call the function with 7 arguments
  z_command (7, "itemRotate (angle,center,degree) Failed : ");
}

/**
 * Scale an item
 *
 * @param item the item to which we apply the transform
 * @param ax horizontal scale
 * @param ay vertical scale
 */
void Zinc::itemScale (ZincItem * item, double ax, double ay)
{
  // call .zinc scale item ax ay
  p1[0] = id;
  p1[1] = ZFCT_scale;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, ax);
  p1[4] = Z_DBL_POOL (1, ay);
  // call the function with 5 arguments
  z_command (5, "itemScale Failed : ");
}

/**
 * Scale an item using a specified center
 *
 * @param item the item to which we apply the transform
 * @param ax horizontal scale
 * @param ay vertical scale
 * @param cx cy center of the scale
 */
void Zinc::itemScale (ZincItem * item, double ax, double ay, double cx, double cy)
{
  // call .zinc scale item ax ay cx cy
  p1[0] = id;
  p1[1] = ZFCT_scale;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, ax);
  p1[4] = Z_DBL_POOL (1, ay);
  p1[5] = Z_DBL_POOL (2, cx);
  p1[6] = Z_DBL_POOL (3, cy);
  // call the function with 7 arguments
  z_command (7, "itemScale (center) Failed : ");
}

/**
 * Skew an item
 *
 * @param item the item to which we apply the transform
 * @param sx horizontal skew
 * @param sy vertical skew
 */
void Zinc::itemSkew (ZincItem * item, double sx, double sy)
{
  // call .zinc skew item sx sy
  p1[0] = id;
  p1[1] = ZFCT_skew;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, sx);
  p1[4] = Z_DBL_POOL (1, sy);
  // call the function with 5 arguments
  z_command (5, "itemSkew Failed : ");
}

/**
 * Skew an item horizontaly
 *
 * @param item the item to which we apply the transform
 * @param sx horizontal skew
 */
void Zinc::itemSkewX (ZincItem * item, double sx)
{
  // call .zinc skew item sx 0
  p1[0] = id;
  p1[1] = ZFCT_skew;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, sx);
  p1[4] = Z_DBL_POOL (1, 0);
  // call the function with 5 arguments
  z_command (5, "itemSkewX Failed : ");
}

/**
 * Skew an item verticaly
 *
 * @param item the item to which we apply the transform
 * @param sy vertical skew
 */
void Zinc::itemSkewY (ZincItem * item, double sy)
{
  // call .zinc skew item 0 sy
  p1[0] = id;
  p1[1] = ZFCT_skew;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, 0);
  p1[4] = Z_DBL_POOL (1, sy);
  // call the function with 5 arguments
  z_command (5, "itemSkewY Failed : ");
}
  
/**
 * Reset all transformations associated with the item
 *
 * @param item the item to which we apply the transform
 */
void Zinc::itemResetTransformation (ZincItem * item)
{
  // call .zinc treset item
  p1[0] = id;
  p1[1] = ZFCT_treset;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "itemResetTransformation Failed : ");
}

/**
 * Replace current transform by a matrix
 *
 * @param item the item to which we apply the transform
 * @param a,b,c,d,e,f the new transform matrix 
 */
void Zinc::itemSetTransformation (ZincItem * item,
                                  double a, double b, double c,
                                  double d, double e, double f)
{
  // call .zinc tset item a b c d e f
  p1[0] = id;
  p1[1] = ZFCT_tset;
  p1[2] = item->object;
  p1[3] = Z_DBL_POOL (0, a);
  p1[4] = Z_DBL_POOL (1, b);
  p1[5] = Z_DBL_POOL (2, c);
  p1[6] = Z_DBL_POOL (3, d);
  p1[7] = Z_DBL_POOL (4, e);
  p1[8] = Z_DBL_POOL (5, f);
  // call the function with 9 arguments
  z_command (9, "itemSetTransformation Failed : ");  
}

/**
 * Get current transform matrix
 * @param item the item to which we apply the transform
 * @param a,b,c,d,e,f places where we'll put the transform matrix
 */
void Zinc::itemGetTransformation (ZincItem * item,
                                  double *a, double *b, double *c,
                                  double *d, double *e, double *f)
{
  // bug in zinc (or not?), it doesn't reset result for the tget function
  //  or apennd a result instead of replacing it
  Tcl_ResetResult (interp);
  // call .zinc tget item
  p1[0] = id;
  p1[1] = ZFCT_tget;
  p1[2] = item->object;
  // call the function with 3 arguments
  z_command (3, "itemGetTransformation Failed : ");

  //retreive the result as a list object
  Tcl_Obj* tmp = Tcl_GetObjResult (interp);
  int num;
  Tcl_Obj** elems;
  z_tcl_call (Tcl_ListObjGetElements (interp, tmp, &num, &elems),
              "itemGetTransformation Failed : ");

  //num is necessarily 6, extract 6 double
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[0], a),
              "itemGetTransformation Failed : ");
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[1], b),
              "itemGetTransformation Failed : ");
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[2], c),
              "itemGetTransformation Failed : ");
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[3], d),
              "itemGetTransformation Failed : ");
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[4], e),
              "itemGetTransformation Failed : ");
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[5], f),
              "itemGetTransformation Failed : ");  
}


/**
 * Multiply current transform by a matrix
 *
 * @param item the item to which we apply the transform
 * @param a,b,c,d,e,f  transform matrix 
 */
void Zinc::itemMatrix (ZincItem * item,
                       double a, double b, double c,
                       double d, double e, double f)
{
  double a0,b0,c0,d0,e0,f0;
  double a1,b1,c1,d1,e1,f1;
  // get current transform
  itemGetTransformation (item, &a0, &b0, &c0, &d0, &e0, &f0);

  //multiply
  a1 = a * a0 + d * b0;
  b1 = b * a0 + e * b0;
  c1 = c * a0 + f * b0 + c0;
  d1 = a * d0 + d * e0;
  e1 = b * d0 + e * e0;
  f1 = c * d0 + f * e0 + f0;

  // set to new transform
  itemSetTransformation (item, a1, b1, c1, d1, e1, f1);
}

/**************************************************
                    BINDING
**************************************************/

/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

//number of elements in the ZincEvent structure
#define EVENT_COUNT 10
//number of basic parameters to a widget callback
#define WIDGETCB_COUNT 3
//number of basic parameters to an item callback
#define ITEMCB_COUNT 4

//the equivalent of z_tcl_call able to be called in a callback
#define z_tcl_call2(fct,msg) \
  {                          \
    int result = (fct);      \
    if (result != TCL_OK)    \
    {                        \
      Tcl_AppendResult (Zinc::interp, msg, NULL); \
      return TCL_ERROR;      \
    }                        \
  }

/**
 * Real callback used by zinc TCL
 *
 * @param client_data the Zinc object
 * @param interp current interpreter
 * @param argc number of arguments
 * @param args table of arguments
 */
int tclCallback (ClientData client_data, Tcl_Interp *interp,
                  int argc, Tcl_Obj *CONST args[])
{
  Zinc *zinc = (Zinc*) client_data;
  int cb;
  ZincItem *item;
  void *userData;
  ZincEvent *ev;
  long value;
  
  //count arguments
  if ((argc != WIDGETCB_COUNT + EVENT_COUNT) && (argc != ITEMCB_COUNT + EVENT_COUNT))
  {
    Tcl_SetResult (Zinc::interp, "Zinclib: Invalid argument count in tclCallback", NULL);
    return TCL_ERROR;
  }
  // skip the bind name
  args++;

  // get the item if this is an item bind
  if (argc == ITEMCB_COUNT + EVENT_COUNT)
  {
    // retreive item
    z_tcl_call2 (Tcl_GetLongFromObj (interp, args[0], &value),
                 "Zinclib: No item in tclCallback");
    item = (ZincItem*) value;
    args++;
  }

  // retreive callback
  z_tcl_call2 (Tcl_GetLongFromObj (interp, args[0], &value),
               "Zinclib: No callback in tclCallback");
  cb = value;

  // retreive userdata
  args++;
  z_tcl_call2 (Tcl_GetLongFromObj (interp, args[0], &value),
               "Zinclib: No userData in tclCallback");
  userData = (void*) value;

  // point args to events values
  args++;
  //fill event structure with all avent values we support
  ev = new ZincEvent;
  // x position of the mouse
  if (Tcl_GetIntFromObj (interp, args[0], &(ev->x)) != TCL_OK)
  {
    ev->x = 0;
  }
  // y position of the mouse
  if (Tcl_GetIntFromObj (interp, args[1], &(ev->y)) != TCL_OK)
  {
    ev->y = 0;
  }
  // keycode
  if (Tcl_GetIntFromObj (interp, args[2], &(ev->k)) != TCL_OK)
  {
    ev->k = 0;
  }
  // timestamp
  if (Tcl_GetLongFromObj (interp, args[3], &(ev->t)) != TCL_OK)
  {
    ev->t = 0;
  }
  // keysyms
  ev->K = String (Tcl_GetString (args[4]));
  // window height
  if (Tcl_GetIntFromObj (interp, args[5], &(ev->h)) != TCL_OK)
  {
    ev->h = 0;
  }
  // window width
  if (Tcl_GetIntFromObj (interp, args[6], &(ev->w)) != TCL_OK)
  {
    ev->w = 0;
  }
  // x position of the mouse within display 
  if (Tcl_GetIntFromObj (interp, args[7], &(ev->X)) != TCL_OK)
  {
    ev->X = 0;
  }
  // y position of the mouse within display 
  if (Tcl_GetIntFromObj (interp, args[8], &(ev->Y)) != TCL_OK)
  {
    ev->Y = 0;
  }
  // button pressed
  if (Tcl_GetIntFromObj (interp, args[9], &(ev->b)) != TCL_OK)
  {
    ev->b = 0;
  }
  
  // Call the callback
  if (argc == ITEMCB_COUNT + EVENT_COUNT)
  {
    // this is a callback on an item
    ZincItemCallback itemCb = (ZincItemCallback)cb;
    (*itemCb) (zinc, item, ev, userData);
  }
  else
  {
    // this is a callback on the zinc widget
    ZincWidgetCallback zincCb = (ZincWidgetCallback)cb;
    (*zincCb) (zinc, ev, userData);
  }
  
  delete ev;
  return TCL_OK;
}

/**
 * Bind a function to an event on the zinc widget
 *
 * @param eventSpecification tcl style event specicication
 * @param callBack the function which will be called back
 * @param userData data we will give back to the callback when called
 * @param add false to replace existing bind or true to add
 */
void Zinc::bind (String eventSpecification,
                 ZincWidgetCallback callBack, void *userData, bool add)
{
  // call bind .zinc eventSpec script
  const char* para[4];
  para[0] = "bind";
  para[1] = window.c_str ();
  para[2] = eventSpecification.c_str ();

  //create callback script
  // this script is a call to the tclCallback function using all arguments we need
  String script;
  // do we add or replace the callback
  if (add)
  {
    script = String("+");
  }
  script += tclCb + " ";                 // name of the tcl function we created
  script += ltos ((long)callBack) + " "; // the real callback (as a pointer)
  script += ltos ((long)userData) + " "; // the user data (as a pointer)
  script += "%x %y %k %t %K %h %w %X %Y %b";// arguments for the event structure
  para[3] = script.c_str ();

  //call the command with 4 arguments
  z_tcl_call ((*bndCmdInfo.proc)(bndCmdInfo.clientData, interp, 4, para),
              "bind Failed : ");
}

/**
 * Annulate a binding
 *
 * @param eventSpecification tcl style event specicication
 */
void Zinc::unbind (String eventSpecification)
{
  // call bind .zinc eventSpec ""
  const char* para[4];;
  para[0] = "bind";
  para[1] = window.c_str ();
  para[2] = eventSpecification.c_str ();
  para[3] = "";

  //call the command with 4 arguments
  z_tcl_call ((*bndCmdInfo.proc)(bndCmdInfo.clientData, interp, 4, para),
              "unbind Failed : ");
}

/**
 * Bind a function to an event on an item
 *
 * @param item the item on which to bind
 * @param eventSpecification tcl style event specicication
 * @param callBack the function which will be called back
 * @param userData data we will give back to the callback when called
 */
void Zinc::itemBind (ZincItem *item, String eventSpec,
                     ZincItemCallback callBack, void *userData, bool add)
{
  // call .zinc bind item eventSpec script
  p1[0] = id;
  p1[1] = ZFCT_bind;
  p1[2] = item->object;
  p1[3] = Z_STR_POOL (0, eventSpec.c_str (), eventSpec.length ());

  //create callback script
  // this script is a call to the tclCallback function using all arguments we need
  String script;
  // do we add or replace the callback
  if (add)
  {
    script = String("+");
  }
  script += tclCb + " ";                 // name of the tcl function we created
  script += ltos ((long)item) + " ";     // the item (as a pointer)
  script += ltos ((long)callBack) + " "; // the real callback (as a pointer)
  script += ltos ((long)userData) + " "; // the user data (as a pointer)
  script += "%x %y %k %t %K %h %w %X %Y %b";  // arguments for the event structure
  p1[4] = Z_STR_POOL (1, script.c_str (), script.length ());

  // call the widget command with 5 arguments
  z_command (5, "itemBind Failed : ");
}

/**
 * Annulate a binding
 *
 * @param item the item on which to unbind
 * @param eventSpecification tcl style event specicication
 */
void Zinc::itemUnbind (ZincItem *item, String eventSpec)
{
  // call .zinc bind item eventSpec ""
  p1[0] = id;
  p1[1] = ZFCT_bind;
  p1[2] = item->object;
  p1[3] = Z_STR_POOL (0, eventSpec.c_str (), eventSpec.length ());
  p1[4] = Z_STR_POOL (1, "", -1);

  //call the command with 5 arguments
  z_command (5, "itemUnbind Failed : ");
}

/*******************************************************
                STATIC PROCEDURES
*******************************************************/

/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

/**
 * Loads the zinc library and initialize tcl and tk
 *
 * @param argv0 the name of the executable as passed in argv[0]
 */
void Zinc::loadZinc (char *argv0) throw (ZincException)
{
  //Initialise internal TCL structure
  Tcl_FindExecutable (argv0);
  //Create an interpreter
  interp = Tcl_CreateInterp();
  if (interp == NULL)
  {
    throw ZincException("Tcl_CreateInterp Error", __FILE__, __LINE__);
  }

  // set display
  Tcl_SetVar(interp, "env", "DISPLAY", TCL_GLOBAL_ONLY);
  //remove prompt
  Tcl_SetVar(interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);

  // needed for Default system startup file for Tcl-based applications
  z_tcl_call (Tcl_Init(interp), "Tcl_Init failed : ");

  //Initialize Tk
//  Tk_Init(interp);
  
  z_tcl_call (Tk_Init (interp), "Tk_Init failed : ");
  
  //Initialize Zinc
  z_tcl_call (Tkzinc_Init (interp), "Tkzinc_Init failed :");

  // Load Img package in order to handle PNG, JPEG, ..
  z_tcl_call (Tcl_GlobalEval (interp, "package require Img"), "Package Img not found");

  //Initialize objects pool
  for (int i(0); i<ZINC_POOL_COUNT ; i++)
  {
    pool[i] = Tcl_NewObj ();
    Tcl_IncrRefCount (pool[i]);
  }

  //initialise frame command info
  if (!Tcl_GetCommandInfo(interp, "toplevel", &topCmdInfo))
  {
    throw ZincException (String ("Toplevel command not found"),
                         __FILE__, __LINE__);
  }

  //initialise zinc command info
  if (!Tcl_GetCommandInfo(interp, "zinc", &zncCmdInfo))
  {
    throw ZincException (String ("Zinc command not found"),
                         __FILE__, __LINE__);
  }

  //initialise image command info
  if (!Tcl_GetCommandInfo(interp, "image", &imgCmdInfo))
  {
    throw ZincException (String ("Image command not found"),
                         __FILE__, __LINE__);
  }

  //initialise font command info
  if (!Tcl_GetCommandInfo(interp, "font", &fntCmdInfo))
  {
    throw ZincException (String ("Font command not found"),
                         __FILE__, __LINE__);
  }

  //initialise focus command info
  if (!Tcl_GetCommandInfo(interp, "focus", &focCmdInfo))
  {
    throw ZincException (String ("Focus command not found"),
                         __FILE__, __LINE__);
  }

  //initialise bind command info
  if (!Tcl_GetCommandInfo(interp, "bind", &bndCmdInfo))
  {
    throw ZincException (String ("Bind command not found"),
                        __FILE__, __LINE__);
  }
}


/**
 * Run tk mainloop and returns when there is no more Tk window
 */
void Zinc::zincMainLoop ()
{
  Tk_MainLoop();
}


/*******************************************************
          AUTOGENERATED METHODS (itemconfigure)
"code.cpp" in Tkzins/generic source from :
   ./gen.pl Arc.c Attrs.c Color.c Curve.c Draw.c  Group.c
        Image.c List.c Item.c Icon.c Rectangle.c tkZinc.c Text.c
*******************************************************/

/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */

/**
 * Call zinc->itemconfigure ( -closed )
 *
 * @param item the item to configure
 * @param value the closed to set
 */
void Zinc::itemSetClosed (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_closed;
  p1[4] = Z_BOO_POOL (1, value);

  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetClosed Failed : ");
}

/**
 * Call zinc->itemcget ( -closed )
 *
 * @param item the item to get closed from
 * @return closed value
 */
bool Zinc::itemGetClosed (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_closed;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetClosed Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetClosed Failed : ");
  return bool (value);
}

/**
 * Call zinc->itemconfigure ( -composealpha )
 *
 * @param item the item to configure
 * @param value the composealpha to set
 */
void Zinc::itemSetComposealpha (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_composealpha;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetComposealpha Failed : ");
}

/**
 * Call zinc->itemcget ( -composealpha )
 *
 * @param item the item to get composealpha from
 * @return composealpha value
 */
bool Zinc::itemGetComposealpha (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_composealpha;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetComposealpha Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetComposealpha Failed : ");
  return bool (value);
}

/**
 * Call zinc->itemconfigure ( -composerotation )
 *
 * @param item the item to configure
 * @param value the composerotation to set
 */
void Zinc::itemSetComposerotation (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_composerotation;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetComposerotation Failed : ");
}

/**
 * Call zinc->itemcget ( -composerotation )
 *
 * @param item the item to get composerotation from
 * @return composerotation value
 */
bool Zinc::itemGetComposerotation (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_composerotation;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetComposerotation Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetComposerotation Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -composescale )
 *
 * @param item the item to configure
 * @param value the composescale to set
 */
void Zinc::itemSetComposescale (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_composescale;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetComposescale Failed : ");
}

/**
 * Call zinc->itemcget ( -composescale )
 *
 * @param item the item to get composescale from
 * @return composescale value
 */
bool Zinc::itemGetComposescale (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_composescale;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetComposescale Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetComposescale Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -extent )
 *
 * @param item the item to configure
 * @param value the extent to set
 */
void Zinc::itemSetExtent (ZincItem * item, unsigned int value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_extent;
  p1[4] = Z_INT_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetExtent Failed : ");
}

/**
 * Call zinc->itemcget ( -extent )
 *
 * @param item the item to get extent from
 * @return extent value
 */
unsigned int Zinc::itemGetExtent (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_extent;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetExtent Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "itemGetExtent Failed : ");
  return (unsigned int)value;
}

/**
 * Call zinc->itemconfigure ( -fillcolor )
 *
 * @param item the item to configure
 * @param value the fillcolor to set
 */
void Zinc::itemSetFillcolor (ZincItem * item, String value)
{
  //Warning, weird bug workaround
  // here is a deep copy
  // without this, on frequent calls, tcl mays segfault
  String tmp = String(value.c_str ());

  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_fillcolor;
  p1[4] = Z_STR_POOL (1, tmp.c_str (), -1);
  //call the zinc function in with 5 arguments internal form
  z_command (5, "itemSetFillcolor Failed : ");
}

/**
 * Call zinc->itemcget ( -fillcolor )
 *
 * @param item the item to get fillcolor from
 * @return fillcolor value
 */
String Zinc::itemGetFillcolor (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_fillcolor;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetFillcolor Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return String (Tcl_GetStringFromObj (tmp, NULL));
}

/**
 * Call zinc->itemconfigure ( -filled )
 *
 * @param item the item to configure
 * @param value the filled to set
 */
void Zinc::itemSetFilled (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_filled;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetFilled Failed : ");
}

/**
 * Call zinc->itemcget ( -filled )
 *
 * @param item the item to get filled from
 * @return filled value
 */
bool Zinc::itemGetFilled (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_filled;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetFilled Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetFilled Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -fillpattern )
 *
 * @param item the item to configure
 * @param value the fillpattern to set
 */
void Zinc::itemSetFillpattern (ZincItem * item, ZincBitmap *value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_fillpattern;
  p1[4] = value->object;
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetFillpattern Failed : ");
}

/**
 * Call zinc->itemcget ( -fillpattern )
 *
 * @param item the item to get fillpattern from
 * @return fillpattern value
 */
ZincBitmap * Zinc::itemGetFillpattern (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_fillpattern;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetFillpattern Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincBitmap (tmp, true);
}

/**
 * Call zinc->itemconfigure ( -linecolor )
 *
 * @param item the item to configure
 * @param value the linecolor to set
 */
void Zinc::itemSetLinecolor (ZincItem * item, String value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_linecolor;
  p1[4] = Z_STR_POOL (1, value.c_str (), value.length ());
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetLinecolor Failed : ");
}

/**
 * Call zinc->itemcget ( -linecolor )
 *
 * @param item the item to get linecolor from
 * @return linecolor value
 */
String Zinc::itemGetLinecolor (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_linecolor;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetLinecolor Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return String (Tcl_GetStringFromObj (tmp, NULL));
}

/**
 * Call zinc->itemconfigure ( -linepattern )
 *
 * @param item the item to configure
 * @param value the linepattern to set
 */
void Zinc::itemSetLinepattern (ZincItem * item, ZincBitmap * value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_linepattern;
  p1[4] = value->object;
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetLinepattern Failed : ");
}

/**
 * Call zinc->itemcget ( -linepattern )
 *
 * @param item the item to get linepattern from
 * @return linepattern value
 */
ZincBitmap * Zinc::itemGetLinepattern (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_linepattern;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetLinepattern Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincBitmap (tmp, true);
}

/**
 * Call zinc->itemconfigure ( -linestyle )
 *
 * @param item the item to configure
 * @param value the linestyle to set
 */
void Zinc::itemSetLinestyle (ZincItem * item, lineStyle value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_linestyle;
  p1[4] = lineStyles[value];
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetLinestyle Failed : ");
}

/**
 * Call zinc->itemcget ( -linestyle )
 *
 * @param item the item to get linestyle from
 * @return linestyle value
 */
lineStyle Zinc::itemGetLinestyle (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_linestyle;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetLinestyle Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   lineStylesStrings, 
                                   "lineStyles",
                                   0, &value),
              "itemGetLinestyle Failed : ");
  return (lineStyle)value;
}

/**
 * Call zinc->itemconfigure ( -linewidth )
 *
 * @param item the item to configure
 * @param value the linewidth to set
 */
void Zinc::itemSetLinewidth (ZincItem * item, double value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_linewidth;
  p1[4] = Z_DBL_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetLinewidth Failed : ");
}

/**
 * Call zinc->itemcget ( -linewidth )
 *
 * @param item the item to get linewidth from
 * @return linewidth value
 */
double Zinc::itemGetLinewidth (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_linewidth;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetLinewidth Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  double value;
  z_tcl_call (Tcl_GetDoubleFromObj (interp, tmp, &value),
              "itemGetLinewidth Failed : ");
  return (double)value;
}

/**
 * Call zinc->itemconfigure ( -pieslice )
 *
 * @param item the item to configure
 * @param value the pieslice to set
 */
void Zinc::itemSetPieslice (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_pieslice;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetPieslice Failed : ");
}

/**
 * Call zinc->itemcget ( -pieslice )
 *
 * @param item the item to get pieslice from
 * @return pieslice value
 */
bool Zinc::itemGetPieslice (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_pieslice;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetPieslice Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetPieslice Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -priority )
 *
 * @param item the item to configure
 * @param value the priority to set
 */
void Zinc::itemSetPriority (ZincItem * item, unsigned int value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_priority;
  p1[4] = Z_INT_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetPriority Failed : ");
}

/**
 * Call zinc->itemcget ( -priority )
 *
 * @param item the item to get priority from
 * @return priority value
 */
unsigned int Zinc::itemGetPriority (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_priority;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetPriority Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "itemGetPriority Failed : ");
  return (unsigned int)value;
}

/**
 * Call zinc->itemconfigure ( -sensitive )
 *
 * @param item the item to configure
 * @param value the sensitive to set
 */
void Zinc::itemSetSensitive (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_sensitive;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetSensitive Failed : ");
}

/**
 * Call zinc->itemcget ( -sensitive )
 *
 * @param item the item to get sensitive from
 * @return sensitive value
 */
bool Zinc::itemGetSensitive (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_sensitive;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetSensitive Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetSensitive Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -startangle )
 *
 * @param item the item to configure
 * @param value the startangle to set
 */
void Zinc::itemSetStartangle (ZincItem * item, unsigned int value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_startangle;
  p1[4] = Z_INT_POOL (1, value);
  //call the zinc function  with 5 argumentsin internal form
  z_command (5, "itemSetStartangle Failed : ");
}

/**
 * Call zinc->itemcget ( -startangle )
 *
 * @param item the item to get startangle from
 * @return startangle value
 */
unsigned int Zinc::itemGetStartangle (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_startangle;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetStartangle Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "itemGetStartangle Failed : ");
  return (unsigned int)value;
}

/**
 * Call zinc->itemconfigure ( -tile )
 *
 * @param item the item to configure
 * @param value the tile to set
 */
void Zinc::itemSetTile (ZincItem * item, ZincBitmap * value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_tile;
  p1[4] = value->object;
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetTile Failed : ");
}

/**
 * Call zinc->itemcget ( -tile )
 *
 * @param item the item to get tile from
 * @return tile value
 */
ZincBitmap * Zinc::itemGetTile (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_tile;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetTile Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincBitmap (tmp, true);
}

/**
 * Call zinc->itemconfigure ( -visible )
 *
 * @param item the item to configure
 * @param value the visible to set
 */
void Zinc::itemSetVisible (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_visible;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetVisible Failed : ");
}

/**
 * Call zinc->itemcget ( -visible )
 *
 * @param item the item to get visible from
 * @return visible value
 */
bool Zinc::itemGetVisible (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_visible;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetVisible Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetVisible Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -capstyle )
 *
 * @param item the item to configure
 * @param value the capstyle to set
 */
void Zinc::itemSetCapstyle (ZincItem * item, capStyle value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_capstyle;
  p1[4] = capStyles[value];
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetCapstyle Failed : ");
}

/**
 * Call zinc->itemcget ( -capstyle )
 *
 * @param item the item to get capstyle from
 * @return capstyle value
 */
capStyle Zinc::itemGetCapstyle (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_capstyle;
  //call the zinc function  with 4 argumentsin internal form
  z_command (4, "itemGetCapstyle Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   capStylesStrings, 
                                   "capStyles",
                                   0, &value),
              "itemGetCapstyle Failed : ");
  return (capStyle)value;
}

/**
 * Call zinc->itemconfigure ( -fillrule )
 *
 * @param item the item to configure
 * @param value the fillrule to set
 */
void Zinc::itemSetFillrule (ZincItem * item, fillRule value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_fillrule;
  p1[4] = fillRules[value];
  //call the zinc function  with 5 argumentsin internal form
  z_command (5, "itemSetFillrule Failed : ");
}

/**
 * Call zinc->itemcget ( -fillrule )
 *
 * @param item the item to get fillrule from
 * @return fillrule value
 */
fillRule Zinc::itemGetFillrule (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_fillrule;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetFillrule Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   fillRulesStrings, 
                                   "fillRules",
                                   0, &value),
              "itemGetFillrule Failed : ");
  return (fillRule)value;
}

/**
 * Call zinc->itemconfigure ( -joinstyle )
 *
 * @param item the item to configure
 * @param value the joinstyle to set
 */
void Zinc::itemSetJoinstyle (ZincItem * item, joinStyle value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_joinstyle;
  p1[4] = joinStyles[value];
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetJoinstyle Failed : ");
}

/**
 * Call zinc->itemcget ( -joinstyle )
 *
 * @param item the item to get joinstyle from
 * @return joinstyle value
 */
joinStyle Zinc::itemGetJoinstyle (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_joinstyle;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetJoinstyle Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   joinStylesStrings, 
                                   "joinStyles",
                                   0, &value),
              "itemGetJoinstyle Failed : ");
  return (joinStyle)value;
}

/**
 * Call zinc->itemconfigure ( -relief )
 *
 * @param item the item to configure
 * @param value the relief to set
 */
void Zinc::itemSetRelief (ZincItem * item, relief value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_relief;
  p1[4] = reliefs[value];
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetRelief Failed : ");
}

/**
 * Call zinc->itemcget ( -relief )
 *
 * @param item the item to get relief from
 * @return relief value
 */
relief Zinc::itemGetRelief (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_relief;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetRelief Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   reliefsStrings, 
                                   "reliefs",
                                   0, &value),
              "itemGetRelief Failed : ");
  return (relief)value;
}

/**
 * Call zinc->itemconfigure ( -smoothrelief )
 *
 * @param item the item to configure
 * @param value the smoothrelief to set
 */
void Zinc::itemSetSmoothrelief (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_smoothrelief;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetSmoothrelief Failed : ");
}

/**
 * Call zinc->itemcget ( -smoothrelief )
 *
 * @param item the item to get smoothrelief from
 * @return smoothrelief value
 */
bool Zinc::itemGetSmoothrelief (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_smoothrelief;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetSmoothrelief Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetSmoothrelief Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -alpha )
 *
 * @param item the item to configure
 * @param value the alpha to set
 */
void Zinc::itemSetAlpha (ZincItem * item, unsigned int value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_alpha;
  p1[4] = Z_INT_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetAlpha Failed : ");
}

/**
 * Call zinc->itemcget ( -alpha )
 *
 * @param item the item to get alpha from
 * @return alpha value
 */
unsigned int Zinc::itemGetAlpha (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_alpha;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetAlpha Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "itemGetAlpha Failed : ");
  return (unsigned int)value;
}

/**
 * Call zinc->itemconfigure ( -atomic )
 *
 * @param item the item to configure
 * @param value the atomic to set
 */
void Zinc::itemSetAtomic (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_atomic;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function in with 5 arguments internal form
  z_command (5, "itemSetAtomic Failed : ");
}

/**
 * Call zinc->itemcget ( -atomic )
 *
 * @param item the item to get atomic from
 * @return atomic value
 */
bool Zinc::itemGetAtomic (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_atomic;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetAtomic Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetAtomic Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -clip )
 *
 * @param item the item to configure
 * @param value the clip to set
 */
void Zinc::itemSetClip (ZincItem * item, ZincItem * value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_clip;
  p1[4] = value->object;
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetClip Failed : ");
}

/**
 * Call zinc->itemcget ( -clip )
 *
 * @param item the item to get clip from
 * @return clip value
 */
ZincItem * Zinc::itemGetClip (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_clip;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetClip Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincItem(tmp);
}

/**
 * Call zinc->itemconfigure ( -anchor )
 *
 * @param item the item to configure
 * @param value the anchor to set
 */
void Zinc::itemSetAnchor (ZincItem * item, anchor value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_anchor;
  p1[4] = anchors[value];
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetAnchor Failed : ");
}

/**
 * Call zinc->itemcget ( -anchor )
 *
 * @param item the item to get anchor from
 * @return anchor value
 */
anchor Zinc::itemGetAnchor (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_anchor;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetAnchor Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   anchorsStrings, 
                                   "anchors",
                                   0, &value),
              "itemGetAnchor Failed : ");
  return (anchor)value;
}

/**
 * Call zinc->itemconfigure ( -color )
 *
 * @param item the item to configure
 * @param value the color to set
 */
void Zinc::itemSetColor (ZincItem * item, String value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_color;
  p1[4] = Z_STR_POOL (1, value.c_str (), value.length ());
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetColor Failed : ");
}

/**
 * Call zinc->itemcget ( -color )
 *
 * @param item the item to get color from
 * @return color value
 */
String Zinc::itemGetColor (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_color;
  //call the zinc function with 4 argument in internal form
  z_command (4, "itemGetColor Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return String (Tcl_GetStringFromObj (tmp, NULL));
}

/**
 * Call zinc->itemconfigure ( -connecteditem )
 *
 * @param item the item to configure
 * @param value the connecteditem to set
 */
void Zinc::itemSetConnecteditem (ZincItem * item, ZincItem * value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_connecteditem;
  p1[4] = value->object;
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetConnecteditem Failed : ");
}

/**
 * Call zinc->itemcget ( -connecteditem )
 *
 * @param item the item to get connecteditem from
 * @return connecteditem value
 */
ZincItem * Zinc::itemGetConnecteditem (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_connecteditem;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetConnecteditem Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincItem(tmp);
}

/**
 * Call zinc->itemconfigure ( -connectionanchor )
 *
 * @param item the item to configure
 * @param value the connectionanchor to set
 */
void Zinc::itemSetConnectionanchor (ZincItem * item, anchor value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_connectionanchor;
  p1[4] = anchors[value];
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetConnectionanchor Failed : ");
}

/**
 * Call zinc->itemcget ( -connectionanchor )
 *
 * @param item the item to get connectionanchor from
 * @return connectionanchor value
 */
anchor Zinc::itemGetConnectionanchor (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_connectionanchor;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetConnectionanchor Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   anchorsStrings, 
                                   "anchors",
                                   0, &value),
              "itemGetConnectionanchor Failed : ");
  return (anchor)value;
}

/**
 * Call zinc->itemconfigure ( -image )
 *
 * @param item the item to configure
 * @param value the image to set
 */
void Zinc::itemSetImage (ZincItem * item, ZincImage * value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_image;
  p1[4] = value->object;
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetImage Failed : ");
}

/**
 * Call zinc->itemcget ( -image )
 *
 * @param item the item to get image from
 * @return image value
 */
ZincImage * Zinc::itemGetImage (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_image;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetImage Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincImage(tmp, true);
}

/**
 * Call zinc->itemconfigure ( -mask )
 *
 * @param item the item to configure
 * @param value the mask to set
 */
void Zinc::itemSetMask (ZincItem * item, ZincBitmap * value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_mask;
  p1[4] = value->object;
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetMask Failed : ");
}

/**
 * Call zinc->itemcget ( -mask )
 *
 * @param item the item to get mask from
 * @return mask value
 */
ZincBitmap * Zinc::itemGetMask (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_mask;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetMask Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincBitmap (tmp, true);
}

/**
 * Call zinc->itemconfigure ( -alignment )
 *
 * @param item the item to configure
 * @param value the alignment to set
 */
void Zinc::itemSetAlignment (ZincItem * item, alignment value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_alignment;
  p1[4] = alignments[value];
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetAlignment Failed : ");
}

/**
 * Call zinc->itemcget ( -alignment )
 *
 * @param item the item to get alignment from
 * @return alignment value
 */
alignment Zinc::itemGetAlignment (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_alignment;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetAlignment Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIndexFromObj (interp, tmp,
                                   alignmentsStrings, 
                                   "alignments",
                                   0, &value),
              "itemGetAlignment Failed : ");
  return (alignment)value;
}

/**
 * Call zinc->itemconfigure ( -font )
 *
 * @param item the item to configure
 * @param value the font to set
 */
void Zinc::itemSetFont (ZincItem * item, ZincFont * value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_font;
  p1[4] = Z_STR_POOL (0, value->name.c_str(), value->name.length());
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetFont Failed : ");
}

/**
 * Call zinc->itemcget ( -font )
 *
 * @param item the item to get font from
 * @return font value
 */
ZincFont * Zinc::itemGetFont (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_font;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetFont Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return new ZincFont (Tcl_GetStringResult (interp));
}

/**
 * Call zinc->itemconfigure ( -overstriked )
 *
 * @param item the item to configure
 * @param value the overstriked to set
 */
void Zinc::itemSetOverstriked (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_overstriked;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetOverstriked Failed : ");
}

/**
 * Call zinc->itemcget ( -overstriked )
 *
 * @param item the item to get overstriked from
 * @return overstriked value
 */
bool Zinc::itemGetOverstriked (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_overstriked;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetOverstriked Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetOverstriked Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -spacing )
 *
 * @param item the item to configure
 * @param value the spacing to set
 */
void Zinc::itemSetSpacing (ZincItem * item, short value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_spacing;
  p1[4] = Z_INT_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetSpacing Failed : ");
}

/**
 * Call zinc->itemcget ( -spacing )
 *
 * @param item the item to get spacing from
 * @return spacing value
 */
short Zinc::itemGetSpacing (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_spacing;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetSpacing Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "itemGetSpacing Failed : ");
  return (short)value;
}

/**
 * Call zinc->itemconfigure ( -text )
 *
 * @param item the item to configure
 * @param value the text to set
 */
void Zinc::itemSetText (ZincItem * item, String value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_text;
  p1[4] = Z_STR_POOL (1, value.c_str (), value.length ());
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetText Failed : ");
}

/**
 * Call zinc->itemcget ( -text )
 *
 * @param item the item to get text from
 * @return text value
 */
String Zinc::itemGetText (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_text;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetText Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  return String (Tcl_GetStringFromObj (tmp, NULL));
}

/**
 * Call zinc->itemconfigure ( -underlined )
 *
 * @param item the item to configure
 * @param value the underlined to set
 */
void Zinc::itemSetUnderlined (ZincItem * item, bool value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_underlined;
  p1[4] = Z_BOO_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetUnderlined Failed : ");
}

/**
 * Call zinc->itemcget ( -underlined )
 *
 * @param item the item to get underlined from
 * @return underlined value
 */
bool Zinc::itemGetUnderlined (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_underlined;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetUnderlined Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetBooleanFromObj (interp, tmp, &value),
              "itemGetUnderlined Failed : ");
  return (bool)value;
}

/**
 * Call zinc->itemconfigure ( -width )
 *
 * @param item the item to configure
 * @param value the width to set
 */
void Zinc::itemSetWidth (ZincItem * item, unsigned short value)
{
  //prepare arguments : .zinc itemconfigure item attribute value
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_width;
  p1[4] = Z_INT_POOL (1, value);
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetWidth Failed : ");
}

/**
 * Call zinc->itemcget ( -width )
 *
 * @param item the item to get width from
 * @return width value
 */
unsigned short Zinc::itemGetWidth (ZincItem * item)
{
  Tcl_Obj* tmp;
  //discard all old results
  Tcl_ResetResult (interp);
  //prepare arguments : .zinc itemcget item 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_width;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetWidth Failed : ");

  //retreive the result trough the tcl interpreter and convert it
  tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "itemGetWidth Failed : ");
  return (unsigned short)value;
}



/*******************************************************
             END OF AUTOGENERATED METHODS
*******************************************************/


/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use z_tcl_call which automaticly handle error return
 * codes or z_command to call a Zinc command which handle all arguments too.
 */
/**
 * Call zinc->itemconfigure ( -firstend )
 *
 * @param item the item to get width from
 * @param a,b,c values used to set end
 */
void Zinc::itemSetFirstend (ZincItem * item, double a, double b, double c)
{
  String value = dtos (a) + " " + dtos (b) + " " + dtos (c);
  // call .zinc itemconfigure item -firstend "a b c"
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_firstend;
  p1[4] = Z_STR_POOL (1, value.c_str (), value.length ());
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetFirstend Failed : ");
}
  
  
/**
 * Call zinc->itemcget ( -firstend )
 *
 * @param item the item to get width from
 * @param a,b,c values used to sedwhere we'll put end
 */
void Zinc::itemGetFirstend (ZincItem * item, double *a, double *b, double *c)
{
  Tcl_Obj *tmp;
  int argc;
  char * line;

  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc itemcget item -firstend
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_firstend;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetFirstend Failed : ");

  //get the result as a string
  tmp = Tcl_GetObjResult (interp);
  line = Tcl_GetStringFromObj (tmp, NULL);

  //interpret the string a 3 double
  argc = sscanf(line, "%lf %lf %lf", a, b, c);
  if (argc != 3)
  {
    throw ZincException (String("itemGetFirstend Failed"), __FILE__, __LINE__);
  }
}

/**
 * Call zinc->itemconfigure ( -lastend )
 *
 * @param item the item to get width from
 * @param a,b,c values used to set end
 */
void Zinc::itemSetLastend (ZincItem * item, double a, double b, double c)
{
  String value = dtos (a) + " " + dtos (b) + " " + dtos (c);
  // call .zinc itemconfigure item -lastend "a b c"
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_lastend;
  p1[4] = Z_STR_POOL (1, value.c_str (), value.length ());
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetLastend Failed : ");
}

/**
 * Call zinc->itemcget ( -lastend )
 *
 * @param item the item to get width from
 * @param a,b,c values used to sedwhere we'll put end
 */
void Zinc::itemGetLastend (ZincItem * item, double *a, double *b, double *c)
{
  Tcl_Obj *tmp;
  int argc;
  char * line;

  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc itemcget item -lastend
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_lastend;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetLastend Failed : ");

  //get the result as a string
  tmp = Tcl_GetObjResult (interp);
  line = Tcl_GetStringFromObj (tmp, NULL);

  //interpret the string a 3 double
  argc = sscanf(line, "%lf %lf %lf", a, b, c);
  if (argc != 3)
  {
    throw ZincException (String("itemGetLastend Failed"), __FILE__, __LINE__);
  }
}

/**
 * Call zinc->itemconfigure ( -position )
 *
 * @param item the item to get width fromset position to
 * @param x,y position
 */
void Zinc::itemSetPosition (ZincItem * item, double x, double y)
{
  // call .zinc itemconfigure item -position {x y}
  p1[0] = id;
  p1[1] = ZFCT_itemconfigure;
  p1[2] = item->object;
  p1[3] = ZOPT_position;
  //make a pair
   p2[0] = Z_DBL_POOL (1, x);
   p2[1] = Z_DBL_POOL (2, y);
  p1[4] = Z_LST_POOL (3, p2, 2); // a list of 2 items
  //call the zinc function with 5 arguments in internal form
  z_command (5, "itemSetPosition Failed : ");
  // clean the list No 3 in the pool
  Z_CLEANLIST (3);
}

/**
 * Call zinc->itemcget ( -position )
 *
 * @param item the item to get position from
 * @param x,y position
 */
void Zinc::itemGetPosition (ZincItem * item, double *x, double *y)
{
  Tcl_Obj *tmp;
  int num;
  Tcl_Obj** elems;

  //discard old results
  Tcl_ResetResult (interp);
  // call .zinc itemcget item -position 
  p1[0] = id;
  p1[1] = ZFCT_itemcget;
  p1[2] = item->object;
  p1[3] = ZOPT_position;
  //call the zinc function with 4 arguments in internal form
  z_command (4, "itemGetPosition Failed : ");

  //retreive the result as a list
  tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_ListObjGetElements (interp, tmp, &num, &elems),
              "itemGetPosition Failed : ");

  //num is necessarily 2 extract 2 double
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[0], x),
              "itemGetPosition Failed : ");
  z_tcl_call (Tcl_GetDoubleFromObj(interp, elems[0], y),
              "itemGetPosition Failed : ");
}

/**
 * Create an image object
 *
 * @param the image reference (a file name)
 * @param isPhoto true for a picture, false for an X11 bitmap
 */
ZincImage* Zinc::createImageFromFile (String image)
{
  const char* para[5];
  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : image create (photo|bitmap) -file image
  para[0] = "image";
  para[1] = "create";
  para[2] = "photo";
  para[3] = "-file";
  para[4] = image.c_str ();

  // call the function with 5 arguments and check for error
  z_tcl_call ((*imgCmdInfo.proc)(imgCmdInfo.clientData, interp, 5, para),
              "createImageFromFile Failed : ");
  return new ZincImage (Tcl_GetObjResult (interp));  
}

/**
 * Create an image object
 *
 * @param the image reference (a base64 String or binary data)
 * @param isPhoto true for a picture, false for an X11 bitmap
 */
ZincImage* Zinc::createImageFromData (String image)
{
  const char* para[5];
  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : image create (photo|bitmap) -data image
  para[0] = "image";
  para[1] = "create";
  para[2] = "photo";
  para[3] = "-data";
  para[4] = image.c_str ();

  // call the function with 5 arguments and check for error
  z_tcl_call ((*imgCmdInfo.proc)(imgCmdInfo.clientData, interp, 5, para),
              "createImageFromData Failed : ");
  return new ZincImage (Tcl_GetObjResult (interp));
}

/**
 * Create a bitmap object from a file
 *
 * @param image the bitmap reference (a file name)
 */
ZincBitmap* Zinc::createBitmapFromFile (String image)
{
  const char* para[5];
  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : image create (photo|bitmap) -file image
  para[0] = "image";
  para[1] = "create";
  para[2] = "bitmap";
  para[3] = "-file";
  para[4] = image.c_str ();

  // call the function with 5 arguments and check for error
  z_tcl_call ((*imgCmdInfo.proc)(imgCmdInfo.clientData, interp, 5, para),
              "createBitmapFromFile Failed : ");
  return new ZincBitmap (Tcl_GetObjResult (interp), false);  
}

/**
 * Create a bitmap object base64 data
 *
 * @param image the bitmap reference (a base64 String or binary data)
 */
ZincBitmap* Zinc::createBitmapFromData (String image)
{
  const char* para[5];
  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : image create (photo|bitmap) -data image
  para[0] = "image";
  para[1] = "create";
  para[2] = "bitmap";
  para[3] = "-data";
  para[4] = image.c_str ();

  // call the function with 5 arguments and check for error
  z_tcl_call ((*imgCmdInfo.proc)(imgCmdInfo.clientData, interp, 5, para),
              "createBitmapFromData Failed : ");
  return new ZincBitmap (Tcl_GetObjResult (interp), false);
}

/**
 * Create a bitmap object using a predefined name
 *
 * @param image the bitmap reference (a name)
 */
ZincBitmap* Zinc::createBitmapFromName (String image)
{
  return new ZincBitmap (image);
}

/**
 * Create an image object
 *
 * @param width Width of image
 * @param height Height of image
 * @param aggBuffer An AGG buffer
 */
ZincImage* Zinc::createImageFromAGGBuffer (int width, int height, unsigned char *aggBuffer)
{
  const char* para[7];
  //discard old results
  Tcl_ResetResult (interp);

  // create a blank offscreen image
  para[0] = "image";
  para[1] = "create";
  para[2] = "photo";
  para[3] = "-height";
  para[4] =  String(itos (height).c_str ()).c_str ();
  para[5] = "-width";
  para[6] =  String(itos (width).c_str ()).c_str ();
  
  // call the function with 7 arguments and check for error
  z_tcl_call ((*imgCmdInfo.proc)(imgCmdInfo.clientData, interp, 7, para),
              "createImageFromBuffer Failed : ");
  // save result
  ZincImage *result = new ZincImage (Tcl_GetObjResult (interp));
  
  // get tcl PhotoImage handle
  Tk_PhotoHandle photo;
  photo = Tk_FindPhoto (interp, Tcl_GetString (result->object));
  if (photo == NULL)
  {
    // todo: error
  }
  
  // create a PhotoImageBlock
  Tk_PhotoImageBlock block;
  block.pixelPtr = aggBuffer;
  block.width = width;
  block.height = height;
  block.pitch = block.width * 3;
  block.pixelSize = 3;
  block.offset[0] = 0;
  block.offset[1] = 1;
  block.offset[2] = 2;
  block.offset[3] = 0;
  
  /* copy block to photo image and leave the rest to tk */
  Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height, TK_PHOTO_COMPOSITE_SET);
  
  // return result
  return result;
}



/**
 * Create a font object
 *
 * @param family the font mamily
 * @param size if a positive number, it is in points, if a negative number,
 *   its absolute value is a size in pixels.
 * @param bold 1 for a bold font, 0 for a normal font, -1 for unspecified
 * @param italic 1 an italic font, 0 for a roman font, -1 for unspecified
 * @param underline 1 for an underlined, 0 for a normal font, -1 for
 *    unspecified
 * @param overstrike 1 for an overstriked font, 0 for a normal font, -1 for unspecified
 */
ZincFont* Zinc::createFont (String family, int size, int bold, int italic,
                            int underline, int overstrike)
{
  const char* para[14];
  //quote family to avoid problems with spaces

  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : font create -family family -size size
  //   -weight weight -slant slant -underline underline -overstrike overstrike
  para[0] = "font";
  para[1] = "create";
  para[2] = "-family";
  para[3] = family.c_str ();
  para[4] = "-size";
  //Warning, weird bug workaround
  // here is a deep copy
  // without this, on one MDK10.1 machine tcl sees an empty string
  String tmp = String(itos (size).c_str ());
  para[5] = tmp.c_str ();

  // use i as a variable parameter pointer
  int i=6; // last parameter is para[5]
  //handle default value for weight
  if (bold != -1)
  {
    para[i++] = "-weight";
    para[i++] = bold == 1 ? "bold" : "normal";
  }
  //handle default value for italic
  if (italic != -1)
  {
    para[i++] = "-slant";
    para[i++] = italic == 1 ? "italic" : "roman";
  }
  //handle default value for underline
  if (underline != -1)
  {
    para[i++] = "-underline";
    para[i++] = underline == 1 ? "true" : "false";
  }
  //handle default value for overstrike
  if (overstrike != -1)
  {
    para[i++] = "-overstrike";
    para[i++] = overstrike == 1 ? "true" : "false";
  }

  // call the function with i arguments and check for error
  z_tcl_call ((*fntCmdInfo.proc)(fntCmdInfo.clientData, interp, i, para),
              "createFont Failed : ");
  return new ZincFont (Tcl_GetStringResult (interp));
}

/**
 * Get font ascent
 *
 * @param font the font
 * @return the font ascent
 */
int Zinc::getFontAscent (ZincFont* font)
{
  const char* para[4];

  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : font metrics font -ascent
  para[0] = "font";
  para[1] = "metrics";
  para[2] = font->name.c_str();
  para[3] = "-ascent";

  // call the function with 4 arguments and check for error
  z_tcl_call ((*fntCmdInfo.proc)(fntCmdInfo.clientData, interp, 4, para),
              "getFontAscent Failed : ");

  //retreive the result as an integer
  Tcl_Obj *tmp = Tcl_GetObjResult (interp);
  int value;
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "getFontAscent Failed : ");
  return value;
}


/**
 * Get Image width
 *
 * @param ZincImage the image to get width from
 * @return the width of the image
 */
int Zinc::getImageWidth (ZincImage *image)
{
  const char* para[3];

  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : image create (photo|bitmap) -data image
  para[0] = "image";
  para[1] = "width";
  para[2] = Tcl_GetString (image->object);

  // call the function with 3 arguments and check for error
  z_tcl_call ((*imgCmdInfo.proc)(imgCmdInfo.clientData, interp, 3, para),
              "getImageWidth Failed : ");

  int value;
  // retreive the result as an integer
  Tcl_Obj *tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "getImageWidth Failed : ");
  return value;
}

/**
 * Get Image height
 *
 * @param ZincImage the image to get height from
 * @return the height of the image
 */
int Zinc::getImageHeight (ZincImage *image)
{
  const char* para[3];

  //discard old results
  Tcl_ResetResult (interp);
  // prepare arguments to call : image create (photo|bitmap) -data image
  para[0] = "image";
  para[1] = "height";
  para[2] = Tcl_GetString (image->object);

  // call the function with 3 arguments and check for error
  z_tcl_call ((*imgCmdInfo.proc)(imgCmdInfo.clientData, interp, 3, para),
              "getImageHeight Failed : ");

  int value;
  // retreive the result as an integer
  Tcl_Obj *tmp = Tcl_GetObjResult (interp);
  z_tcl_call (Tcl_GetIntFromObj (interp, tmp, &value),
              "getImageHeight Failed : ");
  return value;
}

/**
 * This is inline because it is called frequently and needs to be optimized
 * Use this when you need to call a function that can return a TCL error code.
 *
 * @param fct the full function call
 * @param msg the error message to throw in case of error
 */ 
void Zinc::z_tcl_call (int result, char* p_msg) throw (ZincException)
{
  if (result != TCL_OK)
  {
    const char *r;
    String msg = "zinclib: ";
    if (p_msg != NULL)
    {
      msg.append (p_msg);
    }
    r = Tcl_GetStringResult (interp);
    if (r != NULL)
    {
      msg.append (r);
    }
    throw ZincException (msg, __FILE__, __LINE__ );
  }
}

/**
 * This is a inline because it is called frequently and needs to be optimized
 * Use this to call the zinObjectCommand fuction. The call is made using the
 * pre allocated table p1, it must contain Tcl_Obj thar are parameters to
 * the zinObjectCommand function. A parameter indicate how many parameters
 * are passed to the zinObjectCommand function.
 *
 * @param count the number of parameters in p1
 * @param msg the error message to throw in case of error
 */ 
void Zinc::z_command (int count, char* p_msg) throw (ZincException)
{
  int result = (*objCmd) (wi, interp, (count), p1);
  if (result != TCL_OK)
  {
    const char *r;
    String msg = "zinclib: ";
    if (p_msg != NULL)
    {
      msg.append (p_msg);
    }
    r = Tcl_GetStringResult (interp);
    if (r != NULL)
    {
      msg.append (r);
    }
    throw ZincException (msg, __FILE__, __LINE__ );
  }
}

Added jni/tkzinc/zinclib.d/src/Zinc.hpp.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
/**       Zinc.hpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here is the declaration of the Zinc object
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *           David Thevenin <thevenin@intuilab.com>
 *
 */
#include "ZincTypes.hpp"
#include "ZincObjects.hpp"
#include "ZincPath.hpp"
#include "ZincExtern.hpp"
#include <tcl.h>

#ifndef ZINC_HEADER
#define ZINC_HEADER


/** Number of objects in the pool */
const int ZINC_POOL_COUNT   = 7;
/** maximum number of parameter in a zinc function */
const int  ZINC_PARAM_COUNT = 10;

/**Defaults zinc group */
const int DEFAULT_GROUP = 1;

/**
 * This class contains a zinc widget and members to create and modify items
 */
class Zinc
{
  friend class ZincPath;
  
public:
  Tcl_Obj *id;           ///< the id of this object
  WidgetObjCmd objCmd;   ///< the command associated with this object
  ClientData wi;         ///< the zinc object itself
  String tclCb;          ///< name of the binding callback
  int znId;              ///< the znCount at creation time
  String window;         ///< the window which contains the widget

  static int znCount;                   ///< count to create unique ids
  static Tcl_CmdInfo topCmdInfo;        ///< the command associated with toplevel
  static Tcl_CmdInfo zncCmdInfo;        ///< the command associated with zinc
  static Tcl_CmdInfo imgCmdInfo;        ///< the command associated with image
  static Tcl_CmdInfo fntCmdInfo;        ///< the command associated with font
  static Tcl_CmdInfo focCmdInfo;        ///< the command associated with fous
  static Tcl_CmdInfo bndCmdInfo;        ///< the command associated with bind
  static Tcl_Obj* pool[ZINC_POOL_COUNT];///< a pool of tclobj ready to be used
  static Tcl_Obj* p1[ZINC_PARAM_COUNT]; ///< table of pointeur use for parameters
  static Tcl_Obj* p2[ZINC_PARAM_COUNT]; ///< table of pointeur use for parameters

public:
  static Tcl_Interp *interp;            ///< the tcl interpreter

  /**
   * The public constructor
   *
   * @param renderingMode ZINC_BACKEND_X11 or ZINC_BACKEND_OPENGL
   */
  Zinc (int renderingMode);

  /**
   * The public destructor
   */
  ~Zinc ();

  /**
   * Change window title
   *
   * @param title the title string
   */
  void setTitle (String title);

/*****************************************
          WIDGET PROPERTIES
*****************************************/
  
  /**
   * Call zinc->configure ( -backcolor )
   *
   * @param value the backcolor to set
   */
  void setBackcolor (String value);

  /**
   * Call zinc->cget ( -backcolor )
   *
   * @return backcolor value
   */
  String getBackcolor ();

  /**
   * Call zinc->configure ( -forecolor )
   *
   * @param value the forecolor to set
   */
  void setForecolor (String value);

  /**
   * Call zinc->cget ( -forecolor )
   *
   * @return forecolor value
   */
  String getForecolor ();

  /**
   * Call zinc->configure ( -width )
   *
   * @param value the width to set
   */
  void setWidth (int value);

  /**
   * Call zinc->cget ( -width )
   *
   * @return width value
   */
  int getWidth ();

  /**
   * Call zinc->configure ( -height )
   *
   * @param value the height to set
   */
  void setHeight (int value);

  /**
   * Call zinc->cget ( -height )
   *
   * @return height value
   */
  int getHeight ();

  /**
   * Call zinc->configure ( -borderwidth )
   *
   * @param value the borderwidth to set
   */
  void setBorderwidth (int value);

  /**
   * Call zinc->cget ( -borderwidth )
   *
   * @return borderwidth value
   */
  int getBorderwidth ();

  /**
   * Call zinc->configure ( -font )
   *
   * @param value the font to set
   */
  void setFont (ZincFont* value);

  /**
   * Call zinc->cget ( -font )
   *
   * @return font value
   */
  ZincFont* getFont ();

/*****************************************
          WIDGET METHODS
*****************************************/

  /**
   * Get the bounding box of an item
   *
   * @param item the item to get bbox
   * @param bbox a table where we'll put the bounding box
   *             bbox[0] = x0, bbox[1] = y0, bbox[2] = xc, bbox[3] = yc
   */
  void bbox (ZincItem* item, double bbox[4]);

  /**
   * Get the bounding box of an item in its parent group
   *
   * @param item the item to get bbox in its parent group
   * @param bbox a table where we'll put the bounding box
   *             bbox[0] = x0, bbox[1] = y0, bbox[2] = xc, bbox[3] = yc
   */
  void relativeBbox (ZincItem* item, double bbox[4]);


  /**
   * Change the group of an item
   *
   * @param item the item to move
   * @param parentGroup new group for the item
   */
  void chggroup (ZincItem *item, ZincItem *parentGroup);

  /**
   * Clone an item
   *
   * @param item the item to clone
   * @return the cloned item
   */
  ZincItem* clone (ZincItem *item);

  /**
   * Get the number of contour of an item
   *
   * @return number of contour
   */
  int contour (ZincItem *item);

  /**
   * Set the contour of an item to the one of an other
   *
   * @param item the item on which we set the contour
   * @param flag the operation to do on the contour
   * @param reference the item to set contour from
   * @return the number of contour
   */
  int contour (ZincItem *item, itemOperator flag, ZincItem *reference);

  /**
   * Set the contour of an item
   *
   * @param item the item on which we set the contour
   * @param add true to add a path, false to remove
   * @param reference the new contour
   * @return the number of contour
   */
  int contour (ZincItem *item, bool add, ZincPath *contour);

  /**
   * Set or modify the coordinates of an item
   *
   * @param item the item to modify
   * @param contour new coords for the item
   * @param add true to add coords, false to replace
   * @param contourIndex the contour do modify
   * @param coordIndex the coordinate to modify (WARNING, path must be one
   *                   point if the is not the default)
   */
  void coords (ZincItem *item, ZincPath *contour, bool add,
               int contourIndex = -1, int coordIndex = -1);

  /**
   * Remove coords of an item
   *
   * @param item the item to modify
   * @param coordIndex the coordinate to rmove
   * @param contourIndex the contour on which we remove
   */
  void coordsRemove (ZincItem *item, int coordIndex, int contourIndex = -1);

  /**
   * Add a tag to an item
   *
   * @param item the item to add tag to
   * @param tag a tag to add
   */
  void addTag (ZincItem *item, String tag);

  /**
   * Remove a tag from an item
   *
   * @param item the item to remove tag from
   * @param tag a tag to remove (nothing to remove all tags)
   */  
  void dTag (ZincItem *item, String tag = String(""));

  /**
   * List all tags of an item
   * It's up to the caller to delete the resulting table and strings
   *
   * @param item the item to list tag from
   * @param lagList a pointer to a table of String containing tags
   * @return the number of tags
   */
  int getTags (ZincItem *item, String*** tagList);

  /**
   * Set the focus to an item
   *
   * @param item the item to set the focus to
   */
  void focus (ZincItem *item);

  /**
   * Tell if the name is a gradient name
   *
   * @param gname a gradient name
   * @return true if the name is a gradient name, false otherwise
   */
  bool isGname (String gname);

  /**
   * Create a named gradient
   *
   * @param gradient a gradient
   * @param gname a gradient name
   */
  void gname (String gradient, String gname);

  /**
   * Retreive the group of an item
   *
   * @param item the item to get the group from
   * @return the group
   */
  ZincItem* group (ZincItem *item);

  /**
   * Reorder items to lower one
   *
   * @param item the item to lower
   */
  void lower (ZincItem *item);

  /**
   * Reorder items to lower one
   *
   * @param item the item to lower
   * @param belowThis and item that will be over item
   */
  void lower (ZincItem *item, ZincItem *belowThis);

  /**
   * Reorder items to raise one
   *
   * @param item the item to raise
   */
  void raise (ZincItem *item);

  /**
   * Reorder items to raise one
   *
   * @param item the item to raise
   * @param aboveThis an item that will be under item
   */
  void raise (ZincItem *item, ZincItem *aboveThis);

  /**
   * Return the type of an item
   *
   * @param item an item
   * @return the type of the item
   */
   itemType type (ZincItem *item);

  /**
   * Create a Zinc Tag that can be used in place of any item
   *  for zinc functions that must be called using tagOrId
   *
   * @param tag the text of the tag
   * @return a tag item
   */
  ZincItem* createTag(String tag);

/*****************************************
          ITEMS MANIPULATION
*****************************************/
  /**
   * Suppress an item
   *
   * @param item the item to suppress
   */
  void itemRemove (ZincItem *item);

  /**
   * Create a group item
   *
   * @param parentGroup group where we'll put the new group, if NULL we create
   * in the defaults group
   * @return the group item
   */
  ZincItem *itemCreateGroup (ZincItem *parentGroup);

  /**
   * Create a rectangle item
   *
   * @param parentGroup group where we'll put it
   * @param x y width height the coordinates of the new rectangle
   * @return the rectangle item
   */
  ZincItem *itemCreateRectangle (ZincItem *parentGroup, double x, double y,
                                double width, double height);

  /**
   * Create an arc item
   *
   * @param parentGroup group where we'll put it
   * @param x y width height the coordinates of the new rectangle
   * @return the arc item
   */
  ZincItem *itemCreateArc (ZincItem *parentGroup, double x, double y,
                           double width, double height);

  /**
   * Create a text item
   *
   * @param parentGroup group where we'll put it
   * @return the text item
   */
  ZincItem *itemCreateText (ZincItem *parentGroup);

  /**
   * Create a curve item
   *
   * @param parentGroup group where we'll put it
   * @param path the path to display
   * @return the curve item
   */
  ZincItem *itemCreateCurve (ZincItem *parentGroup, ZincPath *path);

  /**
   * Create an icon item
   *
   * @param parentGroup group where we'll put it
   * @param image a zincImage to display
   * @return the icon item
   */
  ZincItem *itemCreateIcon (ZincItem *parentGroup, ZincImage* image);


/**************************************************
                    BINDING
**************************************************/

  /**
   * Bind a function to an event on the zinc widget
   *
   * @param eventSpecification tcl style event specicication
   * @param callBack the function which will be called back
   * @param userData data we will give back to the callback when called
   * @param add false to replace existing bind or true to add
   */
  void bind (String eventSpecification,
             ZincWidgetCallback callBack, void *userData, bool add = false);

  /**
   * Annulate a binding
   *
   * @param eventSpecification tcl style event specicication
   */
  void unbind (String eventSpecification);
  
  /**
   * Bind a function to an event on an item
   *
   * @param item the item on which to bind
   * @param eventSpecification tcl style event specicication
   * @param callBack the function which will be called back
   * @param userData data we will give back to the callback when called
   * @param add false to replace existing bind or true to add
   */
  void itemBind (ZincItem *item, String eventSpecification,
                 ZincItemCallback callBack, void *userData, bool add = false);

  /**
   * Annulate a binding
   *
   * @param item the item on which to unbind
   * @param eventSpecification tcl style event specicication
   */
  void itemUnbind (ZincItem *item, String eventSpecification);

/**************************************************
           TRANSFORMATION METHODS
**************************************************/

  /**
   * Translate the item
   *
   * @param item the item to which we apply the transform
   * @param dx dy translation vector
   */
  void itemTranslate (ZincItem * item, double dx, double dy);

  /**
   * Translate the item
   *
   * @param item the item to which we apply the transform
   * @param x y translation vector
   * @param absolute true if the translation is absolute
   */
  void itemTranslate (ZincItem * item, double x, double y, bool absolute);

  /**
   * Rotate an item
   *
   * @param item the item to which we apply the transform
   * @param angle the angle to rotate in radian
   */
  void itemRotate (ZincItem * item, double angle);

  /**
   * Rotate an item
   *
   * @param item the item to which we apply the transform
   * @param angle the angle to rotate in radian
   * @param x y the center of the rotation
   */
  void itemRotate (ZincItem * item, double angle, double x, double y);

  /**
   * Rotate an item
   *
   * @param item the item to which we apply the transform
   * @param angle the angle to rotate
   * @param degree true for an angle in degree, false for an angle in radians
   */
  void itemRotate (ZincItem * item, double angle, bool degree);

  /**
   * Rotate an item
   *
   * @param item the item to which we apply the transform
   * @param angle the angle to rotate in radian
   * @param x y the center of the rotation
   * @param degree true for an angle in degree, false for an angle in radians
   */
  void itemRotate (ZincItem * item, double angle, double x, double y,
                   bool degree);

  /**
   * Scale an item
   *
   * @param item the item to which we apply the transform
   * @param ax horizontal scale
   * @param ay vertical scale
   */
  void itemScale (ZincItem * item, double ax, double ay);

  /**
   * Scale an item using a specified center
   *
   * @param item the item to which we apply the transform
   * @param ax horizontal scale
   * @param ay vertical scale
   * @param cx cy center of the scale
   */
  void itemScale (ZincItem * item, double ax, double ay, double cx, double cy);

  
  /**
   * Skew an item
   *
   * @param item the item to which we apply the transform
   * @param sx horizontal skew
   * @param sy vertical skew
   */
  void itemSkew (ZincItem * item, double sx, double sy);

  /**
   * Skew an item horizontaly
   *
   * @param item the item to which we apply the transform
   * @param sx horizontal skew
   */
  void itemSkewX (ZincItem * item, double sx);

  /**
   * Skew an item verticaly
   *
   * @param item the item to which we apply the transform
   * @param sy vertical skew
   */
  void itemSkewY (ZincItem * item, double sy);

  /**
   * Reset all transformations associated with the item
   *
   * @param item the item to which we apply the transform
   */
  void itemResetTransformation (ZincItem * item);

  /**
   * Replace current transform by a matrix
   *
   * @param item the item to which we apply the transform
   * @param a,b,c,d,e,f the new transform matrix 
   */
  void itemSetTransformation (ZincItem * item,
                              double a, double b, double c,
                              double d, double e, double f);

  /**
   * Get current transform matrix
   *
   * @param item the item to which we apply the transform
   * @param a,b,c,d,e,f places where we'll put the transform matrix
   */
  void itemGetTransformation (ZincItem * item,
                              double *a, double *b, double *c,
                              double *d, double *e, double *f);

  /**
   * Multiply current transform by a matrix
   *
   * @param item the item to which we apply the transform
   * @param a,b,c,d,e,f the new transform matrix 
   */
  void itemMatrix (ZincItem * item,
                   double a, double b, double c,
                   double d, double e, double f);

/*******************************************************
             AUTOGENERATED METHODS (itemconfigure)
"code.hpp" in Tkzins/generic source from :
   ./gen.pl Arc.c Attrs.c Color.c Curve.c Draw.c  Group.c
        Image.c List.c Item.c Icon.c Rectangle.c tkZinc.c Text.c
*******************************************************/

  /**
   * Call zinc->itemconfigure ( -closed )
   * @param item the item to configure
   * @param value the closed to set
   */
  void itemSetClosed (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -closed )
   * @param item the item to get closed from
   * @return closed value
   */
  bool itemGetClosed (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -composealpha )
   * @param item the item to configure
   * @param value the composealpha to set
   */
  void itemSetComposealpha (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -composealpha )
   * @param item the item to get composealpha from
   * @return composealpha value
   */
  bool itemGetComposealpha (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -composerotation )
   * @param item the item to configure
   * @param value the composerotation to set
   */
  void itemSetComposerotation (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -composerotation )
   * @param item the item to get composerotation from
   * @return composerotation value
   */
  bool itemGetComposerotation (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -composescale )
   * @param item the item to configure
   * @param value the composescale to set
   */
  void itemSetComposescale (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -composescale )
   * @param item the item to get composescale from
   * @return composescale value
   */
  bool itemGetComposescale (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -extent )
   * @param item the item to configure
   * @param value the extent to set
   */
  void itemSetExtent (ZincItem * item, unsigned int value);

  /**
   * Call zinc->itemcget ( -extent )
   * @param item the item to get extent from
   * @return extent value
   */
  unsigned int itemGetExtent (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -fillcolor )
   * @param item the item to configure
   * @param value the fillcolor to set
   */
  void itemSetFillcolor (ZincItem * item, String value);

  /**
   * Call zinc->itemcget ( -fillcolor )
   * @param item the item to get fillcolor from
   * @return fillcolor value
   */
  String itemGetFillcolor (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -filled )
   * @param item the item to configure
   * @param value the filled to set
   */
  void itemSetFilled (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -filled )
   * @param item the item to get filled from
   * @return filled value
   */
  bool itemGetFilled (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -fillpattern )
   * @param item the item to configure
   * @param value the fillpattern to set
   */
  void itemSetFillpattern (ZincItem * item, ZincBitmap * value);

  /**
   * Call zinc->itemcget ( -fillpattern )
   * @param item the item to get fillpattern from
   * @return fillpattern value
   */
  ZincBitmap * itemGetFillpattern (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -linecolor )
   * @param item the item to configure
   * @param value the linecolor to set
   */
  void itemSetLinecolor (ZincItem * item, String value);

  /**
   * Call zinc->itemcget ( -linecolor )
   * @param item the item to get linecolor from
   * @return linecolor value
   */
  String itemGetLinecolor (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -linepattern )
   * @param item the item to configure
   * @param value the linepattern to set
   */
  void itemSetLinepattern (ZincItem * item, ZincBitmap * value);

  /**
   * Call zinc->itemcget ( -linepattern )
   * @param item the item to get linepattern from
   * @return linepattern value
   */
  ZincBitmap * itemGetLinepattern (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -linestyle )
   * @param item the item to configure
   * @param value the linestyle to set
   */
  void itemSetLinestyle (ZincItem * item, lineStyle value);

  /**
   * Call zinc->itemcget ( -linestyle )
   * @param item the item to get linestyle from
   * @return linestyle value
   */
  lineStyle itemGetLinestyle (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -linewidth )
   * @param item the item to configure
   * @param value the linewidth to set
   */
  void itemSetLinewidth (ZincItem * item, double value);

  /**
   * Call zinc->itemcget ( -linewidth )
   * @param item the item to get linewidth from
   * @return linewidth value
   */
  double itemGetLinewidth (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -pieslice )
   * @param item the item to configure
   * @param value the pieslice to set
   */
  void itemSetPieslice (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -pieslice )
   * @param item the item to get pieslice from
   * @return pieslice value
   */
  bool itemGetPieslice (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -priority )
   * @param item the item to configure
   * @param value the priority to set
   */
  void itemSetPriority (ZincItem * item, unsigned int value);

  /**
   * Call zinc->itemcget ( -priority )
   * @param item the item to get priority from
   * @return priority value
   */
  unsigned int itemGetPriority (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -sensitive )
   * @param item the item to configure
   * @param value the sensitive to set
   */
  void itemSetSensitive (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -sensitive )
   * @param item the item to get sensitive from
   * @return sensitive value
   */
  bool itemGetSensitive (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -startangle )
   * @param item the item to configure
   * @param value the startangle to set
   */
  void itemSetStartangle (ZincItem * item, unsigned int value);

  /**
   * Call zinc->itemcget ( -startangle )
   * @param item the item to get startangle from
   * @return startangle value
   */
  unsigned int itemGetStartangle (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -tile )
   * @param item the item to configure
   * @param value the tile to set
   */
  void itemSetTile (ZincItem * item, ZincBitmap * value);

  /**
   * Call zinc->itemcget ( -tile )
   * @param item the item to get tile from
   * @return tile value
   */
  ZincBitmap * itemGetTile (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -visible )
   * @param item the item to configure
   * @param value the visible to set
   */
  void itemSetVisible (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -visible )
   * @param item the item to get visible from
   * @return visible value
   */
  bool itemGetVisible (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -capstyle )
   * @param item the item to configure
   * @param value the capstyle to set
   */
  void itemSetCapstyle (ZincItem * item, capStyle value);

  /**
   * Call zinc->itemcget ( -capstyle )
   * @param item the item to get capstyle from
   * @return capstyle value
   */
  capStyle itemGetCapstyle (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -fillrule )
   * @param item the item to configure
   * @param value the fillrule to set
   */
  void itemSetFillrule (ZincItem * item, fillRule value);

  /**
   * Call zinc->itemcget ( -fillrule )
   * @param item the item to get fillrule from
   * @return fillrule value
   */
  fillRule itemGetFillrule (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -joinstyle )
   * @param item the item to configure
   * @param value the joinstyle to set
   */
  void itemSetJoinstyle (ZincItem * item, joinStyle value);

  /**
   * Call zinc->itemcget ( -joinstyle )
   * @param item the item to get joinstyle from
   * @return joinstyle value
   */
  joinStyle itemGetJoinstyle (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -relief )
   * @param item the item to configure
   * @param value the relief to set
   */
  void itemSetRelief (ZincItem * item, relief value);

  /**
   * Call zinc->itemcget ( -relief )
   * @param item the item to get relief from
   * @return relief value
   */
  relief itemGetRelief (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -smoothrelief )
   * @param item the item to configure
   * @param value the smoothrelief to set
   */
  void itemSetSmoothrelief (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -smoothrelief )
   * @param item the item to get smoothrelief from
   * @return smoothrelief value
   */
  bool itemGetSmoothrelief (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -alpha )
   * @param item the item to configure
   * @param value the alpha to set
   */
  void itemSetAlpha (ZincItem * item, unsigned int value);

  /**
   * Call zinc->itemcget ( -alpha )
   * @param item the item to get alpha from
   * @return alpha value
   */
  unsigned int itemGetAlpha (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -atomic )
   * @param item the item to configure
   * @param value the atomic to set
   */
  void itemSetAtomic (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -atomic )
   * @param item the item to get atomic from
   * @return atomic value
   */
  bool itemGetAtomic (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -clip )
   * @param item the item to configure
   * @param value the clip to set
   */
  void itemSetClip (ZincItem * item, ZincItem * value);

  /**
   * Call zinc->itemcget ( -clip )
   * @param item the item to get clip from
   * @return clip value
   */
  ZincItem * itemGetClip (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -anchor )
   * @param item the item to configure
   * @param value the anchor to set
   */
  void itemSetAnchor (ZincItem * item, anchor value);

  /**
   * Call zinc->itemcget ( -anchor )
   * @param item the item to get anchor from
   * @return anchor value
   */
  anchor itemGetAnchor (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -color )
   * @param item the item to configure
   * @param value the color to set
   */
  void itemSetColor (ZincItem * item, String value);

  /**
   * Call zinc->itemcget ( -color )
   * @param item the item to get color from
   * @return color value
   */
  String itemGetColor (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -connecteditem )
   * @param item the item to configure
   * @param value the connecteditem to set
   */
  void itemSetConnecteditem (ZincItem * item, ZincItem * value);

  /**
   * Call zinc->itemcget ( -connecteditem )
   * @param item the item to get connecteditem from
   * @return connecteditem value
   */
  ZincItem * itemGetConnecteditem (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -connectionanchor )
   * @param item the item to configure
   * @param value the connectionanchor to set
   */
  void itemSetConnectionanchor (ZincItem * item, anchor value);

  /**
   * Call zinc->itemcget ( -connectionanchor )
   * @param item the item to get connectionanchor from
   * @return connectionanchor value
   */
  anchor itemGetConnectionanchor (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -image )
   * @param item the item to configure
   * @param value the image to set
   */
  void itemSetImage (ZincItem * item, ZincImage * value);

  /**
   * Call zinc->itemcget ( -image )
   * @param item the item to get image from
   * @return image value
   */
  ZincImage * itemGetImage (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -mask )
   * @param item the item to configure
   * @param value the mask to set
   */
  void itemSetMask (ZincItem * item, ZincBitmap * value);

  /**
   * Call zinc->itemcget ( -mask )
   * @param item the item to get mask from
   * @return mask value
   */
  ZincBitmap * itemGetMask (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -alignment )
   * @param item the item to configure
   * @param value the alignment to set
   */
  void itemSetAlignment (ZincItem * item, alignment value);

  /**
   * Call zinc->itemcget ( -alignment )
   * @param item the item to get alignment from
   * @return alignment value
   */
  alignment itemGetAlignment (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -font )
   * @param item the item to configure
   * @param value the font to set
   */
  void itemSetFont (ZincItem * item, ZincFont * value);

  /**
   * Call zinc->itemcget ( -font )
   * @param item the item to get font from
   * @return font value
   */
  ZincFont * itemGetFont (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -overstriked )
   * @param item the item to configure
   * @param value the overstriked to set
   */
  void itemSetOverstriked (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -overstriked )
   * @param item the item to get overstriked from
   * @return overstriked value
   */
  bool itemGetOverstriked (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -spacing )
   * @param item the item to configure
   * @param value the spacing to set
   */
  void itemSetSpacing (ZincItem * item, short value);

  /**
   * Call zinc->itemcget ( -spacing )
   * @param item the item to get spacing from
   * @return spacing value
   */
  short itemGetSpacing (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -text )
   * @param item the item to configure
   * @param value the text to set
   */
  void itemSetText (ZincItem * item, String value);

  /**
   * Call zinc->itemcget ( -text )
   * @param item the item to get text from
   * @return text value
   */
  String itemGetText (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -underlined )
   * @param item the item to configure
   * @param value the underlined to set
   */
  void itemSetUnderlined (ZincItem * item, bool value);

  /**
   * Call zinc->itemcget ( -underlined )
   * @param item the item to get underlined from
   * @return underlined value
   */
  bool itemGetUnderlined (ZincItem * item);

  /**
   * Call zinc->itemconfigure ( -width )
   * @param item the item to configure
   * @param value the width to set
   */
  void itemSetWidth (ZincItem * item, unsigned short value);

  /**
   * Call zinc->itemcget ( -width )
   * @param item the item to get width from
   * @return width value
   */
  unsigned short itemGetWidth (ZincItem * item);


/*******************************************************
             END OF AUTOGENERATED METHODS
*******************************************************/

  /**
   * Call zinc->itemconfigure ( -firstend )
   *
   * @param item the item to set firstend to
   * @param a,b,c values used to set end
   */
  void itemSetFirstend (ZincItem * item, double a, double b, double c);
  
  /**
   * Call zinc->itemcget ( -firstend )
   *
   * @param item the item to get firstend from
   * @param a,b,c values used to sedwhere we'll put end
   */
  void itemGetFirstend (ZincItem * item, double *a, double *b, double *c);

  /**
   * Call zinc->itemconfigure ( -lastend )
   *
   * @param item the item to set lastend to
   * @param a,b,c values used to set end
   */
  void itemSetLastend (ZincItem * item, double a, double b, double c);

  /**
   * Call zinc->itemcget ( -lastend )
   *
   * @param item the item to get lastend from
   * @param a,b,c values used to sedwhere we'll put end
   */
  void itemGetLastend (ZincItem * item, double *a, double *b, double *c);

  /**
   * Call zinc->itemconfigure ( -position )
   *
   * @param item the item to get width fromset position to
   * @param x,y position
   */
  void itemSetPosition (ZincItem * item, double x, double y);

  /**
   * Call zinc->itemcget ( -position )
   *
   * @param item the item to get position from
   * @param x,y position
   */
  void itemGetPosition (ZincItem * item, double *x, double *y);

  /**
   * Create an image object from a file
   *
   * @param image the image reference (a file name)
   */
  ZincImage* createImageFromFile (String image);

  /**
   * Create an image object using base64 data
   *
   * @param image the image reference (a base64 String or binary data)
   */
  ZincImage* createImageFromData (String image);

  /**
   * Create a bitmap object from a file
   *
   * @param image the bitmap reference (a file name)
   */
  ZincBitmap* createBitmapFromFile (String image);

  /**
   * Create a bitmap object base64 data
   *
   * @param image the bitmap reference (a base64 String or binary data)
   */
  ZincBitmap* createBitmapFromData (String image);

  /**
   * Create a bitmap object using a predefined name
   *
   * @param image the bitmap reference (a name)
   */
  ZincBitmap* createBitmapFromName (String image);

  /**
   * Create an image object
   *
   * @param width Width of image
   * @param height Height of image
   * @param aggBuffer An AGG buffer
   */
  ZincImage* createImageFromAGGBuffer (int width, int height, unsigned char *aggBuffer);


  /**
   * Create a font object
   *
   * @param family the font mamily
   * @param size if a positive number, it is in points, if a negative number,
   *   its absolute value is a size in pixels.
   * @param bold 1 for a bold font, 0 for a normal font, -1 for unspecified
   * @param italic 1 an italic font, 0 for a roman font, -1 for unspecified
   * @param underline 1 for an underlined, 0 for a normal font, -1 for
   *    unspecified
   * @param overstrike 1 for an overstriked font, 0 for a normal font, -1 for unspecified
   */
  ZincFont* createFont (String family, int size, int bold = -1,
                        int italic = -1, int underline = -1,
                        int overstrike = -1);
 
  /**
   * Get font ascent
   *
   * @param font the font
   * @return the font ascent
   */
  int getFontAscent (ZincFont* font);

  /**
   * Get Image width
   *
   * @param ZincImage the image to get width from
   * @return the width of the image
   */
  int getImageWidth (ZincImage *image);
  
  /**
   * Get Image height
   *
   * @param ZincImage the image to get height from
   * @return the height of the image
   */
  int getImageHeight (ZincImage *image);
  
/*******************************************************
                STATIC PROCEDURES
*******************************************************/

  /**
   * Loads the zinc library and initialize tcl and tk
   *
   * @param argv0 the name of the execytable as passed in argv[0]
   */
  static void loadZinc (char *argv0) throw (ZincException);

  /**
   * Run tk mainloop and returns when there is no more Tk window
   */
  static void zincMainLoop ();

/*******************************************************
               errors management
*******************************************************/
  /**
   * This is inline because it is called frequently and needs to be optimized
   * Use this when you need to call a function that can return a TCL error code.
   *
   * @param fct the full function call
   * @param msg the error message to throw in case of error
   */ 
  static void z_tcl_call (int result, char* p_msg) throw (ZincException);

  /**
   * This is a inline because it is called frequently and needs to be optimized
   * Use this to call the zinObjectCommand fuction. The call is made using the
   * pre allocated table p1, it must contain Tcl_Obj thar are parameters to
   * the zinObjectCommand function. A parameter indicate how many parameters
   * are passed to the zinObjectCommand function.
   *
   * @param count the number of parameters in p1
   * @param msg the error message to throw in case of error
   */ 
  void z_command (int count, char* p_msg) throw (ZincException);

};

#endif

Added jni/tkzinc/zinclib.d/src/ZincExtern.hpp.





















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**       ZincExtern.hpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here we create TkZinc library headers since they don't exist
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */
#include <tcl.h>

#ifndef ZINC_EXTERN
#define ZINC_EXTERN


// those are function have been created within a C compiler
extern "C"
{

  //The TkZinc function that initialises tkzinc
  int Tkzinc_Init(Tcl_Interp *interp);

  //The TkZinc function that creates a zinc object
  int ZincObjCmd(ClientData client_data,    // Main window associated with interpreter.
                 Tcl_Interp *interp,        // Current interpreter. 
                 int        argc,           // Number of arguments.
                 Tcl_Obj   *CONST  args[]); // Argument objects.

  //The TkZinc function that is called by tcl when calling ".zinc fct ..."
#ifdef _WIN32
  typedef int (__cdecl *WidgetObjCmd)
                           (ClientData client_data,   // Information about the widget.
                            Tcl_Interp *interp,       // Current interpreter.
                            int        argc,          // Number of arguments.
                            Tcl_Obj    *CONST args[]); // Argument objects.
#else
  typedef int (*WidgetObjCmd)
                   (ClientData client_data,   // Information about the widget.
                    Tcl_Interp *interp,       // Current interpreter.
                    int        argc,          // Number of arguments.
                    Tcl_Obj    *CONST args[]) // Argument objects.
          __attribute__((cdecl));
#endif
}

#endif

Added jni/tkzinc/zinclib.d/src/ZincInternal.hpp.













































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**       ZincInternal.hpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here we defines macros and constants that are only used within Zinclib code
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *           David Thevenin <thevenin@intuilab.com>
 *
 */

#include <string>
#include <stdio.h>
#ifdef _WIN32
#define snprintf _snprintf
#endif

#include "ZincObjects.hpp"
#ifndef BAZAR
#define BAZAR

#define MAX_NUM_LENGTH 32

// The base name of the TCL function that serve for callbacks
#define Z_TCLCB "zincTclCb"

/**
 * These are macro for shortness and readability of code.
 * They take one Tcl_Obj from the pool and put one value into it. This object
 * is returned. They all have the same signature.
 *
 * @param no the id of the Tcl_Obj to take within the pool (max is
 *    ZINC_POOL_COUNT-1)
 * @param value the value to put in the extracted object
 * @return the object from the pool
 */
// make a boolean object
#define Z_BOO_POOL(no, value) ( Tcl_SetBooleanObj (pool[no], value), pool[no] )
// make an integer object
#define Z_INT_POOL(no, value) ( Tcl_SetIntObj (pool[no], value), pool[no] )
// make a double object
#define Z_DBL_POOL(no, value) ( Tcl_SetDoubleObj (pool[no], value), pool[no] )
// make a string object
#define Z_STR_POOL(no, value, length) ( Tcl_SetStringObj (pool[no],       \
                                                          value, length), \
                                        pool[no] )

/**
 * Make a list object
 *
 * @param no the id of the Tcl_Obj to take within the pool
 * @param value a table of pointer to Tcl_Obj to put in the list
 * @param size the number objects in the table
 * @return the list object from the pool
 */
#define Z_LST_POOL(no, value, size) ( Tcl_SetListObj (pool[no], size, value),\
                                      pool[no] )

/**
 * Clear a list object. Tcl_Obj used in a list object have a refcount
 * incremented and as such can't be reused for anything else. To free those
 * object you need to clean the list object after use.
 *
 * @param no the id of a Tcl_Obj within the pool which contains a list to
 * clear
 */
#define Z_CLEANLIST(no) Tcl_SetIntObj (pool[no], 0)


/**
 * Create a constant Tcl_Obj that can be reused as a parameter later
 *
 * @parameter string define the name and the value ov the object
 */
//create an option object (value prefixed by '-')
#define Z_DEFINE_ZOPT(string) Tcl_Obj* ZOPT_##string = Tcl_NewStringObj ("-" #string, -1);
//create a function object
#define Z_DEFINE_ZFCT(string) Tcl_Obj* ZFCT_##string = Tcl_NewStringObj (#string, -1);
//create an item object
#define Z_DEFINE_ZITM(string) Tcl_Obj* ZITM_##string = Tcl_NewStringObj (#string, -1);

/**
 * Macro to return a parentGroup Tcl_Obj. If a NULL is group given, it returns
 * the default one.
 *
 * @param parentGroup the parent group to take
 */
#define Z_PARENTGROUP(parentGroup)  \
  ( (parentGroup != NULL) ? parentGroup->object : DEFAULT_GROUP_OBJ );

/**
 * Convert an integer to a string
 *
 * @param integer the integer to convert
 */
inline std::string itos (int integer)
{
  char tmp[MAX_NUM_LENGTH];
  // use standard function to convert
  if (snprintf (tmp, MAX_NUM_LENGTH, "%d", integer) < 0)
  {
    throw ZincException ("Error converting integer", __FILE__, __LINE__ );
  }
  return std::string (tmp);
}

/**
 * Convert a long to a string
 *
 * @param l the long to convert
 */
inline std::string ltos (long l)
{
  char tmp[MAX_NUM_LENGTH];
  // use standard function to convert
  if (snprintf (tmp, MAX_NUM_LENGTH, "%ld", l) < 0)
  {
    throw ZincException ("Error converting long", __FILE__, __LINE__ );
  }
  return std::string (tmp);
}

/**
 * Convert a double to a string
 *
 * @param double the integer to convert
 */
inline std::string dtos (double d)
{
  char tmp[MAX_NUM_LENGTH];
  // use standard function to convert
  if (snprintf (tmp, MAX_NUM_LENGTH, "%f", d) < 0)
  {
    throw ZincException ("Error converting double", __FILE__, __LINE__ );
  }
  return std::string (tmp);
}

/**
 * How To call Zinc or Tcl functions:
 *
 * All arguments of the function are Tcl_Obj. To accelerate their call, there
 * is a pool of preconstructed Tcl_Obj and some often used constant Tcl_Obj.
 * p1 and p2 are tables of pointers to be used for arguments.
 * Fill p1 using either predefined objects like ZITM_* or a pool objet that
 * you can fill with the value you want.
 *  Ex : p1[1] = ZFCT_add;
 * Macros have been defined to fill and use a pool object
 *  Ex : p1[2] = Z_INT_POOL(1, 200);
 * Do not use twice the same pool index for the same function call.
 * p2 is used to construct and argument which is a list of Tcl_Obj.
 * To call the function use Z_TCL_CALL which automaticly handle error return
 * codes or Z_COMMAND to call a Zinc command which handle all arguments too.
 */
#endif

Added jni/tkzinc/zinclib.d/src/ZincObjects.cpp.



















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/**       ZincObjects.cpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here we defines classes that are items in zinc
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *           David Thevenin <thevenin@intuilab.com>
 *
 */
#include "ZincInternal.hpp"
#include "ZincObjects.hpp"
#include "Zinc.hpp"


/**
 * The protected default constructor
 */
ZincItem::ZincItem ()
{ }

/**
 * The public  constructor
 *
 * @param obj the object we want to store
 */
ZincItem::ZincItem (Tcl_Obj *obj)
  : object(obj)
{
  // manage refcount so that the tcl_obj can't be freed
  Tcl_IncrRefCount (object);
}

/**
 * The public destructor
 */
ZincItem::~ZincItem ()
{
  // dercrement refcount to free tcl_obj
  Tcl_DecrRefCount (object);
}

/**
 * The public  constructor
 *
 * @param obj the object we want to store
 */
ZincImage::ZincImage (Tcl_Obj *obj)
  : ZincItem (obj), madeFromInternal (false)
{ }

/**
 * The public  constructor
 *
 * @param obj the object we want to store
 */
ZincImage::ZincImage (Tcl_Obj *obj, bool internal)
  : ZincItem (obj), madeFromInternal (internal)
{ }

/**
 * The public destructor
 */
ZincImage::~ZincImage ()
{
  // do not delete returned values
  if (madeFromInternal)
    return;

  // delete using string commands
  const char* para[5];
  para[0] = "image";
  para[1] = "delete";
  para[2] = Tcl_GetString(object);

  // call the function with 3 arguments
  int res = (*Zinc::imgCmdInfo.proc)(Zinc::imgCmdInfo.clientData,
                                     Zinc::interp, 3, para);
  Zinc::z_tcl_call (res, "delete ZincImage Failed : ");
}

/**
 * The public constructor (redefine the inherited one)
 *
 * @param obj the object we want to store
 */
ZincBitmap::ZincBitmap (Tcl_Obj *obj)
  : ZincItem (obj), madeFromInternal (false)
{ }

/**
 * The public constructor (redefine the inherited one)
 *
 * @param obj the object we want to store
 */
ZincBitmap::ZincBitmap (Tcl_Obj *obj, bool internal)
  : ZincItem (obj), madeFromInternal (internal)
{ }

/**
 * The public constructor (redefine the inherited one)
 *
 * @param name the name of a predefined bitmap
 */
ZincBitmap::ZincBitmap (String name)
  : madeFromInternal (true)
{
  object = Tcl_NewStringObj (name.c_str(), name.length ());
  Tcl_IncrRefCount (object);
}

/**
 * The public destructor
 */
ZincBitmap::~ZincBitmap ()
{
  // do not delete Zinc default bitmaps or returned values
  if (madeFromInternal)
    return;

  // delete using string commands
  const char* para[5];
  para[0] = "image";
  para[1] = "delete";
  para[2] = Tcl_GetString(object);

  // call the function with 3 arguments
  int res = (*Zinc::imgCmdInfo.proc)(Zinc::imgCmdInfo.clientData,
                                     Zinc::interp, 3, para);
  Zinc::z_tcl_call (res, "delete ZincBitmap Failed : ");
}

/**
 * The public constructor
 */
ZincFont::ZincFont (const char *font)
  : name (String (font))
{ }

/**
 * A public constructor with a String parameter
 *
 * @param msg the error message
 */
ZincException::ZincException (String p_msg, char *p_file, int p_lineNo)
  : msg (p_msg), file(p_file), line(p_lineNo)
{ }

/**
 * Copy constructor
 *
 * @param exception the original exception
 */
ZincException::ZincException (const ZincException &e)
  : msg (e.msg), file(e.file), line(e.line)
{ }

/**
 * Public destructor
 */
ZincException::~ZincException () throw()
{ }

/**
 * Retreive the exception message
 *
 * @return the message
 */
const char* ZincException::what () const throw ()
{
  String result = "Zinc Exception : ";
  result += msg + " file " + file + ", line " + itos  (line);
  return result.c_str ();
}

Added jni/tkzinc/zinclib.d/src/ZincObjects.hpp.













































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/**       ZincObjects.hpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here we defines classes that are items in zinc
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *           David Thevenin <thevenin@intuilab.com>
 *
 */
#include "ZincTypes.hpp"

#include <exception>
#include <string>
#include <tcl.h>

#ifndef ZINC_OBJECTS
#define ZINC_OBJECTS

// Object representing a zinc item
class ZincItem
{
protected:
  /**
   * The protected default constructor
   */
  ZincItem ();

public:
  Tcl_Obj *object;  //the object we are storing

  /**
   * The public constructor
   *
   * @param obj the object we want to store
   */
  ZincItem (Tcl_Obj *obj);

  /**
   * The public destructor
   */
  virtual ~ZincItem ();
};

// Object representing a zinc image
class ZincImage : public ZincItem
{
  /**
   * The private constructor
   */
  ZincImage ();

  bool madeFromInternal;

public:
  /**
   * The public constructor (redefine the inherited one)
   *
   * @param obj the object we want to store
   */
  ZincImage (Tcl_Obj *obj);

  /**
   * The public constructor (redefine the inherited one)
   *
   * @param obj the object we want to store
   */
  ZincImage (Tcl_Obj *obj, bool internal);

  /**
   * The public destructor
   */
  virtual ~ZincImage ();
};

// Object representing a zinc bitmap
class ZincBitmap : public ZincItem
{
  /**
   * The private constructor
   */
  ZincBitmap ();

  bool madeFromInternal;

public:
  /**
   * The public constructor (redefine the inherited one)
   *
   * @param obj the object we want to store
   */
  ZincBitmap (Tcl_Obj *obj);

  /**
   * The public constructor (redefine the inherited one)
   *
   * @param obj the object we want to store
   */
  ZincBitmap (Tcl_Obj *obj, bool internal);

  /**
   * The public constructor (redefine the inherited one)
   *
   * @param name the name of a predefined bitmap
   */
  ZincBitmap (String name);
  
  /**
   * The public destructor
   */
  virtual ~ZincBitmap ();
};

// Object representing a zinc font
class ZincFont
{
  /**
   * The public default constructor
   */
  ZincFont ();

public:
  String name;

  /**
   * The public constructor
   */
  ZincFont (const char *font);

};

/**
 * Exceptions that are throwed by zinclib
 */
class ZincException : public std::exception
{

private:
  String msg;   // the exception message
  String file;  // file where exception have been caught
  int line;     // line where exception have been caught

public:
  /**
   * A public constructor with a String parameter
   *
   * @param msg the error message
   */
  ZincException (String msg, char *file, int lineNo);

  /**
   * Copy constructor
   *
   * @param exception the original exception
   */
  ZincException (const ZincException &exception);

  /**
   * Public destructor
   */
  virtual ~ZincException () throw();

  /**
   * Retreive the exception message
   *
   * @return the message
   */
  const char* what () const throw ();
};

#endif

Added jni/tkzinc/zinclib.d/src/ZincPath.cpp.































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/**       Path.cpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here we defines The ZincPath object
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */
#include "Zinc.hpp"
#include "ZincInternal.hpp"

#include <math.h>

// convert degree to radians
const double convertRatio = atan2 (1., 1.) * 4. / 180.;

/**
 * Calculate d % m for doubles
 * this is because the C % works only for integers
 */
inline double modulo (double d, double m)
{
  return d - (floor (d / m) * m);
//  return d;
}
  
/**
 * Append the point to the real path
 *
 * @param x,y the point coordinate
 * @param c true if the point is a control point
 */
inline void ZincPath::addPoint (double x, double y, bool c)
{
  // update last control point
  lastX = x;
  lastY = y;

  // we can't use a flat list since zinc accepts flat list only for simple
  // lines
  Tcl_Obj* point[3];
  int i = 2;
  //create a point object
  //an object for x
  point[0] = Tcl_NewDoubleObj (x);
  // an object for y
  point[1] = Tcl_NewDoubleObj (y);
  // an object for 'c' only if needed
  if (c)
  {
    point[2] = Tcl_NewStringObj ("c", -1);
    i = 3;
  }

  // the point (this increments refcount)
  Tcl_Obj* tmp = Tcl_NewListObj (i, point);
  // append the point to the list
  Zinc::z_tcl_call ( Tcl_ListObjAppendElement (Zinc::interp, path, tmp),
               "addpoint Error:");
}

/**
 * Convert ellipse from SVG form to centered form (used only by arcTo)
 *
 * @param x0,y0 origin of the arc
 * @param rx x-radius of ellipse in degree (can be modified)
 * @param ry y-radius of ellipse in degree (can be modified)
 * @param phi rotation of ellipse in degree (can be modified)
 * @param largeArc true if the large part of the ellipse
 * @param sweep true for a positive angle direction for the drawing
 * @param x,y destination point
 * @param cx,cy center coordinate
 * @param theta begining of arc in degree
 * @param delta extent of arc in degree
 */
void ZincPath::convertFromSvg (double x0, double y0, double &rx, double &ry,
                               double &phi, bool largeArc, bool sweep,
                               double x, double y, double &cx, double &cy,
                               double &theta, double &delta)
{
  /* all this strictly follow the script given in "SVG essentials"
   * p85 : convert an elliptical arc fo SVG to an elliptical arc
   * based around a central point
   */

  // temporary variables
  double dx2, dy2, phiR, x1, y1;
  double rxSq, rySq, x1Sq, y1Sq;
  double sign, sq, coef, radiusCheck;
  double cx1, cy1, sx2, sy2;
  double p, n, ux, uy, vx, vy;

  // compute 1/2 distance between current and final point
  dx2 = (x0 - x) / 2.;
  dy2 = (y0 - y) / 2.;

  //convert from degree to radians
  phi = modulo (phi, 360.);
  phiR = phi * convertRatio;

  //compute (x1, y1)
  x1 = cos (phiR) * dx2 + sin (phiR) * dy2;
  y1 = -sin (phiR) * dx2 + cos (phiR) * dy2;

  // make sure radii are large enough
  rx = fabs (rx); ry = fabs (ry);
  rxSq = rx * rx;
  rySq = ry * ry;
  x1Sq = x1 * x1;
  y1Sq = y1 * y1;

  radiusCheck = (x1Sq / rxSq) + (y1Sq / rySq);
  if (radiusCheck > 1.)
  {
    rx *= sqrt (radiusCheck);
    ry *= sqrt (radiusCheck);
    rxSq = rx * rx;
    rySq = ry * ry;
  }

  //step 2 compute (cx1, cy1)
  sign = (largeArc == sweep) ? -1. : 1.;
  sq = ((rxSq * rySq) - (rxSq * y1Sq) - (rySq * x1Sq)) /
    ((rxSq * y1Sq) + (rySq * x1Sq));
  sq = (sq < 0.) ? 0. : sq;
  coef = (sign * sqrt (sq));
  cx1 = coef * ((rx * y1) / ry);
  cy1 = coef * -((ry * x1) / rx);

  //step 3 : compute (cx, cy) from (cx1, cy1)
  sx2 = (x0 + x) / 2;
  sy2 = (y0 + y) / 2;

  cx = sx2 + (cos (phiR) * cx1 - sin (phiR) * cy1);
  cy = sy2 + (sin (phiR) * cx1 + cos (phiR) * cy1);

  //step 4 : compute angle start angle extent
  ux = (x1 - cx1) / rx;
  uy = (y1 - cy1) / ry;
  vx = (-x1 - cx1) / rx;
  vy = (-y1 - cy1) / ry;
  n = sqrt ((ux *ux) + (uy * uy));
  p = ux; // 1 * ux + 0 * uy
  sign = (uy < 0.) ? -1. : 1.;

  theta = sign * acos (p /n);
  theta = theta / convertRatio;

  n = sqrt ((ux * ux + uy * uy) * (vx * vx + vy * vy));
  p = ux * vx + uy * vy;
  sign = ((ux * vy - uy * vx) < 0.) ? -1. : 1.;
  delta = sign * acos (p / n);
  delta = delta / convertRatio;;

  if (!sweep && delta > 0.)
  {
    delta -= 360.;
  }
  else if (sweep && delta < 0.)
  {
    delta += 360.;
  }

//  delta = modulo (delta, 360.);
//  theta = modulo (theta, 360.);
}


/**
 * The public constructor
 *
 * @param x,y the initial point
 */  
ZincPath::ZincPath (double x, double y)
  : firstX (x), firstY (y)
{
  // create a default path
  path = Tcl_NewListObj (0, NULL);
  // the path must not be deleted by tcl
  Tcl_IncrRefCount (path);
  // add the first point
  addPoint (x, y, false);
}

/**
 * The public destructor
 *
 * @warning Do not destroy a ZincPath if Zinc is not loaded
 */
ZincPath::~ZincPath ()
{
  //decrement reference count on all objs in list -> free
  Tcl_SetIntObj (path, 1);
  //decrement reference count on the list -> free
  Tcl_DecrRefCount (path);
}

/**
 * Close current path
 */
void ZincPath::close ()
{
  addPoint (firstX, firstY, false);
}

/**
 * Draw a line from current point to next point
 *
 * @param x,y next point
 */
void ZincPath::lineTo (double x, double y)
{
  addPoint (x, y, false);
}

/**
 * Draw a cubic bezier using specified control and destination points
 * call cubicBezierTo
 *
 * @param cx1,cy1 first control point
 * @param cx2,cy2 second control point
 * @param x,y destination point
 */
void ZincPath::curveTo (double cx1, double cy1, double cx2, double cy2,
                    double x, double y)
{
  cubicBezierTo (cx1, cy1, cx2, cy2, x, y);
}

/**
 * Draw a cubic bezier using specified control and destination points
 *
 * @param cx1,cy1 first control point
 * @param cx2,cy2 second control point
 * @param x,y destination point
 */
void ZincPath::cubicBezierTo (double cx1, double cy1,
                          double cx2, double cy2,
                          double x, double y)
{
  addPoint (cx1, cy1, true);
  addPoint (cx2, cy2, true);
  addPoint (x, y, false);
}

/**
 * Draw a quadratic bezier using specified control and destination point
 *
 * @param cx1,cy1 first control point
 * @param cx2,cy2 second control point
 * @param x,y destination point
 */
void ZincPath::quadraticBezierTo (double cx, double cy, double x, double y)
{
  // convert from a quadratic bezier to a cubic bezier
  // since that's what is supported by zinc
  /* [[x1, y1], [qx, qy, 'q'], [x2,y2]]
     cx1 = x1 + (qx - x1) * 2/3
     cy1 = y1 + (qy - y1) * 2/3
     cx2 = qx + (x2 - qx)/3
     cy2 = qy + (y2 - qy)/3
  */
  double cx1 = lastX + (cx - lastX) * 2/3;
  double cy1 = lastY + (cy - lastY) * 2/3;
  double cx2 = cx + (x - cx) / 3;
  double cy2 = cy + (y - cy) / 3;
  addPoint (cx1, cy1, true);
  addPoint (cx2, cy2, true);
  addPoint (x, y, false);
}

/**
 * Draw an arc from current point to x,y
 *
 * @param rx x-radius of ellipse
 * @param ry y-radius of ellipse
 * @param xAxisRotation rotation of ellipse
 * @param largeArc true if the large part of the ellipse
 * @param sweepFlag true for a positive angle direction for the drawing
 * @param x,y destination point
 */
void ZincPath::arcTo (double rx, double ry, double xAxisRotation, bool largeArc,
                      bool sweepFlag, double x, double y)
{
  double sx, sy, start, arc;
  // convert to a centered representation
  convertFromSvg (lastX, lastY, rx, ry, xAxisRotation, largeArc, sweepFlag,
                  x, y, sx, sy, start, arc);
        
  // this is all taken from first case study for Intuikit

  /* convert to a curve representation
   * For a good approximation, we need 8 quadratic Bezier
   * to make a circle : the maximal angle is 45°
   */
  // local variables
  int segs;
  double segAngle, angle, angleMid;
  double cosphi, sinphi, tx, ty;
  double previousX, previousY;
  double bx, by, qx, qy;
  double cx1, cy1, cx2, cy2;

  //1) calculate segment counts
  segs = int (ceil (fabs (arc) / 45.));

  //let's create segments of the same angle
  //2) calculate this angle
  segAngle = arc / double(segs) * convertRatio;
  
  xAxisRotation = xAxisRotation * convertRatio;
  start = start * convertRatio;
  
  //3) Our fake starting point (relative to (x,y))
  // true start point is (x,y)
  sx = lastX - cos (start) * rx;
  sy = lastY - sin (start) * ry;  

  /* 4) calculate values that will be used for a rotation
   * of centre (x,y) and angle phi
   * the matrix is :
   *     cos(phi)   -sin(phi)  tx
   *     sin(phi)    cos(phi)  ty
   *     0            0        1
   */
  cosphi = cos (xAxisRotation);
  sinphi = sin (xAxisRotation);
  tx = (1. - cosphi) * lastX + sinphi * lastY;
  ty = (1. - cosphi) * lastY - sinphi * lastX;

  //5) save crrent values
  previousX = lastX;
  previousY = lastY;
  angle = start;

  //6) we already got the first point
  
  //7) calculate segments
  for (int i(0) ; i < segs ; i++)
  {
    //7.1) increment angle
    angle += segAngle;
    
    //7.2) calculate intermediate angle value
    angleMid = angle - segAngle / 2.;

    //7.3) calculate last point of the segment from center and rays
    bx = sx + cos (angle) * rx;
    by = sy + sin (angle) * ry;

    //7.4) calculate control point for the quadratic bezier curve
    qx = sx + cos (angleMid) * (rx / cos (segAngle / 2.));
    qy = sy + sin (angleMid) * (ry / cos (segAngle / 2.));

    //7.5) calculate control points for the equivalent bezier curve
    cx1 = previousX + (qx - previousX) * 2. / 3.;
    cy1 = previousY + (qy - previousY) * 2. / 3.;
    cx2 = qx + (bx - qx) / 3.;
    cy2 = qy + (by - qy) / 3.;

    //7.6) add points
    addPoint (cosphi * cx1 - sinphi * cy1 + tx,
              sinphi * cx1 + cosphi * cy1 + ty, true);
    addPoint (cosphi * cx2 - sinphi * cy2 + tx,
              sinphi * cx2 + cosphi * cy2 + ty, true);
    addPoint (cosphi * bx - sinphi * by + tx,
              sinphi * bx + cosphi * by + ty, false);

    //7.7) Save last point
    previousX = bx;
    previousY = by;
  }

}

/**
 * Return a table of Tcl_Obj* containing a liste of coords points
 *  It's up to the caller to delete the resulting table
 *
 * @return a Tcl_Obj* of type list
 */
Tcl_Obj* ZincPath::getTable ()
{
  return path;
}


Added jni/tkzinc/zinclib.d/src/ZincPath.hpp.





































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/**       Path.hpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here we defines The ZincPath object
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */
#include "ZincTypes.hpp"

#include <list>
#include <tcl.h>

#ifndef ZINC_PATH
#define ZINC_PATH

class ZincPath
{
  double firstX, firstY;     //first point's coordinate
  double lastX, lastY;       //last point's coordinate
  Tcl_Obj* path;             //list of points

  /**
   * Append the point to the real path
   *
   * @param x,y the point coordinate
   * @param c true if the point is a control point
   */
  inline void addPoint (double x, double y, bool c);

  /**
   * Convert ellipse from SVG form to centered form (used only by arcTo)
   *
   * @param x0,y0 origin of the arc
   * @param rx x-radius of ellipse in degree (can be modified)
   * @param ry y-radius of ellipse in degree (can be modified)
   * @param phi rotation of ellipse in degree (can be modified)
   * @param largeArc true if the large part of the ellipse
   * @param sweep true for a positive angle direction for the drawing
   * @param x,y destination point
   * @param cx,cy center coordinate
   * @param theta begining of arc in degree
   * @param delta extent of arc in degree
   */
  void convertFromSvg (double x0, double y0, double &rx, double &ry, double &phi,
                       bool larcgeArc, bool sweep, double x, double y,
                       double &cx, double &cy, double &theta, double &delta);


public:
  /**
   * The public constructor
   *
   * @param x,y the initial point
   */  
  ZincPath (double x, double y);

  /**
   * The public destructor
   *
   * @warning Do not destroy a ZincPath if Zinc is not loaded
   */
  ~ZincPath ();

  /******************************************
       ZincPath manipulation
  ******************************************/
  /**
   * Close current path
   */
  void close ();

  /**
   * Draw a line from current point to next point
   *
   * @param x,y next point
   */
  void lineTo (double x, double y);

  /**
   * Draw a cubic bezier using specified control and destination points
   * call cubicBezierTo
   *
   * @param cx1,cy1 first control point
   * @param cx2,cy2 second control point
   * @param x,y destination point
   */
  void curveTo (double cx1, double cy1, double cx2, double cy2,
                double x, double y);

  /**
   * Draw a cubic bezier using specified control and destination points
   *
   * @param cx1,cy1 first control point
   * @param cx2,cy2 second control point
   * @param x,y destination point
   */
  void cubicBezierTo (double cx1, double cy1, double cx2, double cy2,
                      double x, double y);

  /**
   * Draw a quadratic bezier using specified control and destination point
   *
   * @param cx1,cy1 first control point
   * @param cx2,cy2 second control point
   * @param x,y destination point
   */
  void quadraticBezierTo (double cx, double cy, double x, double y);

  /**
   * Draw an arc from current point to x,y
   *
   * @param rx x-radius of ellipse
   * @param ry y-radius of ellipse
   * @param xAxisRotation rotation of ellipse
   * @param largeArc true if the large part of the ellipse
   * @param sweepFlag true for a positive angle direction for the drawing
   * @param x,y destination point
   */
  void arcTo (double rx, double ry, double xAxisRotation, bool largeArc,
              bool sweepFlag, double x, double y);
  
  /**
   * Return a Tcl_Obj* containing a list of coords points
   *  It's up to the caller to delete the resulting table
   *
   * @return a Tcl_Obj* of type list
   */
  Tcl_Obj* getTable ();

};

#endif

Added jni/tkzinc/zinclib.d/src/ZincTypes.hpp.

























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**       ZincTypes.hpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *   Here we defines types and constants that may be usefull for a zinclib user
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */
#include <string>

#ifndef ZINC_TYPES
#define ZINC_TYPES

typedef std::string String;

/**********************************
   Predeclaration of Zinc types
**********************************/
class Zinc;
class ZincPath;
class ZincItem;
class ZincImage;
class ZincFont;
struct ZincEvent;

/*******************************************************
     Signature to use when binding with a callback
*******************************************************/
typedef void (*ZincItemCallback)
             (Zinc *zinc,        // Information about the widget.
              ZincItem *item,    // the item being evented
              ZincEvent *event,  // event information
              void *userData);   // user data provided with bind

typedef void (*ZincWidgetCallback)
             (Zinc *zinc,        // Information about the widget.
              ZincEvent *event,  // event information
              void *userData);   // user data provided with bind


/***********************************
       Library constants
***********************************/

// Rendering model
const int ZINC_BACKEND_X11 = 0;
const int ZINC_BACKEND_OPENGL = 1;


/***********************************
       Library enums
***********************************/

//Styles for line items
typedef enum
{
  lineStyle_simple = 0,  
  lineStyle_dashed,
  lineStyle_mixed,
  lineStyle_dotted
} lineStyle;

//Styles for line cap
typedef enum
{
  capStyle_butt = 0,
  capStyle_projecting,
  capStyle_round
} capStyle;

//List of fill rules
typedef enum
{
  fillRule_odd = 0 ,
  fillRule_nonzero,
  fillRule_positive,
  fillRule_negative,
  fillRule_abs_geq_2
} fillRule;

//list of join style
typedef enum
{
  joinStyle_bevel = 0,
  joinStyle_miter,
  joinStyle_round
} joinStyle;

//list of reliefs
typedef enum
{
  relief_flat = 0,
  relief_raised,
  relief_sunken,
  relief_ridge,
  relief_groove,
  relief_roundraised,
  relief_roundsunken,
  relief_roundridge,
  relief_roundgroove,
  relief_raisedrule,
  relief_sunkenrule
} relief;

//List of alignments
typedef enum
{
  alignment_left = 0,
  alignment_right,
  alignment_center
} alignment;

//list of anchors
typedef enum
{
  anchor_nw = 0,
  anchor_n,
  anchor_ne,
  anchor_e,
  anchor_se,
  anchor_s,
  anchor_sw,
  anchor_w,
  anchor_center
} anchor;

//actions to take when calling contour
typedef enum
{
  item_add_clockwise,
  item_add_counterclockwise,
  item_remove
} itemOperator;

//list of possible itemtypes
typedef enum
{
  item_group,
  item_arc,
  item_text,
  item_rectangle,
  item_curve,
  item_icon
} itemType;

//informations contained in an event
struct ZincEvent
{
  int x,y;  // pointer position                none -> 0
  int k;    // keycode                         none -> 0
  long t;   // timestamp                       none -> 0
  int w,h;  // window width,heigth             none -> 0
  int X,Y;  // pointer position within display none -> 0
  int b;    // button pressed                  none -> 0
  String K; // keysym                          none -> "??"
};



#endif

Added jni/tkzinc/zinclib.d/test/Makefile.









































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
########################################
#       zinclib tests makefile
########################################

# list of tests to make
EXECS = items widget test itemconf

# default : all tests
all: $(EXECS)

# usefull commons
include ../../../v0.1/common.mk

# specific options
INCLUDE   = -I../src
LIBDIR    = ../tmp
LDFLAGS  += -L../../../v0.1/lib -ltcl8.4 -ltk8.4 -lTkZinc $(LIBDIR)/zinclib.o

# generic target
%.o: %.cpp
	$(CXX) $(CXXFLAGS) -o $@ -c $<

clean:
	rm -f *.o $(PROFFILES) $(EXECS) core.* *.exe

clean_code: clean
	rm -f *~ .\#*

# function to create a target for each test
define funct
$(1): $(1).o $(LIBDIR)/zinclib.o
	$$(GCC) $$(LDFLAGS) -o $$@ $$<
endef

# create a target for each test
$(foreach prog,$(EXECS),$(eval $(call funct,$(prog))))

Added jni/tkzinc/zinclib.d/test/itemconf.cpp.









































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
/**       itemconf.cpp
 *      zinclib/tests
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *   Some tests for zinclib
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */


#include "Zinc.hpp"
#include <math.h>
//global variable
Zinc *zn;

//prepare constants
//white color
String white = String ("white");
// red color
String red = String ("red");
// blue color
String blue = String ("blue");
// sample text
String texte = String ("Hello world");
// sample gradient
String gradient = String ("=axial 0 | blue | white 50 | red");
// sample gradient
String gradient2 = String ("=axial 0 | yellow | green 50 | red");
// gradient name
String gname = "g1";
// empty tag
String tag = String("");

String image =
"R0lGODlhZABkAJEAAPX19efn5wAAAAAAACwAAAAAZABkAAAC/4QfAbnLypyBCNrZbm77zGtR0chJ\
HFVu4uclSoaKIFy+caue72fT82rbeUyYnA7RkflywWFF+UuphJLbtMaEVjtITeXpilwfjp2rpqTh\
VuWw2Sczk4GpH5sn3p4w5yLfyKcl5BboR6chd/ZmGFd0Q/IH1IM36MfyOBTSGNYS89DnmMmG0qVY\
BcXJZWJ6WjoHBgfXR7o6B4q19CVVlrT6VHe7OKNLdWmUh/iZqda69RbluRbkFTo6W3uFxws6zRSp\
QzIiubaXyluNFq7XhDna9oueSIbEQt/DzSoXqspTp7sf4hehP122EYH1ChI0SgULmsrTrxwgMffu\
xcpCcN03Uv8UCyWZh8XNtUGsJIIYF3ARDJEZ25QE06RhRHZ6AtkyKGpWJZIW073qZZFdmoeQejHE\
BFTiFHfDHp67Y2mTyZ9aDN5MSWWeJq3fCHJ0uCnrI0J0VorqZPaiNKKHykFE1ijkrklEaE1qG61n\
VxxoZJoE++XTV7Rfd6LjkqZVyWITVyoCKa9sYaV74zwe7FJrVYeOmdHklNXlkWGcNQHFi7afObug\
Q1ZaUrbeNm5nz2F7fClx6HAdU+PLneyoN8t8qV62d+pywuHBgG+0BfWIsZimoQW1+tOe2LQnBXV7\
FjBpMeiFiKrJl27Pc+yUPUvXi34923GE/Vl1hKwm3dbUnBX/X94XM7WVkls8371HzEGpEWgbV81J\
sp8hGokkWGA2kROXYWRZ6FR//4F3XSStTbccReK8VlGIF6qzojXdIMedKicaxdkx4+3zTjuqqVej\
NRzWxdpSiMBmlko/mgiMkM4gVV2BGarjlC9VjaWZfyNmpJk+klWIkyt+ceSJlsdUNllReSlVmJgT\
lRlhT4fk50Vs52Ho43XhiVialTV6JVOJvfF35J402pUNU5Q9s5F8GM6pI2KBOgHiRwrpWeJwu7jm\
opuiQThhXIdlhqBjbzblHz+bjlGeno7S9SlMGFWUXludvjMXPQ1td1+d5V2jjWi0zibFhlh11qBO\
xiZSk3P6/yz1FFi7/TVWl1ByiaicYSIkpa+oomQtONhCGRVoJpKkmmFRjWHFUeP6BhI8hjJ7R4cL\
8dVJiO0kFJSsNyKq5EmN5etNrfyK+g+YAhK7Y3RUIollYiL+hp1uc0JKaRYQs+UedXlajFpk6iE5\
ZKIcv2pqsR93mOezKZX8213xUZWUJc7ZBF+9+ImHJaTB+UkMSoWm7JaT2dyWy503HeQzYx2jaXJw\
pXFL2LXK3Rrjm8DCtU6Fq8kYD6bMpULfVlDd9W+lZ5HntMHKYDTmeHYMBR/ZrOrLU6roonqYhh/Z\
vC1qCv7zl3RtL2np3wkLEuzBMOPNHGxyDi0bhdW+LRCHsP8uOs1AdxtdKaFXAROMFSnaWniq2fka\
sqVmXqkSeUyb2bhPKJ7dXmdYYf1dc8G+6woqsrBYTz5x5uhTLN0BXwtxtsJK7lwwr85aftUEeanZ\
cOa+TJw7y2X9TtgXZyNv0wGp9Z/Wh385vosiTNua056M88LwBH7q8rOnRXyAcutMqGwfF7uVLxXp\
b+L6GZEyNzB4EXBSsflTtvzFNrV1zWDT8wpkegc20A0Gat7BjNiQRyHn6YQc7iKRP/izspyIg4Qz\
4ZGw+GQvOxyuTYyIEpNiJhWAHSg8CqOToWxYtM+hbTspetmqcoanYdVHVPqyjf9cB8G1oC1gd3pi\
hgSFo47S3G9pE1of+CJnn3h5pju4+FFLRHeoMSanjF60jNbsh7Ij6uVfoFoMTKpEmkShUDu2y96I\
Poc54jEvYJETTAJf6JEKyqqQppHZjIKnRGUMTxoXcuSLbrO2E3VOSXwMk9F2pZylNfJmIxlglPg4\
PimZZygKPOXN6jOSlR3NjtSin+WYJ8QDIYYr8gGk5/jFwMpxb41N6s/pdogf7+FCHpArVTLHFDzD\
KWhn+5tRNPQnzbckz0L4+5qEXOMWlrSsknosipAkiDKIfMhLdNwQiawGgAIAADs=";

//Let's test all item types
int main (int argc, char** argv)
{
  double a,b,c,d,e,f;
  //catch exceptions
  try
  {
    //don't forget to load zinc
    Zinc::loadZinc (argv[0]);
    //create the widget
    zn = new Zinc (ZINC_BACKEND_OPENGL);

    //give it parameters
    zn->setWidth (800);
    zn->setHeight (600);

    ZincItem *g1;
    //create a group
    g1 = zn->itemCreateGroup (NULL);
    //create a rectangle
    ZincItem *rect;
    rect = zn->itemCreateRectangle (g1, 10, 10, 100, 100);

    // create an arc
    ZincItem *arc;
    arc = zn->itemCreateArc (NULL, 10, 10, 200, 200);

    // create a curve
    ZincPath* path = new ZincPath(200,200);
    //test lineto
    path->lineTo (250,250);
    //test quadraticBezierTo
    path->quadraticBezierTo (300,200, 300,300);

    //path->close ();
    //display the curve
    ZincItem *curve = zn->itemCreateCurve (g1, path);
     
    // create a sample text
    ZincItem *text = zn->itemCreateText (g1);
    zn->itemSetPosition (text, 10, 300);

    ZincItem *empty = zn->createTag(tag);
    /**************************************
           tests simple sets and gets
    **************************************/

    //transformations
    zn->itemRotate (rect, 45, true);
    zn->itemSetTransformation (rect, 1, 0, 0, 1, 0, 0);
    zn->itemGetTransformation (rect, &a, &b, &c, &d, &e, &f);
    printf ("Transformation \n%f,%f,%f,%f,%f,%f\n", a, b, c, d, e, f);

    //closed
    zn->itemSetClosed (arc, 1);
    printf ("Closed %d\n",zn->itemGetClosed (arc));

    //composeAlpha
    zn->itemSetComposealpha (rect, 1);
    printf ("composeAlpha %d\n", zn->itemGetComposealpha (rect));

    //Composerotation
    zn->itemSetComposerotation (rect, 1);
    printf ("Composerotation %d\n", zn->itemGetComposerotation (rect));
    
    //Composescale
    zn->itemSetComposescale(rect,1);
    printf ("Composescale %d\n", zn->itemGetComposescale (rect));

    //extent
    zn->itemSetExtent (arc, 230);
    printf ("Extent %d\n", zn->itemGetExtent (arc));

    //fillcolor
    zn->itemSetFillcolor(rect, red);
    printf ("Fillcolor %s\n", zn->itemGetFillcolor (rect).c_str ());

    //filled
    zn->itemSetFilled (rect, 1);
    printf ("Filled %d\n", zn->itemGetFilled (rect));

    //linecolor
    zn->itemSetLinecolor (arc, blue);
    printf ("linecolor %s\n", zn->itemGetLinecolor (arc).c_str ());

    //linestyle
    zn->itemSetLinestyle (arc, lineStyle_dashed);
    printf ("linestyle %d\n", zn->itemGetLinestyle (arc));

    //linewidth
    zn->itemSetLinewidth (arc, 3);
    printf ("linewidth %f\n", zn->itemGetLinewidth (arc));

    //piesplice
    zn->itemSetPieslice (arc, 1);
    printf ("piesplice %d\n", zn->itemGetPieslice (arc));

    //priority
    zn->itemSetPriority (rect, 10);
    printf ("priority %d\n", zn->itemGetPriority (rect));

    //Sensitive
    zn->itemSetSensitive (rect, 1);
    printf ("Sensitive %d\n", zn->itemGetSensitive (rect));

    //Startangle
    zn->itemSetStartangle (arc, 90);
    printf ("Startangle %d\n", zn->itemGetStartangle (arc));

    //SetVisible
    zn->itemSetVisible (rect, 1);
    printf ("Visible %d\n", zn->itemGetVisible (rect));

    //Capstyle
    zn->itemSetCapstyle (curve, capStyle_projecting);
    printf ("Capstyle %d\n", zn->itemGetCapstyle (curve));

    //Fillrule
    zn->itemSetFillrule (curve, fillRule_negative);
    printf ("Fillrule %d\n", zn->itemGetFillrule (curve));

    //Joinstyle
    zn->itemSetJoinstyle (curve, joinStyle_miter);
    printf ("Joinstyle %d\n", zn->itemGetJoinstyle (curve));

    //Relief
    zn->itemSetRelief (curve, relief_groove);
    printf ("Relief %d\n", zn->itemGetRelief (curve));
    
    //Smoothrelief
    zn->itemSetSmoothrelief (curve, 1);
    printf ("Smoothrelief %d\n", zn->itemGetSmoothrelief (curve));

    //alpha
    zn->itemSetAlpha (g1, 75);
    printf ("alpha %d\n", zn->itemGetAlpha (g1));

    //Atomic
    zn->itemSetAtomic (g1, 1);
    printf ("Atomic %d\n", zn->itemGetAtomic (g1));

    //Anchor
    zn->itemSetAnchor (text, anchor_nw);
    printf ("Anchor %d\n", zn->itemGetAnchor (text));

    //Color
    zn->itemSetColor (text, blue);
    printf ("Color %s\n", zn->itemGetColor (text).c_str ());

    //ConnectedItem
    zn->itemSetConnecteditem (text, rect);
    ZincItem *it0 = zn->itemGetConnecteditem (text);
    printf ("ConnectedItem %x\n", (int)it0);

    //Connectionanchor
    zn->itemSetConnectionanchor (text, anchor_se);
    printf ("Connectionanchor %d\n", zn->itemGetConnectionanchor (text));

    //Alignment
    zn->itemSetAlignment (text, alignment_right);
    printf ("Alignment %d\n", zn->itemGetAlignment (text));

    //Overstriked
    zn->itemSetOverstriked (text, 1);
    printf ("Overstriked %d\n", zn->itemGetOverstriked (text));

    //Spacing
    zn->itemSetSpacing (text, 10);
    printf ("Spacing %d\n", zn->itemGetSpacing (text));

    //text
    zn->itemSetText (text, texte);
    printf ("text %s\n", zn->itemGetText (text).c_str ());

    //Underlined
    zn->itemSetUnderlined (text, 1);
    printf ("Underlined %d\n", zn->itemGetUnderlined (text));

    //width
    zn->itemSetWidth (text, 500);
    printf ("width %d\n", zn->itemGetWidth (text));
    
    //Clip
    zn->itemSetClip (g1, rect);
    ZincItem *it1 = zn->itemGetClip (g1);
    printf ("Clip %x\n", (int)it1);
    zn->itemSetClip (g1, empty);


    /**************************************
         tests more sets and gets
    **************************************/

    //firt end
    double a,b,c;
    zn->itemSetLastend (curve, 5, 6, 7);
    zn->itemGetLastend (curve, &a, &b, &c);
    printf ("lastend %f, %f, %f\n", a, b, c);
    
    //last end        
    zn->itemSetFirstend (curve, 5, 6, 7);
    zn->itemGetFirstend (curve, &a, &b, &c);
    printf ("firstend %f, %f, %f\n", a, b, c);


    // position
    zn->itemGetPosition (text, &a, &b);
    printf ("position %f, %f\n", a, b);

    //font
    ZincFont *fn = zn->itemGetFont (text);
    printf("Font %s\n", fn->name.c_str ());

    // add tags
    zn->addTag (rect, String ("tag0"));
    zn->addTag (rect, String ("tag1"));

    //tags
    String **taglist;
    int count = zn->getTags (rect, &taglist);
    for ( int i = 0 ; i < count ; i++ )
    {
      printf("Tag %d : %s\n", i, taglist[i]->c_str ());
    }

    // delete tag
    zn->dTag (rect, String ("tag0"));

    // new rectangle
    ZincItem *r2;
    r2 = zn->itemCreateRectangle (g1, 210, 210, 300, 300);

    //icons
    ZincImage* img = zn->createImageFromData (image);
    ZincItem *icon = zn->itemCreateIcon (g1, img);
    zn->itemTranslate (icon, 500,10);

    //getImage
    ZincImage *it2 = zn->itemGetImage (icon);
    printf("Image %x\n", (int)it2);

    //bitmaps
    ZincBitmap *bm = zn->createBitmapFromName ("AlphaStipple5");
    zn->itemSetFillpattern (r2, bm);

    //fillpattern
    zn->itemSetFillpattern (curve, bm);
    ZincBitmap *it3 = zn->itemGetFillpattern (curve);
    printf("fillpattern %x\n", (int)it3);
    
    //tile
    zn->itemSetTile (curve, bm);
    ZincBitmap *it4 = zn->itemGetTile (curve);
    printf("Tile %x\n", (int)it4);

    //mask
    zn->itemSetMask (icon, bm);
    ZincBitmap *it5 =  zn->itemGetMask (icon);
    printf("Mask %x\n", (int)it5);

    //linepattern
    zn->itemSetLinepattern (curve, bm);
    ZincBitmap *it6 = zn->itemGetLinepattern (curve);
    printf("linepattern %x\n", (int)it6);

    /****************************************
         tests other functions for items
    ****************************************/

    // raise and lower
    zn->raise (icon);
    zn->lower (icon);
    zn->raise (icon, r2);
    zn->lower (icon, r2);

    //gradient name related
    printf("Not gname %d\n", zn->isGname (gname));
    zn->gname (gradient, gname);
    printf("Is gname %d\n", zn->isGname (gname));

    //clone
    ZincItem *i2 = zn->clone (icon);
    zn->itemTranslate (i2, 50, 50);

    // type
    printf("Type %d\n", zn->type (icon));

    //font
    delete fn;
    fn = zn->getFont ();
    printf("Font %s\n", fn->name.c_str ());

    // get contour
    printf ("n Contours %d\n", zn->contour (rect));
    
    // set contour
    ZincItem *curve2 = zn->itemCreateCurve (g1, path);
    zn->contour (curve2, item_add_clockwise, r2);
    zn->contour (curve2, item_add_counterclockwise, rect);

    // set coords
    zn->coords (curve2, path, false );
    zn->coords (curve2, path, true, 1, 1 );

    //remove coords
    //zn->coordsRemove (curve2, 0);

    //deletes
    delete path;
    delete empty;
    delete arc;
    delete r2;
    for(int i=0;i<count;i++)
    {
      delete taglist[i];
    }
    delete[] taglist;
    delete bm;
    delete it0;
    delete it1;
    delete it2;
    delete it3;
    delete it4;
    delete it5;
    delete it6;
    delete curve2;
    delete rect;
    delete img;
    delete icon;
    delete i2;
    delete g1;
    delete text;
    delete fn;
    delete curve;
      
    //run all this
    Zinc::zincMainLoop ();

    // delete the widget
    delete (zn);
  }
  catch (ZincException e)
  {
    printf("ERROR : %s\n",e.what ());
  }
}

Added jni/tkzinc/zinclib.d/test/items.cpp.











































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/**       items.cpp
 *      zinclib/tests
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *   Some tests for zinclib
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */


#include "Zinc.hpp"
#include <math.h>
//global variable
Zinc *zn;

const double PI = atan2 (1., 1.) * 4.;

//prepare constants
//black color
String black = String ("white");
// red color
String red = String ("red");
// sample text
String texte = String ("Hello world");
// sample gradient
String gradient = String ("=axial 0 | blue | white 50 | red");
// sample gradient
String gradient2 = String ("=axial 0 | yellow | green 50 | red");

//Let's test all item types
int main (int argc, char** argv)
{
  //catch exceptions
  try
  {
    //don't forget to load zinc
    Zinc::loadZinc (argv[0]);
    ZincPath *path;

    //create the widget
    zn = new Zinc (ZINC_BACKEND_OPENGL);

    //give it parameters
    zn->setWidth (600);
    zn->setHeight (400);

    //change background color
    printf ("%s\n",zn->getBackcolor ().c_str ());
    zn->setBackcolor (black);
    printf ("%s\n",zn->getBackcolor ().c_str ());

    ZincItem *g1;
    ZincItem *g2;
    //create a group
    g1 = zn->itemCreateGroup (NULL);
    // create another group (with parent)
    g2 = zn->itemCreateGroup (g1);

    //create a rectangle
    ZincItem *rect;
    rect = zn->itemCreateRectangle (g1, 10, 10, 100, 100);
    // fill the rectangle
    zn->itemSetFilled (rect, 1);
    // remove the rectangle
    zn->itemRemove (rect);
    delete rect;

    //try a second one
    rect = zn->itemCreateRectangle (g1, 10, 10, 100, 100);
    // fill the rectangle
    zn->itemSetFilled (rect, 1);
    // in red
    zn->itemSetFillcolor (rect, red);
    zn->itemSetTransformation (rect, cos (PI / 4), sin (PI / 4),
                               -sin (PI / 4), cos (PI / 4), 100, 0);
    delete rect;

    // create an arc
    ZincItem *arc;
    arc = zn->itemCreateArc (NULL, 10, 10, 200, 200);

    // give parameters to the arc
    zn->itemSetClosed (arc, 1);
    zn->itemSetExtent (arc, 230);
    // fill the arc
    zn->itemSetFilled (arc, 1);
    // with a gradient
    zn->itemSetFillcolor (arc, gradient);
    delete arc;

    // create a sample text
    ZincItem *text = zn->itemCreateText (g2);
    zn->itemSetText (text, texte);
    zn->itemSetPosition (text, 10, 300);
    zn->itemSetPosition (text, 10, 300);
    delete text;

    // create a curve
    path = new ZincPath(200,200);
    //test lineto
    path->lineTo (250,250);
    //test quadraticBezierTo
    path->quadraticBezierTo (300,200, 300,300);
    //test cubicBezierTo
    path->cubicBezierTo (400,400, 500,300, 400,200);
    path->curveTo (500,200, 500,100, 400,100);

    //test arcs
    path->arcTo (100, 100, 0, false, true, 300, 100);


    // test close
    path->close ();
    //display the curve
    ZincItem *pa = zn->itemCreateCurve (g2, path);
    zn->contour (pa, false, path);
    zn->contour (pa, true, path);
    delete path;
    // fill the arc
    zn->itemSetFilled (pa, 1);
    // with a gradient
    zn->itemSetFillcolor (pa, gradient2);
    zn->itemTranslate (pa, 30, 30, false);

    // test bounding box
    double bbox[4];
    zn->bbox (pa, bbox);
    printf ("bbox %f, %f, %f, %f\n", bbox[0], bbox[1], bbox[2], bbox[3]);
    delete pa;
    
    // create an icon from a file
    ZincImage *image = zn->createImageFromFile ("paper.gif");
    ZincItem *icon = zn->itemCreateIcon (g2, image);
    printf("icon width %d, height %d\n",
           zn->getImageWidth (image), zn->getImageHeight (image));
    zn->itemSetPosition (icon, 200, 10);
    zn->itemTranslate (icon, -20, 10);
    zn->itemRotate (icon, 0);
    zn->itemRotate (icon, -45, 0, 0);
    zn->itemRotate (icon, 45, true);
    zn->itemRotate (icon, 45, 0, 0, true);
    delete icon;

    // another icon to test other transforms
    ZincItem *icon2 = zn->itemCreateIcon (g2, image);
    zn->itemSetPosition (icon2, 300, 10);
    zn->itemScale (icon2, 3., 3.);
    zn->itemScale (icon2, .5, .5, 0, 0);
    zn->itemSkew (icon2, 10, 10);
    zn->itemSkewX (icon2, -10);
    zn->itemSkewY (icon2, -10);

    // test bounding box
    zn->relativeBbox (icon2, bbox);
    printf ("relativeBbox %f, %f, %f, %f\n", bbox[0], bbox[1], bbox[2], bbox[3]);
    delete icon2;


    // another icon to test other transforms
    ZincItem *icon3 = zn->itemCreateIcon (g2, image);
    zn->itemSetPosition (icon3, 400, 10);
    zn->itemScale (icon3, 3., 3.);
    zn->itemResetTransformation (icon3);
    double a, b, c, d, e, f;
    zn->itemGetTransformation (icon3, &a, &b, &c, &d, &e, &f);
    printf ("Transform %f %f %f %f %f %f\n", a, b, c, d, e, f);
    zn->itemSetTransformation (icon3, a, b, c, d, e, f+20);
    zn->itemMatrix (icon3, 2, 0, 0, 2, 1, 1);
    delete icon3;
    delete image;

    delete g1;
    delete g2;
    
    //run all this
    Zinc::zincMainLoop ();

    // delete the widget
    delete (zn);
  }
  catch (ZincException e)
  {
    printf("ERROR : %s\n",e.what ());
  }
}

Added jni/tkzinc/zinclib.d/test/paper-grey.gif.

cannot compute difference between binary files

Added jni/tkzinc/zinclib.d/test/paper.gif.

cannot compute difference between binary files

Added jni/tkzinc/zinclib.d/test/runtests.sh.



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/sh
 
TEST="test items widget itemconf"

# execution
#pour Unix stantard
export LD_LIBRARY_PATH=../../../v0.1/lib:$LD_LIBRARY_PATH
#pour MacOS X
export DYLD_LIBRARY_PATH=../../../v0.1/lib:$DYLD_LIBRARY_PATH
 
if ( make 1>&2 )
then
   for test in $TEST
   do
      ./$test
   done
fi

Added jni/tkzinc/zinclib.d/test/test.cpp.























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/**       test.cpp
 *      zinclib
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *   Some tests for zinclib
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */


#include "Zinc.hpp"
#include <stack>
#include <queue>

#define CNT 5000

ZincPath *path;
Zinc *zn;
Zinc *zn2;
int stop = 0;
String gradient = String("=axial 0 | blue | red");
std::queue<ZincItem*> pile;

void znCb (Zinc *zinc,  ZincItem *item, ZincEvent *event, void *userData)
{
  printf ("Callback : x=%d y=%d k=%d t=%ld K=%s\n",
          event->x, event->y, event->k, event->t, event->K.c_str ());
  try
  {
    ZincItem *rect;
    int j;
    if (stop == 0)
    {
      for (int i (0) ; i < CNT ; i++ )
      {
        j = i%300;

        rect = zn->itemCreateRectangle (NULL, 10+j, 10+j, 100, 100);
        zn->itemSetFilled (rect, 1);
        zn->itemSetFillcolor (rect, gradient);
        pile.push(rect);
      }
      stop = 1;
    }
    else
    {
      for (int i (0) ; i < CNT ; i++ )
      {
        rect = pile.front();
//        printf("rect %d %s\n",i,Tcl_GetString(rect->object));
        zn->itemRemove (rect);
        delete rect;
        pile.pop();
      }
      stop = 0;
    }
  }
  catch (ZincException e)
  {
    printf("ERRORCB : %s\n",e.what ());
  }
//  return 0;
}

void znCb2 (Zinc *zinc,  ZincItem *item, ZincEvent *event, void *userData)
{
  printf ("Callback2 : x=%d y=%d k=%d t=%1d K=%s\n",
          event->x, event->y, event->k, event->t, event->K.c_str ());
///  return 0;
}

int main (int argc, char** argv)
{
  try
  {
    Zinc::loadZinc (argv[0]);
    String black = String("white");
    String red = String("red");
    String texte = String("Bonjour lé gen");
    zn = new Zinc (ZINC_BACKEND_OPENGL);

    zn->setWidth (600);
    zn->setHeight (400);

    printf ("%s\n",zn->getBackcolor ().c_str());
    zn->setBackcolor (black);
    printf ("%s\n",zn->getBackcolor ().c_str());

    ZincItem *g1;
    ZincItem *g2;
    printf("create group1\n");
    g1 = zn->itemCreateGroup (NULL);
    printf("create group2\n");
    g2 = zn->itemCreateGroup (g1);

    printf("create rect\n");
    ZincItem *rect;
    rect = zn->itemCreateRectangle (g1, 10, 10, 100, 100);
    zn->itemSetFilled (rect, 1);
    zn->itemSetFillcolor (rect, red);
    printf("create arc\n");
    ZincItem *arc;
    arc = zn->itemCreateArc (NULL, 10, 10, 200, 200);

    zn->itemSetClosed (arc, 1);
    zn->itemSetExtent (arc, 230);
    zn->itemSetFilled (arc, 1);
    zn->itemSetFillcolor (arc, gradient);

    printf ("create text\n");
    ZincItem *text = zn->itemCreateText (g2);
    zn->itemSetText (text, texte);
    zn->itemSetPosition (text, 10, 200);
    delete text;
 
    printf ("create curve\n");
    path = new ZincPath(5,5);
    path->lineTo (100,5);
    path->lineTo (200,100);
    ZincItem *curve = zn->itemCreateCurve (g2, path);
    path->lineTo (200,200);
    delete curve;

    printf("create icon\n");
    ZincImage *image = zn->createImageFromFile ("paper.gif");
    ZincItem *icon = zn->itemCreateIcon (g2, image);
    zn->itemSetPosition (icon, 200, 10);
    
    printf("binding\n");
    zn->focus (arc);
    zn->itemBind (arc, String("<KeyPress-a>"), znCb, NULL);
    zn->itemBind (arc, String("<Button-1>"), znCb2, NULL);

    
/*    zn2 = new Zinc (ZINC_BACKEND_OPENGL);
    ZincItem *rect2;
    rect2 = zn2->itemCreateRectangle (NULL, 10, 10, 100, 100);
    zn2->focus (rect2);
    zn2->itemSetFilled (rect2, 1);
    zn2->itemSetFillcolor (rect2, red);
    zn2->setWidth (600);
    zn2->setHeight (400);
    zn2->itemBind (rect2, String("<KeyPress-a>"), znCb2, NULL);
*/    
    Zinc::zincMainLoop ();

    delete g1;
    delete g2;
    delete icon;
    delete image;
    delete arc;
    delete rect;
    delete (zn);
  }
  catch (ZincException e)
  {
    printf("ERROR : %s\n",e.what ());
  }
}

Added jni/tkzinc/zinclib.d/test/test.svg.

















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 10.0, SVG Export Plug-In . SVG Version: 3.0.0 Build 77)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"    "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" [
	<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
	<!ENTITY ns_svg "http://www.w3.org/2000/svg">
	<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg  xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
	 width="100" height="100" viewBox="0 0 100 100" overflow="visible" enable-background="new 0 0 100 100" xml:space="preserve">
	<g id="Layer_1">
		
			<image width="100" height="100" id="XMLID_1_" xlink:href="data:;base64,R0lGODlhZABkAJEAAPX19efn5wAAAAAAACwAAAAAZABkAAAC/4QfAbnLypyBCNrZbm77zGtR0chJ
HFVu4uclSoaKIFy+caue72fT82rbeUyYnA7RkflywWFF+UuphJLbtMaEVjtITeXpilwfjp2rpqTh
VuWw2Sczk4GpH5sn3p4w5yLfyKcl5BboR6chd/ZmGFd0Q/IH1IM36MfyOBTSGNYS89DnmMmG0qVY
BcXJZWJ6WjoHBgfXR7o6B4q19CVVlrT6VHe7OKNLdWmUh/iZqda69RbluRbkFTo6W3uFxws6zRSp
QzIiubaXyluNFq7XhDna9oueSIbEQt/DzSoXqspTp7sf4hehP122EYH1ChI0SgULmsrTrxwgMffu
xcpCcN03Uv8UCyWZh8XNtUGsJIIYF3ARDJEZ25QE06RhRHZ6AtkyKGpWJZIW073qZZFdmoeQejHE
BFTiFHfDHp67Y2mTyZ9aDN5MSWWeJq3fCHJ0uCnrI0J0VorqZPaiNKKHykFE1ijkrklEaE1qG61n
VxxoZJoE++XTV7Rfd6LjkqZVyWITVyoCKa9sYaV74zwe7FJrVYeOmdHklNXlkWGcNQHFi7afObug
Q1ZaUrbeNm5nz2F7fClx6HAdU+PLneyoN8t8qV62d+pywuHBgG+0BfWIsZimoQW1+tOe2LQnBXV7
FjBpMeiFiKrJl27Pc+yUPUvXi34923GE/Vl1hKwm3dbUnBX/X94XM7WVkls8371HzEGpEWgbV81J
sp8hGokkWGA2kROXYWRZ6FR//4F3XSStTbccReK8VlGIF6qzojXdIMedKicaxdkx4+3zTjuqqVej
NRzWxdpSiMBmlko/mgiMkM4gVV2BGarjlC9VjaWZfyNmpJk+klWIkyt+ceSJlsdUNllReSlVmJgT
lRlhT4fk50Vs52Ho43XhiVialTV6JVOJvfF35J402pUNU5Q9s5F8GM6pI2KBOgHiRwrpWeJwu7jm
opuiQThhXIdlhqBjbzblHz+bjlGeno7S9SlMGFWUXludvjMXPQ1td1+d5V2jjWi0zibFhlh11qBO
xiZSk3P6/yz1FFi7/TVWl1ByiaicYSIkpa+oomQtONhCGRVoJpKkmmFRjWHFUeP6BhI8hjJ7R4cL
8dVJiO0kFJSsNyKq5EmN5etNrfyK+g+YAhK7Y3RUIollYiL+hp1uc0JKaRYQs+UedXlajFpk6iE5
ZKIcv2pqsR93mOezKZX8213xUZWUJc7ZBF+9+ImHJaTB+UkMSoWm7JaT2dyWy503HeQzYx2jaXJw
pXFL2LXK3Rrjm8DCtU6Fq8kYD6bMpULfVlDd9W+lZ5HntMHKYDTmeHYMBR/ZrOrLU6roonqYhh/Z
vC1qCv7zl3RtL2np3wkLEuzBMOPNHGxyDi0bhdW+LRCHsP8uOs1AdxtdKaFXAROMFSnaWniq2fka
sqVmXqkSeUyb2bhPKJ7dXmdYYf1dc8G+6woqsrBYTz5x5uhTLN0BXwtxtsJK7lwwr85aftUEeanZ
cOa+TJw7y2X9TtgXZyNv0wGp9Z/Wh385vosiTNua056M88LwBH7q8rOnRXyAcutMqGwfF7uVLxXp
b+L6GZEyNzB4EXBSsflTtvzFNrV1zWDT8wpkegc20A0Gat7BjNiQRyHn6YQc7iKRP/izspyIg4Qz
4ZGw+GQvOxyuTYyIEpNiJhWAHSg8CqOToWxYtM+hbTspetmqcoanYdVHVPqyjf9cB8G1oC1gd3pi
hgSFo47S3G9pE1of+CJnn3h5pju4+FFLRHeoMSanjF60jNbsh7Ij6uVfoFoMTKpEmkShUDu2y96I
Poc54jEvYJETTAJf6JEKyqqQppHZjIKnRGUMTxoXcuSLbrO2E3VOSXwMk9F2pZylNfJmIxlglPg4
PimZZygKPOXN6jOSlR3NjtSin+WYJ8QDIYYr8gGk5/jFwMpxb41N6s/pdogf7+FCHpArVTLHFDzD
KWhn+5tRNPQnzbckz0L4+5qEXOMWlrSsknosipAkiDKIfMhLdNwQiawGgAIAADs="/>
	</g>
</svg>

Added jni/tkzinc/zinclib.d/test/widget.cpp.

























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/**       items.cpp
 *      zinclib/tests
 *
 *   This software is the property of IntuiLab SA, France.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the author may not be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 *   Some tests for zinclib
 *
 *      08/03/05
 *
 *      Contributors:
 *           Benoit Peccatte <peccatte@intuilab.com>
 *
 */


#include "Zinc.hpp"
//global variable
Zinc *zn;
Zinc *zn2;

//prepare constants
//black color
String black = String("white");
// red color
String red = String("blue");
// sample text
String texte = String("Hello world");
// sample gradient
String gradient = String("=axial 0 | blue | white 50 | red");


void znCb (Zinc *zinc,  ZincItem *item, ZincEvent *event, void *userData)
{
  printf ("Callback1 : x=%d y=%d k=%d t=%ld K=%s w=%d h=%d X=%d Y=%d b=%d\n",
          event->x, event->y, event->k, event->t, event->K.c_str (),
          event->w, event->h, event->X, event->Y, event->b );
}


void znCb2 (Zinc *zinc,  ZincItem *item, ZincEvent *event, void *userData)
{
  printf ("Callback2 : x=%d y=%d k=%d t=%ld K=%s w=%d h=%d X=%d Y=%d b=%d\n",
          event->x, event->y, event->k, event->t, event->K.c_str (),
          event->w, event->h, event->X, event->Y, event->b );
}

void znCb3 (Zinc *zinc, ZincEvent *event, void *userData)
{
  printf ("Callback3 : x=%d y=%d k=%d t=%ld K=%s w=%d h=%d X=%d Y=%d b=%d\n",
          event->x, event->y, event->k, event->t, event->K.c_str (),
          event->w, event->h, event->X, event->Y, event->b );
}

//Let's test all item types
int main (int argc, char** argv)
{
  //catch exceptions
  try
  {
    //don't forget to load zinc
    Zinc::loadZinc (argv[0]);

    //create the widget
    zn = new Zinc (ZINC_BACKEND_OPENGL);

    //give it parameters
    zn->setWidth (600);
    zn->setHeight (400);
    zn->setTitle("window1");

    //change background color
    printf ("Backcolor %s\n",zn->getBackcolor ().c_str());
    // test background color
    zn->setBackcolor (black);
    printf ("Backcolor %s\n",zn->getBackcolor ().c_str());

    //change foreground color
    printf ("Forecolor %s\n",zn->getForecolor ().c_str());
    // test foreground color
    zn->setForecolor (red);
    printf ("Forecolor %s\n",zn->getForecolor ().c_str());

    ZincItem *g1;
    ZincItem *g2;
    //create a group
    g1 = zn->itemCreateGroup (NULL);
    // create another group (with parent)
    g2 = zn->itemCreateGroup (g1);

    //create a rectangle
    ZincItem *rect;
    rect = zn->itemCreateRectangle (g1, 10, 10, 100, 100);
    // fill the rectangle
    zn->itemSetFilled (rect, 1);
    // in red
    zn->itemSetFillcolor (rect, red);

    //test change group
    zn->chggroup (rect, g2);
    ZincItem *g = zn->group (rect);
    printf("Group %x\n", (int)g);
    delete g;
    zn->chggroup (rect, g1);

    // test bindings
    zn->focus (rect);
    zn->itemBind (rect, String("<KeyPress-a>"), znCb, NULL);
    zn->itemBind (rect, String("<Button-1>"), znCb2, NULL);
    zn->itemBind (rect, String("<KeyPress-a>"), znCb2, NULL,true);

    //test widget properties
    printf ("Borderwidth %d\n", zn->getBorderwidth ());
    zn->setBorderwidth (3);
    printf ("Borderwidth %d\n", zn->getBorderwidth ());

    // fonts
    ZincFont *font = zn->createFont ("courier", 24);
    printf ("setFont\n");
    zn->setFont (font);
    printf ("fontAscent %d\n", zn->getFontAscent (font));
    ZincItem* text = zn->itemCreateText (NULL);
    zn->itemSetText (text, texte);
    zn->itemSetPosition (text, 10, 300);
    printf ("itemsetFont\n");
    zn->itemSetFont (text, font);
    delete text;
    delete font;

    //test a second widget
    zn2 = new Zinc (ZINC_BACKEND_OPENGL);
    zn2->setWidth (600);
    zn2->setHeight (800);
    zn2->setHeight (400);
    zn2->setHeight (600);
    zn2->setTitle("window2");
    printf("Dimension %d x %d\n",
           zn2->getWidth(), zn2->getHeight());
    ZincItem *rect2;

    //something on the 2nd widget
    rect2 = zn2->itemCreateRectangle (NULL, 100, 100, 100, 100);

    //binding on the 2nd widget directly
    zn2->focus (rect2);
    zn2->itemSetFilled (rect2, 1);
    zn2->itemSetFillcolor (rect2, gradient);
    zn2->bind (String("<KeyPress-a>"), znCb3, NULL);
    zn2->bind (String("<KeyPress-a>"), znCb3, NULL,true);
    zn2->unbind (String("<KeyPress-a>"));
    zn2->bind (String("<KeyPress-a>"), znCb3, NULL);

    //exception test
    try
    {
      zn->itemSetClip (rect2, rect2);
    }
    catch (ZincException &e)
    {
      printf("Exception OK SUCCESS %s OK SUCCESS\n", e.what());
    }

    delete rect;
    delete rect2;
    delete g1;
    delete g2;
    
    //run all this
    Zinc::zincMainLoop ();

    // delete the widget
    delete (zn);
  }
  catch (ZincException &e)
  {
    printf("ERROR : %s\n",e.what ());
  }
  catch (std::exception &e)
  {
    printf("STD ERROR : %s\n",e.what ());
  }
}

Changes to undroid/build-undroidwish-freebsd.sh.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1129
1130
1131
1132
1133
1134
1135















1136
1137
1138
1139
1140
1141
1142
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1274
1275
1276
1277
1278
1279
1280


1281
1282
1283
1284
1285
1286
1287
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-generic.sh.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

if test "$(uname -o)" = "GNU/Linux" ; then
  case $(uname -m) in
    arm*)
      SUBDIRS="${SUBDIRS} piio"
      ;;
    aarch*)







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

if test "$(uname -o)" = "GNU/Linux" ; then
  case $(uname -m) in
    arm*)
      SUBDIRS="${SUBDIRS} piio"
      ;;
    aarch*)
1128
1129
1130
1131
1132
1133
1134















1135
1136
1137
1138
1139
1140
1141
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
  if test -d ${PFX_HERE}/lib/piio* ; then
    cp -rp ${PFX_HERE}/lib/piio* assets
  fi
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
  if test -d ${PFX_HERE}/lib/piio* ; then
    cp -rp ${PFX_HERE}/lib/piio* assets
  fi
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1276
1277
1278
1279
1280
1281
1282


1283
1284
1285
1286
1287
1288
1289
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-illumos.sh.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint tcl-augeas"
SUBDIRS="${SUBDIRS} snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint tcl-augeas"
SUBDIRS="${SUBDIRS} snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1110
1111
1112
1113
1114
1115
1116















1117
1118
1119
1120
1121
1122
1123
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1249
1250
1251
1252
1253
1254
1255


1256
1257
1258
1259
1260
1261
1262
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-linux32.sh.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1127
1128
1129
1130
1131
1132
1133















1134
1135
1136
1137
1138
1139
1140
  DESTDIR=${HERE} ./configure --build=i586-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
  DESTDIR=${HERE} ./configure --build=i586-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=i586-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1272
1273
1274
1275
1276
1277
1278


1279
1280
1281
1282
1283
1284
1285
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-linux64.sh.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1127
1128
1129
1130
1131
1132
1133















1134
1135
1136
1137
1138
1139
1140
  DESTDIR=${HERE} ./configure --build=x86_64-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
  DESTDIR=${HERE} ./configure --build=x86_64-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=x86_64-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so
1239
1240
1241
1242
1243
1244
1245

1246
1247
1248
1249
1250
1251
1252
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1272
1273
1274
1275
1276
1277
1278


1279
1280
1281
1282
1283
1284
1285
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-macosx.sh.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint tcl-augeas"
SUBDIRS="${SUBDIRS} snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint tcl-augeas"
SUBDIRS="${SUBDIRS} snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1122
1123
1124
1125
1126
1127
1128
















1129
1130
1131
1132
1133
1134
1135
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/macosx --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/macosx --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} LDFLAGS="-Wl,-undefined,dynamic_lookup -Wl,-flat_namespace" \
    ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/macosx --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so
1228
1229
1230
1231
1232
1233
1234

1235
1236
1237
1238
1239
1240
1241
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1261
1262
1263
1264
1265
1266
1267


1268
1269
1270
1271
1272
1273
1274
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-wayland.sh.

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk v4l2"
SUBDIRS="${SUBDIRS} tkhtml dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1104
1105
1106
1107
1108
1109
1110















1111
1112
1113
1114
1115
1116
1117
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/sdl2wish* ${PFX_HERE}/lib/*/*.so
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1249
1250
1251
1252
1253
1254
1255


1256
1257
1258
1259
1260
1261
1262
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-win32.sh.

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} twapi tclwmf libdmtx ZBar zint snack tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} twapi tclwmf libdmtx ZBar zint snack tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086















1087
1088
1089
1090
1091
1092
1093

echo -n "build tclcsv ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tclcsv
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll







|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

echo -n "build tclcsv ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tclcsv
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=i386-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzink ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=i386-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll
1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1223
1224
1225
1226
1227
1228
1229


1230
1231
1232
1233
1234
1235
1236
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-undroidwish-win64.sh.

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} twapi tclwmf libdmtx ZBar zint snack tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl freetype SDL2 sdl2tk blt jpeg-turbo"
SUBDIRS="${SUBDIRS} 3dcanvas tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} twapi tclwmf libdmtx ZBar zint snack tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1068
1069
1070
1071
1072
1073
1074















1075
1076
1077
1078
1079
1080
1081
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzink ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --with-tk=${HERE}/sdl2tk/sdl \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll
1176
1177
1178
1179
1180
1181
1182

1183
1184
1185
1186
1187
1188
1189
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
  cp -rp ${PFX_HERE}/lib/tclepeg* assets
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo sdl2tk*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1211
1212
1213
1214
1215
1216
1217


1218
1219
1220
1221
1222
1223
1224
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-vanilla-freebsd.sh.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1089
1090
1091
1092
1093
1094
1095















1096
1097
1098
1099
1100
1101
1102
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/unix \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1236
1237
1238
1239
1240
1241
1242


1243
1244
1245
1246
1247
1248
1249
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-vanilla-generic.sh.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

if test "$(uname -o)" = "GNU/Linux" ; then
  case $(uname -m) in
    arm*)
      SUBDIRS="${SUBDIRS} piio"
      ;;
    aarch*)







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

if test "$(uname -o)" = "GNU/Linux" ; then
  case $(uname -m) in
    arm*)
      SUBDIRS="${SUBDIRS} piio"
      ;;
    aarch*)
1097
1098
1099
1100
1101
1102
1103















1104
1105
1106
1107
1108
1109
1110
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/unix \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so
1214
1215
1216
1217
1218
1219
1220

1221
1222
1223
1224
1225
1226
1227
    cp -rp ${PFX_HERE}/lib/piio* assets
  fi
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
    cp -rp ${PFX_HERE}/lib/piio* assets
  fi
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1247
1248
1249
1250
1251
1252
1253


1254
1255
1256
1257
1258
1259
1260
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-vanilla-illumos.sh.

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1072
1073
1074
1075
1076
1077
1078















1079
1080
1081
1082
1083
1084
1085
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/unix \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so
1180
1181
1182
1183
1184
1185
1186

1187
1188
1189
1190
1191
1192
1193
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1213
1214
1215
1216
1217
1218
1219


1220
1221
1222
1223
1224
1225
1226
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-vanilla-linux32.sh.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1085
1086
1087
1088
1089
1090
1091















1092
1093
1094
1095
1096
1097
1098
  DESTDIR=${HERE} ./configure --build=i586-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  DESTDIR=${HERE} ./configure --build=i586-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=i586-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/unix \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1232
1233
1234
1235
1236
1237
1238


1239
1240
1241
1242
1243
1244
1245
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-vanilla-linux64.sh.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk v4l2 tkhtml"
SUBDIRS="${SUBDIRS} dbus-tcl dbus-intf tclx libdmtx ZBar zint"
SUBDIRS="${SUBDIRS} tcl-augeas tktray snack tkvnc tksvg VecTcl tclral"
SUBDIRS="${SUBDIRS} tclepeg tcluvc xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1085
1086
1087
1088
1089
1090
1091















1092
1093
1094
1095
1096
1097
1098
  DESTDIR=${HERE} ./configure --build=x86_64-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  DESTDIR=${HERE} ./configure --build=x86_64-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzinc ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=x86_64-linux-gnu --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/unix --with-tk=${HERE}/sdl2tk/unix \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/tclsh* ${PFX_HERE}/bin/wish* ${PFX_HERE}/lib/*/*.so
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1232
1233
1234
1235
1236
1237
1238


1239
1240
1241
1242
1243
1244
1245
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-vanilla-win32.sh.

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk tkhtml twapi"
SUBDIRS="${SUBDIRS} tclwmf libdmtx ZBar zint snack winico tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk tkhtml twapi"
SUBDIRS="${SUBDIRS} tclwmf libdmtx ZBar zint snack winico tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056















1057
1058
1059
1060
1061
1062
1063

echo -n "build tclcsv ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tclcsv
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll







|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078

echo -n "build tclcsv ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tclcsv
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=i386-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzink ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=i386-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --with-tk=${HERE}/sdl2tk/win \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll
1161
1162
1163
1164
1165
1166
1167

1168
1169
1170
1171
1172
1173
1174
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1196
1197
1198
1199
1200
1201
1202


1203
1204
1205
1206
1207
1208
1209
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi

Changes to undroid/build-vanilla-win64.sh.

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk tkhtml twapi"
SUBDIRS="${SUBDIRS} tclwmf libdmtx ZBar zint snack winico tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {







|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
fi

SUBDIRS="tcl libressl zlib curl tcludp tdom tclvfs tclkit trofs tbcload tls"
SUBDIRS="${SUBDIRS} Memchan TclCurl sdl2tk blt jpeg-turbo 3dcanvas"
SUBDIRS="${SUBDIRS} tkimg trf tktable tktreectrl tkpath itk tkhtml twapi"
SUBDIRS="${SUBDIRS} tclwmf libdmtx ZBar zint snack winico tkvnc tksvg"
SUBDIRS="${SUBDIRS} VecTcl tclral tclepeg xotcl nsf vu rl_json tkdnd mpexpr"
SUBDIRS="${SUBDIRS} tclcsv tkzinc"

ACTION="$1"
if test -z "$ACTION" ; then
  ACTION=build
fi

clean_build_stamps() {
1038
1039
1040
1041
1042
1043
1044















1045
1046
1047
1048
1049
1050
1051
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail
















echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --enable-threads || exit 1
  make || exit 1
  make install DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "build tkzink ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  cd tkzinc
  test -e build-stamp && echo >&3 "already done" && exit 0
  DESTDIR=${HERE} ./configure --build=x86_64-windows-mingw32 --prefix=${PFX} \
    --with-tcl=${HERE}/tcl/win --with-tk=${HERE}/sdl2tk/win \
    --enable-threads --disable-shape --enable-gl || exit 1
  make package || exit 1
  make install-package install-demos DESTDIR=${HERE} || exit 1
  touch build-stamp
  echo >&3 "done"
) || fail

echo -n "strip binaries ... "
(
  exec 3>&1
  exec >> build.log 2>&1
  set -x
  $STRIP ${PFX_HERE}/bin/*.exe ${PFX_HERE}/lib/*/*.dll
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets

  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'







>







1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
  cp -rp ${PFX_HERE}/lib/xotcl* assets
  cp -rp ${PFX_HERE}/lib/nsf* assets
  cp -rp ${PFX_HERE}/lib/vu* assets
  cp -rp ${PFX_HERE}/lib/rl_json* assets
  cp -rp ${PFX_HERE}/lib/tkdnd* assets
  cp -rp ${PFX_HERE}/lib/Mpexpr* assets
  cp -rp ${PFX_HERE}/lib/tclcsv* assets
  cp -rp ${PFX_HERE}/lib/Tkzinc* assets
  # add shortcuts providing builtin:widget, builtin:tksqlite, etc.
  (
    cd assets
    echo > widget \
      'source [file dirname [info script]]/'$(echo tk8*)'/demos/widget'
    echo > tksqlite \
      'source [file dirname [info script]]/'$(echo tksqlite*)'/tksqlite.tcl'
1184
1185
1186
1187
1188
1189
1190


1191
1192
1193
1194
1195
1196
1197
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)


  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi







>
>







1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
      'source [file dirname [info script]]/'$(echo vnc*)'/vncviewer.tcl'
    echo > vectclab \
      'source [file dirname [info script]]/'$(echo VecTcLab*)'/vectclab.tcl'
    echo > tkmc \
      'source [file dirname [info script]]/'$(echo TkMC*)'/tkmc.tcl'
    echo > helpviewer \
      'source [file dirname [info script]]/'$(echo helpviewer*/main.tcl)
    echo > zinc-widget \
      'source [file dirname [info script]]/'$(echo Tkzinc*/demos/zinc-widget)
  )
  # add tkchat
  if test -d ${AWDIR}/tkchat/assets ; then
    cp -rp ${AWDIR}/tkchat/assets/app assets/tkchat-app
    echo > assets/tkchat \
      'source [file dirname [info script]]/tkchat-app/main.tcl'
  fi