pax_global_header00006660000000000000000000000064130604651530014515gustar00rootroot0000000000000052 comment=1cc8f765d1598a545b67b03d8d0a7bfe4a65572e mlpost-0.8.2/000077500000000000000000000000001306046515300130425ustar00rootroot00000000000000mlpost-0.8.2/.bzrignore000066400000000000000000000010361306046515300150440ustar00rootroot00000000000000test/*tex test/*mp test/*mpx test/*log test/*aux test/*dvi test/*ps test/tests.[0-9]* test/othergraphs.[0-9]* test/testmanual.[0-9]* examples/*tex examples/*mp examples/*mpx examples/*log examples/*aux examples/*dvi examples/*ps examples/*cm[io] examples/*.ml.html examples/*png examples/index.html test/manual/*log test/manual/*mpx test/manual/*.[0-9]* test/othergraphs/*log test/othergraphs/*mpx test/othergraphs/*.[0-9]* *.cm[oxia] *.cmxa *.annot tool.ml *.opt version.ml config.log config.status configure Makefile .depend autom4te.cache mlpost-0.8.2/.gitignore000066400000000000000000000010251306046515300150300ustar00rootroot00000000000000META Makefile _build/ _build_dot _build_lablgtk autom4te.cache/ config.log config.status configure mlpost.mli myocamlbuild.ml ocamlbuild.Makefile simple.Makefile version.ml doc examples/*.mps test/*.mps test/*.mp test/*.ps test/*.mpx test/*.tex test/*.log test/*.aux test/*.pdf test/*.dvi test/*.[0-9]* test/othergraphs/*.[0-9]* test/othergraphs/*.mpx test/othergraphs/*.mps test/othergraphs/*.log test/manual/*.[0-9]* test/manual/*.mpx test/manual/*.mps test/manual/*.log www/*.html www/version.prehtml *.native \#*\# .#* _mlpost.* mlpost-0.8.2/AUTHORS000066400000000000000000000002511306046515300141100ustar00rootroot00000000000000Main Developers: Jean-Christophe Filliâtre Johannes Kanig Stéphane Lescuyer Contributors: Romain Bardou Claude Marché Florence Plateau François Bobot mlpost-0.8.2/CHANGES000066400000000000000000000144271306046515300140450ustar00rootroot00000000000000o - changes in behaviour, new features, bugfixes * - incompatible changes in the interface version 0.8.2, March 10, 2017 ----------------------------- o mlpost does not complain anymore about Metapost errors o ocamlopt is called with warning 58 disabled o fixed installation with OCaml 4.04 o new module [Triangle] to draw tree-like, triangular shapes * (internal) Misc.call_cmd now does print output of the called program directly, instead of returning it as a string * module Generate has been removed version 0.8.1, April 26th 2010 ------------------------------ o configure: store absolute paths of programs o configure: fixed META file o doc: documentation for contribs o contrib lablgtk: background setting possible and function auto_aspect version 0.8.0, April 13th, 2010 ------------------------------- * ocaml >= 3.10.1 is required now * externalimage work only with png image * module Color: the definitions of the following colors have changed: lightblue, green, lightgreen, orange, lightcyan, purple, lightyellow These colors are now compatible to HTML/CSS and X11 definitions * Box: Box.tabularl did modify the input boxes, now it leaves them unchanged (reported by Julien Signoles) o contrib Mlpost_lablgtk : define a gtk widget to display mlpost figures It also allow to easily create an interface to interact with an mlpost figures o contrib Mlpost_dot : Use graphviz (dot) to place picture, box, ... make contrib && make install-contrib mlpost -contrib dot [...] o module Real_plot: Plot function from float to float. It can use logarithmic scale. o module Color: new function hsv to create a color from hsv colorspace and color_gen to generate different colors using hsv colorspace o concrete computations are now available without the Cairo library o option -ps with -cairo o adding Concrete.baseline o Num: new units em, ex o Bugfix: "make install" with ocamlfind (reported by Julien Signoles) o Bugfix: Concrete does not complain about being unsupported for the following functions: set_verbosity; set_prelude, set_prelude2, set_t1disasm o Bugfix: Don't use "tracingchoices" o Bugfix #411: correct definition of objects used in Path.subpath o metapost errors are printed (this should rarely occur) o each call of mpost are done in separate and temporary directories version 0.7.4, October 20th, 2009 -------------------------------- o Mlpost tool : Fix compilation with ocamlbuild version 0.7.3, October 13th, 2009 -------------------------------- o Fix installation without ocamlfind and without ocamlbuild version 0.7.2, October 9th, 2009 -------------------------------- * -classic-display is not an option of mlpost tool anymore (use -v instead) * Change in the signature of Cairost.emit_cairo o Fix the -compile-name option with ocamlbuild o ocamlfind remove/install is used if ocamlfind is present o The backend Concrete output informations only with the verbose option o Radar: fixed size of bullets o Helpers: the functions for boxes have a new optional argument [within] to give a box in which the arguments will be searched o Box: new functions [set_{post,pre}_draw] * Box: [get_name] now returns a string option o Tree.Simple: alignment options for [node] o Box: optional argument dash version 0.7.1, July 24th, 2009 ------------------------------ o Fix for Performance bug when shifting boxes version 0.7, July 23rd, 2009 ---------------------------- * add Point.draw and Path.draw (alias of Command.draw) which can mask Command.draw in case of an open Point after an open Command * Command.draw_arrow becomes Arrow.simple * Arrow.draw: ~pos becomes ~anchor, new ~pos is point on path * Arrow.draw: now gives the same result by default as Arrow.simple (former Command.draw_arrow) * Arrow.draw2 becomes Arrow.point_to_point * Mlpost tool: -pdf now the default; use -ps to produce .1 files * Mlpost tool: erases all generated intermediate files on success o New experimental backend using Cairo; it permits output in PS, PDF, SVG and X11; use it with commandline option -cairo. It is intended to deliver the same results as the old metapost backend. Please send a bug report if it is not the case o A module Concrete which permits to compute concrete values of mlpost objects, e.g. the float value corresponding to an object of type Num.t , the concrete point { x : float; y : float } corresponding to a Point.t, and so on o A better tree drawing algorithm (module Tree) o new function Tree.nodel to add labels to tree edges o "Smart" paths to construct a path by giving only a sequence of directions (module Path) o Histograms and Radar diagrams (modules Hist and Radar) o The type Picture.t now is equal to the type Command.t (no more conversion needed) o module Box: each box has a name by default; use Box.sub to retrieve a box with the same name inside another o New optional argument sep of Path.strip to strip both ends of a path; used in Tree, Box.cpath, and Helpers o New position constructors `North, `South, `Upperleft to improve upon `Top, `Bot etc, but the old variants are still there version 0.6, February 4th, 2009 ------------------------------- * "open Mlpost" is not added to input files any more - users have to add by themselves * the type Command.figure becomes Command.t o inclusion of external images (png, jpg etc) o transformations on boxes o Box.{grid,gridl,gridi}: new options hpadding, vpadding, stroke, pen o additional options for many functions o corrections of some small bugs in box calculations o A function in the API to scan a TeX file for the prelude version 0.5, Octobre 20, 2008 (first public release) ---------------------------------------------------- o new option -native to use native compilation, useful for complicated pictures version 0.3 ----------- o new module Pos to place lists, arrays, trees * Num.f function removed o new commandline arguments -v, -eps * The functions in the Shapes module now build objects of type Shapes.t instead of Path.t * In Diag, one can now specify more (and different) types of boxes for nodes version 0.2, July 22nd, 2008 ---------------------------- o Box: no more use of boxes.mp, replaced by Ocaml code o License: LGPL updated to version 2.1 o Num: t is now an abstract datatype o Moved repository to a trunk/branches style o Subversion repository updated to schema version 5 version 0.1 ----------- o first release of Mlpost mlpost-0.8.2/FAQ000066400000000000000000000032131306046515300133730ustar00rootroot00000000000000Frequently Asked Questions about Mlpost ------------------------------------------------------------------------------ 1) When I run the mlpost tool on my figure, I get the error "! Unable to make mpx file.". Answer: This is a cryptical error message from metapost saying that there is some error in the Latex code that is part of your figure. However, it often points to some random Latex code, so you will have to figure out the problem by yourself, or by looking at the "mpxerr.tex" file that has been generated. You can also try to pass the "mpxerr.tex" file to latex to see which is the exact latex error message. ------------------------------------------------------------------------------ 2) When I look at generated "foo.1" or "foo.mps" file, gv/evince does not display the figure correctly / gives some error. Answer: These generated files are not proper PostScript files. They need to be included in a Latex file using \includegraphics. If you pass the -eps option to mlpost, it generates encapsulated PostScript files that can be viewed with a PostScript viewer like gv. However, font rendering may be quite different. ------------------------------------------------------------------------------ 3) In my Latex prelude I include other Latex files using "\input{foo.tex}". When I compile my figure with mlpost, these files are not found. You are probably compiling your figure and your Latex file in different directories. You can make the file "foo.tex" visible to Latex changing the environment variable $TEXINPUTS to contain the directory where "foo.tex" lives. ------------------------------------------------------------------------------ mlpost-0.8.2/INSTALL000066400000000000000000000035361306046515300141020ustar00rootroot00000000000000Dependencies: * You need OCaml 4.0 or higher to compile Mlpost. * You need Ocamlfind * You need the libraries bitstring, lablgtk2 and cairo for cairo support. Check the output of ./configure to see if cairo has been selected. * To use Mlpost, you need metapost and metafun (packages texlive-metapost and context in debian) if you don't use the -mps option. * For the html version of the examples, you need caml2html, version 1.3.0 or higher. * One example needs the tex chess fonts to work (package tex-chess in debian) * For external images, you need imagemagick * For the contrib package Mlpost_dot you need Objective Caml 3.10.2 or higher and dot (graphviz) at runtime 1. Configure with ./configure If you want to specify the directory where libraries (cmi, cma, ...) will be installed: ./configure LIBDIR=/your/libdir If you want to specify the directory where the binary (mlpost) will be installed: ./configure --bindir=/your/bindir 2. Compile with make 3. Install (as root) with make install It installs the library in Ocaml's standard library and the tool "mlpost" in /usr/local/bin (or any other directory specified with ./configure --bindir). 4 (optional) Compile the contrib librairies make contrib 5 (optional) Install the contrib librairies make install-contrib 6 (optional) copy the files from the latex subdirectory at a place where latex can find it (see the README in that directory) 7 (optional). Create the documentation in doc/ with make doc and the examples in examples/ with make -C examples and (optional) the contrib examples after installing the contrib librairies make -C examples contrib To create html versions of the examples, you need caml2html version 1.3.0; you can then issue make -C examples html mlpost-0.8.2/LICENSE000066400000000000000000000656161306046515300140650ustar00rootroot00000000000000The Library is distributed under the terms of the GNU Library General Public License version 2.1 (included below). As a special exception to the GNU Library General Public License, you may link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Library General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Library General Public License. ====================================================================== 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 How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! mlpost-0.8.2/META.in000066400000000000000000000005631306046515300141240ustar00rootroot00000000000000description = "OCaml interface to Mlpost" version = "@PACKAGE_VERSION@" archive(byte) = "mlpost.cma" archive(native) = "mlpost.cmxa" requires = "@METAREQUIRESPACKAGE@" package "options" ( version = "@PACKAGE_VERSION@" requires = "mlpost" archive(byte) = "mlpost_desc_options.cma mlpost_options.cma" archive(native) = "mlpost_desc_options.cmxa mlpost_options.cmxa" ) mlpost-0.8.2/Makefile.in000066400000000000000000000205151306046515300151120ustar00rootroot00000000000000########################################################################## # # # Copyright (C) Johannes Kanig, Stephane Lescuyer # # Jean-Christophe Filliatre, Romain Bardou and Francois Bobot # # # # This software is free software; you can redistribute it and/or # # modify it under the terms of the GNU Library General Public # # License version 2.1, with the special exception on linking # # described in file LICENSE. # # # # This software 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. # # # ########################################################################## #common variables set by configure script ############################################ # where to install the binaries prefix=@prefix@ datarootdir = @datarootdir@ datadir = @datadir@ exec_prefix=@exec_prefix@ BINDIR=@bindir@ LIBDIR=@LIBDIR@ OCAMLFIND=@OCAMLFIND@ OCAMLBUILDBIN=@OCAMLBUILD@ # where to install the man page MANDIR=@mandir@ PSVIEWER=@PSVIEWER@ PDFVIEWER=@PDFVIEWER@ # other variables set by ./configure OCAMLC = @OCAMLC@ OCAMLOPT = @OCAMLOPT@ OCAMLDEP = @OCAMLDEP@ OCAMLLEX = @OCAMLLEX@ OCAMLYACC= @OCAMLYACC@ #(not used) OCAMLLIB = @OCAMLLIB@ OCAMLBEST= @OCAMLBEST@ OCAMLVERSION = @OCAMLVERSION@ OCAMLWEB = @OCAMLWEB@ OCAMLWIN32 = @OCAMLWIN32@ EXE = @EXE@ LIBEXT = @LIBEXT@ OBJEXT = @OBJEXT@ TAGS = @TAGS@ INCLUDES = -I gui -I +threads @INCLUDEGTK2@ BFLAGS = -dtypes $(INCLUDES) OFLAGS = -g -dtypes $(INCLUDES) -for-pack Mlpost LABLGTK2 = @LABLGTK2@ LABLGTK2LIB = @LABLGTK2LIB@ CAIROLABLGTK2 = @CAIROLABLGTK2@ CAIROLABLGTK2LIB = @CAIROLABLGTK2LIB@ # main target ############# NAME = mlpost MLPOSTVERSION=@PACKAGE_VERSION@ # decide which Makefile to use include ocamlbuild.Makefile # common part of both Makefiles ################################## # misc ###### dep: $(OCAMLDEP) *.mli *.ml | ocamldot | dot -Tps | $(PSVIEWER) - wc: ocamlwc *.ml* backend/*.ml* -p man: nroff -Tascii -mandoc mlpost.1 | less # headers ######### headers: headache -c headache_config.txt -h header.txt \ *.in README.txt *.mli *.ml *.mll backend/*.ml backend/*.ml[iyl] ./config.status # installation ############## install: install-$(OCAMLBEST) install-bin install-contrib : install-$(OCAMLBEST)-contrib install-byte-contrib: install-byte-dot install-byte-lablgtk install-opt-contrib: install-opt-dot install-opt-lablgtk BCMA = $(addprefix $(BUILD), $(CMA) $(DLL)) BCMXA = $(addprefix $(BUILD), $(CMXA) $(OBJ)) BCMT = $(addprefix $(BUILD), mlpost.cmti mlpost.cmt) DESTDIR=-destdir $(LIBDIR:/mlpost=) install-byte: $(OCAMLFIND) remove $(DESTDIR) mlpost $(OCAMLFIND) install $(DESTDIR) mlpost $(BUILD)mlpost.cmi META $(BCMA) $(BCMT) install-opt: $(OCAMLFIND) remove $(DESTDIR) mlpost $(OCAMLFIND) install $(DESTDIR) mlpost $(BUILD)mlpost$(LIBEXT) $(BUILD)mlpost.cmi META $(BCMXA) $(BCMA) $(BCMT) install-byte-dot: $(OCAMLFIND) remove $(DESTDIR) mlpost_dot $(OCAMLFIND) install $(DESTDIR) mlpost_dot contrib/dot/META \ $(addprefix contrib/dot/_build/mlpost_dot,.cmi .cma .cmt .cmti) install-opt-dot: $(OCAMLFIND) remove $(DESTDIR) mlpost_dot $(OCAMLFIND) install $(DESTDIR) mlpost_dot contrib/dot/META \ $(addprefix contrib/dot/_build/mlpost_dot,.cmi .cma .cmxa $(LIBEXT) .cmt .cmti) ifeq "$(LABLGTK2)$(CAIROLABLGTK2)" "yesyes" install-byte-lablgtk: $(OCAMLFIND) remove $(DESTDIR) mlpost_lablgtk $(OCAMLFIND) install $(DESTDIR) mlpost_lablgtk contrib/lablgtk/META \ $(addprefix contrib/lablgtk/_build/mlpost_lablgtk,.cmi .cma .cmt .cmti) install-opt-lablgtk: $(OCAMLFIND) remove $(DESTDIR) mlpost_lablgtk $(OCAMLFIND) install $(DESTDIR) mlpost_lablgtk contrib/lablgtk/META \ $(addprefix contrib/lablgtk/_build/mlpost_lablgtk,.cmi .cma .cmxa $(LIBEXT) .cmt .cmti) else install-byte-lablgtk: install-opt-lablgtk: endif install-byte-contrib: install-byte-dot install-byte-lablgtk install-bin: mkdir -p $(BINDIR) $(MANDIR)/man1 cp -f $(BUILD)$(TOOL) $(BINDIR)/mlpost cp -f mlpost.1 $(MANDIR)/man1 uninstall: uninstall-contrib $(OCAMLFIND) remove $(DESTDIR) mlpost rm -f $(BINDIR)/mlpost rm -f $(MANDIR)/mlpost uninstall-contrib: $(OCAMLFIND) remove $(DESTDIR) mlpost_dot $(OCAMLFIND) remove $(DESTDIR) mlpost_lablgtk # export ######## EXPORTDIR=$(NAME)-$(MLPOSTVERSION) TAR=$(EXPORTDIR).tar WWW = /users/www-perso/projets/mlpost FTP = $(WWW)/download FILES := $(wildcard *.ml) $(wildcard *.mli) $(wildcard *.mll) \ $(wildcard *.in) configure README.txt INSTALL LICENSE CHANGES FAQ \ mlpost.1 _tags *.mlpack mlpost_yeslablgtk.odocl mlpost_nolablgtk.odocl ocamlbuild.Makefile BACKENDFILES = backend/*ml backend/*mli backend/_tags DVIFILES = dvi/*mly dvi/*mll dvi/*ml dvi/*mli dvi/_tags CONCRETEFILES = concrete/*ml concrete/*mli concrete/_tags GENERATEDSOURCEFILES = version.ml myocamlbuild.ml $(GENERATED) GUIFILES = gui/*.mll gui/*.ml gui/_tags EXFILES = examples/Makefile examples/*.ml examples/all.template\ examples/index.html examples/parse.mll examples/README\ examples/prototype.js examples/style.css \ examples/powered-by-caml.128x58.png CONTRIBDOTFILES = $(addprefix contrib/dot/, dot.ml dot.mli Makefile META mlpost_dot.mli mlpost_dot.mlpack _tags xdot_ast.mli xdot_lexer.mll xdot_parser.mly) CONTRIBLABLGTKFILES = $(addprefix contrib/lablgtk/, META mlpost_lablgtk.ml mlpost_lablgtk.mli) CUSTOMDOCFILES = customdoc/all.template customdoc/img_doc.ml customdoc/img.ml \ customdoc/Makefile customdoc/_tags LATEXFILES = latex/*sty latex/*tex latex/README export: export-source export-www export-examples export-doc cp README.txt INSTALL LICENSE CHANGES FAQ $(FTP) export-source: source cp export/$(TAR).gz $(FTP) source: mkdir -p export/$(EXPORTDIR) cp $(filter-out $(GENERATEDSOURCEFILES), $(FILES)) export/$(EXPORTDIR) mkdir -p export/$(EXPORTDIR)/backend cp $(BACKENDFILES) export/$(EXPORTDIR)/backend mkdir -p export/$(EXPORTDIR)/dvi cp $(DVIFILES) export/$(EXPORTDIR)/dvi mkdir -p export/$(EXPORTDIR)/concrete cp $(CONCRETEFILES) export/$(EXPORTDIR)/concrete mkdir -p export/$(EXPORTDIR)/gui cp $(GUIFILES) export/$(EXPORTDIR)/gui mkdir -p export/$(EXPORTDIR)/examples cp $(EXFILES) export/$(EXPORTDIR)/examples mkdir -p export/$(EXPORTDIR)/customdoc cp $(CUSTOMDOCFILES) export/$(EXPORTDIR)/customdoc mkdir -p export/$(EXPORTDIR)/latex cp $(LATEXFILES) export/$(EXPORTDIR)/latex mkdir -p export/$(EXPORTDIR)/contrib/dot mkdir -p export/$(EXPORTDIR)/contrib/lablgtk cp $(CONTRIBDOTFILES) export/$(EXPORTDIR)/contrib/dot cp $(CONTRIBLABLGTKFILES) export/$(EXPORTDIR)/contrib/lablgtk cd export ; tar cf $(TAR) $(EXPORTDIR) ; gzip -f --best $(TAR) DOCFILES:=$(shell echo *.mli) DOCFILES:=$(filter-out types.mli, $(DOCFILES)) export-doc: doc mkdir -p $(WWW)/doc/img cp doc/*.html doc/style.css $(WWW)/doc cp doc/img/*.png $(WWW)/doc/img export-www: www/version.prehtml make -C www www/version.prehtml: Makefile echo "<#def version>$(MLPOSTVERSION)" > www/version.prehtml export-examples: $(MAKEEXAMPLES) cp -f --parents examples/*.png examples/*.html examples/*.svg examples/prototype.js examples/style.css $(WWW) # Emacs tags ############ tags: find . -name "*.ml*" | sort -r | xargs \ etags "--regex=/let[ \t]+\([^ \t]+\)/\1/" \ "--regex=/let[ \t]+rec[ \t]+\([^ \t]+\)/\1/" \ "--regex=/and[ \t]+\([^ \t]+\)/\1/" \ "--regex=/type[ \t]+\([^ \t]+\)/\1/" \ "--regex=/exception[ \t]+\([^ \t]+\)/\1/" \ "--regex=/val[ \t]+\([^ \t]+\)/\1/" \ "--regex=/module[ \t]+\([^ \t]+\)/\1/" .PHONY: ocamlwizard ocamlwizard: ocamlrun -bt ocamlwizard compile types.mli $(CMO:.cmo=.ml) mlpost.mli # Makefile is rebuilt whenever Makefile.in or configure.in is modified ###################################################################### Makefile META version.ml myocamlbuild.ml: Makefile.in META.in version.ml.in config.status myocamlbuild.ml.in ./config.status chmod a-w myocamlbuild.ml META Makefile version.ml config.status: configure ./config.status --recheck configure: configure.in autoconf mlpost-0.8.2/README.txt000066400000000000000000000053521306046515300145450ustar00rootroot00000000000000************************************************************************** * * * Copyright (C) Johannes Kanig, Stephane Lescuyer * * Jean-Christophe Filliatre, Romain Bardou and Francois Bobot * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License version 2.1, with the special exception on linking * * described in file LICENSE. * * * * This software 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. * * * ************************************************************************** This is MLPost ! Usage: ------ * Open the Mlpost pack: open Mlpost * Define your figures in an Ocaml file fig.ml let fig_a = ... let fig_b = ... Each figure has type Command.t. * Add some code to emit Metapost code, as follows let () = Metapost.emit "file_a" fig_a let () = Metapost.emit "file_b" fig_b * Then run the mlpost program on this file mlpost fig.ml It will create PostScript figures in files file_a.1, file_b.1, etc. Options: -------- mlpost supports the following options: -pdf creates .mps files instead of .1, for inclusion in LaTeX files compiled with pdflatex (the PostScript file is actually the same, but the suffix is used by pdflatex to identify PostScript produced by Metapost) -latex main.tex indicates the main LaTeX file, from which the prelude is extracted to be passed to Metapost (this way you can use macros, fonts and packages from your LaTeX document in your figures). -xpdf opens an xpdf viewer with the generated figure. Subsequent calls with the option -xpdf will refresh the viewer, if it is still open. -native compile to native code. This is usually faster. -eps produce standalone postscript files -ocamlbuild use ocamlbuild to compile the source; this may be useful it there are a lot of dependencies -ccopt pass options to the ocaml compiler -execopt pass options to the compiled program Cairo output: ------------- The following functions are not supported in combination with the Concrete / Cairo modules: * Path.build_cycle * Pen.square * Pen.from_path mlpost-0.8.2/TODO000066400000000000000000000030661306046515300135370ustar00rootroot000000000000001) BUGS (des erreurs ou des TODOs trs importantes) ========== * installation des fichiers Latex pour inclusion d'images * images et sortie postscript ? * Probleme d'alignement avec slideshow + externalimage 2) TODO (amliorer du comportement interne, doc, des bugs pas trs importants) ============ * ranger le module Helpers * les fonctions de scale : pourquoi prennent-elles des Num.t, et non pas de float ? * Box.group, align etc prennent des listes, Box.elts renvoie un tableau ? 3) FEATURES (choses qui n'existent pas encore dans mlpost) =========================== * refaire Diag : - pouvoir mettre n'importe quelle bote - pouvoir choisir les flches - interface fonctionelle - le supprimer en fait ? indiquer "deprecated" au dessus ? * Box : - foncteur WithBox pour faciliter l'accs aux botes nommes - clipping * Arrow : - rajouter draw_box_box, draw_point_box, draw_box_point ou d'autres noms * fusionner Picture et Box ?? * TODO BACKEND - build-cycle - Transformations sur les pens ------------------------------------------------------------------------------- des liens avec des exemples : http://tex.loria.fr/prod-graph/zoonekynd/metapost/metapost.html http://melusine.eu.org/syracuse/metapost/cheno/illustrations/illustrations.html http://melusine.eu.org/syracuse/metapost/mpman/ http://www.cs.ucc.ie/~dongen/mpost/mpost.html http://www.ursoswald.ch/metapost/tutorial.pdf http://remote.science.uva.nl/~heck/Courses/mptut.pdf (* ceci est metafun (metapost plus des macros) *) http://www.pragma-ade.com/general/manuals/metafun-p.pdf mlpost-0.8.2/_tags000066400000000000000000000013671306046515300140710ustar00rootroot00000000000000<*.cmx> and not and not and not : for-pack(Mlpost) : linkall : pkg_cairo or : pkg_cairo : use_unix : syntax_mymacroparser or : syntax_macro : use_unix, pkg_bitstring, pkg_cairo, use_cairo_bigarray : use_unix, pkg_bitstring, pkg_cairo, use_cairo_bigarray : use_unix, pkg_bitstring, pkg_cairo, use_cairo_bigarray : include : syntax_macro, pkg_cairo : syntax_macro, pkg_cairo : use_freetype, use_libmlpost_ft : use_freetype, use_libmlpost_ft, pkg_cairo, I(backend) mlpost-0.8.2/alphafill.mp000066400000000000000000000024421306046515300153360ustar00rootroot00000000000000% taken from http://wwwmathlabo.univ-poitiers.fr/~phan/metalpha.html % picture alphapict_; alphapict_=nullpicture; color fillcolor; fillcolor=red; fgalpha := 0.5; % usual alpha parameter bgalpha:= 1; % alpha parameter with respect to the background vardef alphafill expr c = alphapict_ := nullpicture; alphafill_(currentpicture, c); addto currentpicture also alphapict_; enddef; def alphafill_(expr p, c) = begingroup save p_, xmax_, xmin_, ymax_, ymin_; picture p_; p_ = nullpicture; (xmin_, ymin_) = llcorner c; (xmax_, ymax_) = urcorner c; addto p_ contour c withcolor bgalpha[background, fillcolor]; for p__ within p: numeric xmin__, xmax__, ymin__, ymax__; (xmin__, ymin__) = llcorner p__; (xmax__, ymax__) = urcorner p__; if (xmax__<= xmin_) or (xmin__ >= xmax_): else: if (ymax__<= ymin_) or (ymin__ >= ymax_): else: if (not clipped p__) and (not bounded p__): addto p_ also p__ withcolor fgalpha[(redpart p__, greenpart p__, bluepart p__), fillcolor]; else: begingroup save alphapict_; picture alphapict_; alphapict_ = nullpicture; alphafill_(p__, pathpart p__); addto p_ also alphapict_; endgroup; fi fi fi endfor clip p_ to c; addto alphapict_ also p_; endgroup; enddef; mlpost-0.8.2/arrow.ml000066400000000000000000000235441306046515300145360ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Path (* Extended arrows. *) let normalize = Point.normalize let neg = Point.scale (Num.bp (-1.)) let direction_on_path f p = Path.direction (f *. Path.length p) p let point_on_path f p = Path.point (f *. Path.length p) p let subpath_01 f t p = let l = Path.length p in Path.subpath (f *. l) (t *. l) p (* Atoms *) type line = { brush : Types.brush; from_point: float; to_point: float; dist: Num.t; } type head_description = { hd_command: Command.t; hd_cut: Types.path option; } let make_head ?cut command = { hd_command = command; hd_cut = cut; } type head = Point.t -> Point.t -> head_description type belt = { clip: bool; rev: bool; point: float; head: head; } type kind = { lines: line list; belts: belt list; } let empty = { lines = []; belts = []; } let add_line ?brush ?dashed ?color ?pen ?(from_point = 0.) ?(to_point = 1.) ?(dist = Num.bp 0.) kind = let brush = Types.mkBrushOpt brush color pen dashed in { kind with lines = { brush = brush; from_point = from_point; to_point = to_point; dist = dist; } :: kind.lines } let head_classic_points ?(angle = 60.) ?(size = Num.bp 4.) p dir = let dir = Point.scale size dir in let dir_a = neg (Point.rotate (angle /. 2.) dir) in let dir_b = neg (Point.rotate (-. angle /. 2.) dir) in let a = Point.add p dir_a in let b = Point.add p dir_b in a, b let head_classic ?color ?brush ?pen ?dashed ?angle ?size p dir = let a, b = head_classic_points ?angle ?size p dir in let path = Path.pathp ~style: Path.jLine [a; p; b] in make_head ~cut: path (Command.draw ?color ?brush ?pen ?dashed path) let head_triangle ?color ?brush ?pen ?dashed ?angle ?size p dir = let a, b = head_classic_points ?angle ?size p dir in let path = Path.pathp ~style: Path.jLine ~cycle: Path.jLine [a; p; b] in let cut = Path.pathp ~style: Path.jLine [a; b] in make_head ~cut (Command.draw ?color ?brush ?pen ?dashed path) let head_triangle_full ?color ?angle ?size p dir = let a, b = head_classic_points ?angle ?size p dir in let path = Path.pathp ~style: Path.jLine ~cycle: Path.jLine [a; p; b] in let cut = Path.pathp ~style: Path.jLine [a; b] in make_head ~cut (Command.fill ?color path) let add_belt ?(clip = false) ?(rev = false) ?(point = 0.5) ?(head = fun x -> head_classic x) kind = { kind with belts = { clip = clip; rev = rev; point = point; head = head; } :: kind.belts } let add_head ?head kind = add_belt ~clip: true ~point: 1. ?head kind let add_foot ?head kind = add_belt ~clip: true ~rev: true ~point: 0. ?head kind let parallel_path path dist = (* TODO: true parallelism (right now its a bad approximation which only works well for straight arrows, or slightly curved arrow with a small dist) *) let d = direction_on_path 0.5 path in let d = Point.rotate 90. d in let d = normalize d in let d = Point.mult dist d in Path.shift d path (* Compute the path of a line along an arrow path. Return the line (unchanged) and the computed path. *) let make_arrow_line path line = let path = if line.from_point <> 0. || line.to_point <> 1. then subpath_01 line.from_point line.to_point path else path in let path = parallel_path path line.dist in line, path (* Compute the command and the clipping path of a belt along an arrow path. Return the belt (unchanged), the command and the clipping path. *) let make_arrow_belt path belt = let p = point_on_path belt.point path in let d = normalize (direction_on_path belt.point path) in let d = if belt.rev then neg d else d in let hd = belt.head p d in belt, hd.hd_command, hd.hd_cut (* Clip a line with a belt clipping path if needed. *) let clip_line_with_belt (line, line_path) (belt, _, clipping_path) = let cut = match belt.clip, clipping_path with | true, Some clipping_path -> (if belt.rev then Path.cut_before else Path.cut_after) clipping_path | false, _ | true, None -> fun x -> x in line, cut line_path (* Compute the command to draw a line. *) let draw_line (line, line_path) = Command.draw ~brush:line.brush line_path let classic = add_head (add_line empty) let triangle = add_head ~head: head_triangle (add_line empty) let triangle_full = add_head ~head: head_triangle_full (add_line empty) let implies = add_head (add_line ~dist: (Num.cm 0.035) (add_line ~dist: (Num.cm (-0.035)) empty)) let iff = add_foot implies let draw ?(kind = triangle_full) ?tex ?(pos = 0.5) ?anchor path = let lines, belts = kind.lines, kind.belts in let lines = List.map (make_arrow_line path) lines in let belts = List.map (make_arrow_belt path) belts in let lines = List.map (fun line -> List.fold_left clip_line_with_belt line belts) lines in let lines = List.map draw_line lines in let belts = List.map (fun (_, x, _) -> x) belts in let labels = match tex with | None -> [] | Some tex -> [Command.label ?pos: anchor (Picture.tex tex) (point_on_path pos path)] in Command.seq (lines @ belts @ labels) (* Instances *) type ('a,'b) arrow_from_to = ?kind: kind -> ?tex: string -> ?pos: float -> ?anchor: Command.position -> ?style:Path.joint -> ?outd: Path.direction -> ?ind: Path.direction -> ?sep:Num.t -> 'a -> 'b -> Command.t let point_to_point ?kind ?tex ?pos ?anchor ?style ?outd ?ind ?sep a b = let r, l = outd, ind in let path = (Path.pathk ?style [Path.knotp ?r a; Path.knotp ?l b]) in let path = match sep with | None -> path | Some n -> Path.strip n path in draw ?kind ?tex ?pos ?anchor path let box_to_box ?kind ?tex ?pos ?anchor ?style ?outd ?ind ?sep a b = draw ?kind ?tex ?pos ?anchor (Box.cpath ?style ?outd ?ind ?sep a b) let box_to_point ?kind ?tex ?pos ?anchor ?style ?outd ?ind ?sep a b = draw ?kind ?tex ?pos ?anchor (Box.cpath_left ?style ?outd ?ind ?sep a b) let point_to_box ?kind ?tex ?pos ?anchor ?style ?outd ?ind ?sep a b = draw ?kind ?tex ?pos ?anchor (Box.cpath_right ?style ?outd ?ind ?sep a b) (*******************************************************************************) (* To be sorted *) (*******************************************************************************) let simple_point_point ?style ?outd ?ind ?sep a b = let r,l = outd, ind in Box.strip ?sep (pathk ?style [knotp ?r a; knotp ?l b]) (*let normalize p = Point.scale (Num.divn (Num.bp 1.) (Point.length p)) p*) let neg = Point.scale (Num.bp (-1.)) let thick_path ?style ?outd ?ind ?(width = Num.bp 10.) ?(head_length = Num.multf 2. width) ?(head_width = head_length) a b = let path = simple_point_point ?style ?outd ?ind a b in let a_dir = normalize (Path.direction 0. path) in let a_normal = Point.rotate 90. a_dir in let a1 = Point.add (Point.scale (Num.divf width 2.) a_normal) a in let a2 = Point.add (Point.scale (Num.divf width (-2.)) a_normal) a in let b_dir = normalize (Path.direction 1. path) in let b_normal = Point.rotate 90. b_dir in let c = Point.add (Point.scale (Num.neg head_length) b_dir) b in let c1 = Point.add (Point.scale (Num.divf width 2.) b_normal) c in let c2 = Point.add (Point.scale (Num.divf width (-2.)) b_normal) c in let c1' = Point.add (Point.scale (Num.divf head_width 2.) b_normal) c in let c2' = Point.add (Point.scale (Num.divf head_width (-2.)) b_normal) c in (* let path_ac = simple ?style ?outd ?ind a c in let m = Path.point 0.5 path_ac in let m_dir = normalize (Path.direction 0.5 path_ac) in let m_dir2 = Point.scale (Num.bp 0.) m_dir in let m_normal = Point.rotate 90. m_dir in let m1 = Point.add (Point.scale (Num.divf width 2.) m_normal) m in let m2 = Point.add (Point.scale (Num.divf width (-2.)) m_normal) m in*) let path1 = pathk ~style:jCurve [ knotp ~r: (vec a_dir) a1; (* knotp m1;*) knotp ~l: (vec b_dir) c1; ] in let path2 = pathk ~style:jCurve [ knotp ~r: (vec (neg b_dir)) c2; (* knotp m2;*) knotp ~l: (vec (neg a_dir)) a2; ] in let path_head = pathk ~style:jLine [ knotp c1'; knotp b; knotp c2'; ] in cycle ~style:jLine (append ~style:jLine (append ~style:jLine path1 path_head) path2) let draw_thick ?style ?(boxed=true) ?line_color ?fill_color ?outd ?ind ?width ?head_length ?head_width a b = let p = thick_path ?style ?outd ?ind ?width ?head_length ?head_width a b in let draw_cmd = if boxed then Command.draw ?color:line_color p else Command.nop in let fill_cmd = match fill_color with | None -> Command.nop | Some c -> Command.fill ~color:c p in Command.append fill_cmd draw_cmd let simple ?color ?brush ?pen ?dashed p = let kind = add_head ~head:(head_triangle_full ?color) (add_line ?dashed ?color ?brush ?pen empty) in draw ~kind p mlpost-0.8.2/backend-test.ml000066400000000000000000000514041306046515300157440ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Mlpost open Num open Command open Format open Helpers open Point open Path module T = Transform let (++) x y = pt (cm x, cm y) let shift x y = transform [Transform.shifted (x ++ y)] let () = Random.init 1234 open Tree open Box let tabular l = "{\\begin{tabular}{l}" ^ String.concat " \\\\ " l ^ "\\end{tabular}}" let box_list, box_tab = let s a b c = shift (Point.p (a,b)) c in let b1 = tex "1" in let b2 = s 50. 50. (tex "2") in let b3 = s (-50.) 50. (tex "longer") in let b4 = s 0. 30. (tex "$\\cdot$") in let b5 = s (-30.) 0. (tex (tabular ["hig"; "her"])) in let b6 = empty () in [b1; b2; b3; b4; b5;], [ [b1; b2; b3] ; [b4; b5; b6] ] let hannotate' text bl = hbox ~padding:(Num.bp 50.) [tex text; bl] let hannotate text bl = hannotate' text (group bl) let vannotate' text bl = vbox ~padding:(Num.bp 50.) [tex text; bl] let vannotate text bl = vannotate' text (group bl) let halign_test = let b = box_list in draw ~debug:true (vbox [ hannotate "beginning" b; hannotate "halign" (halign ~pos:`Center zero b); hannotate "halign-bot" (halign ~pos:`Bot zero b); hannotate "halign-top" (halign ~pos:`Top zero b) ]) let hplace_test = let b = box_list in draw ~debug:true (vbox [ hannotate "beginning" b; hannotate "hplace" (hplace b); hannotate "hplace-ul-mw" (hplace ~pos:`Upleft ~min_width:(Num.bp 10.) b); hannotate "hplace-lr-sw" (hplace ~pos:`Lowright ~same_width:true b) ]) let hbox_test = let b = box_list in draw ~debug:true (vbox [ hannotate "beginning" b; hannotate' "hbox" (hbox b); hannotate' "hbox-pad-ul" (hbox ~pos:`Upleft ~padding:(Num.bp 20.) b); ]) let hblock_test = let b = box_list in draw (vbox [ hannotate "beginning" b; hannotate' "hblock" (hblock b); hannotate' "hblock-ul-mw" (hblock ~pos:`Upleft ~min_width:(Num.bp 20.) b); hannotate' "hblock-lr-sw" (hblock ~pos:`Lowright ~same_width:true b); ]) let valign_test = let b = box_list in draw ~debug:true (hbox [ vannotate "beginning" b; vannotate "valign" (valign ~pos:`Center zero b); vannotate "valign-left" (valign ~pos:`Left zero b); vannotate "valign-right" (valign ~pos:`Right zero b) ]) let vplace_test = let b = box_list in draw ~debug:true (hbox [ vannotate "beginning" b; vannotate "vplace" (vplace b); vannotate "vplace-ul-mh" (vplace ~pos:`Upleft ~min_height:(Num.bp 20.) b); vannotate "vplace-lr-sh" (vplace ~pos:`Lowright ~same_height:true b) ]) let vbox_test = let b = box_list in draw ~debug:true (hbox [ vannotate "beginning" b; vannotate' "vbox" (vbox b); vannotate' "vbox-pad-ul" (vbox ~pos:`Upleft ~padding:(Num.bp 20.) b); ]) let vblock_test = let b = box_list in draw (hbox [ vannotate "beginning" b; vannotate' "vblock" (vblock b); vannotate' "vblock-ul-mw" (vblock ~pos:`Upleft ~min_height:(Num.bp 20.) b); vannotate' "vblock-lr-sw" (vblock ~pos:`Lowright ~same_height:true b); ]) let tabularl_test = draw ~debug:true (vbox [ hannotate' "tabularl" (tabularl box_tab); hannotate' "tabularl-lr" (tabularl ~pos:`Lowright box_tab); ]) (* Bresenham (JCF) *) (* the data to plot are computed here *) let x2 = 9 let y2 = 6 let bresenham_data = let a = Array.create (x2+1) 0 in let y = ref 0 in let e = ref (2 * y2 - x2) in for x = 0 to x2 do a.(x) <- !y; if !e < 0 then e := !e + 2 * y2 else begin y := !y + 1; e := !e + 2 * (y2 - x2) end done; a (* drawing *) let bresenham0 = let width = bp 6. and height = bp 6. in let g = Box.gridi (x2+1) (y2+1) (fun i j -> let fill = if bresenham_data.(i) = y2-j then Some Color.red else None in Box.empty ~width ~height ?fill ~stroke:(Some Color.black) ()) in Box.draw g let block1 = let b1 = hblock ~min_width:(width (tex "c")) [empty (); tex "A"; tex "B"; tex "c"; tex "toto"] in let b2 = hblock ~same_width:true [tex "A"; tex "B"; tex ~fill:Color.red "c"; tex "toto"] in draw (vbox [b1;b2]) let block2 = draw (hblock [tex "A"; tex "B"; tex "c"; tex "toto"]) let vblock1 = draw (vblock [tex "A"; tex "B"; tex "c"; tex "toto"]) let hbox1 = draw (hbox ~pos:`Top [tex "."; tex "B"; tex "c"; tex "toto"]) let hbox2 = let s b = Box.shift (Point.p (100.,100.)) b in let stroke = Some Color.red in let b = vbox ~stroke ~pos:`Left [tex "A"; s (tex "Bx") ; tex "c"; tex "toto"] in let t = hbox ~stroke [b;b;b] in draw (vbox [t;s t;t]) let simple_box = Box.draw (Box.rect ~stroke:(Some Color.black) (Box.empty ~width:(bp 50.) ~height:(bp 50.) ())) let hvbox = let row = vbox [tex "A"; tex "B"; tex "C" ] in let col = hbox [nth 0 row ; tex "D" ; tex "E"] in seq [ draw row; draw col ] let d1 = let a = circle (tex "$\\sqrt2$") in let b = shift (2. ++ 0.) (rect ~fill:Color.purple (tex "$\\pi$")) in let pen = Pen.scale (bp 3.) Pen.default in seq [ draw a; draw b; Command.draw ~color:Color.red (Path.shift (1. ++ 1.) (bpath a)); draw_label_arrow ~color:Color.orange ~pen ~pos:`Upright (Picture.tex "foo") (west a) (south_east b); box_arrow ~color:Color.blue a b; ] open Box let d2 = let tex = tex ~stroke:(Some Color.black) in let b = hbox ~padding:(bp 10.) ~pos:`Top ~stroke:(Some Color.red) ~dx:(bp 2.) ~dy:(bp 2.) [vbox ~padding:(bp 4.) ~pos:`Right [tex "A"; tex "BC"; tex "D"]; vbox ~padding:(bp 4.) ~pos:`Left [tex "E"; tex "FGH"]] in seq [draw ~debug:false b; box_arrow (nth 1 (nth 0 b)) (nth 0 (nth 1 b))] let proval = let f = 7. in let pen = Pen.rotate 40. (Pen.yscale (bp 0.5) Pen.square) in let check = jointpath [-1.2,1.2; 0., -2. ; 2., 2. ; 5., 5.] [jLine ; jCurve; jCurve] in seq [ fill ~color:(Color.gray 0.2) (Path.scale (Num.bp f) fullcircle) ; label ~pos:`Left (Picture.tex "Pr") (Point.p (f /. (-4.),0.)) ; label ~pos:`Right (Picture.tex "al") (Point.p (f /. 4.,0.)) ; Command.draw ~color:Color.green ~pen check;] open Tree let yannick style = let tt s = Box.tex ~style ~fill:Color.orange ("\\texttt{" ^ s ^ "}") in let node s = node ~ls:(bp 20.) ~cs:(bp 10.) ~edge_style:Square (tt s) in let leaf s = leaf (tt s) in let tree = node "ComposerPage" [ leaf "MemSet"; node "ComposerMessages" [ node "ComposerMsg" [ leaf "StrCpy"; leaf "DeclarerPanneRobustesse" ] ] ] in draw tree let rec random_tree ?arrow_style ?edge_style ?stroke ?pen ?sep n = let random_tree = random_tree ?arrow_style ?edge_style ?stroke ?pen ?sep in let tex s = shadow (tex ~fill:Color.yellow ~stroke:(Some Color.black) s) in match n with | 1 -> leaf (tex "1") | 2 -> node ?arrow_style ?edge_style ?stroke ?pen ?sep (Box.tex ~style:Box.Rect ~fill:(Color.rgb 0.5 0.3 0.2) "2") [leaf (tex "1")] | n -> let k = 1 + Random.int (n - 2) in node ?arrow_style ?edge_style ?stroke ?pen ?sep (tex (string_of_int n)) [random_tree k; random_tree (n - 1 - k)] let d2c, d2s, d2sq, d2hsq = (* let ls = bp (-1.0) in *) let stroke = Color.blue and pen = Pen.circle and arrow_style = Directed in draw (random_tree ~edge_style:Curve ~arrow_style ~stroke ~pen ~sep:(bp 5.) 17), draw (random_tree ~edge_style:Straight ~arrow_style ~stroke ~pen ~sep:(bp 3.) 17), draw (random_tree ~edge_style:Square ~arrow_style ~stroke ~pen 17), draw (random_tree ~edge_style:HalfSquare ~arrow_style ~stroke ~pen 17) let d5 = let rand_tree name i = set_name name (set_stroke Color.black (to_box (random_tree i))) in let t1 = rand_tree "1" 5 in let t2 = rand_tree "2" 6 in let bl = Box.hbox ~padding:(Num.cm 2.) [ box t1; box t2] in let b1 = nth 0 (get "1" bl) in let b2 = nth 0 (nth 0 (nth 1 (get "2" bl))) in seq [ Box.draw bl; box_arrow ~sep:(bp 5.) b1 b2; ] let tree1 () = pic (draw (random_tree (1 + Random.int 5))) let rec random_tree2 = function | 1 -> leaf (tree1 ()) | 2 -> node ~cs:(mm 0.2) (tree1 ()) [leaf (tree1 ())] | n -> let k = 1 + Random.int (n - 2) in node ~cs:(mm 0.2) (tree1 ()) [random_tree2 k; random_tree2 (n - 1 - k)] let d6 = draw (random_tree2 10) let cheno011 = let p = Path.path ~cycle:jCurve [(0.,0.); (30.,40.); (40.,-20.); (10.,20.)] in let pen = Pen.scale (bp 1.5) Pen.circle in seq [Command.draw p; seq (List.map (fun (pos, l, i) -> Command.dotlabel ~pos (Picture.tex l) (point i p)) [`Bot, "0", 0.; `Upleft, "1", 1. ; `Lowleft, "2", 2. ; `Top, "3", 3. ; `Left, "4", 4. ]); Command.draw ~pen (subpath 1.3 3.2 p)] open Dash let d3 = let p = pathp [cmp (0., 0.); cmp (5., 0.)] in let pat = pattern [on (bp 6.); off (bp 12.); on (bp 6.)] in Command.draw p ~dashed:pat let d4 = seq [cheno011; iter 1 5 (fun i -> Picture.transform [T.rotated (10. *. float i)] cheno011) ] let d7 = let pic = Picture.transform [T.scaled (bp 4.)] (Picture.tex "bound this!") in let pbox = pathp ~style:jLine ~cycle:jLine [Picture.ulcorner pic; Picture.urcorner pic; Picture.lrcorner pic; Picture.llcorner pic] in seq [pic; Command.draw (Picture.bbox pic); Command.draw pbox; Command.dotlabel ~pos:`Left (Picture.tex "ulcorner") (Picture.ulcorner pic); Command.dotlabel ~pos:`Left (Picture.tex "llcorner") (Picture.llcorner pic); Command.dotlabel ~pos:`Right (Picture.tex "urcorner") (Picture.urcorner pic); Command.dotlabel ~pos:`Right (Picture.tex "lrcorner") (Picture.lrcorner pic); ] let half pic = Picture.transform [Transform.scaled (bp 0.5)] pic let rec right_split n pic = if n <= 0 then pic else let smaller = right_split (n-1) (half pic) in Picture.beside pic (Picture.below smaller smaller) let d11 = let p1 = Picture.transform [Transform.rotated 90.] (Picture.tex "recursion") in p1 (* right_split 4 p1 *) let rec sierpinski p n = if n = 0 then p else let sp = sierpinski p (n-1) in let p = half sp in let p1 = Picture.beside p p in Picture.below p p1 let d12 = let p1 = Picture.tex "A" in sierpinski p1 7 (** plots *) open Plot let sk = mk_skeleton 20 14 (Num.bp 20.) (Num.bp 20.) let d13 = draw_grid sk let squaref x = x *. x let f2 i = sqrt (float_of_int i) let f3 i = squaref (float_of_int i) let d14 = let hdash _ = Dash.scaled 0.5 Dash.withdots in let vdash _ = Dash.scaled 2. Dash.evenly in let hvpen i = if i mod 5 = 0 then Pen.scale (bp 2.5) Pen.default else Pen.default in let pen = Pen.scale (bp 4.) Pen.default in seq [draw_grid ~hdash ~vdash ~hpen:hvpen ~vpen:hvpen sk; draw_func ~pen f2 sk; draw_func ~pen f3 sk ] let f1 i = let aux = function | 0 -> 1 | 1 | 2 -> 2 | 3 | 4 -> 3 | 5 -> 4 | 6 | 7 -> 5 | 8 |9 -> 6 | 10 -> 7 | 11 | 12 -> 8 | 13 | 14 -> 9 | 15 -> 10 | 16 | 17 -> 11 | 18 | 19 -> 12 | 20 -> 13 | _ -> 0 in float_of_int (aux i) let f2 i = let aux = function | 0 | 1 | 2 -> 0 | 3 -> 1 | 4 -> 2 | 5 | 6 | 7 -> 3 | 8 -> 4 | 9 -> 5 | 10 | 11 | 12 -> 6 | 13 -> 7 | 14 -> 8 | 15 | 16 | 17 -> 9 | 18 -> 10 | 19 -> 11 | 20 -> 12 | _ -> 0 in float_of_int (aux i) let f3 i = float_of_int ((i+3)/5) let flab i = (Picture.transform [Transform.scaled (bp 1.7)] (Picture.tex (Printf.sprintf "$f_{\\omega_%d}$" i)), `Top, 19) let instants = let pen = Pen.scale (bp 2.5) Pen.default in let base = Command.draw ~pen (Path.path ~style:jLine [(0.,-65.); (280.,-65.)]) in let tick i = let xi = float_of_int i *. 14. in let yi = if f1 i = f1 (i-1) then -60. else -45. in let p = Path.path ~style:jLine [(xi,-65.); (xi, yi)] in Command.draw ~pen p in Command.seq [base; Command.iter 0 20 tick; Command.label (Picture.transform [Transform.scaled two] (Picture.tex "$\\omega_1$")) (p (-20., -55.))] let florence = let sk = mk_skeleton 20 14 (bp 14.) (bp 20.) in let pen = Pen.scale (bp 4.) Pen.default in let pen2 = Pen.scale (bp 3.) Pen.default in let dash _ = Dash.scaled 0.5 Dash.withdots in let dash2 = Dash.scaled 0.66 Dash.withdots in let dash3 = Dash.scaled 0.9 Dash.evenly in let vcaption, hcaption = let tr = [Transform.scaled (bp 1.5)] in Picture.transform tr (Picture.tex "\\textsf{Number of ones}"), Picture.transform tr (Picture.tex "\\textsf{Instants}") in let plot = draw_func ~drawing:Stepwise ~style:jLine in seq [ draw_grid ~hdash:dash ~vdash:dash ~color:(Color.gray 0.5) sk; draw_axes ~closed:true ~hcaption ~vcaption sk; plot ~pen ~label:(flab 1) f1 sk; plot ~pen:pen2 ~dashed:dash2 ~label:(flab 2) f2 sk; plot ~pen ~dashed:dash3 ~label:(flab 3) f3 sk; instants ] let shapes1 = Box.vbox [Box.path (Shapes.rectangle (bp 10.) (bp 20.)); Box.path (Shapes.rectangle (bp 35.) (bp 15.)); Box.path (Shapes.rectangle (bp 15.) (bp 35.)); Box.path (Shapes.round_rect (bp 55.) (bp 25.) (bp 10.) (bp 10.)); Box.path (Shapes.round_rect (bp 55.) (bp 25.) (bp 20.) (bp 5.)); Box.path (Shapes.round_rect (bp 70.) (bp 25.) (bp 14.) (bp 14.)); ] let shapes2 = Box.vbox [ (* Shapes.arc_ellipse (f 10.) (f 10.) 0. 1.7; Shapes.arc_ellipse ~stroke:Color.red (f 30.) (f 10.) 0. 1.7; Shapes.arc_ellipse ~stroke:Color.red ~close:true (f 30.) (f 10.) 0. 1.7; Shapes.arc_ellipse ~fill:Color.black ~stroke:Color.red (f 30.) (f 10.) 0. 1.7; *) Box.path (Shapes.ellipse (bp 10.) (bp 10.)); Box.path (Shapes.ellipse (bp 30.) (bp 10.)); Box.path (Shapes.ellipse (bp 30.) (bp 10.)); ] let farey n = let u x = Num.bp (200.0 *. x) in let circle x y r = Command.fill ~color:Color.lightgray (Path.shift (Point.pt (u y, u x)) (Path.scale (u (2.*.r)) fullcircle)) in let quartercircle x y r theta = Command.draw (Path.shift (Point.pt (u y, u x)) (Path.scale (u (2.*.r)) (Path.rotate theta quartercircle))) in let rec aux acc p1 q1 p2 q2 = let p = p1 + p2 in let q = q1 + q2 in if q>n then acc else let fq = float q in let fr = 0.5 /. fq /. fq in let acc = circle (float p /. fq) fr fr :: acc in let acc = aux acc p1 q1 p q in aux acc p q p2 q2 in let l = aux [ quartercircle 0.0 0.5 0.5 90.0; quartercircle 1.0 0.5 0.5 180.0] 0 1 1 1 in Picture.scale (Num.bp 30.0) (Command.seq l) let why_platform = let tabular l = "{\\begin{tabular}{l}" ^ String.concat " \\\\ " l ^ "\\end{tabular}}" in let dx = bp 5. and dy = bp 5. in let space ~name b = rect ~stroke:None ~name ~dx ~dy b in let green s = space ~name:s (round_rect ~dx ~dy ~stroke:None ~fill:Color.lightgreen (tex s)) in let pink s = space ~name:s (shadow (rect ~dx ~dy ~fill:(Color.color "light pink") (tex ("\\large\\sf " ^ s)))) in let interactive = tex ~name:"interactive" (tabular ["Interactive provers"; "(Coq, PVS,"; "Isabelle/HOL, etc.)"]) in let automatic = tex ~name:"automatic" (tabular ["Automatic provers"; "(Alt-Ergo, Simplify,"; "Yices, Z3, CVC3, etc.)"]) in let b = tabularl ~hpadding:(bp 20.) ~vpadding:(bp 30.) [[green "Annotated C programs"; empty (); green "JML-annotated Java programs"]; [pink "Caduceus"; green "Why program"; pink "Krakatoa";]; [empty (); pink "Why"; empty ()]; [interactive; green "verification conditions"; automatic]] in let arrow x y = let p = Box.cpath (get x b) (get y b) in Arrow.draw_thick ~line_color:Color.red ~width:(bp 4.) ~head_width:(bp 10.) ~fill_color:Color.red (Path.point 0. p) (Path.point 1. p) in seq [Box.draw b; arrow "Annotated C programs" "Caduceus"; arrow "Caduceus" "Why program"; arrow "JML-annotated Java programs" "Krakatoa"; arrow "Krakatoa" "Why program"; arrow "Why program" "Why"; arrow "Why" "verification conditions"; arrow "verification conditions" "interactive"; arrow "verification conditions" "automatic"; ] (*** let alt_ergo = let b = tabularl ~hpadding:(bp 20.) ~vpadding:(bp 30.) [[green "Annotated C programs"; empty (); green "JML-annotated Java programs"]; [pink "Caduceus"; green "Why program"; pink "Krakatoa";]; [empty (); pink "Why"; empty ()]; [interactive; green "verification conditions"; automatic]] in [Box.draw b] ***) let rotatedbox = let t = tex "$A^{-1}$" in let b1 = Box.rotate 90. t in Box.draw (Box.hblock [b1;t]) let style = RoundRect let stroke = Some Color.black let pen = Pen.scale (bp 2.) Pen.circle let dx = bp 5. let dy = dx let tex = Box.tex ~style ~pen ~dx ~dy let tex' = Box.tex ~style ~pen ~dx ~dy:(bp 10.) let assia_schema = let tabular l = "{\\begin{tabular}{l}" ^ String.concat " \\\\ " l ^ "\\end{tabular}}" in let lang = tex ~stroke:(Some Color.red) "langage de developpement de preuves" in let genie = Box.tex "Genie logiciel formel" in let moteur = tex' ~stroke:(Some Color.purple) (tabular ["moteur de"; "dev de preuves"]) in let verif = tex' ~stroke:(Some Color.purple) (tabular ["verificateur";" de preuves"]) in let langf = Box.round_rect ~stroke:(Some Color.blue) ~pen ~dx:(bp 50.) ~dy:(bp 10.) (Box.tex "langage formel") in let h = Box.hbox ~padding:(bp 20.) [moteur;verif] in let v = Box.vbox ~dx ~dy:(bp 10.) ~pen ~padding:(bp 5.) ~style ~stroke:(Some Color.orange) [lang; genie] in Box.draw (Box.vbox ~padding:(bp (-5.)) [langf; h;v]) let grid_with_padding = let red s = rect ~stroke:None ~fill:Color.lightred (tex s) in let blue s = rect ~stroke:None ~fill:Color.lightblue (tex s) in let b = gridl ~stroke:None ~hpadding:(bp 5.) ~vpadding:(bp 5.) [[empty (); red "abc"; red "def"]; [blue "titre 1"; red ""; red ""]; [blue "titre 2"; red ""; red ""]] in Box.draw b let grid_with_padding_2 = let red s = rect ~stroke:None ~fill:Color.lightred (tex s) in let blue s = rect ~stroke:None ~fill:Color.lightblue (tex s) in let pen = Pen.scale (Num.pt 1.5) Pen.circle in let b = gridl ~stroke:(Some Color.white) ~pen ~hpadding:(bp 5.) ~vpadding:(bp 5.) [[empty (); red "abc"; red "def"]; [blue "titre 1"; red ""; red ""]; [blue "titre 2"; red ""; red ""]] in seq [Box.draw b; Box.draw (shift (Point.pt (bp 5., bp 5.)) b)] let figs = [ halign_test; hplace_test; hbox_test; hblock_test; valign_test; vplace_test; vbox_test; vblock_test; tabularl_test; grid_with_padding; grid_with_padding_2; rotatedbox; assia_schema; hbox1; hbox2; bresenham0; simple_box; block1; hvbox; d2; block2; vblock1; yannick Box.Rect; yannick Box.Patatoid;d1; d2sq; d2hsq; cheno011; d3; d4; d7; d11; d12 ; (* farey 17; *) florence; Box.draw shapes1; Box.draw shapes2; d14; d13; (* why_platform; d5; d6; proval; d2s; d2c; *) ] let _ = let freshx = let x = ref 0 in let s = "testspdf" in fun () -> s ^ (string_of_int (!x)) in List.iter (fun x -> Metapost.emit (freshx ()) x) figs (* let figs = let r = ref 0 in List.map (fun f -> incr r; !r, f) figs (* CM fonts do not scale well *) let theprelude = "\\documentclass[a4paper]{article} \\usepackage[T1]{fontenc} \\usepackage{times} " let () = Metapost.generate_mp ~prelude:theprelude "test/tests.mp" figs; Misc.write_to_formatted_file "test/tests.tex" (fun fmt -> fprintf fmt "\\documentclass[a4paper]{article}@."; fprintf fmt "\\usepackage[T1]{fontenc}@."; fprintf fmt "\\usepackage{times}@."; fprintf fmt "\\usepackage{fullpage}@."; fprintf fmt "\\usepackage[]{graphicx}@."; fprintf fmt "@[\\begin{document}@."; List.iter (fun (i,_) -> fprintf fmt "@\n %i\\quad" i; fprintf fmt "\\includegraphics[width=\\textwidth,height=\\textheight,keepaspectratio]{tests.%d}" i; fprintf fmt "@\n \\vspace{3cm}@\n" ) figs; fprintf fmt "@]@\n\\end{document}@.") *) mlpost-0.8.2/backend/000077500000000000000000000000001306046515300144315ustar00rootroot00000000000000mlpost-0.8.2/backend/_tags000066400000000000000000000003761306046515300154570ustar00rootroot00000000000000<*dvicairo.*> or : pkg_lablgtk2, pkg_cairo.lablgtk2 <*dvicairo.*> : pkg_cairo : pkg_cairo : pkg_cairo : pkg_cairo <*.cmx> : for-pack(Mlpost) : include_freetype : pkg_cairomlpost-0.8.2/backend/draw.ml000066400000000000000000000116431306046515300157250ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Point_lib module S = Spline_lib let draw_tex cr tex = Cairo.save cr; Cairo.transform cr tex.Gentex.trans; Dvicairo.draw {Dvicairo.pic = cr; x_origin = 0.; y_origin = 0.} tex.Gentex.tex; Cairo.restore cr (*;Format.printf "Gentex : %a@." print tex*) module MetaPath = struct type pen = Matrix.t let curve_to cr s = let _, sb, sc, sd = Spline.explode s in Cairo.curve_to cr sb.x sb.y sc.x sc.y sd.x sd.y let draw_path cr = function | S.Path p -> begin match p.S.pl with | [] -> assert false | (x::_) as l -> let sa = Spline.left_point x in Cairo.move_to cr sa.x sa.y; List.iter (curve_to cr) l end ; if p.S.cycle then Cairo.close_path cr | S.Point _ -> failwith "Metapost fail in that case what should I do???" let stroke cr pen = function | S.Path _ as path -> (*Format.printf "stroke : %a@." S.print path;*) draw_path cr path; Cairo.save cr; (*Matrix.set*) Cairo.transform cr pen; Cairo.stroke cr; Cairo.restore cr; | S.Point p -> (*Format.printf "stroke : %a@." S.print path;*) Cairo.save cr; Cairo.transform cr (Matrix.translation p); Cairo.transform cr pen; draw_path cr (Metapath_lib.Approx.fullcircle 1.); Cairo.fill cr; Cairo.restore cr let fill cr path = draw_path cr path; Cairo.fill cr end module Picture = struct open Concrete_types exception Not_implemented of string let not_implemented s = raise (Not_implemented s) let rec color cr = function | OPAQUE (RGB (r,g,b)) -> Cairo.set_source_rgb cr r g b | OPAQUE (CMYK _) -> not_implemented "cmyk" | OPAQUE (Gray g) -> color cr (OPAQUE (RGB (g,g,g))) | TRANSPARENT (a,RGB (r,g,b)) -> Cairo.set_source_rgba cr r g b a | TRANSPARENT (a,CMYK _) -> not_implemented "cmyk" | TRANSPARENT (a,(Gray g)) -> color cr (TRANSPARENT (a,RGB (g,g,g))) let color_option cr = function | None -> () | Some c -> color cr c let dash cr = function | None | Some (_,[]) -> (); | Some (f,l) -> Cairo.set_dash cr (Array.of_list l) f let inversey cr height = Cairo.translate cr ~tx:0. ~ty:height; Cairo.scale cr ~sx:1. ~sy:(-.1.) open Picture_lib let rec draw_aux cr = function | Empty -> () | Transform (m,t) -> Cairo.save cr; Cairo.transform cr m; (*Format.printf "Transform : %a@." Matrix.print m;*) draw_aux cr t; Cairo.restore cr | OnTop l -> List.iter (draw_aux cr) l | Tex t -> Cairo.save cr; Cairo.scale cr ~sx:1. ~sy:(-.1.); draw_tex cr t; Cairo.restore cr | Stroke_path(path,c,pen,d) -> Cairo.save cr; color_option cr c; dash cr d; MetaPath.stroke cr pen path; Cairo.restore cr | Fill_path (path,c)-> Cairo.save cr; color_option cr c; MetaPath.fill cr path; Cairo.restore cr | Clip (com,p) -> Cairo.save cr; MetaPath.draw_path cr p; Cairo.clip cr; draw_aux cr com; Cairo.restore cr | ExternalImage (filename,height,m) -> Cairo.save cr; Cairo.transform cr m; inversey cr height; let img = Cairo_png.image_surface_create_from_file filename in Cairo.set_source_surface cr img 0. 0.; Cairo.paint cr; Cairo.restore cr let draw cr width height p = Cairo.save cr; inversey cr height; Cairo.set_line_width cr default_line_size; (* Only elliptical pens use the stroke command *) Cairo.set_line_cap cr Cairo.LINE_CAP_ROUND; Cairo.set_line_join cr Cairo.LINE_JOIN_ROUND; draw_aux cr (content p); Cairo.restore cr let where cr t (x,y) = not_implemented "where" let move t id p = not_implemented "move" end mlpost-0.8.2/backend/draw.mli000066400000000000000000000032241306046515300160720ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) val draw_tex : Cairo.t -> Gentex.t -> unit module MetaPath : sig type pen = Matrix.t val stroke : Cairo.t -> pen -> Spline_lib.path -> unit val fill : Cairo.t -> Spline_lib.path -> unit val draw_path : Cairo.t -> Spline_lib.path -> unit end module Picture : sig val draw : Cairo.t -> float -> float -> Picture_lib.t -> unit val where : Cairo.t -> Picture_lib.t -> float * float -> Picture_lib.id list val move : Cairo.t -> Picture_lib.t -> Picture_lib.id -> float * float -> float * float end mlpost-0.8.2/backend/dvicairo.ml000066400000000000000000000106461306046515300165720ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format open Dviinterp open Mlpost_ft type multi_page_pic = {pic :Cairo.t; x_origin : float; y_origin : float } let conversion = 0.3937 *. 72. let point_of_cm cm = conversion *. cm let fonts_known = Hashtbl.create 30 let find_font font = let font_name = font.Fonts.glyphs_tag in try Hashtbl.find fonts_known font_name with Not_found -> if Defaults.get_debug () then printf "Cairo : Loading font@."; let face = font.Fonts.glyphs_ft in let f = Cairo_ft.font_face_create_for_ft_face face 0 in Hashtbl.add fonts_known font_name f;f let clean_up () = () let set_source_color pic = function | RGB(r,g,b) -> if Defaults.get_debug () then printf "Use color RGB (%f,%f,%f)@." r g b; Cairo.set_source_rgb pic r g b | Gray(g) -> if Defaults.get_debug () then printf "Use color Gray (%f)@." g; Cairo.set_source_rgb pic g g g | CMYK _ -> failwith "dvicairo : I don't know how to convert CMYK\ to RGB and cairo doesn't support it" | HSB _ -> failwith "dvicairo : I'm lazy I haven't written this conversion" (* http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_HSV_to_RGB and in color.ml*) let fill_rect s dinfo x1 y1 w h = let x1 = point_of_cm x1 +. s.x_origin and y1 = point_of_cm y1 +. s.y_origin and w = point_of_cm w and h = point_of_cm h in if Defaults.get_debug () then printf "Draw a rectangle in (%f,%f) with w=%f h=%f@." x1 y1 w h; Cairo.save s.pic; set_source_color s.pic dinfo.Dviinterp.color; Cairo.rectangle s.pic x1 y1 w h; Cairo.fill s.pic; Cairo.restore s.pic let draw_type1 s text_type1 = let dinfo = text_type1.c_info in let font = text_type1.c_font in let char = text_type1.c_glyph in let x,y = text_type1.c_pos in let f = find_font font in let char = font.Fonts.glyphs_enc (Int32.to_int char) and x = point_of_cm x +. s.x_origin and y = point_of_cm y +. s.y_origin and ratio = point_of_cm font.Fonts.glyphs_ratio_cm in if Defaults.get_debug () then begin try printf "Draw the char %i(%c) in (%f,%f) x%f@." char (Char.chr char) x y ratio; with _ -> printf "Draw the char %i in (%f,%f) x%f@." char x y ratio end; Cairo.save s.pic; set_source_color s.pic dinfo.Dviinterp.color; Cairo.set_font_face s.pic f ; Cairo.set_font_size s.pic ratio; (* slant and extend *) (match font.Fonts.slant with | Some a when Defaults.get_verbosity () -> printf "slant of %f not used@." a | Some _ | None -> ()); (match font.Fonts.extend with | Some a when Defaults.get_debug () -> printf "extend of %f not used@." a | Some _ | None -> ()); Cairo.show_glyphs s.pic [|{Cairo.index = char; Cairo.glyph_x = x; Cairo.glyph_y = y}|]; Cairo.stroke s.pic; Cairo.restore s.pic let _specials s info xxx x y = if Defaults.get_debug () then printf "specials : \"%s\" at (%f,%f)@." xxx x y let rec draw_string s text = draw_commands s (decompose_text text) and draw_command s = function | Fill_rect (info, x, y, w, h) -> fill_rect s info x y w h | Draw_text text -> draw_string s text | Specials (info,xxx,x,y) -> _specials s info xxx x y | Draw_text_type1 text_type1 -> draw_type1 s text_type1 and draw_commands s = List.iter (draw_command s) let draw = draw_commands mlpost-0.8.2/backend/dvicairo.mli000066400000000000000000000003131306046515300167310ustar00rootroot00000000000000type multi_page_pic = {pic :Cairo.t; x_origin : float; y_origin : float } val draw : multi_page_pic -> Dviinterp.command list -> unit mlpost-0.8.2/backend/icairost.ml000066400000000000000000000103171306046515300166020ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Point_lib open Format let create create_surface out_file (draw:Cairo.t -> unit) height width = if Defaults.get_debug () then printf "height = %f, width = %f@." height width; let oc = open_out out_file in let s = create_surface oc ~width_in_points:width ~height_in_points:height in let cr = Cairo.create s in draw cr; if Defaults.get_debug () then printf "Clean up surface_finish ...@."; Cairo.surface_finish s; if Defaults.get_debug () then printf "Clean up close file ...@."; close_out oc let rec iter_after f after = function | [] -> () | [a] -> f a | a::l -> f a; after a;iter_after f after l let error_replace_by_tex msg_error f arg = match msg_error with | None -> f arg | Some w -> try f arg with exn -> let msg = sprintf "Error : %s" (Printexc.to_string exn) in let msg = Picture.escape_all msg in printf "%s@." msg; f (Types.mkPicture (Types.mkPITex (sprintf "\\begin{minipage}{%f pt} %s \\end{minipage} " w msg))) let min_if_inf = {x= -1.;y= -1.} let max_if_inf = {x= 1.;y= 1.} let emit_gen ?msg_error create next_page figs = (*Format.printf "Fig : %a@." Print.commandpic (List.hd figs);*) let figs = Compute.commandpicl_error (error_replace_by_tex msg_error) figs in let (min,max) = Point_lib.list_min_max Picture_lib.bounding_box figs in let min = norm_infinity min_if_inf min in let max = norm_infinity max_if_inf max in let ({x=xmin;y=ymin},{x=xmax;y=ymax}) = min,max in (*Point_lib.sub min Compute.bbox_offset, Point_lib.add max Compute.bbox_offset in*) let height = ymax -. ymin in let width = xmax -. xmin in let not_null f = if f <= 0. then 1. else f in let height = not_null height and width = not_null width in let figs = List.map (fun fig -> Picture_lib.shift fig (-.xmin) (-.ymin)) figs in (* try *) create (fun cr -> iter_after (Draw.Picture.draw cr width height) (next_page cr) figs ) height width (* with Cairo.Error e -> invalid_arg *) (* ("Cairost generation error :" ^ (Cairo.string_of_status e)) *) let dumb_next_page _ _ = assert false let emit_pdf ?msg_error fname fig = emit_gen ?msg_error (create Cairo_pdf.surface_create_for_channel fname) dumb_next_page [fig] let emit_ps fname fig = emit_gen (create Cairo_ps.surface_create_for_channel fname) dumb_next_page [fig] let emit_svg fname fig = emit_gen (create Cairo_svg.surface_create_for_channel fname) dumb_next_page [fig] let emit_png fname fig = emit_gen (fun draw height width -> let width = int_of_float (ceil width) in let height = int_of_float (ceil height) in let surf = Cairo.image_surface_create Cairo.FORMAT_ARGB32 ~width ~height in let cr = (Cairo.create surf) in draw cr; Cairo_png.surface_write_to_file surf fname) dumb_next_page [fig] let emit_cairo cairo (width,height) fig = (*Compute.clear (); LookForTeX.clear ();*) let fig = Compute.commandpic fig in Draw.Picture.draw cairo width height fig let emit_pdfs fname figs = emit_gen (create Cairo_pdf.surface_create_for_channel fname) (fun cr _ -> Cairo.show_page cr) figs mlpost-0.8.2/backend/libmlpost_ft.clib000066400000000000000000000000161306046515300177570ustar00rootroot00000000000000ml_mlpost_ft.omlpost-0.8.2/backend/ml_mlpost_ft.c000066400000000000000000000017001306046515300172720ustar00rootroot00000000000000 #include #include #define CAML_NAME_SPACE #include #include #include FT_FREETYPE_H #define FT_Face_val(v) (FT_Face)(Field(v, 0)) CAMLprim value ml_FT_Get_Name_Index(value font, value char_name) { int index = FT_Get_Name_Index (FT_Face_val (font), String_val (char_name)); return Val_int (index); } CAMLprim value ml_FT_Get_Char_Index(value font, value charcode) { int index = FT_Get_Char_Index (FT_Face_val (font), Long_val (charcode)); return Val_int (index); } CAMLprim value ml_FT_num_charmaps(value font) { FT_Face face = FT_Face_val (font); return Val_int (face->num_charmaps); } CAMLprim value ml_FT_set_charmap(value font, value charmap_index) { FT_Face face = FT_Face_val (font); FT_CharMap charmap = (face->charmaps)[Int_val(charmap_index)]; return Val_int (FT_Set_Charmap(face,charmap)); } mlpost-0.8.2/backend/mlpost_ft.ml000066400000000000000000000010521306046515300167700ustar00rootroot00000000000000 open Cairo_ft external ft_get_name_index : ft_face -> string -> int = "ml_FT_Get_Name_Index" external ft_get_char_index : ft_face -> int -> int = "ml_FT_Get_Char_Index" external ft_num_charmaps : ft_face -> int = "ml_FT_num_charmaps" external ft_set_charmap : ft_face -> int -> int = "ml_FT_set_charmap" let ft_set_charmap face index = if index < 0 || ft_num_charmaps face <= index then invalid_arg "ft_set_charmap : invalid charmap index"; let r = ft_set_charmap face index in if r <> 0 then invalid_arg "ft_set_charmap : unsuccesful" mlpost-0.8.2/backend/myocamlbuild.ml000066400000000000000000000103671306046515300174530ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Ocamlbuild_plugin (* open Command -- no longer needed for OCaml >= 3.10.2 *) (* these functions are not really officially exported *) let run_and_read = Ocamlbuild_pack.My_unix.run_and_read let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings let split s ch = let x = ref [] in let rec go s = let pos = String.index s ch in x := (String.before s pos)::!x; go (String.after s (pos + 1)) in try go s with Not_found -> !x let split_nl s = split s '\n' let before_space s = try String.before s (String.index s ' ') with Not_found -> s (* this lists all supported packages *) let find_packages () = List.map before_space (split_nl & run_and_read "ocamlfind list") (* this is supposed to list available syntaxes, but I don't know how to do it. *) let find_syntaxes () = ["camlp4o"; "camlp4r"; "bitstring.syntax"] (* ocamlfind command *) let ocamlfind x = S[A"ocamlfind"; x] let _ = dispatch begin function | Before_options -> (* by using Before_options one let command line options have an higher priority *) (* on the contrary using After_options will guarantee to have the higher priority *) (* override default commands by ocamlfind ones *) Options.ocamlc := ocamlfind & A"ocamlc"; Options.ocamlopt := ocamlfind & A"ocamlopt"; Options.ocamldep := ocamlfind & A"ocamldep"; Options.ocamldoc := ocamlfind & A"ocamldoc"; Options.ocamlmktop := ocamlfind & A"ocamlmktop" | After_rules -> (* When one link an OCaml library/binary/package, one should use -linkpkg *) flag ["ocaml"; "link"] & A"-linkpkg"; (* For each ocamlfind package one inject the -package option when * compiling, computing dependencies, generating documentation and * linking. *) List.iter begin fun pkg -> flag ["ocaml"; "compile"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "doc"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "link"; "pkg_"^pkg] & S[A"-package"; A pkg]; end (find_packages ()); (* Like -package but for extensions syntax. Morover -syntax is useless * when linking. *) List.iter begin fun syntax -> flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; end (find_syntaxes ()); (* The default "thread" tag is not compatible with ocamlfind. Indeed, the default rules add the "threads.cma" or "threads.cmxa" options when using this tag. When using the "-linkpkg" option with ocamlfind, this module will then be added twice on the command line. To solve this, one approach is to add the "-thread" option when using the "threads" package using the previous plugin. *) flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]) | _ -> () end mlpost-0.8.2/box.ml000066400000000000000000000611201306046515300141640ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types open Num open Point open Num.Infix type style = | Rect | Circle | RoundRect | Patatoid | Patatoid2 | Ellipse | RoundBox | Custom of (Num.t -> Num.t -> Num.t * Num.t * Path.t) let margin = Num.bp 2. module Name = struct type t = | Internal of int | Userdef of string let compare = Pervasives.compare let print fmt = function | Internal i -> Format.pp_print_int fmt i | Userdef s -> Format.pp_print_string fmt s end module NMap = Map.Make(Name) let print_dom fmt m = Format.fprintf fmt "@[{"; NMap.iter (fun k _ -> Format.fprintf fmt "%a;@ " Name.print k) m; Format.fprintf fmt "}@]" type t = { name : Name.t; width : Num.t; height : Num.t; ctr : Point.t; stroke : Color.t option; pen : Pen.t option; fill : Color.t option; contour : Path.t; desc : desc; dash : Dash.t option; post_draw : t -> Command.t ; pre_draw : t -> Command.t } and desc = | Emp | Pic of Picture.t | Grp of t array * t NMap.t let width b = b.width let height b = b.height let ctr b = b.ctr let bpath b = b.contour let set_bpath p b = {b with contour = p} let halfheight b = Point.pt (zero, b.height /./ 2.) let halfwidth b = Point.pt (b.width /./ 2., zero) let north b = Point.add b.ctr (halfheight b) let south b = Point.sub b.ctr (halfheight b) let east b = Point.add b.ctr (halfwidth b) let west b = Point.sub b.ctr (halfwidth b) let build_point a b = Point.pt (xpart a, ypart b) let north_west x = build_point (west x) (north x) let north_east x = build_point (east x) (north x) let south_west x = build_point (west x) (south x) let south_east x = build_point (east x) (south x) type vposition = [ |Command.vposition | `Custom of t -> Num.t] type hposition = [ |Command.hposition | `Custom of t -> Num.t] type vposition_red = [ |Types.vposition_red | `Custom of t -> Num.t] type hposition_red = [ |Types.hposition_red | `Custom of t -> Num.t] type position = [ |Command.position | `Custom of t -> Point.t] type position_red = [ |Types.position_red | `Custom of t -> Point.t] let hreduce = function | `Custom c -> `Custom c | #Command.hposition as p -> (hreduce p:> hposition_red) let vreduce = function | `Custom c -> `Custom c | #Command.vposition as p -> (vreduce p:> vposition_red) let pos_reduce = function | `Custom c -> `Custom c | #Command.position as p -> (pos_reduce p:> position_red) let corner pos x = match pos with | `Custom c -> c x | #Types.position as other -> match Types.pos_reduce other with | `Northwest -> north_west x | `Northeast -> north_east x | `Southwest -> south_west x | `Southeast -> south_east x | `West -> west x | `East -> east x | `Center -> ctr x | `North -> north x | `South -> south x let cornerh pos x = match pos with | `Custom c -> c x | #Command.position as pos -> xpart (corner pos x) let cornerv pos x = match pos with | `Custom c -> c x | #Command.position as pos -> ypart (corner pos x) let rec transform t b = let tr = Point.transform t in let nw = tr (north_west b) and sw = tr (south_west b) and se = tr (south_east b) in let hvec = Point.sub nw sw and wvec = Point.sub se sw in { b with ctr = Point.transform t b.ctr; height = Num.abs (ypart hvec) +/ Num.abs (ypart wvec); width = Num.abs (xpart hvec) +/ Num.abs (xpart wvec); contour = Path.transform t b.contour; desc = transform_desc t b.desc; } and transform_desc t = function | Emp -> Emp | Pic p -> Pic (Picture.transform t p) | Grp (a , m ) -> Grp (Array.map (transform t) a, NMap.map (transform t) m) let rec shift pt b = { b with ctr = Point.shift pt b.ctr; contour = Path.shift pt b.contour; desc = shift_desc pt b.desc; } and shift_desc pt = function | Emp -> Emp | Pic p -> Pic (Picture.shift pt p) | Grp (a,m) -> let s = shift pt in Grp (Array.map s a, NMap.map s m) let scale f p = transform [Transform.scaled f] p let rotate f p = transform [Transform.rotated f] p let yscale n p = transform [Transform.yscaled n] p let xscale n p = transform [Transform.xscaled n] p let center pt x = shift (Point.sub pt x.ctr) x let border pos b = match pos with | `North -> ypart (ctr b) +/ height b /./ 2. | `South -> ypart (ctr b) -/ height b /./ 2. | `West -> xpart (ctr b) -/ width b /./ 2. | `East -> xpart (ctr b) +/ width b /./ 2. let rec draw ?(debug=false) b = let path_cmd = match b.stroke, b.pen with | None, _ -> Command.nop | Some color, None -> Command.draw ~color ?dashed:b.dash b.contour | Some color, Some pen -> Command.draw ~pen ~color ?dashed:b.dash b.contour in let fill_cmd = match b.fill with | None -> Command.nop | Some color -> Command.fill ~color b.contour in let contents_cmd = match b.desc with | Emp -> Command.nop | Pic pic -> pic | Grp (a, _) -> Command.iter 0 (Array.length a - 1) (fun i -> draw ~debug a.(i)) in let debug_cmd = if debug then (* TODO maybe we should better draw the rectangle [w,h] instead of the contour *) let rect = Path.shift b.ctr (Shapes.rectangle b.width b.height) in Command.seq [Command.draw ~color:Color.red ~dashed:Dash.evenly rect; match b.name with | Name.Internal _ -> Command.nop | Name.Userdef s -> Command.label ~pos:`Center (Picture.tex ("\\tiny " ^ (Picture.escape_all s))) (north_west b)] else Command.nop in Command.seq [b.pre_draw b; fill_cmd; contents_cmd; path_cmd; debug_cmd; b.post_draw b] let rect_ w h = w, h, Shapes.rectangle w h let circ_ w h = let m = maxn w h in m, m, Shapes.circle m let ellipse_ w h = let p = Shapes.ellipse w h in let pic = Command.draw p in Picture.width pic, Picture.height pic, p let round_rect_ w h = let rx = (minn w h) /./ 10. in w, h, Shapes.round_rect w h rx rx let round_box_ w h = w, h, Shapes.round_box w h let patatoid_ w h = let p = Shapes.patatoid w h in let pic = Command.draw p in Picture.width pic, Picture.height pic, p let patatoid2_ w h = let p = Shapes.patatoid2 w h in let pic = Command.draw p in Picture.width pic, Picture.height pic, p let from_style = function | Rect -> rect_ | Circle -> circ_ | RoundRect -> round_rect_ | Patatoid -> patatoid_ | Patatoid2 -> patatoid2_ | Ellipse -> ellipse_ | RoundBox -> round_box_ | Custom f -> f let make_contour s ?(dx=margin) ?(dy=margin) w h c = let w = w +/ 2. *./ dx and h = h +/ 2. *./ dy in let w,h, p = (from_style s) w h in w, h, Path.shift c p let no_drawing _ = Command.nop let fresh_name = let x = ref 1 in (fun () -> incr x; Name.Internal (!x) ) let mkbox ?(style=Rect) ?dx ?dy ?name ?brush ?(stroke=Some Color.black) ?pen ?dash ?fill ?(pre_draw=no_drawing) ?(post_draw=no_drawing) w h c desc = let w,h,s = make_contour style ?dx ?dy w h c in let b = Brush.t ?pen ?dash ?color:stroke ?brush () in let name = match name with | None -> fresh_name () | Some s -> Name.Userdef s in { desc = desc; name = name; stroke = Brush.color b; pen = Brush.pen b; fill = fill; dash = Brush.dash b; width = w; height = h; ctr = c; contour = s; post_draw = post_draw; pre_draw = pre_draw } let pic ?style ?dx ?dy ?name ?brush ?(stroke=None) ?pen ?dash ?fill pic = let c = Picture.ctr pic in mkbox ?style ?dx ?dy ?name ?brush ~stroke ?pen ?dash ?fill (Picture.width pic) (Picture.height pic) c (Pic pic) let merge_maps = let add_one m b = let m = match b.desc with | Emp | Pic _ -> m | Grp (_, m') -> NMap.fold NMap.add m' m in NMap.add b.name b m in List.fold_left add_one NMap.empty let box ?style ?dx ?dy ?name ?brush ?stroke ?pen ?dash ?fill b = mkbox ?style ?dx ?dy ?name ?brush ?stroke ?pen ?dash ?fill (width b) (height b) (ctr b) (Grp ([|b|], merge_maps [b] )) let path ?style ?dx ?dy ?name ?brush ?(stroke=None) ?pen ?dash ?fill p = pic ?style ?dx ?dy ?name ?brush ~stroke ?pen ?dash ?fill (Picture.make (Command.draw p)) let empty ?(width=Num.zero) ?(height=Num.zero) ?style ?name ?brush ?(stroke=None) ?pen ?dash ?fill () = mkbox ?style ?name ~dx:zero ~dy:zero ?brush ~stroke ?pen ?dash ?fill width height Point.origin Emp let empty_from_box ?style ?name ?brush ?(stroke=None) ?pen ?dash ?fill box = mkbox ?style ?name ?brush ~stroke ?pen ?dash ?fill (width box) (height box) (ctr box) Emp (* groups the given boxes in a new box *) let group ?style ?(dx=Num.zero) ?(dy=Num.zero) ?name ?brush ?(stroke=None) ?pen ?dash ?fill bl = let xmin b = xpart (south_west b) in let xmax b = xpart (north_east b) in let ymin b = ypart (south_west b) in let ymax b = ypart (north_east b) in match bl with | [] -> empty ~width:dx ~height:dy ?style ?name ?brush ~stroke ?pen ?dash ?fill () | [b] -> box ?style ~dx ~dy ?name ?brush ~stroke ?pen ?dash ?fill b | b::r -> let xmin,xmax,ymin,ymax = List.fold_left (fun (xmin',xmax',ymin',ymax') b -> (Num.minn xmin' (xmin b), Num.maxn xmax' (xmax b), Num.minn ymin' (ymin b), Num.maxn ymax' (ymax b))) (xmin b, xmax b, ymin b, ymax b) r in let w = xmax -/ xmin in let h = ymax -/ ymin in let c = Point.pt (xmin +/ w /./ 2., ymin +/ h /./ 2.) in mkbox ?style ~dx ~dy ?name ?brush ~stroke ?pen ?dash ?fill w h c (Grp (Array.of_list bl, merge_maps bl)) let group_array ?name ?brush ?stroke ?fill ?dx ?dy ba = group ?name ?brush ?stroke ?fill ?dx ?dy (Array.to_list ba) (* groups the given boxes in a rectangular shape of size [w,h] and center [c] *) let group_rect ?name ?(stroke=None) w h c bl = mkbox ~dx:zero ~dy:zero ?name ~stroke w h c (Grp (Array.of_list bl, merge_maps bl)) type 'a box_creator = ?dx:Num.t -> ?dy:Num.t -> ?name:string -> ?brush:Brush.t -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> 'a -> t let rect = box ~style:Rect let circle = box ~style:Circle let ellipse = box ~style:Ellipse let round_rect = box ~style:RoundRect let patatoid = box ~style:Patatoid let patatoid2 = box ~style:Patatoid2 let round_box = box ~style:RoundBox let tex ?style ?dx ?dy ?name ?brush ?(stroke=None) ?pen ?dash ?fill s = pic ?style ?dx ?dy ?name ?brush ~stroke ?pen ?dash ?fill (Picture.tex s) let nth i b = match b.desc with | Grp (a, _ ) -> let n = Array.length a - 1 in if i < 0 || i > n then invalid_arg (Format.sprintf "Box.nth: index %d out of 0..%d" i n); a.(i) | Emp -> invalid_arg "Box.nth: empty box" | Pic _ -> invalid_arg "Box.nth: picture box" let elts b = match b.desc with | Emp | Pic _ -> [||] | Grp (a, _) -> a let elts_list b = Array.to_list (elts b) let get' n b = if b.name = n then b else match b.desc with | Emp -> invalid_arg "Box.get: empty box" | Pic _ -> invalid_arg "Box.get: picture box" | Grp (_, m) -> try NMap.find n m with Not_found -> invalid_arg (Misc.sprintf "Box.get: no sub-box %a out of %a" Name.print n print_dom m) let get n b = get' (Name.Userdef n) b let sub b1 b2 = get' b1.name b2 let relative b g = let b' = sub b g in let v = Point.sub (ctr b) (ctr b') in shift v g let get_fill b = b.fill let set_fill c b = { b with fill = Some c } let get_stroke b = b.stroke let set_stroke s b = {b with stroke = Some s } let clear_stroke b = { b with stroke = None } let get_name b = match b.name with | Name.Internal _ -> None | Name.Userdef s -> Some s let get_dash b = b.dash let set_dash d b = {b with dash = Some d } let clear_dash b = {b with dash = None } let set_name name b = {b with name = Name.Userdef name} let set_post_draw f b = {b with post_draw = f} let set_pre_draw f b = {b with pre_draw = f} let add_post_draw f b = let d = b.post_draw in { b with post_draw = (fun t -> Command.append (d t) (f t)) } let clear_post_draw b = {b with post_draw = no_drawing } let clear_pre_draw b = {b with pre_draw = no_drawing } let shadow b = let shadow b = let shad i = let d = bp (i /. 2.) in Command.fill ~color:(Color.gray (0.2 +. i *. 0.2)) (Path.shift (Point.pt (d, d)) (bpath b)) in Command.seq (List.rev_map shad [1. ; 2. ; 3.]) in { b with pre_draw = shadow } let get_pen b = b.pen let set_pen p b = { b with pen = Some p } let set_contour c b = { b with contour = c } (* new box primitives *) let ycoord pos a = (* get the vertical position of a box, using a either Top, Bot or the center as reference *) match vreduce pos with | `Custom c -> c a | #Types.vposition_red as p -> match p with | `Center -> ypart (ctr a) | (`North | `South) as x -> border x a let xcoord pos a = (* get the horizontal position of a box, using a either Left, Right or the center as reference *) match hreduce pos with | `Custom c -> c a | #Types.hposition_red as p -> match p with | `Center -> xpart (ctr a) | (`West | `East) as x -> border x a let box_fold f acc l = let _, l = List.fold_left (fun (acc,l) b -> let acc, b = f acc b in acc, b::l) (acc,[]) l in List.rev l let halign ?(pos : vposition =`Center) y l = List.map (fun b -> shift (Point.pt (zero, y -/ ycoord pos b)) b) l let set_height pos h b = let nc = match vreduce pos with | `Center -> ypart b.ctr | `North -> ypart b.ctr +/ (b.height -/ h) /./ 2. | `South -> ypart b.ctr -/ (b.height -/ h) /./ 2. | `Custom c -> let n = c b in n +/ ((ypart b.ctr -/ n) */ (h // b.height)) in { b with height = h; ctr = Point.pt (xpart b.ctr, nc) } let set_width pos w b = let nc = match hreduce pos with | `Center -> xpart b.ctr | `West -> xpart b.ctr -/ (b.width -/ w) /./ 2. | `East -> xpart b.ctr +/ (b.width -/ w) /./ 2. | `Custom c -> let n = c b in n +/ ((xpart b.ctr -/ n) */ (w // b.width)) in { b with width = w; ctr = Point.pt (nc, ypart b.ctr) } let set_gen2 mycorner chdim pos1 y1 pos2 y2 box = let pos1 = mycorner pos1 box in let pos2 = mycorner pos2 box in let a = (y1 -/ y2) // (pos1 -/ pos2) in let b = ((y2 */ pos1) -/ (y1 */ pos2)) // (pos1 -/ pos2) in let w,h = chdim (fun x -> a */ x) (box.width,box.height) in let ctr = chdim (fun x -> a */ x +/ b) (xpart box.ctr,ypart box.ctr) in { box with width = w; height = h; ctr = Point.pt ctr } let set_height2 pos1 y1 pos2 y2 b = set_gen2 cornerv (fun conv (x,y) -> (x, conv y)) pos1 y1 pos2 y2 b let set_width2 pos1 y1 pos2 y2 b = set_gen2 cornerh (fun conv (x,y) -> (conv x,y)) pos1 y1 pos2 y2 b let valign ?(pos=`Center) x l = List.map (fun b -> shift (Point.pt (x -/ xcoord pos b, zero)) b) l let extractv pos = match pos_reduce pos with | `Northwest | `North | `Northeast -> `North | `West | `Center | `East -> `Center | `Southwest | `South | `Southeast -> `South | `Custom c -> `Custom (fun t -> ypart (c t)) let extracth pos = match pos_reduce pos with | `Northwest | `West | `Southwest -> `West | `North | `Center | `South -> `Center | `Northeast | `East | `Southeast -> `East | `Custom c -> `Custom (fun t -> xpart (c t)) let set_size pos ~width ~height b = set_height (extractv pos) height (set_width (extracth pos) width b) let max_height l = Num.fold_max height Num.zero l let max_width l = Num.fold_max width Num.zero l let same_size ?(pos=`Center) bl = List.map (set_size pos ~width:(max_width bl) ~height:(max_height bl)) bl let same_height ?(pos=`Center) bl = List.map (set_height pos (max_height bl)) bl let same_width ?(pos=`Center) bl = List.map (set_width pos (max_width bl)) bl let hplace ?(padding=zero) ?(pos=`Center) ?(min_width=zero) ?(same_width=false) l = if l = [] then [] else let min_width = if same_width then Num.maxn (max_width l) min_width else min_width in let l = List.map (fun b -> set_width (extracth pos) (Num.maxn min_width b.width) b) l in let refb = List.hd l in let refc = ctr refb and refw = width refb in box_fold (fun x p -> x+/ p.width +/ padding, center (Point.pt (x +/ p.width /./ 2., ypart p.ctr)) p) (xpart refc -/ refw /./ 2.) l let vplace ?(padding=zero) ?(pos=`Center) ?(min_height=zero) ?(same_height=false) l = if l = [] then [] else let min_height = if same_height then Num.maxn (max_height l) min_height else min_height in let l = List.map (fun b -> set_height (extractv pos) (Num.maxn min_height b.height) b) l in let refb = List.hd l in let refc = ctr refb and refh = height refb in box_fold (fun y p -> y -/ p.height -/ padding, center (Point.pt (xpart p.ctr, y -/ p.height /./ 2.)) p) (ypart refc +/ refh /./ 2.) l let hbox_list ?padding ?(pos=`Center) ?min_width ?same_width l = match l with | [] -> [] | hd::_ -> let y = ypart (corner pos hd) in halign ~pos:(extractv pos) y (hplace ?padding ~pos:pos ?min_width ?same_width l) let vbox_list ?padding ?(pos=`Center) ?min_height ?same_height l = match l with | [] -> [] | hd::_ -> let x = xpart (corner pos hd) in let l = vplace ?padding ~pos ?min_height ?same_height l in valign ~pos:(extracth pos) x l let hequalize h l = List.map (set_height h) l let wequalize w l = List.map (set_width w) l let hbox ?padding ?pos ?style ?min_width ?same_width ?dx ?dy ?name ?brush ?stroke ?pen ?dash ?fill l = group ?style ?dx ?dy ?name ?brush ?stroke ?pen ?dash ?fill (hbox_list ?padding ?pos ?min_width ?same_width l) let vbox ?padding ?pos ?style ?min_height ?same_height ?dx ?dy ?name ?brush ?stroke ?pen ?dash ?fill l = group ?style ?dx ?dy ?name ?stroke ?pen ?dash ?fill (vbox_list ?padding ?pos ?min_height ?same_height l) let modify_box ?stroke ?pen ?dash b = let s = match stroke with | None -> Some Color.black | Some x -> x in { b with stroke = s; pen = pen; dash = dash; contour = Path.shift b.ctr (Shapes.rectangle b.width b.height) } let hblock ?padding ?(pos=`Center) ?name ?stroke ?pen ?dash ?min_width ?same_width pl = group ?name (List.map (modify_box ?stroke ?pen ?dash) (hbox_list ?padding ~pos ?min_width ?same_width (List.map (set_height (extractv pos) (max_height pl)) pl))) let vblock ?padding ?(pos=`Center) ?name ?stroke ?pen ?dash ?min_height ?same_height pl = group ?name (List.map (modify_box ?stroke ?pen ?dash) (vbox_list ?padding ~pos ?min_height ?same_height (List.map (set_width (extracth pos) (max_width pl)) pl))) let tabularl ?hpadding ?vpadding ?(pos=`Center) ?style ?name ?stroke ?pen ?dash ?fill pll = (* we first compute the widths of columns and heights of rows *) let hmaxl = List.map (Num.fold_max height Num.zero) pll in let rec calc_wmax pll = match pll with | [] :: _ -> [] | _ -> let cols, qll = List.fold_left (fun (col,rem) pl -> (List.hd pl :: col, List.tl pl :: rem)) ([],[]) pll in (Num.fold_max width Num.zero cols) :: (calc_wmax qll) in let wmaxl = calc_wmax pll in let pll = List.map2 (fun row height -> List.map2 (fun cell width -> set_size pos ~height ~width (group [cell])) row wmaxl ) pll hmaxl in vbox ?padding:vpadding ~pos ?style ?name ?stroke ?pen ?dash ?fill (List.map (fun r -> hbox ?padding:hpadding ~pos r) pll) let tabular ?(hpadding=Num.zero) ?(vpadding=Num.zero) ?pos ?style ?name ?stroke ?pen ?dash ?fill m = let pll = Array.to_list (Array.map Array.to_list m) in tabularl ~hpadding ~vpadding ?pos ?style ?name ?stroke ?pen ?dash ?fill pll let tabulari ?(hpadding=Num.zero) ?(vpadding=Num.zero) ?pos ?style ?name ?stroke ?pen ?dash ?fill w h f = let m = Array.init h (fun j -> Array.init w (fun i -> f i j)) in tabular ~hpadding ~vpadding ?pos ?style ?name ?stroke ?pen ?dash ?fill m let gridl ?hpadding ?vpadding ?(pos=`Center) ?stroke ?pen ?dash pll = let hmax = Num.fold_max (Num.fold_max height Num.zero) Num.zero pll in let wmax = Num.fold_max (Num.fold_max width Num.zero) Num.zero pll in let pll = List.map (fun l -> List.map (fun c -> set_height (extractv pos) hmax (set_width (extracth pos) wmax c)) l) pll in let pll = vbox_list ~pos ?padding:vpadding (List.map (fun r -> group (List.map (modify_box ?stroke ?pen ?dash) (hbox_list ?padding:hpadding ~pos r))) pll) in group pll let grid ?hpadding ?vpadding ?pos ?stroke ?pen ?dash m = let pll = Array.to_list (Array.map Array.to_list m) in gridl ?hpadding ?vpadding ?pos ?stroke ?pen ?dash pll let gridi ?hpadding ?vpadding ?pos ?stroke ?pen ?dash w h f = let m = Array.init h (fun j -> Array.init w (fun i -> f i j)) in grid ?hpadding ?vpadding ?pos ?stroke ?pen ?dash m let henlarge l = let toh f x = xpart (f x) in let min = Num.fold_min (toh west) (bp infinity) l in let max = Num.fold_max (toh east) (bp neg_infinity) l in List.map (set_width2 `West min `East max) l let venlarge l = let tow f x = ypart (f x) in let min = Num.fold_min (tow south) (bp infinity) l in let max = Num.fold_max (tow north) (bp neg_infinity) l in List.map (set_height2 `North max `South min) l module P = Path let strip ?sep p = match sep with | None -> p | Some n -> Path.strip n p let cpath ?style ?outd ?ind ?sep a b = let r,l = outd, ind in let p = P.pathk ?style [P.knotp ?r (ctr a); P.knotp ?l (ctr b)] in strip ?sep (P.cut_after (bpath b) (P.cut_before (bpath a) p)) let cpath_left ?style ?outd ?ind ?sep a b = let r,l = outd, ind in let p = P.pathk ?style [P.knotp ?r (ctr a); P.knotp ?l b] in strip ?sep (P.cut_before (bpath a) p) let cpath_right ?style ?outd ?ind ?sep a b = let r,l = outd, ind in let p = P.pathk ?style [P.knotp ?r a; P.knotp ?l (ctr b)] in strip ?sep (P.cut_after (bpath b) p) (* (* Deleted because of circular dependency with the Arrow module. It did not seem to be used anyway. *) let thick_arrow ?style ?(boxed=true) ?line_color ?fill_color ?outd ?ind ?width ?head_length ?head_width a b = let p = cpath a b in let pa = Path.point 0. p in let pb = Path.point 1. p in Arrow.draw_thick ?style ~boxed ?line_color ?fill_color ?outd ?ind ?width ?head_length ?head_width pa pb *) (* Specials Points *) let setp name pt box = let add_smap m = NMap.add (Name.Userdef name) (shift pt (empty ~name ())) m in { box with desc = match box.desc with | Emp -> Grp ([|box|], add_smap NMap.empty) | Pic _ -> Grp ([|box|], add_smap NMap.empty) | Grp (l,m) -> Grp (l, add_smap m)} let getp name box = ctr (get name box) let getpx name box = xpart (getp name box) let getpy name box = ypart (getp name box) (*let place_relative_to ?(same_height=false) ?(pos=`Center) ?pos2 ?(offset=Num.zero) ?(orientation) box1 box2 = let pos = pos_reduce pos in let pos2 = match pos2 with | None -> inverse_pos pos | Some s -> pos_reduce s in let [box1;box2] = if same_height then same_height [box1;box2] else [box1;box2] in let point1 = corner pos box1 in let point2 = corner pos box2 in let orient = match orient with | None -> Point.normalize (Point.sub point1 (ctr box1)) | Some s -> pos_reduce s in let vec = normalize *) (* placement *) let opposite_position: position -> position = function | #Types.position as x -> (Types.opposite_position x :> position) | `Custom f -> `Custom (fun b -> Point.sub (ctr b) (f b)) let place posa ?(pos = opposite_position posa) ?padding a b = let pa = corner posa a in let pb = corner pos b in let c = shift (Point.sub pa pb) b in match padding with | None -> c | Some padding -> shift (Point.mult padding (normalize (Point.sub pa (ctr a)))) c (* Boxlike *) let set_pos = center mlpost-0.8.2/brush.ml000066400000000000000000000054241306046515300145240ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types module Pen = Pen module Dash = struct include Dash let scaled = mkDScaled end type t = brush let opt_def def = function | None -> def | Some s -> s let opt_map f = function | None -> None | Some s -> Some (f s) let t color ?(pen) ?(dash) ?(scale) ?(brush) () = match scale with | None -> mkBrushOpt brush color pen dash | Some s -> mkBrushOpt brush color (Some (Pen.scale s (opt_def Pen.default pen))) (opt_map (Dash.scaled s) dash) (** {2 Predefined Colors} *) type brush_colored = ?pen:Pen.t -> ?dash:Dash.t -> ?scale:Num.t -> ?brush:t -> unit -> t (** {3 base colors} *) let white = t (Some Color.white) let black = t (Some Color.black) let red = t (Some Color.red) let blue = t (Some Color.blue) let green = t (Some Color.green) let cyan = t (Some Color.cyan) let yellow = t (Some Color.yellow) let magenta = t (Some Color.magenta) (** {3 lighter colors} *) let lightred = t (Some Color.lightred) let lightblue = t (Some Color.lightblue) let lightgreen = t (Some Color.lightgreen) let lightcyan = t (Some Color.lightcyan) let lightyellow = t (Some Color.lightyellow) let lightmagenta = t (Some Color.lightmagenta) (** {3 grays} *) let gray f = t (Some (Color.gray f)) let lightgray = t (Some Color.lightgray) let mediumgray = t (Some Color.mediumgray) let darkgray = t (Some Color.darkgray) (** {3 additional colors} *) let orange = t (Some Color.orange) let purple = t (Some Color.purple) let t ?color = t color let color t = t.Hashcons.node.color let pen (t:t) = (t.Hashcons.node.pen : Pen.t option) let dash t = t.Hashcons.node.dash mlpost-0.8.2/bugs/000077500000000000000000000000001306046515300140025ustar00rootroot00000000000000mlpost-0.8.2/bugs/arrows.ml000066400000000000000000000030141306046515300156470ustar00rootroot00000000000000open Mlpost open Num open Box open Command open Point open Path module Co = Color module P = Pen module T = Transform module N = Num module H = Helpers let a = -50., -12.5 let b = 0., -50. let c = 50., -12.5 let d = 0., 50. let e = 50., 12.5 let g = -50., 12.5 let [b;d] = List.map (fun (x,y) -> x,y+.50.) [b;d] let l1 = cycle (path ~style:jCurve [a; c; e; g]) let l2 = path ~style:jCurve [b; d] let l3 = path ~style:jCurve [a; c; e; g;d;b;c] let d1 = 1,seq [draw l1;draw l2] let d2 = 2,draw (cut_before l1 l2) let d3 = 3,draw (cut_before l2 l1) let d4 = 4,draw (cut_after l1 l2) let d5 = 5,draw (cut_after l2 l1) let d6 = 6, Arrow.simple l2 let d7 = let draw_direction p n = let po = point n p in let dir = direction n p in draw (pathp ~style:jLine [po;add po dir]) in 7, seq [draw l3; seq (List.map (draw_direction l3) [0.;1.;2.;2.9;3.;3.1;3.9;4.;4.1;5.;6.]) ] let min = -100. let max = 100. let b = (cycle ~style:jLine (path ~style:jLine [(min,min);(max,min);(max,max);(min,max)])) (* Pour avoir une echelle *) let embed (id,p) = id,seq [draw b;p] let figs = List.map embed [d1;d2;d3;d4;d5;d6;d7] let mpostfile = "testmanual" let cairostfile = "testmanual_cairo" let texfile = "arrows.tex" open Format let _ = ignore(Sys.command "mkdir -p arrows"); Sys.chdir "arrows"; Metapost.generate mpostfile ~pdf:true figs; Cairost.generate_pdfs cairostfile figs; Generate.generate_tex_cairo texfile "testmanual" "testmanual" "testmanual_cairo" figs mlpost-0.8.2/bugs/contributed2.ml000066400000000000000000000007121306046515300167400ustar00rootroot00000000000000open Mlpost open Command open Color open Box open Point open Num let repository ?wc patches = let pbox = circle (p (0., 0.)) patches in let p = draw_box ~fill: green pbox in let r = match wc with | None -> p | Some wc -> let c = label ~pos: Pbot wc (south pbox) in draw_box ~fill: yellow (circle (Point.p (0., 0.)) (Picture.make c)) in [ r ] let fig = repository ~wc: (Picture.tex "Copie de travail") (Picture.tex "Patches") mlpost-0.8.2/bugs/mp/000077500000000000000000000000001306046515300144165ustar00rootroot00000000000000mlpost-0.8.2/bugs/mp/architecture.ml000066400000000000000000000075261306046515300174440ustar00rootroot00000000000000open Mlpost open Box (* Some custom values *) let padding = Num.bp 15. let big_padding = Num.bp 30. let delta = Num.bp 5. let big_delta = Num.bp 10. let big_title s = tex ("\\textbf{\\Large{" ^ s ^ "}}") let small_title s = tex ("\\textbf{\\emph{\\large{" ^ s ^ "}}}") let external_color = Color.rgb8 255 165 0 let framac_color = Color.rgb8 50 205 50 let plugin_color = Color.lightcyan let cil_color = Color.rgb8 250 128 114 let std_box ?color s = rect ~name:s ?fill:color (tex s) let mk_services ?(big=false) ?color title b = round_rect ?fill:color ~name:title ~dx:padding ~dy:(if big then big_delta else delta) (vbox ~padding:big_delta [ (if big then big_title else small_title) title; b ]) let std_plugins = mk_services "Standard Plug-ins" (hbox ~padding [ std_box "Plug-in 1"; tex "\\dots"; std_box "Plug-in $n$" ]) let kernel_integrated_plugins = mk_services "Kernel-integrated Plug-ins" (hbox ~padding [ std_box "Plug-in 1"; tex "\\dots"; std_box "Plug-in $p$" ]) let plugins_types = mk_services "Kernel-integrated Plug-ins Types" ~color:plugin_color (hbox ~padding [ std_box "Plug-in types 1"; tex "\\dots"; std_box "Plug-in types $q$" ]) let kernel_frontend = mk_services ~color:framac_color "Plug-ins Values" (hbox ~padding [ std_box ~color:plugin_color "Db"; std_box "Dynamic" ]) let kernel_specific_services = mk_services "Specific Services" (vbox ~padding [ hbox ~padding [ std_box "AST Manipulation"; std_box "Memory States" ]; std_box "Abstract Interpretation Lattices"; std_box "Utilities" ]) let kernel_general_services = mk_services "General Services" (vbox ~padding [ std_box "Project"; hbox ~padding [std_box "Plugin"; std_box "Journal" ]; std_box "Cmdline"; hbox ~padding [ std_box "Type"; std_box "Log" ] ]) let cil = mk_services ~color:cil_color "Extended Cil" (vbox ~padding [ std_box "Extended Cil API"; rect ~name:"Cil Kernel" (vbox [ tex "Extended Cil Kernel"; tex "Lexing, Parsing, Typing, Linking" ]); std_box "Extended Cil AST" ]) let figure = vbox ~padding:big_padding [ mk_services ~big:true "Plug-ins" ~color:plugin_color (hbox ~padding:big_padding [ std_plugins; kernel_integrated_plugins ]); mk_services ~big:true ~color:framac_color "Plug-ins API inside Frama-C" (hbox ~padding:big_padding [ kernel_frontend; plugins_types ]); mk_services ~big:true "Frama-C Kernel" ~color:framac_color (hbox ~padding:big_padding [ kernel_specific_services; kernel_general_services ]); cil ] let arrow ?(big=false) src dst = let getf s = get s figure in let src = getf src in let dst = getf dst in if big then Helpers.box_arrow ~color:Color.red ~pen:Pen.circle src dst else Helpers.box_arrow src dst let cmds = Command.seq [ draw figure; (* Kernel Specific Services *) (* arrow "AST Manipulation" "Abstract Interpretation Lattices"; arrow "Memory States" "Abstract Interpretation Lattices"; arrow "Abstract Interpretation Lattices" "Utilities"; (* Kernel General Services *) arrow "Project" "Journal"; arrow "Journal" "Cmdline"; arrow "Cmdline" "Type"; arrow "Plugin" "Cmdline"; arrow "Cmdline" "Log"; (* Extended Cil *) arrow "Extended Cil API" "Cil Kernel"; arrow "Cil Kernel" "Extended Cil AST"; (* inter-services arrow *) arrow ~big:true "Plug-ins" "Plug-ins API inside Frama-C"; arrow ~big:true "Plug-ins Values" "Kernel-integrated Plug-ins Types"; arrow ~big:true "Plug-ins API inside Frama-C" "Frama-C Kernel"; arrow ~big:true "Specific Services" "General Services"; arrow ~big:true "Specific Services" "Extended Cil"; arrow ~big:true "Extended Cil" "General Services" ; *) ] let _ = Metapost.emit "architecture" cmds mlpost-0.8.2/bugs/mp/integrated_plugin.ml000066400000000000000000000175361306046515300204700ustar00rootroot00000000000000open Mlpost open Box (* Some custom values *) let padding = Num.bp 15. let delta = Num.bp 10. let unused = "$^\\star$" let big_title s = "\\textbf{\\Large{" ^ s ^ "}}" let small_title s = "\\textbf{\\large{" ^ s ^ "}}" let external_color = Color.rgb8 255 165 0 let internal_color = Color.rgb8 50 205 50 let plugin_color = Color.lightcyan let make_color = Color.rgb8 250 128 114 let intf_color = Color.rgb8 46 139 97 (* Some very useful functions: should be in some way in the mlpost API? *) let box_width ?name ?style ?fill ?dy w b = box ?name ?style ?fill ?dy ~dx:(Num.divf (Num.subn w (width b)) 2.) b let box_height ?name ?style ?fill ?dx h b = box ?name ?style ?fill ?dx ~dy:(Num.divf (Num.subn h (height b)) 2.) b let box_hw ?name ?style ?fill h b = box ?name ?style ?fill ~dx:(Num.divf (Num.subn h (width b)) 2.) ~dy:(Num.divf (Num.subn h (height b)) 2.) b let vbox_same_width ?name ?padding ~style l = let max = List.fold_left (fun acc b -> Num.maxn acc (width b)) Num.zero l in vbox ?name ?padding (List.map (fun b -> box_width max ~style ?fill:(get_fill b) ~dy:Num.zero (clear_stroke b)) l) let simulate_box ?name b = empty ?name ~width:(width b) ~height:(height b) () let xmed ?(coef=0.5) p1 p2 = Num.multf coef (Num.addn (Point.xpart p1) (Point.xpart p2)) let ymed ?(coef=0.5) p1 p2 = Num.multf coef (Num.addn (Point.ypart p1) (Point.ypart p2)) let med ?xcoef ?ycoef p1 p2 = Point.pt (xmed ?coef:xcoef p1 p2, ymed ?coef:ycoef p1 p2) (* Some special functions for this figure *) let modul ?(color=external_color) ?same_height ?same_width s = let t = tex s in match same_height, same_width with | None, None -> box ~name:s ~fill:color ~style:Rect t | Some h, None -> box_height ~name:s ~fill:color ~style:Rect h t | None, Some w -> box_width ~name:s ~fill:color ~style:Rect w t | Some h, Some w -> assert (h = w); box_hw ~name:s ~fill:color ~style:Rect w t (* The figure itself *) let fig = (* special external modules: Makefile.in + Design *) let design = rect ~fill:external_color ~name:"design" (vbox [ tex ("Design" ^ unused); tex "(GUI extension point)" ]) in let std_modul = modul ~same_height:(height design) in (* empty modules *) let empty_modules ?(color=internal_color) () = let empty_module = std_modul ~color ~same_width:(height design) "" in let points = tex "\\dots" in hbox ~padding [ empty_module; points; empty_module ] in let makein = std_modul ~color:make_color "Makefile.in" in let configurein = std_modul ~color:make_color "configure.in" in let autotools = hbox ~padding [ makein; configurein ] in let tests = round_rect ~name:"tests" ~fill:plugin_color ~dx:padding ~dy:delta (vbox ~padding:delta [ tex (small_title "Plug-in tests suite"); empty_modules ~color:plugin_color () ]) in let types = round_rect ~fill:intf_color ~dx:padding ~dy:delta (vbox ~padding:delta [ tex (small_title ("Plug-in types" ^ unused)); empty_modules ~color:intf_color () ]) in (* Plug-in implem *) let title = tex (small_title "Plug-in implementation") in let register = std_modul ~color:internal_color "Register" in let options = std_modul ~color:internal_color "Options" in let b = vbox_same_width ~padding:delta ~style:Rect [ register; options ] in let b = vbox ~padding:delta [ title; b; empty_modules () ] in let implem = round_rect ~name:"implem" ~fill:internal_color ~dx:delta ~dy:delta b in (* Plug-in GUI *) let gui = tex (small_title "Plug-in GUI$^\\star$") in let gui = round_rect ~name:"gui" ~dx:delta ~dy:(Num.addn delta (Num.divf padding 2.)) ~fill:internal_color (vbox ~padding:delta [ gui; empty_modules () ]) in (* Makefile *) let makefile = let t = tex (small_title "Empty plug-in interface") in box_height ~name:"makefile" ~style:RoundRect ~fill:intf_color (Num.subn (height implem) (Num.addn (height gui) padding)) t in (* Makefile + Plug-in GUI *) let right_box = vbox_same_width ~name:"right" ~padding ~style:RoundRect [ makefile; gui ] in (* left column *) let db_main = std_modul "Db.Main" in let db = std_modul "Db" in let journal = std_modul ("Journal" ^ unused) in let plugin = std_modul "Plugin" in let prj = std_modul ("Project" ^ unused) in let typ = std_modul ("Type" ^ unused) in let left_box = vbox_same_width ~padding ~style:Rect [ db; db_main; plugin; typ; journal; prj ] in (* setting the components as a matrix *) let figure = hbox ~padding:(Num.multf 3. padding) [ left_box; tabularl ~hpadding:padding ~vpadding:(Num.multf 3. padding) [ [ tests; autotools ]; [ simulate_box ~name:"ei" implem; simulate_box ~name:"er" right_box ]; [ types; design ] ] ] in let getf s = get s figure in (* add the Plug-in directory and merge it in the matrix *) let nwp = north_west (getf "ei") in let sep = south_east (getf "er") in let main_box = hbox ~padding [ implem; right_box ] in let title = tex (big_title "Plug-in directory") in let b = vbox ~padding:delta [ title; main_box ] in let directory_box = let r = round_rect ~fill:plugin_color ~dx:padding ~dy:delta b in center (med nwp sep) r in (* caption *) let caption = tabularl ~pos:`Right ~hpadding:delta [ [ tex "\\textbf{Caption:}"; empty () ]; [ tex "$\\star$"; tex "part not covered in this tutorial" ]; [ hbox ~padding [ empty ~name:"c1" (); empty ~name:"c2" () ]; tex "registration points through hooks" ]; [ hbox ~padding [ empty ~name:"c3" (); empty ~name:"c4" () ]; tex "insertion points directly into the pointed file" ] ] in let full_box = vbox ~padding ~pos:` Right [ figure; caption ] in let draw_arrow ?(insert=false) l = let p = Path.pathp ~style:Path.jLine l in if insert then Arrow.simple ~color:Color.red ~pen:Pen.circle p else Arrow.simple p in let arrow ?insert pos src dst = let p1, p2 = match pos with | `West -> let p2 = west dst in Point.pt (Point.xpart (east src), Point.ypart p2), p2 | `East -> let p2 = east dst in Point.pt (Point.xpart (west src), Point.ypart p2), p2 | `South -> let p2 = south dst in Point.pt (Point.xpart p2, Point.ypart (north src)), p2 | `North -> let p2 = north dst in Point.pt (Point.xpart p2, Point.ypart (south src)), p2 in draw_arrow ?insert [ p1; p2 ] in let third_arrow coef ?insert ?(yscale=1.) src dst = let p1 = Point.yscale (Num.bp yscale) (west src) in let p4 = (*east dst*) (* JS: don't know why it doesn't work *) Point.pt (Point.xpart (east left_box), Point.ypart (east dst)) in let x = xmed ~coef p1 p4 in let p2 = Point.pt (x, Point.ypart p1) in let p3 = Point.pt (x, Point.ypart p4) in (* Why [Arrow.draw] does not provide the same result? *) draw_arrow ?insert [ p1; p2; p3; p4 ] in let getf s = get s full_box in Command.seq [ draw full_box; draw directory_box; arrow `East (getf "c1") (getf "c2"); arrow ~insert:true `East (getf "c3") (getf "c4"); arrow `North (get "gui" directory_box) (getf "design"); arrow ~insert:true `West (getf "tests") (getf "Makefile.in"); arrow ~insert:true `South directory_box (getf "Makefile.in"); arrow ~insert:true `South directory_box (getf "configure.in"); third_arrow ~insert:true 0.5 ~yscale:0.3 directory_box (getf "Db"); third_arrow 0.29 (get "Options" directory_box) (getf "Plugin"); third_arrow 0.32 (get "Register" directory_box) (getf "Db.Main"); third_arrow 0.4 ~yscale:1.23 (get "implem" directory_box) (getf ("Journal" ^ unused)); third_arrow 0.4 ~yscale:1.23 (get "implem" directory_box) (getf ("Type" ^ unused)); third_arrow 0.55 ~yscale:1.5 directory_box (getf ("Project" ^ unused)); ] let _ = Metapost.emit "integrated_plugin" fig mlpost-0.8.2/bugs/mp/makefiles.ml000066400000000000000000000050371306046515300167150ustar00rootroot00000000000000open Mlpost open Box (* Some custom values *) let small_padding = Num.bp 20. let padding = Num.bp 50. let delta = Num.bp 5. let big_title s = tex ("\\textbf{\\Large{" ^ s ^ "}}") let small_title s = tex ("\\textbf{\\emph{\\large{" ^ s ^ "}}}") let plugin_color = Color.rgb8 255 165 0 let framac_color = Color.rgb8 50 205 50 (*let plugin_color = Color.lightcyan*) let cil_color = Color.rgb8 250 128 114 let std_box color name s = round_rect ~name ~fill:color ~dx:delta ~dy:delta (tex s) let config = std_box framac_color "config" "Makefile.config.in" let framac = std_box framac_color "framac" "Makefile.in" let plugin = std_box framac_color "plugin" "Makefile.plugin" let dynamic = std_box framac_color "dynamic" "Makefile.dynamic" let spec1 = std_box plugin_color "spec1" "specific Makefile for plug-in 1" let dots = tex ~name:"dots" "$\\dots$" let specn = std_box plugin_color "specn" "specific Makefile for plug-in $n$" let spec_box = hbox ~padding:small_padding [ spec1; dots; specn ] let box0 = hbox ~padding:small_padding [ framac; dots; plugin ] let box1 = hbox ~padding [ box0; dynamic ] let caption = tabularl ~pos:`Right ~hpadding:delta [ [ tex "\\textbf{Caption:}"; empty () ]; [ hbox ~padding:small_padding [ tex ~name:"m1" "$m1$"; tex ~name:"m2" "$m2$" ]; tex "Makefile $m1$ is included into Makefile $m2$" ] ] let gen_box = vbox ~padding [ config; box1; spec_box ] let full_box = vbox ~padding:small_padding ~pos:`Right [ gen_box; caption ] let arrow ?outd ?style ?color src dst = let getf s = get s full_box in let src = getf src in let dst = getf dst in Helpers.box_arrow ?outd ?style ?color ~pen:Pen.circle src dst let plugin_fc scale = let p1 = west (get "plugin" full_box) in let p2 = east (get "framac" full_box) in let p3 = Point.segment 0.33 p1 p2 in let p4 = Point.segment 0.66 p1 p2 in let p3 = Point.yscale (Num.bp scale) p3 in let p4 = Point.yscale (Num.bp scale) p4 in arrow (* ~outd:(Path.vec p3 p4)*) ~style:(Path.jControls p3 p4) ~color:plugin_color "plugin" "framac" let cmds = Command.seq [ draw full_box; arrow ~color:framac_color "config" "framac"; arrow ~color:framac_color "config" "dynamic"; arrow ~color:framac_color "plugin" "dynamic"; arrow ~color:plugin_color "dynamic" "spec1"; (* arrow "dynamic" "dots";*) arrow ~color:plugin_color "dynamic" "specn"; (* arrow plugin_color "plugin" "framac";*) plugin_fc 0.8; plugin_fc 1.2; arrow "m1" "m2" ] let _ = Metapost.emit "makefiles" cmds mlpost-0.8.2/bugs/mp/plugin.ml000066400000000000000000000145721306046515300162570ustar00rootroot00000000000000open Mlpost open Box (* Some custom values *) let padding = Num.bp 15. let delta = Num.bp 10. let unused = "$^\\star$" let big_title s = "\\textbf{\\Large{" ^ s ^ "}}" let small_title s = "\\textbf{\\large{" ^ s ^ "}}" let external_color = Color.rgb8 255 165 0 let internal_color = Color.rgb8 50 205 50 let plugin_color = Color.lightcyan let make_color = (*Color.rgb8 46 139 97*) Color.rgb8 250 128 114 (* Some very useful functions: should be in some way in the mlpost API? *) let box_width ?name ?style ?fill ?dy w b = box ?name ?style ?fill ?dy ~dx:(Num.divf (Num.subn w (width b)) 2.) b let box_height ?name ?style ?fill ?dx h b = box ?name ?style ?fill ?dx ~dy:(Num.divf (Num.subn h (height b)) 2.) b let box_hw ?name ?style ?fill h b = box ?name ?style ?fill ~dx:(Num.divf (Num.subn h (width b)) 2.) ~dy:(Num.divf (Num.subn h (height b)) 2.) b let vbox_same_width ?name ?padding ~style l = let max = List.fold_left (fun acc b -> Num.maxn acc (width b)) Num.zero l in vbox ?name ?padding (List.map (fun b -> box_width max ~style ?fill:(get_fill b) ~dy:Num.zero (clear_stroke b)) l) let simulate_box ?name b = empty ?name ~width:(width b) ~height:(height b) () let xmed ?(coef=0.5) p1 p2 = Num.multf coef (Num.addn (Point.xpart p1) (Point.xpart p2)) let ymed ?(coef=0.5) p1 p2 = Num.multf coef (Num.addn (Point.ypart p1) (Point.ypart p2)) let med ?xcoef ?ycoef p1 p2 = Point.pt (xmed ?coef:xcoef p1 p2, ymed ?coef:ycoef p1 p2) (* Some special functions for this figure *) let modul ?(color=external_color) ?same_height ?same_width s = let t = tex s in match same_height, same_width with | None, None -> box ~name:s ~fill:color ~style:Rect t | Some h, None -> box_height ~name:s ~fill:color ~style:Rect h t | None, Some w -> box_width ~name:s ~fill:color ~style:Rect w t | Some h, Some w -> assert (h = w); box_hw ~name:s ~fill:color ~style:Rect w t (* The figure itself *) let fig = (* special external modules: Makefile.dynamic + Design *) let design = rect ~fill:external_color ~name:"design" (vbox [ tex ("Design" ^ unused); tex "(GUI extension point)" ]) in let std_modul = modul ~same_height:(height design) in let dynmake = std_modul ~color:make_color "Makefile.dynamic" in (* empty modules *) let empty_modules = let empty_module = std_modul ~color:internal_color ~same_width:(height design) "" in let points = tex "\\dots" in hbox ~padding [ empty_module; points; empty_module ] in (* Plug-in implem *) let title = tex (small_title "Plug-in implementation") in let register = std_modul ~color:internal_color "Register" in let options = std_modul ~color:internal_color "Options" in let b = vbox_same_width ~padding:delta ~style:Rect [ register; options ] in let b = vbox ~padding:delta [ title; b; empty_modules ] in let implem = round_rect ~name:"implem" ~fill:internal_color ~dx:delta ~dy:delta b in (* Plug-in GUI *) let gui = tex (small_title "Plug-in GUI$^\\star$") in let gui = round_rect ~name:"gui" ~dx:delta ~dy:(Num.addn delta (Num.divf padding 2.)) ~fill:internal_color (vbox ~padding:delta [ gui; empty_modules ]) in (* Makefile *) let makefile = let t = tex "\\large{Makefile}" in box_height ~name:"makefile" ~style:RoundRect ~fill:make_color (Num.subn (height implem) (Num.addn (height gui) padding)) t in (* Makefile + Plug-in GUI *) let right_box = vbox_same_width ~name:"right" ~padding ~style:RoundRect [ makefile; gui ] in (* left column *) let db = std_modul "Db.Main" in let dyn = std_modul ("Dynamic" ^ unused) in let journal = std_modul ("Journal" ^ unused) in let plugin = std_modul "Plugin" in let prj = std_modul ("Project" ^ unused) in let typ = std_modul ("Type" ^ unused) in let left_box = vbox_same_width ~padding ~style:Rect [ db; dyn; plugin; typ; journal; prj ] in (* setting the components as a matrix *) let figure = hbox ~padding:(Num.multf 3. padding) [ left_box; tabularl ~hpadding:padding ~vpadding:(Num.multf 3. padding) [ [ empty (); dynmake ]; [ simulate_box ~name:"ei" implem; simulate_box ~name:"er" right_box ]; [ empty (); design ] ] ] in let getf s = get s figure in (* add the Plug-in directory and merge it in the matrix *) let nwp = north_west (getf "ei") in let sep = south_east (getf "er") in let main_box = hbox ~padding [ implem; right_box ] in let title = tex (big_title "Plug-in directory") in let b = vbox ~padding:delta [ title; main_box ] in let directory_box = let r = round_rect ~fill:plugin_color ~dx:padding ~dy:delta b in center (med nwp sep) r in (* caption *) let caption = tabularl ~pos:`Right ~hpadding:delta [ [ tex "\\textbf{Caption:}"; empty () ]; [ tex "$\\star$"; tex "part not covered in this tutorial" ]; [ hbox ~padding [ empty ~name:"c1" (); empty ~name:"c2" () ]; tex "registration points" ] ] in let full_box = vbox ~padding ~pos:` Right [ figure; caption ] in let arrow src dst = Helpers.box_arrow src dst in let third_arrow coef ?(yscale=1.) src dst = let p1 = Point.yscale (Num.bp yscale) (west src) in let p4 = (*east dst*) (* JS: don't know why it doesn't work *) Point.pt (Point.xpart (east left_box), Point.ypart (east dst)) in let x = xmed ~coef p1 p4 in let p2 = Point.pt (x, Point.ypart p1) in let p3 = Point.pt (x, Point.ypart p4) in (* Why [Arrow.draw] does not provide the same result? *) Arrow.simple (Path.pathp ~style:Path.jLine [ p1; p2; p3; p4 ]) in let getf s = get s full_box in Command.seq [ draw full_box; draw directory_box; arrow (getf "c1") (getf "c2"); arrow (get "gui" directory_box) (getf "design"); arrow (get "makefile" directory_box) (getf "Makefile.dynamic"); third_arrow 0.32 (get "Options" directory_box) (getf "Plugin"); third_arrow 0.35 (get "Register" directory_box) (getf ("Dynamic" ^ unused)); third_arrow 0.35 (get "Register" directory_box) (getf "Db.Main"); third_arrow 0.4 ~yscale:1.23 (get "implem" directory_box) (getf ("Journal" ^ unused)); third_arrow 0.4 ~yscale:1.23 (get "implem" directory_box) (getf ("Type" ^ unused)); third_arrow 0.55 ~yscale:1.5 directory_box (getf ("Project" ^ unused)); ] let _ = Metapost.emit "plugin" fig mlpost-0.8.2/cairost.ml000066400000000000000000000065451306046515300150520ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) IFDEF CAIRO THEN let supported = true module M = Mps open Icairost let emit_pdf = emit_pdf let emit_ps = emit_ps let emit_png = emit_png let emit_svg = emit_svg let emit_pdfs = emit_pdfs type cairo_t = Cairo.t let emit_cairo = emit_cairo (*let emit_cairo = fun x -> ()*) let dump_pdf () = Queue.iter (fun (fname,fig) -> let pdfname = File.mk fname "pdf" in let pdfname_s = File.to_string pdfname in try emit_pdf pdfname_s fig with | Cairo.Error status -> Format.printf "An@ internal@ error@ occured@ during@ the\ generation@ of@ %s@ with@ Cairo :@ %s@." pdfname_s (Cairo.string_of_status status) | error -> Format.printf "An@ internal@ error@ occured@ during@ the\ @ generation@ of@ %s :@ %s@." pdfname_s (Printexc.to_string error) ) Defaults.figures let dump_pdfs fname = let figs = List.rev (Queue.fold (fun l (_,x) -> x::l) [] Defaults.figures) in emit_pdfs (fname^".pdf") figs let generate_pdfs pdffile figs = List.iter (fun (i,fig) -> emit_pdf ~msg_error:100. (Printf.sprintf "%s-%i.pdf" pdffile i) fig) figs let dump_ext ext f () = Queue.iter (fun (fname,fig) -> let s = File.to_string (File.mk fname ext) in f s fig) Defaults.figures let dump_ps = dump_ext "ps" emit_ps let dump_png = dump_ext "png" emit_png let dump_svg = dump_ext "svg" emit_svg ELSE let supported = false let float_of_num n = failwith "Cairost.float_of_num : not supported" let emit_pdf ?msg_error s c = failwith "Cairost.emit_pdf: not supported" let emit_png s c = failwith "Cairost.emit_png: not supported" let emit_ps s c = failwith "Cairost.emit_ps: not supported" let emit_svg s c = failwith "Cairost.emit_svg: not supported" let emit_pdfs s c = failwith "Cairost.emit_pdfs: not supported" let dump_pdf _ = failwith "Cairost.dump_pdf : not supported" let dump_pdfs _ = failwith "Cairost.dump_pdfs : not supported" let dump_ps _ = failwith "Cairost.dump_ps : not supported" let dump_png _ = failwith "Cairost.dump_png : not supported" let dump_svg _ = failwith "Cairost.dump_svg : not supported" let generate_pdfs _ _ = failwith "Cairost.generate_pdfs : not supported" type cairo_t = unit let emit_cairo _ _ _ = failwith "Cairost.emit_cairo : not supported" END mlpost-0.8.2/color.ml000066400000000000000000001356261306046515300145270ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Concrete_types type st = Concrete_types.scolor = | RGB of float * float * float | CMYK of float * float * float * float | Gray of float type t = Concrete_types.color = |OPAQUE of scolor |TRANSPARENT of float * scolor let rgb8 r g b = OPAQUE (RGB ((float r)/.255., (float g)/.255., (float b)/.255.)) let rgb8a r g b a = TRANSPARENT ((float a)/.255., RGB ((float r)/.255., (float g)/.255., (float b)/.255.)) let rgb_from_int i = let b = i land 0xFF in let g = (i land 0xFF00) lsr 8 in let r = (i land 0xFF0000) lsr 16 in rgb8 r g b (* http://en.wikipedia.org/wiki/HSL_and_HSV *) let hsv h s v = assert (0.<= s && s<=1.); assert (0.<= v && v<=1.); let c = v *. s in let h' = h /. 60. in let x = c *. (1. -. (abs_float ((mod_float h' 2.) -. 1.))) in let (r_1, g_1, b_1) = if 0. <= h' && h' < 1. then (c,x,0.) else if 1. <= h' && h' < 2. then (x,c,0.) else if 2. <= h' && h' < 3. then (0.,c,x) else if 3. <= h' && h' < 4. then (0.,x,c) else if 4. <= h' && h' < 5. then (x,0.,c) else if 5. <= h' && h' < 6. then (c,0.,x) else (0.,0.,0.) in let m = v -. c in OPAQUE (RGB (r_1 +. m, g_1 +. m, b_1 +. m)) let color_gen s v = let choices = ref [] in let value = 180. in let next = ref 0. in fun () -> let rec aux acc value current = function | [] -> assert (current = 0.); next := value; List.rev_append acc [true] | true::l -> aux (false::acc) (value/.2.) (current-.value) l | false::l -> next := current +. value; List.rev_append acc (true::l) in let res = !next in choices := aux [] value res !choices; hsv res s v let red = OPAQUE (RGB (1.0,0.0,0.0)) let lightred = OPAQUE (RGB (1.0,0.5,0.5)) let blue = OPAQUE (RGB (0.0,0.0,1.0)) let lightblue = rgb_from_int 0xADD8E6 let green = rgb_from_int 0x008000 let lightgreen = rgb_from_int 0x90EE90 let orange = rgb_from_int 0xFFA500 let purple = rgb_from_int 0x7F007F let magenta = OPAQUE (RGB (1.0,0.0,1.0)) let cyan = OPAQUE (RGB (0.0,1.0,1.0)) let lightcyan = rgb_from_int 0xE0FFFF let yellow = OPAQUE (RGB (1.0,1.0,0.0)) let lightyellow = rgb_from_int 0xFFFFE0 (* these colors do not correspond to neither X11 nor HTML colors - commented out*) (* let lightblue = OPAQUE (RGB (0.5,0.5,1.0)) *) (* let green = OPAQUE (RGB (0.0,1.0,0.0)) *) (* let lightgreen = OPAQUE (RGB (0.5,1.0,0.5)) *) (* let orange = OPAQUE (RGB (1.0,0.4,0.0)) *) (* let purple = OPAQUE (RGB (0.6,0.0,0.6)) *) (* let lightcyan = OPAQUE (RGB (0.5,1.0,1.0)) *) (* let lightyellow = OPAQUE (RGB (1.0,1.0,0.5)) *) let lightmagenta = OPAQUE (RGB (1.0,0.5,1.0)) let gray f = OPAQUE (Gray f) let white = gray 1.0 let lightgray = gray 0.75 let mediumgray = gray 0.5 let darkgray = gray 0.25 let black = gray 0.0 let default = black let rgb r g b = OPAQUE (RGB (r,g,b)) let rgba r g b a = TRANSPARENT (a,RGB (r,g,b)) let cmyk c m y k = OPAQUE (CMYK (c,m,y,k)) let cmyka c m y k a = TRANSPARENT (a,CMYK (c,m,y,k)) let is_opaque = function |OPAQUE _ -> true | _ -> false let opaque = function |TRANSPARENT (_,c) -> OPAQUE c | c -> c let transparent f = function |TRANSPARENT (f2,c) -> TRANSPARENT (f*.f2,c) |OPAQUE c -> TRANSPARENT (f,c) let colors : (string, t) Hashtbl.t = Hashtbl.create 91 let color n = Hashtbl.find colors n (** generated part *) let _ = Hashtbl.add colors "snow" (rgb8 255 250 250) let _ = Hashtbl.add colors "ghost" (rgb8 248 248 255) let _ = Hashtbl.add colors "GhostWhite" (rgb8 248 248 255) let _ = Hashtbl.add colors "white smoke" (rgb8 245 245 245) let _ = Hashtbl.add colors "WhiteSmoke" (rgb8 245 245 245) let _ = Hashtbl.add colors "gainsboro" (rgb8 220 220 220) let _ = Hashtbl.add colors "floral white" (rgb8 255 250 240) let _ = Hashtbl.add colors "FloralWhite" (rgb8 255 250 240) let _ = Hashtbl.add colors "old lace" (rgb8 253 245 230) let _ = Hashtbl.add colors "OldLace" (rgb8 253 245 230) let _ = Hashtbl.add colors "linen" (rgb8 250 240 230) let _ = Hashtbl.add colors "antique white" (rgb8 250 235 215) let _ = Hashtbl.add colors "AntiqueWhite" (rgb8 250 235 215) let _ = Hashtbl.add colors "papaya whip" (rgb8 255 239 213) let _ = Hashtbl.add colors "PapayaWhip" (rgb8 255 239 213) let _ = Hashtbl.add colors "blanched almond" (rgb8 255 235 205) let _ = Hashtbl.add colors "BlanchedAlmond" (rgb8 255 235 205) let _ = Hashtbl.add colors "bisque" (rgb8 255 228 196) let _ = Hashtbl.add colors "peach puff" (rgb8 255 218 185) let _ = Hashtbl.add colors "PeachPuff" (rgb8 255 218 185) let _ = Hashtbl.add colors "navajo white" (rgb8 255 222 173) let _ = Hashtbl.add colors "NavajoWhite" (rgb8 255 222 173) let _ = Hashtbl.add colors "moccasin" (rgb8 255 228 181) let _ = Hashtbl.add colors "cornsilk" (rgb8 255 248 220) let _ = Hashtbl.add colors "ivory" (rgb8 255 255 240) let _ = Hashtbl.add colors "lemon chiffon" (rgb8 255 250 205) let _ = Hashtbl.add colors "LemonChiffon" (rgb8 255 250 205) let _ = Hashtbl.add colors "seashell" (rgb8 255 245 238) let _ = Hashtbl.add colors "honeydew" (rgb8 240 255 240) let _ = Hashtbl.add colors "mint cream" (rgb8 245 255 250) let _ = Hashtbl.add colors "MintCream" (rgb8 245 255 250) let _ = Hashtbl.add colors "azure" (rgb8 240 255 255) let _ = Hashtbl.add colors "alice blue" (rgb8 240 248 255) let _ = Hashtbl.add colors "AliceBlue" (rgb8 240 248 255) let _ = Hashtbl.add colors "lavender" (rgb8 230 230 250) let _ = Hashtbl.add colors "lavender blush" (rgb8 255 240 245) let _ = Hashtbl.add colors "LavenderBlush" (rgb8 255 240 245) let _ = Hashtbl.add colors "misty rose" (rgb8 255 228 225) let _ = Hashtbl.add colors "MistyRose" (rgb8 255 228 225) let _ = Hashtbl.add colors "white" (rgb8 255 255 255) let _ = Hashtbl.add colors "black" (rgb8 0 0 0) let _ = Hashtbl.add colors "dark slate gray" (rgb8 47 79 79) let _ = Hashtbl.add colors "DarkSlateGray" (rgb8 47 79 79) let _ = Hashtbl.add colors "dark slate grey" (rgb8 47 79 79) let _ = Hashtbl.add colors "DarkSlateGrey" (rgb8 47 79 79) let _ = Hashtbl.add colors "dim gray" (rgb8 105 105 105) let _ = Hashtbl.add colors "DimGray" (rgb8 105 105 105) let _ = Hashtbl.add colors "dim grey" (rgb8 105 105 105) let _ = Hashtbl.add colors "DimGrey" (rgb8 105 105 105) let _ = Hashtbl.add colors "slate gray" (rgb8 112 128 144) let _ = Hashtbl.add colors "SlateGray" (rgb8 112 128 144) let _ = Hashtbl.add colors "slate grey" (rgb8 112 128 144) let _ = Hashtbl.add colors "SlateGrey" (rgb8 112 128 144) let _ = Hashtbl.add colors "light slate gray" (rgb8 119 136 153) let _ = Hashtbl.add colors "LightSlateGray" (rgb8 119 136 153) let _ = Hashtbl.add colors "light slate grey" (rgb8 119 136 153) let _ = Hashtbl.add colors "LightSlateGrey" (rgb8 119 136 153) let _ = Hashtbl.add colors "gray" (rgb8 190 190 190) let _ = Hashtbl.add colors "grey" (rgb8 190 190 190) let _ = Hashtbl.add colors "light grey" (rgb8 211 211 211) let _ = Hashtbl.add colors "LightGrey" (rgb8 211 211 211) let _ = Hashtbl.add colors "light gray" (rgb8 211 211 211) let _ = Hashtbl.add colors "LightGray" (rgb8 211 211 211) let _ = Hashtbl.add colors "midnight blue" (rgb8 25 25 112) let _ = Hashtbl.add colors "MidnightBlue" (rgb8 25 25 112) let _ = Hashtbl.add colors "navy" (rgb8 0 0 128) let _ = Hashtbl.add colors "navy blue" (rgb8 0 0 128) let _ = Hashtbl.add colors "NavyBlue" (rgb8 0 0 128) let _ = Hashtbl.add colors "cornflower blue" (rgb8 100 149 237) let _ = Hashtbl.add colors "CornflowerBlue" (rgb8 100 149 237) let _ = Hashtbl.add colors "dark slate blue" (rgb8 72 61 139) let _ = Hashtbl.add colors "DarkSlateBlue" (rgb8 72 61 139) let _ = Hashtbl.add colors "slate blue" (rgb8 106 90 205) let _ = Hashtbl.add colors "SlateBlue" (rgb8 106 90 205) let _ = Hashtbl.add colors "medium slate blue" (rgb8 123 104 238) let _ = Hashtbl.add colors "MediumSlateBlue" (rgb8 123 104 238) let _ = Hashtbl.add colors "light slate blue" (rgb8 132 112 255) let _ = Hashtbl.add colors "LightSlateBlue" (rgb8 132 112 255) let _ = Hashtbl.add colors "medium blue" (rgb8 0 0 205) let _ = Hashtbl.add colors "MediumBlue" (rgb8 0 0 205) let _ = Hashtbl.add colors "royal blue" (rgb8 65 105 225) let _ = Hashtbl.add colors "RoyalBlue" (rgb8 65 105 225) let _ = Hashtbl.add colors "blue" (rgb8 0 0 255) let _ = Hashtbl.add colors "dodger blue" (rgb8 30 144 255) let _ = Hashtbl.add colors "DodgerBlue" (rgb8 30 144 255) let _ = Hashtbl.add colors "deep sky blue" (rgb8 0 191 255) let _ = Hashtbl.add colors "DeepSkyBlue" (rgb8 0 191 255) let _ = Hashtbl.add colors "sky blue" (rgb8 135 206 235) let _ = Hashtbl.add colors "SkyBlue" (rgb8 135 206 235) let _ = Hashtbl.add colors "light sky blue" (rgb8 135 206 250) let _ = Hashtbl.add colors "LightSkyBlue" (rgb8 135 206 250) let _ = Hashtbl.add colors "steel blue" (rgb8 70 130 180) let _ = Hashtbl.add colors "SteelBlue" (rgb8 70 130 180) let _ = Hashtbl.add colors "light steel blue" (rgb8 176 196 222) let _ = Hashtbl.add colors "LightSteelBlue" (rgb8 176 196 222) let _ = Hashtbl.add colors "light blue" (rgb8 173 216 230) let _ = Hashtbl.add colors "LightBlue" (rgb8 173 216 230) let _ = Hashtbl.add colors "powder blue" (rgb8 176 224 230) let _ = Hashtbl.add colors "PowderBlue" (rgb8 176 224 230) let _ = Hashtbl.add colors "pale turquoise" (rgb8 175 238 238) let _ = Hashtbl.add colors "PaleTurquoise" (rgb8 175 238 238) let _ = Hashtbl.add colors "dark turquoise" (rgb8 0 206 209) let _ = Hashtbl.add colors "DarkTurquoise" (rgb8 0 206 209) let _ = Hashtbl.add colors "medium turquoise" (rgb8 72 209 204) let _ = Hashtbl.add colors "MediumTurquoise" (rgb8 72 209 204) let _ = Hashtbl.add colors "turquoise" (rgb8 64 224 208) let _ = Hashtbl.add colors "cyan" (rgb8 0 255 255) let _ = Hashtbl.add colors "light cyan" (rgb8 224 255 255) let _ = Hashtbl.add colors "LightCyan" (rgb8 224 255 255) let _ = Hashtbl.add colors "cadet blue" (rgb8 95 158 160) let _ = Hashtbl.add colors "CadetBlue" (rgb8 95 158 160) let _ = Hashtbl.add colors "medium aquamarine" (rgb8 102 205 170) let _ = Hashtbl.add colors "MediumAquamarine" (rgb8 102 205 170) let _ = Hashtbl.add colors "aquamarine" (rgb8 127 255 212) let _ = Hashtbl.add colors "dark green" (rgb8 0 100 0) let _ = Hashtbl.add colors "DarkGreen" (rgb8 0 100 0) let _ = Hashtbl.add colors "dark olive green" (rgb8 85 107 47) let _ = Hashtbl.add colors "DarkOliveGreen" (rgb8 85 107 47) let _ = Hashtbl.add colors "dark sea green" (rgb8 143 188 143) let _ = Hashtbl.add colors "DarkSeaGreen" (rgb8 143 188 143) let _ = Hashtbl.add colors "sea green" (rgb8 46 139 87) let _ = Hashtbl.add colors "SeaGreen" (rgb8 46 139 87) let _ = Hashtbl.add colors "medium sea green" (rgb8 60 179 113) let _ = Hashtbl.add colors "MediumSeaGreen" (rgb8 60 179 113) let _ = Hashtbl.add colors "light sea green" (rgb8 32 178 170) let _ = Hashtbl.add colors "LightSeaGreen" (rgb8 32 178 170) let _ = Hashtbl.add colors "pale green" (rgb8 152 251 152) let _ = Hashtbl.add colors "PaleGreen" (rgb8 152 251 152) let _ = Hashtbl.add colors "spring green" (rgb8 0 255 127) let _ = Hashtbl.add colors "SpringGreen" (rgb8 0 255 127) let _ = Hashtbl.add colors "lawn green" (rgb8 124 252 0) let _ = Hashtbl.add colors "LawnGreen" (rgb8 124 252 0) let _ = Hashtbl.add colors "green" (rgb8 0 255 0) let _ = Hashtbl.add colors "chartreuse" (rgb8 127 255 0) let _ = Hashtbl.add colors "medium spring green" (rgb8 0 250 154) let _ = Hashtbl.add colors "MediumSpringGreen" (rgb8 0 250 154) let _ = Hashtbl.add colors "green yellow" (rgb8 173 255 47) let _ = Hashtbl.add colors "GreenYellow" (rgb8 173 255 47) let _ = Hashtbl.add colors "lime green" (rgb8 50 205 50) let _ = Hashtbl.add colors "LimeGreen" (rgb8 50 205 50) let _ = Hashtbl.add colors "yellow green" (rgb8 154 205 50) let _ = Hashtbl.add colors "YellowGreen" (rgb8 154 205 50) let _ = Hashtbl.add colors "forest green" (rgb8 34 139 34) let _ = Hashtbl.add colors "ForestGreen" (rgb8 34 139 34) let _ = Hashtbl.add colors "olive drab" (rgb8 107 142 35) let _ = Hashtbl.add colors "OliveDrab" (rgb8 107 142 35) let _ = Hashtbl.add colors "dark khaki" (rgb8 189 183 107) let _ = Hashtbl.add colors "DarkKhaki" (rgb8 189 183 107) let _ = Hashtbl.add colors "khaki" (rgb8 240 230 140) let _ = Hashtbl.add colors "pale goldenrod" (rgb8 238 232 170) let _ = Hashtbl.add colors "PaleGoldenrod" (rgb8 238 232 170) let _ = Hashtbl.add colors "light goldenrod yellow" (rgb8 250 250 210) let _ = Hashtbl.add colors "LightGoldenrodYellow" (rgb8 250 250 210) let _ = Hashtbl.add colors "light yellow" (rgb8 255 255 224) let _ = Hashtbl.add colors "LightYellow" (rgb8 255 255 224) let _ = Hashtbl.add colors "yellow" (rgb8 255 255 0) let _ = Hashtbl.add colors "gold" (rgb8 255 215 0) let _ = Hashtbl.add colors "light goldenrod" (rgb8 238 221 130) let _ = Hashtbl.add colors "LightGoldenrod" (rgb8 238 221 130) let _ = Hashtbl.add colors "goldenrod" (rgb8 218 165 32) let _ = Hashtbl.add colors "dark goldenrod" (rgb8 184 134 11) let _ = Hashtbl.add colors "DarkGoldenrod" (rgb8 184 134 11) let _ = Hashtbl.add colors "rosy brown" (rgb8 188 143 143) let _ = Hashtbl.add colors "RosyBrown" (rgb8 188 143 143) let _ = Hashtbl.add colors "indian red" (rgb8 205 92 92) let _ = Hashtbl.add colors "IndianRed" (rgb8 205 92 92) let _ = Hashtbl.add colors "saddle brown" (rgb8 139 69 19) let _ = Hashtbl.add colors "SaddleBrown" (rgb8 139 69 19) let _ = Hashtbl.add colors "sienna" (rgb8 160 82 45) let _ = Hashtbl.add colors "peru" (rgb8 205 133 63) let _ = Hashtbl.add colors "burlywood" (rgb8 222 184 135) let _ = Hashtbl.add colors "beige" (rgb8 245 245 220) let _ = Hashtbl.add colors "wheat" (rgb8 245 222 179) let _ = Hashtbl.add colors "sandy brown" (rgb8 244 164 96) let _ = Hashtbl.add colors "SandyBrown" (rgb8 244 164 96) let _ = Hashtbl.add colors "tan" (rgb8 210 180 140) let _ = Hashtbl.add colors "chocolate" (rgb8 210 105 30) let _ = Hashtbl.add colors "firebrick" (rgb8 178 34 34) let _ = Hashtbl.add colors "brown" (rgb8 165 42 42) let _ = Hashtbl.add colors "dark salmon" (rgb8 233 150 122) let _ = Hashtbl.add colors "DarkSalmon" (rgb8 233 150 122) let _ = Hashtbl.add colors "salmon" (rgb8 250 128 114) let _ = Hashtbl.add colors "light salmon" (rgb8 255 160 122) let _ = Hashtbl.add colors "LightSalmon" (rgb8 255 160 122) let _ = Hashtbl.add colors "orange" (rgb8 255 165 0) let _ = Hashtbl.add colors "dark orange" (rgb8 255 140 0) let _ = Hashtbl.add colors "DarkOrange" (rgb8 255 140 0) let _ = Hashtbl.add colors "coral" (rgb8 255 127 80) let _ = Hashtbl.add colors "light coral" (rgb8 240 128 128) let _ = Hashtbl.add colors "LightCoral" (rgb8 240 128 128) let _ = Hashtbl.add colors "tomato" (rgb8 255 99 71) let _ = Hashtbl.add colors "orange red" (rgb8 255 69 0) let _ = Hashtbl.add colors "OrangeRed" (rgb8 255 69 0) let _ = Hashtbl.add colors "red" (rgb8 255 0 0) let _ = Hashtbl.add colors "hot pink" (rgb8 255 105 180) let _ = Hashtbl.add colors "HotPink" (rgb8 255 105 180) let _ = Hashtbl.add colors "deep pink" (rgb8 255 20 147) let _ = Hashtbl.add colors "DeepPink" (rgb8 255 20 147) let _ = Hashtbl.add colors "pink" (rgb8 255 192 203) let _ = Hashtbl.add colors "light pink" (rgb8 255 182 193) let _ = Hashtbl.add colors "LightPink" (rgb8 255 182 193) let _ = Hashtbl.add colors "pale violet red" (rgb8 219 112 147) let _ = Hashtbl.add colors "PaleVioletRed" (rgb8 219 112 147) let _ = Hashtbl.add colors "maroon" (rgb8 176 48 96) let _ = Hashtbl.add colors "medium violet red" (rgb8 199 21 133) let _ = Hashtbl.add colors "MediumVioletRed" (rgb8 199 21 133) let _ = Hashtbl.add colors "violet red" (rgb8 208 32 144) let _ = Hashtbl.add colors "VioletRed" (rgb8 208 32 144) let _ = Hashtbl.add colors "magenta" (rgb8 255 0 255) let _ = Hashtbl.add colors "violet" (rgb8 238 130 238) let _ = Hashtbl.add colors "plum" (rgb8 221 160 221) let _ = Hashtbl.add colors "orchid" (rgb8 218 112 214) let _ = Hashtbl.add colors "medium orchid" (rgb8 186 85 211) let _ = Hashtbl.add colors "MediumOrchid" (rgb8 186 85 211) let _ = Hashtbl.add colors "dark orchid" (rgb8 153 50 204) let _ = Hashtbl.add colors "DarkOrchid" (rgb8 153 50 204) let _ = Hashtbl.add colors "dark violet" (rgb8 148 0 211) let _ = Hashtbl.add colors "DarkViolet" (rgb8 148 0 211) let _ = Hashtbl.add colors "blue violet" (rgb8 138 43 226) let _ = Hashtbl.add colors "BlueViolet" (rgb8 138 43 226) let _ = Hashtbl.add colors "purple" (rgb8 160 32 240) let _ = Hashtbl.add colors "medium purple" (rgb8 147 112 219) let _ = Hashtbl.add colors "MediumPurple" (rgb8 147 112 219) let _ = Hashtbl.add colors "thistle" (rgb8 216 191 216) let _ = Hashtbl.add colors "snow1" (rgb8 255 250 250) let _ = Hashtbl.add colors "snow2" (rgb8 238 233 233) let _ = Hashtbl.add colors "snow3" (rgb8 205 201 201) let _ = Hashtbl.add colors "snow4" (rgb8 139 137 137) let _ = Hashtbl.add colors "seashell1" (rgb8 255 245 238) let _ = Hashtbl.add colors "seashell2" (rgb8 238 229 222) let _ = Hashtbl.add colors "seashell3" (rgb8 205 197 191) let _ = Hashtbl.add colors "seashell4" (rgb8 139 134 130) let _ = Hashtbl.add colors "AntiqueWhite1" (rgb8 255 239 219) let _ = Hashtbl.add colors "AntiqueWhite2" (rgb8 238 223 204) let _ = Hashtbl.add colors "AntiqueWhite3" (rgb8 205 192 176) let _ = Hashtbl.add colors "AntiqueWhite4" (rgb8 139 131 120) let _ = Hashtbl.add colors "bisque1" (rgb8 255 228 196) let _ = Hashtbl.add colors "bisque2" (rgb8 238 213 183) let _ = Hashtbl.add colors "bisque3" (rgb8 205 183 158) let _ = Hashtbl.add colors "bisque4" (rgb8 139 125 107) let _ = Hashtbl.add colors "PeachPuff1" (rgb8 255 218 185) let _ = Hashtbl.add colors "PeachPuff2" (rgb8 238 203 173) let _ = Hashtbl.add colors "PeachPuff3" (rgb8 205 175 149) let _ = Hashtbl.add colors "PeachPuff4" (rgb8 139 119 101) let _ = Hashtbl.add colors "NavajoWhite1" (rgb8 255 222 173) let _ = Hashtbl.add colors "NavajoWhite2" (rgb8 238 207 161) let _ = Hashtbl.add colors "NavajoWhite3" (rgb8 205 179 139) let _ = Hashtbl.add colors "NavajoWhite4" (rgb8 139 121 94) let _ = Hashtbl.add colors "LemonChiffon1" (rgb8 255 250 205) let _ = Hashtbl.add colors "LemonChiffon2" (rgb8 238 233 191) let _ = Hashtbl.add colors "LemonChiffon3" (rgb8 205 201 165) let _ = Hashtbl.add colors "LemonChiffon4" (rgb8 139 137 112) let _ = Hashtbl.add colors "cornsilk1" (rgb8 255 248 220) let _ = Hashtbl.add colors "cornsilk2" (rgb8 238 232 205) let _ = Hashtbl.add colors "cornsilk3" (rgb8 205 200 177) let _ = Hashtbl.add colors "cornsilk4" (rgb8 139 136 120) let _ = Hashtbl.add colors "ivory1" (rgb8 255 255 240) let _ = Hashtbl.add colors "ivory2" (rgb8 238 238 224) let _ = Hashtbl.add colors "ivory3" (rgb8 205 205 193) let _ = Hashtbl.add colors "ivory4" (rgb8 139 139 131) let _ = Hashtbl.add colors "honeydew1" (rgb8 240 255 240) let _ = Hashtbl.add colors "honeydew2" (rgb8 224 238 224) let _ = Hashtbl.add colors "honeydew3" (rgb8 193 205 193) let _ = Hashtbl.add colors "honeydew4" (rgb8 131 139 131) let _ = Hashtbl.add colors "LavenderBlush1" (rgb8 255 240 245) let _ = Hashtbl.add colors "LavenderBlush2" (rgb8 238 224 229) let _ = Hashtbl.add colors "LavenderBlush3" (rgb8 205 193 197) let _ = Hashtbl.add colors "LavenderBlush4" (rgb8 139 131 134) let _ = Hashtbl.add colors "MistyRose1" (rgb8 255 228 225) let _ = Hashtbl.add colors "MistyRose2" (rgb8 238 213 210) let _ = Hashtbl.add colors "MistyRose3" (rgb8 205 183 181) let _ = Hashtbl.add colors "MistyRose4" (rgb8 139 125 123) let _ = Hashtbl.add colors "azure1" (rgb8 240 255 255) let _ = Hashtbl.add colors "azure2" (rgb8 224 238 238) let _ = Hashtbl.add colors "azure3" (rgb8 193 205 205) let _ = Hashtbl.add colors "azure4" (rgb8 131 139 139) let _ = Hashtbl.add colors "SlateBlue1" (rgb8 131 111 255) let _ = Hashtbl.add colors "SlateBlue2" (rgb8 122 103 238) let _ = Hashtbl.add colors "SlateBlue3" (rgb8 105 89 205) let _ = Hashtbl.add colors "SlateBlue4" (rgb8 71 60 139) let _ = Hashtbl.add colors "RoyalBlue1" (rgb8 72 118 255) let _ = Hashtbl.add colors "RoyalBlue2" (rgb8 67 110 238) let _ = Hashtbl.add colors "RoyalBlue3" (rgb8 58 95 205) let _ = Hashtbl.add colors "RoyalBlue4" (rgb8 39 64 139) let _ = Hashtbl.add colors "blue1" (rgb8 0 0 255) let _ = Hashtbl.add colors "blue2" (rgb8 0 0 238) let _ = Hashtbl.add colors "blue3" (rgb8 0 0 205) let _ = Hashtbl.add colors "blue4" (rgb8 0 0 139) let _ = Hashtbl.add colors "DodgerBlue1" (rgb8 30 144 255) let _ = Hashtbl.add colors "DodgerBlue2" (rgb8 28 134 238) let _ = Hashtbl.add colors "DodgerBlue3" (rgb8 24 116 205) let _ = Hashtbl.add colors "DodgerBlue4" (rgb8 16 78 139) let _ = Hashtbl.add colors "SteelBlue1" (rgb8 99 184 255) let _ = Hashtbl.add colors "SteelBlue2" (rgb8 92 172 238) let _ = Hashtbl.add colors "SteelBlue3" (rgb8 79 148 205) let _ = Hashtbl.add colors "SteelBlue4" (rgb8 54 100 139) let _ = Hashtbl.add colors "DeepSkyBlue1" (rgb8 0 191 255) let _ = Hashtbl.add colors "DeepSkyBlue2" (rgb8 0 178 238) let _ = Hashtbl.add colors "DeepSkyBlue3" (rgb8 0 154 205) let _ = Hashtbl.add colors "DeepSkyBlue4" (rgb8 0 104 139) let _ = Hashtbl.add colors "SkyBlue1" (rgb8 135 206 255) let _ = Hashtbl.add colors "SkyBlue2" (rgb8 126 192 238) let _ = Hashtbl.add colors "SkyBlue3" (rgb8 108 166 205) let _ = Hashtbl.add colors "SkyBlue4" (rgb8 74 112 139) let _ = Hashtbl.add colors "LightSkyBlue1" (rgb8 176 226 255) let _ = Hashtbl.add colors "LightSkyBlue2" (rgb8 164 211 238) let _ = Hashtbl.add colors "LightSkyBlue3" (rgb8 141 182 205) let _ = Hashtbl.add colors "LightSkyBlue4" (rgb8 96 123 139) let _ = Hashtbl.add colors "SlateGray1" (rgb8 198 226 255) let _ = Hashtbl.add colors "SlateGray2" (rgb8 185 211 238) let _ = Hashtbl.add colors "SlateGray3" (rgb8 159 182 205) let _ = Hashtbl.add colors "SlateGray4" (rgb8 108 123 139) let _ = Hashtbl.add colors "LightSteelBlue1" (rgb8 202 225 255) let _ = Hashtbl.add colors "LightSteelBlue2" (rgb8 188 210 238) let _ = Hashtbl.add colors "LightSteelBlue3" (rgb8 162 181 205) let _ = Hashtbl.add colors "LightSteelBlue4" (rgb8 110 123 139) let _ = Hashtbl.add colors "LightBlue1" (rgb8 191 239 255) let _ = Hashtbl.add colors "LightBlue2" (rgb8 178 223 238) let _ = Hashtbl.add colors "LightBlue3" (rgb8 154 192 205) let _ = Hashtbl.add colors "LightBlue4" (rgb8 104 131 139) let _ = Hashtbl.add colors "LightCyan1" (rgb8 224 255 255) let _ = Hashtbl.add colors "LightCyan2" (rgb8 209 238 238) let _ = Hashtbl.add colors "LightCyan3" (rgb8 180 205 205) let _ = Hashtbl.add colors "LightCyan4" (rgb8 122 139 139) let _ = Hashtbl.add colors "PaleTurquoise1" (rgb8 187 255 255) let _ = Hashtbl.add colors "PaleTurquoise2" (rgb8 174 238 238) let _ = Hashtbl.add colors "PaleTurquoise3" (rgb8 150 205 205) let _ = Hashtbl.add colors "PaleTurquoise4" (rgb8 102 139 139) let _ = Hashtbl.add colors "CadetBlue1" (rgb8 152 245 255) let _ = Hashtbl.add colors "CadetBlue2" (rgb8 142 229 238) let _ = Hashtbl.add colors "CadetBlue3" (rgb8 122 197 205) let _ = Hashtbl.add colors "CadetBlue4" (rgb8 83 134 139) let _ = Hashtbl.add colors "turquoise1" (rgb8 0 245 255) let _ = Hashtbl.add colors "turquoise2" (rgb8 0 229 238) let _ = Hashtbl.add colors "turquoise3" (rgb8 0 197 205) let _ = Hashtbl.add colors "turquoise4" (rgb8 0 134 139) let _ = Hashtbl.add colors "cyan1" (rgb8 0 255 255) let _ = Hashtbl.add colors "cyan2" (rgb8 0 238 238) let _ = Hashtbl.add colors "cyan3" (rgb8 0 205 205) let _ = Hashtbl.add colors "cyan4" (rgb8 0 139 139) let _ = Hashtbl.add colors "DarkSlateGray1" (rgb8 151 255 255) let _ = Hashtbl.add colors "DarkSlateGray2" (rgb8 141 238 238) let _ = Hashtbl.add colors "DarkSlateGray3" (rgb8 121 205 205) let _ = Hashtbl.add colors "DarkSlateGray4" (rgb8 82 139 139) let _ = Hashtbl.add colors "aquamarine1" (rgb8 127 255 212) let _ = Hashtbl.add colors "aquamarine2" (rgb8 118 238 198) let _ = Hashtbl.add colors "aquamarine3" (rgb8 102 205 170) let _ = Hashtbl.add colors "aquamarine4" (rgb8 69 139 116) let _ = Hashtbl.add colors "DarkSeaGreen1" (rgb8 193 255 193) let _ = Hashtbl.add colors "DarkSeaGreen2" (rgb8 180 238 180) let _ = Hashtbl.add colors "DarkSeaGreen3" (rgb8 155 205 155) let _ = Hashtbl.add colors "DarkSeaGreen4" (rgb8 105 139 105) let _ = Hashtbl.add colors "SeaGreen1" (rgb8 84 255 159) let _ = Hashtbl.add colors "SeaGreen2" (rgb8 78 238 148) let _ = Hashtbl.add colors "SeaGreen3" (rgb8 67 205 128) let _ = Hashtbl.add colors "SeaGreen4" (rgb8 46 139 87) let _ = Hashtbl.add colors "PaleGreen1" (rgb8 154 255 154) let _ = Hashtbl.add colors "PaleGreen2" (rgb8 144 238 144) let _ = Hashtbl.add colors "PaleGreen3" (rgb8 124 205 124) let _ = Hashtbl.add colors "PaleGreen4" (rgb8 84 139 84) let _ = Hashtbl.add colors "SpringGreen1" (rgb8 0 255 127) let _ = Hashtbl.add colors "SpringGreen2" (rgb8 0 238 118) let _ = Hashtbl.add colors "SpringGreen3" (rgb8 0 205 102) let _ = Hashtbl.add colors "SpringGreen4" (rgb8 0 139 69) let _ = Hashtbl.add colors "green1" (rgb8 0 255 0) let _ = Hashtbl.add colors "green2" (rgb8 0 238 0) let _ = Hashtbl.add colors "green3" (rgb8 0 205 0) let _ = Hashtbl.add colors "green4" (rgb8 0 139 0) let _ = Hashtbl.add colors "chartreuse1" (rgb8 127 255 0) let _ = Hashtbl.add colors "chartreuse2" (rgb8 118 238 0) let _ = Hashtbl.add colors "chartreuse3" (rgb8 102 205 0) let _ = Hashtbl.add colors "chartreuse4" (rgb8 69 139 0) let _ = Hashtbl.add colors "OliveDrab1" (rgb8 192 255 62) let _ = Hashtbl.add colors "OliveDrab2" (rgb8 179 238 58) let _ = Hashtbl.add colors "OliveDrab3" (rgb8 154 205 50) let _ = Hashtbl.add colors "OliveDrab4" (rgb8 105 139 34) let _ = Hashtbl.add colors "DarkOliveGreen1" (rgb8 202 255 112) let _ = Hashtbl.add colors "DarkOliveGreen2" (rgb8 188 238 104) let _ = Hashtbl.add colors "DarkOliveGreen3" (rgb8 162 205 90) let _ = Hashtbl.add colors "DarkOliveGreen4" (rgb8 110 139 61) let _ = Hashtbl.add colors "khaki1" (rgb8 255 246 143) let _ = Hashtbl.add colors "khaki2" (rgb8 238 230 133) let _ = Hashtbl.add colors "khaki3" (rgb8 205 198 115) let _ = Hashtbl.add colors "khaki4" (rgb8 139 134 78) let _ = Hashtbl.add colors "LightGoldenrod1" (rgb8 255 236 139) let _ = Hashtbl.add colors "LightGoldenrod2" (rgb8 238 220 130) let _ = Hashtbl.add colors "LightGoldenrod3" (rgb8 205 190 112) let _ = Hashtbl.add colors "LightGoldenrod4" (rgb8 139 129 76) let _ = Hashtbl.add colors "LightYellow1" (rgb8 255 255 224) let _ = Hashtbl.add colors "LightYellow2" (rgb8 238 238 209) let _ = Hashtbl.add colors "LightYellow3" (rgb8 205 205 180) let _ = Hashtbl.add colors "LightYellow4" (rgb8 139 139 122) let _ = Hashtbl.add colors "yellow1" (rgb8 255 255 0) let _ = Hashtbl.add colors "yellow2" (rgb8 238 238 0) let _ = Hashtbl.add colors "yellow3" (rgb8 205 205 0) let _ = Hashtbl.add colors "yellow4" (rgb8 139 139 0) let _ = Hashtbl.add colors "gold1" (rgb8 255 215 0) let _ = Hashtbl.add colors "gold2" (rgb8 238 201 0) let _ = Hashtbl.add colors "gold3" (rgb8 205 173 0) let _ = Hashtbl.add colors "gold4" (rgb8 139 117 0) let _ = Hashtbl.add colors "goldenrod1" (rgb8 255 193 37) let _ = Hashtbl.add colors "goldenrod2" (rgb8 238 180 34) let _ = Hashtbl.add colors "goldenrod3" (rgb8 205 155 29) let _ = Hashtbl.add colors "goldenrod4" (rgb8 139 105 20) let _ = Hashtbl.add colors "DarkGoldenrod1" (rgb8 255 185 15) let _ = Hashtbl.add colors "DarkGoldenrod2" (rgb8 238 173 14) let _ = Hashtbl.add colors "DarkGoldenrod3" (rgb8 205 149 12) let _ = Hashtbl.add colors "DarkGoldenrod4" (rgb8 139 101 8) let _ = Hashtbl.add colors "RosyBrown1" (rgb8 255 193 193) let _ = Hashtbl.add colors "RosyBrown2" (rgb8 238 180 180) let _ = Hashtbl.add colors "RosyBrown3" (rgb8 205 155 155) let _ = Hashtbl.add colors "RosyBrown4" (rgb8 139 105 105) let _ = Hashtbl.add colors "IndianRed1" (rgb8 255 106 106) let _ = Hashtbl.add colors "IndianRed2" (rgb8 238 99 99) let _ = Hashtbl.add colors "IndianRed3" (rgb8 205 85 85) let _ = Hashtbl.add colors "IndianRed4" (rgb8 139 58 58) let _ = Hashtbl.add colors "sienna1" (rgb8 255 130 71) let _ = Hashtbl.add colors "sienna2" (rgb8 238 121 66) let _ = Hashtbl.add colors "sienna3" (rgb8 205 104 57) let _ = Hashtbl.add colors "sienna4" (rgb8 139 71 38) let _ = Hashtbl.add colors "burlywood1" (rgb8 255 211 155) let _ = Hashtbl.add colors "burlywood2" (rgb8 238 197 145) let _ = Hashtbl.add colors "burlywood3" (rgb8 205 170 125) let _ = Hashtbl.add colors "burlywood4" (rgb8 139 115 85) let _ = Hashtbl.add colors "wheat1" (rgb8 255 231 186) let _ = Hashtbl.add colors "wheat2" (rgb8 238 216 174) let _ = Hashtbl.add colors "wheat3" (rgb8 205 186 150) let _ = Hashtbl.add colors "wheat4" (rgb8 139 126 102) let _ = Hashtbl.add colors "tan1" (rgb8 255 165 79) let _ = Hashtbl.add colors "tan2" (rgb8 238 154 73) let _ = Hashtbl.add colors "tan3" (rgb8 205 133 63) let _ = Hashtbl.add colors "tan4" (rgb8 139 90 43) let _ = Hashtbl.add colors "chocolate1" (rgb8 255 127 36) let _ = Hashtbl.add colors "chocolate2" (rgb8 238 118 33) let _ = Hashtbl.add colors "chocolate3" (rgb8 205 102 29) let _ = Hashtbl.add colors "chocolate4" (rgb8 139 69 19) let _ = Hashtbl.add colors "firebrick1" (rgb8 255 48 48) let _ = Hashtbl.add colors "firebrick2" (rgb8 238 44 44) let _ = Hashtbl.add colors "firebrick3" (rgb8 205 38 38) let _ = Hashtbl.add colors "firebrick4" (rgb8 139 26 26) let _ = Hashtbl.add colors "brown1" (rgb8 255 64 64) let _ = Hashtbl.add colors "brown2" (rgb8 238 59 59) let _ = Hashtbl.add colors "brown3" (rgb8 205 51 51) let _ = Hashtbl.add colors "brown4" (rgb8 139 35 35) let _ = Hashtbl.add colors "salmon1" (rgb8 255 140 105) let _ = Hashtbl.add colors "salmon2" (rgb8 238 130 98) let _ = Hashtbl.add colors "salmon3" (rgb8 205 112 84) let _ = Hashtbl.add colors "salmon4" (rgb8 139 76 57) let _ = Hashtbl.add colors "LightSalmon1" (rgb8 255 160 122) let _ = Hashtbl.add colors "LightSalmon2" (rgb8 238 149 114) let _ = Hashtbl.add colors "LightSalmon3" (rgb8 205 129 98) let _ = Hashtbl.add colors "LightSalmon4" (rgb8 139 87 66) let _ = Hashtbl.add colors "orange1" (rgb8 255 165 0) let _ = Hashtbl.add colors "orange2" (rgb8 238 154 0) let _ = Hashtbl.add colors "orange3" (rgb8 205 133 0) let _ = Hashtbl.add colors "orange4" (rgb8 139 90 0) let _ = Hashtbl.add colors "DarkOrange1" (rgb8 255 127 0) let _ = Hashtbl.add colors "DarkOrange2" (rgb8 238 118 0) let _ = Hashtbl.add colors "DarkOrange3" (rgb8 205 102 0) let _ = Hashtbl.add colors "DarkOrange4" (rgb8 139 69 0) let _ = Hashtbl.add colors "coral1" (rgb8 255 114 86) let _ = Hashtbl.add colors "coral2" (rgb8 238 106 80) let _ = Hashtbl.add colors "coral3" (rgb8 205 91 69) let _ = Hashtbl.add colors "coral4" (rgb8 139 62 47) let _ = Hashtbl.add colors "tomato1" (rgb8 255 99 71) let _ = Hashtbl.add colors "tomato2" (rgb8 238 92 66) let _ = Hashtbl.add colors "tomato3" (rgb8 205 79 57) let _ = Hashtbl.add colors "tomato4" (rgb8 139 54 38) let _ = Hashtbl.add colors "OrangeRed1" (rgb8 255 69 0) let _ = Hashtbl.add colors "OrangeRed2" (rgb8 238 64 0) let _ = Hashtbl.add colors "OrangeRed3" (rgb8 205 55 0) let _ = Hashtbl.add colors "OrangeRed4" (rgb8 139 37 0) let _ = Hashtbl.add colors "red1" (rgb8 255 0 0) let _ = Hashtbl.add colors "red2" (rgb8 238 0 0) let _ = Hashtbl.add colors "red3" (rgb8 205 0 0) let _ = Hashtbl.add colors "red4" (rgb8 139 0 0) let _ = Hashtbl.add colors "DebianRed" (rgb8 215 7 81) let _ = Hashtbl.add colors "DeepPink1" (rgb8 255 20 147) let _ = Hashtbl.add colors "DeepPink2" (rgb8 238 18 137) let _ = Hashtbl.add colors "DeepPink3" (rgb8 205 16 118) let _ = Hashtbl.add colors "DeepPink4" (rgb8 139 10 80) let _ = Hashtbl.add colors "HotPink1" (rgb8 255 110 180) let _ = Hashtbl.add colors "HotPink2" (rgb8 238 106 167) let _ = Hashtbl.add colors "HotPink3" (rgb8 205 96 144) let _ = Hashtbl.add colors "HotPink4" (rgb8 139 58 98) let _ = Hashtbl.add colors "pink1" (rgb8 255 181 197) let _ = Hashtbl.add colors "pink2" (rgb8 238 169 184) let _ = Hashtbl.add colors "pink3" (rgb8 205 145 158) let _ = Hashtbl.add colors "pink4" (rgb8 139 99 108) let _ = Hashtbl.add colors "LightPink1" (rgb8 255 174 185) let _ = Hashtbl.add colors "LightPink2" (rgb8 238 162 173) let _ = Hashtbl.add colors "LightPink3" (rgb8 205 140 149) let _ = Hashtbl.add colors "LightPink4" (rgb8 139 95 101) let _ = Hashtbl.add colors "PaleVioletRed1" (rgb8 255 130 171) let _ = Hashtbl.add colors "PaleVioletRed2" (rgb8 238 121 159) let _ = Hashtbl.add colors "PaleVioletRed3" (rgb8 205 104 137) let _ = Hashtbl.add colors "PaleVioletRed4" (rgb8 139 71 93) let _ = Hashtbl.add colors "maroon1" (rgb8 255 52 179) let _ = Hashtbl.add colors "maroon2" (rgb8 238 48 167) let _ = Hashtbl.add colors "maroon3" (rgb8 205 41 144) let _ = Hashtbl.add colors "maroon4" (rgb8 139 28 98) let _ = Hashtbl.add colors "VioletRed1" (rgb8 255 62 150) let _ = Hashtbl.add colors "VioletRed2" (rgb8 238 58 140) let _ = Hashtbl.add colors "VioletRed3" (rgb8 205 50 120) let _ = Hashtbl.add colors "VioletRed4" (rgb8 139 34 82) let _ = Hashtbl.add colors "magenta1" (rgb8 255 0 255) let _ = Hashtbl.add colors "magenta2" (rgb8 238 0 238) let _ = Hashtbl.add colors "magenta3" (rgb8 205 0 205) let _ = Hashtbl.add colors "magenta4" (rgb8 139 0 139) let _ = Hashtbl.add colors "orchid1" (rgb8 255 131 250) let _ = Hashtbl.add colors "orchid2" (rgb8 238 122 233) let _ = Hashtbl.add colors "orchid3" (rgb8 205 105 201) let _ = Hashtbl.add colors "orchid4" (rgb8 139 71 137) let _ = Hashtbl.add colors "plum1" (rgb8 255 187 255) let _ = Hashtbl.add colors "plum2" (rgb8 238 174 238) let _ = Hashtbl.add colors "plum3" (rgb8 205 150 205) let _ = Hashtbl.add colors "plum4" (rgb8 139 102 139) let _ = Hashtbl.add colors "MediumOrchid1" (rgb8 224 102 255) let _ = Hashtbl.add colors "MediumOrchid2" (rgb8 209 95 238) let _ = Hashtbl.add colors "MediumOrchid3" (rgb8 180 82 205) let _ = Hashtbl.add colors "MediumOrchid4" (rgb8 122 55 139) let _ = Hashtbl.add colors "DarkOrchid1" (rgb8 191 62 255) let _ = Hashtbl.add colors "DarkOrchid2" (rgb8 178 58 238) let _ = Hashtbl.add colors "DarkOrchid3" (rgb8 154 50 205) let _ = Hashtbl.add colors "DarkOrchid4" (rgb8 104 34 139) let _ = Hashtbl.add colors "purple1" (rgb8 155 48 255) let _ = Hashtbl.add colors "purple2" (rgb8 145 44 238) let _ = Hashtbl.add colors "purple3" (rgb8 125 38 205) let _ = Hashtbl.add colors "purple4" (rgb8 85 26 139) let _ = Hashtbl.add colors "MediumPurple1" (rgb8 171 130 255) let _ = Hashtbl.add colors "MediumPurple2" (rgb8 159 121 238) let _ = Hashtbl.add colors "MediumPurple3" (rgb8 137 104 205) let _ = Hashtbl.add colors "MediumPurple4" (rgb8 93 71 139) let _ = Hashtbl.add colors "thistle1" (rgb8 255 225 255) let _ = Hashtbl.add colors "thistle2" (rgb8 238 210 238) let _ = Hashtbl.add colors "thistle3" (rgb8 205 181 205) let _ = Hashtbl.add colors "thistle4" (rgb8 139 123 139) let _ = Hashtbl.add colors "gray0" (rgb8 0 0 0) let _ = Hashtbl.add colors "grey0" (rgb8 0 0 0) let _ = Hashtbl.add colors "gray1" (rgb8 3 3 3) let _ = Hashtbl.add colors "grey1" (rgb8 3 3 3) let _ = Hashtbl.add colors "gray2" (rgb8 5 5 5) let _ = Hashtbl.add colors "grey2" (rgb8 5 5 5) let _ = Hashtbl.add colors "gray3" (rgb8 8 8 8) let _ = Hashtbl.add colors "grey3" (rgb8 8 8 8) let _ = Hashtbl.add colors "gray4" (rgb8 10 10 10) let _ = Hashtbl.add colors "grey4" (rgb8 10 10 10) let _ = Hashtbl.add colors "gray5" (rgb8 13 13 13) let _ = Hashtbl.add colors "grey5" (rgb8 13 13 13) let _ = Hashtbl.add colors "gray6" (rgb8 15 15 15) let _ = Hashtbl.add colors "grey6" (rgb8 15 15 15) let _ = Hashtbl.add colors "gray7" (rgb8 18 18 18) let _ = Hashtbl.add colors "grey7" (rgb8 18 18 18) let _ = Hashtbl.add colors "gray8" (rgb8 20 20 20) let _ = Hashtbl.add colors "grey8" (rgb8 20 20 20) let _ = Hashtbl.add colors "gray9" (rgb8 23 23 23) let _ = Hashtbl.add colors "grey9" (rgb8 23 23 23) let _ = Hashtbl.add colors "gray10" (rgb8 26 26 26) let _ = Hashtbl.add colors "grey10" (rgb8 26 26 26) let _ = Hashtbl.add colors "gray11" (rgb8 28 28 28) let _ = Hashtbl.add colors "grey11" (rgb8 28 28 28) let _ = Hashtbl.add colors "gray12" (rgb8 31 31 31) let _ = Hashtbl.add colors "grey12" (rgb8 31 31 31) let _ = Hashtbl.add colors "gray13" (rgb8 33 33 33) let _ = Hashtbl.add colors "grey13" (rgb8 33 33 33) let _ = Hashtbl.add colors "gray14" (rgb8 36 36 36) let _ = Hashtbl.add colors "grey14" (rgb8 36 36 36) let _ = Hashtbl.add colors "gray15" (rgb8 38 38 38) let _ = Hashtbl.add colors "grey15" (rgb8 38 38 38) let _ = Hashtbl.add colors "gray16" (rgb8 41 41 41) let _ = Hashtbl.add colors "grey16" (rgb8 41 41 41) let _ = Hashtbl.add colors "gray17" (rgb8 43 43 43) let _ = Hashtbl.add colors "grey17" (rgb8 43 43 43) let _ = Hashtbl.add colors "gray18" (rgb8 46 46 46) let _ = Hashtbl.add colors "grey18" (rgb8 46 46 46) let _ = Hashtbl.add colors "gray19" (rgb8 48 48 48) let _ = Hashtbl.add colors "grey19" (rgb8 48 48 48) let _ = Hashtbl.add colors "gray20" (rgb8 51 51 51) let _ = Hashtbl.add colors "grey20" (rgb8 51 51 51) let _ = Hashtbl.add colors "gray21" (rgb8 54 54 54) let _ = Hashtbl.add colors "grey21" (rgb8 54 54 54) let _ = Hashtbl.add colors "gray22" (rgb8 56 56 56) let _ = Hashtbl.add colors "grey22" (rgb8 56 56 56) let _ = Hashtbl.add colors "gray23" (rgb8 59 59 59) let _ = Hashtbl.add colors "grey23" (rgb8 59 59 59) let _ = Hashtbl.add colors "gray24" (rgb8 61 61 61) let _ = Hashtbl.add colors "grey24" (rgb8 61 61 61) let _ = Hashtbl.add colors "gray25" (rgb8 64 64 64) let _ = Hashtbl.add colors "grey25" (rgb8 64 64 64) let _ = Hashtbl.add colors "gray26" (rgb8 66 66 66) let _ = Hashtbl.add colors "grey26" (rgb8 66 66 66) let _ = Hashtbl.add colors "gray27" (rgb8 69 69 69) let _ = Hashtbl.add colors "grey27" (rgb8 69 69 69) let _ = Hashtbl.add colors "gray28" (rgb8 71 71 71) let _ = Hashtbl.add colors "grey28" (rgb8 71 71 71) let _ = Hashtbl.add colors "gray29" (rgb8 74 74 74) let _ = Hashtbl.add colors "grey29" (rgb8 74 74 74) let _ = Hashtbl.add colors "gray30" (rgb8 77 77 77) let _ = Hashtbl.add colors "grey30" (rgb8 77 77 77) let _ = Hashtbl.add colors "gray31" (rgb8 79 79 79) let _ = Hashtbl.add colors "grey31" (rgb8 79 79 79) let _ = Hashtbl.add colors "gray32" (rgb8 82 82 82) let _ = Hashtbl.add colors "grey32" (rgb8 82 82 82) let _ = Hashtbl.add colors "gray33" (rgb8 84 84 84) let _ = Hashtbl.add colors "grey33" (rgb8 84 84 84) let _ = Hashtbl.add colors "gray34" (rgb8 87 87 87) let _ = Hashtbl.add colors "grey34" (rgb8 87 87 87) let _ = Hashtbl.add colors "gray35" (rgb8 89 89 89) let _ = Hashtbl.add colors "grey35" (rgb8 89 89 89) let _ = Hashtbl.add colors "gray36" (rgb8 92 92 92) let _ = Hashtbl.add colors "grey36" (rgb8 92 92 92) let _ = Hashtbl.add colors "gray37" (rgb8 94 94 94) let _ = Hashtbl.add colors "grey37" (rgb8 94 94 94) let _ = Hashtbl.add colors "gray38" (rgb8 97 97 97) let _ = Hashtbl.add colors "grey38" (rgb8 97 97 97) let _ = Hashtbl.add colors "gray39" (rgb8 99 99 99) let _ = Hashtbl.add colors "grey39" (rgb8 99 99 99) let _ = Hashtbl.add colors "gray40" (rgb8 102 102 102) let _ = Hashtbl.add colors "grey40" (rgb8 102 102 102) let _ = Hashtbl.add colors "gray41" (rgb8 105 105 105) let _ = Hashtbl.add colors "grey41" (rgb8 105 105 105) let _ = Hashtbl.add colors "gray42" (rgb8 107 107 107) let _ = Hashtbl.add colors "grey42" (rgb8 107 107 107) let _ = Hashtbl.add colors "gray43" (rgb8 110 110 110) let _ = Hashtbl.add colors "grey43" (rgb8 110 110 110) let _ = Hashtbl.add colors "gray44" (rgb8 112 112 112) let _ = Hashtbl.add colors "grey44" (rgb8 112 112 112) let _ = Hashtbl.add colors "gray45" (rgb8 115 115 115) let _ = Hashtbl.add colors "grey45" (rgb8 115 115 115) let _ = Hashtbl.add colors "gray46" (rgb8 117 117 117) let _ = Hashtbl.add colors "grey46" (rgb8 117 117 117) let _ = Hashtbl.add colors "gray47" (rgb8 120 120 120) let _ = Hashtbl.add colors "grey47" (rgb8 120 120 120) let _ = Hashtbl.add colors "gray48" (rgb8 122 122 122) let _ = Hashtbl.add colors "grey48" (rgb8 122 122 122) let _ = Hashtbl.add colors "gray49" (rgb8 125 125 125) let _ = Hashtbl.add colors "grey49" (rgb8 125 125 125) let _ = Hashtbl.add colors "gray50" (rgb8 127 127 127) let _ = Hashtbl.add colors "grey50" (rgb8 127 127 127) let _ = Hashtbl.add colors "gray51" (rgb8 130 130 130) let _ = Hashtbl.add colors "grey51" (rgb8 130 130 130) let _ = Hashtbl.add colors "gray52" (rgb8 133 133 133) let _ = Hashtbl.add colors "grey52" (rgb8 133 133 133) let _ = Hashtbl.add colors "gray53" (rgb8 135 135 135) let _ = Hashtbl.add colors "grey53" (rgb8 135 135 135) let _ = Hashtbl.add colors "gray54" (rgb8 138 138 138) let _ = Hashtbl.add colors "grey54" (rgb8 138 138 138) let _ = Hashtbl.add colors "gray55" (rgb8 140 140 140) let _ = Hashtbl.add colors "grey55" (rgb8 140 140 140) let _ = Hashtbl.add colors "gray56" (rgb8 143 143 143) let _ = Hashtbl.add colors "grey56" (rgb8 143 143 143) let _ = Hashtbl.add colors "gray57" (rgb8 145 145 145) let _ = Hashtbl.add colors "grey57" (rgb8 145 145 145) let _ = Hashtbl.add colors "gray58" (rgb8 148 148 148) let _ = Hashtbl.add colors "grey58" (rgb8 148 148 148) let _ = Hashtbl.add colors "gray59" (rgb8 150 150 150) let _ = Hashtbl.add colors "grey59" (rgb8 150 150 150) let _ = Hashtbl.add colors "gray60" (rgb8 153 153 153) let _ = Hashtbl.add colors "grey60" (rgb8 153 153 153) let _ = Hashtbl.add colors "gray61" (rgb8 156 156 156) let _ = Hashtbl.add colors "grey61" (rgb8 156 156 156) let _ = Hashtbl.add colors "gray62" (rgb8 158 158 158) let _ = Hashtbl.add colors "grey62" (rgb8 158 158 158) let _ = Hashtbl.add colors "gray63" (rgb8 161 161 161) let _ = Hashtbl.add colors "grey63" (rgb8 161 161 161) let _ = Hashtbl.add colors "gray64" (rgb8 163 163 163) let _ = Hashtbl.add colors "grey64" (rgb8 163 163 163) let _ = Hashtbl.add colors "gray65" (rgb8 166 166 166) let _ = Hashtbl.add colors "grey65" (rgb8 166 166 166) let _ = Hashtbl.add colors "gray66" (rgb8 168 168 168) let _ = Hashtbl.add colors "grey66" (rgb8 168 168 168) let _ = Hashtbl.add colors "gray67" (rgb8 171 171 171) let _ = Hashtbl.add colors "grey67" (rgb8 171 171 171) let _ = Hashtbl.add colors "gray68" (rgb8 173 173 173) let _ = Hashtbl.add colors "grey68" (rgb8 173 173 173) let _ = Hashtbl.add colors "gray69" (rgb8 176 176 176) let _ = Hashtbl.add colors "grey69" (rgb8 176 176 176) let _ = Hashtbl.add colors "gray70" (rgb8 179 179 179) let _ = Hashtbl.add colors "grey70" (rgb8 179 179 179) let _ = Hashtbl.add colors "gray71" (rgb8 181 181 181) let _ = Hashtbl.add colors "grey71" (rgb8 181 181 181) let _ = Hashtbl.add colors "gray72" (rgb8 184 184 184) let _ = Hashtbl.add colors "grey72" (rgb8 184 184 184) let _ = Hashtbl.add colors "gray73" (rgb8 186 186 186) let _ = Hashtbl.add colors "grey73" (rgb8 186 186 186) let _ = Hashtbl.add colors "gray74" (rgb8 189 189 189) let _ = Hashtbl.add colors "grey74" (rgb8 189 189 189) let _ = Hashtbl.add colors "gray75" (rgb8 191 191 191) let _ = Hashtbl.add colors "grey75" (rgb8 191 191 191) let _ = Hashtbl.add colors "gray76" (rgb8 194 194 194) let _ = Hashtbl.add colors "grey76" (rgb8 194 194 194) let _ = Hashtbl.add colors "gray77" (rgb8 196 196 196) let _ = Hashtbl.add colors "grey77" (rgb8 196 196 196) let _ = Hashtbl.add colors "gray78" (rgb8 199 199 199) let _ = Hashtbl.add colors "grey78" (rgb8 199 199 199) let _ = Hashtbl.add colors "gray79" (rgb8 201 201 201) let _ = Hashtbl.add colors "grey79" (rgb8 201 201 201) let _ = Hashtbl.add colors "gray80" (rgb8 204 204 204) let _ = Hashtbl.add colors "grey80" (rgb8 204 204 204) let _ = Hashtbl.add colors "gray81" (rgb8 207 207 207) let _ = Hashtbl.add colors "grey81" (rgb8 207 207 207) let _ = Hashtbl.add colors "gray82" (rgb8 209 209 209) let _ = Hashtbl.add colors "grey82" (rgb8 209 209 209) let _ = Hashtbl.add colors "gray83" (rgb8 212 212 212) let _ = Hashtbl.add colors "grey83" (rgb8 212 212 212) let _ = Hashtbl.add colors "gray84" (rgb8 214 214 214) let _ = Hashtbl.add colors "grey84" (rgb8 214 214 214) let _ = Hashtbl.add colors "gray85" (rgb8 217 217 217) let _ = Hashtbl.add colors "grey85" (rgb8 217 217 217) let _ = Hashtbl.add colors "gray86" (rgb8 219 219 219) let _ = Hashtbl.add colors "grey86" (rgb8 219 219 219) let _ = Hashtbl.add colors "gray87" (rgb8 222 222 222) let _ = Hashtbl.add colors "grey87" (rgb8 222 222 222) let _ = Hashtbl.add colors "gray88" (rgb8 224 224 224) let _ = Hashtbl.add colors "grey88" (rgb8 224 224 224) let _ = Hashtbl.add colors "gray89" (rgb8 227 227 227) let _ = Hashtbl.add colors "grey89" (rgb8 227 227 227) let _ = Hashtbl.add colors "gray90" (rgb8 229 229 229) let _ = Hashtbl.add colors "grey90" (rgb8 229 229 229) let _ = Hashtbl.add colors "gray91" (rgb8 232 232 232) let _ = Hashtbl.add colors "grey91" (rgb8 232 232 232) let _ = Hashtbl.add colors "gray92" (rgb8 235 235 235) let _ = Hashtbl.add colors "grey92" (rgb8 235 235 235) let _ = Hashtbl.add colors "gray93" (rgb8 237 237 237) let _ = Hashtbl.add colors "grey93" (rgb8 237 237 237) let _ = Hashtbl.add colors "gray94" (rgb8 240 240 240) let _ = Hashtbl.add colors "grey94" (rgb8 240 240 240) let _ = Hashtbl.add colors "gray95" (rgb8 242 242 242) let _ = Hashtbl.add colors "grey95" (rgb8 242 242 242) let _ = Hashtbl.add colors "gray96" (rgb8 245 245 245) let _ = Hashtbl.add colors "grey96" (rgb8 245 245 245) let _ = Hashtbl.add colors "gray97" (rgb8 247 247 247) let _ = Hashtbl.add colors "grey97" (rgb8 247 247 247) let _ = Hashtbl.add colors "gray98" (rgb8 250 250 250) let _ = Hashtbl.add colors "grey98" (rgb8 250 250 250) let _ = Hashtbl.add colors "gray99" (rgb8 252 252 252) let _ = Hashtbl.add colors "grey99" (rgb8 252 252 252) let _ = Hashtbl.add colors "gray100" (rgb8 255 255 255) let _ = Hashtbl.add colors "grey100" (rgb8 255 255 255) let _ = Hashtbl.add colors "dark grey" (rgb8 169 169 169) let _ = Hashtbl.add colors "DarkGrey" (rgb8 169 169 169) let _ = Hashtbl.add colors "dark gray" (rgb8 169 169 169) let _ = Hashtbl.add colors "DarkGray" (rgb8 169 169 169) let _ = Hashtbl.add colors "dark blue" (rgb8 0 0 139) let _ = Hashtbl.add colors "DarkBlue" (rgb8 0 0 139) let _ = Hashtbl.add colors "dark cyan" (rgb8 0 139 139) let _ = Hashtbl.add colors "DarkCyan" (rgb8 0 139 139) let _ = Hashtbl.add colors "dark magenta" (rgb8 139 0 139) let _ = Hashtbl.add colors "DarkMagenta" (rgb8 139 0 139) let _ = Hashtbl.add colors "dark red" (rgb8 139 0 0) let _ = Hashtbl.add colors "DarkRed" (rgb8 139 0 0) let _ = Hashtbl.add colors "light green" (rgb8 144 238 144) let _ = Hashtbl.add colors "LightGreen" (rgb8 144 238 144) mlpost-0.8.2/command.ml000066400000000000000000000047771306046515300150310ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Misc open Types module T = Transform type hposition = Types.hposition type vposition = Types.vposition type position = Types.position type t = commandpic let label ?(pos=`Center) pic point = mkCommand (mkCLabel pic pos point) (* replace later *) let dotlabel ?(pos=`Center) pic point = mkCommand (mkCDotLabel pic pos point) let draw ?brush ?color ?pen ?dashed t = (* We don't use a default to avoid the output of ... withcolor (0.00red+0.00green+0.00blue) withpen .... for each command in the output file *) mkCommand (mkCDraw t (mkBrushOpt brush color pen dashed)) let fill ?color t = mkCommand (mkCFill t color) let seq l = mkSeq l let iter from until f = let l = Misc.fold_from_to (fun acc i -> f i :: acc) [] from until in seq (List.rev l) let draw_pic p = p let append c1 c2 = seq [c1; c2] let (++) = append let externalimage filename spec = if not (Filename.check_suffix filename "png") then invalid_arg (Format.sprintf "externalimage support only png image : %s" filename); if not (Sys.file_exists filename) then invalid_arg (Format.sprintf "externalimage file doesn't exist : %s" filename); let filename = if Filename.is_relative filename then Filename.concat (Sys.getcwd ()) filename else filename in mkCommand (mkCExternalImage filename spec) (* syntactic sugar *) let iterl f l = seq (List.map f l) let nop = seq [] mlpost-0.8.2/compile.ml000066400000000000000000000212051306046515300150240ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types open Hashcons module C = Compiled_types module D = Duplicate let nop = C.CSeq [] let (++) c1 c2 = match c1,c2 with | C.CSeq [], _ -> c2 | _, C.CSeq [] -> c1 | _, _ -> C.CSeq [c1 ; c2] let path_names = D.PthM.create 257 let picture_names = D.PicM.create 257 let option_compile f = function | None -> None, nop | Some obj -> let obj, c = f obj in Some obj, c let rec num n = n, nop and point p = p, nop and knot k = match k.Hashcons.node with | { knot_in = d1 ; knot_p = p ; knot_out = d2 } -> let d1, c1 = direction d1 in let p, c2 = point p in let d2, c3 = direction d2 in (d1,p,d2), c1 ++ c2 ++ c3 and joint j = match j.Hashcons.node with | JLine -> C.JLine, nop | JCurve -> C.JCurve, nop | JCurveNoInflex -> C.JCurveNoInflex, nop | JTension (a,b) -> C.JTension (a,b), nop | JControls (p1,p2) -> let p1,c1 = point p1 in let p2,c2 = point p2 in C.JControls (p1,p2), c1 ++ c2 and direction d = match d.Hashcons.node with | Vec p -> let p, code = point p in C.Vec p, code | Curl f -> C.Curl f, nop | NoDir -> C.NoDir, nop and metapath p = match p.Hashcons.node with | MPAConcat (pa,j,p) -> let p, c1 = metapath p in let pa, c2 = knot pa in let j, c3 = joint j in C.PAConcat (pa,j,p), c1 ++ c2 ++ c3 | MPAAppend (p1,j,p2) -> let p1, c1 = metapath p1 in let j, c2 = joint j in let p2, c3 = metapath p2 in C.PAAppend (p1,j,p2), c1 ++ c2 ++ c3 | MPAKnot path -> let path, code = knot path in C.PAKnot path, code | MPAofPA p -> let p,c = path p in C.PAScope p, c and path' = function | PAofMPA p -> let p,c = metapath p in C.PAScope p, c | MPACycle (d,j,p) -> let d, c1 = direction d in let j, c2 = joint j in let p, c3 = metapath p in C.PACycle (d,j,p), c1 ++ c2 ++ c3 | PATransformed (p,tr) -> let p, c1 = path p in let tr, c2 = transform tr in (* group transformations, for slightly smaller metapost code *) (* this only happens in the Metapost AST, to be able to use * path components that already have a name *) C.PATransformed(p,tr), c1 ++ c2 | PACutAfter (p1,p2) -> let p1, c1 = path p1 in let p2, c2 = path p2 in C.PACutAfter (p1,p2), c1 ++ c2 | PACutBefore (p1,p2) -> let p1, c1 = path p1 in let p2, c2 = path p2 in C.PACutBefore (p1,p2), c1 ++ c2 | PABuildCycle pl -> let npl = List.map path pl in C.PABuildCycle (List.map fst npl), C.CSeq (List.map snd npl) | PASub (f1, f2, p) -> (* the Metapost subpath command needs a path name as argument *) let f1, c1 = num f1 in let f2, c2 = num f2 in let p', code = path_save p in begin match p' with | C.PAName x -> C.PASub (f1,f2,x), c1 ++ c2 ++ code | _ -> assert false end | PABBox p -> let p, code = commandpic_pic p in C.PABBox p, code | PAUnitSquare -> C.PAUnitSquare, nop | PAQuarterCircle -> C.PAQuarterCircle, nop | PAHalfCircle -> C.PAHalfCircle, nop | PAFullCircle -> C.PAFullCircle, nop and path p = let cnt = !(D.PthM.find D.path_map p) in if cnt >= 2 then path_save p else path' p.node and path_save p = try let x = D.PthM.find path_names p in C.PAName x, nop with Not_found -> let p', code = path' p.node in let x = Name.path () in let () = D.PthM.add path_names p x in C.PAName x, code ++ C.CDeclPath (x,p') and picture' = function | PITransformed (p,tr) -> let tr, c1 = transform tr in let pic, c2 = commandpic_pic p in C.PITransformed (pic,tr), c1 ++ c2 | PITex s -> C.PITex s, nop | PIClip (pic,pth) -> let pic, c1 = commandpic_pic_save pic in let pth, c2 = path pth in let pn = Name.picture () in (* slight redundance here *) C.PIName pn, c1 ++ c2 ++ C.CSimplePic (pn,pic) ++ C.CClip (pn,pth) and picture pic = let cnt = !(D.PicM.find D.picture_map pic) in if cnt >= 2 then picture_save pic else picture' pic.node and picture_save pic = try let x = D.PicM.find picture_names pic in C.PIName x, nop with Not_found -> let x = Name.picture () in let () = D.PicM.add picture_names pic x in let pic', code = picture' pic.node in C.PIName x, code ++ C.CSimplePic (x,pic') and commandpic_pic pc = match pc.Hashcons.node with | Picture p -> picture p | Command c -> let pn = Name.picture () in C.PIName pn, C.CDefPic (pn, command c) | Seq l -> let pn = Name.picture () in C.PIName pn, C.CDefPic (pn, C.CSeq (List.map commandpic_cmd l)) and commandpic_pic_save pc = match pc.Hashcons.node with | Picture p -> picture_save p | _ -> commandpic_pic pc and commandpic_cmd pc = match pc.Hashcons.node with | Picture p -> let p, code = picture p in C.CSeq [code; C.CDrawPic p] | Command c -> command c | Seq l -> C.CSeq (List.map commandpic_cmd l) and transform t = let t = List.fold_left Matrix.multiply Matrix.identity t in let pn = Name.transform () in pn, C.CDefTrans (pn, t) and pen p = match p.Hashcons.node with | PenCircle -> C.PenCircle, nop | PenSquare -> C.PenSquare, nop | PenFromPath p -> let p, code = path p in C.PenFromPath p, code | PenTransformed (p, tr) -> let p, c1 = pen p in let tr, c2 = transform tr in C.PenTransformed (p,tr), c1 ++ c2 and dash d = match d.Hashcons.node with | DEvenly -> C.DEvenly, nop | DWithdots -> C.DWithdots, nop | DScaled (f, d) -> let f,c1 = num f in let d,c2 = dash d in C.DScaled (f,d) , c1 ++ c2 | DShifted (p,d) -> let p, c1 = point p in let d, c2 = dash d in C.DShifted (p,d), c1 ++ c2 | DPattern l -> let l1,l2 = List.fold_right (fun pat (patl, cl) -> let pat,c = dash_pattern pat in pat::patl, c::cl ) l ([],[]) in C.DPattern l1, C.CSeq l2 and dash_pattern o = match o.Hashcons.node with | On f -> let f1, c1 = num f in C.On f1, c1 | Off f -> let f1, c1 = num f in C.Off f1, c1 and command c = match c.Hashcons.node with | CDraw (p, b) -> let p, c1 = path p in let {color = color; pen = pe; dash = dsh} = b.Hashcons.node in let pe, c2 = (option_compile pen) pe in let dsh, c3 = (option_compile dash) dsh in C.CSeq [c1; c2; c3; C.CDraw (p, color, pe, dsh)] (* | CDrawPic p -> let p, code = picture p in C.CSeq [code; C.CDrawPic p] *) | CFill (p, c) -> let p, code = path p in C.CSeq [code; C.CFill (p, c)] | CDotLabel (pic, pos, pt) -> let pic, c1 = commandpic_pic pic in let pt, c2 = point pt in c1 ++ c2 ++ C.CDotLabel (pic,pos,pt) | CLabel (pic, pos ,pt) -> let pic, c1 = commandpic_pic pic in let pt, c2 = point pt in c1 ++ c2 ++ C.CLabel (pic,pos,pt) | CExternalImage (filename,spec) -> let spec,code = match spec with | `Exact (h,w) -> let hn,hc = num h in let wn,wc = num w in `Exact (hn,wn),hc ++ wc | `Inside (h,w) -> let hn,hc = num h in let wn,wc = num w in `Inside (hn,wn),hc++wc | `Height h -> let hn,hc = num h in `Height hn,hc | `Width w -> let wn,wc = num w in `Width wn,wc | `None -> `None,C.CSeq [] in code++C.CExternalImage (filename,spec) let reset () = D.PthM.clear D.path_map; D.PthM.clear path_names; D.PicM.clear D.picture_map; D.PicM.clear picture_names mlpost-0.8.2/compiled_types.ml000066400000000000000000000060651306046515300164230ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type num = float and point = Point_lib.t and direction = | Vec of point | Curl of float | NoDir and joint = | JLine | JCurve | JCurveNoInflex | JTension of float * float | JControls of point * point and knot = direction * point * direction and path = | PAScope of path | PAConcat of knot * joint * path | PACycle of direction * joint * path | PAFullCircle | PAHalfCircle | PAQuarterCircle | PAUnitSquare | PATransformed of path * transform | PAKnot of knot | PAAppend of path * joint * path | PACutAfter of path * path | PACutBefore of path * path | PABuildCycle of path list (* PASub only takes a name *) | PASub of num * num * name | PABBox of picture | PAName of name and matrix = Types.matrix and transform = name and picture = | PITex of string | PITransformed of picture * transform | PIName of name and dash = | DEvenly | DWithdots | DScaled of num * dash | DShifted of point * dash | DPattern of on_off list and pen = | PenCircle | PenSquare | PenFromPath of path | PenTransformed of pen * transform and command = | CDraw of path * color option * pen option * dash option | CDrawArrow of path * color option * pen option * dash option | CDrawPic of picture | CFill of path * color option | CLabel of picture * position * point | CDotLabel of picture * position * point | CSeq of command list | CDeclPath of name * path | CDeclPoint of name * point | CDeclNum of name * num | CDefPic of name * command | CDefTrans of name * matrix | CSimplePic of name * picture | CClip of name * path | CExternalImage of string * spec_image and spec_image = [ `None | `Width of num (* keep the proportion of the image *) | `Height of num | `Inside of num * num (* must be inside a box of this height and width *) | `Exact of num * num] and color = Types.color and position = Types.position and name = Types.name and on_off = | On of num | Off of num mlpost-0.8.2/concrete.ml000066400000000000000000000125071306046515300152030ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) IFDEF CONCRETE THEN let supported = true type cnum = float let set_verbosity = Defaults.set_verbosity let set_prelude = Defaults.set_prelude_from_file let set_prelude2 s = let s = match s with None -> "" | Some s -> s in Defaults.set_prelude s let set_t1disasm = Defaults.set_t1disasm module CPoint = Point_lib module CPath = struct module S = Spline_lib type t = S.path type abscissa = float let length p = float (S.length p) let is_closed = S.is_closed let is_a_point x = S.is_a_point x let intersection p1 p2 = S.intersection p1 p2 let one_intersection p1 p2 = S.one_intersection p1 p2 let reverse = S.reverse let iter = S.iter let fold_left = S.fold_left let cut_before = S.cut_before let cut_after = S.cut_after let split = S.split let subpath = S.subpath let direction_of_abscissa = S.direction_of_abscissa let point_of_abscissa = S.abscissa_to_point let bounding_box = S.bounding_box let dist_min_point = S.dist_min_point let dist_min_path = S.dist_min_path let print = S.print end module CTransform = Matrix let float_of_num = Compute.num let cpoint_of_point = Compute.point let cpath_of_path = Compute.path let ctransform_of_transform = Compute.transform let baselines s = Picture_lib.baseline (Compute.picture (Types.mkPITex s)) let num_of_float = Misc.id let point_of_cpoint = Misc.id let path_of_cpath p = let knot x = Types.mkKnot Types.mkNoDir (point_of_cpoint x) Types.mkNoDir in let start = knot (CPath.point_of_abscissa p 0.) in let path = CPath.fold_left (fun acc _ b c d -> let joint = Types.mkJControls (point_of_cpoint b) (point_of_cpoint c) in Types.mkMPAConcat (knot d) joint acc ) (Types.mkMPAKnot start) p in if CPath.is_closed p then Types.mkMPACycle Types.mkNoDir Types.mkJLine path else Types.mkPAofMPA path let transform_of_ctransform x = [x] ELSE let supported = false let not_supported s = failwith ("Concrete."^s^" : not supported") module CPoint = struct let not_supported s = failwith ("Concrete.Cpoint."^s^" : not supported") type t = {x:float; y:float} let add _ _ = not_supported "add" let sub _ _ = not_supported "sub" let opp _ = not_supported "opp" let mult _ _ = not_supported "mult" let div _ _ = not_supported "div" module Infix = struct let (+/) = add let (-/) = sub let ( */) = mult let ( //) = div end let print _ _ = not_supported "print" end module CPath = struct let not_supported s = failwith ("Concrete.CPath."^s^" : not supported") type t = unit type abscissa = float type point = CPoint.t let length _ = not_supported "length" let is_closed _ = not_supported "is_closed" let is_a_point _ = not_supported "is_a_point" let intersection p1 p2 = not_supported "intersection" let one_intersection p1 p2 = not_supported "one_intersection" let reverse _ = not_supported "reverse" let iter _ _ = not_supported "iter" let fold_left _ _ = not_supported "fold_left" let cut_before _ _ = not_supported "cut_before" let cut_after _ _ = not_supported "cut_after" let split p t = not_supported "split" let subpath p t1 t2 = not_supported "subpath" let direction_of_abscissa p t1 = not_supported "direction_of_abscissa" let point_of_abscissa p t1 = not_supported "point_of_abscissa" let bounding_box _ = not_supported "bounding_box" let dist_min_point path point = not_supported "dist_min_point" let dist_min_path path1 path2 = not_supported "dist_min_path" let print _ _ = not_supported "print" end module CTransform = struct type t = { xx : float; yx : float; xy : float; yy : float; x0 : float; y0 : float; } end let float_of_num _ = not_supported "float_of_num" let compute_nums _ = not_supported "compute_nums" let cpoint_of_point _ = not_supported "cpoint_of_point" let cpath_of_path _ = not_supported "cpath_of_path" let ctransform_of_transform _ = not_supported "ctransform_of_transform" let num_of_float f = not_supported "num_of_float" let point_of_cpoint p = not_supported "point_of_cpoint" let path_of_cpath p = not_supported "path_of_cpath" let transform_of_ctransform _ = not_supported "transform_of_ctransform" let baselines p = not_supported "baselines" END mlpost-0.8.2/concrete/000077500000000000000000000000001306046515300146445ustar00rootroot00000000000000mlpost-0.8.2/concrete/_tags000066400000000000000000000001151306046515300156610ustar00rootroot00000000000000 : pkg_cairo : syntax_macro <*.cmx> : for-pack(Mlpost) mlpost-0.8.2/concrete/compute.ml000066400000000000000000000252551306046515300166630ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module P = Point_lib module M = Matrix let default_labeloffset = 3.5 (* should be 3. but not enough*) let default_pen = M.scale 0.5 let bbox_offset = {P.x=2.;P.y=2.} let pi = 3.1415926535897932384626433832795029 let pi_div_180 = pi /. 180.0 let deg2rad f = pi_div_180 *. f open Types open Hashcons module S = Spline_lib module Pi = Picture_lib module MP = Metapath_lib let memoize f fname memoize = fun arg -> try Hashtbl.find memoize arg.tag with Not_found -> let result = try f arg.node with exn -> if Defaults.get_debug () then Format.printf "Compute.%s raises : %s@.@?" fname (Printexc.to_string exn); raise exn in Hashtbl.add memoize arg.tag result; result let nop = Picture_lib.empty let option_compile f = function | None -> None | Some obj -> Some (f obj) let option_def_compile def f = function | None -> def | Some obj -> f obj let middle x y = (x/.2.)+.(y/.2.) let point_of_position ecart ({ P.x = xmin; y = ymin}, { P.x = xmax; y = ymax}) pos = match pos_reduce pos with | `North -> {P.x=middle xmin xmax; y=ymax+.ecart} | `South -> {P.x=middle xmin xmax; y=ymin-.ecart} | `West -> {P.x=xmin-.ecart; y=middle ymin ymax} | `East -> {P.x=xmax+.ecart; y=middle ymin ymax} | `Northwest -> {P.x=xmin-.ecart;y=ymax+.ecart} | `Northeast -> {P.x=xmax+.ecart;y=ymax+.ecart} | `Southwest -> {P.x=xmin-.ecart;y=ymin-.ecart} | `Southeast -> {P.x=xmax+.ecart;y=ymin-.ecart} | `Center -> {P.x = middle xmin xmax; P.y = middle ymin ymax } let anchor_of_position pos = match pos_reduce pos with | `North -> `South | `South -> `North | `West -> `East | `East -> `West | `Northwest -> `Southeast | `Northeast -> `Southwest | `Southwest -> `Northeast | `Southeast -> `Northwest | `Center -> `Center let metapath_memoize = Hashtbl.create 50 let path_memoize = Hashtbl.create 50 let picture_memoize = Hashtbl.create 50 let command_memoize = Hashtbl.create 50 let clear () = Hashtbl.clear metapath_memoize; Hashtbl.clear path_memoize; Hashtbl.clear picture_memoize; Hashtbl.clear command_memoize let float_to_metapost f = (* Compatibility with metapost *) if f = infinity then 4095.99998 (* cf mpman *) else if f > 4095. then 4095. else if abs_float f < 0.0001 then 0. else f let rec num n = n and point p = p (* and point' = function | PTPair (f1,f2) -> let f1 = num f1 in let f2 = num f2 in {P.x=f1;y=f2} | PTPointOf (f,p) -> let p = path p in let f = Spline_lib.abscissa_of_metapost p (num f) in Spline_lib.abscissa_to_point p f | PTDirectionOf (f,p) -> let p = path p in let f = Spline_lib.abscissa_of_metapost p (num f) in Spline_lib.direction_of_abscissa p f | PTAdd (p1,p2) -> let p1 = point p1 in let p2 = point p2 in P.add p1 p2 | PTSub (p1,p2) -> let p1 = point p1 in let p2 = point p2 in P.sub p1 p2 | PTMult (f,p) -> let f = num f in let p1 = point p in P.mult f p1 | PTRotated (f,p) -> let p1 = point p in P.rotated (deg2rad f) p1 | PTPicCorner (pic, corner) -> let p = commandpic pic in point_of_position 0. (Picture_lib.bounding_box p) (corner :> position) | PTTransformed (p,tr) -> let p = point p in let tr = transform tr in P.transform tr p and point p = memoize point' "point" point_memoize p *) and knot k = match k.Hashcons.node with | { knot_in = d1 ; knot_p = p ; knot_out = d2 } -> let d1 = direction d1 in let p = point p in let d2 = direction d2 in let d1,d2 = MP.equalize_dir (d1,d2) in d1,MP.knot p,d2 and joint dl j dr = match j.Hashcons.node with | JLine -> MP.line_joint | JCurve -> MP.curve_joint dl dr | JCurveNoInflex -> MP.curve_no_inflex_joint dl dr | JTension (a,b) -> MP.tension_joint dl a b dr | JControls (p1,p2) -> let p1 = point p1 in let p2 = point p2 in MP.controls_joint p1 p2 and direction d = match d.Hashcons.node with | Vec p -> let p = point p in MP.vec_direction p | Curl f -> MP.curl_direction (float_to_metapost f) | NoDir -> MP.no_direction and metapath' = function | MPAConcat (pa,j,p) -> let pdl,p,pdr = metapath p in let dl,pa,dr = knot pa in let j = joint pdr j dl in pdl,MP.concat p j pa,dr | MPAAppend (p1,j,p2) -> let p1dl,p1,p1dr = metapath p1 in let p2dl,p2,p2dr = metapath p2 in let j = joint p1dr j p2dl in p1dl,MP.append p1 j p2,p2dr | MPAKnot k -> let dl,p,dr = knot k in dl,MP.start p, dr | MPAofPA p -> MP.no_direction, MP.from_path (path p), MP.no_direction and metapath p = memoize metapath' "metapath" metapath_memoize p and path' = function | PAofMPA p -> let _,mp,_ = (metapath p) in MP.to_path mp | MPACycle (d,j,p) -> let d = direction d in let _,p,dr = metapath p in let j = joint dr j d in MP.cycle j p | PATransformed (p,tr) -> let p = path p in let tr = transform tr in Spline_lib.transform tr p | PACutAfter (p1,p2) -> let p1 = path p1 in let p2 = path p2 in Spline_lib.cut_after p1 p2 | PACutBefore (p1,p2) -> let p1 = path p1 in let p2 = path p2 in Spline_lib.cut_before p1 p2 | PABuildCycle pl -> (* let npl = List.map path pl in *) (* TODO *) assert false (* Spline_lib.buildcycle npl *) | PASub (f1, f2, p) -> let p = path p in Spline_lib.subpath p (num f1) (num f2) | PABBox p -> let p = commandpic p in let pmin,pmax = Picture_lib.bounding_box p in let pmin,pmax = P.sub pmin bbox_offset,P.add pmax bbox_offset in Spline_lib.close (Spline_lib.create_lines [{P.x = pmin.P.x; y = pmin.P.y}; {P.x = pmin.P.x; y = pmax.P.y}; {P.x = pmax.P.x; y = pmax.P.y}; {P.x = pmax.P.x; y = pmin.P.y}]) | PAUnitSquare -> MP.Approx.unitsquare 1. | PAQuarterCircle -> MP.Approx.quartercircle 1. | PAHalfCircle -> MP.Approx.halfcirle 1. | PAFullCircle -> MP.Approx.fullcircle 1. and path p = (*Format.printf "path : %a@.@?" Print.path p;*) memoize path' "path" path_memoize p and picture' = function | PITransformed (p,tr) -> let tr = transform tr in let pic = commandpic p in Picture_lib.transform tr pic | PITex s -> let tex = Gentex.create s in Picture_lib.tex tex | PIClip (pic,pth) -> let pic = commandpic pic in let pth = path pth in Picture_lib.clip pic pth and picture p = memoize picture' "picture" picture_memoize p and transform t = List.fold_left Matrix.multiply Matrix.identity t and commandpic p = match p.Hashcons.node with | Picture p -> picture p | Command c -> command c | Seq l -> begin match l with | [] -> Picture_lib.empty | [x] -> commandpic x | (x::r) -> List.fold_left (fun acc c -> Picture_lib.on_top acc (commandpic c)) (commandpic x) r end and dash d = match d.Hashcons.node with | DEvenly -> Picture_lib.Dash.line | DWithdots -> Picture_lib.Dash.dots | DScaled (f, d) -> let f = num f in let d = dash d in Picture_lib.Dash.scale f d | DShifted (p,d) -> let p = point p in let d = dash d in Picture_lib.Dash.shifted p.P.x d | DPattern l -> let l = List.map dash_pattern l in Picture_lib.Dash.pattern l and dash_pattern o = match o.Hashcons.node with | On f -> Picture_lib.Dash.On (num f) | Off f -> Picture_lib.Dash.Off (num f) and command' = function | CDraw (p, b) -> let p = path p in let {color = c; pen = pe; dash = dsh} = b.Hashcons.node in let pe = (option_def_compile default_pen pen) pe in let dsh = (option_compile dash) dsh in Picture_lib.stroke_path p c pe dsh | CFill (p, c) -> let p = path p in Picture_lib.fill_path p c | CDotLabel (pic, pos, pt) -> Picture_lib.on_top (Picture_lib.draw_point (point pt)) (command (mkCLabel pic pos pt)) | CLabel (pic, pos ,pt) -> let pic = commandpic pic in let pt = point pt in let mm = (Picture_lib.bounding_box pic) in let anchor = anchor_of_position pos in let pos = (point_of_position default_labeloffset mm anchor) in let tr = Matrix.translation (P.sub pt pos) in Picture_lib.transform tr pic | CExternalImage (filename,sp) -> Picture_lib.external_image filename (spec sp) and spec = function | `Exact (n1,n2) -> `Exact (num n1, num n2) | `Height n -> `Height (num n) | `Width n -> `Width (num n) | `Inside (n1,n2) -> `Inside (num n1, num n2) | `None -> `None and pen p = (* TODO : the bounding box is not aware of the pen size *) match p.Hashcons.node with | PenCircle -> Matrix.identity | PenSquare -> (*TODO not with cairo...*)assert false (*Picture_lib.PenSquare*) | PenFromPath p -> (*TODO : very hard*)assert false (*Picture_lib.PenFromPath (path p)*) | PenTransformed (p, tr) -> Matrix.multiply (transform tr) (pen p) and command c = memoize command' "command" command_memoize c let commandl_error ferror arg = List.map (ferror command) arg let commandpicl_error ferror arg = List.map (ferror commandpic) arg let numl_error ferror arg = List.map (ferror num) arg let pointl_error ferror arg = List.map (ferror point) arg let pathl_error ferror arg = List.map (ferror path) arg let metapathl_error ferror arg = List.map (ferror metapath) arg let picturel_error ferror arg = List.map (ferror picture) arg mlpost-0.8.2/concrete/concrete_types.ml000066400000000000000000000002561306046515300202270ustar00rootroot00000000000000type scolor = | RGB of float * float * float | CMYK of float * float * float * float | Gray of float type color = |OPAQUE of scolor |TRANSPARENT of float * scolor mlpost-0.8.2/concrete/ctypes.mli000066400000000000000000000005231306046515300166560ustar00rootroot00000000000000IFDEF CAIRO THEN type matrix = Cairo.matrix = { xx : float; yx : float; xy : float; yy : float; x0 : float; y0 : float; } type point = Cairo.point = {x : float; y : float} ELSE type matrix = { xx : float; yx : float; xy : float; yy : float; x0 : float; y0 : float; } type point = {x : float; y : float} END mlpost-0.8.2/concrete/gentex.ml000066400000000000000000000135331306046515300164750ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Printf open Point_lib let com_latex = "latex" let jobname = "gentex" let filename = File.from_string jobname (* FIXME different from Metapost.default_prelude? *) let latex_cmd tmpdir = Printf.sprintf "latex -jobname=%s -ipc -halt-on-error -output-dir '%s'" jobname (File.Dir.to_string tmpdir) (* Printf.sprintf "cat" *) type t = {tex : Dviinterp.page; trans : Matrix.t; bb : (float * float * float * float)} let set_verbosity b = () type proc = { outc : in_channel; inc : out_channel; errc : in_channel } type comm = { latex : proc ; dvi : Dvi.Incremental.t; tmpdir : File.Dir.t } let truncate_or_touch f = File.open_in_gen [Open_trunc; Open_creat; Open_rdonly] 0o600 f let ends_with en s = let l = String.length s in let k = String.length en in if k <= l then try for i = 0 to k - 1 do if s.[l - i - 1] <> en.[k - i - 1] then raise Exit done; true with Exit -> false else false let read_up_to_one = (* FIXME deal with EOF exception: Actually that print on stdout and that throw the error. Perhaps can we throw an exception with all in it. But it is not very fun for user (only part of the string in an exception is printed) *) let end_ = "[1]" in let rec aux buf inc = let s = try input_line inc with End_of_file -> Buffer.output_buffer stdout buf; invalid_arg ("One tex snipet contains an error") in Buffer.add_string buf s; Buffer.add_char buf '\n'; if ends_with end_ s then () else aux buf inc in fun inc -> let buf = Buffer.create 10 in aux buf inc let read_up_to_one p = read_up_to_one p.outc let mk_proc_latex tmpdir = let outc,inc,errc = Unix.open_process_full (latex_cmd tmpdir) (Unix.environment ()) in { outc = outc; inc = inc ; errc = errc } let write_to_proc p s = Printf.fprintf p.inc s let push_prelude p prel = (* the shipout macro from metapost, that adds a vrule at the end of the tex * to obtain easily the size of the dvi *) write_to_proc p "%s \\begin{document} \\gdef\\mpxshipout{\\shipout\\hbox\\bgroup%% \\setbox0=\\hbox\\bgroup}%% \\gdef\\stopmpxshipout{\\egroup \\dimen0=\\ht0 \\advance\\dimen0\\dp0 \\dimen1=\\ht0 \\dimen2=\\dp0 \\setbox0=\\hbox\\bgroup \\box0 \\ifnum\\dimen0>0 \\vrule width1sp height\\dimen1 depth\\dimen2 \\else \\vrule width1sp height1sp depth0sp\\relax \\fi\\egroup \\ht0=0pt \\dp0=0pt \\box0 \\egroup}\n%!" prel let shipout_and_flush p s = write_to_proc p "\\mpxshipout %s\\stopmpxshipout\n%!" s let end_doc p = write_to_proc p "\\end{document}\n%!" let extract cl = (* the vrule added by the metapost shipout macro is exploited and removed *) match cl with | Dviinterp.Fill_rect (_,x,y,_,h)::cl -> let bb = (0., -.(y+.h), x, -.y) in {tex = cl; trans = Matrix.identity; bb = bb} | _ -> assert false let comm = ref None (* TODO : do that only when clean is requested. note if an error occured comm become None *) let () = at_exit (fun () -> match !comm with | None -> () | Some p -> File.Dir.rm p.tmpdir) let read_up_to_one p = try read_up_to_one p with e -> comm := None;raise e let create tex = (* FIXME at some point we have to close the latex process *) match !comm with | None -> let tmpdir = Metapost_tool.create_temp_dir "mlpost" "" in let p = mk_proc_latex tmpdir in push_prelude p (Defaults.get_prelude ()); shipout_and_flush p tex; read_up_to_one p; let filename = File.place tmpdir (File.set_ext filename "dvi") in let dvi_chan = File.open_in filename in let t, pgs = Dvi.Incremental.mk_t dvi_chan in comm := Some { latex = p ; dvi = t ; tmpdir = tmpdir}; extract (Dviinterp.Incremental.load_page t (List.hd pgs)) | Some p -> shipout_and_flush p.latex tex; read_up_to_one p.latex; let pgs = Dvi.Incremental.next_pages p.dvi in extract (Dviinterp.Incremental.load_page p.dvi (List.hd pgs)) let point_of_cm cm = (0.3937 *. 72.) *. cm let get_dimen_cm x = x.bb let get_dimen_pt x = let (x_min,y_min,x_max,y_max) = get_dimen_cm x in (point_of_cm x_min, point_of_cm y_min, point_of_cm x_max, point_of_cm y_max) (** donne la dimension en centimètre *) let get_bases_cm x = assert false let get_bases_pt x = assert false let bounding_box x = let (xmin,ymin,xmax,ymax) = get_dimen_pt x in if Defaults.get_debug () then Format.printf "gentex bb : %f %f %f %f@." xmin ymin xmax ymax; {x=xmin;y=ymin},{x=xmax;y=ymax} let print fmt tex = let min,max = bounding_box tex in Format.fprintf fmt "[%a,%a]" print min print max let deb_print fmt tex = Format.printf "{ tex: %a ; matrix: %a }" Dviinterp.Print.page tex.tex Matrix.print tex.trans mlpost-0.8.2/concrete/gentex.mli000066400000000000000000000032311306046515300166400ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) val set_verbosity : bool -> unit type t = {tex : Dviinterp.page ; trans : Matrix.t; bb : (float * float * float * float)} val create : string -> t val get_dimen_pt : t -> float * float * float * float val get_dimen_cm : t -> float * float * float * float val bounding_box : t -> Point_lib.t * Point_lib.t val get_bases_pt : t -> float list val get_bases_cm : t -> float list val print : Format.formatter -> t -> unit val deb_print : Format.formatter -> t -> unit (** donne la dimension en centimètre *) mlpost-0.8.2/concrete/matrix.ml000066400000000000000000000056661306046515300165170ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Ctypes type point = Ctypes.point type t = matrix = { xx : float; yx : float; xy : float; yy : float; x0 : float; y0 : float; } (* specialized negation here to avoid dependency *) let neg_point p = { x = -.p.x; y = -.p.y} let linear xx xy yx yy = { xx = xx; xy = xy; yx = yx; yy = yy; x0 = 0.; y0 = 0. } (* let scale_mult m f = { xx = m.xx *. f; xy = m.xy *. f; yx = m.yx *. f; yy = m.yy *. f; x0 = m.x0 *. f; y0 = m.y0 *. f; } *) let init_translate x y = { xx = 1.; yx = 0.; xy = 0.; yy = 1.; x0 = x; y0 = y } let init_scale x y = { xx = x; yx = 0.; xy = 0.; yy = y; x0 = 0.; y0 = 0. } let init_identity = { xx = 1.; yx = 0.; xy = 0.; yy = 1.; x0 = 0.; y0 = 0. } let init_rotate a = let s = sin a in let c = cos a in { xx = c; yx = s; xy = -.s; yy = c; x0 = 0.; y0 = 0. } let multiply a b = { xx = a.xx *. b.xx +. a.yx *. b.xy ; yx = a.xx *. b.yx +. a.yx *. b.yy; xy = a.xy *. b.xx +. a.yy *. b.xy; yy = a.xy *. b.yx +. a.yy *. b.yy; x0 = a.x0 *. b.xx +. a.y0 *. b.xy +. b.x0; y0 = a.x0 *. b.yx +. a.y0 *. b.yy +. b.y0; } let translate m tx ty = multiply (init_translate tx ty) m let translation p = init_translate p.x p.y let xy_translation x y = init_translate x y let rotation = init_rotate let scale f = init_scale f f let xscaled f = init_scale f 1. let yscaled f = init_scale 1. f let slanted f = linear 1. f 0. 1. let zscaled p = linear p.x (0. -. p.y) p.y p.x let reflect p1 p2 = (*TODO *) assert false let rotate m f = multiply (init_rotate f) m let rotate_around p f = translate (rotate (translation (neg_point p)) f) p.x p.y let to_cairo x = x let identity = init_identity let remove_translation t = { t with x0 = 0.; y0 = 0.} let print fmt m = Format.fprintf fmt "[|[|%f;%f|];[|%f;%f|];[|%f;%f|]|]" m.xx m.xy m.yx m.yy m.x0 m.y0 mlpost-0.8.2/concrete/matrix.mli000066400000000000000000000011301306046515300166460ustar00rootroot00000000000000type point = Ctypes.point type t = Ctypes.matrix = { xx : float; yx : float; xy : float; yy : float; x0 : float; y0 : float; } val scale : float -> t val rotation : float -> t val xscaled : float -> t val yscaled : float -> t val slanted : float -> t val translation : point -> t val zscaled : point -> t val reflect : point -> point -> t val rotate_around : point -> float -> t val identity : t val multiply : t -> t -> t val xy_translation : float -> float -> t val remove_translation : t -> t val linear : float -> float -> float -> float -> t val print : Format.formatter -> t -> unit mlpost-0.8.2/concrete/metapath_lib.ml000066400000000000000000000530231306046515300176320ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module P = Point_lib open Point_lib open Point_lib.Infix module S = Spline_lib exception Not_implemented of string let not_implemented s = raise (Not_implemented s) let square x = x *. x let debug = false let info = debug || false type point = P.t type direction = | DVec of point | DCurl of float | DNo type joint = | JLine | JCurve of direction * direction | JCurveNoInflex of direction * direction | JTension of direction * float * float * direction | JControls of point * point type knot = point type t = | Start of knot | Cons of t * joint * knot | Start_Path of Spline.t list | Append_Path of t * joint * (Spline.t list) open Format let rec print_dir fmt = function |DNo -> fprintf fmt "DNo" |DVec p -> fprintf fmt "DVec %a" Point_lib.print p |DCurl f -> fprintf fmt "Dcurl %f" f and print_knot = Point_lib.print and print_joint fmt = function | JLine -> fprintf fmt "JLine" | JCurve (d1,d2) -> fprintf fmt "JCurve(%a,%a)" print_dir d1 print_dir d2 | JCurveNoInflex _ -> fprintf fmt "JCurveNoInflex" | JTension (_,f1,f2,_) -> fprintf fmt "JTension (%f,%f)" f1 f2 | JControls (p1,p2) -> fprintf fmt "JControls (%a,%a)" Point_lib.print p1 Point_lib.print p2 and print fmt = function | Start k1 -> fprintf fmt "[%a" print_knot k1 | Cons (p,j,k) -> fprintf fmt "%a;%a-%a" print p print_joint j print_knot k | Start_Path p-> fprintf fmt "{%a}" S.print_splines p | Append_Path (p1,j,p2) -> fprintf fmt "%a;%a-%a" print p1 print_joint j S.print_splines p2 type tension = float let tunity:tension = 1. (* Metafont is wiser in the computation of calc_value, calc_ff, curl_ratio, ... *) (* dk1, uk1 are d_k-1, u_k-1 *) (* ((3-α)α²γ + β³) / ( α³γ + (3-β)β²) *) let curl_ratio gamma alpha1 beta1 = let alpha = 1./.alpha1 and beta = 1./.beta1 in let gamma = if alpha <= beta then gamma *.square (alpha /. beta) else gamma in let beta = if alpha <= beta then beta else beta *. square (beta /. alpha) in (gamma *. (3. -. alpha) +. beta) /. (alpha *. gamma +. 3. -. beta) let reduce_angle x = (* 292. define reduce angle (#) *) if (abs_float x) > 180. then if x>0. then x -. 360. else x +. 360. else x let velocity st ct sf cf t = let num = (* 2 + √2(st - sf/16)(sf - st/16) * (ct -cf) *) 2. +. (sqrt 2.) *. (st -. (sf /. 16.)) *. (sf -. (st /. 16.)) *. (ct -. cf) in let denom = (* 3(1+1/2(√5 - 1))ct + 1/2(3-√5)cf *) 3. *. (1. +. 0.5 *. ((sqrt 5.) -. 1.) *. ct +. 0.5 *. (3. -. (sqrt 5.)) *. cf) in min ((num /. t) /. denom) 4. let calc_value dk1 dk art alt uk1 = (* Calculate the values aa = Ak /Bk , bb = Dk /Ck , dd = (3 - k-1 )dk,k+1 , ee = (3 - k+1 )dk-1,k , and cc = (Bk - uk-1 Ak )/Bk 288 *) let aa = 1./.(3.*.art -. 1.) in let bb = 1./.(3.*.alt -. 1.) in let cc = 1.-.(uk1*.aa) in let dd = dk*.(3.-.(1./.art)) in let ee = dk1*.(3.-.(1./.alt)) in aa,bb,cc,dd,ee let calc_ff cc dd ee art alt = (* Calculate the ratio ff = Ck /(Ck + Bk - uk-1 Ak ) 289 *) if alt < art then ee /. (ee +. cc *. dd *. (alt /. art)**2.) else let ee = ee *. (art /. alt)**2. in ee /. (ee +. cc *. dd) type path_type = | Endpoint | Explicit of point | Open of tension | Endcycle of tension | Curl of tension * float | Given of tension * float let tension = function | Endpoint -> 1. (* not sure ... *) | Explicit _ -> assert false | Open t | Endcycle t | Curl (t,_) | Given (t,_) -> t type kpath = { mutable left : path_type; mutable right : path_type; mutable link : kpath; mutable coord : point} let dumb_pos = {x=666.;y=42.} let dumb_dir = Endcycle 42. let rec dumb_link = { left = dumb_dir; right = dumb_dir; coord = dumb_pos; link = dumb_link} let mk_kpath ?(left=dumb_dir) ?(right=dumb_dir) ?(link=dumb_link) ?(coord=dumb_pos) () = { left = left; right = right; link = link; coord = coord } let print_path_type fmt = function | Endpoint -> fprintf fmt "Endpoint" | Explicit p -> fprintf fmt "Explicit %a" P.print p | Open t -> fprintf fmt "Open %f" t | Endcycle t -> fprintf fmt "Endcycle %f" t | Curl (t,f) -> fprintf fmt "Curl (%f,%f)" t f | Given (t,f) -> fprintf fmt "Given (%f,%f)" t f let print_one_kpath fmt q = fprintf fmt "@[{left = @[%a@];@,coord = @[%a@];@,right = @[%a@]}@]" print_path_type q.left P.print q.coord print_path_type q.right let print_kpath fmt p = let rec aux fmt q = fprintf fmt "@[{left = @[%a@];@,coord = @[%a@];@,right = @[%a@];@,link= @[%a@]}@]" print_path_type q.left P.print q.coord print_path_type q.right (fun fmt q -> if q!=p && q!=dumb_link then aux fmt q else fprintf fmt "...") q.link in aux fmt p let pi = acos (-.1.) let n_arg = let coef = 180./.pi in fun p -> (atan2 p.y p.x)*.coef let sincos = let coef = pi/.180. in fun a -> let a = coef *. a in sin a, cos a let set_controls p q at af rtension ltension deltaxy = (* procedure set controls (p, q : pointer ; k : integer ) 299 *) let st,ct = at in let sf,cf = af in let rr = velocity st ct sf cf (abs_float rtension) in let ss = velocity sf cf st ct (abs_float ltension) in let rr, ss = (* Decrease the velocities if necessary 300 *) if (rtension < 0. || ltension < 0.) && ((st >= 0. && sf >= 0.) || (st <= 0. && sf <= 0.)) then begin let sine = 2. *. cf *. abs_float st +. cf *. abs_float sf in if sine > 0. then let choice t s k = let sa = abs_float s in if t< 0. && sa < k *. sine then sa /. sine else k in choice rtension sf rr, choice ltension st ss else rr,ss end else rr, ss in let sb = p.coord +/ rr*/ (ct */ deltaxy +/ st */ P.swapmy deltaxy) in p.right <- Explicit sb; let sc = q.coord -/ ss */ (cf */ deltaxy +/ sf */ P.swapmx deltaxy) in q.left <- Explicit sc let print_array print fmt = Array.iter (fun e -> fprintf fmt "%a;@," print e) let print_float fmt = fprintf fmt "%f" let solve_choices p q n deltaxyk deltak psik = (* If Only one simple arc*) match p with | {right = Given (rt,rp);link={left=Given (lt,lq)}} -> (* Reduce to simple case of two givens and return 301 *) let aa = n_arg deltaxyk.(0) in let at = sincos (rp -. aa) in let saf,caf = sincos (lq -. aa) in let af = -.saf,caf in set_controls p q at af rt lt deltaxyk.(0) | {right = Curl (tp,cp);link={left=Curl (tq,cq)}} -> (* Reduce to simple case of straight line and return 302 *) let lt = abs_float tq and rt = abs_float tp in let tmp = P.sign deltaxyk.(0) in let fx p t f = let d = if t = tunity then deltaxyk.(0) +/ tmp else deltaxyk.(0) in Explicit (f p.coord (d // (3. *. t)) ) in p.right <- fx p rt (+/); q.left <- fx q lt (-/); | {link=t} as s -> let thetak = Array.make (n+2) 0. in let uu = Array.make (n+1) 0. in let vv = Array.make (n+1) 0. in let ww = Array.make (n+1) 0. in let curl_eq lt rt cc = (* Set up the equation for a curl 294 / 295 *) let lt = abs_float lt and rt = abs_float rt in if lt = tunity && rt = tunity then (2. *. cc +. 1.) /. (cc +. 2.) else curl_ratio cc rt lt in begin match p with |{right=Given (_,rp)} -> (* Set up the equation for a given value of 0 293 *) vv.(0) <- reduce_angle (rp -. n_arg deltaxyk.(0)); uu.(0) <- 0.; ww.(0) <- 0. |{right=Curl (tp,cc);link={left=lt}} -> uu.(0) <- curl_eq (tension lt) tp cc; vv.(0) <- -. (psik.(1) *. uu.(0)); ww.(0) <- 0. |{right=Open _} -> uu.(0) <- 0.;vv.(0) <- 0.;ww.(0) <- 1. | _ -> (* { there are no other cases } in 285 because of 273 *) assert false end; (let rec aux k r = function (* last point*) | {left=Curl (t,cc)} -> let ff = curl_eq t (tension r.right) cc in thetak.(n) <- -.((vv.(n-1)*.ff) /. (1.-.ff *. uu.(n-1))) | {left=Given (_,f)} -> (* Calculate the given value of n and goto found 292 *) thetak.(n) <- reduce_angle (f -. n_arg deltaxyk.(n-1)) | {link=t} as s-> (*end cycle , open : Set up equation to match mock curvatures at zk ; then goto found with n adjusted to equal 0 , if a cycle has ended 287 *) let art = abs_float (tension r.right) in let alt = abs_float (tension t.left) in let aa,bb,cc,dd,ee = calc_value deltak.(k-1) deltak.(k) art alt uu.(k-1) in let art = abs_float (tension s.right) in let alt = abs_float (tension s.left) in let ff = calc_ff cc dd ee art alt in uu.(k)<- ff*.bb; (* Calculate the values of vk and wk 290 *) let acc = -. (psik.(k+1)*.uu.(k)) in (match r.right with | Curl _ -> (*k=1...*) ww.(k) <- 0.; vv.(k) <- acc -. (psik.(1) *. (1. -. ff)) | _ -> let ff = (1. -. ff)/. cc in let acc = acc -. (psik.(k) *. ff) in let ff = ff*.aa in vv.(k) <- acc -. (vv.(k-1)*.ff); ww.(k) <- -. (ww.(k-1)*.ff)); (match s.left with | Endcycle _ -> (* Adjust n to equal 0 and goto found 291 *) let aa,bb = (let rec aux aa bb = function | 0 -> (vv.(n) -. (aa*.uu.(n))), (ww.(n) -. (bb*.uu.(n))) | k -> aux (vv.(k) -. (aa*.uu.(k))) (ww.(k) -. (bb*.uu.(k))) (k-1) in aux 0. 1. (n-1)) in let aa = aa /. (1. -. bb) in thetak.(n) <- aa; vv.(0) <- aa; for k = 1 to n-1 do vv.(k) <- vv.(k) +. (aa*.ww.(k)); done; | _ -> aux (k+1) s t); in aux 1 s t); (* Finish choosing angles and assigning control points 297 *) for k = n-1 downto 0 do thetak.(k) <- vv.(k) -. (thetak.(k+1) *. uu.(k)) done; (let rec aux k = function | _ when k = n -> () | {right=rt;link={left=lt} as t} as s -> let at = sincos thetak.(k) in let af = sincos (-.psik.(k+1) -. thetak.(k+1)) in set_controls s t at af (tension rt) (tension lt) deltaxyk.(k); aux (k+1) t in aux 0 p) let make_choices knots = (* If consecutive knots are equal, join them explicitly 271*) (let p = ref knots in while !p != knots do (match !p with | ({coord=coord;right=(Given _|Curl _|Open _);link=q} as k) when coord == q.coord -> if debug then Format.printf "@[find consecutive knots :k = @[%a@];\ @,q = @[%a@]@]@." print_one_kpath k print_one_kpath q; k.right <- Explicit coord; q.left <- Explicit coord; (match k.left with | Open tension -> k.left <- Curl (tension,tunity) | _ -> ()); (match k.right with | Open tension -> k.right <- Curl (tension,tunity) | _ -> ()); | _ -> ()); p:=(!p).link; done); (*Find the first breakpoint, h, on the path; insert an artificial breakpoint if the path is an unbroken cycle 272*) let h = (let rec aux = function | {left = (Endpoint | Endcycle _ | Explicit _ | Curl _ | Given _)} | {right= (Endpoint | Endcycle _ | Explicit _ | Curl _ | Given _)} as h -> h | {left = Open t} as h when h==knots -> knots.left <- Endcycle t; knots | {link=h} -> aux h in aux knots) in if debug then Format.printf "@[find h :h = @[%a@]@]@." print_one_kpath h; (*repeat Fill in the control points between p and the next breakpoint, then advance p to that breakpoint 273 until p = h*) (let rec aux = function | {right =(Endpoint|Explicit _);link = q} -> if q!=h then aux q | p -> let n,q = (let rec search_q n = function |{left=Open _;right=Open _;link=q} -> search_q (n+1) q | q -> (n,q) in search_q 1 p.link) in if debug then Format.printf "@[search_q : n = %i;@,p = @[%a@];@,q = @[%a@]@]@." n print_one_kpath p print_one_kpath q; (*Fill in the control information between consecutive breakpoints p and q 278*) (* Calculate the turning angles k and the distances dk,k+1 ; set n to the length of the path 281*) let deltaxyk = Array.make (n+1) P.zero in (* Un chemin sans cycle demande un tableau de taille n, de n+1 avec cycle *) let deltak = Array.make (n+1) 0. in let psik = Array.make (n+2) 0. in (let rec fill_array k = function (* K. utilise des inégalitées pour k=n et k = n+1 -> k>=n*) | s when k = n && (match s.left with |Endcycle _ -> false | _ -> true) -> psik.(n) <- 0. (* On a fait un tour le s.left précédent était un Endcycle *) | _ when k = n+1 -> psik.(n+1)<-psik.(1) | {link=t} as s -> deltaxyk.(k) <- t.coord -/ s.coord; deltak.(k) <- P.norm deltaxyk.(k); (if k > 0 then let {x=cosine;y=sine} = deltaxyk.(k-1) // deltak.(k-1) in let m = Matrix.linear cosine sine (-. sine) cosine in let psi = n_arg (Point_lib.transform m deltaxyk.(k)) in psik.(k) <- psi); fill_array (k+1) t in fill_array 0 p); if debug then (Format.printf "deltaxyk : %a@." (print_array P.print) deltaxyk; Format.printf "deltak : %a@." (print_array print_float) deltak; Format.printf "psik : %a@." (print_array print_float) psik); (*Remove open types at the breakpoints 282*) (match q with | {left=Open t} -> q.left <- Curl (t,1.) (* TODO cas bizarre *) | _ -> ()); (match p with | {left=Explicit pe;right=Open t} -> let del = p.coord -/ pe in if del=P.zero then p.right <- Curl (t,1.) else p.right <- Given (t,n_arg del) | _ -> ()); (*Format.printf "@[remove : p = @[%a@];@,q = @[%a@]@]@." print_one_kpath p print_one_kpath q;*) (* an auxiliary function *) solve_choices p q n deltaxyk deltak psik; if q!=h then aux q in aux h) let tension_of = function | JTension (_,t1,t2,_) -> (t1,t2) | JCurveNoInflex (_,_) -> (-1.,-1.) | _ -> (1.,1.) let direction t = function | DNo -> Open t | DVec p -> Given (t,n_arg p) | DCurl f -> Curl (t,f) let right_of_join p = function | JLine -> Explicit p | JControls (c,_) -> Explicit c | JCurve (d,_) -> direction 1. d | JCurveNoInflex (d,_) -> direction 1. d (*pas totalement correcte*) | JTension (d,f,_,_) -> direction f d let left_of_join p = function | JLine -> Explicit p | JControls (_,c) -> Explicit c | JCurve (_,d) -> direction 1. d | JCurveNoInflex (_,d) -> direction 1. d (*pas totalement correcte*) | JTension (_,_,f,d) -> direction f d let path_to_meta nknot l = let rec aux aknot = function | [] -> assert false | [a] -> let sa,sb,sc,sd = Spline.explode a in nknot.left <- Explicit sc; nknot.coord <- sd; aknot.link <- nknot ; aknot.right <- Explicit sb; aknot.coord <- sa; () | a::l -> let sa,sb,sc,_ = Spline.explode a in let nknot = mk_kpath ~left:(Explicit sc) () in aknot.link <- nknot; aknot.right <- Explicit sb; aknot.coord <- sa; aux nknot l in let aknot = mk_kpath ~left:Endpoint () in aux aknot l; aknot let print_option f fmt = function | None -> Format.fprintf fmt "None" | Some e -> f fmt e let kmeta_to_path ?cycle meta = if info then Format.printf "@[before (cycle:%a) : @[%a@]@]@." (print_option print_joint) cycle print meta; let rec to_knots aknot = function | Start p -> aknot.coord <- p; aknot.left <- Endpoint; aknot | Cons (pa,join,p) -> aknot.coord <- p; aknot.left <- left_of_join p join; let nknot = mk_kpath ~right:(right_of_join p join) ~link:aknot () in to_knots nknot pa | Start_Path pa -> path_to_meta aknot pa | Append_Path (p1,join,p2) -> let aknot2 = path_to_meta aknot p2 in aknot2.left<- left_of_join aknot2.coord join; let nknot = mk_kpath ~right:(right_of_join aknot2.coord join) ~link:aknot2 () in to_knots nknot p1 in let lknots = mk_kpath ~right:Endpoint () in let knots = to_knots lknots meta in lknots.link <- knots; (* Choose control points for the path and put the result into cur exp 891 *) (* when nocycle *) begin match cycle with |Some join -> begin lknots.right <- right_of_join knots.coord join; knots.left <- left_of_join knots.coord join; end | None -> begin (match knots.right with | Open t -> knots.right <- Curl (t,1.) | _ -> ()); (match lknots.left with | Open t -> lknots.left <- Curl (t,1.) | _ -> ()); end end; if debug then Format.printf "@[middle : @[%a@]@]@." print_kpath knots; make_choices knots; if debug then Format.printf "@[after : @[%a@]@]@." print_kpath knots; let rec aux = function | {right = Endpoint} -> [] | {right = Explicit sb;coord = sa; link={left = Explicit sc;coord = sd} as s} -> Spline.create sa sb sc sd :: (if s==knots then [] else (aux s)) | _ -> assert false in aux knots let kto_path ?cycle = function | Start p -> S.Point p | mp -> let res = S.Path { S.pl = kmeta_to_path ?cycle mp; cycle = cycle <> None} in if info then Format.printf "@[end : @[%a@]@]@." S.print res; res let rec to_path_simple = function | Start p -> S.create_line p p | Cons (pa,JLine,p) -> S.add_end_line (to_path_simple pa) p | Cons (pa,JControls(c1,c2),p) -> S.add_end_spline (to_path_simple pa) c1 c2 p | Start_Path p -> S.Path {S.pl=p;cycle=false} | Append_Path (p1,JControls(c1,c2),p2) -> S.append (to_path_simple p1) c1 c2 (S.Path {S.pl=p2;cycle=false}) | (Cons(pa,JCurve _,p)) -> S.add_end_line (to_path_simple pa) p (* Faux*) |p -> Format.printf "not implemented %a@." print p; not_implemented "to_path" let knot p = p let vec_direction p = DVec p let curl_direction f = DCurl f let no_direction = DNo let equalize_dir = function (* Faut-il égaliser l'un avec l'autre *et* l'autre avec l'un? *) (*Put the pre-join direction information into node q 879 *) | DNo, ((DVec p) as y) -> y,y | c -> c let start k = Start k let line_joint = (*JLine but metafont defined -- as a macro for*) JCurve(curl_direction 1.,curl_direction 1.) let curve_joint dir1 dir2 = JCurve(dir1,dir2) let curve_no_inflex_joint dir1 dir2 = JCurveNoInflex(dir1,dir2) let tension_joint dir1 f1 f2 dir2 = JTension (dir1,f1,f2,dir2) let controls_joint p1 p2 = JControls (p1,p2) let concat p j k = Cons (p,j,k) let rec append p j = function | Start knot -> Cons (p,j,knot) | Cons(p2,j2,k2) -> Cons(append p j p2,j2,k2) | Start_Path p2 -> Append_Path(p,j,p2) | Append_Path (p2,j2,p3) -> Append_Path(append p j p2,j2,p3) let to_path p = kto_path p let cycle j p = kto_path ~cycle:j p let from_path = function | S.Path p -> Start_Path p.S.pl | S.Point p -> Start p module Approx = struct let lineto = S.create_lines let simple_join = curve_joint no_direction no_direction let curve l = let rec aux = function | [] -> assert false | [a] -> start (knot a) | a::l -> concat (aux l) simple_join (knot a) in aux (List.rev l) let fullcircle_ l = let l2 = l/.2. in cycle simple_join (curve [{x=l2;y=0.};{x=0.;y=l2};{x= -.l2;y=0.};{x=0.;y= -.l2}]) let fullcircle1 = lazy (fullcircle_ 1.) let fullcircle = function | 1. -> Lazy.force fullcircle1 | l -> fullcircle_ l let halfcirle l = (* 2. because fullcircle is defined with 4 points *) S.subpath (fullcircle l) 0. 2. let quartercircle l = S.subpath (fullcircle l) 0. 1. let unitsquare l = let p = {x=0.;y=0.} in (S.close (S.create_lines [p;{x=l;y=0.};{x=l;y=l};{x=0.;y=l};p])) end mlpost-0.8.2/concrete/metapath_lib.mli000066400000000000000000000051211306046515300177770ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type point = Point_lib.t type t type joint type knot type direction val print : Format.formatter -> t -> unit val print_joint : Format.formatter -> joint -> unit val print_dir : Format.formatter -> direction -> unit val print_knot : Format.formatter -> knot -> unit val knot : point -> knot val vec_direction : point -> direction val curl_direction : float -> direction val no_direction : direction val equalize_dir : direction * direction -> direction * direction val line_joint : joint val curve_joint : direction -> direction -> joint val curve_no_inflex_joint : direction -> direction -> joint val tension_joint : direction -> float -> float -> direction -> joint val controls_joint : point -> point -> joint val start : knot -> t val concat : t -> joint -> knot -> t val append : t -> joint -> t -> t val cycle : joint -> t -> Spline_lib.path val to_path : t -> Spline_lib.path val from_path : Spline_lib.path -> t module Approx : sig val lineto : point list -> Spline_lib.path val fullcircle : float -> Spline_lib.path (** fullcircle l is the circle of diameter l centered on (0, 0) *) val halfcirle : float -> Spline_lib.path (** halfcircle l is the upper half of a fullcircle of diameter l *) val quartercircle : float -> Spline_lib.path (** quartercircle l is the first quadrant of a circle of diameter l *) val unitsquare : float -> Spline_lib.path (** unitsquare l : the path (0,0)--(l,0)--(l,l)--(0,l)--cycle *) end mlpost-0.8.2/concrete/mps.ml000066400000000000000000000421401306046515300157760ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Point_lib open Matrix module P = Picture_lib module S = Spline_lib open Dviinterp open Concrete_types let fprintf = Printf.fprintf let conversion = 0.3937 *. 72. let point_of_cm cm = conversion *. cm let float fmt f = (* PDF does not understand e notation, so we protect the printf which uses %g in the cases where this would use e notation; we do not need that much precision anyway*) let a = abs_float f in if a < 0.0001 then fprintf fmt "0" else if a >= 1.e04 then fprintf fmt "%.4f" f else Printf.fprintf fmt "%.4g" f let rec list sep p fmt l = match l with | [] -> () | [x] -> p fmt x | x::xs -> p fmt x; sep fmt; list sep p fmt xs let option sep p fmt o = match o with | None -> () | Some x -> p fmt x ; sep fmt let nothing _ = () let space fmt = fprintf fmt " " type specials_env = { externalimages : (string * Matrix.t,int) Hashtbl.t; colors : (P.color,int) Hashtbl.t; count : int ref} let new_specials_env () = {externalimages = Hashtbl.create 7; colors = Hashtbl.create 17; count = ref 0} module MPS = struct type line_cap = | ButtCap | RoundCap | SquareCap type line_join = | MiterJoin | RoundJoin | BevelJoin let moveto_float fmt x y = fprintf fmt "%a %a moveto" float x float y let lineto_float fmt x y = fprintf fmt "%a %a lineto" float x float y let rlineto_float fmt x y = fprintf fmt "%a %a rlineto" float x float y let lineto fmt p = lineto_float fmt p.x p.y let moveto fmt p = moveto_float fmt p.x p.y let rlineto fmt p = rlineto_float fmt p.x p.y let lineto_floatp fmt (x,y) = lineto_float fmt x y let curveto fmt p1 p2 p3 = fprintf fmt "%a %a %a %a %a %a curveto" float p1.x float p1.y float p2.x float p2.y float p3.x float p3.y let close_path fmt = fprintf fmt "close_path" let newpath fmt = fprintf fmt "newpath" let stroke fmt = fprintf fmt "stroke" let fill fmt = fprintf fmt "fill" let showpage fmt = fprintf fmt "showpage" let clip fmt = fprintf fmt "clip" let gsave fmt = fprintf fmt "gsave" let grestore fmt = fprintf fmt "grestore" let setlinewidth fmt f = (** strange treatment of linewidth of Metapost *) fprintf fmt "0 %a dtransform truncate idtransform setlinewidth pop" float f let setlinecap fmt c = let i = match c with | ButtCap -> 0 | RoundCap -> 1 | SquareCap -> 2 in fprintf fmt "%d setlinecap" i let setlinejoin fmt j = let i = match j with | MiterJoin -> 0 | RoundJoin -> 1 | BevelJoin -> 2 in fprintf fmt "%d setlinejoin" i let matrix fmt t = fprintf fmt "[%a %a %a %a %a %a]" float t.xx float t.yx float t.xy float t.yy float t.x0 float t.y0 let transform fmt t = if t = Matrix.identity then () else fprintf fmt "%a concat" matrix t let scolor_rgb fmt r g b = fprintf fmt "%a %a %a setrgbcolor" float r float g float b let scolor_cmyk fmt c m y k = fprintf fmt "%a %a %a %a setcmykcolor" float c float m float y float k let scolor_gray fmt c = fprintf fmt "%a setgray" float c let scolor fmt c = match c with | Concrete_types.RGB (r,g,b) -> scolor_rgb fmt r g b | Concrete_types.CMYK (c,m,y,k) -> scolor_cmyk fmt c m y k | Concrete_types.Gray c -> scolor_gray fmt c let color fmt c = match c with | Concrete_types.OPAQUE c -> scolor fmt c | Concrete_types.TRANSPARENT _ -> (* harvest take care of that case *) assert false let dvi_color fmt c = match c with | Dviinterp.RGB (r,g,b) -> scolor_rgb fmt r g b | Dviinterp.CMYK (c,m,y,k) -> scolor_cmyk fmt c m y k | Dviinterp.HSB _ -> assert false | Dviinterp.Gray g -> scolor_gray fmt g let dash fmt (offset,pattern) = fprintf fmt "[%a ] %a setdash" (list space float) pattern float offset let char_const fmt c = fprintf fmt "\\%03lo" c let glyph fmt cl font = fprintf fmt "(%a) %s %a fshow" (list nothing char_const) cl (Fonts.tex_name font) float (Fonts.scale font conversion) let glyphp fmt (cl, font) = glyph fmt cl font let rectangle fmt p w h = fprintf fmt "%t %a %a %a %a %t %t" newpath moveto p lineto_floatp (p.x+.w, p.y) lineto_floatp (p.x+.w, p.y+.h) lineto_floatp (p.x, p.y+.h) close_path fill let rectanglep fmt (p,w,h) = rectangle fmt p w h end let in_context fmt f = fprintf fmt "%t %t %t" MPS.gsave f MPS.grestore let fill_rect fmt trans i x y w h = let x = point_of_cm x and y = point_of_cm y and w = point_of_cm w and h = point_of_cm h in let p = { x = x ; y = y } in in_context fmt (fun _ -> fprintf fmt "%a %a %a" MPS.transform trans MPS.dvi_color i.Dviinterp.color MPS.rectanglep (p,w,h) ) let draw_char fmt trans text = (* FIXME why do we need to negate y coordinates? *) let (f1,f2) = text.tex_pos in let f1 = point_of_cm f1 and f2 = point_of_cm f2 in let p = { x = f1; y = -. f2 } in in_context fmt (fun _ -> fprintf fmt "%a %a %a %a" MPS.transform trans MPS.dvi_color text.Dviinterp.tex_info.Dviinterp.color MPS.moveto p MPS.glyphp (text.tex_string, text.tex_font) ) (* FIXME why do we need to negate y coordinates? *) let tex_cmd fmt trans c = match c with | Dviinterp.Fill_rect (i,x,y,w,h) -> fill_rect fmt trans i x (-. y) w h | Dviinterp.Draw_text text -> draw_char fmt trans text | Dviinterp.Specials _ -> () | Dviinterp.Draw_text_type1 _ -> assert false let draw_tex fmt t = list space (fun fmt x -> tex_cmd fmt t.Gentex.trans x) fmt t.Gentex.tex let curveto fmt s = let sa, sb, sc, sd = Spline.explode s in if sa = sb && sc = sd then MPS.lineto fmt sd else MPS.curveto fmt sb sc sd let path = let rec path fmt = function | S.Path p -> begin match p.S.pl with | [] -> assert false | (x::_) as l -> fprintf fmt "%a %a" MPS.moveto (Spline.left_point x) (list space curveto) l end ; if p.S.cycle then begin fprintf fmt " %t" MPS.close_path end | S.Point p -> fprintf fmt "%a %a" MPS.moveto p MPS.rlineto p in fun fmt p -> fprintf fmt "%t %a" MPS.newpath path p let pen fmt t = (* FIXME do something better *) (* for now assume that the pen is simply a scaled circle, so just grab the xx * value of the matrix and use that as linewidth *) MPS.setlinewidth fmt t.xx let specials_signal = 0.123 let specials_division = 1000. (** map real color to encoded color : - identity for four first case - encoding for transparency - encoding specials rgb opaque color *) let add_color_se clr se = match clr with | None -> clr | Some OPAQUE Gray _ -> clr | Some OPAQUE CMYK _ -> clr | Some OPAQUE RGB (r,_,_) when r <> specials_signal -> clr | Some clr -> let nb = try Hashtbl.find se.colors clr with Not_found -> incr se.count; let nb = !(se.count) in Hashtbl.add se.colors clr nb; nb in let nb = (float_of_int nb) /. specials_division in Some (OPAQUE (RGB (specials_signal,0.003,nb))) let add_image_se = let dumb_path = Spline_lib.create_lines [Point_lib.zero;Point_lib.zero; Point_lib.zero;Point_lib.zero] in let dumb_path = Spline_lib.close dumb_path in fun p se -> let nb = try Hashtbl.find se.externalimages p with Not_found -> incr se.count; let nb = !(se.count) in Hashtbl.add se.externalimages p nb; nb in (* 0.010? *) let nb = (float_of_int nb) /. specials_division in let c = Some (OPAQUE (RGB (specials_signal,0.019,nb))) in P.Fill_path(dumb_path,c) let rec harvest se = function | P.Empty as p -> p | P.OnTop l -> let add acc e = let p = harvest se e in if p = P.Empty then acc else p::acc in let l = List.fold_left add [] l in if l = [] then P.Empty else P.OnTop (List.rev l) | P.Stroke_path(p,c,d,e) -> P.Stroke_path(p,add_color_se c se,d,e) | P.Fill_path (p,c) -> P.Fill_path (p,add_color_se c se) | P.Tex _ as p -> p | P.Transform (m,t) -> harvest se (P.apply_transform_cmds m t) | P.Clip (com,p) -> let com = harvest se com in if com = P.Empty then com else P.Clip (com,p) | P.ExternalImage (f,h,m) -> add_image_se (f,m) se (* For specials in mps The specials are described at the bottom of the preamble The first line describe the version, the special signal and the special_div %%MetaPostSpecials: 2.0 123 1000 The next describe specials : length data special_number special_type %%MetaPostSpecial: 7 1 0.5 1 0 0 1 3 Color cmyk : 7 (cmyk_counter) c m y k special_number 1 Color spot : 2 Color rgba : 7 mode_transparency value_transparency r g b special_number 3 Color cmyka : 8 mode_transparency value_transparency c m y k special_number 4 Color spota : 8 mode_transparency value_transparency ? ? ? ? special_number 5 In the text they appear as color : special_signal (1 cmyk 2 spot 3 rgb) special_number 0.123 0.003 0.001 setrgbcolor *) let print_specials_color = let pr_color fmt c = match c with | RGB (r,b,g) -> fprintf fmt "%f %f %f" r g b | Gray g -> fprintf fmt "%f %f %f" g g g | CMYK (c,m,y,k) -> fprintf fmt "%f %f %f %f" c m y k in fun fmt cl id -> let trans, c = match cl with | OPAQUE c -> 1., c | TRANSPARENT (a,c) -> a, c in let mode, special_type = match c with | RGB _ | Gray _ -> 7, 3 | CMYK _ -> 8, 4 in fprintf fmt "%%%%MetaPostSpecial: "; fprintf fmt "%i 1 %f %a %i %i\n" mode trans pr_color c id special_type let print_specials_extimg fmt (f,m) id = fprintf fmt "%%%%MetaPostSpecial: 9 %f %f %f %f %f %f %s %i 10\n" m.xx m.yx m.xy m.yy m.x0 m.y0 f id let print_specials fmt cx = let se = new_specials_env () in let cx = harvest se cx in if Hashtbl.length se.colors <> 0 || Hashtbl.length se.externalimages <> 0 then begin fprintf fmt "%%%%MetaPostSpecials: 2.0 %i %i\n" (int_of_float (specials_signal *. specials_division)) (int_of_float specials_division); Hashtbl.iter (print_specials_color fmt) se.colors; Hashtbl.iter (print_specials_extimg fmt) se.externalimages end; cx let rec picture fmt p = match p with | P.Empty -> () | P.OnTop l -> list space picture fmt l | P.Stroke_path(pa,clr,pe,da) -> in_context fmt (fun _ -> fprintf fmt "%a%a%a %a %t\n" (option space MPS.color) clr (option space MPS.dash) da pen pe path pa MPS.stroke) | P.Fill_path (p,clr)-> in_context fmt (fun _ -> fprintf fmt "%a %a %t\n" (option space MPS.color) clr path p MPS.fill) | P.Tex t -> draw_tex fmt t | P.Clip (com,p) -> in_context fmt (fun _ -> fprintf fmt "%a %t %a" path p MPS.clip picture com ) | P.Transform _ | P.ExternalImage _ -> assert false module BitMap = struct (* FIXME replace me by something more efficient *) (* encode our bitmap as a string (array of chars) *) type t = string (* a char '0' corresponds to '0', a char '1' corresponds to '1' *) let mk n = String.make n '0' let set t n = t.[n] <- '1' let get t n = t.[n] let min t = try String.index t '1' with Not_found -> assert false let safe_sub_four s i = (* if the string does not have 4 remaining chars, pad with zeros *) let my_len = 4 in let l = String.length s in if i + my_len <= l then String.sub s i my_len else let buf = String.make my_len '0' in for j = i to l - 1 do buf.[j-i] <- s.[j] done; buf let one_char t i = match safe_sub_four t i with | "0000" -> '0' | "0001" -> '1' | "0010" -> '2' | "0011" -> '3' | "0100" -> '4' | "0101" -> '5' | "0110" -> '6' | "0111" -> '7' | "1000" -> '8' | "1001" -> '9' | "1010" -> 'a' | "1011" -> 'b' | "1100" -> 'c' | "1101" -> 'd' | "1110" -> 'e' | "1111" -> 'f' | _ -> assert false let chars t = let b = Buffer.create 5 in let rec aux k = let c = one_char t k in if c = '0' then Buffer.contents b else begin Buffer.add_char b c; aux (k+4) end in let m = min t in Printf.sprintf "%x:%s" m (aux m) end (* FIXME do better than comparing font names *) module FontCmp = struct type t = Fonts.t let compare a b = String.compare (Fonts.tex_name a) (Fonts.tex_name b) end (* module FS = Set.Make(FontCmp) *) module FM = Map.Make(FontCmp) let max_char f = (Fonts.metric f).Tfm.file_hdr.Tfm.ec let fonts p = let x = ref FM.empty in Picture_lib.iter (fun p -> match p with | P.Tex g -> List.iter (fun c -> match c with | Draw_text text -> let f = text.tex_font in let map = try FM.find f !x with Not_found -> let map = BitMap.mk (max_char f) in x := FM.add f map !x; map in List.iter (fun x -> BitMap.set map (Int32.to_int x)) text.tex_string | _ -> ()) g.Gentex.tex | _ -> ()) p; !x (* Following the dvips manual, for example on http://www.radicaleye.com/dvipsman/dvips.html#SEC34, the Font line looks as follows: %*Font: tfmname scaledbp designbp hex-start:hex-bitstring Here is the meaning of each of these elements: tfmname The TeX TFM filename, e.g., `cmr10'. You can give the same tfmname on more than one `%*Font' line; this is useful when the number of characters from the font used needs a longer hex-bitstring (see item below) than conveniently fits on one line. scaledbp The size at which you are using the font, in PostScript points (TeX big points). 72bp = 72.27pt = 1in. designbp The designsize of the font, again in PostScript points. This should match the value in the TFM file tfmname. Thus, for `cmr10', it should be `9.96265'. hex-start The character code of the first character used from the font, specified as two ASCII hexadecimal characters, e.g., `4b' or `4B' for `K'. hex-bitstring An arbitrary number of ASCII hexadecimal digits specifying which characters following (and including) hex-start are used. This is treated as a bitmap. For example, if your figure used the single letter `K', you would use `4b:8' for hex-start and hex-bitstring. If it used `KLMNP', you would use `4b:f4'. *) let fontdecl fmt f map = let n = Fonts.tex_name f in let d = Fonts.design_size f in let r = point_of_cm (Fonts.ratio_cm f) in let magic_string = BitMap.chars map in fprintf fmt "%%*Font: %s %f %f %s\n" n d r magic_string let draw fmt x = let {x = minx; y = miny},{x = maxx; y = maxy} = Picture_lib.bounding_box x in let minxt, minyt, maxxt, maxyt = floor minx, floor miny, ceil maxx, ceil maxy in fprintf fmt "%%!PS\n"; fprintf fmt "%%%%BoundingBox: %f %f %f %f\n" minxt minyt maxxt maxyt; fprintf fmt "%%%%HiResBoundingBox: %f %f %f %f\n" minx miny maxx maxy; fprintf fmt "%%%%Creator: Mlpost %s\n" Version.version; (** metapost add a creation date but it breaks determinism *) (* fprintf fmt "%%%%CreationDate: %s\n" (Misc.date_string ()); *) fprintf fmt "%%%%Pages: 1\n"; FM.iter (fontdecl fmt) (fonts x); fprintf fmt "%%%%BeginProlog\n"; fprintf fmt "%%%%EndProlog\n"; fprintf fmt "%%%%Page: 1 1\n"; let cx = print_specials fmt (P.content x) in fprintf fmt "%a %a %a %a %t" MPS.setlinewidth (P.default_line_size /.2.) MPS.setlinecap MPS.RoundCap MPS.setlinejoin MPS.RoundJoin picture cx MPS.showpage; fprintf fmt "\n%%%%EOF\n" let generate_one fn fig = File.write_to fn (fun fmt -> let fig = Compute.commandpic fig in (* Format.printf "picturelib code: \n %a@." P.Print.pic fig; *) draw fmt fig); fn let mps figl = List.map (fun (fn,fig) -> let fn = File.mk fn "mps" in (* Format.printf "metapost code:\n %a@."Print.commandpic fig; *) generate_one fn fig) figl let dump () = ignore (mps (Defaults.emited ())) let generate figs = ignore (mps figs) mlpost-0.8.2/concrete/mps.mli000066400000000000000000000023751306046515300161550ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) val draw : out_channel -> Picture_lib.t -> unit val dump: unit -> unit val generate : (string * Command.t) list -> unit mlpost-0.8.2/concrete/myocamlbuild.ml000066400000000000000000000107711306046515300176650ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Ocamlbuild_plugin (* open Command -- no longer needed for OCaml >= 3.10.2 *) (* these functions are not really officially exported *) let run_and_read = Ocamlbuild_pack.My_unix.run_and_read let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings let split s ch = let x = ref [] in let rec go s = let pos = String.index s ch in x := (String.before s pos)::!x; go (String.after s (pos + 1)) in try go s with Not_found -> !x let split_nl s = split s '\n' let before_space s = try String.before s (String.index s ' ') with Not_found -> s (* this lists all supported packages *) let find_packages () = List.map before_space (split_nl & run_and_read "ocamlfind list") (* this is supposed to list available syntaxes, but I don't know how to do it. *) let find_syntaxes () = ["camlp4o"; "camlp4r"; "bitstring.syntax"] (* ocamlfind command *) let ocamlfind x = S[A"ocamlfind"; x] let _ = dispatch begin function | Before_options -> (* by using Before_options one let command line options have an higher priority *) (* on the contrary using After_options will guarantee to have the higher priority *) (* override default commands by ocamlfind ones *) Options.ocamlc := ocamlfind & A"ocamlc"; Options.ocamlopt := ocamlfind & A"ocamlopt"; Options.ocamldep := ocamlfind & A"ocamldep"; Options.ocamldoc := ocamlfind & A"ocamldoc"; Options.ocamlmktop := ocamlfind & A"ocamlmktop" | After_rules -> (* When one link an OCaml library/binary/package, one should use -linkpkg *) flag ["ocaml"; "link"] & A"-linkpkg"; (* For each ocamlfind package one inject the -package option when * compiling, computing dependencies, generating documentation and * linking. *) List.iter begin fun pkg -> flag ["ocaml"; "compile"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "doc"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "link"; "pkg_"^pkg] & S[A"-package"; A pkg]; end (find_packages ()); (* Like -package but for extensions syntax. Morover -syntax is useless * when linking. *) List.iter begin fun syntax -> flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; end (find_syntaxes ()); (* The default "thread" tag is not compatible with ocamlfind. Indeed, the default rules add the "threads.cma" or "threads.cmxa" options when using this tag. When using the "-linkpkg" option with ocamlfind, this module will then be added twice on the command line. To solve this, one approach is to add the "-thread" option when using the "threads" package using the previous plugin. *) flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]) | _ -> () end mlpost-0.8.2/concrete/picture_lib.ml000066400000000000000000000202271306046515300175020ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) let diameter_of_a_dot = 3. let default_line_size = 1. module BoundingBox : sig type pen = Spline_lib.path type t (** The type of the approximation *) val iter : (Spline.t -> unit) -> t -> unit val empty : t val create : ?base:pen -> Spline_lib.path -> t val of_path : ?base:pen -> Spline_lib.path -> t val union : t -> t -> t val transform : Matrix.t -> t -> t val bounding_box : t -> Point_lib.t * Point_lib.t val of_bounding_box : Point_lib.t * Point_lib.t -> t end = struct (* A rendre plus performant ou pas*) (* le point correspond à un écart à prendre autour de la bounding box *) module S = Spline_lib module P = Point_lib type pen = S.path type t = (Spline.t list * pen) list let iter f l = List.iter (fun (e,_) -> List.iter (fun s -> f s) e) l let empty = [] let create ?(base= S.Point P.zero) = function | S.Path p -> [p.S.pl,base] | S.Point p -> let x = match S.of_bounding_box (p,p) with | S.Path p -> p.S.pl | S.Point _ -> assert false in [x, base] let of_path = create let union x y = List.rev_append x y let transform t x = List.map (fun (x,f) -> List.map (Spline.transform t) x, S.transform (Matrix.remove_translation t) f) x open P open P.Infix let bounding_box sl = let (x_min,y_min,x_max,y_max) = P.list_min_max_float (fun (e,f) -> let (x_min,y_min,x_max,y_max)= P.list_min_max_float Spline.precise_bounding_box e in let pen_min,pen_max = S.bounding_box f in let p1,p2 = {x=x_min;y=y_min}+/pen_min,{x=x_max;y=y_max}+/pen_max in (p1.x,p1.y,p2.x,p2.y)) sl in {x=x_min;y=y_min},{x=x_max;y=y_max} let of_bounding_box l = create (S.of_bounding_box l) end module MP = Metapath_lib open Types module P = Point_lib module S = BoundingBox type transform = Matrix.t type num = float type dash = float * num list type pen = transform type color = Concrete_types.color type path = Spline_lib.path type id = int type interactive = | IntEmpty | IntTransform of interactive * transform | IntClip of interactive * path | IntOnTop of interactive * interactive | Inter of path * id type commands = | Empty | Transform of transform * commands | OnTop of commands list | Tex of Gentex.t | Stroke_path of path * color option * pen * dash option | Fill_path of path * color option | Clip of commands * path | ExternalImage of string * float * transform and t = { fcl : commands; fb : BoundingBox.t; fi : interactive} let content x = x.fcl let empty = { fcl = Empty; fb = S.empty ; fi = IntEmpty } let tex t = {fcl = Tex t; fb = S.of_bounding_box (Gentex.bounding_box t); fi = IntEmpty} let fill_path p c = {fcl = Fill_path (p,c); fb = S.of_path p; fi = IntEmpty} let base_of_pen pen = Spline_lib.transform pen (MP.Approx.fullcircle default_line_size) let stroke_path p c pen d = { fcl= Stroke_path (p,c,pen,d); fb = S.of_path ~base:(base_of_pen pen) p; fi = IntEmpty} let draw_point p = stroke_path (Spline_lib.create_point p) None (Matrix.scale diameter_of_a_dot) None let clip p path = {fcl= Clip (p.fcl,path); fb = S.of_path path; (* la bounding box d'un clip est la bounding_box du chemin fermé*) fi = IntClip (p.fi,path)} let externalimage_dimension filename : float * float = let inch = Unix.open_process_in (Format.sprintf "identify -format \"%%h\\n%%w\" \"%s\"" filename) in try let h = float_of_string (input_line inch) in let w = float_of_string (input_line inch) in (h,w) with End_of_file | Failure "float_of_string" -> invalid_arg (Format.sprintf "Unknown external image %s" filename) let external_image filename spec = let fh,fw = externalimage_dimension filename in let height,width = begin match spec with | `Exact (h,w) -> (h,w) | `None -> (fh,fw) | `Height h -> h,(fw/.fh)*.h | `Width w -> (fh/.fw)*.w,w | `Inside (h,w) -> let w = min (h*.(fw/.fh)) w in (fh/.fw)*.w,w end in (* TODO : width/.fw pour cairo width pour mps *) let m = Matrix.multiply (Matrix.xscaled width) (Matrix.yscaled height) in {fcl = ExternalImage (filename,height,m); fb = S.of_bounding_box (P.zero,{P.x=width;y=height}); fi = IntEmpty} let interactive path id = {fcl = Empty; fb = S.empty; fi = Inter (path,id)} let is_empty t = t.fcl = Empty let on_top t1 t2 = if is_empty t1 then t2 else if is_empty t2 then t1 else { fcl = OnTop [t1.fcl;t2.fcl]; fb = S.union (t1.fb) (t2.fb); fi = IntOnTop (t1.fi,t2.fi) } let transform m t = {fcl = Transform (m,t.fcl); fb = S.transform m t.fb; fi = IntTransform (t.fi,m)} let shift t w h = transform (Matrix.xy_translation w h) t let bounding_box t = S.bounding_box t.fb let baseline p = match p.fcl with | Tex tex -> Gentex.get_bases_pt tex | _ -> [] let apply_transform_cmds t = let rec aux pic = match pic with | Empty -> Empty | OnTop l -> OnTop (List.map aux l) | Fill_path (p,c) -> Fill_path (path p,c) | Stroke_path (pa,c,pe,d) -> Stroke_path (path pa, c, pe, d) | Clip (cmds, p) -> Clip (aux cmds, path p) | Tex g -> Tex { g with Gentex.trans = Matrix.multiply t g.Gentex.trans } | ExternalImage (f,h,m) -> ExternalImage (f,h,Matrix.multiply t m) | Transform (t', l) -> Transform (Matrix.multiply t' t, l) and path p = Spline_lib.transform t p in aux let iter f t = let rec aux p = f p; match p with | Empty | Fill_path _ | Stroke_path _ | ExternalImage _ | Tex _ -> () | OnTop l -> List.iter aux l | Clip (c,_) -> aux c | Transform (_,l) -> aux l in aux (content t) let apply_transform t p = { p with fcl = apply_transform_cmds t p.fcl; fb = BoundingBox.transform t p.fb; } module Dash = struct type t = float * float list type input_dash = | On of float | Off of float let shifted f (x,d) = (x+.f,d) let line = 0., [3.; 3. ] let dots = 0., [0.; 5.] let rec on acc = function | [] -> [acc] | On f::l -> on (f +. acc) l | Off f::l -> acc::(off f l) and off acc = function | [] -> [acc] | On f::l -> acc::(on f l) | Off f::l -> off (f +. acc) l and to_dash = function | [] -> [] | On f::l -> on f l | Off f::l -> 0. :: (off f l) let pattern l = 0., to_dash l let scale f (x,l) = x, List.map (fun z -> f *. z) l end module Print = struct (* debug printing *) open Format let rec command fmt c = match c with | Empty -> pp_print_string fmt "empty" | Stroke_path (p,_,_,_) -> Spline_lib.print fmt p | Tex g -> Gentex.deb_print fmt g | OnTop cl -> Misc.print_list Misc.newline command fmt cl (* | Transform of transform * commands | Fill_path of path * color option | Clip of commands * path | ExternalImage of string * float * float *) | _ -> assert false let pic fmt p = command fmt p.fcl end mlpost-0.8.2/concrete/picture_lib.mli000066400000000000000000000055641306046515300176620ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type transform = Matrix.t type num = float type dash = float * num list type pen = transform type color = Concrete_types.color type path = Spline_lib.path type interactive type commands = | Empty | Transform of transform * commands | OnTop of commands list | Tex of Gentex.t | Stroke_path of path * color option * pen * dash option | Fill_path of path * color option | Clip of commands * path | ExternalImage of string * float * transform (* filename, height, transform *) type t type id = int val content : t -> commands val tex : Gentex.t -> t val fill_path : path -> color option -> t val stroke_path : path -> color option -> pen -> dash option -> t val draw_point : Point_lib.t -> t val default_line_size : float val clip : t -> path -> t val external_image : string -> [< `Exact of float * float | `Height of float | `Inside of float * float | `None | `Width of float ] -> t val interactive : Spline_lib.path -> id -> t val on_top : t -> t -> t val empty : t val transform : Matrix.t -> t -> t val shift : t -> float -> float -> t val apply_transform : Matrix.t -> t -> t val apply_transform_cmds : Matrix.t -> commands -> commands val iter : (commands -> unit) -> t -> unit val bounding_box : t -> Point_lib.t * Point_lib.t (* lower left and upper right point *) (* Return the empty list if the picture is not directly a Tex *) val baseline : t -> float list module Dash : sig type t = dash type input_dash = | On of float | Off of float val shifted : float -> t -> t val line : t val dots : t val pattern : input_dash list -> t val scale : float -> t -> t end module Print : sig val command : Format.formatter -> commands -> unit val pic : Format.formatter -> t -> unit end mlpost-0.8.2/concrete/point_lib.ml000066400000000000000000000061571306046515300171660ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Ctypes type t = point = { x : float; y : float } let zero = { x = 0. ; y = 0. } let add a b = {x = a.x+.b.x; y = a.y+.b.y} let sub a b = {x = a.x-.b.x; y = a.y-.b.y} let opp a = {x = -.a.x; y = -.a.y} let mult c a = {x = a.x*.c; y = a.y*.c} let div a c = {x = a.x/.c; y = a.y/.c} let transform m p = { x = m.xx *. p.x +. m.xy *. p.y +. m.x0; y = m.yx *. p.x +. m.yy *. p.y +. m.y0; } (* copied here from matrix.ml to avoid dependency *) let init_rotate a = let s = sin a in let c = cos a in { xx = c; yx = s; xy = -.s; yy = c; x0 = 0.; y0 = 0. } let rotated f = transform (init_rotate f) let swapmx {x=x;y=y} = {x=y;y= -.x} let swapmy {x=x;y=y} = {x= -.y;y=x} module Infix = struct let (+/) = add let (-/) = sub let ( */) = mult let ( //) = div end open Infix let segment f p1 p2 = (1.-.f) */ p1 +/ f */ p2 let middle = segment 0.5 let print fmt x = Format.fprintf fmt "(%f,%f)" x.x x.y let norm2 p : float = p.x*.p.x+.p.y*.p.y let norm p = sqrt (norm2 p) let dist2 a b = norm2 (a -/ b) let dist a b = sqrt (dist2 a b) let list_min_max f = List.fold_left (fun ({x=x_min;y=y_min},{x=x_max;y=y_max}) s -> let ({x=sx_min;y=sy_min},{x=sx_max;y=sy_max}) = f s in {x=min x_min sx_min;y=min y_min sy_min}, {x=max x_max sx_max;y=max y_max sy_max}) ({x=infinity;y=infinity},{x=neg_infinity;y=neg_infinity}) let list_min_max_float f p = List.fold_left (fun (x_min,y_min,x_max,y_max) s -> let (sx_min,sy_min,sx_max,sy_max) = f s in (min x_min sx_min,min y_min sy_min, max x_max sx_max,max y_max sy_max)) (infinity,infinity,neg_infinity,neg_infinity) p let sign f = if f = 0. then 0. else if f < 0. then -1. else 1. let sign { x=x; y = y} = { x = sign x; y = sign y} let norm_infinity default f = if f = infinity || f = neg_infinity then default else f let norm_infinity {x=xdef;y=ydef} {x=x;y=y} = {x= norm_infinity xdef x;y= norm_infinity ydef y} mlpost-0.8.2/concrete/point_lib.mli000066400000000000000000000037451306046515300173370ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type t = Ctypes.point = { x : float; y : float } val zero : t val add : t -> t -> t val sub : t -> t -> t val mult : float -> t -> t val div : t -> float -> t val rotated : float -> t -> t val transform : Ctypes.matrix -> t -> t val swapmx : t -> t val swapmy : t -> t val sign : t -> t val middle : t -> t -> t val norm : t -> float val norm2 : t -> float val dist : t -> t -> float val dist2 : t -> t -> float val list_min_max : ('a -> t * t) -> 'a list -> t * t val list_min_max_float : ('a -> float * float * float * float) -> 'a list -> float * float * float * float val opp : t -> t val print : Format.formatter -> t -> unit module Infix : sig val (+/) : t -> t -> t val (-/) : t -> t -> t val ( */) : float -> t -> t val ( //) : t -> float -> t end val norm_infinity : t -> t -> t val segment : float -> t -> t -> t mlpost-0.8.2/concrete/spline.ml000066400000000000000000000257051306046515300165010ustar00rootroot00000000000000open Point_lib open Point_lib.Infix module P = Point_lib type point = Ctypes.point type abscissa = float type t = { sa : point; sb : point; sc : point; sd : point; } let inter_depth = ref 15 let debug = false let pt_f fmt p = Format.fprintf fmt "{@[ %.20g,@ %.20g @]}" p.x p.y let print fmt pt = Format.fprintf fmt "@[{ %a,@ %a,@ %a,@ %a }@]@." pt_f pt.sa pt_f pt.sb pt_f pt.sc pt_f pt.sd let create a b c d = { sa = a; sb = b; sc = c; sd = d; } let create_with_offset offs a b c d = create a b c d let explode s = s.sa, s.sb, s.sc, s.sd let reverse conv {sa=sa;sb=sb;sc=sc;sd=sd} = {sa=sd;sb=sc;sc=sb;sd=sa} let right_control_point t = t.sc let right_point t = t.sd let left_point t = t.sa let left_control_point t = t.sb let cubic a b c d t = t*.(t*.(t*.(d +. 3.*.(b -. c) -. a) +. 3. *. (c -. (2. *. b) +. a)) +. 3. *. (b -. a)) +. a (* ((t^3)*(d - (3*c) + (3*b) - a)) + (3*(t^2)*(c - (2*b) + a)) + * (3*t*(b - a)) + a*) (* d *. (t**3.) +. 3. *. c *. (t**2.) *. (1. -. t) +. 3. *. b *. (t**1.) * *.(1. -. t)**2. +. a *. (1. -. t)**3.*) let point_of s t = { x=cubic s.sa.x s.sb.x s.sc.x s.sd.x t; y=cubic s.sa.y s.sb.y s.sc.y s.sd.y t;} let point_of_s s t = assert ( 0. <= t && t <= 1.); point_of s t let direction s t = (* An expression as polynomial: short but lots of point operations (d-3*c+3*b-a)*t^2+(2*c-4*b+2*a)*t+b-a *) (* t */ (t */ (s.sd -/ 3. */ (s.sc +/ s.sb) -/ s.sa) +/ 2. */ (s.sc +/ s.sa -/ 2. */ s.sb)) +/ s.sb -/ s.sa *) (* This expression is longer, but has less operations on points: *) (t**2.) */ s.sd +/ (((2. *. t) -. (3. *. (t**2.)))) */ s.sc +/ ((1. -. (4. *. t)+.(3. *. (t**2.)))) */ s.sb +/ (-.((1. -. t)**2.)) */ s.sa let extremum a b c d = let eqa = d -. a +. (3.*.(b -. c)) in let eqb = 2.*.(c +. a -. (2.*.b)) in let eqc = b -. a in (*Format.printf "eqa : %f; eqb : %f; eqc : %f@." eqa eqb eqc;*) let test s l = if s>=0. && s<=1. then s::l else l in if eqa = 0. then if eqb = 0. then [] else test (-. eqc /. eqb) [] else (*let sol delta = (delta -. (2.*.b) +. a +. c)/. (a -. d +. (3.*.(c -. b))) in*) (*let delta = ((b*.b) -. (c*.(b +. a -. c)) +. (d*.(a -. b))) in*) let sol delta = (delta +. eqb) /. (-.2.*.eqa) in let delta = (eqb*.eqb) -. (4.*.eqa*.eqc) in (*Format.printf "delta2 : %f; delta : %f@." delta2 delta;*) match compare delta 0. with | x when x<0 -> [] | 0 -> test (sol 0.) [] | _ -> let delta = delta**0.5 in test (sol delta) (test (sol (-.delta)) []) let remarkable a b c d = let res = 0.::1.::(extremum a b c d) in (*Format.printf "remarquable : %a@." (fun fmt -> List.iter (Format.printf "%f;")) res;*) res let apply_x f s = f s.sa.x s.sb.x s.sc.x s.sd.x let apply_y f s = f s.sa.y s.sb.y s.sc.y s.sd.y let apply4 f s = f s.sa s.sb s.sc s.sd let f4 f a b c d = f (f a b) (f c d) let bounding_box s = let x_max = apply_x (f4 Pervasives.max) s in let y_max = apply_y (f4 Pervasives.max) s in let x_min = apply_x (f4 Pervasives.min) s in let y_min = apply_y (f4 Pervasives.min) s in x_min,y_min,x_max,y_max let precise_bounding_box s = (*Format.printf "precise : %a@." print_spline s;*) let x_remarq = List.map (apply_x cubic s) (apply_x remarkable s) in let y_remarq = List.map (apply_y cubic s) (apply_y remarkable s) in let x_max = List.fold_left Pervasives.max neg_infinity x_remarq in let y_max = List.fold_left Pervasives.max neg_infinity y_remarq in let x_min = List.fold_left Pervasives.min infinity x_remarq in let y_min = List.fold_left Pervasives.min infinity y_remarq in x_min,y_min,x_max,y_max let bisect a = let b = a in (*D\leftarrow (C+D)/2*) let b = {b with sd = middle b.sd b.sc} in (*C\leftarrow (B+C)/2, D\leftarrow (C+D)/2*) let b = {b with sc = middle b.sc b.sb} in let b = {b with sd = middle b.sd b.sc} in (*B\leftarrow (A+B)/2, C\leftarrow (B+C)/2, D\leftarrow(C+D)/2*) let b = {b with sb = middle b.sb b.sa} in let b = {b with sc = middle b.sc b.sb} in let b = {b with sd = middle b.sd b.sc} in let c = a in let c = {c with sa = middle c.sa c.sb} in let c = {c with sb = middle c.sb c.sc} in let c = {c with sa = middle c.sa c.sb} in let c = {c with sc = middle c.sc c.sd} in let c = {c with sb = middle c.sb c.sc} in let c = {c with sa = middle c.sa c.sb} in b,c let test_in amin amax bmin bmax = (amin <= bmax && bmin <= amax) let is_intersect a b = let (ax_min,ay_min,ax_max,ay_max) = bounding_box a in let (bx_min,by_min,bx_max,by_max) = bounding_box b in test_in ax_min ax_max bx_min bx_max && test_in ay_min ay_max by_min by_max let is_intersect_precise a b = let (ax_min,ay_min,ax_max,ay_max) = precise_bounding_box a in let (bx_min,by_min,bx_max,by_max) = precise_bounding_box b in test_in ax_min ax_max bx_min bx_max && test_in ay_min ay_max by_min by_max let intersect_fold f acc a b = let rec aux acc a b t1 t2 dt = function | 0 -> if is_intersect a b then f (t1 + (dt/2), t2 + (dt/2)) acc else acc | n -> if is_intersect a b then let n = n - 1 and dt = dt / 2 in let a1,a2 = bisect a and b1,b2 = bisect b in let acc = aux acc a1 b1 t1 t2 dt n in let acc = aux acc a1 b2 t1 (t2+dt) dt n in let acc = aux acc a2 b1 (t1+dt) t2 dt n in let acc = aux acc a2 b2 (t1+dt) (t2+dt) dt n in acc else acc in let nmax = int_of_float (2.**(float_of_int (!inter_depth+1))) in aux acc a b 0 0 nmax !inter_depth exception Found of int*int let one_intersection a b = let nmax = 2.**(float_of_int (!inter_depth+1)) in let f_from_i x = (float_of_int x)*.(1./.nmax) in try intersect_fold (fun (x,y) () -> raise (Found (x,y))) () a b; raise Not_found with Found (t1,t2) -> f_from_i t1, f_from_i t2 module UF = Unionfind let intersection a b = if a=b then [] else let rem_noise delta mdelta = function | [] -> [] | noisy -> let uf = UF.init noisy in let link sel msel = let sorted = List.fast_sort (fun x y -> compare (sel x) (sel y)) noisy in let rec pass bef = function |[] -> () |e::l -> if sel bef - sel e <= delta then (if abs (msel e - msel bef) <= mdelta then UF.union e bef uf; pass bef l) else () in ignore (List.fold_left (fun acc bef -> pass bef acc;bef::acc) [] sorted) in link fst snd; link snd fst; UF.fold_classes (fun x acc -> x :: acc) [] uf in let nmax = 2.**(float_of_int (!inter_depth+1)) in let l = intersect_fold (fun x acc -> x::acc) [] a b in if debug then Format.printf "@[%a@]@." (fun fmt -> List.iter (fun (f1,f2) -> Format.fprintf fmt "%i,%i" f1 f2) ) l; let l = rem_noise (2 * !inter_depth) (16 * !inter_depth) l in let f_from_i x = x *. (1./.nmax) in let res = List.rev_map (fun (x,y) -> (f_from_i x,f_from_i y)) l in if debug then Format.printf "@[%a@]@." (fun fmt -> List.iter (pt_f fmt)) (List.map (fun (t1,t2) -> (point_of a t1) -/ (point_of b t2)) res); res type split = | Min | Max | InBetween of t * t let split s t = assert (0. <= t && t <= 1.); if t = 1. then Max else if t = 0. then Min else let t0 = (*_01_of_s s*) t in let _1t0 = 1.-.t0 in let b1 = t0 */ s.sb +/ _1t0 */ s.sa in let c1 = (t0 *. t0) */ s.sc +/ (2. *. t0 *. _1t0) */ s.sb +/ (_1t0 *. _1t0) */ s.sa in let d1 = point_of s t0 in let a2 = d1 in let c2 = _1t0 */ s.sc +/ t0 */ s.sd in let b2 = (_1t0*._1t0) */ s.sb +/ (2.*._1t0*.t0) */ s.sc +/ (t0*.t0) */ s.sd in InBetween ({s with sb = b1;sd = d1;sc = c1}, {s with sa = a2;sb = b2;sc = c2}) let norm2 a b = a*.a +. b*.b let is_possible (axmin,aymin,axmax,aymax) (bxmin,bymin,bxmax,bymax) = match axmin > bxmax, aymin > bymax, axmax < bxmin, aymax < bymin with | true , true , _ , _ -> norm2 (axmin -. bxmax) (aymin -. bymax) | _ , _ , true , true -> norm2 (axmax -. bxmin) (aymax -. bymin) | true , _ , _ , true -> norm2 (axmin -. bxmax) (aymax -. bymin) | _ , true , true , _ -> norm2 (axmax -. bxmin) (aymin -. bymax) | false, true , false, _ -> norm2 0. (aymin -. bymax) | false, _ , false, true -> norm2 0. (aymax -. bymin) | true , false, _ , false -> norm2 (axmin -. bxmax) 0. | _ , false, true , false -> norm2 (axmax -. bxmin) 0. | false, false, false, false -> 0. let dist_min_point ({x=px;y=py} as p) s = (* TODO simplify *) let is_possible_at a = is_possible (bounding_box a) (px,py,px,py) in let nmax = 2.**(float_of_int (!inter_depth+1)) in let rec aux a ((min,_) as pmin) t1 dt = function | 0 -> let t1 = float_of_int (t1 + dt/2) /. nmax in let pt1 = point_of s t1 in let dist = P.dist2 pt1 p in if dist < min then (dist, t1) else pmin | n -> let dt = dt/2 in let (af,al) = bisect a in let dist_af = is_possible_at af in let dist_al = is_possible_at al in let doit ((min,_) as pmin) dist am t = if dist < min then aux am pmin t dt (n-1) else pmin in if dist_af let t1 = float_of_int (t1 + dt/2) /. nmax in let t2 = float_of_int (t2 + dt/2) /. nmax in let ap = point_of s1 t1 in let bp = point_of s2 t2 in let dist = norm2 (ap.x -. bp.x) (ap.y -. bp.y) in if dist < min then (dist,(t1,t2)) else pmin | n -> let n = n-1 in let dt = dt/2 in let (af,al) = bisect a in let (bf,bl) = bisect b in let doit dist am bm t1 t2 ((min,_) as pmin) = if dist < min then aux am bm pmin t1 t2 dt n else pmin in let l = [af,bf,t1,t2; af,bl,t1,t2+dt; al,bf,t1+dt,t2;al,bl,t1+dt,t2+dt] in let l = List.map (fun (am,bm,t1,t2) -> let dist = is_possible_at am bm in dist, doit dist am bm t1 t2) l in let l = List.fast_sort (fun (da,_) (db,_) -> compare da db) l in List.fold_left (fun pmin (_,doit) -> doit pmin) pmin l in let pmin = P.dist2 (left_point s1) (left_point s2), (0., 0.) in aux s1 s2 pmin 0 0 (int_of_float nmax) !inter_depth let translate t a = { sa = a.sa +/ t; sb = a.sb +/ t; sc = a.sc +/ t; sd = a.sd +/ t} let transform t a = { sa = P.transform t a.sa; sb = P.transform t a.sb; sc = P.transform t a.sc; sd = P.transform t a.sd } mlpost-0.8.2/concrete/spline.mli000066400000000000000000000061501306046515300166430ustar00rootroot00000000000000type point = Ctypes.point type abscissa = float type t (** The type of Splines *) val inter_depth : int ref (** A mesure to decide how many iterations do to in intersection computations; * higher means more precise *) val debug : bool val print : Format.formatter -> t -> unit val create : point -> point -> point -> point -> t (** [create a b c d] creates a spline with points a and d and control points b and c. By default, the abscissa of the spline starts at [0.] and ends at [1.]. *) val create_with_offset : float -> point -> point -> point -> point -> t (** create a spline with abscissa between [ [f,f+1] ] *) val explode : t -> point * point * point * point (** return the four points of the spline; left point, left control point, second point, second control point*) val left_point : t -> point val left_control_point : t -> point val right_point : t -> point val right_control_point : t -> point (** the four points of a spline *) val reverse : (float -> float) -> t -> t (** reverse a spline, using a conversion function for max and min *) val point_of : t -> abscissa -> point (** compute the location of the given abscissa on a spline *) val point_of_s : t -> abscissa -> point (** compute the location of the given abscissa on a spline, but convert abscissa to [0,1] interval first *) val direction : t -> abscissa -> point (** give the direction (derivative) of the spline at the given abscissa *) val bounding_box : t -> float * float * float * float (** a bounding_box of the given spline *) val precise_bounding_box : t -> float * float * float * float (** a more precise bounding_box of the given spline *) val one_intersection : t -> t -> float * float (** compute a single intersection of the two splines; raise [Not_found] if there is no intersection. *) val intersection : t -> t -> (float * float) list (** compute all intersections of the two splines; raise [Not_found] if there * is no intersection. *) val apply4 : (point -> point -> point -> point -> 'a) -> t -> 'a (** apply a function to the four points of the spline *) type split = | Min | Max | InBetween of t * t (** the type which caracterizes a split of a spline - Min - we have splitted at the left end Max - we have splitted at the right end InBetween (s1,s2) - we have splitted somewhere in between, and the resulting two new splines are [s1] and [s2] *) val split : t -> abscissa -> split (** split a spline at the given abscissa *) val dist_min_point : point -> t -> float * float (** [dist_min_point p s] computes the minimal distance of [p] to [s], as well as the abscissa which corresponds to this minimal distance; the return value is [distance, abscissa]. *) val dist_min_spline : t -> t -> float * (float * float) (** [dist_min_path p1 p2] computes the minimal distance of [p1] to [p2], as well as the two abscissa which correspond to this minimal distance; the return value is [distance, (abscissa_on_p1, abscissa_on_p2)]. *) val translate : point -> t -> t (** translate all points of the spline *) val transform : Matrix.t -> t -> t (** transform all points of the spline *) mlpost-0.8.2/concrete/spline_lib.ml000066400000000000000000000255431306046515300173270ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format exception Not_implemented of string let not_implemented s = raise (Not_implemented s) module Error = struct let max_absc t f = invalid_arg (f^": the abscissa given is greater than max_abscissa : "^ (string_of_float t)) let min_absc ?value f = let value = match value with | None -> "" | Some f -> ": "^(string_of_float f) in invalid_arg (f^": the abscissa given is smaller than min_abscissa"^value) let absc_point f = invalid_arg (f^": a point has only the abscissa 0.") let dir_point f = invalid_arg (f^": a point has no direction.") end module P = Point_lib type point = P.t let id x = x open Point_lib open Point_lib.Infix let rec one_to_one2 f acc a b = List.fold_left (fun acc ea -> List.fold_left (fun acc eb -> f acc ea eb) acc b) acc a let debug = Spline.debug type spline = Spline.t type abscissa = Spline.abscissa type path_ = {pl : spline list; cycle : bool} type path = | Point of point | Path of path_ let is_closed = function | Point _ -> false | Path p -> p.cycle let is_a_point = function | Point p -> Some p | Path _ -> None let rec print_list sep prf fmt = function | [] -> () | [x] -> prf fmt x | (x::xs) -> prf fmt x; sep fmt (); print_list sep prf fmt xs let semicolon fmt () = Format.fprintf fmt ";@ " let print_splines = print_list semicolon Spline.print let print fmt = function | Point p -> fprintf fmt "@[Point %a@]" P.print p | Path p -> fprintf fmt "@[cycle : %b; %a@]" p.cycle print_splines p.pl let create_point p = Point p let create a b c d = Path {pl = [Spline.create a b c d ]; cycle = false} let create_line a d = create a a d d let create_lines = function | [] -> assert false | [a] -> Point a | l -> let rec aux = function | [] |[_]-> [] | a::(d::_ as l) -> Spline.create a a d d :: aux l in Path { pl = aux l; cycle = false } let min_abscissa = function | Path p -> 0. | Point _ -> 0. let length = function | Point _ -> 0 | Path p -> List.length p.pl let max_abscissa p = float (length p) let with_last f p acc = let rec aux = function | [] -> assert false | [e] -> let sd = Spline.right_point e and sc = Spline.right_control_point e in e :: (f sc sd) :: acc | a::l -> a::(aux l) in {p with pl = aux p.pl} let add_end p c d = match p with | Point p -> create p c c d | Path p -> Path (with_last (fun mb a -> Spline.create a (2. */ a -/ mb) c d) p []) let add_end_line p d = match p with | Point p -> create_line p d | Path p -> Path (with_last (fun mb a -> Spline.create a a d d) p []) let add_end_spline p sb sc d = match p with | Point p -> create p sb sc d | Path p -> Path (with_last (fun _ a -> Spline.create a sb sc d) p []) let abscissa_to f pl t = let tn,tf = truncate t, t -. floor t in let rec aux tn l = match tn,l with |_,[] -> Error.max_absc t "abscissa_to" |1,[a] when tf = 0. -> f a 1. |0,a::l -> f a tf |_,_::l -> aux (pred tn) l in if 0. > t then Error.min_absc "abscissa_to" else aux tn pl let abscissa_to_point p0 t = match p0 with | Path p -> abscissa_to Spline.point_of_s p.pl t | Point p when t = 0. -> p | Point _ -> Error.absc_point "abscissa_to_point" let direction_of_abscissa p0 t = match p0 with | Point _ -> Error.dir_point "direction_of_abscissa" | Path p -> abscissa_to Spline.direction p.pl t let unprecise_bounding_box = function | Path s -> let (x_min,y_min,x_max,y_max) = P.list_min_max_float Spline.bounding_box s.pl in ({x=x_min;y=y_min},{x=x_max;y=y_max}) | Point s -> s,s let bounding_box = function | Path s -> let (x_min,y_min,x_max,y_max) = P.list_min_max_float Spline.precise_bounding_box s.pl in ({x=x_min;y=y_min},{x=x_max;y=y_max}) | Point s -> (s,s) exception Found of (float * float) let one_intersection a b = match a,b with | Path a,Path b -> (try one_to_one2 (fun () a b -> try raise (Found (Spline.one_intersection a b)) with Not_found -> ()) () a.pl b.pl; if debug then Format.printf "one_intersection : Not_found@."; raise Not_found with Found a -> a) | _ -> if debug then Format.printf "one_intersection : Not_found not two paths@."; raise Not_found let intersection a b = match a,b with | Path a,Path b -> one_to_one2 (fun acc a b -> acc@(Spline.intersection a b)) [] a.pl b.pl | _ -> [] let fold_left f acc = function | Path p -> List.fold_left (fun acc s -> Spline.apply4 (f acc) s) acc p.pl | Point _ -> acc let iter f = function | Path p -> List.iter (Spline.apply4 f) p.pl | Point _ -> () let union_conv ap bp = let max = max_abscissa ap in let min = min_abscissa bp in let diff = max-.min in (fun x -> x +. diff) let append_conv ap bp = let union_conv = union_conv ap bp in (fun x -> union_conv x +. 1.) let ext_list = function | [] -> assert false | (a::_) as l -> a,l let append ap0 sb sc bp0 = match bp0 with | Path bp -> (* let conv x = append_conv ap0 bp0 x +. 1. in *) (* let l = List.map (fun b -> Spline.set_min_max conv conv b) bp.pl in *) let fbpconv,bpconv = ext_list bp.pl in begin match ap0 with | Path ap -> let spl = with_last (fun _ sa -> Spline.create sa sb sc (Spline.left_point fbpconv)) ap bpconv in Path {spl with cycle = false} | Point p1 -> Path {bp with pl = (Spline.create p1 sb sc (Spline.left_point fbpconv)) ::bp.pl } end | Point p2 -> match ap0 with | Point p1 -> create p1 sb sc p2 | Path p -> add_end_spline ap0 sb sc p2 let reverse x = match x with | Path p as p0 -> let conv = let max = max_abscissa p0 in let min = min_abscissa p0 in let sum = max +. min in (fun x -> sum -. x) in let rec aux acc = function | [] -> acc | a::l -> aux (Spline.reverse conv a :: acc) l in Path {p with pl = aux [] p.pl} | Point _ as p -> p (*left ((t^3)*(d + (3*(b - c)) - a)) + * ((t^2)*(d - (3*b) + (2*a))) + (t*((2*c) - b - a)) + b *) (*right 3*d - c *) let cast_path_to_point p = function | Path {pl=[];} -> Point p | x -> x (* (((t0*tt)^3)*(d + (3*(b - c)) - a)) + (3*((((t0*tt)^2)* (c + a - (2*b))) + (t0*tt*(b - a)))) + a *) let split_aux s t l = match Spline.split s t with | Spline.Min -> [],Path {pl=s::l;cycle=false} | Spline.Max -> let p = cast_path_to_point (Spline.right_point s) (Path {pl=l;cycle=false}) in [s], p | Spline.InBetween (s1,s2) -> [s1], Path {pl = s2 :: l ; cycle = false } let split p0 t = match p0 with | Path p -> let tn,tf = truncate t, t -. floor t in let rec aux tn l = match tn,l with |_,[] -> Error.max_absc t "split" |1,[a] when tf = 0. -> split_aux a 1. l |0,a::l -> split_aux a tf l |_,a::l -> let (p1,p2) = aux (pred tn) l in (a::p1,p2) in if 0. > t then Error.min_absc "split" else let (p1,p2) = aux tn p.pl in cast_path_to_point (Spline.left_point (List.hd p.pl)) (Path {pl=p1;cycle = false}),p2 | Point _ when t = 0. -> p0,p0 | Point _ -> Error.absc_point "split" let subpath p t1 t2 = assert (t1 <= t2); let t2 = if ceil t1 = ceil t2 then (t2 -. t1)/.((ceil t1) -. t1) else t2 -. (floor t1) in (* TODO implement it in a more efficient way *) fst (split (snd (split p t1)) t2) let cut_before a b = (* TODO implement it in a more efficient way *) try let t = (fst (one_intersection b a)) in let res = snd (split b t) in (* Format.printf "t : %f@.point %a@.b : %a@.res : %a@." t P.print (abscissa_to_point b t) print b print res;*) res with Not_found -> b let cut_after a b = (* TODO implement it in a more efficient way *) try let b = reverse b in reverse (snd (split b (fst (one_intersection b a)))) with Not_found -> b let dicho_split x = assert false let dist_min_point p point = match p with | Path p -> begin match p.pl with | [] -> assert false | x::xs -> let m = Spline.dist_min_point point x in List.fold_left (fun ((d1,_) as m1) x -> let ((d2,_) as m2) = Spline.dist_min_point point x in if d1 < d2 then m1 else m2) m xs end | Point p -> P.dist2 p point, 0. let dist_min_path p1 p2 = match p1, p2 with | Path p1, Path p2 -> begin match p1.pl, p2.pl with | [], _ | _, [] -> assert false | x::xs, y :: ys -> let acc = Spline.dist_min_spline x y in one_to_one2 (fun ((d1,_) as m1) a b -> let (d2,_) as m2 = Spline.dist_min_spline a b in if d1 < d2 then m1 else m2) acc xs ys end |Path _ as p1, Point p2 -> let d,a = dist_min_point p1 p2 in d, (a, 0.) |Point p1, (Path _ as p2) -> let d,a = dist_min_point p2 p1 in d, (0., a) |Point p1, Point p2 -> P.dist2 p1 p2, (0.,0.) let translate t p = match p with | Path p -> Path {p with pl=List.map (Spline.translate t) p.pl} | Point p -> Point (p +/ t) let transform t = function | Path p -> Path {p with pl= List.map (Spline.transform t) p.pl} | Point p -> Point (P.transform t p) let buildcycle p1 p2 = not_implemented ("buildcycle") let close = function | Path p1 (* TODO: tester si il est fermé*) -> Path {p1 with cycle = true} | Point _ -> invalid_arg ("This path cannot be closed") let of_bounding_box ({x=x_min;y=y_min},{x=x_max;y=y_max}) = let dl = {x=x_min;y=y_min} in let dr = {x=x_max;y=y_min} in let ul = {x=x_min;y=y_max} in let ur = {x=x_max;y=y_max} in close (create_lines [ul;ur;dr;dl;ul]) mlpost-0.8.2/concrete/spline_lib.mli000066400000000000000000000111111306046515300174620ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type point = Point_lib.t type abscissa = Spline.abscissa type path_ = {pl : Spline.t list; cycle : bool} type path = | Point of point | Path of path_ val is_closed : path -> bool val is_a_point : path -> point option val create : point -> point -> point -> point -> path (** create a b c d return a path with : - point a as the starting point, - point b as its control point, - point d as the ending point, - point c as its control point *) val create_point : point -> path (** create a path consisting of a single point *) val create_line : point -> point -> path (** create a straight line between two points *) val create_lines : point list -> path (** create a path consisting of straight lines connecting the points in argument *) val close : path -> path (** close a path *) val min_abscissa : path -> abscissa val max_abscissa : path -> abscissa val length : path -> int (** number of vertex *) val add_end : path -> point -> point -> path (** add_end p a b return the path p with one more spline at the end.*) val add_end_line : path -> point -> path val add_end_spline : path -> point -> point -> point -> path val append : path -> point -> point -> path -> path val reverse : path -> path (** reverse p return the path p reversed *) (*val union : path -> path -> path (** union p1 p2 return the union of path p1 and p2. [min_abscissa p1;max_abscissa p1] are points of p1, ]max_abscissa p1;max_abscissa p1+max_abscissa p2-min_abscissa p2] are points of p2 *) val union_conv : path -> path -> (abscissa -> abscissa) *) val one_intersection : path -> path -> (abscissa * abscissa) val intersection : path -> path -> (abscissa * abscissa) list (** intersection p1 p2 return a list of pair of abscissa. In each pairs (a1,a2), a1 (resp. a2) is the abscissa in p1 (resp. p2) of one intersection point between p1 and p2. Additionnal point of intersection (two point for only one real intersection) can appear in degenerate case. *) val fold_left : ('a -> point -> point -> point -> point -> 'a) -> 'a -> path -> 'a (** fold on all the splines of a path *) val iter : (point -> point -> point -> point -> unit) -> path -> unit (** iter on all the splines of a path *) val cut_before : path -> path -> path val cut_after : path -> path -> path (** remove the part of a path before the first intersection or after the last*) val split : path -> abscissa -> path * path val subpath : path -> abscissa -> abscissa -> path val direction_of_abscissa : path -> abscissa -> point val abscissa_to_point : path -> abscissa -> point val bounding_box : path -> point * point val unprecise_bounding_box : path -> point * point val dist_min_point : path -> point -> float * abscissa (** [dist_min_point p s] computes the minimal distance of [p] to [s], as well as the abscissa which corresponds to this minimal distance; the return value is [distance, abscissa]. *) val dist_min_path : path -> path -> float * (abscissa * abscissa) (** [dist_min_path p1 p2] computes the minimal distance of [p1] to [p2], as well as the two abscissa which correspond to this minimal distance; the return value is [distance, (abscissa_on_p1, abscissa_on_p2)]. *) val translate : point -> path -> path val transform : Matrix.t -> path -> path val buildcycle : path -> path -> path val of_bounding_box : point * point -> path val print : Format.formatter -> path -> unit val print_splines : Format.formatter -> Spline.t list -> unit mlpost-0.8.2/concrete/unionfind.ml000066400000000000000000000060471306046515300171760ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This is code which has been taken from (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2008 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) and has been modified since then by the Mlpost authors *) module M = struct type t = int * int let equal = Pervasives.(=) let compare = Pervasives.compare let hash = Hashtbl.hash end type elt = float * float type inputelt = M.t module H = Hashtbl.Make(M) type cell = { mutable c : int; mutable data : elt; mutable father : cell } type t = cell H.t (* a forest *) let init l = let h = H.create 997 in List.iter (fun ((a,b) as x) -> let t = float_of_int a, float_of_int b in let rec cell = { c = 1; data = t; father = cell } in H.add h x cell) l; h let rec find_aux cell = if cell.father == cell then cell else let r = find_aux cell.father in cell.father <- r; r let find x h = (find_aux (H.find h x)).data let avg ra rb = let ax,ay = ra.data and bx,by = rb.data in let ac = float_of_int ra.c and bc = float_of_int rb.c in let z = ac +. bc in (ac *. ax +. bc *. bx) /. z, (ac *. ay +. bc *. by) /. z let union x y h = let rx = find_aux (H.find h x) in let ry = find_aux (H.find h y) in if rx != ry then begin if rx.c > ry.c then begin ry.father <- rx; rx.data <- avg rx ry; rx.c <- rx.c + ry.c end else if rx.c < ry.c then begin rx.father <- ry; ry.data <- avg rx ry; ry.c <- rx.c + ry.c end else begin ry.father <- rx; rx.data <- avg rx ry; rx.c <- rx.c + ry.c end end let fold_classes f acc h = let seen = Hashtbl.create 127 in H.fold (fun _ v acc -> let r = find_aux v in let d = r.data in if Hashtbl.mem seen r then acc else (Hashtbl.add seen r () ;f d acc) ) h acc mlpost-0.8.2/concrete/unionfind.mli000066400000000000000000000036371306046515300173510ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This is code which has been taken from *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2008 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* and has been modified since then by the Mlpost authors *) (* Unionfind structure over tuples of ints. Representatives contain the average * of their class, so they are of type float * float *) type elt = float * float type inputelt = int * int type t val init : inputelt list -> t val find : inputelt -> t -> elt val union : inputelt -> inputelt -> t -> unit (* merge two classes and compute new average *) val fold_classes : (elt -> 'a -> 'a) -> 'a -> t -> 'a mlpost-0.8.2/configure.in000066400000000000000000000233721306046515300153620ustar00rootroot00000000000000########################################################################## # # # Copyright (C) Johannes Kanig, Stephane Lescuyer # # Jean-Christophe Filliatre, Romain Bardou and Francois Bobot # # # # This software is free software; you can redistribute it and/or # # modify it under the terms of the GNU Library General Public # # License version 2.1, with the special exception on linking # # described in file LICENSE. # # # # This software 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. # # # ########################################################################## # the script generated by autoconf from this input will set the following # variables: # OCAMLC "ocamlc" if present in the path, or a failure # or "ocamlc.opt" if present with same version number as ocamlc # OCAMLOPT "ocamlopt" (or "ocamlopt.opt" if present), or "no" # OCAMLBEST either "byte" if no native compiler was found, # or "opt" otherwise # OCAMLDEP "ocamldep" # OCAMLLEX "ocamllex" (or "ocamllex.opt" if present) # OCAMLYACC "ocamlyac" # OCAMLLIB the path to the ocaml standard library # OCAMLVERSION the ocaml version number # OCAMLWEB "ocamlweb" (not mandatory) # OCAMLWIN32 "yes"/"no" depending on Sys.os_type = "Win32" # EXE ".exe" if OCAMLWIN32=yes, "" otherwise # The name of the package and its version AC_INIT(mlpost,0.8.2,[],[],[]) # The compilation date TODAY=`date` # Check for Ocaml compilers # we first look for ocamlc in the path; if not present, we fail AC_PATH_PROG(OCAMLC,ocamlc,no) if test "$OCAMLC" = no ; then AC_MSG_ERROR(Cannot find ocamlc.) fi # we extract Ocaml version number and library path OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` echo "ocaml version is $OCAMLVERSION" OCAMLLIB=`$OCAMLC -v | tail -1 | cut -f 4 -d " "` if test "$OCAMLLIB" != ${OCAMLLIB#/usr} -a \ -d /usr/local${OCAMLLIB#/usr}; then OCAMLLIBLOCAL=/usr/local${OCAMLLIB#/usr} echo "ocaml library path is $OCAMLLIB and $OCAMLLIBLOCAL" else echo "ocaml library path is $OCAMLLIB" fi case $OCAMLVERSION in 1.*|2.*|3.*) AC_MSG_ERROR(Mlpost doesn't support OCaml version smaller than 4.0. Aborting.) ;; esac # then we look for ocamlopt; if not present, we issue a warning # if the version is not the same, we also discard it # we set OCAMLBEST to "opt" or "byte", whether ocamlopt is available or not AC_PATH_PROG(OCAMLOPT,ocamlopt,no) OCAMLBEST=byte if test "$OCAMLOPT" = no ; then AC_MSG_WARN(Cannot find ocamlopt; bytecode compilation only.) else AC_MSG_CHECKING(ocamlopt version) TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlopt discarded.) OCAMLOPT=no else AC_MSG_RESULT(ok) OCAMLBEST=opt fi fi # checking for ocamlc.opt AC_PATH_PROG(OCAMLCDOTOPT,ocamlc.opt,no) if test "$OCAMLCDOTOPT" != no ; then AC_MSG_CHECKING(ocamlc.opt version) TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlc.opt discarded.) else AC_MSG_RESULT(ok) OCAMLC=$OCAMLCDOTOPT fi fi # checking for ocamlopt.opt if test "$OCAMLOPT" != no ; then AC_PATH_PROG(OCAMLOPTDOTOPT,ocamlopt.opt,no) if test "$OCAMLOPTDOTOPT" != no ; then AC_MSG_CHECKING(ocamlc.opt version) TMPVER=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVER" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlopt.opt discarded.) else AC_MSG_RESULT(ok) OCAMLOPT=$OCAMLOPTDOTOPT fi fi fi # checking for camlp4o AC_PATH_PROG(CAMLP4O,camlp4o,no) if test "$CAMLP4O" != no ; then AC_MSG_CHECKING(camlp4o version) TMPVER=`$CAMLP4O -version` if test "$TMPVER" != "$OCAMLVERSION" ; then AC_MSG_ERROR(differs from ocamlc; Aborting.) else AC_MSG_RESULT(ok) fi fi # currently commented out because some other part of the code relies on # camlp4o in bytecode #AC_PATH_PROG(CAMLP4ODOTOPT, camlp4o.opt,no) #if test "$CAMLP4ODOTOPT" != no ; then # AC_MSG_CHECKING(camlp4o.opt version) # TMPVER=`$CAMLP4ODOTOPT -version` # if test "$TMPVER" != "$OCAMLVERSION" ; then # AC_MSG_ERROR(differs from ocamlc; Aborting.) # else # AC_MSG_RESULT(ok) # CAMLP4O=$CAMLP4ODOTOPT # fi #fi #checking for ocamldoc AC_PATH_PROG(OCAMLDOC,ocamldoc,no) # ocamldep, ocamllex and ocamlyacc should also be present in the path AC_PATH_PROG(OCAMLDEP,ocamldep,no) if test "$OCAMLDEP" = no ; then AC_MSG_ERROR(Cannot find ocamldep.) fi AC_PATH_PROG(OCAMLLEX,ocamllex,no) if test "$OCAMLLEX" = no ; then AC_MSG_ERROR(Cannot find ocamllex.) else AC_PATH_PROG(OCAMLLEXDOTOPT,ocamllex.opt,no) if test "$OCAMLLEXDOTOPT" != no ; then OCAMLLEX=$OCAMLLEXDOTOPT fi fi AC_PATH_PROG(OCAMLYACC,ocamlyacc,no) if test "$OCAMLYACC" = no ; then AC_MSG_ERROR(Cannot find ocamlyacc.) fi #First check that the versions for ocamlbuild are OK AC_PATH_PROG(OCAMLBUILD, ocamlbuild, no) if test "$OCAMLBUILD" = no; then AC_MSG_ERROR(Cannot find ocamlbuild.) else AC_MSG_RESULT(ok) fi AC_PATH_PROG(OCAMLWEB,ocamlweb,true) # platform AC_MSG_CHECKING(platform) if echo "let _ = Sys.os_type" | ocaml | grep -q Win32; then AC_MSG_RESULT(Win32) OCAMLWIN32=yes EXE=.exe LIBEXT=.lib OBJEXT=.obj else AC_MSG_RESULT(not Win32) OCAMLWIN32=no EXE= LIBEXT=.a OBJEXT=.o fi ## Where are the library we need # we look for ocamlfind; if not present, we just don't use it to find # libraries AC_CHECK_PROG(USEOCAMLFIND,ocamlfind,yes,no) if test "$USEOCAMLFIND" = no; then AC_MSG_ERROR(Cannot find ocamlfind.) fi OCAMLFINDLIB=$(ocamlfind printconf stdlib) OCAMLFIND=$(which ocamlfind) if test "$OCAMLFINDLIB" != "$OCAMLLIB"; then echo "ocamlfind : $OCAMLFINDLIB, ocamlc : $OCAMLLIB" AC_MSG_ERROR(Your ocamlfind is not compatible with your ocamlc.) fi if test "$LIBDIR" = ""; then LIBDIR=$(ocamlfind printconf destdir)/mlpost fi echo "Mlpost library will be installed in: $LIBDIR" AC_ARG_ENABLE(cairo, [ --enable-cairo enable the cairo backend (requires cairo library, implies --enable-concrete)[default=yes]],, enable_cairo=yes) CAIRO=no if test "$enable_cairo" = yes; then # checking for mlcairo CAIROLIB=$(ocamlfind query cairo) if test -n "$CAIROLIB";then echo "ocamlfind found cairo in $CAIROLIB" CAIRO=yes fi fi AC_ARG_ENABLE(concrete, [ --enable-concrete enable concrete computations (requires bitstring library) [default=yes]],, enable_concrete=yes) BITSTRING=no if test "$enable_concrete" = yes; then BITSTRINGLIB=$(ocamlfind query bitstring) if test -n "$BITSTRINGLIB";then echo "ocamlfind found bitstring in $BITSTRINGLIB" BITSTRING=yes fi fi if test "$BITSTRING" = yes; then if test "$CAIRO" = yes; then TAGS="-tags cairo_yes,concrete_yes" INCLUDELIBS="-I $CAIROLIB -I $BITSTRINGLIB" METAREQUIRESPACKAGE="unix cairo bitstring" else CAIRO=no TAGS="-tag concrete_yes" INCLUDELIBS="-I $BITSTRINGLIB" METAREQUIRESPACKAGE="unix bitstring" fi else CAIRO=no BITSTRING=no TAGS="" INCLUDELIBS="" METAREQUIRESPACKAGE="unix" fi #TEMPORAIRE #CAIRO=no #INCLUDELIBS="" AC_ARG_ENABLE(lablgtk, [ --enable-lablgtk enable the cairo backend (requires cairo library, implies --enable-lablgtk)[default=yes]],, enable_lablgtk=yes) LABLGTK2=no if test "$enable_lablgtk" = yes; then # checking for lablgtk2 LABLGTK2LIB=$(ocamlfind query lablgtk2) if test -n "$LABLGTK2LIB";then echo "ocamlfind found lablgtk2 in $LABLGTK2LIB" fi fi if test -n "$LABLGTK2LIB" ; then LABLGTK2=yes INCLUDEGTK2="-I +lablgtk2" else LABLGTK2=no fi # checking for cairo.lablgtk2 CAIROLABLGTK2LIB=$(ocamlfind query cairo.lablgtk2) if test -n "$CAIROLABLGTK2LIB";then echo "ocamlfind found cairo.lablgtk2 in $CAIROLABLGTK2LIB" fi if test -n "$LABLGTK2LIB" ; then CAIROLABLGTK2=yes else CAIROLABLGTK2=no fi #Viewer for ps and pdf AC_CHECK_PROGS(PSVIEWER,gv evince) AC_CHECK_PROGS(PDFVIEWER,xpdf acroread evince) # substitutions to perform AC_SUBST(OCAMLC) AC_SUBST(OCAMLOPT) AC_SUBST(CAMLP4O) AC_SUBST(OCAMLDOC) AC_SUBST(OCAMLDEP) AC_SUBST(OCAMLLEX) AC_SUBST(OCAMLYACC) AC_SUBST(OCAMLBEST) AC_SUBST(OCAMLVERSION) AC_SUBST(OCAMLWEB) AC_SUBST(OCAMLFIND) AC_SUBST(OCAMLBUILD) AC_SUBST(LABLGTK2) AC_SUBST(INCLUDEGTK2) AC_SUBST(LABLGTK2LIB) AC_SUBST(CAIROLABLGTK2) AC_SUBST(CAIROLABLGTK2LIB) AC_SUBST(TAGS) AC_SUBST(CAIROLIB) AC_SUBST(INCLUDELIBS) AC_SUBST(BITSTRINGLIB) AC_SUBST(OCAMLWIN32) AC_SUBST(EXE) AC_SUBST(LIBEXT) AC_SUBST(OBJEXT) AC_SUBST(LIBDIR) AC_SUBST(PACKAGE_VERSION) AC_SUBST(TODAY) AC_SUBST(METAREQUIRESPACKAGE) echo "---------------------------------------------------" echo " Mlpost library will be installed in: $LIBDIR" echo -n " native code compilation: " if test "$OCAMLBEST" == "opt"; then echo "yes"; else echo "no"; fi echo " Support for concrete computations in mlpost: "$BITSTRING echo " Cairo support in mlpost: "$CAIRO echo " Contrib mlpost_lablgtk : "$LABLGTK2 echo "---------------------------------------------------" # Finally create the Makefile from Makefile.in AC_CONFIG_FILES(META version.ml Makefile myocamlbuild.ml) AC_OUTPUT chmod a-w Makefile chmod a-w myocamlbuild.ml chmod a-w META chmod a-w version.ml mlpost-0.8.2/contrib/000077500000000000000000000000001306046515300145025ustar00rootroot00000000000000mlpost-0.8.2/contrib/dot/000077500000000000000000000000001306046515300152705ustar00rootroot00000000000000mlpost-0.8.2/contrib/dot/META000066400000000000000000000002651306046515300157440ustar00rootroot00000000000000description = "Library for Mlpost which use dot to place Box, Picture, ..." version = "0.1" archive(byte) = "mlpost_dot.cma" archive(native) = "mlpost_dot.cmxa" requires = "mlpost" mlpost-0.8.2/contrib/dot/Makefile000066400000000000000000000006211306046515300167270ustar00rootroot00000000000000BUILD=_build # TO suppress OCAMLBUILD=ocamlbuild OCAMLFIND=ocamlfind all : $(OCAMLBUILD) -I $(MLPOST_LIB) -tag dtypes -no-links mlpost_dot.cma mlpost_dot.cmxa mlpost_dot.a dot.cmi -classic-display install : $(OCAMLFIND) remove mlpost_dot $(OCAMLFIND) install mlpost_dot $(BUILD)/mlpost_dot.cma $(BUILD)/mlpost_dot.cmxa $(BUILD)/mlpost_dot.a $(BUILD)/dot.cmi META clean : $(OCAMLBUILD) -cleanmlpost-0.8.2/contrib/dot/_tags000066400000000000000000000000661306046515300163120ustar00rootroot00000000000000<*.cmx> and not : for-pack(Mlpost_dot)mlpost-0.8.2/contrib/dot/dot.ml000066400000000000000000000077611306046515300164230ustar00rootroot00000000000000open Xdot_ast open Mlpost let parse_file f = let f = open_in f in let f = Lexing.from_channel f in let d = Xdot_lexer.main f in d module Pi = Picture let ip (x,y) = (*Format.printf "%i,%i@." x y;*) Point.bpp (x,y) let interp_node (id,pos) = let t = Pi.tex ("mlpost_node"^string_of_int id) in let t = Pi.shift (ip pos) t in t (* http://lists.cairographics.org/archives/cairo/2009-April/016916.html *) open Num open Command module P = Point (* let bezier_of_bspline l = let spline = Array.of_list l in let q0 = P.scale (bp (1./.6.0)) (P.add (P.add spline.(0) (P.scale (bp 4.0) spline.(1))) spline.(2)) in let lastpt = Array.length spline - 3 in let path = ref (MetaPath.start (MetaPath.knotp q0)) in for i = 0 to lastpt-1 do let p1 = spline.(i + 1) in let p2 = spline.(i + 2) in let p3 = spline.(i + 3) in let q1 = P.add (P.scale (bp (4.0/.6.0)) p1) (P.scale (bp (2.0/.6.0)) p2) in let q2 = P.add (P.scale (bp (2.0/.6.0)) p1) (P.scale (bp (4.0/.6.0)) p2) in let q3 = P.scale (bp (1./.6.0)) (P.add (P.add p1 (P.scale (bp 4.0) p2)) p3) in path := MetaPath.concat ~style:(MetaPath.jControls q1 q2) (!path) (MetaPath.knotp q3) done; MetaPath.to_path !path *) let bezier_of_point_list = function | [] -> invalid_arg "Need at least one point" | a::l -> let rec aux acc = function | [] -> acc | [_]|[_;_] -> invalid_arg "not enough point (k*3 +1)" | a::b::c::l -> aux (MetaPath.concat ~style:(MetaPath.jControls a b) acc (MetaPath.knotp c)) l in MetaPath.to_path (aux (MetaPath.start (MetaPath.knotp a)) l) let interp_spline l = let l = List.map ip l in let p = bezier_of_point_list l in p let interp_edge (_,_,path) = interp_spline path open Format let print_nodes fmt l = List.iter (fun (n,w,h) -> fprintf fmt "%s [width=%f,height=%f];@." n (w/.72.) (h/.72.)) l let print_edges fmt l = List.iter (fun (x,y) -> fprintf fmt "%s -> %s;@." x y) l let print_dot fmt rankdir nodes edges = fprintf fmt "@[digraph G {@[ graph [rankdir=%s]; node [label=\"\",shape=\"box\"]; edge [dir=none]; @[%a@] @[%a@] @]}@]" rankdir print_nodes nodes print_edges edges let call_dot orient nodes edges = let rankdir = match orient with | `TB -> "TB" | `LR -> "LR" | `BT -> "BT" | `RL -> "RL" in let ((pin,pout) as p) = Unix.open_process "dot -Txdot" in (*"tee example_in.log | dot -Txdot |tee example_out.log" in*) (*"cat example_out.log" in*) let pout2 = formatter_of_out_channel pout in print_dot pout2 rankdir nodes edges; pp_print_flush pout2 (); flush pout; close_out pout; let pin = Lexing.from_channel pin in let d = Xdot_lexer.main pin in match Unix.close_process p with | Unix.WEXITED 0 -> d | _ -> invalid_arg ("Dot doesn't like this graph") (** User interface *) module Make (B : Signature.Boxlike) = struct type node = { id : int; fig : B.t} type edge = node * node let rec assoc_node n = function | [] -> raise Not_found | a::_ when a.id = n -> a.fig | _::l -> assoc_node n l let mknode = let c = ref (-1) in fun x -> incr c; {id = !c; fig = x} let mkedge s e = (s,e) let mkedges l = l let node_name id = Xdot_lexer.node_name id let place ?(orient:[`TB|`LR|`BT|`RL]=`TB) nodes edges = let nodes2 = List.map (fun n -> node_name n.id, Concrete.float_of_num (B.width n.fig), Concrete.float_of_num (B.height n.fig)) nodes in let edges = List.map (fun (n1,n2) -> (node_name n1.id,node_name n2.id)) edges in let d = call_dot orient nodes2 edges in (*printf "d.nodes : %i@.d.edges : %i" (List.length d.nodes) (List.length d.edges);*) let nodes = List.map (fun (n,p) -> let fig = assoc_node n nodes in B.set_pos (ip p) fig) d.nodes in let edges = List.map interp_edge d.edges in (nodes,(edges:Mlpost.Path.t list)) end mlpost-0.8.2/contrib/dot/dot.mli000066400000000000000000000005001306046515300165540ustar00rootroot00000000000000open Mlpost module Make (B : Signature.Boxlike) : sig type node type edge = node * node val mknode : B.t -> node val mkedge : node -> node -> edge val mkedges : (node * node) list -> edge list val place : ?orient:[`TB|`LR|`BT|`RL] -> node list -> edge list -> B.t list * Path.t list end mlpost-0.8.2/contrib/dot/mlpost_dot.mli000066400000000000000000000016521306046515300201630ustar00rootroot00000000000000(** Place figures, boxes or boxlikes with graphviz *) open Mlpost module Dot : sig module Make (B : Signature.Boxlike) : sig type node type edge = node * node val mknode : B.t -> node (** creates an abstract node from a boxlike *) val place : ?orient:[`TB|`LR|`BT|`RL] -> node list -> edge list -> B.t list * Path.t list (** [place ~orient nodes edges] returns a concrete representation of the abstract directed graph composed by [nodes] linked by [edges]. The concrete representation is composed by the list of all the boxlikes of [nodes] placed by dot and by the list of paths representing the [edges] drawn by dot @param orient specifies the orientation of the graph : - `TB top to bottom (default) - `LR left to right - `BT bottom to top - `RL right to left *) end end mlpost-0.8.2/contrib/dot/mlpost_dot.mlpack000066400000000000000000000000321306046515300206400ustar00rootroot00000000000000Xdot_parser Xdot_lexer Dotmlpost-0.8.2/contrib/dot/xdot_ast.mli000066400000000000000000000006231306046515300176210ustar00rootroot00000000000000type statement = | Graph of (string * string) list | Node of int * (string * string) list | Edge of int * int * (string * string) list type file = statement option list type point = float * float type path = point list type node = int * point type edge = int * int * path type digraph = {bounding_box : point * point; nodes : node list; edges : edge list} mlpost-0.8.2/contrib/dot/xdot_lexer.mll000066400000000000000000000117351306046515300201620ustar00rootroot00000000000000{ open Format open Lexing open Xdot_parser type error = | IllegalCharacter of char | UnterminatedComment | UnterminatedString exception Error of error let report fmt = function | IllegalCharacter c -> fprintf fmt "illegal character %c" c | UnterminatedComment -> fprintf fmt "unterminated comment" | UnterminatedString -> fprintf fmt "unterminated string" (* lexical errors *) let keywords = Hashtbl.create 97 let () = List.iter (fun (x,y) -> Hashtbl.add keywords x y) [ "digraph", DIGRAPH; "graph", GRAPH; ] let newline lexbuf = let pos = lexbuf.lex_curr_p in lexbuf.lex_curr_p <- { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } let string_buf = Buffer.create 1024 let char_for_backslash = function | 'n' -> '\n' | 't' -> '\t' | c -> c } let newline = '\n' let space = [' ' '\t' '\r'] let lalpha = ['a'-'z' '_'] let ualpha = ['A'-'Z'] let alpha = lalpha | ualpha let digit = ['0'-'9'] let ident = alpha (alpha | digit | '\'')* let decimal_literal = ['0'-'9']+ let int = '-'? decimal_literal let float = '-'? decimal_literal ('.' decimal_literal)? rule token = parse | newline { newline lexbuf; token lexbuf } | space+ { token lexbuf } | "mlpost_node" (int as i) {NODE (int_of_string i)} | ident as id { try Hashtbl.find keywords id with Not_found -> IDENT id } | "\"" { STRING (string lexbuf) } | "'" { QUOTE } | "," { COMMA } | "(" { LEFTPAR } | ")" { RIGHTPAR } | ":" { COLON } | ";" { SEMICOLON } | "->" { ARROW } | "<->" { LRARROW } | "." { DOT } | "|" { BAR } | "=" { EQUAL } | "[" { LEFTSQ } | "]" { RIGHTSQ } | "{" { LEFTAC } | "}" { RIGHTAC } | eof { EOF } | _ as c { raise (Error (IllegalCharacter c)) } and pos = parse | newline { newline lexbuf; token lexbuf } | (float as x) {FLOAT (float_of_string x)} | space+ {SPACE} | ',' {COMMA} | eof { EOF } | _ as c { raise (Error (IllegalCharacter c)) } and string = parse | "\"" { let s = Buffer.contents string_buf in Buffer.clear string_buf; s } | "\\" (_ as c) { Buffer.add_char string_buf (char_for_backslash c); string lexbuf } | newline { newline lexbuf; Buffer.add_char string_buf '\n'; string lexbuf } | eof { raise (Error UnterminatedString) } | _ as c { Buffer.add_char string_buf c; string lexbuf } { open Xdot_ast let (*parse_string_with*) ps_with parse s = let lexbuf = Lexing.from_string s in try parse pos lexbuf with Error e -> Format.eprintf "mlpost_dot error (pos,path,bb) : %a@." report e; exit 1 | Parsing.Parse_error -> let pstart = lexeme_start_p lexbuf in let pend = lexeme_end_p lexbuf in Format.eprintf "mlpost_dot(pos) parsing error at line %d, characters %d-%d@." pstart.pos_lnum (pstart.pos_cnum - pstart.pos_bol) (pend.pos_cnum - pend.pos_bol); exit 1 | e -> Format.printf "mlpost_dot error in pos, path or bounding_box : %s@." (Printexc.to_string e); exit 1 let xdot_type digraph = let bounding_box = ref None in let nodes = ref [] in let edges = ref [] in List.iter (function | None -> () | Some Graph l -> begin try bounding_box := Some (ps_with Xdot_parser.bounding_box (List.assoc "bb" l)) with Not_found -> () end | Some Node (i,l) -> begin try let p = ps_with Xdot_parser.pos (List.assoc "pos" l) in nodes := (i,p)::!nodes with Not_found -> () end | Some Edge (i1,i2,l) -> begin try let p = ps_with Xdot_parser.path (List.assoc "pos" l) in edges := (i1,i2,p)::!edges with Not_found -> () end) digraph; let bounding_box = match !bounding_box with | None -> Format.eprintf "Dot doesn't give any bounding box!! Please report to mlpost authors@."; exit 1 | Some bb -> bb in { bounding_box = bounding_box; edges = !edges; nodes = !nodes} let main f = try let digraph = Xdot_parser.file token f in xdot_type digraph with Error e -> Format.eprintf "mlpost_dot error : %a@." report e; exit 1 | Parsing.Parse_error -> let pstart = lexeme_start_p f in let pend = lexeme_end_p f in Format.eprintf "parsing error at line %d, characters %d-%d@." pstart.pos_lnum (pstart.pos_cnum - pstart.pos_bol) (pend.pos_cnum - pend.pos_bol); exit 1 let node_name id = Format.sprintf "mlpost_node%i" id } (* Local Variables: compile-command: "unset LANG; make -C ../.. contrib" End: *) mlpost-0.8.2/contrib/dot/xdot_parser.mly000066400000000000000000000025051306046515300203470ustar00rootroot00000000000000%{ open Xdot_ast open Parsing %} /* Tokens */ %token IDENT %token STRING %token INT %token FLOAT %token NODE /* keywords */ %token DIGRAPH BOUNDINGBOX POS GRAPH /* symbols */ %token ARROW %token BAR %token COLON COMMA SPACE SEMICOLON %token DOT EQUAL %token LEFTPAR LEFTPAR_STAR_RIGHTPAR LEFTSQ %token LRARROW %token QUOTE %token RIGHTPAR RIGHTSQ %token LEFTAC RIGHTAC %token UNDERSCORE %token EOF /* Entry points */ %type file %start file %type path %start path %type bounding_box %start bounding_box %type pos %start pos %% file: | DIGRAPH IDENT LEFTAC statements RIGHTAC EOF { $4 } statements: | {[]} | statement SEMICOLON statements {$1::$3} statement: | IDENT LEFTSQ properties RIGHTSQ {None} | GRAPH LEFTSQ properties RIGHTSQ {Some (Graph $3)} | NODE LEFTSQ properties RIGHTSQ {Some (Node ($1,$3))} | NODE ARROW NODE LEFTSQ properties RIGHTSQ {Some (Edge ($1,$3,$5))} properties: | property {[$1]} | property COMMA properties {$1::$3} property: | IDENT EQUAL STRING {($1,$3)} | IDENT EQUAL IDENT {($1,$3)} pos: | pos_bas EOF {$1} pos_bas: | FLOAT COMMA FLOAT {($1,$3)} path: | pos_bas EOF {[$1]} | pos_bas SPACE path {($1::$3)} bounding_box: | pos_bas COMMA pos_bas {($1,$3)} mlpost-0.8.2/contrib/graphics/000077500000000000000000000000001306046515300163025ustar00rootroot00000000000000mlpost-0.8.2/contrib/graphics/mlpost_graphics.ml000066400000000000000000000053071306046515300220370ustar00rootroot00000000000000open Mlpost module Virtual = struct let num i = Num.px (float i) type t = {mutable x : int; mutable y : int; mutable cmds : Command.t list; mutable color : Color.t; mutable filename : string} let t = {x = 0; y = 0; cmds = []; color = Color.black; filename="mlpost_graphics"} let clear_graph () = t.x <- 0; t.y <- 0; t.cmds <- []; t.color <- Color.black let get_cmds () = Command.seq t.cmds let set_color c = t.color <- c let red = Color.red let blue = Color.blue let green = Color.green let black = Color.black let white = Color.white let moveto x y = t.x <- x; t.y <- y let push c = t.cmds <- c::t.cmds let circle x y r = let circle = Path.scale (num r) Path.fullcircle in let circle = Path.shift (Point.pt (num x,num y)) circle in circle let fill_circle x y r = push (Path.fill ~color:t.color (circle x y r)) let lineto x y = push (Path.draw (Path.pathn [num t.x, num t.y; num x, num y])) let rect x y w h = let rect = Path.unitsquare in (* let rect = Path.shift (Point.pt (Num.bp 0.5,Num.bp 0.5)) rect in *) let rect = Path.yscale (num h) rect in let rect = Path.xscale (num w) rect in let rect = Path.shift (Point.pt (num x,num y)) rect in rect let draw_rect x y w h = push (Path.draw (rect x y w h)) let set_emit f = t.filename <- f let synchronize = at_exit (fun () -> Printf.printf "Dump!!\n%!"; Mps.dump ();Cairost.dump_png ()); let c = ref (-1) in fun () -> incr c; Metapost.emit (t.filename^(string_of_int !c)) (get_cmds ()) let draw_string s = let pic = Picture.tex s in (* TODO escape character *) let pic = Picture.shift (Point.pt (num t.x,num t.y)) pic in push pic end (* Use also Graphics *) module Double = struct include Graphics let clear_graph () = Virtual.clear_graph (); Graphics.clear_graph () let get_cmds = Virtual.get_cmds let set_ratio = Virtual.set_ratio let set_color (c1,c2) = Virtual.set_color c1; Graphics.set_color c2 let red = (Virtual.red,Graphics.red) let green = (Virtual.green,Graphics.green) let blue = (Virtual.blue,Graphics.blue) let black = (Virtual.black,Graphics.black) let white = (Virtual.white,Graphics.white) let moveto x y = Virtual.moveto x y; Graphics.moveto x y let fill_circle x y r = Virtual.fill_circle x y r;Graphics.fill_circle x y r let lineto x y = Virtual.lineto x y; Graphics.lineto x y let draw_rect x y w h = Virtual.draw_rect x y w h; Graphics.draw_rect x y w h let set_emit = Virtual.set_emit let synchronize () = Virtual.synchronize (); Graphics.synchronize () let draw_string s = Virtual.draw_string s;Graphics.draw_string s end mlpost-0.8.2/contrib/graphics/mlpost_graphics.mli000066400000000000000000000136201306046515300222050ustar00rootroot00000000000000(** Library for using Mlpost through standard library graphics API *) (** Subset of the Graphics API signature supported by Mlpost_graphics *) module type Graphics = sig val open_graph : string -> unit val close_graph : unit -> unit val set_window_title : string -> unit val resize_window : int -> int -> val clear_graph : unit -> val size_x : unit -> val size_y : unit -> int type color val rgb : int -> int -> int -> color (** [rgb r g b] returns the integer encoding the color with red component [r], green component [g], and blue component [b]. [r], [g] and [b] are in the range [0..255]. *) val black : color val white : color val red : color val green : color val blue : color val yellow : color val cyan : color val magenta : color val moveto : int -> int -> unit (** Position the current point. *) val rmoveto : int -> int -> unit (** [rmoveto dx dy] translates the current point by the given vector. *) val current_x : unit -> int (** Return the abscissa of the current point. *) val current_y : unit -> int (** Return the ordinate of the current point. *) val current_point : unit -> int * int (** Return the position of the current point. *) val lineto : int -> int -> unit (** Draw a line with endpoints the current point and the given point, and move the current point to the given point. *) val rlineto : int -> int -> unit (** Draw a line with endpoints the current point and the current point translated of the given vector, and move the current point to this point. *) val curveto : int * int -> int * int -> int * int -> unit (** [curveto b c d] draws a cubic Bezier curve starting from the current point to point [d], with control points [b] and [c], and moves the current point to [d]. *) val draw_rect : int -> int -> int -> int -> unit (** [draw_rect x y w h] draws the rectangle with lower left corner at [x,y], width [w] and height [h]. The current point is unchanged. Raise [Invalid_argument] if [w] or [h] is negative. *) val draw_poly_line : (int * int) array -> unit (** [draw_poly_line points] draws the line that joins the points given by the array argument. The array contains the coordinates of the vertices of the polygonal line, which need not be closed. The current point is unchanged. *) val draw_poly : (int * int) array -> unit (** [draw_poly polygon] draws the given polygon. The array contains the coordinates of the vertices of the polygon. The current point is unchanged. *) val draw_segments : (int * int * int * int) array -> unit (** [draw_segments segments] draws the segments given in the array argument. Each segment is specified as a quadruple [(x0, y0, x1, y1)] where [(x0, y0)] and [(x1, y1)] are the coordinates of the end points of the segment. The current point is unchanged. *) val draw_arc : int -> int -> int -> int -> int -> int -> unit (** [draw_arc x y rx ry a1 a2] draws an elliptical arc with center [x,y], horizontal radius [rx], vertical radius [ry], from angle [a1] to angle [a2] (in degrees). The current point is unchanged. Raise [Invalid_argument] if [rx] or [ry] is negative. *) val draw_ellipse : int -> int -> int -> int -> unit (** [draw_ellipse x y rx ry] draws an ellipse with center [x,y], horizontal radius [rx] and vertical radius [ry]. The current point is unchanged. Raise [Invalid_argument] if [rx] or [ry] is negative. *) val draw_circle : int -> int -> int -> unit (** [draw_circle x y r] draws a circle with center [x,y] and radius [r]. The current point is unchanged. Raise [Invalid_argument] if [r] is negative. *) val set_line_width : int -> unit (** Set the width of points and lines drawn with the functions above. Under X Windows, [set_line_width 0] selects a width of 1 pixel and a faster, but less precise drawing algorithm than the one used when [set_line_width 1] is specified. Raise [Invalid_argument] if the argument is negative. *) (** {6 Text drawing} *) val draw_char : char -> unit (** See {!Graphics.draw_string}.*) val draw_string : string -> unit (** Draw a character or a character string with lower left corner at current position. After drawing, the current position is set to the lower right corner of the text drawn. *) val set_font : string -> unit (** Set the font used for drawing text. The interpretation of the argument to [set_font] is implementation-dependent. *) val set_text_size : int -> unit (** Set the character size used for drawing text. The interpretation of the argument to [set_text_size] is implementation-dependent. *) val text_size : string -> int * int (** Return the dimensions of the given text, if it were drawn with the current font and size. *) (** {6 Filling} *) val fill_rect : int -> int -> int -> int -> unit (** [fill_rect x y w h] fills the rectangle with lower left corner at [x,y], width [w] and height [h], with the current color. Raise [Invalid_argument] if [w] or [h] is negative. *) val fill_poly : (int * int) array -> unit (** Fill the given polygon with the current color. The array contains the coordinates of the vertices of the polygon. *) val fill_arc : int -> int -> int -> int -> int -> int -> unit (** Fill an elliptical pie slice with the current color. The parameters are the same as for {!Graphics.draw_arc}. *) val fill_ellipse : int -> int -> int -> int -> unit (** Fill an ellipse with the current color. The parameters are the same as for {!Graphics.draw_ellipse}. *) val fill_circle : int -> int -> int -> unit (** Fill a circle with the current color. The parameters are the same as for {!Graphics.draw_circle}. *) end (** Create only mlpost figures *) module Virtual : Graphics (** Create mlpost figures and call graphics function *) module Double : Graphics mlpost-0.8.2/contrib/lablgtk/000077500000000000000000000000001306046515300161225ustar00rootroot00000000000000mlpost-0.8.2/contrib/lablgtk/META000066400000000000000000000003361306046515300165750ustar00rootroot00000000000000description = "Library for Mlpost to easily display mlpost figures into an x-window" version = "0.1" archive(byte) = "mlpost_lablgtk.cma" archive(native) = "mlpost_lablgtk.cmxa" requires = "mlpost cairo.lablgtk2 lablgtk2" mlpost-0.8.2/contrib/lablgtk/mlpost_lablgtk.ml000066400000000000000000000145541306046515300215030ustar00rootroot00000000000000 (* Lablgtk - Examples *) open StdLabels open Mlpost open Format module P = Picture type auto_aspect = width:Num.t -> height:Num.t -> P.t -> Mlpost.Transform.t let aa_nothing ~width ~height _ = [] let aa_center ~width ~height pic = let p = Point.pt (Num.divf width 2.,Num.divf height 2.) in [Transform.shifted (Point.sub p (P.ctr pic))] let aa_fit_page ~width ~height pic = let swidth = Num.divn width (P.width pic) in let sheight = Num.divn height (P.height pic) in let scale = Num.minn swidth sheight in let t = Transform.scaled scale in t::(aa_center ~width ~height (P.transform [t] pic)) let aa_fit_width ~width ~height pic = let swidth = Num.divn width (P.width pic) in let t = (Transform.scaled swidth) in t::(aa_center ~width ~height (P.transform [t] pic)) let aa_fit_height ~width ~height pic = let sheight = Num.divn height (P.height pic) in let t = (Transform.scaled sheight) in t::(aa_center ~width ~height (P.transform [t] pic)) class mlpost_pic ?width ?height ?packing ?show () = (* Create the drawing area. *) let da = GMisc.drawing_area ?width ?height ?packing ?show () in let drawable = lazy (new GDraw.drawable da#misc#window) in let new_pixmap color width height = let drawable = GDraw.pixmap ~width ~height () in drawable#set_foreground color ; drawable in object (self) inherit GObj.widget da#as_widget val mutable need_update = true (* The mlpost pic. *) val mutable pic = Command.nop method set_pic t = pic <- t; need_update <- true method pic = pic (* For the background color *) val mutable background = `WHITE method background = background method set_background c = background <- c (* For the aspect *) val mutable auto_aspect = aa_nothing method set_auto_aspect x = auto_aspect <- x val mutable show_corner = false method set_show_corner b = show_corner <- b val mutable size = (1,1) method size = size val mutable pm = new_pixmap `WHITE 1 1 val origin = Point.origin method private repaint () = let drawable = Lazy.force drawable in let (width, height) as ssize = drawable#size in size <- ssize; pm <- new_pixmap background width height; (* reset the pixmap *) pm#rectangle ~x:0 ~y:0 ~width ~height ~filled:true (); let w,h = (float_of_int width,float_of_int height) in (* *) let pic = if show_corner then let f x = Point.draw ~color:Color.red (Picture.corner x pic) in Command.seq (pic:: (List.map f [`Center;`Northeast;`Southeast; `Northwest;`Southwest])) else pic in let t = auto_aspect ~width:(Num.pt w) ~height:(Num.pt h) pic in let pic = Picture.transform t pic in let cr = Cairo_lablgtk.create pm#pixmap in Cairost.emit_cairo cr (w,h) pic; need_update<-false (* Repaint the widget. *) method private expose ev = if need_update then self#repaint (); let area = GdkEvent.Expose.area ev in let gwin = da#misc#window in let d = new GDraw.drawable gwin in let x = Gdk.Rectangle.x area and y = Gdk.Rectangle.y area in let width = Gdk.Rectangle.width area and height = Gdk.Rectangle.height area in d#put_pixmap ~x ~y ~xsrc:x ~ysrc:y ~width ~height pm#pixmap initializer ignore (da#event#connect#expose ~callback:(fun ev -> self#expose ev; false)); ignore (da#event#connect#configure ~callback:(fun _ -> need_update <- true; false)); end module Interface = struct type interface = { window : GWindow.window; main_vbox : GPack.box; mutable show : bool; (* The main window is shown *) mutable picda : ((unit -> Command.t) * (mlpost_pic * GWindow.window)) list} let new_interface ?width ?height ?title () = let window = GWindow.window ?width ?height ?title () in let vbox = GPack.vbox ~packing:window#add () in let _ = GMenu.menu_bar ~packing:vbox#pack () in ignore(window#connect#destroy ~callback:GMain.quit); {window = window;main_vbox = vbox; show = false; picda = []} let remove_pic window pic = window.picda <- List.remove_assq pic window.picda let add_pic w ?width ?height ?title ?(show_corner=false) ?(auto_aspect=aa_nothing) pic = let window = GWindow.window ?width ?height ?title () in let mlpost_pic = new mlpost_pic ?width ?height ~packing:window#add () in mlpost_pic#set_pic (pic ()); mlpost_pic#set_auto_aspect auto_aspect; mlpost_pic#set_show_corner show_corner; w.picda <- (pic,(mlpost_pic,window))::w.picda; ignore(window#connect#destroy ~callback:(fun () -> remove_pic w pic)); if w.show then ignore(window#show ()) let refresh w = List.iter (fun (pic,(mlpic,_)) -> begin try mlpic#set_pic (pic ()) with e -> Format.eprintf "Error raised inside picure generation@ :@ %s@." (Printexc.to_string e) end; GtkBase.Widget.queue_draw mlpic#as_widget) w.picda (** Editor window *) let create_option w ~packing ?label l = (match label with | None -> () | Some text -> ignore (GMisc.label ~text ~packing ())); let menu = GMenu.menu () in let optionmenu = GMenu.option_menu ~packing () in optionmenu #set_menu menu; optionmenu #set_history 3; ignore (List.fold_left ~f:(fun group (s,(c:unit -> unit)) -> let c () = c ();refresh w in let menuitem = GMenu.radio_menu_item ?group ~label:s ~packing:menu#append () in ignore(menuitem#connect#toggled c); Some (menuitem#group) ) ~init:None l) let create_option w = create_option w ~packing:w.main_vbox#pack let create_text w ?label first set = (match label with | None -> () | Some text -> ignore (GMisc.label ~text ~packing:w.main_vbox#pack ())); let text = GText.view ~packing:w.main_vbox#pack ~show:true () in text#buffer#set_text first; ignore (text#buffer#connect#changed (fun () -> set (text#buffer#get_text ());refresh w)) let main w = ignore(w.window#show ()); List.iter (fun (_,(_,window)) -> ignore(window#show ())) w.picda; GMain.main () end mlpost-0.8.2/contrib/lablgtk/mlpost_lablgtk.mli000066400000000000000000000057121306046515300216500ustar00rootroot00000000000000(** Use Mlpost figures inside gtk interface. *) open Mlpost type auto_aspect = width:Num.t -> height:Num.t -> Mlpost.Picture.t -> Mlpost.Transform.t val aa_nothing : auto_aspect val aa_center : auto_aspect val aa_fit_page : auto_aspect val aa_fit_width : auto_aspect val aa_fit_height : auto_aspect (** GTK widget which displays an mlpost picture. *) class mlpost_pic : ?width:int -> ?height:int -> ?packing:(GObj.widget -> unit) -> ?show:bool -> unit -> object inherit GObj.widget val obj : Gtk.widget Gtk.obj method pic : Mlpost.Picture.t (** The displayed picture *) method set_pic : Mlpost.Picture.t -> unit (** Sets the picture to display. This function doesn't refresh the widget. *) method background : GDraw.color (** The actual background color *) method set_background : GDraw.color -> unit (** Sets the background color *) method size : int * int (** The size of the drawing area (width,height) *) method set_auto_aspect : auto_aspect -> unit (** define the transformation used to have a good aspect of the picture (centered, ...) *) method set_show_corner : bool -> unit end module Interface : sig (** {1 Abstract lablgtk in order to display Mlpost figures inside a very simple interface} *) type interface (** An interface is composed by one control window and by some display window *) val new_interface : ?width:int -> ?height:int -> ?title:string -> unit -> interface (** create a new interface with an empty control window *) (** {2 Interfaces} *) val create_text : interface -> ?label:string -> string -> (string -> unit) -> unit (** [create_text ~label get set] adds to the control window a text input. [get] is the initial value, [set] is called each times the value of the text input is changed. *) val create_option : interface -> ?label:string -> (string * (unit -> unit)) list -> unit (** [create_option ~label value_list] adds to the control window a radio menu item. [value_list] is a pair of one of the choice and the callback function used when this choice is selected. *) val remove_pic : interface -> (unit -> Mlpost.Command.t) -> unit (** [remove_pic gen_pic] removes a display window created by [add_pic gen_pic] *) (** {2 Required function} *) (** functions needed to see one mlpost picure : *) val add_pic : interface -> ?width:int -> ?height:int -> ?title:string -> ?show_corner:bool -> ?auto_aspect:auto_aspect -> (unit -> Mlpost.Command.t) -> unit (** [add_pic get_pic] add a new display window. [get_pic] is called each times the window must be refreshed. If the value of one of the interfaces is changed, the displayed picure is refreshed.*) val main : interface -> unit (** Start the main loop. During the main loop some texts or options can be added and {!add_pic} can be called *) end mlpost-0.8.2/customdoc/000077500000000000000000000000001306046515300150425ustar00rootroot00000000000000mlpost-0.8.2/customdoc/Makefile000066400000000000000000000000671306046515300165050ustar00rootroot00000000000000img.cmo: img.ml ocamlc -I +ocamldoc -c -dtypes img.ml mlpost-0.8.2/customdoc/_tags000066400000000000000000000001471306046515300160640ustar00rootroot00000000000000 : use_ocamldoc : use_unix, pkg_cairo, pkg_bitstring, use_bigarray, use_libmlpost_ftmlpost-0.8.2/customdoc/all.template000066400000000000000000000003061306046515300173460ustar00rootroot00000000000000\documentclass{article} \usepackage{graphicx} \pagestyle{empty} \begin{document} \includegraphics[scale=3]{all.mps} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: mlpost-0.8.2/customdoc/img.ml000066400000000000000000000015511306046515300161520ustar00rootroot00000000000000class my_gen = object(self) inherit Odoc_html.html (** Return HTML code for the given text of a bar tag. *) method html_of_img t = match t with | [] -> "" | (x::r) -> begin match x with | Odoc_info.Raw s -> Format.sprintf "\"%s\"" s s | _ -> "" end initializer tag_functions <- ("img", self#html_of_img) :: tag_functions end let my_generator = new my_gen let _ = Odoc_args.set_doc_generator (Some my_generator :> Odoc_args.doc_generator option) ; (* we need to deactivate the -html option of ocamldoc, otherwise our generator * is overwritten by the standard html generator. Ocamlbuild gives the -html * option to ocamldoc, so this is really required *) Odoc_args.add_option ("-html", Arg.Unit (fun () -> ()), "") mlpost-0.8.2/customdoc/img_doc.ml000066400000000000000000000101411306046515300167720ustar00rootroot00000000000000open Mlpost open Command open Box open Num module Forms = struct let circle = draw (circle (empty ~height:(bp 5.) ~width:(bp 5.) ())) let rect = draw (rect (empty ~height:(bp 5.) ~width:(bp 5.) ())) let round_rect = draw (round_rect (empty ~height:(bp 5.) ~width:(bp 5.) ())) let ellipse = draw (ellipse (empty ~width:(bp 5.) ())) let patatoid = draw (patatoid (empty ~height:(bp 5.) ~width:(bp 10.) ())) let tex = draw (tex "text") end let brect = Box.rect (empty ~height:(bp 5.) ~width:(bp 5.) ()) module Dirs = struct let dot p = Command.draw ~pen:(Pen.scale (bp 4.) Pen.circle) (Path.pathp [p]) let ctr = seq [ draw brect; dot (ctr brect) ] let north = seq [ draw brect; dot (north brect) ] let south = seq [ draw brect; dot (south brect) ] let west = seq [ draw brect; dot (west brect) ] let east = seq [ draw brect; dot (east brect) ] let north_west = seq [ draw brect; dot (north_west brect) ] let south_west = seq [ draw brect; dot (south_west brect) ] let north_east = seq [ draw brect; dot (north_east brect) ] let south_east = seq [ draw brect; dot (south_east brect) ] end let cpic c = Box.pic ~stroke:None (Picture.make c) module Size = struct open Arrow let head = head_triangle_full let kind = add_foot ~head (add_head ~head (add_line empty)) let dbl_arrow = let ar = Arrow.point_to_point ~kind Point.origin (Point.pt (bp 10.,Num.zero)) in cpic ar let width = Box.draw (Box.vbox [ brect; dbl_arrow; ]) let height = Box.draw (Box.hbox [ Box.rotate 90. dbl_arrow; brect ]) end module Move = struct let fnstex s = Picture.tex (Format.sprintf "{\\footnotesize %s}" s) let shift = let pt = Point.pt (bp 40., bp 25.) in let vec = cpic ( seq [Arrow.point_to_point Point.origin pt; Command.dotlabel ~pos:`Top (fnstex "pt") pt; Command.dotlabel ~pos:`Bot (fnstex "(0,0)") Point.origin; ]) in let b = brect in let b' = Box.shift pt b in let shift = cpic ( seq [Box.draw b; Box.draw b'; Arrow.point_to_point (Box.ctr b) (Box.ctr b')]) in Box.draw (Box.hbox [vec; shift]) let center = let pt = Point.pt (bp 40., bp 25.) in let vec = seq [Arrow.point_to_point Point.origin pt; Command.dotlabel ~pos:`Top (fnstex "pt") pt; ] in let b = brect in let b' = Box.center pt b in seq [vec; Box.draw b; Box.draw b'] end module Align = struct let dist = 20. let p1 = Point.p (-.dist, dist) let p2 = Point.sub Point.origin p1 let mkb s = round_rect (tex s) let a, b , c = let a = mkb "A" and borig = mkb "B" and corig = mkb "C" in let b = shift p1 borig in let c = shift p2 corig in a, b, c let all = [a;b;c] let orig = group all let sidebyside l = let b = group l in let s = hbox ~padding:(Num.bp 50.) [orig; b] in seq [ draw s; Helpers.box_arrow ~sep:(Num.bp 20.) ~within:s ~pen:Pen.circle ~color:Color.red orig b ] let origfig = draw orig let halign = sidebyside (halign Num.zero all) let hplace = sidebyside (hplace all) let hbox = sidebyside (hbox_list all) end let _ = Metapost.emit "circle" Forms.circle let _ = Metapost.emit "rect" Forms.rect let _ = Metapost.emit "round_rect" Forms.round_rect let _ = Metapost.emit "ellipse" Forms.ellipse let _ = Metapost.emit "patatoid" Forms.patatoid let _ = Metapost.emit "tex" Forms.tex let _ = Metapost.emit "ctr" Dirs.ctr let _ = Metapost.emit "north" Dirs.north let _ = Metapost.emit "south" Dirs.south let _ = Metapost.emit "west" Dirs.west let _ = Metapost.emit "east" Dirs.east let _ = Metapost.emit "north_west" Dirs.north_west let _ = Metapost.emit "south_west" Dirs.south_west let _ = Metapost.emit "north_east" Dirs.north_east let _ = Metapost.emit "south_east" Dirs.south_east let _ = Metapost.emit "width" Size.width let _ = Metapost.emit "height" Size.height let _ = Metapost.emit "shift" Move.shift let _ = Metapost.emit "center" Move.center let _ = Metapost.emit "halign" Align.halign let _ = Metapost.emit "hplace" Align.hplace let _ = Metapost.emit "hbox" Align.hbox let () = Mlpost.Metapost.dump "img_doc" mlpost-0.8.2/dash.ml000066400000000000000000000025361306046515300143210ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types type t = Types.dash type on_off = Types.on_off let on = mkOn let off = mkOff let evenly = mkDEvenly let withdots = mkDWithdots let scaled f = mkDScaled f let shifted = mkDShifted let pattern = mkDPattern mlpost-0.8.2/defaults.ml000066400000000000000000000023121306046515300152010ustar00rootroot00000000000000let defaultprelude = "\\documentclass{article}\n" let default_filename_prefix = "" let default_required_files : File.t list = [] let default_t1disasm : string option = None let default_verbosity = false let default_debug = false let mk_ref_default x = let r = ref x in (fun () -> !r), (fun x -> r := x) let get_prelude, set_prelude = mk_ref_default defaultprelude let set_prelude_from_file f = set_prelude (Metapost_tool.read_prelude_from_tex_file f) let get_t1disasm, set_t1disasm = mk_ref_default default_t1disasm let get_filename_prefix, set_filename_prefix = mk_ref_default default_filename_prefix let required_files = ref default_required_files let get_required_files () = ! required_files let set_required_files l = required_files := List.map File.from_string l let append_required_file f = required_files := File.from_string f :: !required_files let get_verbosity, set_verbosity = mk_ref_default default_verbosity let get_debug, set_debug = mk_ref_default default_debug type job = string * Types.commandpic type jobs = job list let figures = Queue.create () let emit s f = let s = get_filename_prefix () ^ s in Queue.add (s, f) figures let emited () = Queue.fold (fun l t -> t :: l) [] figures mlpost-0.8.2/defaults.mli000066400000000000000000000012661306046515300153610ustar00rootroot00000000000000val get_prelude : unit -> string val set_prelude : string -> unit val set_prelude_from_file : string -> unit val get_filename_prefix : unit -> string val set_filename_prefix : string -> unit val set_required_files : string list -> unit val get_required_files : unit -> File.t list val append_required_file : string -> unit val get_t1disasm : unit -> string option val set_t1disasm : string option -> unit val set_verbosity : bool -> unit val get_verbosity : unit -> bool val set_debug : bool -> unit val get_debug : unit -> bool type job = string * Types.commandpic type jobs = job list val figures : job Queue.t val emit : string -> Types.commandpic -> unit val emited : unit -> jobs mlpost-0.8.2/diag.ml000066400000000000000000000115721306046515300143060ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Helpers module Node = struct type t = { box_style : (Box.t -> Box.t) option; id : int; fill : Color.t option; boxed: bool option; x : float; y : float; s : Box.t; } let create = let c = ref min_int in fun style fill boxed x y s -> incr c; { box_style = style; id = !c; fill = fill; boxed = boxed; x = x; y = y; s = s; } let hash n = n.id let equal n1 n2 = n1.id == n2.id end module Hnode = Hashtbl.Make(Node) open Node type node = Node.t let node ?style ?fill ?boxed x y s = Node.create style fill boxed x y s type dir = Up | Down | Left | Right | Angle of float type arrow = { src : node; dst : node; lab : string; line_width : Num.t option; boxed:bool; line_color: Color.t option; fill_color : Color.t option; head : bool; dashed : Types.dash option; pos : Command.position option; outd : dir option; ind : dir option; } type t = { nodes : node list; boxes : Box.t Hnode.t; mutable arrows: arrow list; } let create l = { nodes = l; boxes = Hnode.create 17; arrows = [] } let arrow d ?(lab="") ?line_width ?(boxed=true) ?line_color ?fill_color ?pos ?(head=true) ?dashed ?outd ?ind n1 n2 = d.arrows <- { src = n1; dst = n2; lab = lab; line_width = line_width ; boxed = boxed ; line_color = line_color ; fill_color = fill_color ; head = head; dashed = dashed; pos = pos; outd = outd; ind = ind } :: d.arrows let outdir = function | Up -> Path.vec Point.up | Down -> Path.vec Point.down | Left -> Path.vec Point.left | Right -> Path.vec Point.right | Angle f -> Path.vec (Point.dir f) let indir = function | Up -> Path.vec Point.down | Down -> Path.vec Point.up | Left -> Path.vec Point.right | Right -> Path.vec Point.left | Angle f -> Path.vec (Point.dir f) let outdir = function None -> None | Some x -> Some (outdir x) let indir = function None -> None | Some x -> Some (indir x) type node_style = Box.t -> Box.t let make_box ?fill ?boxed ~style ~scale d n = let p = Point.pt (scale n.x, scale n.y) in let pic = n.s in let b = match n.box_style with | None -> style pic | Some f -> f pic in let b = Box.center p b in let b = match fill with None -> b | Some f -> Box.set_fill f b in let b = match boxed with | None -> b | Some true -> Box.set_stroke Color.black b | Some false -> Box.clear_stroke b in Hnode.add d.boxes n b; b let box_of d = Hnode.find d.boxes let draw_arrow ?stroke ?pen ?dashed d a = let src = box_of d a.src in let dst = box_of d a.dst in match a.line_width with | None -> let ba, bla = if a.head then box_arrow, box_label_arrow else box_line, box_label_line in let color = match a.line_color with | None -> stroke | Some _ as c -> c in if a.lab = "" then ba ?color ?pen ?dashed:a.dashed ?outd:(outdir a.outd) ?ind:(indir a.ind) src dst else bla ?color ?pen ?dashed:a.dashed ?outd:(outdir a.outd) ?ind:(indir a.ind) ?pos:a.pos (Picture.tex a.lab) src dst | Some width -> let path = Box.cpath ?outd:(outdir a.outd) ?ind:(indir a.ind) src dst in let src = Path.point 0. path in let dst = Path.point 1. path in Arrow.draw_thick ~boxed:a.boxed ?line_color:a.line_color ?fill_color:a.fill_color ?outd:(outdir a.outd) ?ind:(indir a.ind) ~width src dst let fortybp x = Num.bp (40. *. x) let defaultbox s = Box.round_rect ~dx:Num.two ~dy:Num.two s let draw ?(scale=fortybp) ?(style=defaultbox) ?boxed ?fill ?stroke ?pen d = let l = List.map (fun n -> let fill = if n.fill <> None then n.fill else fill in let boxed = if n.Node.boxed <> None then n.Node.boxed else boxed in Box.draw (make_box ?fill ?boxed ~style ~scale d n)) d.nodes in Command.seq (l @ List.map (draw_arrow ?stroke ?pen d) d.arrows) mlpost-0.8.2/duplicate.ml000066400000000000000000000071651306046515300153570ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types open Hashcons (* A duplicate analysis - find out the number of times a node is used *) module MetaPath = struct type t = metapath_node hash_consed let equal = (==) let hash x = x.hkey end module Path = struct type t = path_node hash_consed let equal = (==) let hash x = x.hkey end module Picture = struct type t = picture_node hash_consed let equal = (==) let hash x = x.hkey end module MPthM = Hashtbl.Make (MetaPath) module PthM = Hashtbl.Make (Path) module PicM = Hashtbl.Make (Picture) let path_map = PthM.create 257 let picture_map = PicM.create 257 let test_and_incr_path n = try incr (PthM.find path_map n); true with Not_found -> PthM.add path_map n (ref 1); false let test_and_incr_pic n = try incr (PicM.find picture_map n); true with Not_found -> PicM.add picture_map n (ref 1); false let option_count f = function | None -> () | Some x -> f x let rec metapath p = match p.Hashcons.node with | MPAConcat (k,j,p) -> metapath p | MPAAppend (p1,j,p2) -> metapath p1; metapath p2 | MPAKnot k -> () | MPAofPA p -> path p and path' = function | PAofMPA p -> metapath p | MPACycle (_,_,p) -> metapath p | PATransformed (p,_) -> path p | PACutAfter (p1,p2) | PACutBefore (p1,p2) -> path p1; path p2 | PABuildCycle pl -> List.iter path pl | PASub (f1, f2, p) -> path p | PABBox p -> commandpic p | PAUnitSquare | PAQuarterCircle | PAHalfCircle | PAFullCircle -> () and path p = (* Format.printf "%a@." Print.path p; *) if test_and_incr_path p then () else path' p.node and picture' = function | PITransformed (p,_) -> commandpic p | PITex s -> () | PIClip (pic,pth) -> commandpic pic; path pth and picture p = if test_and_incr_pic p then () else picture' p.node and command c = match c.node with | CDraw (p, b) -> path p; brush b | CFill (p, c) -> path p | CDotLabel (pic, _, _) -> commandpic pic | CLabel (pic, _ ,_) -> commandpic pic | CExternalImage _ -> () and brush b = let b = b.Hashcons.node in option_count pen b.pen; option_count dash b.dash and pen p = match p.Hashcons.node with | PenCircle | PenSquare -> () | PenFromPath p -> path p | PenTransformed (p, _) -> pen p and dash d = match d.Hashcons.node with | DEvenly | DWithdots -> () | DScaled (f, d) -> dash d | DShifted (_, d) -> dash d | DPattern l -> List.iter dash_pattern l and dash_pattern _ = () and commandpic p = match p.node with | Picture p -> picture p | Command c -> command c | Seq l -> List.iter commandpic l mlpost-0.8.2/dvi/000077500000000000000000000000001306046515300136245ustar00rootroot00000000000000mlpost-0.8.2/dvi/Makefile000066400000000000000000000002241306046515300152620ustar00rootroot00000000000000OCAMLBUILD := ocamlbuild -cflag "-dtypes" all: $(OCAMLBUILD) dev_save.cmx clean: $(OCAMLBUILD) -clean doc: $(OCAMLBUILD) dvi.docdir/index.html mlpost-0.8.2/dvi/_tags000066400000000000000000000002251306046515300146430ustar00rootroot00000000000000 or : syntax_bitstring or : pkg_bitstring, pkg_bitstring.syntax <*.cmx> : for-pack(Mlpost) : pkg_cairomlpost-0.8.2/dvi/dvi.ml000066400000000000000000000526511306046515300147510ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Dvi_util type preamble = { pre_version : int; pre_num : int32; pre_den : int32; pre_mag : int32; pre_text : string; } type postamble = { last_page : int32; post_num : int32; post_den : int32; post_mag : int32; post_height : int32; post_width : int32; post_stack : int; post_pages : int; } type postpostamble = { postamble_pointer : int32; post_post_version : int; } type command = | SetChar of int32 | SetRule of int32 * int32 | PutChar of int32 | PutRule of int32 * int32 | Push | Pop | Right of int32 | Wdefault | W of int32 | Xdefault | X of int32 | Down of int32 | Ydefault | Y of int32 | Zdefault | Z of int32 | FontNum of int32 | Special of string type page = { counters : int32 array; previous : int32; commands : command list } type fontmap = Dvi_util.font_def Int32Map.t type t = { preamble : preamble; pages : page list; postamble : postamble; postpostamble : postpostamble; font_map : fontmap } (* vf *) type preamble_vf = { pre_vf_version : int; pre_vf_text : string; pre_vf_cs : int32; pre_vf_ds : float; } type char_desc = { char_code : int32; char_tfm : int32; char_commands : command list} type vf = { vf_preamble : preamble_vf; vf_font_map : fontmap; vf_chars_desc : char_desc list} (* *) let fontmap d = d.font_map module Print = struct open Format let preamble fmt p = fprintf fmt "* Preamble :\n"; fprintf fmt "\tversion number = %d\n" p.pre_version; fprintf fmt "\tnumerator/denominator = %ld/%ld\n" p.pre_num p.pre_den; fprintf fmt "\tmagnification = %ld\n" p.pre_mag; fprintf fmt "\tcomment : %s\n" p.pre_text let fonts fmt fonts = fprintf fmt "* Fonts defined in this file :\n"; Int32Map.iter (fun k f -> Print_font.font k fmt f) fonts let postamble fmt p = fprintf fmt "* Postamble :\n"; fprintf fmt "\tlast page = %ld\n" p.last_page; fprintf fmt "\tnumerator/denominator = %ld/%ld\n" p.post_num p.post_den; fprintf fmt "\tmagnification = %ld\n" p.post_mag; fprintf fmt "\theight - width = %ld - %ld\n" p.post_height p.post_width; fprintf fmt "\tmaximum stack depth = %d\n" p.post_stack; fprintf fmt "\ttotal # of pages = %d\n" p.post_pages let postpostamble fmt p = fprintf fmt "* Postpostamble :\n"; fprintf fmt "\tPostamble can be found at %ld.\n" p.postamble_pointer; fprintf fmt "\tDVI version : %d\n" p.post_post_version let commands fmt = function | SetChar c -> Format.fprintf fmt "Setting character %ld.@\n" c | SetRule(a, b) -> Format.fprintf fmt "Setting rule (w=%ld, h=%ld).@\n" a b | PutChar c -> Format.fprintf fmt "Putting character %ld.@\n" c | PutRule(a, b) -> Format.fprintf fmt "Putting rule (w=%ld, h=%ld).@\n" a b | Push -> Format.fprintf fmt "Push current state.@\n" | Pop -> Format.fprintf fmt "Pop current state.@\n" | Right b -> Format.fprintf fmt "Moving right %ld.@\n" b | Wdefault -> Format.fprintf fmt "Moving right by the default W.@\n" | W b -> Format.fprintf fmt "Moving right and changing W to %ld.@\n" b | Xdefault -> Format.fprintf fmt "Moving right by the default X.@\n" | X b -> Format.fprintf fmt "Moving right and changing X to %ld.@\n" b | Down a -> Format.fprintf fmt "Moving down %ld.@\n" a | Ydefault -> Format.fprintf fmt "Moving down by the default Y.@\n" | Y a -> Format.fprintf fmt "Moving down and changing Y to %ld.@\n" a | Zdefault -> Format.fprintf fmt "Moving down by the default Z.@\n" | Z a -> Format.fprintf fmt "Moving down and changing Z to %ld.@\n" a | FontNum f -> Format.fprintf fmt "Font is now set to %ld@\n" f | Special xxx -> Format.fprintf fmt "Special command : %s@\n" xxx let print_chars fmt c = Format.fprintf fmt "@[%ld : %a@]@\n" c.char_code (Misc.print_list Misc.newline commands) c.char_commands let print_chars_desc = (Misc.print_list Misc.newline print_chars) let print_vf fmt vf = Format.fprintf fmt "cs=%ld ds=%f %s@\n%a@\n%a@\n" vf.vf_preamble.pre_vf_cs vf.vf_preamble.pre_vf_ds vf.vf_preamble.pre_vf_text fonts vf.vf_font_map print_chars_desc vf.vf_chars_desc let page verbose fmt {counters = c; previous = prev; commands = cmds} = fprintf fmt "* Page number :"; Array.iter (fun c -> fprintf fmt "%ld;" c) c; fprintf fmt "\n"; fprintf fmt "\tPrevious page can be found at %ld\n" prev; if verbose then Misc.print_list Misc.newline commands fmt cmds else fprintf fmt "\t" let pages verbose fmt = List.iter (fun p -> fprintf fmt "%a\n" (page verbose) p) let page_verb = page true let pages_verb = pages true let page = page false let pages = pages false let doc name fmt doc = fprintf fmt "***********************\n"; fprintf fmt "Reading DVI file : %s\n" name; fprintf fmt "%a%a%a%a%a" preamble doc.preamble pages doc.pages fonts doc.font_map postamble doc.postamble postpostamble doc.postpostamble end exception DviError of string ;; let dvi_error s = raise (DviError s) let preamble bits = bitmatch bits with | { 247 : 8; (* Preamble opcode *) version : 8; (* DVI version *) num : 32 : bigendian; (* numerator *) den : 32 : bigendian; (* denominator *) mag : 32 : bigendian; (* magnification *) k : 8; (* size of string x *) x : 8*k : string; (* file comment *) bits : -1 : bitstring } -> { pre_version = version; pre_num = num; pre_den = den; pre_mag = mag; pre_text = x }, bits | { _ : -1 : bitstring } -> dvi_error "Ill-formed preamble" let add_font k font map = if Int32Map.mem k map then dvi_error "Redefinition of font not allowed" else Int32Map.add k font map let font_def bits = bitmatch bits with | { checksum : 32 : bigendian; (* checksum of the TMF file *) scale_factor : 32 : bigendian; (* scale factor *) design_size : 32 : bigendian; (* design size *) a : 8; (* size of the area *) l : 8; (* size of the filename *) name : (a+l)*8 : string; (* the full name w/ area *) bits : -1 : bitstring } -> mk_font_def ~checksum ~scale_factor ~design_size ~area:(String.sub name 0 a) ~name:(String.sub name a l), bits | { _ : -1 : bitstring } -> dvi_error "Ill_formed font definition" let page_counters bits = bitmatch bits with | { c0 : 32 : bigendian; c1 : 32 : bigendian; c2 : 32 : bigendian; c3 : 32 : bigendian; c4 : 32 : bigendian; c5 : 32 : bigendian; c6 : 32 : bigendian; c7 : 32 : bigendian; c8 : 32 : bigendian; c9 : 32 : bigendian; prev : 32 : bigendian; bits : -1 : bitstring } -> [| c0; c1; c2; c3; c4; c5; c6; c7; c8; c9 |], prev, bits | { _ : -1 : bitstring } -> dvi_error "Ill-formed counters after bop" let signed i j unsigned = if Int32.zero = Int32.logand unsigned i then unsigned else Int32.logor unsigned j let signed_8 = signed (Int32.shift_left Int32.one 23) (Int32.logxor Int32.minus_one (Int32.of_int 0xff)) let signed_16 = signed (Int32.shift_left Int32.one 15) (Int32.logxor Int32.minus_one (Int32.of_int 0xffff)) let signed_24 = signed (Int32.shift_left Int32.one 23) (Int32.logxor Int32.minus_one (Int32.of_int 0xffffff)) let command bits = bitmatch bits with (* Setting Characters *) | { k : 8 ; bits : -1 : bitstring } when 0 <= k && k <= 127 -> SetChar (Int32.of_int k), bits | { 128 : 8; k : 8; bits : -1 : bitstring } -> SetChar (Int32.of_int k), bits | { 129 : 8; k : 16; bits : -1 : bitstring } -> SetChar (Int32.of_int k), bits | { 130 : 8; k : 24; bits : -1 : bitstring } -> SetChar (Int32.of_int k), bits | { 131 : 8; k : 32; bits : -1 : bitstring } -> SetChar k, bits (* Setting a Rule *) | { 132 : 8; a : 32; b: 32; bits : -1 : bitstring } -> SetRule(a, b), bits (* Putting Characters *) | { 133 : 8; k : 8; bits : -1 : bitstring } -> PutChar (Int32.of_int k), bits | { 134 : 8; k : 16; bits : -1 : bitstring } -> PutChar (Int32.of_int k), bits | { 135 : 8; k : 24; bits : -1 : bitstring } -> PutChar (Int32.of_int k), bits | { 136 : 8; k : 32; bits : -1 : bitstring } -> PutChar k, bits (* Putting a Rule *) | { 137 : 8; a : 32; b: 32; bits : -1 : bitstring } -> PutRule(a, b), bits (* Stack operations *) | { 141 : 8; bits : -1 : bitstring } -> Push, bits | { 142 : 8; bits : -1 : bitstring } -> Pop, bits (* Moving to the right *) (* Must be signed but bitstring 2.0.0 fails*) | { 143 : 8; b : 8 ; bits : -1 : bitstring } -> Right (signed_8 (Int32.of_int b)), bits | { 144 : 8; b : 16 ; bits : -1 : bitstring } -> Right (signed_16 (Int32.of_int b)), bits | { 145 : 8; b : 24 ; bits : -1 : bitstring } -> Right (signed_24 (Int32.of_int b)), bits | { 146 : 8; b : 32 ; bits : -1 : bitstring } -> Right b, bits (* Moving/spacing to the right w *) | { 147 : 8; bits : -1 : bitstring } -> Wdefault, bits | { 148 : 8; b : 8; bits : -1 : bitstring } -> W (signed_8 (Int32.of_int b)), bits | { 149 : 8; b : 16; bits : -1 : bitstring } -> W (signed_16 (Int32.of_int b)), bits | { 150 : 8; b : 24; bits : -1 : bitstring } -> W (signed_24 (Int32.of_int b)), bits | { 151 : 8; b : 32; bits : -1 : bitstring } -> W b, bits (* Moving/spacing to the right x *) | { 152 : 8; bits : -1 : bitstring } -> Xdefault, bits | { 153 : 8; b : 8; bits : -1 : bitstring } -> X (signed_8 (Int32.of_int b)), bits | { 154 : 8; b : 16; bits : -1 : bitstring } -> X (signed_16 (Int32.of_int b)), bits | { 155 : 8; b : 24; bits : -1 : bitstring } -> X (signed_24 (Int32.of_int b)), bits | { 156 : 8; b : 32; bits : -1 : bitstring } -> X b, bits (* Moving down *) | { 157 : 8; a : 8; bits : -1 : bitstring } -> Down (signed_8 (Int32.of_int a)), bits | { 158 : 8; a : 16; bits : -1 : bitstring } -> Down (signed_16 (Int32.of_int a)), bits | { 159 : 8; a : 24; bits : -1 : bitstring } -> Down (signed_24 (Int32.of_int a)), bits | { 160 : 8; a : 32; bits : -1 : bitstring } -> Down a, bits (* Moving/spacing down y *) | { 161 : 8; bits : -1 : bitstring } -> Ydefault, bits | { 162 : 8; a : 8; bits : -1 : bitstring } -> Y (signed_8 (Int32.of_int a)), bits | { 163 : 8; a : 16; bits : -1 : bitstring } -> Y (signed_16 (Int32.of_int a)), bits | { 164 : 8; a : 24; bits : -1 : bitstring } -> Y (signed_24 (Int32.of_int a)), bits | { 165 : 8; a : 32; bits : -1 : bitstring } -> Y a, bits (* Moving/spacing down z *) | { 166 : 8; bits : -1 : bitstring } -> Zdefault, bits | { 167 : 8; a : 8; bits : -1 : bitstring } -> Z (signed_8 (Int32.of_int a)), bits | { 168 : 8; a : 16; bits : -1 : bitstring } -> Z (signed_16 (Int32.of_int a)), bits | { 169 : 8; a : 24; bits : -1 : bitstring } -> Z (signed_24 (Int32.of_int a)), bits | { 170 : 8; a : 32; bits : -1 : bitstring } -> Z a, bits (* Setting Fonts *) | { k : 8 ; bits : -1 : bitstring } when 171 <= k && k <= 234 -> FontNum (Int32.of_int (k-171)), bits | { 235 : 8; k : 8; bits : -1 : bitstring } -> FontNum (Int32.of_int k), bits | { 236 : 8; k : 16; bits : -1 : bitstring } -> FontNum (Int32.of_int k), bits | { 237 : 8; k : 24; bits : -1 : bitstring } -> FontNum (Int32.of_int k), bits | { 238 : 8; k : 32; bits : -1 : bitstring } -> FontNum k, bits (* Special Commands *) | { 239 : 8; k : 8; x : k * 8 : string; bits : -1 : bitstring } -> Special x, bits | { 240 : 8; k : 16; x : k * 8 : string; bits : -1 : bitstring } -> Special x, bits | { 241 : 8; k : 24; x : k * 8 : string; bits : -1 : bitstring } -> Special x, bits | { 242 : 8; k : 32; x : (Int32.to_int k) * 8 : string; bits : -1 : bitstring } -> Special x, bits | { _ : -1 : bitstring } -> dvi_error "bad command !" let rec page commands fonts bits = bitmatch bits with | { 140 : 8; bits : -1 : bitstring } -> (* End of page opcode *) commands, fonts, bits (* nop opcode *) | { 138 : 8; bits : -1 : bitstring } -> page commands fonts bits (* font definitions *) | { 243 : 8; k : 8; bits : -1 : bitstring } -> let font, bits = font_def bits in page commands (add_font (Int32.of_int k) font fonts) bits | { 244 : 8; k : 16 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in page commands (add_font (Int32.of_int k) font fonts) bits | { 245 : 8; k : 24 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in page commands (add_font (Int32.of_int k) font fonts) bits | { 246 : 8; k : 32 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in page commands (add_font k font fonts) bits (* normal command *) | { bits : -1 : bitstring } -> let cmd, bits = command bits in page (cmd::commands) fonts bits let page = page [] let rec pages p fonts bits = bitmatch bits with (* nop opcode *) | { 138 : 8; bits : -1 : bitstring } -> pages p fonts bits (* font definitions *) | { 243 : 8; k : 8; bits : -1 : bitstring } -> let font, bits = font_def bits in pages p (add_font (Int32.of_int k) font fonts) bits | { 244 : 8; k : 16 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in pages p (add_font (Int32.of_int k) font fonts) bits | { 245 : 8; k : 24 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in pages p (add_font (Int32.of_int k) font fonts) bits | { 246 : 8; k : 32 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in pages p (add_font k font fonts) bits (* begin page opcode *) | { 139 : 8; bits : -1 : bitstring } -> let counters, previous, bits = page_counters bits in let cmds, fonts, bits = page fonts bits in let newp = {counters = counters; previous = previous; commands = List.rev cmds} in (* Pages in reverse order *) pages (newp::p) fonts bits | { bits : -1 : bitstring } -> p, fonts, bits (* dvi_error "Expected : nop, font_definition, or new page" *) let read_pages = pages [] let postamble bits = let rec skip_font_defs bits = bitmatch bits with (* nop opcode *) | { 138 : 8; bits : -1 : bitstring } -> skip_font_defs bits (* font definitions *) | { 243 : 8; k : 8; bits : -1 : bitstring } -> let _, bits = font_def bits in skip_font_defs bits | { 244 : 8; k : 16 : bigendian; bits : -1 : bitstring } -> let _, bits = font_def bits in skip_font_defs bits | { 245 : 8; k : 24 : bigendian; bits : -1 : bitstring } -> let _, bits = font_def bits in skip_font_defs bits | { 246 : 8; k : 32 : bigendian; bits : -1 : bitstring } -> let _, bits = font_def bits in skip_font_defs bits | { bits : -1 : bitstring } -> bits in bitmatch bits with | { 248 : 8; (* Postamble opcode *) last_page : 32 : bigendian; (* DVI version *) num : 32 : bigendian; (* numerator *) den : 32 : bigendian; (* denominator *) mag : 32 : bigendian; (* magnification *) height : 32 : bigendian; (* tallest page *) width : 32 : bigendian; (* widest page *) stack : 16 : bigendian; (* stack depth *) pages : 16 : bigendian; (* number of pages *) bits : -1 : bitstring } -> { last_page = last_page; post_num = num; post_den = den; post_mag = mag; post_height = height; post_width = width; post_stack = stack; post_pages = pages }, skip_font_defs bits | { _ : -1 : bitstring } -> dvi_error "Ill-formed postamble" let postpostamble bits = let rec read_223 bits = bitmatch bits with | { 223 : 8; rest : -1 : bitstring } -> read_223 rest | { rest : -1 : bitstring } -> if Bitstring.bitstring_length rest = 0 then () else dvi_error "Ill-formed suffix : only 223 expected." in bitmatch bits with | { 249 : 8; postamble_pointer : 32 : bigendian; version : 8; rest : -1 : bitstring } -> read_223 rest; { postamble_pointer = postamble_pointer; post_post_version = version } | { _ : -1 : bitstring } -> dvi_error "ill-formed postpostamble" let read_file file = let bits = Bitstring.bitstring_of_file file in let preamble, bits = preamble bits in let pages, fonts, bits = read_pages Int32Map.empty bits in let postamble, bits = postamble bits in let postpostamble = postpostamble bits in { preamble = preamble; pages = List.rev pages; postamble = postamble; postpostamble = postpostamble; font_map = fonts } let vf_preamble bits = bitmatch bits with | { 247 : 8; (* Preamble opcode *) version : 8; (* VF version *) k : 8; (* size of string x *) x : 8*k : string; (* file comment *) cs : 32 : bigendian; (* denominator *) ds : 32 : bigendian; (* magnification *) bits : -1 : bitstring } -> { pre_vf_version = version; pre_vf_text = x; pre_vf_cs = cs; pre_vf_ds = (Int32.to_float ds) /. (2.**20.) }, bits | { _ : -1 : bitstring } -> dvi_error "Ill-formed preamble" (* Could factor the code with the one of page?*) let rec preamble_fonts fonts bits = bitmatch bits with (* font definitions *) | { 243 : 8; k : 8; bits : -1 : bitstring } -> let font, bits = font_def bits in preamble_fonts (add_font (Int32.of_int k) font fonts) bits | { 244 : 8; k : 16 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in preamble_fonts (add_font (Int32.of_int k) font fonts) bits | { 245 : 8; k : 24 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in preamble_fonts (add_font (Int32.of_int k) font fonts) bits | { 246 : 8; k : 32 : bigendian; bits : -1 : bitstring } -> let font, bits = font_def bits in preamble_fonts (add_font k font fonts) bits | { bits : -1 : bitstring } -> fonts,bits let rec command_list cmds bits = if Bitstring.bitstring_length bits = 0 then cmds else let cmd,bits = command bits in command_list (cmd::cmds) bits let rec vf_chars chars bits = bitmatch bits with | {248 : 8} -> chars | {242 : 8; pl : 32; cc : 32; tfm : 32; _ : (Int32.to_int pl)*8 : bitstring; bits : -1 : bitstring } -> let char = { char_code = cc; char_tfm = tfm; char_commands = []} in vf_chars (char::chars) bits | {pl : 8; cc : 8; tfm : 24; coms : pl*8 : bitstring; bits : -1 : bitstring } -> let coms = List.rev (command_list [] coms) in let char = { char_code = Int32.of_int cc; char_tfm = Int32.of_int tfm; char_commands = coms} in vf_chars (char::chars) bits | {i : 8} -> dvi_error "vf : ill-formed character" let print_vf = Print.print_vf let read_vf_file file = let bits = Bitstring.bitstring_of_file file in let preamble, bits = vf_preamble bits in let fonts, bits = preamble_fonts Int32Map.empty bits in let chars_desc = List.rev (vf_chars [] bits) in {vf_preamble = preamble; vf_font_map = fonts; vf_chars_desc = chars_desc} let get_conv_from_preamble p = let formule_magique_cm mag num den = ((Int32.to_float mag) *. ((Int32.to_float num) /. (Int32.to_float den))) /. (10.**8.) in formule_magique_cm p.pre_mag p.pre_num p.pre_den let get_conv doc = get_conv_from_preamble doc.preamble let get_height_cm doc = (get_conv doc) *. (Int32.to_float doc.postamble.post_height) let get_width_cm doc = (get_conv doc) *. (Int32.to_float doc.postamble.post_width) let pages d = d.pages let commands p = p.commands module Incremental = struct type t = { mutable fonts : fontmap; mutable preamble : preamble; chan : in_channel; mutable bits : string * int * int; } let mk_t c = let bits = Bitstring.bitstring_of_chan c in let preamble, bits = preamble bits in let pgs, fonts, bits = read_pages Int32Map.empty bits in { fonts = fonts ; preamble = preamble ; bits = bits; chan = c }, pgs let next_pages t = let nextbits = Bitstring.bitstring_of_chan t.chan in let pgs, fonts, bits = read_pages t.fonts (Bitstring.concat [t.bits; nextbits]) in t.fonts <- fonts; t.bits <- bits; pgs let get_conv i = get_conv_from_preamble i.preamble let font_map i = i.fonts end mlpost-0.8.2/dvi/dvi.mli000066400000000000000000000051311306046515300151110ustar00rootroot00000000000000(** Low-level DVI interface *) (** The DVI preamble *) type preamble = { pre_version : int; pre_num : int32; pre_den : int32; pre_mag : int32; pre_text : string; } (** The DVI postamble *) type postamble = { last_page : int32; post_num : int32; post_den : int32; post_mag : int32; post_height : int32; post_width : int32; post_stack : int; post_pages : int; } (** The DVI postpostamble *) type postpostamble = { postamble_pointer : int32; post_post_version : int; } (** The type of commands. All coordinates in this type are relative to the current state of the DVI document. *) type command = | SetChar of int32 | SetRule of int32 * int32 | PutChar of int32 | PutRule of int32 * int32 | Push | Pop | Right of int32 | Wdefault | W of int32 | Xdefault | X of int32 | Down of int32 | Ydefault | Y of int32 | Zdefault | Z of int32 | FontNum of int32 | Special of string (** A page is a list of commands *) type page = { counters : int32 array; previous : int32; commands : command list } type fontmap = Dvi_util.font_def Dvi_util.Int32Map.t (** A document is a list of pages, plus a preamble, postamble, postpostamble and font map *) type t = { preamble : preamble; pages : page list; postamble : postamble; postpostamble : postpostamble; font_map : fontmap } (** a few accessor functions *) val get_conv : t -> float val fontmap : t -> fontmap val commands : page -> command list val pages : t -> page list val read_file : string -> t val get_height_cm : t -> float val get_width_cm : t -> float (** Vf files *) (* Vf type *) type preamble_vf = { pre_vf_version : int; pre_vf_text : string; pre_vf_cs : int32; pre_vf_ds : float; } type char_desc = { char_code : int32; char_tfm : int32; char_commands : command list} type vf = { vf_preamble : preamble_vf; vf_font_map : fontmap; vf_chars_desc : char_desc list} val print_vf : Format.formatter -> vf -> unit val read_vf_file : string -> vf module Incremental : sig (** Useful to read a DVI file page per page *) type t (** The type that stores information regarding the DVI file *) (* val mk_t : in_channel -> t *) val mk_t : in_channel -> t * page list val next_pages : t -> page list (** read all available pages *) val get_conv : t -> float val font_map : t -> fontmap end module Print : sig val page : Format.formatter -> page -> unit val pages : Format.formatter -> page list -> unit val page_verb : Format.formatter -> page -> unit val pages_verb : Format.formatter -> page list -> unit end mlpost-0.8.2/dvi/dvi.odocl000066400000000000000000000000501306046515300154230ustar00rootroot00000000000000Dvi Dviinterp Dev_save Fonts Metric Tfm mlpost-0.8.2/dvi/dvi_util.ml000066400000000000000000000023441306046515300160000ustar00rootroot00000000000000 module Int32 = struct include Int32 let hash = to_int let equal x y = compare x y = 0 end module Int32Map = Map.Make(Int32) module Int32H = Hashtbl.Make(Int32) type font_def = { checksum : int32; scale_factor : int32; design_size : int32; area : string; name : string; } let mk_font_def ~checksum ~scale_factor ~design_size ~area ~name = { checksum = checksum ; scale_factor = scale_factor ; design_size = design_size ; area = area ; name = name } module Print_font = struct open Format let print_option pr ff = function |None -> fprintf ff "None" |Some a -> pr ff a let font_map ff font = fprintf ff "Tex:%s Human:%s Slant:%a Extend:%a Enc:%a Pfab:%s@." font.Fonts_type.tex_name font.Fonts_type.human_name (print_option pp_print_float) font.Fonts_type.slant (print_option pp_print_float) font.Fonts_type.extend (print_option pp_print_string) font.Fonts_type.enc_name font.Fonts_type.pfab_name let font k fmt f = fprintf fmt "\tFont number %ld (%s in directory [%s]) :\n" k f.name f.area; fprintf fmt "\t Checksum = %lx\n" f.checksum; fprintf fmt "\t Scale factor / Design size : %ld / %ld\n" f.scale_factor f.design_size end mlpost-0.8.2/dvi/dviinterp.ml000066400000000000000000000314501306046515300161650ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format open Dvi_util open Fonts type color = | RGB of float * float * float | CMYK of float * float * float * float | HSB of float * float * float | Gray of float (* a state can be pushed/ popped *) type state = { h : int32; v : int32; w : int32; x : int32; y : int32; z : int32; } (* text *) type env_info = {ei_conv : float; ei_pos : int32 * int32} type info = { color : color } type text = { tex_font : Fonts.t; tex_string : Int32.t list; tex_pos : float * float; tex_info : info; tex_env : env_info} type text_type1 = { c_glyph : Int32.t; c_font : Fonts.type1; c_pos : float * float; c_info : info} type command = | Fill_rect of info * float * float * float * float (** [Fill_rect info x y w h] should draw a rectangle at [(x,y)] of width [w] and height [h]. *) | Draw_text of text | Specials of info * string * float * float (** [Specials info s x y] should draw special [s], encoded as a string, at pos. [(x,y)]. [info] can contain additional information such as color. *) | Draw_text_type1 of text_type1 (** Can appear only after a decomposition of text *) type page = command list type env = { mutable ecolor : color; color_stack : color Stack.t; conv : float; mutable font : Int32.t; stack : state Stack.t; mutable s : state; use_type1 : bool; } let info_of_env env = {color = env.ecolor} let new_env conv use_type1 = {ecolor = Gray 0.; conv = conv; font = Int32.zero; stack = Stack.create (); s = {h=Int32.zero; v=Int32.zero; w=Int32.zero; x=Int32.zero; y=Int32.zero; z=Int32.zero; }; color_stack = Stack.create (); use_type1 = use_type1; } let rec scanf_with s def = function | [] -> def s | a::l -> try a s with Scanf.Scan_failure _ | Failure _ | End_of_file -> scanf_with s def l let print_state fmt s = fprintf fmt "{h = %ld; v = %ld; w = %ld; x = %ld; y = %ld; z= %ld}@." s.h s.v s.w s.x s.y s.z let put_rule env cmds a b = let x = env.conv *. (Int32.to_float env.s.h) and y = env.conv *. (Int32.to_float env.s.v) and w = env.conv *. (Int32.to_float b) and h = env.conv *. (Int32.to_float a) in (Fill_rect (info_of_env env,x,(y -. h),w,h))::cmds let load_fonts font_map conv = if Defaults.get_debug () then printf "conv : %f@." conv; Int32Map.fold (fun k fdef -> Int32Map.add k (Fonts.load_font fdef conv) ) font_map Int32Map.empty let set_env_char (_,font,_) (h,v) c = begin if Defaults.get_debug () then printf "Setting character %ld at (%ld,%ld).@." c h v; let fwidth = Fonts.char_width font (Int32.to_int c) in let width = Int32.of_float fwidth in (Int32.add h width,v) end let rec put_char_type1 (info,font,conv) char (h,v) cmds = match glyphs font with | VirtualFont vf -> (* FixMe how to use vf_design_size? Hack use the one of the first dvi, wrong!!*) if Defaults.get_debug () then printf "VirtualFont : %s ds=%f conv=%f@." (Fonts.tex_name font) vf.vf_design_size conv; let conv = (* vf.vf_design_size *)conv in let env = new_env conv true in env.s <- {env.s with h = h; v = v}; (* FIXME design size, font_scale,... All is messed up... :( *) let fm = load_fonts vf.vf_font_map (conv (* for palatino (vf?)*) *. 0.65 (* experimental :( *)) in let l = try Int32H.find vf.vf_chars char with Not_found -> failwith ("virtual font not found") in interp_command fm env cmds l | Type1 font1 -> let x = conv *. (Int32.to_float h) and y = conv *. (Int32.to_float v) in if Defaults.get_debug () then printf "Type1 : %s,%ld,%f,%f@." (Fonts.tex_name font) char x y; let text_type1 = { c_glyph = char; c_font = font1; c_pos = x,y; c_info = info} in Draw_text_type1 text_type1::cmds and put_text (info,font,conv) scl ((h,v) as pos) cmds = let x = conv *. (Int32.to_float h) and y = conv *. (Int32.to_float v) in let text = {tex_font = font; tex_string = List.rev scl; tex_pos = (x,y); tex_info = info; tex_env = {ei_conv = conv; ei_pos = pos}} in Draw_text text::cmds and set_char fm env cmds l = let info = (info_of_env env) in let font = Int32Map.find env.font fm in let conv = env.conv in let ifc = (info,font,conv) in let pos = (env.s.h,env.s.v) in let cmds,(h,v),l = if env.use_type1 then set_char_type1 ifc pos cmds l else set_char_tex ifc [] pos pos cmds l in env.s <- {env.s with h = h; v = v}; interp_command fm env cmds l and set_char_type1 ifc pos cmds l = match l with | Dvi.SetChar c::l -> let cmds = put_char_type1 ifc c pos cmds in let pos = set_env_char ifc pos c in cmds, pos, l | Dvi.PutChar c::l -> if Defaults.get_debug () then printf "Putting character %ld.@." c; let cmds = put_char_type1 ifc c pos cmds in cmds, pos, l | _ -> assert false and set_char_tex ifc scl pos_start pos_end cmds (l : Dvi.command list) = match l with | Dvi.SetChar c::l -> let pos_end = set_env_char ifc pos_end c in set_char_tex ifc (c::scl) pos_start pos_end cmds l | Dvi.PutChar c::l -> if Defaults.get_debug () then printf "Putting character %ld.@." c; close_string ifc (c::scl) pos_start pos_end cmds l | l -> close_string ifc scl pos_start pos_end cmds l and close_string ifc scl pos_start pos_end cmds l = let cmds = put_text ifc scl pos_start cmds in cmds,pos_end,l and interp_command fm env cmds l = match l with | [] -> cmds | (Dvi.SetChar _ | Dvi.PutChar _)::_ -> set_char fm env cmds l | Dvi.SetRule(a, b)::l -> if Defaults.get_debug () then printf "Setting rule (w=%ld, h=%ld).@." a b; let cmds = put_rule env cmds a b in env.s <- {env.s with h = Int32.add env.s.h b}; interp_command fm env cmds l | Dvi.PutRule(a, b)::l -> if Defaults.get_debug () then printf "Putting rule (w=%ld, h=%ld).@." a b; let cmds = put_rule env cmds a b in interp_command fm env cmds l | Dvi.Push::l -> if Defaults.get_debug () then printf "Push current state.@."; Stack.push env.s env.stack; interp_command fm env cmds l | Dvi.Pop::l -> (try if Defaults.get_debug () then printf "Pop current state.@."; env.s <- Stack.pop env.stack with Stack.Empty -> failwith "Empty color stack !"); interp_command fm env cmds l | Dvi.Right b::l -> if Defaults.get_debug () then printf "Moving right %ld.@." b; env.s<-{env.s with h = Int32.add env.s.h b}; interp_command fm env cmds l | Dvi.Wdefault::l -> if Defaults.get_debug () then printf "Moving right by the default W.@."; env.s<-{env.s with h = Int32.add env.s.h env.s.w}; interp_command fm env cmds l | Dvi.W b::l -> if Defaults.get_debug () then printf "Moving right and changing W to %ld.@." b; env.s<-{env.s with h = Int32.add env.s.h b; w = b}; interp_command fm env cmds l | Dvi.Xdefault::l -> if Defaults.get_debug () then printf "Moving right by the default X.@."; env.s<-{env.s with h = Int32.add env.s.h env.s.x}; interp_command fm env cmds l | Dvi.X b::l -> if Defaults.get_debug () then printf "Moving right and changing X to %ld.@." b; env.s<-{env.s with h = Int32.add env.s.h b; x = b}; interp_command fm env cmds l | Dvi.Down a::l -> if Defaults.get_debug () then printf "Moving down %ld.@." a; env.s <- {env.s with v = Int32.add env.s.v a}; interp_command fm env cmds l | Dvi.Ydefault::l -> if Defaults.get_debug () then printf "Moving down by the default Y.@."; env.s <- {env.s with v = Int32.add env.s.v env.s.y}; interp_command fm env cmds l | Dvi.Y a::l -> if Defaults.get_debug () then printf "Moving down and changing Y to %ld.@." a; env.s <- {env.s with v = Int32.add env.s.v a; y = a}; interp_command fm env cmds l | Dvi.Zdefault::l -> if Defaults.get_debug () then printf "Moving down by the default Z.@."; env.s <- {env.s with v = Int32.add env.s.v env.s.z}; interp_command fm env cmds l | Dvi.Z a::l -> if Defaults.get_debug () then printf "Moving down and changing Z to %ld.@." a; env.s <- {env.s with v = Int32.add env.s.v a; z = a}; interp_command fm env cmds l | Dvi.FontNum f::l -> env.font <- f; if Defaults.get_debug () then printf "Font is now set to %ld@." f; interp_command fm env cmds l | Dvi.Special xxx::l -> if Defaults.get_debug () then printf "Special command : %s@." xxx; let x = env.conv *. (Int32.to_float env.s.h) and y = env.conv *. (Int32.to_float env.s.v) in let push color = Stack.push env.ecolor env.color_stack; env.ecolor <- color; cmds in let cmds = scanf_with xxx (fun s -> Specials (info_of_env env,s,x,y)::cmds) [(fun s -> Scanf.sscanf s "color push rgb %f %f %f" (fun r g b -> push (RGB (r,g,b)))); (fun s -> Scanf.sscanf s "color push cmyk %f %f %f %f" (fun c m y k -> push (CMYK(c,m,y,k)))); (fun s -> Scanf.sscanf s "color push gray %f" (fun g -> push (Gray(g)))); (fun s -> Scanf.sscanf s "color push hsb %f %f %f" (fun h s b -> push (HSB(h,s,b)))); (fun s -> Scanf.sscanf s "color pop%n" (fun _ -> env.ecolor <- (* todo : color stack seems to traverse pages and so pop before push in one page *) try Stack.pop env.color_stack with Stack.Empty -> failwith "Empty color stack !");cmds);] in interp_command fm env cmds l let interp_page conv fm p = interp_command fm (new_env conv false) [] (Dvi.commands p) let load_doc doc = let conv = Dvi.get_conv doc in let fonts = load_fonts (Dvi.fontmap doc) conv in let pages = List.fold_left (fun acc p -> if Defaults.get_debug () then printf "#### Starting New Page ####@." else if Defaults.get_verbosity () then printf "."; (interp_page conv fonts p)::acc) [] (Dvi.pages doc) in List.rev pages let load_file file = let doc = Dvi.read_file (File.to_string file) in if Defaults.get_verbosity () then printf "Dvi file parsing and interpretation :@.@?"; let res = load_doc doc in if Defaults.get_verbosity () then printf " done@.@?"; res let decompose_text text = let font = text.tex_font in let pos = text.tex_env.ei_pos in if Defaults.get_debug () then printf "decompose text at (%ld,%ld)@." (fst pos) (snd pos); let info = text.tex_info in let ifc = (info,font,text.tex_env.ei_conv) in let fold (pos,cmds) c = let cmds = put_char_type1 ifc c pos cmds in (set_env_char ifc pos c,cmds) in let _,cmds = List.fold_left fold (pos,[]) text.tex_string in cmds module Incremental = struct let load_page i p = let conv = Dvi.Incremental.get_conv i in let fonts = load_fonts (Dvi.Incremental.font_map i) conv in interp_page conv fonts p end module Print = struct (* debug printing *) open Format let command fmt c = match c with | Fill_rect (_,x,y,w,h) -> fprintf fmt "rect(%f,%f,%f,%f)" x y w h | Draw_text text -> fprintf fmt "glyph (%s)" (Fonts.tex_name text.tex_font) | Specials _ -> assert false | Draw_text_type1 _ -> assert false let page fmt p = fprintf fmt "[< %a >]" (Misc.print_list Misc.newline command) p let dvi fmt d = Misc.print_list (fun fmt () -> fprintf fmt "@\n@\n") page fmt d end mlpost-0.8.2/dvi/dviinterp.mli000066400000000000000000000036441306046515300163420ustar00rootroot00000000000000(** This module provides a functor to read DVI files *) (** The type of colors in a DVI file *) type color = | RGB of float * float * float | CMYK of float * float * float * float | HSB of float * float * float | Gray of float (** The info type *) type info = { color : color } (* A device can choose the way it want to see a text : - A string in some tex font at some position - A list of glyph of some type1 font each at his own position *) type env_info type text = { tex_font : Fonts.t; tex_string : Int32.t list; tex_pos : float * float; tex_info : info; tex_env : env_info} type text_type1 = { c_glyph : Int32.t; c_font : Fonts.type1; c_pos : float * float; c_info : info} type command = | Fill_rect of info * float * float * float * float (** [Fill_rect info x y w h] should draw a rectangle at [(x,y)] of width [w] and height [h]. *) | Draw_text of text | Specials of info * string * float * float (** [Specials info s x y] should draw special [s], encoded as a string, at pos. [(x,y)]. [info] can contain additional information such as color. *) | Draw_text_type1 of text_type1 (** Can appear only after a decomposition of text *) type page = command list val load_file : File.t -> page list (** [load_file arg fn] loads the dvi document in file [fn], passes [arg] and the loaded document to {!Dev.new_document} and calls the drawing functions of {!Dev} as needed. At the end, the return value of the device is returned. The command list are in reverse order inside a page*) val decompose_text : text -> command list module Incremental : sig val load_page : Dvi.Incremental.t -> Dvi.page -> page end module Print : sig (* debug printing *) val command : Format.formatter -> command -> unit val page : Format.formatter -> page -> unit val dvi : Format.formatter -> page list -> unit end mlpost-0.8.2/dvi/fonts.ml000066400000000000000000000212751306046515300153160ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Dvi_util exception Fonterror of string let font_error s = raise (Fonterror s) type type1 = { glyphs_tag : int; (* That must be separated from cairo *) glyphs_ft : Cairo_ft.ft_face; (* the file, pfb or pfa, which define the glyphs *) glyphs_enc : int -> int; (* the conversion of the characters between tex and the font *) slant : float option; extend : float option; glyphs_ratio_cm : float} type vf = { vf_design_size : float; vf_font_map : Dvi_util.font_def Dvi_util.Int32Map.t; vf_chars : Dvi.command list Int32H.t} type glyphs = | Type1 of type1 | VirtualFont of vf type t = { tex_name : string; metric : Tfm.t; glyphs : glyphs Lazy.t; ratio : float; ratio_cm : float } let tex_name t = t.tex_name let ratio_cm t = t.ratio_cm let metric t = t.metric let design_size t = Tfm.design_size t.metric let glyphs t = Lazy.force t.glyphs let scale t f = t.ratio_cm *. f let kwhich = "kpsewhich" let which_fonts_table = "pdftex.map" let memoize f nb = let memoize = Hashtbl.create nb in fun arg -> try Hashtbl.find memoize arg with Not_found -> let result = f arg in Hashtbl.add memoize arg result; result let find_file_aux file = let temp_fn = Filename.temp_file "font_path" "" in let exit_status = Sys.command (Format.sprintf "%s %s > %s" kwhich file temp_fn) in if exit_status <> 0 then begin Sys.remove temp_fn; font_error "kwhich failed" end else let cin = open_in temp_fn in let n = try input_line cin with _ -> close_in cin; Sys.remove temp_fn; font_error "Cannot find font" in close_in cin; Sys.remove temp_fn; n let find_file = memoize find_file_aux 30 module HString = Hashtbl let deal_with_error ?(pfb=false) lexbuf f = try f () with | (Parsing.Parse_error |Failure _) as a-> let p_start = Lexing.lexeme_start_p lexbuf in let p_end = Lexing.lexeme_end_p lexbuf in let str = if not pfb then "" else match !Pfb_lexer.state with | Pfb_lexer.Header -> "header" | Pfb_lexer.Encoding -> "encoding" | Pfb_lexer.Charstring -> "charstring" in Format.eprintf "line %i, characters %i-%i : %s parse_error state : %s@." p_start.Lexing.pos_lnum p_start.Lexing.pos_bol p_end.Lexing.pos_bol (Lexing.lexeme lexbuf) str ; raise a let load_fonts_map filename = if Defaults.get_verbosity () then Format.printf "Load font map from %s...@?" filename; let file = open_in filename in let lexbuf = Lexing.from_channel file in deal_with_error lexbuf (fun () -> let result = Map_parser.pdftex_main Map_lexer.pdftex_token lexbuf in let table = HString.create 1500 in List.iter (fun x -> HString.add table x.Fonts_type.tex_name x) result; if Defaults.get_verbosity () then Format.printf "done@."; table) let load_enc_aux filename = if Defaults.get_verbosity () then Format.printf "Loading enc from %s...@?" filename; let file = open_in filename in let lexbuf = Lexing.from_channel file in deal_with_error lexbuf (fun () -> let result = Pfb_parser.enc_main Pfb_lexer.enc_token lexbuf in let enc_table = Array.create 256 "" in let count = ref 0 in List.iter (fun x -> enc_table.(!count)<-x;incr(count)) result; if Defaults.get_verbosity () then Format.printf "done@."; enc_table) let load_enc = memoize load_enc_aux 15 let fonts_map_table = lazy (load_fonts_map (find_file which_fonts_table)) let fonts_table = (HString.create 1500 : (string,t) Hashtbl.t) let load_font_tfm fd = if Defaults.get_verbosity () then Format.printf "Loading font %s at [%ld/%ld]...@?" fd.name fd.scale_factor fd.design_size; let filename = if fd.area <> "" then Filename.concat fd.area fd.name else find_file (fd.name^".tfm") in if Defaults.get_debug () then Format.printf "Trying to find metrics at %s...@." filename; let tfm = Tfm.read_file filename in (* FixMe in vf file the checksum of tfm is 0 *) if (Int32.compare fd.checksum Int32.zero <> 0 && Int32.compare tfm.Tfm.body.Tfm.header.Tfm.checksum fd.checksum <> 0) then font_error "Metrics checksum do not match !.@."; if Defaults.get_debug () then Format.printf "Metrics successfully loaded for font %s from %s.@." fd.name filename; if Defaults.get_verbosity () then Format.printf "done@."; tfm let compute_trans_enc encoding_table font_ft char = let char_name = encoding_table.(char) in Mlpost_ft.ft_get_name_index font_ft char_name let font_is_virtual s = try Some (find_file (s^".vf")) with Fonterror _ -> None let id = let c = ref (-1) in fun () -> incr c; !c let ft = lazy (Cairo_ft.init_freetype ()) let load_glyphs tex_name ratio_cm = match font_is_virtual tex_name with | Some vf -> let vf = Dvi.read_vf_file vf in let vf_chars = Int32H.create 257 in let add cd = Int32H.add vf_chars cd.Dvi.char_code cd.Dvi.char_commands in List.iter add vf.Dvi.vf_chars_desc; VirtualFont { vf_design_size = vf.Dvi.vf_preamble.Dvi.pre_vf_ds; vf_font_map = vf.Dvi.vf_font_map; vf_chars = vf_chars} | None -> let font_map = try HString.find (Lazy.force fonts_map_table) tex_name with Not_found -> invalid_arg (Format.sprintf "This tex font : %s has no pfb counterpart@ \ and seems not to be virtual@ \ it can't be currently used with the cairo backend" tex_name) in let pfab = find_file font_map.Fonts_type.pfab_name in let pfab = Cairo_ft.new_face (Lazy.force ft) pfab in let glyphs_enc = match font_map.Fonts_type.enc_name with | None -> (* 0 seems to be an empty one, 1 the one in the pfb, but I'm not sure*) let charmap_index = 1 in Mlpost_ft.ft_set_charmap pfab charmap_index; Mlpost_ft.ft_get_char_index pfab | Some x -> let enc = load_enc (find_file x) in compute_trans_enc enc pfab in (* let glyphs_enc i = *) (* let r = glyphs_enc i in *) (* Printf.printf "char : %i -> %i\n%!" i r; *) (* r in *) Type1 { glyphs_tag = id (); glyphs_ft = pfab; glyphs_enc = glyphs_enc; slant = font_map.Fonts_type.slant; extend = font_map.Fonts_type.extend; glyphs_ratio_cm = ratio_cm} let load_font doc_conv fdef = let tex_name = fdef.name in let tfm = load_font_tfm fdef in let ratio = Int32.to_float fdef.scale_factor (*(Int32.to_float (Int32.mul mag fdef.Dvi.scale_factor)) /. 1000. (* fdef.Dvi.design_size *)*) and ratio_cm = (Int32.to_float fdef.scale_factor) *. doc_conv in let glyphs = lazy (load_glyphs tex_name ratio_cm) in { tex_name = tex_name; metric = tfm; glyphs = glyphs; ratio = ratio; ratio_cm = ratio_cm } let load_font = let memoize = Hashtbl.create 15 in fun (fdef : font_def) (doc_conv : float) -> try Hashtbl.find memoize (doc_conv,fdef.name) with Not_found -> let result = load_font doc_conv fdef in Hashtbl.add memoize (doc_conv,fdef.name) result; result let char_width t c = Metric.char_width t.metric c *. t.ratio let char_height t c = Metric.char_height t.metric c *. t.ratio let char_depth t c = Metric.char_depth t.metric c *. t.ratio let char_dims t c = let a,b,c = Metric.char_dims t.metric c and f = t.ratio in a *. f, b *. f, c *. f mlpost-0.8.2/dvi/fonts.mli000066400000000000000000000026471306046515300154710ustar00rootroot00000000000000open Dvi_util (** Load fonts and extract information *) type type1 = private { glyphs_tag : int; (* unique tag *) glyphs_ft : Cairo_ft.ft_face; (* the file, pfb or pfa, which define the glyphs *) glyphs_enc : int -> int; (* the conversion of the charactersx between tex and the font *) slant : float option; extend : float option; glyphs_ratio_cm : float} type vf =private { vf_design_size : float; vf_font_map : Dvi_util.font_def Dvi_util.Int32Map.t; (* Font on which the virtual font is defined *) vf_chars : Dvi.command list Int32H.t; (* The dvi command which define each character*)} type glyphs = | Type1 of type1 | VirtualFont of vf type t (** the type of a loaded font *) val load_font : font_def -> float -> t (** [load_font def f] loads font [def] scaled by [f] *) val metric : t -> Tfm.t (** Obtain the font metric *) val tex_name : t -> string (** get the name of the font as used by TeX *) val ratio_cm : t -> float (** The font ratio, in cm *) val glyphs : t -> glyphs val char_width : t -> int -> float val char_height : t -> int -> float val char_depth : t -> int -> float (** get information about the [i]th char of the font *) val char_dims : t -> int -> float * float * float (** width, height, depth of the [i]th char *) val scale : t -> float -> float (** [scale t f] scale the given float [f] by [ratio_cm t] *) val design_size : t -> float (** the design size of the font *) mlpost-0.8.2/dvi/fonts_type.mli000066400000000000000000000026031306046515300165220ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type encoding = [ `File of string | `Adobe_remap | `None] type font_map = { tex_name : string; human_name : string; enc_name : string option; pfab_name : string; slant : float option; extend : float option; } mlpost-0.8.2/dvi/map_lexer.mll000066400000000000000000000042211306046515300163050ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* File lexer.mll *) { open Map_parser (* The type token is defined in parser.mli *) let incr_linenum lexbuf = let pos = lexbuf.Lexing.lex_curr_p in lexbuf.Lexing.lex_curr_p <- { pos with Lexing.pos_lnum = pos.Lexing.pos_lnum + 1; Lexing.pos_bol = pos.Lexing.pos_cnum; } } let ident = (['-''_''a'-'z''A'-'Z''0'-'9'])+ let float = ['-']?['0'-'9']*'.'['0'-'9']+ let int = ['0'-'9']+ rule pdftex_token = parse [' ' '\t'] { pdftex_token lexbuf } (* skip blanks *) | ("%" [^'\n']* "\n") {incr_linenum lexbuf; pdftex_token lexbuf } (* comment *) | ['\n' ] { incr_linenum lexbuf; EOL } | '"' { DQUOTE } | "ExtendFont" { EXTEND } | "SlantFont" { SLANT } | "ReEncodeFont" { REENCODEFONT } | '<' ('<' |'[')? ' '* (ident ".enc" as a) { IDENC a } | '<' ('<' |'[')? ' '* (ident ".pf" ['a''b'] as a) { IDPFAB a} | '<' ('<' |'[')? ' '* (ident ".ttf" as a) { IDTTF a} | ident as a { ID a } | float as a { FLOAT (float_of_string a) } | eof { EOF } mlpost-0.8.2/dvi/map_parser.mly000066400000000000000000000054331306046515300165050ustar00rootroot00000000000000/**************************************************************************/ /* */ /* Copyright (C) Johannes Kanig, Stephane Lescuyer */ /* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot */ /* */ /* This software is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License version 2.1, with the special exception on linking */ /* described in file LICENSE. */ /* */ /* This software 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. */ /* */ /**************************************************************************/ /* File parser.mly */ %{ open Fonts_type let enc = ref None let slant = ref None let extend = ref None let pfab = ref None let compose tex human = match !pfab with |None -> (Parsing.parse_error "No pfab for this font ttf");None |Some v_pfab -> let font = {tex_name = tex; human_name = human; enc_name = !enc; pfab_name = v_pfab; slant = !slant; extend = !extend } in (slant := None; extend := None; enc := None; pfab := None;Some font) let add_some l = function | None -> l | Some a -> a::l %} %token FLOAT %token ID IDENC IDPFAB IDTTF %token EOL EOF %token REMAP SLANT EXTEND %token DQUOTE LESS %token DEFAULT NONE %token REENCODEFONT %type pdftex_main %start pdftex_main %% /*dvipdfm_main pr: dvipdfm_line EOL dvipdfm_main { pr $1 } dvipdfm_line EOF {[$1]} ; dvipdfm_line: ID ID ID ID ;*/ pdftex_main : | pdftex_line EOL pdftex_main {add_some $3 $1} | pdftex_line EOF {add_some [] $1} | EOL pdftex_main {$2} | EOF {[]} ; pdftex_line: | ID ID pdftex_options {compose $1 $2} | ID pdftex_options {compose $1 $1} pdftex_options: | {} | DQUOTE pdftex_options_aux DQUOTE pdftex_options {$2} | IDENC pdftex_options {enc:=Some $1} | IDPFAB pdftex_options {pfab:=Some $1} | IDTTF pdftex_options {pfab:=None} pdftex_options_aux: | {} | FLOAT SLANT pdftex_options_aux {slant:=Some $1} | FLOAT EXTEND pdftex_options_aux {extend:=Some $1} | ID REENCODEFONT pdftex_options_aux {} mlpost-0.8.2/dvi/metric.ml000066400000000000000000000015621306046515300154450ustar00rootroot00000000000000type t = Tfm.t open Tfm (* compute index of the character *) let to_abs_idx t i = i - t.file_hdr.bc (* get info struct of character *) let get_info t i = t.body.char_info.(to_abs_idx t i) let char_width t c = t.body.width.((get_info t c).width_index) let char_height t c = t.body.height.((get_info t c).height_index) let char_depth t c = t.body.depth.((get_info t c).depth_index) let char_italic t c = t.body.italic.((get_info t c).italic_index) let char_dims t c = let i = get_info t c in let b = t.body in b.width.(i.width_index), b.height.(i.height_index), b.depth.(i.depth_index) let slant t = t.body.param.(0) let space t = t.body.param.(1) let space_stretch t = t.body.param.(2) let space_shrink t = t.body.param.(3) let x_height t = t.body.param.(4) let quad t = t.body.param.(5) let extra_space t = t.body.param.(6) (* is the size of one em in the font. *) mlpost-0.8.2/dvi/metric.mli000066400000000000000000000027621306046515300156210ustar00rootroot00000000000000(** A high-level interface for Font metrics *) type t = Tfm.t val char_width : t -> int -> float (** [char_width t i] returns the width of the [i]th character of the font metric [t], [0] is the first character *) val char_height : t -> int -> float (** same as [char_width], but for character height *) val char_depth : t -> int -> float (** same as [char_width], but for character depth *) val char_italic : t -> int -> float (** same as [char_width], but for italic correction of the character *) val char_dims : t -> int -> float * float * float (** [char_dims metric i] returns the width, height and depth of the [i]th char, slightly more efficient than invoking the other functions three times *) val slant : t -> float (** is the amount of italic slant, which is used to help position accents. For example, slant=.25 means that when you go up one unit, you also go .25 units to the right. *) val space : t -> float (** is the normal spacing between words in text. Note that character " " in the font need not have anything to do with blank spaces. *) val space_stretch : t -> float (** is the amount of glue stretching between words. *) val space_shrink : t -> float (** is the amount of glue shrinking between words. *) val x_height : t -> float (** is the height of letters for which accents don't have to be raised or lowered. *) val quad : t -> float (** is the size of one em in the font. *) val extra_space : t -> float (** is the amount added to [space] at the ends of sentences. *) mlpost-0.8.2/dvi/myocamlbuild.ml000066400000000000000000000064131306046515300166430ustar00rootroot00000000000000open Ocamlbuild_plugin (* open Command -- no longer needed for OCaml >= 3.10.2 *) (* these functions are not really officially exported *) let run_and_read = Ocamlbuild_pack.My_unix.run_and_read let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings let split s ch = let x = ref [] in let rec go s = let pos = String.index s ch in x := (String.before s pos)::!x; go (String.after s (pos + 1)) in try go s with Not_found -> !x let split_nl s = split s '\n' let before_space s = try String.before s (String.index s ' ') with Not_found -> s (* this lists all supported packages *) let find_packages () = List.map before_space (split_nl & run_and_read "ocamlfind list") let syntaxes = ["bitstring","/usr/lib/ocaml/bitstring", "camlp4o -I /usr/lib/ocaml/bitstring bitstring.cma bitstring_persistent.cma pa_bitstring.cmo"] (* ocamlfind command *) let ocamlfind x = S[A"ocamlfind"; x] let _ = dispatch begin function | Before_options -> (* by using Before_options one let command line options have an higher priority *) (* on the contrary using After_options will guarantee to have the higher priority *) (* override default commands by ocamlfind ones *) Options.ocamlc := ocamlfind & A"ocamlc"; Options.ocamlopt := ocamlfind & A"ocamlopt"; Options.ocamldep := ocamlfind & A"ocamldep"; Options.ocamldoc := ocamlfind & A"ocamldoc"; Options.ocamlmktop := ocamlfind & A"ocamlmktop" | After_rules -> (* When one link an OCaml library/binary/package, one should use -linkpkg *) flag ["ocaml"; "link"] & A"-linkpkg"; (* For each ocamlfind package one inject the -package option when * compiling, computing dependencies, generating documentation and * linking. *) List.iter begin fun pkg -> flag ["ocaml"; "compile"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "doc"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "link"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S[A"-package"; A pkg]; end (find_packages ()); (* Like -package but for extensions syntax. Morover -syntax is useless * when linking. *) List.iter begin function syntax,lib,pp -> flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-pp"; A pp]; flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-pp"; A pp]; flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-pp"; A pp]; end syntaxes; (* The default "thread" tag is not compatible with ocamlfind. Indeed, the default rules add the "threads.cma" or "threads.cmxa" options when using this tag. When using the "-linkpkg" option with ocamlfind, this module will then be added twice on the command line. To solve this, one approach is to add the "-thread" option when using the "threads" package using the previous plugin. *) flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]) | _ -> () end mlpost-0.8.2/dvi/pfb_lexer.mll000066400000000000000000000067771306046515300163210ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* File lexer.mll *) { open Format open Pfb_parser (* The type token is defined in parser.mli *) let incr_linenum lexbuf = let pos = lexbuf.Lexing.lex_curr_p in lexbuf.Lexing.lex_curr_p <- { pos with Lexing.pos_lnum = pos.Lexing.pos_lnum + 1; Lexing.pos_bol = pos.Lexing.pos_cnum; } type state = |Header | Encoding | Charstring let state = ref Header } let ident = (['.''-''_''a'-'z''A'-'Z''0'-'9'])+ let float = ['-']?['0'-'9']*'.'['0'-'9']+ let int = ['0'-'9']+ rule header_token = parse | "/Encoding" [^'\n']* '\n' [^'\n']* '\n' {incr_linenum lexbuf; incr_linenum lexbuf; state:=Encoding; DUMB} | [^'\n']* '\n' {incr_linenum lexbuf; header_token lexbuf} | _ {eprintf "During header parsing\n"; failwith ""} and encoding_token = parse | "dup " (int as id) {ID_ENCODING (int_of_string id)} | ' '* '/' (ident as id) " put\n" {incr_linenum lexbuf; NAME_ENCODING id} | "readonly" {shortcut_token lexbuf} | _ {eprintf "During encoding parsing@."; failwith ""} and shortcut_token = parse | [^'/']* "/CharStrings" [^'\n']* '\n' {incr_linenum lexbuf; state:=Charstring; DUMB} | [^'\n']* '\n' {incr_linenum lexbuf; shortcut_token lexbuf} | _ {eprintf "During middle parsing@.";failwith ""} and charstring_token = parse | '/' (ident as id) [^'{''\n']* '{' [^'}']* '}' [^'\n']* '\n' {incr_linenum lexbuf; NAME_CHARSTRING id} | '/' (ident as id) [^'\n']* '\n' {incr_linenum lexbuf; NAME_CHARSTRING id} | "end" [^'\n']* '\n' {end_token lexbuf} | [^'\n']* '\n' {incr_linenum lexbuf;charstring_token lexbuf} | _ {Printf.eprintf "During charstring parsing@."; failwith ""} and end_token = parse | _* eof {state:=Header; DUMB} | _ {eprintf "During end parsing@."; failwith ""} and enc_token = parse | '%' [^'\n']* '\n' {incr_linenum lexbuf; enc_token lexbuf} | '/' [^'[']* '[' '\n' {incr_linenum lexbuf; DUMB} | '/' (ident as a) {NAME_ENCODING a} | '\n' {incr_linenum lexbuf; enc_token lexbuf} | [' ''\t']* {enc_token lexbuf} | ']' _* eof {DUMB} | _ {failwith "enc token not exhaustive"} { let pfb_human_token x = match !state with |Header -> header_token x |Encoding -> encoding_token x |Charstring -> charstring_token x } mlpost-0.8.2/dvi/pfb_parser.mly000066400000000000000000000034721306046515300165000ustar00rootroot00000000000000/**************************************************************************/ /* */ /* Copyright (C) Johannes Kanig, Stephane Lescuyer */ /* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot */ /* */ /* This software is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License version 2.1, with the special exception on linking */ /* described in file LICENSE. */ /* */ /* This software 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. */ /* */ /**************************************************************************/ /* File parser.mly */ %{ open Fonts_type let encoding_table = ref (Array.create 256 "") %} %token NAME_CHARSTRING, NAME_ENCODING %token ID_ENCODING %token DUMB %type <(string array) * (string list)> pfb_human_main %type enc_main %start pfb_human_main enc_main %% pfb_human_main : DUMB encoding DUMB charstrings DUMB{ let rencoding_table = !encoding_table in encoding_table := Array.create 256 ""; (rencoding_table,$4)} encoding : | {} | ID_ENCODING NAME_ENCODING encoding {(!encoding_table).($1)<-$2 } charstrings : | {[]} | NAME_CHARSTRING charstrings { $1::$2} enc_main : | DUMB enc_aux DUMB {$2} enc_aux : | {[]} | NAME_ENCODING enc_aux {$1::$2} mlpost-0.8.2/dvi/tfm.ml000066400000000000000000000210411306046515300147420ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format type file_hdr = { lf : int; lh : int; bc : int; ec : int; nw : int; nh : int; nd : int; ni : int; nl : int; nk : int; ne : int; np : int; } type fix_word = float type header = { checksum : int32; design_size : fix_word; coding_scheme : string option; identifier : string option; seven_bit_safe_flag : int option; face : int option; } type char_info_word = { width_index : int; height_index : int; depth_index : int; italic_index : int; tag : int; info_remainder : int } type lig_kern_command = { skip_byte : int; next_char : int; op_byte : int; kern_remainder : int; } type extensible_recipe = { top : int; mid : int; bot : int; rep : int; } type body = { header : header; char_info : char_info_word array; width : fix_word array; height : fix_word array; depth : fix_word array; italic : fix_word array; lig_kern : lig_kern_command array; kern : fix_word array; exten : extensible_recipe array; param : fix_word array; } type t = { file_hdr : file_hdr; body : body } module Print = struct let file_hdr fmt fh = fprintf fmt "File header :\n"; fprintf fmt " lf=%d; lh=%d; bc=%d; ec=%d;\n" fh.lf fh.lh fh.bc fh.ec; fprintf fmt " nw=%d; nh=%d; nd=%d; ni=%d;\n" fh.nw fh.nh fh.nh fh.ni; fprintf fmt " nl=%d; nk=%d; ne=%d; np=%d;\n" fh.nl fh.nk fh.ne fh.np let wd fmt (wd : fix_word) = pp_print_float fmt wd let wds fmt a = Array.iteri (fun i c -> fprintf fmt " %d : %a\n" i wd c) a let header fmt hdr = fprintf fmt " Header : Checksum = %lx; Design size = %a\n" hdr.checksum wd hdr.design_size let info fmt info = fprintf fmt " Char : Width = %d, Height = %d, Depth = %d, Italic = %d\n" info.width_index info.height_index info.depth_index info.italic_index; fprintf fmt " tag = %d; remainder = %d\n" info.tag info.info_remainder let infos fmt infos = Array.iter (fun c -> fprintf fmt "%a" info c) infos let kern_cmd fmt kc = fprintf fmt " Lig Kern command : skip = %d, next = %d, op = %d, rem = %d\n" kc.skip_byte kc.next_char kc.op_byte kc.kern_remainder let kern_cmds fmt kcs = Array.iter (fun c -> fprintf fmt "%a" kern_cmd c) kcs let recipe fmt r = fprintf fmt " Recipe : top = %d, mid = %d, bot = %d, rep = %d\n" r.top r.mid r.bot r.rep let recipes fmt rs = Array.iter (fun c -> fprintf fmt "%a" recipe c) rs let body fmt body = fprintf fmt "Body : \n%a\n" header body.header; fprintf fmt "%a Widths:\n%a Heights:\n%a Depths:\n%a Italic:\n%a" infos body.char_info wds body.width wds body.height wds body.depth wds body.italic; fprintf fmt "%a Kerns:\n%a%a Params:\n%a" kern_cmds body.lig_kern wds body.kern recipes body.exten wds body.param let tfm name fmt {file_hdr = fh; body = bdy} = fprintf fmt "***********************\n"; fprintf fmt "Reading Tex Font Metrics file : %s\n" name; fprintf fmt "%a%a" file_hdr fh body bdy end exception TfmError of string ;; let tfm_error s = raise (TfmError s) let tfm_assert d a = if a then () else tfm_error d let read_n dummy f n bits = let a = Array.make n dummy in let rec iter_until i bits = if i = n then bits else let wd, bits = f bits in a.(i) <- wd; iter_until (i+1) bits in let bits = iter_until 0 bits in a, bits let epsilon = 1./.(2.**20.) let fix_word bits = bitmatch bits with | { word : 32 : bigendian; bits : -1 : bitstring} -> (Int32.to_float word) *. epsilon, bits | { _ : -1 : bitstring } -> tfm_error "ill-formed fix_word" let read_n_fixwds = read_n 0. fix_word let file_hdr bits = bitmatch bits with | { lf : 16 : unsigned, bigendian; lh : 16 : unsigned, bigendian; bc : 16 : unsigned, bigendian; ec : 16 : unsigned, bigendian; nw : 16 : unsigned, bigendian; nh : 16 : unsigned, bigendian; nd : 16 : unsigned, bigendian; ni : 16 : unsigned, bigendian; nl : 16 : unsigned, bigendian; nk : 16 : unsigned, bigendian; ne : 16 : unsigned, bigendian; np : 16 : unsigned, bigendian; bits : -1 : bitstring } -> tfm_assert "number of characters" (bc-1 <= ec && ec <= 255); tfm_assert "extensible character table too big" (ne <= 256); tfm_assert "total size constraint" (lf = 6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np); { lf = lf; lh = lh; bc = bc; ec = ec; nw = nw; nh = nh; nd = nd; ni = ni; nl = nl; nk = nk; ne = ne; np = np }, bits | { _ : -1 : bitstring } -> tfm_error "ill formed header" let header sz bits = bitmatch bits with | { checksum : 32 : bigendian; bits : -1 : bitstring } -> begin let design, bits = fix_word bits in bitmatch bits with | { _ : (sz-2)*32 : string; bits : -1 : bitstring } -> { checksum = checksum; design_size = design; coding_scheme = None; identifier = None; seven_bit_safe_flag = None; face = None; }, bits | { _ : -1 : bitstring } -> tfm_error "ill-formed body header2" end | { _ : -1 : bitstring } -> tfm_error "ill-formed body header1" let dummy_info = { width_index = 0; height_index = 0; depth_index = 0; italic_index = 0; tag = 0; info_remainder = 0 } let char_info_word bits = bitmatch bits with | { width_idx : 8; height_idx : 4; depth_idx : 4; italic_idx : 6; tag : 2; remainder : 8; bits : -1 : bitstring } -> { width_index = width_idx; height_index = height_idx; depth_index = depth_idx; italic_index = italic_idx; tag = tag; info_remainder = remainder }, bits | { _ : -1 : bitstring } -> tfm_error "ill-formed char info word" let read_info_words = read_n dummy_info char_info_word let kern_dummy = { skip_byte = 0; next_char = 0; op_byte = 0; kern_remainder = 0 } let lig_kern_cmd bits = bitmatch bits with | { skip_byte : 8; next_char : 8; op_byte : 8; remainder : 8; bits : -1 : bitstring } -> { skip_byte = skip_byte; next_char = next_char ; op_byte = op_byte; kern_remainder = remainder; }, bits | { _ : -1 : bitstring } -> tfm_error "ill-formed lig kern command" let read_kern_cmds = read_n kern_dummy lig_kern_cmd let recipe_dummy = { top = 0; mid = 0; bot = 0; rep = 0; } let exten_recipe bits = bitmatch bits with | { top : 8; mid : 8; bot : 8; rep : 8; bits : -1 : bitstring } -> { top = top; mid = mid; bot = bot; rep = rep}, bits | { _ : -1 : bitstring } -> tfm_error "ill-formed extensible recipe" let read_recipes = read_n recipe_dummy exten_recipe let body fh bits = let hdr, bits = header fh.lh bits in let infos, bits = read_info_words (fh.ec - fh.bc + 1) bits in let width, bits = read_n_fixwds fh.nw bits in let height, bits = read_n_fixwds fh.nh bits in let depth, bits = read_n_fixwds fh.nd bits in let italic, bits = read_n_fixwds fh.ni bits in let lig_kern, bits = read_kern_cmds fh.nl bits in let kern, bits = read_n_fixwds fh.nk bits in let exten, bits = read_recipes fh.ne bits in let param, bits = read_n_fixwds fh.np bits in if Bitstring.bitstring_length bits <> 0 then printf "Warning : ignored extra data after parameters.\n"; { header = hdr; char_info = infos; width = width; height = height; depth = depth; italic = italic; lig_kern = lig_kern; kern = kern; exten = exten; param = param; } let read_file file = let bits = Bitstring.bitstring_of_file file in let fh, bits = file_hdr bits in if Defaults.get_debug () then Print.file_hdr std_formatter fh; let body = body fh bits in { file_hdr = fh; body = body } let design_size t = t.body.header.design_size mlpost-0.8.2/dvi/tfm.mli000066400000000000000000000042041306046515300151150ustar00rootroot00000000000000(** A low level interface for TeX Font Metric (Tfm) files *) (** The structure of the types follows very closely the one of Tfm files. See documentation for this file type to get more detailed information about the record fields. *) type file_hdr = { lf : int; (** length of the entire file, in words *) lh : int; (** length of the header data, in words *) bc : int; (** smallest character code in the font *) ec : int; (** largest character code in the font *) nw : int; (** number of words in the width table *) nh : int; (** number of words in the height table *) nd : int; (** number of words in the depth table *) ni : int; (** number of words in the italic correction table *) nl : int; (** number of words in the lig/kern table *) nk : int; (** number of words in the kern table *) ne : int; (** number of words in the extensible character table *) np : int; (** number of font parameter words *) } type fix_word = float type header = { checksum : int32; (** font checksum *) design_size : fix_word; (** The font design size *) coding_scheme : string option; identifier : string option; seven_bit_safe_flag : int option; face : int option; } type char_info_word = { width_index : int; height_index : int; depth_index : int; italic_index : int; tag : int; info_remainder : int } (** information about a char *) type lig_kern_command = { skip_byte : int; next_char : int; op_byte : int; kern_remainder : int; } (** a kerning command *) type extensible_recipe = { top : int; mid : int; bot : int; rep : int; } (** information about extensible characters *) type body = { header : header; char_info : char_info_word array; width : fix_word array; height : fix_word array; depth : fix_word array; italic : fix_word array; lig_kern : lig_kern_command array; kern : fix_word array; exten : extensible_recipe array; param : fix_word array; } (** the body of a Tfm file *) type t = { file_hdr : file_hdr; body : body } (** A tfm file *) val read_file : string -> t (** read a tfm file *) val design_size : t -> float (** accessor for the [design_size] of the font *) mlpost-0.8.2/examples/000077500000000000000000000000001306046515300146605ustar00rootroot00000000000000mlpost-0.8.2/examples/.gitignore000066400000000000000000000001421306046515300166450ustar00rootroot00000000000000*.1 *.log *.tex *.aux *.png *.dvi *.dummy *.html *.ps *.pdf *.svg *.annot *.cmx *.cmi *.o parse.mlmlpost-0.8.2/examples/Makefile000066400000000000000000000077201306046515300163260ustar00rootroot00000000000000MAX := 17 # all files that are generated from boxes.ml BOXESPNG := $(foreach i,$(shell seq 1 9), boxes$(i).png) # all files that are generated from paths.ml PATHSPNG := $(foreach i,$(shell seq 1 17), paths$(i).png) # all files that are generated from misc.ml MISCPNG := $(foreach i,1 2 $(shell seq 4 9) $(shell seq 11 14), misc$(i).png) # all files that are generated from tree.ml TREEPNG := $(foreach i,$(shell seq 1 14), tree$(i).png) # all files that are generated from label.ml LABELPNG := $(foreach i,$(shell seq 1 2), label$(i).png) # all files that are generated from automata.ml AUTOMPNG := automata1.png automata2.png automata4.png HISTPNG := hist1.png RADARPNG := radar1.png radar2.png REALPLOTPNG := real_plot1.png real_plot2.png COLORPNG := color1.png color2.png color3.png color4.png INCLUDEPNG := include1.png include2.png include3.png DOTPNG := dot_dot1.png dot_dot2.png HTMLFILES := boxes.ml.html paths.ml.html misc.ml.html tree.ml.html \ label.ml.html automata.ml.html hist.ml.html radar.ml.html\ real_plot.ml.html dot_dot.ml.html color.ml.html include.ml.html MLPOST:=mlpost -v -ps ALL := $(BOXESPNG) $(PATHSPNG) $(MISCPNG) $(TREEPNG) $(LABELPNG) $(AUTOMPNG)\ $(HISTPNG) $(RADARPNG) $(REALPLOTPNG) $(COLORPNG) $(INCLUDEPNG) #Direct mps output ALL_MPS := $(addprefix mps_,$(ALL)) ALL_CAIRO := $(addprefix cairo_,$(ALL)) ALL_CAIRO_PNG := $(addprefix png_,$(ALL_CAIRO)) ALL_CAIRO_PDF := $(addprefix pdf_,$(ALL_CAIRO)) ALL_CAIRO_PS := $(addprefix ps_,$(ALL_CAIRO)) ALL_CAIRO_SVG := $(addprefix svg_,$(ALL_CAIRO:.png=.svg)) all : all_metapost all_cairo all_mps all_metapost: $(ALL) all_mps: $(ALL_MPS) all_cairo: all_cairo_png all_cairo_ps all_cairo_pdf all_cairo_svg all_cairo_png: $(ALL_CAIRO_PNG) all_cairo_pdf: $(ALL_CAIRO_PDF) all_cairo_ps: $(ALL_CAIRO_PS) all_cairo_svg: $(ALL_CAIRO_SVG) .PHONY: all all_metapost all_mps all_cairo all_cairo_png all_cairo_pdf \ all_cairo_ps all_cairo_svg contrib:$(DOTPNG)\ $(addprefix png_cairo_,$(DOTPNG))\ $(addprefix pdf_cairo_,$(DOTPNG))\ $(addprefix ps_cairo_,$(DOTPNG))\ $(addprefix svg_cairo_,$(DOTPNG:png=svg)) #Compilation %_dot.native : %_dot.ml $(MLPOST) -native -contrib dot -dont-execute -compile-name $@ $^ %.native : %.ml $(MLPOST) -native -dont-execute -compile-name $@ $^ #With Metapost : $(foreach i,$(shell seq 1 $(MAX)), %$(i).1) : %.native ./$^ -ps #With direct mps output : $(foreach i,$(shell seq 1 $(MAX)), mps_%$(i).mps) : %.native ./$^ -mps -prefix "mps_" #With cairo pdf $(foreach i,$(shell seq 1 $(MAX)), pdf_cairo_%$(i).pdf) : %.native ./$^ -pdf -cairo -prefix "pdf_cairo_" #With cairo ps $(foreach i,$(shell seq 1 $(MAX)), ps_cairo_%$(i).ps) : %.native ./$^ -ps -cairo -prefix "ps_cairo_" #With cairo png $(foreach i,$(shell seq 1 $(MAX)), png_cairo_%$(i).png) : %.native ./$^ -png -cairo -prefix "png_cairo_" #With cairo svg $(foreach i,$(shell seq 1 $(MAX)), svg_cairo_%$(i).svg) : %.native ./$^ -svg -cairo -prefix "svg_cairo_" parse.ml: parse.mll ocamllex parse.mll parse: parse.ml ocamlopt.opt -o parse parse.ml #Other html: $(HTMLFILES) %.ml.html : %.ml parse style.css caml2html -css -hc -ext "parse:./parse" $*.ml %.png: %.ps convert $^ $@ %.png: %.pdf convert $^ $@ %.pdf.tex: all.pdf.template sed -e 's/all/$*/' all.pdf.template > $@ %.tex: all.template sed -e 's/all/$*/' all.template > $@ %.ps: %.1 %.tex latex $* dvips -E $*.dvi -o %.pdf: %.mps %.pdf.tex pdflatex $*.pdf.tex mv $*.pdf.pdf $*.pdf # %.pdf: %.mps all.template2 # sed -e 's/all/$*/' all.template2 > $*.tex # pdflatex $* # %.mps: %.1 # cp $*.1 $*.mps ALLTEX:=$(ALL:.png=.tex) $(ALL_MPS:.png=.pdf.tex) clean: rm -f *.aux *.dvi *.ps *.1 *.log $(PNGFILES) *.mp *.mpx *.mps *.pdf rm -f $(ALLTEX) rm -f $(HTML) rm -f parse.ml *.cmx *.cmo *.cmi parse *.o rm -f *.dummy *.dummy_dot *.native *.annot rm -f $(filter-out powered-by-caml.128x58.png,$(wildcard *.png)) editor2 : ocamlbuild editor2.native lattice_lablgtk : lattice_lablgtk.ml $(MLPOST) -contrib lablgtk lattice_lablgtk.ml mlpost-0.8.2/examples/README000066400000000000000000000013621306046515300155420ustar00rootroot00000000000000To compile the examples, issue make Note that this only compiles the images. If you want to have the html files as well, do make html ======Developers notes============= * You need the latest version of caml2html: svn checkout svn://svn.forge.ocamlcore.org/svnroot/caml2html To compile that, you also need camlmix, either by godi, or http://martin.jambon.free.fr/camlmix/ * using (*html, you can put html into the target file * code hiding is done via (*parse. currently supported: <> inserts the javascript code to toggle visibility of an element <> - close the last opened div * you can modify parse.mll if you need more than that mlpost-0.8.2/examples/_tags000066400000000000000000000003411306046515300156760ustar00rootroot00000000000000 : pkg_lablgtk2, pkg_cairo.lablgtk2 : pkg_lablgtk2, pkg_cairo.lablgtk2, pkg_mlpost : pkg_lablgtk2, pkg_cairo.lablgtk2, pkg_mlpost : pkg_mlpost, pkg_mlpost_lablgtkmlpost-0.8.2/examples/all.template000066400000000000000000000003721306046515300171670ustar00rootroot00000000000000\documentclass{article} \usepackage{graphicx} \pagestyle{empty} \usepackage[paperwidth=1000pt, paperheight=2000pt]{geometry} \begin{document} \includegraphics{all.mps} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: mlpost-0.8.2/examples/all.template2000066400000000000000000000003061306046515300172460ustar00rootroot00000000000000\documentclass{article} \usepackage{graphicx} \pagestyle{empty} \begin{document} \includegraphics[scale=3]{all.mps} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: mlpost-0.8.2/examples/animations.ml000066400000000000000000000107171306046515300173620ustar00rootroot00000000000000open Mlpost module P = Path module N = Num open Point let (|>) x f = f x let red dir distmax distmin = let l = dir |> length |> N.minn (N.bp distmax) |> N.maxn (N.bp distmin) in scale l (normalize dir) let little_man ~phead ~plhand ~prhand ~plfoot ~prfoot = let downbody = origin in let upbody = bpp (0.,1.) in let armfac = 0.75 in let body = P.pathp [downbody;upbody] in let dneck = (sub phead upbody) in let neck,head = let red = red dneck 0.75 0.25 in (add (scale (N.bp (0.5/.0.75)) red) upbody ,add red upbody) in let head = P.fullcircle |> P.scale (N.bp 0.5) |> P.shift head in let neck = P.pathp [neck;upbody] in let handbody = scale (N.bp armfac) upbody in let pos anchor dir = (add anchor (red (sub dir anchor) 1. 0.10)) in let hand dir = let c = P.fullcircle |> P.scale (N.bp 0.1) in let p = (pos handbody dir) in (P.shift p c,p) in let lhand,plhand = hand plhand in let rhand,prhand = hand prhand in let foot dir = let c = P.fullcircle |> P.scale (N.bp 0.1) in let p = (pos origin dir) in (P.shift p c,p) in let lfoot,plfoot = foot plfoot in let rfoot,prfoot = foot prfoot in let larm = P.pathp [handbody;plhand] in let rarm = P.pathp [handbody;prhand] in let lleg = P.pathp [origin;plfoot] in let rleg = P.pathp [origin;prfoot] in [ body;head;neck;larm;rarm;lhand;rhand;lfoot;rleg;lleg;rfoot] let rot p i = rotate (360.*.i) p let rot_lit i = (little_man ~phead:(rot (bpp (0.,2.)) i) ~plhand:(rot (bpp (-.2.,1.)) i) ~prhand:(rot (bpp (2.,1.)) i) ~plfoot:(rot (bpp (-.2.,-1.)) i) ~prfoot:(rot (bpp (2.,-1.)) i) |> List.map (P.scale (N.cm 1.)) |> List.map P.draw |> Command.seq) (*let () = List.iter (fun (s,f) -> Metapost.emit s f) ["little_man0", rot_lit 0.; "little_man1", rot_lit 0.1; "little_man2", rot_lit 0.2; "little_man3", rot_lit 0.3; "little_man4", rot_lit 0.4;] *) let _ = GMain.Main.init () let width = ref 400 let height = ref 400 let new_pixmap width height = let drawable = GDraw.pixmap ~width ~height () in drawable#set_foreground `WHITE ; drawable#rectangle ~x:0 ~y:0 ~width ~height ~filled:true () ; drawable let pm = ref (new_pixmap !width !height) let need_update = ref true let init_time = Unix.gettimeofday () let fps = let nb = ref 0 in let time = ref (Unix.time ()) in (fun () -> let time2 = Unix.time () in if time2 -. !time > 1. then (Format.printf "fps : %i@." !nb; nb:=0; time := time2) else incr nb) let paint () = let cr = Cairo_lablgtk.create !pm#pixmap in !pm#rectangle ~x:0 ~y:0 ~width:!width ~height:!height ~filled:true (); let w,h = (float_of_int !width,float_of_int !height) in let i = (Unix.gettimeofday () -. init_time) in let fig = (rot_lit i) in let fig = Picture.shift (ptp (w/.2.,h/.2.)) fig in fps (); Cairost.emit_cairo cr (w,h) fig let refresh da = need_update := true ; GtkBase.Widget.queue_draw da#as_widget let grow_pixmap () = pm := new_pixmap !width !height ; need_update := true (* no need to queue a redraw here, an expose event should follow the configure, right ? *) let config_cb ev = let w = GdkEvent.Configure.width ev in let h = GdkEvent.Configure.height ev in let has_grown = w > !width || h > !height in width := w ; height := h ; if has_grown then grow_pixmap () ; true let expose da x y width height = let gwin = da#misc#window in let d = new GDraw.drawable gwin in d#put_pixmap ~x ~y ~xsrc:x ~ysrc:y ~width ~height !pm#pixmap let expose_cb da ev = let area = GdkEvent.Expose.area ev in let module GR = Gdk.Rectangle in if !need_update then paint () ; expose da (GR.x area) (GR.y area) (GR.width area) (GR.height area) ; refresh da; true let button_ev da ev = match GdkEvent.get_type ev with | `BUTTON_RELEASE -> refresh da;true | _ -> false let init packing = let da = GMisc.drawing_area ~width:!width ~height:!height ~packing () in da#misc#set_can_focus true ; da#event#add [ `KEY_PRESS ; `BUTTON_MOTION ; `BUTTON_PRESS ; `BUTTON_RELEASE ] ; ignore (da#event#connect#expose (expose_cb da)) ; ignore (da#event#connect#configure (config_cb)); ignore (da#event#connect#button_release (button_ev da)) let main = let w = GWindow.window ~title:"Cairo spline demo" ~allow_grow:true ~allow_shrink:true () in ignore (w#connect#destroy GMain.quit) ; init w#add ; w#show () ; GMain.main () mlpost-0.8.2/examples/automata.ml000066400000000000000000000161101306046515300170240ustar00rootroot00000000000000 (* A small library to draw automata. *) open Mlpost open Path open Point open Num open Command open Box (*parse <> *) (* Nodes are boxes (type Box.t), created using functions such as "state" and "final" below. These boxes are given names using the labeled argument ~name, for further reference in transition drawing. Nodes placement is left to the user, and is typically performed using alignment functions such as Box.hbox, Box.vbox or Box.tabularl (see examples below). Given a set of placed nodes, that is a box containing nodes as sub-boxes, function "transition" draws a transition from one node to another, given their names. A label and its position are also given. Optional arguments outd and ind can be used to control the shape of the arrow (when it must not be a straight arrow). Function "loop" is used to draw a self-transition, drawn below a node (it could be easily generalized to draw a loop to the right of the node, etc.). Finally, function "initial" draws an incoming arrow to the left of a node (again, it could be generalized). *) let state = Box.tex ~dx:(bp 4.) ~style:Circle ~stroke:(Some Color.black) let final = Box.box ~style:Circle let transition states tex anchor ?outd ?ind x_name y_name = let x = Box.get x_name states and y = Box.get y_name states in let outd = match outd with None -> None | Some a -> Some (vec (dir a)) in let ind = match ind with None -> None | Some a -> Some (vec (dir a)) in Arrow.draw ~tex ~anchor (cpath ?outd ?ind x y) let loop states tex name = let box = Box.get name states in let a = Point.shift (Box.south box) (Point.pt (cm 0., cm (-0.4))) in let c = Box.ctr box in let p = Path.pathk [ knotp ~r: (vec (dir 225.)) c; knotp a; knotp ~l: (vec (dir 135.)) c; ] in let bp = Box.bpath box in Arrow.draw ~tex ~anchor:`Bot (cut_after bp (cut_before bp p)) let initial states name = let b = Box.get name states in let p = Box.west b in Arrow.draw (Path.pathp [ Point.shift p (Point.pt (cm (-0.3), zero)); p ]) (*** Examples ***************************************************************) (*parse <> *) (*parse <> *) (**** let state name s = rect ~name ~stroke:None (rect (tex ("$" ^ s ^ "$"))) let automata3 = let states = tabularl ~hpadding:(cm 1.) ~vpadding:(cm 1.) [[state "11" "S\\rightarrow E\\bullet"; state "0" "S\\rightarrow\\bullet E"; state "5" "E\\rightarrow\\texttt{int}\\bullet"; ]; [state "1" "E\\rightarrow\\bullet E\\texttt{+}E"; state "3" "E\\rightarrow\\bullet\\texttt{(}E\\texttt{)}"; state "2" "E\\rightarrow\\bullet\\texttt{int}"; ]; [state "4" "E\\rightarrow E\\bullet\\texttt{+}E"; state "7" "E\\rightarrow E\\texttt{+}\\bullet E"; state "6" "E\\rightarrow\\texttt{(}\\bullet E\\texttt{)}"; ]; [state "9" "E\\rightarrow E\\texttt{+}E\\bullet"; state "10" "E\\rightarrow\\texttt{(}E\\texttt{)}\\bullet"; state "8" "E\\rightarrow\\texttt{(}E \\bullet\\texttt{)}"; ] ] in let eps = "$\\epsilon$" in let tt s = "\\texttt{" ^ s ^ "}" in [draw states; transition states "$E$" `Top "0" "11"; transition states eps `Upleft "0" "1"; transition states eps `Upright "0" "2"; transition states eps `Left "0" "3"; loop states eps "1"; transition states "$E$" `Left "1" "4"; transition states eps `Top "1" "3"; transition states eps `Upright ~outd:20. "1" "2"; transition states (tt "+") `Top "4" "7"; transition states eps `Lowleft "7" "1"; transition states eps `Right "7" "2"; transition states eps `Right "7" "3"; transition states "$E$" `Upleft "7" "9"; transition states (tt "int") `Left "2" "5"; transition states (tt "(") ~outd:(-0.) `Top "3" "6"; transition states "$E$" `Left "6" "8"; transition states (tt ")") `Top "8" "10"; transition states eps ~outd:170. `Lowleft "6" "1"; transition states eps `Right "6" "2"; transition states eps ~outd:160. `Top "6" "3"; ] ****) (*parse <> *) let () = Metapost.emit "automata1" (Picture.scale (Num.bp 3.) automata1) let () = Metapost.emit "automata2" (Picture.scale (Num.bp 3.) automata2) let () = Metapost.emit "automata4" (Picture.scale (Num.bp 2.) automata4) mlpost-0.8.2/examples/boxes.ml000066400000000000000000000135731306046515300163430ustar00rootroot00000000000000open Mlpost open Num open Command open Helpers open Path open Point open Color open Box (*parse <> *) (*parse <> <> <> <> <> <) x f = f x let draw_point ?(color=Color.red) t = Point.draw ~pen:(Pen.scale (bp 4.) Pen.default) ~color t (* aligne verticalement le barycentre [(west,5);(east,2)] *) let boxes6 = let two = Num.bp 2. in let five = Num.bp 5. in let tex = tex ~dx:two ~dy:two in let a = tex "recursively enumerable languages" in let b = tex "context sensitive" in let c = tex "context free" in let add_point t = let w = corner `West t in let e = corner `East t in let p = P.mult (one // (two +/ five)) (P.add (P.mult five w) (P.mult two e)) in setp "something" p t in let a = add_point a in let b = add_point b in let c = add_point c in let points = [a;b;c] |> List.map (getp "something") |> List.map draw_point |> Command.seq in (*(*Example de dbuggage quand on a le nouveau backend*) List.iter fun p -> let {Concrete.CPoint.x=x;y=y} = Concrete.cpoint_of_point (getp "something" p) in Format.printf "x = %f; y = %f@." x y) [a;b;c];*) Command.seq [ points; Box.draw (vbox ~pos:(`Custom (getp "something")) [a;b;c])] (*parse >> < Point.add (Point.scale (bp 0.5) (ctr b)) (Point.scale (bp 0.5) (corner `Southeast b)))) ] in Command.seq boxes (*parse >> < 90. && arc < 270. then Box.rotate 180. b else b in let b = Box.center up b in let t = Transform.rotate_around P.origin arc in Box.transform [t] b in let rec aux acc = function | x when x=n -> acc | n -> let a = (float_of_int n)*.arc in let a = mod_float a 360. in aux (turn a (f n)::acc) (n+1) in aux [] 0 let place_circle_ ?auto_inverse r n f = let arc = 360./.(float_of_int n) in place_around ?auto_inverse r arc n f let boxes8 = let yop d i = Box.circle (Box.tex (Printf.sprintf "$%i_{%02d}$" d i)) in let rec aux acc = function | 0 -> acc | i -> let n = (float_of_int (i*10))**0.8 in let r = cm (2.8*.n/.15.) in let n = int_of_float n in aux (Box.draw (Box.group (place_circle_ ~auto_inverse:true r n (yop i)))::acc) (i-1) in Command.seq (aux [] 3) (*parse >> <> *) let () = List.iter (fun (i,fig) -> Metapost.emit ("boxes"^(string_of_int i)) (Picture.scale (Num.bp 3.) fig)) [1,boxes1; 2,boxes2; 3,boxes3; 4,boxes4; 5,boxes5; 6,boxes6; 7,boxes7; 8,boxes8; 9,boxes9] mlpost-0.8.2/examples/cairo_test.ml000066400000000000000000000045351306046515300173550ustar00rootroot00000000000000open Mlpost open Command open Picture open Point open Path module H = Helpers (*parse <> *) (*parse <> <> *) let bp = Num.bp let ribbon = MetaPath.concat ~style:(MetaPath.jControls (pt (bp 310.,bp 300.)) (pt (bp 10.,bp 310.))) (MetaPath.start (knotp (pt (bp 110., bp 20.)))) (MetaPath.knotp (pt (bp 210.,bp 20.))) let ribbon = draw (of_metapath ribbon) let path_test = path ~style:jCurve (z0::z1::z2::[]) let tg p t = draw (pathp ~style:jLine [point t p;add (point t p) (direction t p)]) let test = seq ((draw path_test)::(List.map (tg path_test) [0.;0.264543;0.5;0.785651;1.;1.3528;1.5;1.8653;2.;])) let some_cut = let p = Point.p (10.,10.) in let p1 = path [0., 0.; 50.,50.] in let p2 = path [0., 50.; 50.,0.] in let p3 = cut_after p1 p2 in seq [ draw p1; draw p3; draw (Path.shift p p2) ] let w0 = 0.,0. let w1 = -50.,50. let w2 = 0.,100. let w3 = 50.,50. let labels2 = seq [H.dotlabels ~pos:`Top ["0";"2"] (map_bp [w0;w2]); dotlabel ~pos:`Left (tex "3") (bpp w3); dotlabel ~pos:`Right (tex "1") (bpp w1) ] (*let circle = seq [ draw (MetaPath.cycle ~style:jCurve (MetaPath.path ~style:jCurve (w0::w1::w2::w3::[])));labels2]*) let circle = seq [draw (Path.scale (bp 100.) Path.halfcircle);draw (Path.scale (bp 50.) Path.quartercircle)] let to_export = [ "other27", other27; "handbook3", handbook3; "ribbon", ribbon; "test", test; "circle", circle; "somecut", some_cut; ] let _ = List.iter (fun (name,fig) -> Metapost.emit name fig) to_export mlpost-0.8.2/examples/color.ml000066400000000000000000000020031306046515300163230ustar00rootroot00000000000000open Mlpost module P = Path module C = Color (*parse <> *) (*parse < let c = C.hsv ((foi fnbh h)*.360.) s (foi fnbv v) in square c)) let color1 = hsv_grid 10 10 0. (*parse >> <> <> < square (gc ()))) (*parse >> *) let () = List.iter (fun (name,fig) -> Metapost.emit name (Picture.scale (Num.bp 2.) fig)) ["color1",color1; "color2",color2; "color3",color3; "color4",color_gen_line 10] mlpost-0.8.2/examples/concrete.ml000066400000000000000000000025761306046515300170260ustar00rootroot00000000000000open Mlpost open Command module Pi = Picture module Po = Point module Pa = Path module Cn = Concrete let a = -50., -12.5 let b = -12.5, -50. let c = 50., -12.5 let d = -12.5, 50. let e = 50., 12.5 let f = 12.5, 50. let g = -50., 12.5 let h = 12.5, -50. let for_joint joint = let l1 = Pa.path ~style:joint [a; c; e; g] in let l2 = Pa.path ~style:joint [b; d; f; h] in (l1,l2) let fig1 (l1,l2) = seq [draw l1;draw l2] let fig2 ((l1,l2) as arg) = let cl1 = Cn.cpath_of_path l1 in let cl2 = Cn.cpath_of_path l2 in let inter = Cn.CPath.intersection cl1 cl2 in let inter1,inter2 = List.split inter in let inter1 = List.map (Cn.CPath.point_of_abscissa cl1) inter1 in let inter2 = List.map (Cn.CPath.point_of_abscissa cl2) inter2 in let inter = inter1@inter2 in let inter = List.map Cn.point_of_cpoint inter in let draw_a_point c = draw ~pen:(Pen.scale (Num.bp 4.) Pen.default) ~color:Color.red (Pa.pathp [c]) in let inter = List.map draw_a_point inter in let label = label ~pos:`Center (Pi.tex (Format.sprintf "%i intersections" (List.length inter1))) Po.origin in seq ((fig1 arg)::label::inter) let _ = List.iter (fun (f,n) -> Metapost.emit n f) [fig2 (for_joint Pa.jLine),"jLine"; fig2 (for_joint Pa.jCurve),"jCurve"] let _ = Cairost.emit_svg "concrete.svg" (fig2 (for_joint Pa.jCurve)) let _ = Cairost.emit_ps "concrete.ps" (fig2 (for_joint Pa.jCurve)) mlpost-0.8.2/examples/dot_dot.ml000066400000000000000000000021551306046515300166510ustar00rootroot00000000000000(* mlpost -contrib dot dot.ml *) open Mlpost open Mlpost_dot module Pi = Picture open Command (*parse <> *) (*parse <> <> *) let () = List.iter (fun (n,f) -> Metapost.emit n f) ["dot_dot1",dot1; "dot_dot2",dot2] mlpost-0.8.2/examples/editor2.ml000066400000000000000000000155071306046515300165720ustar00rootroot00000000000000(**************************************************************************) (* Lablgtk - Examples *) (* *) (* There is no specific licensing policy, but you may freely *) (* take inspiration from the code, and copy parts of it in your *) (* application. *) (* *) (**************************************************************************) (* $Id: editor2.ml 1347 2007-06-20 07:40:34Z guesdon $ *) open StdLabels let _ = GMain.Main.init () let file_dialog ~title ~callback ?filename () = let sel = GWindow.file_selection ~title ~modal:true ?filename () in ignore(sel#cancel_button#connect#clicked ~callback:sel#destroy); ignore(sel#ok_button#connect#clicked ~callback: begin fun () -> let name = sel#filename in sel#destroy (); callback name end); sel#show () let input_channel b ic = let buf = String.create 1024 and len = ref 0 in while len := input ic buf 0 1024; !len > 0 do Buffer.add_substring b buf 0 !len done let with_file name ~f = let ic = open_in name in try f ic; close_in ic with exn -> close_in ic; raise exn class editor ?packing ?show () = object (self) val text = GText.view ?packing ?show () val mutable filename = None method text = text method load_file name = try let b = Buffer.create 1024 in with_file name ~f:(input_channel b); let s = Glib.Convert.locale_to_utf8 (Buffer.contents b) in let n_buff = GText.buffer ~text:s () in text#set_buffer n_buff; filename <- Some name; n_buff#place_cursor n_buff#start_iter with _ -> prerr_endline "Load failed" method open_file () = file_dialog ~title:"Open" ~callback:self#load_file () method save_dialog () = file_dialog ~title:"Save" ?filename ~callback:(fun file -> self#output ~file) () method save_file () = match filename with Some file -> self#output ~file | None -> self#save_dialog () method output ~file = try if Sys.file_exists file then Sys.rename file (file ^ "~"); let s = text#buffer#get_text () in let oc = open_out file in output_string oc (Glib.Convert.locale_from_utf8 s); close_out oc; filename <- Some file with _ -> prerr_endline "Save failed" method get_text () = text#buffer#get_text () end let window = GWindow.window ~width:500 ~height:300 ~title:"editor" () let vbox = GPack.vbox ~packing:window#add () let menubar = GMenu.menu_bar ~packing:vbox#pack () let factory = new GMenu.factory ~accel_path:"/" menubar let accel_group = factory#accel_group let file_menu = factory#add_submenu "File" let edit_menu = factory#add_submenu "Edit" let scrollwin = GBin.scrolled_window ~packing:vbox#add () let editor = new editor ~packing:scrollwin#add () open Mlpost let fig () = let fig = Box.tex (editor#get_text ()) in let fig = Box.center Point.origin fig in let fig = Box.scale (Num.bp 2.) fig in Box.draw fig let width = 400 let height = 500 let window2 = GWindow.window ~width ~height ~title:"view" () let () = ignore(window2#connect#destroy ~callback:GMain.quit); ignore(window2#show ()) let new_pixmap width height = let drawable = GDraw.pixmap ~width ~height () in drawable#set_foreground `WHITE ; drawable#rectangle ~x:0 ~y:0 ~width ~height ~filled:true () ; drawable let pm = ref (new_pixmap width height) let need_update = ref true let paint () = try let w,h = (float_of_int width,float_of_int height) in let fig = Picture.shift (Point.ptp (w/.2.,h/.2.)) (fig ()) in let _ = Mlpost.Concrete.float_of_num (Picture.width fig) in let cr = Cairo_lablgtk.create !pm#pixmap in !pm#rectangle ~x:0 ~y:0 ~width ~height ~filled:true (); Cairost.emit_cairo cr (w,h) fig with _ -> () let refresh da = need_update := true ; GtkBase.Widget.queue_draw da#as_widget let expose da x y width height = let gwin = da#misc#window in let d = new GDraw.drawable gwin in d#put_pixmap ~x ~y ~xsrc:x ~ysrc:y ~width ~height !pm#pixmap let expose_cb da ev = let area = GdkEvent.Expose.area ev in let module GR = Gdk.Rectangle in if !need_update (*&& editor#text#buffer#modified*) then paint (); expose da (GR.x area) (GR.y area) (GR.width area) (GR.height area); need_update := false; true let button_ev da ev = match GdkEvent.get_type ev with | `BUTTON_RELEASE -> refresh da;true | _ -> false let init packing = let da = GMisc.drawing_area ~width ~height ~packing () in da#misc#set_can_focus true ; ignore (da#event#connect#expose (expose_cb da)); da#event#add [ `BUTTON_RELEASE ] ; ignore (da#event#connect#button_release (button_ev da)); ignore (editor#text#buffer#connect#changed ~callback:(fun _ -> refresh da)); da let dda = let dda = init window2#add in window2#show (); dda (** Editor window *) open GdkKeysyms let _ = ignore(window#connect#destroy ~callback:GMain.quit); let factory = new GMenu.factory ~accel_path:"/////" file_menu ~accel_group in ignore(factory#add_item "Open" ~key:_O ~callback:editor#open_file); ignore(factory#add_item "Save" ~key:_S ~callback:editor#save_file); ignore(factory#add_item "Save as..." ~callback:editor#save_dialog); ignore(factory#add_separator ()); ignore(factory#add_item "Quit" ~key:_Q ~callback:window#destroy); let factory = new GMenu.factory ~accel_path:"///" edit_menu ~accel_group in ignore(factory#add_item "Copy" ~key:_C ~callback: (fun () -> editor#text#buffer#copy_clipboard GMain.clipboard)); ignore(factory#add_item "Cut" ~key:_X ~callback: (fun () -> GtkSignal.emit_unit editor#text#as_view GtkText.View.S.cut_clipboard)); ignore(factory#add_item "Paste" ~key:_V ~callback: (fun () -> GtkSignal.emit_unit editor#text#as_view GtkText.View.S.paste_clipboard)); ignore(factory#add_separator ()); ignore(factory#add_check_item "Word wrap" ~active:false ~callback: (fun b -> editor#text#set_wrap_mode (if b then `WORD else `NONE))); ignore(factory#add_check_item "Read only" ~active:false ~callback:(fun b -> editor#text#set_editable (not b))); ignore(factory#add_item "Save accels" ~callback:(fun () -> GtkData.AccelMap.save "test.accel")); ignore(factory#add_item "Refresh" ~callback:(fun () -> refresh dda)); ignore(window#add_accel_group accel_group); ignore(editor#text#event#connect#button_press ~callback:(fun ev -> let button = GdkEvent.Button.button ev in if button = 3 then begin file_menu#popup ~button ~time:(GdkEvent.Button.time ev); true end else false)); ignore(window#show ()); let () = GtkData.AccelMap.load "test.accel" in GMain.main () mlpost-0.8.2/examples/hist.ml000066400000000000000000000034301306046515300161610ustar00rootroot00000000000000open Mlpost open Num open Color open Box (*parse <> *) (*parse <> <> <> <> <> <> <> <> <> <> *) let _ = List.iter (fun (name,fig) -> Metapost.emit name fig) [ "hist1", hist1; "hist2", hist2; "hist3", hist3; "hist4", hist4; "hist5", hist5; "hist6", hist6; "hist7", hist7; "hist8", hist8; "hist9", hist9; "hist10", hist10; ] mlpost-0.8.2/examples/include.ml000066400000000000000000000017541306046515300166440ustar00rootroot00000000000000open Mlpost open Command (*parse <> *) (*parse <> *) (*parse <> <> *) let () = List.iter (fun (i,fig) -> Metapost.emit ("include"^(string_of_int i)) fig) [1,include1; 2,include2; 3,include3] mlpost-0.8.2/examples/index.html000066400000000000000000000015221306046515300166550ustar00rootroot00000000000000 Mlpost Examples Section

Mlpost Examples Section

Boxes

Paths

Trees

Labels

Automata

Terms

Color

Radars

Function plot

Other and more complex examples

Include png pictures

Contributions

Mlpost_dot contrib

mlpost-0.8.2/examples/label.ml000066400000000000000000000017741306046515300163020ustar00rootroot00000000000000open Mlpost open Command open Picture open Point open Path module H = Helpers (*parse <> *) (*parse <> <> *) let _ = List.iter (fun (name,fig) -> Metapost.emit name (Picture.scale (Num.bp 3.) fig)) [ "label1", label1; "label2", label2; ] mlpost-0.8.2/examples/lattice_lablgtk.ml000066400000000000000000000053351306046515300203450ustar00rootroot00000000000000open Mlpost open Command open Picture open Path open Num open Num.Infix open Helpers (** Copy from misc.ml!!! *) (* type of Box lattice *) type node = N of Box.t * node list (* a node and its successors *) type lattice = node list list (* nodes lines, from top to bottom *) (* drawing *) let dx = bp 12. let dy = bp 12. module H = Hashtbl.Make(struct type t = Box.t let hash b = Hashtbl.hash b let equal = (==) end) let nodes = H.create 97 let draw la = let line l = Box.hbox ~padding:dx (List.map (function (N (b,_)) -> b) l) in let to_list b = Array.to_list (Box.elts b) in let to_list2 b = List.map to_list (to_list b) in let la' = Box.vbox ~padding:dy (List.map line la) in List.iter2 (List.iter2 (fun (N (b, _)) b' -> H.add nodes b b')) la (to_list2 la'); let box b = H.find nodes b in let draw_node (N (b,l)) = let b = box b in Box.draw b ++ iterl (fun (N(s,_)) -> box_arrow b (box s)) l in iterl (iterl draw_node) la (* example: the subwords lattice *) let node s l = let s = if s = "" then "$\\varepsilon$" else s in let s = "\\rule[-0.1em]{0in}{0.8em}" ^ s in N (Box.circle (Box.tex s), l) (* folds over the bits of an integer (as powers of two) *) let fold_bit f = let rec fold acc n = if n = 0 then acc else let b = n land (-n) in fold (f acc b) (n - b) in fold (* the bits in [n] indicate the selected characters of [s] *) let subword s n = let len = fold_bit (fun l _ -> l+1) 0 n in let w = String.create len in let j = ref 0 in for i = 0 to String.length s - 1 do if n land (1 lsl i) != 0 then begin w.[!j] <- s.[i]; incr j end done; w (* builds the lattice of [s]'s subwords *) let subwords s = let n = String.length s in let levels = Array.create (n+1) [] in let memo = Hashtbl.create 97 in let rec make_node lvl x = try Hashtbl.find memo x with Not_found -> let n = node (subword s x) (fold_bit (fun l b -> make_node (lvl - 1) (x - b) :: l) [] x) in Hashtbl.add memo x n; levels.(lvl) <- n :: levels.(lvl); n in let _ = make_node n (lnot ((-1) lsl n)) in Array.to_list levels let lattice s = draw (subwords s) (** End of the copy *) open Mlpost_lablgtk module L = Mlpost_lablgtk.Interface let _ = GMain.Main.init () let word = ref "abcd" let int = L.new_interface () let () = L.create_text int ~label:"lattice of subwords of" !word ((:=) word) let aa ~width ~height _ = let p = Point.pt (Num.divf width 2.,Num.divf height 2.) in [Transform.shifted p] let aa2 ~width ~height pic = let p = Point.pt (Num.divf width 2.,Num.divf height 2.) in [Transform.shifted (Point.sub p (Picture.ctr pic))] let () = L.add_pic ~auto_aspect:aa_fit_page int (fun () -> lattice !word) let () = L.main int mlpost-0.8.2/examples/misc.ml000066400000000000000000000515751306046515300161620ustar00rootroot00000000000000open Mlpost open Command open Picture open Path open Num open Num.Infix open Helpers (*parse <> *) (*parse < iter 0 (h-1) (f i)); iter 0 w (fun i -> draw ~pen (pathn [p i 0; p i h])); iter 0 h (fun j -> draw ~pen (pathn [p 0 j; p w j]))] let misc1 = let d = 10. in let p i j = bp (float i *. d), bp (float j *. d) in let p2 i j = bp ((0.5 +. float i) *. d), bp ((0.5 +. float j) *. d) in let pic q i j = draw_pic (Picture.center (Point.pt (p2 i j)) q) in let cell i j = if j = bresenham_data.(i) then let sq = Path.scale (bp d) unitsquare in let sq = shift (Point.pt (p i j)) sq in fill ~color:Color.red sq else seq [] in seq [grid (x2+1) (y2+1) d cell; pic (tex "0") 0 (-1); pic (tex "0") (-1) 0; pic (tex "$x_2$") x2 (-1); pic (tex "$y_2$") (-1) y2; ] (*parse >> *) open Diag (*parse < iter 0 (h-1) (f i)); iter 0 w (fun i -> Command.draw ~pen (pathn [p i 0; p i h])); iter 0 h (fun j -> Command.draw ~pen (pathn [p 0 j; p w j]))] let bq = tex "\\font\\Chess=chess10 {\\Chess q}" let question = tex "?" let misc3 = let d = 15. in let p i j = bp (float i *. d), bp (float j *. d) in let p2 i j = bp ((0.5 +. float i) *. d), bp ((0.5 +. float j) *. d) in let pic q i j = draw_pic (Picture.center (Point.pt (p2 i j)) q) in let cell i j = let l = if (i+j) mod 2 = 1 then let sq = Path.scale (bp d) unitsquare in let sq = shift (Point.pt (p i j)) sq in [fill ~color:(Color.gray 0.7) sq] else [] in seq (if i = 4 && j = 7 || i = 3 && j = 5 || i = 6 && j = 6 then l @ [pic bq i j] else if j = 4 then l @ [pic question i j] else l) in grid 8 8 d cell *) (*parse >> < Array.init 4 (fun j -> node (foi i) (foi j) (Box.empty ~width:(bp 4.) ()))) (* (Printf.sprintf "(%d,%d)" i j))) *) let nodesl = List.flatten (List.map Array.to_list (Array.to_list nodes)) let diag = create nodesl let add = arrow diag ~head:false let edges = for i = 0 to 5 do for j = 0 to 3 do (try (add ~outd:(Angle 45.) nodes.(i).(j) nodes.(i+1).(j+1)) with _ -> ()); (try (add ~outd:(Angle 135.) nodes.(i).(j) nodes.(i-1).(j+1)) with _ -> ()); (try (add ~outd:Up nodes.(i).(j) nodes.(i).(j+1)) with _ -> ()); done done let graph = draw ~fill:(Color.gray 0.8) ~style:(Box.circle ~dx:(Num.bp 6.) ~dy:(Num.bp 6.)) diag let misc4 = draw_pic (Picture.scale (bp 0.5) (Picture.make graph)) (*parse >> < Array.init 4 (fun j -> (node (foi i) (foi j) (Box.empty ~width:(bp 4.) ()), i, j))) (* (Printf.sprintf "(%d,%d)" i j), i, j))) *) let nodesl = List.fold_left (fun acc (n,i,j) -> if (i+j) mod 2 = 0 then n::acc else acc) [] (List.flatten (List.map Array.to_list (Array.to_list nodes))) let diag = create nodesl let node i j = let (n, _, _) = nodes.(i).(j) in n let add = arrow diag ~head:false let edges = for i = 0 to 5 do for j = 0 to 3 do if (i + j) mod 2 = 0 then begin (try (add ~outd:(Angle 165.) (node i j) (node (i-3) (j+1))) with _ -> ()); (try (add ~outd:(Angle 135.) (node i j) (node (i-1) (j+1))) with _ -> ()); (try (add ~outd:(Angle 45.) (node i j) (node (i+1) (j+1))) with _ -> ()); (try (add ~outd:(Angle 15.) (node i j) (node (i+3) (j+1))) with _ -> ()); end done done let graph = draw ~fill:(Color.gray 0.8) ~style:(Box.circle ~dx:(Num.bp 6.) ~dy:(Num.bp 6.)) diag let misc5 = draw_pic (Picture.scale (bp 0.5) (Picture.make graph)) (*parse >> <> < failwith "No empty list allowed" | [x] -> x | (x::xs) -> append ~style x (fold_append xs) let s = 0.004 let xs1 = 48. let xs2 = 25. let ys = 19. let add (a1,a2) (b1,b2) = (a1 +. b1 , a2 +. b2) let mult f (a1,a2) = (f *. a1, f *. a2) let myscale = List.map (mult s) let misc7 = let pen1 = Pen.circle in let mygreen = Color.rgb 0.8 0.9 0.8 in let p1 = ( 750.,8000. -. 4950. ) in let p2 = (1050.,8000. -. 4950. ) in let p3 = (2100.,8000. -. 4800. ) in let p4 = (2925.,8000. -. 4650. ) in let p5 = (4050.,8000. -. 5100. ) in let p6 = (4050.,8000. -. 5550. ) in let p7 = (3750.,8000. -. 6075. ) in let p8 = (3150.,8000. -. 6900. ) in let p9 = (3075.,8000. -. 7500. ) in let p10 = (3525.,8000. -. 7950. ) in let p11 = (4275.,8000. -. 8775. ) in let p12 = (5400.,8000. -. 9300. ) in let p13 = (4725.,8000. -. 8550. ) in let p14 = (4275.,8000. -. 7725. ) in let p15 = (4875.,8000. -. 8325. ) in let p16 = (5550.,8000. -. 8700. ) in let p17 = (5100.,8000. -. 7950. ) in let p18 = (4800.,8000. -. 7125. ) in let p19 = (5400.,8000. -. 7725. ) in let p20 = (6150.,8000. -. 8100. ) in let p21 = (5550.,8000. -. 7275. ) in let p22 = (5250.,8000. -. 6375. ) in let p23 = (5850.,8000. -. 7050. ) in let p24 = (6600.,8000. -. 7500. ) in let p25 = (6075.,8000. -. 6675. ) in let p26 = (5700.,8000. -. 5775. ) in let p27 = (6975.,8000. -. 7125. ) in let p28 = (8625.,8000. -. 7950. ) in let p29 = (7875.,8000. -. 7350. ) in let p30 = (7275.,8000. -. 6750. ) in let p31 = (8175.,8000. -. 7200. ) in let p32 = (9150.,8000. -. 7425. ) in let p33 = (8325.,8000. -. 6975. ) in let p34 = (7725.,8000. -. 6375. ) in let p35 = (8550.,8000. -. 6750. ) in let p36 = (9525.,8000. -. 6825. ) in let p37 = (8625.,8000. -. 6450. ) in let p38 = (8100.,8000. -. 6000. ) in let p39 = (9000.,8000. -. 6300. ) in let p40 = (9975.,8000. -. 6300. ) in let p41 = (9075.,8000. -. 6000. ) in let p42 = (8400.,8000. -. 5550. ) in let p43 = (9525.,8000. -. 5925. ) in let p44 = (10425.,8000.-. 5925. ) in let p45 = (9300.,8000. -. 5550. ) in let p46 = (8250.,8000. -. 5100. ) in let p47 = (7275.,8000. -. 4875. ) in let p48 = (6300.,8000. -. 4800. ) in let p49 = (7275.,8000. -. 4500. ) in let p50 = (8400.,8000. -. 4500. ) in let p51 = (7500.,8000. -. 4050. ) in let p52 = (6825.,8000. -. 3900. ) in let p53 = (7800.,8000. -. 3825. ) in let p54 = (8700.,8000. -. 3975. ) in let p55 = (7875.,8000. -. 3375. ) in let p56 = (7050.,8000. -. 3075. ) in let p57 = (8175.,8000. -. 3150. ) in let p58 = (8925.,8000. -. 3450. ) in let p59 = (8175.,8000. -. 2775. ) in let p60 = (7350.,8000. -. 2400. ) in let p61 = (8250.,8000. -. 2475. ) in let p62 = (9225.,8000. -. 3000. ) in let p63 = (8850.,8000. -. 2100. ) in let p64 = (8400.,8000. -. 1650. ) in let p66 = (8100.,8000. -. 1875. ) in let p67 = (7200.,8000. -. 1575. ) in let p68 = (5850.,8000. -. 1500. ) in let p69 = (5625.,8000. -. 2025. ) in let p70 = (5475.,8000. -. 2400. ) in let p71 = (5100.,8000. -. 3000. ) in let p72 = (4650.,8000. -. 3750. ) in let p73 = (3525.,8000. -. 3450. ) in let p74 = (2550.,8000. -. 3075. ) in let p75 = (2325.,8000. -. 3375. ) in let p76 = (2100.,8000. -. 3600. ) in let p77 = (1425.,8000. -. 4050. ) in let p78 = ( 975.,8000. -. 4350. ) in let p79 = ( 525.,8000. -. 4875. ) in let p80 = (1840.,8000. -. 4600. ) in let p81 = (2375.,8000. -. 4550. ) in let line1 = path (myscale [p79;p1;p2;p3;p4;p5]) in let line2 = fold_append ~style:jLine (List.map (fun l -> path (myscale l) ) [ [p9;p10;p11;p12] ; [p12; p13; p14] ; [p14; p15; p16] ; [p16; p17; p18] ; [p18; p19; p20] ; [p20; p21; p22] ; [p22; p23; p24] ; [p24; p25; p26] ; [p26; p27; p28] ; [p28; p29; p30] ; [p30; p31; p32] ; [p32; p33; p34] ; [p34; p35; p36] ; [p36; p37; p38] ; [p38; p39; p40] ; [p40; p41; p42] ; [p42; p43; p44] ; [p44; p45; p46] ; [p46; p47; p48] ; [p48; p49; p50] ; [p50; p51; p52] ; [p52; p53; p54] ; [p54; p55; p56] ; [p56; p57; p58] ; [p58; p59; p60] ; [p60; p61; p62] ; [p62; p66; p67; p68 ] ]) in let line3 = path (myscale [p62; p63; p64 ]) in let line4 = path (myscale [p72; p73; p74 ]) in let line5 = path (myscale [p79; p80; p81]) in let line6 = path (myscale [p6; p6; p7; p8; p9 ]) in let line7 = path (myscale [p74; p75; p76; p77; p78; p78; p79]) in let line8 = path (myscale [p68; p69; p70; p71; p72]) in let bird = cycle ~style:jLine (fold_append ~style:jLine [line1 ; line6; line2; line8; line4; line7]) in Command.iter (-1) 1 (fun x -> Command.iter (-1) 1 (fun y -> let xf, yf = float_of_int x, float_of_int y in let offset = (xf *. xs1 +. yf *. xs2, yf *. ys) in let offset2 = ( (xf +. 1.) *. xs1 +. (yf -. 1.) *. xs2, (yf -. 1.) *. ys ) in let tr p = Path.shift (bpp offset) p in let mypath po = let offset = add offset2 po in Path.shift (bpp offset) Path.fullcircle in seq ([ fill ~color:Color.red (mypath (-12.,27.)); Command.draw ~color:Color.blue (mypath (-12.,27.))] @ [ fill ~color:mygreen (tr bird)] @ List.map (fun p -> Command.draw ~pen:pen1 (tr p)) [line1;line2;line3;line4;line5] @ List.map (fun p -> Command.draw ~pen:pen1 (tr p)) [line6; line7; line8] ) ) ) (*parse >> < b) l) in let to_list b = Array.to_list (Box.elts b) in let to_list2 b = List.map to_list (to_list b) in let la' = Box.vbox ~padding:dy (List.map line la) in List.iter2 (List.iter2 (fun (N (b, _)) b' -> H.add nodes b b')) la (to_list2 la'); let box b = H.find nodes b in let draw_node (N (b,l)) = let b = box b in Box.draw b ++ iterl (fun (N(s,_)) -> box_arrow b (box s)) l in iterl (iterl draw_node) la (* example: the subwords lattice *) let node s l = let s = if s = "" then "$\\varepsilon$" else s in let s = "\\rule[-0.1em]{0in}{0.8em}" ^ s in N (Box.circle (Box.tex s), l) (* folds over the bits of an integer (as powers of two) *) let fold_bit f = let rec fold acc n = if n = 0 then acc else let b = n land (-n) in fold (f acc b) (n - b) in fold (* the bits in [n] indicate the selected characters of [s] *) let subword s n = let len = fold_bit (fun l _ -> l+1) 0 n in let w = String.create len in let j = ref 0 in for i = 0 to String.length s - 1 do if n land (1 lsl i) != 0 then begin w.[!j] <- s.[i]; incr j end done; w (* builds the lattice of [s]'s subwords *) let subwords s = let n = String.length s in let levels = Array.create (n+1) [] in let memo = Hashtbl.create 97 in let rec make_node lvl x = try Hashtbl.find memo x with Not_found -> let n = node (subword s x) (fold_bit (fun l b -> make_node (lvl - 1) (x - b) :: l) [] x) in Hashtbl.add memo x n; levels.(lvl) <- n :: levels.(lvl); n in let _ = make_node n (lnot ((-1) lsl n)) in Array.to_list levels let misc8 = draw (subwords "abcd") (*parse >> < 0 then match t with | One -> let d = Point.segment r0 a c in seq [pave One b c d (n-1); pave Four b d a (n-1) ] | Two -> let d = Point.segment r0 a b in seq [ pave Two c d b (n-1) ; pave Three c a d (n-1) ] | Three -> let d = Point.segment r1 a b in let e = Point.segment r0 a c in seq [ pave One d c e (n-1) ; pave Three b c d (n-1); pave Four d e a (n-1)] | Four -> let d = Point.segment r1 a c in let e = Point.segment r0 a b in seq [ pave Two d e b (n-1) ; pave Three d a e (n-1); pave Four c d b (n-1)] else let pen = Pen.circle in let gb = Color.rgb 0. 1. 1. in let gr = Color.rgb 1. 1. 0. in let path = pathp ~style:jLine ~cycle:jLine [a;b;c] in let color, segs = match t with | One -> gb, [a;c]::[a;b]::[] | Two -> gb, [a;b]::[a;b]::[] | Three -> gr, [a;c]::[c;b]::[] | Four -> gr, [b;c]::[a;b]::[] in seq [Command.draw path; fill path ~color; seq (List.map (fun l -> Command.draw ~pen (pathp ~style:jLine l)) segs) ] let misc9 = let a = cmp (0., 0.) in let b = cmp (3., 0.) in let d = Point.rotate 72. b in let c = Point.add d (cmp (3.,0.)) in seq [pave Three a c d 6; pave Four a b c 6] (* (*>> <> <> < proj i 0 j) let up = square Color.yellow (fun i j -> proj i j 3) let left = square Color.green (fun i j -> proj 0 (3 - i) j) let misc12 = seq [iter 0 2 (fun i -> iter 0 2 (right i)); iter 0 2 (fun i -> iter 0 2 (up i)); iter 0 2 (fun i -> iter 0 2 (left i));] (*parse >> <> <> *) let () = List.iter (fun (i,fig) -> Metapost.emit ("misc"^(string_of_int i)) (Picture.scale (Num.bp 3.) fig)) [1,misc1; 2,misc2; (* 3,misc3; chess10 can't be used by cairo*) 4,misc4; 5,misc5; 6,misc6; 7,misc7; 8,misc8; 9,misc9; (* 10,misc10; Pen.square is not implemented *) 11,misc11; 12,misc12; 13,misc13; 14,misc14] mlpost-0.8.2/examples/myocamlbuild.ml000066400000000000000000000071231306046515300176760ustar00rootroot00000000000000open Ocamlbuild_plugin (* open Command -- no longer needed for OCaml >= 3.10.2 *) (* these functions are not really officially exported *) let run_and_read = Ocamlbuild_pack.My_unix.run_and_read let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings let split s ch = let x = ref [] in let rec go s = let pos = String.index s ch in x := (String.before s pos)::!x; go (String.after s (pos + 1)) in try go s with Not_found -> !x let split_nl s = split s '\n' let before_space s = try String.before s (String.index s ' ') with Not_found -> s (* this lists all supported packages *) let find_packages () = List.map before_space (split_nl & run_and_read "ocamlfind list") (* this is supposed to list available syntaxes, but I don't know how to do it. *) let find_syntaxes () = ["camlp4o"; "camlp4r"] (* ocamlfind command *) let ocamlfind x = S[A"ocamlfind"; x] let _ = dispatch begin function | Before_options -> (* by using Before_options one let command line options have an higher priority *) (* on the contrary using After_options will guarantee to have the higher priority *) (* override default commands by ocamlfind ones *) Options.ocamlc := ocamlfind & A"ocamlc"; Options.ocamlopt := ocamlfind & A"ocamlopt"; Options.ocamldep := ocamlfind & A"ocamldep"; Options.ocamldoc := ocamlfind & A"ocamldoc"; Options.ocamlmktop := ocamlfind & A"ocamlmktop" | After_rules -> (* When one link an OCaml library/binary/package, one should use -linkpkg *) flag ["ocaml"; "link"] & A"-linkpkg"; (* For each ocamlfind package one inject the -package option when * compiling, computing dependencies, generating documentation and * linking. *) List.iter begin fun pkg -> flag ["ocaml"; "compile"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "doc"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "link"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "infer_interface"; "pkg_"^pkg] & S[A"-package"; A pkg]; end (find_packages ()); (* Like -package but for extensions syntax. Morover -syntax is useless * when linking. *) List.iter begin fun syntax -> flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "infer_interface"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; end (find_syntaxes ()); (* The default "thread" tag is not compatible with ocamlfind. Indeed, the default rules add the "threads.cma" or "threads.cmxa" options when using this tag. When using the "-linkpkg" option with ocamlfind, this module will then be added twice on the command line. To solve this, one approach is to add the "-thread" option when using the "threads" package using the previous plugin. *) flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "infer_interface"] (S[A "-thread"]) | _ -> () end mlpost-0.8.2/examples/parse.mll000066400000000000000000000056371306046515300165130ustar00rootroot00000000000000{ open Lexing let togglescript = " hide mpost show cairo png show mps show cairo ps show cairo pdf show cairo svg " } let alpha_lower = ['a'-'z' ] let alpha_upper = ['A'-'Z'] let alpha = ['a' - 'z' 'A'-'Z'] let digit = ['0'-'9'] let identifier = alpha_lower (alpha | digit | '\'' | '_')* let blank = [' ' '\t' '\n' '\r' ] rule scan = parse | "<>" { Printf.printf "%s" togglescript; scan lexbuf } | ">>" { Printf.printf "


"; scan lexbuf } | "<<" (identifier as i) { Printf.printf "
\
" i; Printf.printf "
\
" i; Printf.printf "
\
" i; Printf.printf "
\
" i; Printf.printf "
\
" i; Printf.printf "
\ \
" i; Printf.printf "
"; Printf.printf "" i; Printf.printf "show/hide code"; Printf.printf "
"; Printf.printf "
" i; Printf.printf "

"; scan lexbuf } | blank { scan lexbuf } | eof { Printf.printf "%!" } { let _ = let buf = Lexing.from_channel stdin in scan buf } mlpost-0.8.2/examples/paths.ml000066400000000000000000000103041306046515300163270ustar00rootroot00000000000000open Mlpost open Point open Path open Command open Dash (*parse <> *) let l = [0.,0.; 1., 0.; 0., 1.] (*parse <> <> <> <> < draw ~pen (path ~scale:Num.cm [a])) [a;b;c]) ] (*parse >> *) let a = cmp (0., 0.) let b = cmp (1., 0.) let c = cmp (0., 1.) (*html


*) (*parse <> <> <> < draw ~pen ~color (pathp ~style:jLine [a;b])) [a,b;b,c;c,a] cl) (*parse >> <> <> *) let triangle = path ~scale:Num.cm ~style:jLine ~cycle:jLine l (*html
*) (*parse <> <> *) let pen = Pen.scale (Num.bp 2.) Pen.circle (*html
*) (*parse <> <> < dotlabel ~pos (Picture.tex l) (Path.point i p)) [`Bot, "0", 0.; `Upleft, "1", 1. ; `Lowleft, "2", 2. ; `Top, "3", 3. ; `Left, "4", 4. ]); draw ~pen (subpath 1.3 3.2 p)] (*parse >> <> *) let _ = List.iter (fun (name,fig) -> Metapost.emit name (Picture.scale (Num.bp 3.) fig)) [ "paths1", paths1 ; "paths2", paths2; "paths3", paths3; "paths4", paths4; "paths5", paths5; "paths6", paths6; "paths7", paths7; "paths8", paths8; "paths9", paths9; "paths10", paths10; "paths11", paths11; "paths12", paths12; "paths13", paths13; "paths14", paths14; "paths15", paths15; "paths16", paths16; "paths17", paths17; ] mlpost-0.8.2/examples/powered-by-caml.128x58.png000066400000000000000000000061251306046515300212370ustar00rootroot00000000000000PNG  IHDR:OPLTEffffggjjnnppssuuwwxxzz}}dd^^\\NNffeeddccbbaa``^^]]\\[[ZZYYWWVVUUTTSSRRNNKKJJIIHHFFFFDDDDCCAA4hhggbbPPe33KKy>>g55kkjjY..``a33mmZZWWeeooppUUrr@##tto>>mmhhvvMMwwyy||RR||ppՀ}KKփՂׇׅ҃׈؉ss؋kkٍَ·W::bb[[۔֑__ܗttݙN66ޛݚaaޝ̑ߟߠٜᤤhh㪪ڣ֠tt㬬Ĕ䯯ssrXX沲ff絵ګ緷ɠxxeRR龾ɨťxffʆssָèĻӭî˨՚⧛ȼcftRNSfYbKGD pHYsHHFk> vpAg:.wlIDATXř \U߬,88% ;+ ǒx殚E&%ᅊiVZfZixT~ӴPS)\;3gofނ؀\h`4k#-f,bQnX|mKt@w$D5<55 j&8D 'w 6Qjc+1E`dokިε;έp&zqv{/H! 9X [Ih֠8jBhrptik @GОcMYhSǚvLl9@bF΄c.V!΢yUg|5£>|#8l-M6 1&1a}XU;cG-9(2,Ssua|x+XG1RD~2CC1hpB$D` SPI!@& y0+`C .@=߫@ B\>H d<~PѷLc"`O!ۊhDH' r)A'$p O`Q(`Ml~2^ _%~2c6ޗ~} ?5jnF,{ L/J[hֲ$LH>c BBMt~x`> ;gNGNܪ WNBik}(gt.ӥӹRiյI ()f"t( /ɜ9 B)7svඒI:\nI \rx1{r&-/ՙ7iRK6gNvy0zÐpaB :rsҖUTe(NzYLBG2Ӵ#ƉEjY h=J{DZ' x;rS+h.ǿ1 gd(C+{[q;_pB^h8{.á3R@9{\>׌@`IIQXjʣ/2zLtkV8Q'۸82C'j 4JQ$MR[:g.߹5+55gޣv(~pE1~>V4(LS%}ef>1h`ênE}(""j,Zz;<,qֻ; =jɑM"%L1k ξ4pzpu~wĴ£% 8Yeb+3nc~\{:Htd,l9 7~5!aqy8b$a9m O` ?'q6>./T K7m١SdTNƟ/e3߅@wġW+|ebVޑM%ޢ nw/ՊlGSH`S[I) j T.LY_Djr=[8+/)E{=)ߡbYx؈"~00V|VYEuA%K-y7 ,esi +-M;y$x|9L9uqJC{Эu*zѭ1@GB%tEXtdate:create2010-04-12T22:47:48+02:00]-%tEXtdate:modify2010-02-12T16:30:16+01:00XIENDB`mlpost-0.8.2/examples/preambule.tex000066400000000000000000000002531306046515300173560ustar00rootroot00000000000000%% -*- coding : utf8 -*- \documentclass[12pt,a4paper]{article} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{lmodern} \begin{document} \end{document} mlpost-0.8.2/examples/prototype.js000066400000000000000000004211161306046515300172700ustar00rootroot00000000000000/* Prototype JavaScript framework, version 1.6.1 * (c) 2005-2009 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://www.prototypejs.org/ * *--------------------------------------------------------------------------*/ var Prototype = { Version: '1.6.1', Browser: (function(){ var ua = navigator.userAgent; var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; return { IE: !!window.attachEvent && !isOpera, Opera: isOpera, WebKit: ua.indexOf('AppleWebKit/') > -1, Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, MobileSafari: /Apple.*Mobile.*Safari/.test(ua) } })(), BrowserFeatures: { XPath: !!document.evaluate, SelectorsAPI: !!document.querySelector, ElementExtensions: (function() { var constructor = window.Element || window.HTMLElement; return !!(constructor && constructor.prototype); })(), SpecificElementExtensions: (function() { if (typeof window.HTMLDivElement !== 'undefined') return true; var div = document.createElement('div'); var form = document.createElement('form'); var isSupported = false; if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { isSupported = true; } div = form = null; return isSupported; })() }, ScriptFragment: ']*>([\\S\\s]*?)<\/script>', JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, emptyFunction: function() { }, K: function(x) { return x } }; if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false; var Abstract = { }; var Try = { these: function() { var returnValue; for (var i = 0, length = arguments.length; i < length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) { } } return returnValue; } }; /* Based on Alex Arnell's inheritance implementation. */ var Class = (function() { function subclass() {}; function create() { var parent = null, properties = $A(arguments); if (Object.isFunction(properties[0])) parent = properties.shift(); function klass() { this.initialize.apply(this, arguments); } Object.extend(klass, Class.Methods); klass.superclass = parent; klass.subclasses = []; if (parent) { subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); } for (var i = 0; i < properties.length; i++) klass.addMethods(properties[i]); if (!klass.prototype.initialize) klass.prototype.initialize = Prototype.emptyFunction; klass.prototype.constructor = klass; return klass; } function addMethods(source) { var ancestor = this.superclass && this.superclass.prototype; var properties = Object.keys(source); if (!Object.keys({ toString: true }).length) { if (source.toString != Object.prototype.toString) properties.push("toString"); if (source.valueOf != Object.prototype.valueOf) properties.push("valueOf"); } for (var i = 0, length = properties.length; i < length; i++) { var property = properties[i], value = source[property]; if (ancestor && Object.isFunction(value) && value.argumentNames().first() == "$super") { var method = value; value = (function(m) { return function() { return ancestor[m].apply(this, arguments); }; })(property).wrap(method); value.valueOf = method.valueOf.bind(method); value.toString = method.toString.bind(method); } this.prototype[property] = value; } return this; } return { create: create, Methods: { addMethods: addMethods } }; })(); (function() { var _toString = Object.prototype.toString; function extend(destination, source) { for (var property in source) destination[property] = source[property]; return destination; } function inspect(object) { try { if (isUndefined(object)) return 'undefined'; if (object === null) return 'null'; return object.inspect ? object.inspect() : String(object); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } } function toJSON(object) { var type = typeof object; switch (type) { case 'undefined': case 'function': case 'unknown': return; case 'boolean': return object.toString(); } if (object === null) return 'null'; if (object.toJSON) return object.toJSON(); if (isElement(object)) return; var results = []; for (var property in object) { var value = toJSON(object[property]); if (!isUndefined(value)) results.push(property.toJSON() + ': ' + value); } return '{' + results.join(', ') + '}'; } function toQueryString(object) { return $H(object).toQueryString(); } function toHTML(object) { return object && object.toHTML ? object.toHTML() : String.interpret(object); } function keys(object) { var results = []; for (var property in object) results.push(property); return results; } function values(object) { var results = []; for (var property in object) results.push(object[property]); return results; } function clone(object) { return extend({ }, object); } function isElement(object) { return !!(object && object.nodeType == 1); } function isArray(object) { return _toString.call(object) == "[object Array]"; } function isHash(object) { return object instanceof Hash; } function isFunction(object) { return typeof object === "function"; } function isString(object) { return _toString.call(object) == "[object String]"; } function isNumber(object) { return _toString.call(object) == "[object Number]"; } function isUndefined(object) { return typeof object === "undefined"; } extend(Object, { extend: extend, inspect: inspect, toJSON: toJSON, toQueryString: toQueryString, toHTML: toHTML, keys: keys, values: values, clone: clone, isElement: isElement, isArray: isArray, isHash: isHash, isFunction: isFunction, isString: isString, isNumber: isNumber, isUndefined: isUndefined }); })(); Object.extend(Function.prototype, (function() { var slice = Array.prototype.slice; function update(array, args) { var arrayLength = array.length, length = args.length; while (length--) array[arrayLength + length] = args[length]; return array; } function merge(array, args) { array = slice.call(array, 0); return update(array, args); } function argumentNames() { var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') .replace(/\s+/g, '').split(','); return names.length == 1 && !names[0] ? [] : names; } function bind(context) { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; var __method = this, args = slice.call(arguments, 1); return function() { var a = merge(args, arguments); return __method.apply(context, a); } } function bindAsEventListener(context) { var __method = this, args = slice.call(arguments, 1); return function(event) { var a = update([event || window.event], args); return __method.apply(context, a); } } function curry() { if (!arguments.length) return this; var __method = this, args = slice.call(arguments, 0); return function() { var a = merge(args, arguments); return __method.apply(this, a); } } function delay(timeout) { var __method = this, args = slice.call(arguments, 1); timeout = timeout * 1000 return window.setTimeout(function() { return __method.apply(__method, args); }, timeout); } function defer() { var args = update([0.01], arguments); return this.delay.apply(this, args); } function wrap(wrapper) { var __method = this; return function() { var a = update([__method.bind(this)], arguments); return wrapper.apply(this, a); } } function methodize() { if (this._methodized) return this._methodized; var __method = this; return this._methodized = function() { var a = update([this], arguments); return __method.apply(null, a); }; } return { argumentNames: argumentNames, bind: bind, bindAsEventListener: bindAsEventListener, curry: curry, delay: delay, defer: defer, wrap: wrap, methodize: methodize } })()); Date.prototype.toJSON = function() { return '"' + this.getUTCFullYear() + '-' + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + this.getUTCDate().toPaddedString(2) + 'T' + this.getUTCHours().toPaddedString(2) + ':' + this.getUTCMinutes().toPaddedString(2) + ':' + this.getUTCSeconds().toPaddedString(2) + 'Z"'; }; RegExp.prototype.match = RegExp.prototype.test; RegExp.escape = function(str) { return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); }; var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, execute: function() { this.callback(this); }, stop: function() { if (!this.timer) return; clearInterval(this.timer); this.timer = null; }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.execute(); this.currentlyExecuting = false; } catch(e) { this.currentlyExecuting = false; throw e; } } } }); Object.extend(String, { interpret: function(value) { return value == null ? '' : String(value); }, specialChar: { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\' } }); Object.extend(String.prototype, (function() { function prepareReplacement(replacement) { if (Object.isFunction(replacement)) return replacement; var template = new Template(replacement); return function(match) { return template.evaluate(match) }; } function gsub(pattern, replacement) { var result = '', source = this, match; replacement = prepareReplacement(replacement); if (Object.isString(pattern)) pattern = RegExp.escape(pattern); if (!(pattern.length || pattern.source)) { replacement = replacement(''); return replacement + source.split('').join(replacement) + replacement; } while (source.length > 0) { if (match = source.match(pattern)) { result += source.slice(0, match.index); result += String.interpret(replacement(match)); source = source.slice(match.index + match[0].length); } else { result += source, source = ''; } } return result; } function sub(pattern, replacement, count) { replacement = prepareReplacement(replacement); count = Object.isUndefined(count) ? 1 : count; return this.gsub(pattern, function(match) { if (--count < 0) return match[0]; return replacement(match); }); } function scan(pattern, iterator) { this.gsub(pattern, iterator); return String(this); } function truncate(length, truncation) { length = length || 30; truncation = Object.isUndefined(truncation) ? '...' : truncation; return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this); } function strip() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); } function stripTags() { return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); } function stripScripts() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); } function extractScripts() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); } function evalScripts() { return this.extractScripts().map(function(script) { return eval(script) }); } function escapeHTML() { return this.replace(/&/g,'&').replace(//g,'>'); } function unescapeHTML() { return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); } function toQueryParams(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); if (!match) return { }; return match[1].split(separator || '&').inject({ }, function(hash, pair) { if ((pair = pair.split('='))[0]) { var key = decodeURIComponent(pair.shift()); var value = pair.length > 1 ? pair.join('=') : pair[0]; if (value != undefined) value = decodeURIComponent(value); if (key in hash) { if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; hash[key].push(value); } else hash[key] = value; } return hash; }); } function toArray() { return this.split(''); } function succ() { return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); } function times(count) { return count < 1 ? '' : new Array(count + 1).join(this); } function camelize() { var parts = this.split('-'), len = parts.length; if (len == 1) return parts[0]; var camelized = this.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0]; for (var i = 1; i < len; i++) camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); return camelized; } function capitalize() { return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); } function underscore() { return this.replace(/::/g, '/') .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') .replace(/([a-z\d])([A-Z])/g, '$1_$2') .replace(/-/g, '_') .toLowerCase(); } function dasherize() { return this.replace(/_/g, '-'); } function inspect(useDoubleQuotes) { var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { if (character in String.specialChar) { return String.specialChar[character]; } return '\\u00' + character.charCodeAt().toPaddedString(2, 16); }); if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; return "'" + escapedString.replace(/'/g, '\\\'') + "'"; } function toJSON() { return this.inspect(true); } function unfilterJSON(filter) { return this.replace(filter || Prototype.JSONFilter, '$1'); } function isJSON() { var str = this; if (str.blank()) return false; str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); } function evalJSON(sanitize) { var json = this.unfilterJSON(); try { if (!sanitize || json.isJSON()) return eval('(' + json + ')'); } catch (e) { } throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); } function include(pattern) { return this.indexOf(pattern) > -1; } function startsWith(pattern) { return this.indexOf(pattern) === 0; } function endsWith(pattern) { var d = this.length - pattern.length; return d >= 0 && this.lastIndexOf(pattern) === d; } function empty() { return this == ''; } function blank() { return /^\s*$/.test(this); } function interpolate(object, pattern) { return new Template(this, pattern).evaluate(object); } return { gsub: gsub, sub: sub, scan: scan, truncate: truncate, strip: String.prototype.trim ? String.prototype.trim : strip, stripTags: stripTags, stripScripts: stripScripts, extractScripts: extractScripts, evalScripts: evalScripts, escapeHTML: escapeHTML, unescapeHTML: unescapeHTML, toQueryParams: toQueryParams, parseQuery: toQueryParams, toArray: toArray, succ: succ, times: times, camelize: camelize, capitalize: capitalize, underscore: underscore, dasherize: dasherize, inspect: inspect, toJSON: toJSON, unfilterJSON: unfilterJSON, isJSON: isJSON, evalJSON: evalJSON, include: include, startsWith: startsWith, endsWith: endsWith, empty: empty, blank: blank, interpolate: interpolate }; })()); var Template = Class.create({ initialize: function(template, pattern) { this.template = template.toString(); this.pattern = pattern || Template.Pattern; }, evaluate: function(object) { if (object && Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { if (object == null) return (match[1] + ''); var before = match[1] || ''; if (before == '\\') return match[2]; var ctx = object, expr = match[3]; var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; match = pattern.exec(expr); if (match == null) return before; while (match != null) { var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; ctx = ctx[comp]; if (null == ctx || '' == match[3]) break; expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); match = pattern.exec(expr); } return before + String.interpret(ctx); }); } }); Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; var $break = { }; var Enumerable = (function() { function each(iterator, context) { var index = 0; try { this._each(function(value) { iterator.call(context, value, index++); }); } catch (e) { if (e != $break) throw e; } return this; } function eachSlice(number, iterator, context) { var index = -number, slices = [], array = this.toArray(); if (number < 1) return array; while ((index += number) < array.length) slices.push(array.slice(index, index+number)); return slices.collect(iterator, context); } function all(iterator, context) { iterator = iterator || Prototype.K; var result = true; this.each(function(value, index) { result = result && !!iterator.call(context, value, index); if (!result) throw $break; }); return result; } function any(iterator, context) { iterator = iterator || Prototype.K; var result = false; this.each(function(value, index) { if (result = !!iterator.call(context, value, index)) throw $break; }); return result; } function collect(iterator, context) { iterator = iterator || Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator.call(context, value, index)); }); return results; } function detect(iterator, context) { var result; this.each(function(value, index) { if (iterator.call(context, value, index)) { result = value; throw $break; } }); return result; } function findAll(iterator, context) { var results = []; this.each(function(value, index) { if (iterator.call(context, value, index)) results.push(value); }); return results; } function grep(filter, iterator, context) { iterator = iterator || Prototype.K; var results = []; if (Object.isString(filter)) filter = new RegExp(RegExp.escape(filter)); this.each(function(value, index) { if (filter.match(value)) results.push(iterator.call(context, value, index)); }); return results; } function include(object) { if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true; var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; } function inGroupsOf(number, fillWith) { fillWith = Object.isUndefined(fillWith) ? null : fillWith; return this.eachSlice(number, function(slice) { while(slice.length < number) slice.push(fillWith); return slice; }); } function inject(memo, iterator, context) { this.each(function(value, index) { memo = iterator.call(context, memo, value, index); }); return memo; } function invoke(method) { var args = $A(arguments).slice(1); return this.map(function(value) { return value[method].apply(value, args); }); } function max(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { value = iterator.call(context, value, index); if (result == null || value >= result) result = value; }); return result; } function min(iterator, context) { iterator = iterator || Prototype.K; var result; this.each(function(value, index) { value = iterator.call(context, value, index); if (result == null || value < result) result = value; }); return result; } function partition(iterator, context) { iterator = iterator || Prototype.K; var trues = [], falses = []; this.each(function(value, index) { (iterator.call(context, value, index) ? trues : falses).push(value); }); return [trues, falses]; } function pluck(property) { var results = []; this.each(function(value) { results.push(value[property]); }); return results; } function reject(iterator, context) { var results = []; this.each(function(value, index) { if (!iterator.call(context, value, index)) results.push(value); }); return results; } function sortBy(iterator, context) { return this.map(function(value, index) { return { value: value, criteria: iterator.call(context, value, index) }; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); } function toArray() { return this.map(); } function zip() { var iterator = Prototype.K, args = $A(arguments); if (Object.isFunction(args.last())) iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { return iterator(collections.pluck(index)); }); } function size() { return this.toArray().length; } function inspect() { return '#'; } return { each: each, eachSlice: eachSlice, all: all, every: all, any: any, some: any, collect: collect, map: collect, detect: detect, findAll: findAll, select: findAll, filter: findAll, grep: grep, include: include, member: include, inGroupsOf: inGroupsOf, inject: inject, invoke: invoke, max: max, min: min, partition: partition, pluck: pluck, reject: reject, sortBy: sortBy, toArray: toArray, entries: toArray, zip: zip, size: size, inspect: inspect, find: detect }; })(); function $A(iterable) { if (!iterable) return []; if ('toArray' in Object(iterable)) return iterable.toArray(); var length = iterable.length || 0, results = new Array(length); while (length--) results[length] = iterable[length]; return results; } function $w(string) { if (!Object.isString(string)) return []; string = string.strip(); return string ? string.split(/\s+/) : []; } Array.from = $A; (function() { var arrayProto = Array.prototype, slice = arrayProto.slice, _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available function each(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]); } if (!_each) _each = each; function clear() { this.length = 0; return this; } function first() { return this[0]; } function last() { return this[this.length - 1]; } function compact() { return this.select(function(value) { return value != null; }); } function flatten() { return this.inject([], function(array, value) { if (Object.isArray(value)) return array.concat(value.flatten()); array.push(value); return array; }); } function without() { var values = slice.call(arguments, 0); return this.select(function(value) { return !values.include(value); }); } function reverse(inline) { return (inline !== false ? this : this.toArray())._reverse(); } function uniq(sorted) { return this.inject([], function(array, value, index) { if (0 == index || (sorted ? array.last() != value : !array.include(value))) array.push(value); return array; }); } function intersect(array) { return this.uniq().findAll(function(item) { return array.detect(function(value) { return item === value }); }); } function clone() { return slice.call(this, 0); } function size() { return this.length; } function inspect() { return '[' + this.map(Object.inspect).join(', ') + ']'; } function toJSON() { var results = []; this.each(function(object) { var value = Object.toJSON(object); if (!Object.isUndefined(value)) results.push(value); }); return '[' + results.join(', ') + ']'; } function indexOf(item, i) { i || (i = 0); var length = this.length; if (i < 0) i = length + i; for (; i < length; i++) if (this[i] === item) return i; return -1; } function lastIndexOf(item, i) { i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; var n = this.slice(0, i).reverse().indexOf(item); return (n < 0) ? n : i - n - 1; } function concat() { var array = slice.call(this, 0), item; for (var i = 0, length = arguments.length; i < length; i++) { item = arguments[i]; if (Object.isArray(item) && !('callee' in item)) { for (var j = 0, arrayLength = item.length; j < arrayLength; j++) array.push(item[j]); } else { array.push(item); } } return array; } Object.extend(arrayProto, Enumerable); if (!arrayProto._reverse) arrayProto._reverse = arrayProto.reverse; Object.extend(arrayProto, { _each: _each, clear: clear, first: first, last: last, compact: compact, flatten: flatten, without: without, reverse: reverse, uniq: uniq, intersect: intersect, clone: clone, toArray: clone, size: size, inspect: inspect, toJSON: toJSON }); var CONCAT_ARGUMENTS_BUGGY = (function() { return [].concat(arguments)[0][0] !== 1; })(1,2) if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; })(); function $H(object) { return new Hash(object); }; var Hash = Class.create(Enumerable, (function() { function initialize(object) { this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); } function _each(iterator) { for (var key in this._object) { var value = this._object[key], pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } } function set(key, value) { return this._object[key] = value; } function get(key) { if (this._object[key] !== Object.prototype[key]) return this._object[key]; } function unset(key) { var value = this._object[key]; delete this._object[key]; return value; } function toObject() { return Object.clone(this._object); } function keys() { return this.pluck('key'); } function values() { return this.pluck('value'); } function index(value) { var match = this.detect(function(pair) { return pair.value === value; }); return match && match.key; } function merge(object) { return this.clone().update(object); } function update(object) { return new Hash(object).inject(this, function(result, pair) { result.set(pair.key, pair.value); return result; }); } function toQueryPair(key, value) { if (Object.isUndefined(value)) return key; return key + '=' + encodeURIComponent(String.interpret(value)); } function toQueryString() { return this.inject([], function(results, pair) { var key = encodeURIComponent(pair.key), values = pair.value; if (values && typeof values == 'object') { if (Object.isArray(values)) return results.concat(values.map(toQueryPair.curry(key))); } else results.push(toQueryPair(key, values)); return results; }).join('&'); } function inspect() { return '#'; } function toJSON() { return Object.toJSON(this.toObject()); } function clone() { return new Hash(this); } return { initialize: initialize, _each: _each, set: set, get: get, unset: unset, toObject: toObject, toTemplateReplacements: toObject, keys: keys, values: values, index: index, merge: merge, update: update, toQueryString: toQueryString, inspect: inspect, toJSON: toJSON, clone: clone }; })()); Hash.from = $H; Object.extend(Number.prototype, (function() { function toColorPart() { return this.toPaddedString(2, 16); } function succ() { return this + 1; } function times(iterator, context) { $R(0, this, true).each(iterator, context); return this; } function toPaddedString(length, radix) { var string = this.toString(radix || 10); return '0'.times(length - string.length) + string; } function toJSON() { return isFinite(this) ? this.toString() : 'null'; } function abs() { return Math.abs(this); } function round() { return Math.round(this); } function ceil() { return Math.ceil(this); } function floor() { return Math.floor(this); } return { toColorPart: toColorPart, succ: succ, times: times, toPaddedString: toPaddedString, toJSON: toJSON, abs: abs, round: round, ceil: ceil, floor: floor }; })()); function $R(start, end, exclusive) { return new ObjectRange(start, end, exclusive); } var ObjectRange = Class.create(Enumerable, (function() { function initialize(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; } function _each(iterator) { var value = this.start; while (this.include(value)) { iterator(value); value = value.succ(); } } function include(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; } return { initialize: initialize, _each: _each, include: include }; })()); var Ajax = { getTransport: function() { return Try.these( function() {return new XMLHttpRequest()}, function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')} ) || false; }, activeRequestCount: 0 }; Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responder) { if (!this.include(responder)) this.responders.push(responder); }, unregister: function(responder) { this.responders = this.responders.without(responder); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (Object.isFunction(responder[callback])) { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) { } } }); } }; Object.extend(Ajax.Responders, Enumerable); Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++ }, onComplete: function() { Ajax.activeRequestCount-- } }); Ajax.Base = Class.create({ initialize: function(options) { this.options = { method: 'post', asynchronous: true, contentType: 'application/x-www-form-urlencoded', encoding: 'UTF-8', parameters: '', evalJSON: true, evalJS: true }; Object.extend(this.options, options || { }); this.options.method = this.options.method.toLowerCase(); if (Object.isString(this.options.parameters)) this.options.parameters = this.options.parameters.toQueryParams(); else if (Object.isHash(this.options.parameters)) this.options.parameters = this.options.parameters.toObject(); } }); Ajax.Request = Class.create(Ajax.Base, { _complete: false, initialize: function($super, url, options) { $super(options); this.transport = Ajax.getTransport(); this.request(url); }, request: function(url) { this.url = url; this.method = this.options.method; var params = Object.clone(this.options.parameters); if (!['get', 'post'].include(this.method)) { params['_method'] = this.method; this.method = 'post'; } this.parameters = params; if (params = Object.toQueryString(params)) { if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params; else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='; } try { var response = new Ajax.Response(this); if (this.options.onCreate) this.options.onCreate(response); Ajax.Responders.dispatch('onCreate', this, response); this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); this.body = this.method == 'post' ? (this.options.postBody || params) : null; this.transport.send(this.body); /* Force Firefox to handle ready state 4 for synchronous requests */ if (!this.options.asynchronous && this.transport.overrideMimeType) this.onStateChange(); } catch (e) { this.dispatchException(e); } }, onStateChange: function() { var readyState = this.transport.readyState; if (readyState > 1 && !((readyState == 4) && this._complete)) this.respondToReadyState(this.transport.readyState); }, setRequestHeaders: function() { var headers = { 'X-Requested-With': 'XMLHttpRequest', 'X-Prototype-Version': Prototype.Version, 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' }; if (this.method == 'post') { headers['Content-type'] = this.options.contentType + (this.options.encoding ? '; charset=' + this.options.encoding : ''); /* Force "Connection: close" for older Mozilla browsers to work * around a bug where XMLHttpRequest sends an incorrect * Content-length header. See Mozilla Bugzilla #246651. */ if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) headers['Connection'] = 'close'; } if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; if (Object.isFunction(extras.push)) for (var i = 0, length = extras.length; i < length; i += 2) headers[extras[i]] = extras[i+1]; else $H(extras).each(function(pair) { headers[pair.key] = pair.value }); } for (var name in headers) this.transport.setRequestHeader(name, headers[name]); }, success: function() { var status = this.getStatus(); return !status || (status >= 200 && status < 300); }, getStatus: function() { try { return this.transport.status || 0; } catch (e) { return 0 } }, respondToReadyState: function(readyState) { var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); if (state == 'Complete') { try { this._complete = true; (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(response, response.headerJSON); } catch (e) { this.dispatchException(e); } var contentType = response.getHeader('Content-type'); if (this.options.evalJS == 'force' || (this.options.evalJS && this.isSameOrigin() && contentType && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) this.evalResponse(); } try { (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); } catch (e) { this.dispatchException(e); } if (state == 'Complete') { this.transport.onreadystatechange = Prototype.emptyFunction; } }, isSameOrigin: function() { var m = this.url.match(/^\s*https?:\/\/[^\/]*/); return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ protocol: location.protocol, domain: document.domain, port: location.port ? ':' + location.port : '' })); }, getHeader: function(name) { try { return this.transport.getResponseHeader(name) || null; } catch (e) { return null; } }, evalResponse: function() { try { return eval((this.transport.responseText || '').unfilterJSON()); } catch (e) { this.dispatchException(e); } }, dispatchException: function(exception) { (this.options.onException || Prototype.emptyFunction)(this, exception); Ajax.Responders.dispatch('onException', this, exception); } }); Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; Ajax.Response = Class.create({ initialize: function(request){ this.request = request; var transport = this.transport = request.transport, readyState = this.readyState = transport.readyState; if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { this.status = this.getStatus(); this.statusText = this.getStatusText(); this.responseText = String.interpret(transport.responseText); this.headerJSON = this._getHeaderJSON(); } if(readyState == 4) { var xml = transport.responseXML; this.responseXML = Object.isUndefined(xml) ? null : xml; this.responseJSON = this._getResponseJSON(); } }, status: 0, statusText: '', getStatus: Ajax.Request.prototype.getStatus, getStatusText: function() { try { return this.transport.statusText || ''; } catch (e) { return '' } }, getHeader: Ajax.Request.prototype.getHeader, getAllHeaders: function() { try { return this.getAllResponseHeaders(); } catch (e) { return null } }, getResponseHeader: function(name) { return this.transport.getResponseHeader(name); }, getAllResponseHeaders: function() { return this.transport.getAllResponseHeaders(); }, _getHeaderJSON: function() { var json = this.getHeader('X-JSON'); if (!json) return null; json = decodeURIComponent(escape(json)); try { return json.evalJSON(this.request.options.sanitizeJSON || !this.request.isSameOrigin()); } catch (e) { this.request.dispatchException(e); } }, _getResponseJSON: function() { var options = this.request.options; if (!options.evalJSON || (options.evalJSON != 'force' && !(this.getHeader('Content-type') || '').include('application/json')) || this.responseText.blank()) return null; try { return this.responseText.evalJSON(options.sanitizeJSON || !this.request.isSameOrigin()); } catch (e) { this.request.dispatchException(e); } } }); Ajax.Updater = Class.create(Ajax.Request, { initialize: function($super, container, url, options) { this.container = { success: (container.success || container), failure: (container.failure || (container.success ? null : container)) }; options = Object.clone(options); var onComplete = options.onComplete; options.onComplete = (function(response, json) { this.updateContent(response.responseText); if (Object.isFunction(onComplete)) onComplete(response, json); }).bind(this); $super(url, options); }, updateContent: function(responseText) { var receiver = this.container[this.success() ? 'success' : 'failure'], options = this.options; if (!options.evalScripts) responseText = responseText.stripScripts(); if (receiver = $(receiver)) { if (options.insertion) { if (Object.isString(options.insertion)) { var insertion = { }; insertion[options.insertion] = responseText; receiver.insert(insertion); } else options.insertion(receiver, responseText); } else receiver.update(responseText); } } }); Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { initialize: function($super, container, url, options) { $super(options); this.onComplete = this.options.onComplete; this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); this.updater = { }; this.container = container; this.url = url; this.start(); }, start: function() { this.options.onComplete = this.updateComplete.bind(this); this.onTimerEvent(); }, stop: function() { this.updater.options.onComplete = undefined; clearTimeout(this.timer); (this.onComplete || Prototype.emptyFunction).apply(this, arguments); }, updateComplete: function(response) { if (this.options.decay) { this.decay = (response.responseText == this.lastText ? this.decay * this.options.decay : 1); this.lastText = response.responseText; } this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); }, onTimerEvent: function() { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); function $(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i])); return elements; } if (Object.isString(element)) element = document.getElementById(element); return Element.extend(element); } if (Prototype.BrowserFeatures.XPath) { document._getElementsByXPath = function(expression, parentElement) { var results = []; var query = document.evaluate(expression, $(parentElement) || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0, length = query.snapshotLength; i < length; i++) results.push(Element.extend(query.snapshotItem(i))); return results; }; } /*--------------------------------------------------------------------------*/ if (!window.Node) var Node = { }; if (!Node.ELEMENT_NODE) { Object.extend(Node, { ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12 }); } (function(global) { var SETATTRIBUTE_IGNORES_NAME = (function(){ var elForm = document.createElement("form"); var elInput = document.createElement("input"); var root = document.documentElement; elInput.setAttribute("name", "test"); elForm.appendChild(elInput); root.appendChild(elForm); var isBuggy = elForm.elements ? (typeof elForm.elements.test == "undefined") : null; root.removeChild(elForm); elForm = elInput = null; return isBuggy; })(); var element = global.Element; global.Element = function(tagName, attributes) { attributes = attributes || { }; tagName = tagName.toLowerCase(); var cache = Element.cache; if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { tagName = '<' + tagName + ' name="' + attributes.name + '">'; delete attributes.name; return Element.writeAttribute(document.createElement(tagName), attributes); } if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); }; Object.extend(global.Element, element || { }); if (element) global.Element.prototype = element.prototype; })(this); Element.cache = { }; Element.idCounter = 1; Element.Methods = { visible: function(element) { return $(element).style.display != 'none'; }, toggle: function(element) { element = $(element); Element[Element.visible(element) ? 'hide' : 'show'](element); return element; }, hide: function(element) { element = $(element); element.style.display = 'none'; return element; }, show: function(element) { element = $(element); element.style.display = ''; return element; }, remove: function(element) { element = $(element); element.parentNode.removeChild(element); return element; }, update: (function(){ var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ var el = document.createElement("select"), isBuggy = true; el.innerHTML = ""; if (el.options && el.options[0]) { isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; } el = null; return isBuggy; })(); var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ try { var el = document.createElement("table"); if (el && el.tBodies) { el.innerHTML = "test"; var isBuggy = typeof el.tBodies[0] == "undefined"; el = null; return isBuggy; } } catch (e) { return true; } })(); var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { var s = document.createElement("script"), isBuggy = false; try { s.appendChild(document.createTextNode("")); isBuggy = !s.firstChild || s.firstChild && s.firstChild.nodeType !== 3; } catch (e) { isBuggy = true; } s = null; return isBuggy; })(); function update(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) return element.update().insert(content); content = Object.toHTML(content); var tagName = element.tagName.toUpperCase(); if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { element.text = content; return element; } if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { if (tagName in Element._insertionTranslations.tags) { while (element.firstChild) { element.removeChild(element.firstChild); } Element._getContentFromAnonymousElement(tagName, content.stripScripts()) .each(function(node) { element.appendChild(node) }); } else { element.innerHTML = content.stripScripts(); } } else { element.innerHTML = content.stripScripts(); } content.evalScripts.bind(content).defer(); return element; } return update; })(), replace: function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); else if (!Object.isElement(content)) { content = Object.toHTML(content); var range = element.ownerDocument.createRange(); range.selectNode(element); content.evalScripts.bind(content).defer(); content = range.createContextualFragment(content.stripScripts()); } element.parentNode.replaceChild(content, element); return element; }, insert: function(element, insertions) { element = $(element); if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = {bottom:insertions}; var content, insert, tagName, childNodes; for (var position in insertions) { content = insertions[position]; position = position.toLowerCase(); insert = Element._insertionTranslations[position]; if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { insert(element, content); continue; } content = Object.toHTML(content); tagName = ((position == 'before' || position == 'after') ? element.parentNode : element).tagName.toUpperCase(); childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); if (position == 'top' || position == 'after') childNodes.reverse(); childNodes.each(insert.curry(element)); content.evalScripts.bind(content).defer(); } return element; }, wrap: function(element, wrapper, attributes) { element = $(element); if (Object.isElement(wrapper)) $(wrapper).writeAttribute(attributes || { }); else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); else wrapper = new Element('div', wrapper); if (element.parentNode) element.parentNode.replaceChild(wrapper, element); wrapper.appendChild(element); return wrapper; }, inspect: function(element) { element = $(element); var result = '<' + element.tagName.toLowerCase(); $H({'id': 'id', 'className': 'class'}).each(function(pair) { var property = pair.first(), attribute = pair.last(); var value = (element[property] || '').toString(); if (value) result += ' ' + attribute + '=' + value.inspect(true); }); return result + '>'; }, recursivelyCollect: function(element, property) { element = $(element); var elements = []; while (element = element[property]) if (element.nodeType == 1) elements.push(Element.extend(element)); return elements; }, ancestors: function(element) { return Element.recursivelyCollect(element, 'parentNode'); }, descendants: function(element) { return Element.select(element, "*"); }, firstDescendant: function(element) { element = $(element).firstChild; while (element && element.nodeType != 1) element = element.nextSibling; return $(element); }, immediateDescendants: function(element) { if (!(element = $(element).firstChild)) return []; while (element && element.nodeType != 1) element = element.nextSibling; if (element) return [element].concat($(element).nextSiblings()); return []; }, previousSiblings: function(element) { return Element.recursivelyCollect(element, 'previousSibling'); }, nextSiblings: function(element) { return Element.recursivelyCollect(element, 'nextSibling'); }, siblings: function(element) { element = $(element); return Element.previousSiblings(element).reverse() .concat(Element.nextSiblings(element)); }, match: function(element, selector) { if (Object.isString(selector)) selector = new Selector(selector); return selector.match($(element)); }, up: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(element.parentNode); var ancestors = Element.ancestors(element); return Object.isNumber(expression) ? ancestors[expression] : Selector.findElement(ancestors, expression, index); }, down: function(element, expression, index) { element = $(element); if (arguments.length == 1) return Element.firstDescendant(element); return Object.isNumber(expression) ? Element.descendants(element)[expression] : Element.select(element, expression)[index || 0]; }, previous: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); var previousSiblings = Element.previousSiblings(element); return Object.isNumber(expression) ? previousSiblings[expression] : Selector.findElement(previousSiblings, expression, index); }, next: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); var nextSiblings = Element.nextSiblings(element); return Object.isNumber(expression) ? nextSiblings[expression] : Selector.findElement(nextSiblings, expression, index); }, select: function(element) { var args = Array.prototype.slice.call(arguments, 1); return Selector.findChildElements(element, args); }, adjacent: function(element) { var args = Array.prototype.slice.call(arguments, 1); return Selector.findChildElements(element.parentNode, args).without(element); }, identify: function(element) { element = $(element); var id = Element.readAttribute(element, 'id'); if (id) return id; do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); Element.writeAttribute(element, 'id', id); return id; }, readAttribute: function(element, name) { element = $(element); if (Prototype.Browser.IE) { var t = Element._attributeTranslations.read; if (t.values[name]) return t.values[name](element, name); if (t.names[name]) name = t.names[name]; if (name.include(':')) { return (!element.attributes || !element.attributes[name]) ? null : element.attributes[name].value; } } return element.getAttribute(name); }, writeAttribute: function(element, name, value) { element = $(element); var attributes = { }, t = Element._attributeTranslations.write; if (typeof name == 'object') attributes = name; else attributes[name] = Object.isUndefined(value) ? true : value; for (var attr in attributes) { name = t.names[attr] || attr; value = attributes[attr]; if (t.values[attr]) name = t.values[attr](element, value); if (value === false || value === null) element.removeAttribute(name); else if (value === true) element.setAttribute(name, name); else element.setAttribute(name, value); } return element; }, getHeight: function(element) { return Element.getDimensions(element).height; }, getWidth: function(element) { return Element.getDimensions(element).width; }, classNames: function(element) { return new Element.ClassNames(element); }, hasClassName: function(element, className) { if (!(element = $(element))) return; var elementClassName = element.className; return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); }, addClassName: function(element, className) { if (!(element = $(element))) return; if (!Element.hasClassName(element, className)) element.className += (element.className ? ' ' : '') + className; return element; }, removeClassName: function(element, className) { if (!(element = $(element))) return; element.className = element.className.replace( new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); return element; }, toggleClassName: function(element, className) { if (!(element = $(element))) return; return Element[Element.hasClassName(element, className) ? 'removeClassName' : 'addClassName'](element, className); }, cleanWhitespace: function(element) { element = $(element); var node = element.firstChild; while (node) { var nextNode = node.nextSibling; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) element.removeChild(node); node = nextNode; } return element; }, empty: function(element) { return $(element).innerHTML.blank(); }, descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); if (element.compareDocumentPosition) return (element.compareDocumentPosition(ancestor) & 8) === 8; if (ancestor.contains) return ancestor.contains(element) && ancestor !== element; while (element = element.parentNode) if (element == ancestor) return true; return false; }, scrollTo: function(element) { element = $(element); var pos = Element.cumulativeOffset(element); window.scrollTo(pos[0], pos[1]); return element; }, getStyle: function(element, style) { element = $(element); style = style == 'float' ? 'cssFloat' : style.camelize(); var value = element.style[style]; if (!value || value == 'auto') { var css = document.defaultView.getComputedStyle(element, null); value = css ? css[style] : null; } if (style == 'opacity') return value ? parseFloat(value) : 1.0; return value == 'auto' ? null : value; }, getOpacity: function(element) { return $(element).getStyle('opacity'); }, setStyle: function(element, styles) { element = $(element); var elementStyle = element.style, match; if (Object.isString(styles)) { element.style.cssText += ';' + styles; return styles.include('opacity') ? element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; } for (var property in styles) if (property == 'opacity') element.setOpacity(styles[property]); else elementStyle[(property == 'float' || property == 'cssFloat') ? (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : property] = styles[property]; return element; }, setOpacity: function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; return element; }, getDimensions: function(element) { element = $(element); var display = Element.getStyle(element, 'display'); if (display != 'none' && display != null) // Safari bug return {width: element.offsetWidth, height: element.offsetHeight}; var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; var originalDisplay = els.display; els.visibility = 'hidden'; if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari els.position = 'absolute'; els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = originalDisplay; els.position = originalPosition; els.visibility = originalVisibility; return {width: originalWidth, height: originalHeight}; }, makePositioned: function(element) { element = $(element); var pos = Element.getStyle(element, 'position'); if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; if (Prototype.Browser.Opera) { element.style.top = 0; element.style.left = 0; } } return element; }, undoPositioned: function(element) { element = $(element); if (element._madePositioned) { element._madePositioned = undefined; element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; } return element; }, makeClipping: function(element) { element = $(element); if (element._overflow) return element; element._overflow = Element.getStyle(element, 'overflow') || 'auto'; if (element._overflow !== 'hidden') element.style.overflow = 'hidden'; return element; }, undoClipping: function(element) { element = $(element); if (!element._overflow) return element; element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; element._overflow = null; return element; }, cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return Element._returnOffset(valueL, valueT); }, positionedOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { if (element.tagName.toUpperCase() == 'BODY') break; var p = Element.getStyle(element, 'position'); if (p !== 'static') break; } } while (element); return Element._returnOffset(valueL, valueT); }, absolutize: function(element) { element = $(element); if (Element.getStyle(element, 'position') == 'absolute') return element; var offsets = Element.positionedOffset(element); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; var height = element.clientHeight; element._originalLeft = left - parseFloat(element.style.left || 0); element._originalTop = top - parseFloat(element.style.top || 0); element._originalWidth = element.style.width; element._originalHeight = element.style.height; element.style.position = 'absolute'; element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.width = width + 'px'; element.style.height = height + 'px'; return element; }, relativize: function(element) { element = $(element); if (Element.getStyle(element, 'position') == 'relative') return element; element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.height = element._originalHeight; element.style.width = element._originalWidth; return element; }, cumulativeScrollOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode; } while (element); return Element._returnOffset(valueL, valueT); }, getOffsetParent: function(element) { if (element.offsetParent) return $(element.offsetParent); if (element == document.body) return $(element); while ((element = element.parentNode) && element != document.body) if (Element.getStyle(element, 'position') != 'static') return $(element); return $(document.body); }, viewportOffset: function(forElement) { var valueT = 0, valueL = 0; var element = forElement; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body && Element.getStyle(element, 'position') == 'absolute') break; } while (element = element.offsetParent); element = forElement; do { if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { valueT -= element.scrollTop || 0; valueL -= element.scrollLeft || 0; } } while (element = element.parentNode); return Element._returnOffset(valueL, valueT); }, clonePosition: function(element, source) { var options = Object.extend({ setLeft: true, setTop: true, setWidth: true, setHeight: true, offsetTop: 0, offsetLeft: 0 }, arguments[2] || { }); source = $(source); var p = Element.viewportOffset(source); element = $(element); var delta = [0, 0]; var parent = null; if (Element.getStyle(element, 'position') == 'absolute') { parent = Element.getOffsetParent(element); delta = Element.viewportOffset(parent); } if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop; } if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if (options.setWidth) element.style.width = source.offsetWidth + 'px'; if (options.setHeight) element.style.height = source.offsetHeight + 'px'; return element; } }; Object.extend(Element.Methods, { getElementsBySelector: Element.Methods.select, childElements: Element.Methods.immediateDescendants }); Element._attributeTranslations = { write: { names: { className: 'class', htmlFor: 'for' }, values: { } } }; if (Prototype.Browser.Opera) { Element.Methods.getStyle = Element.Methods.getStyle.wrap( function(proceed, element, style) { switch (style) { case 'left': case 'top': case 'right': case 'bottom': if (proceed(element, 'position') === 'static') return null; case 'height': case 'width': if (!Element.visible(element)) return null; var dim = parseInt(proceed(element, style), 10); if (dim !== element['offset' + style.capitalize()]) return dim + 'px'; var properties; if (style === 'height') { properties = ['border-top-width', 'padding-top', 'padding-bottom', 'border-bottom-width']; } else { properties = ['border-left-width', 'padding-left', 'padding-right', 'border-right-width']; } return properties.inject(dim, function(memo, property) { var val = proceed(element, property); return val === null ? memo : memo - parseInt(val, 10); }) + 'px'; default: return proceed(element, style); } } ); Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( function(proceed, element, attribute) { if (attribute === 'title') return element.title; return proceed(element, attribute); } ); } else if (Prototype.Browser.IE) { Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( function(proceed, element) { element = $(element); try { element.offsetParent } catch(e) { return $(document.body) } var position = element.getStyle('position'); if (position !== 'static') return proceed(element); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); return value; } ); $w('positionedOffset viewportOffset').each(function(method) { Element.Methods[method] = Element.Methods[method].wrap( function(proceed, element) { element = $(element); try { element.offsetParent } catch(e) { return Element._returnOffset(0,0) } var position = element.getStyle('position'); if (position !== 'static') return proceed(element); var offsetParent = element.getOffsetParent(); if (offsetParent && offsetParent.getStyle('position') === 'fixed') offsetParent.setStyle({ zoom: 1 }); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); return value; } ); }); Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( function(proceed, element) { try { element.offsetParent } catch(e) { return Element._returnOffset(0,0) } return proceed(element); } ); Element.Methods.getStyle = function(element, style) { element = $(element); style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); var value = element.style[style]; if (!value && element.currentStyle) value = element.currentStyle[style]; if (style == 'opacity') { if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) if (value[1]) return parseFloat(value[1]) / 100; return 1.0; } if (value == 'auto') { if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) return element['offset' + style.capitalize()] + 'px'; return null; } return value; }; Element.Methods.setOpacity = function(element, value) { function stripAlpha(filter){ return filter.replace(/alpha\([^\)]*\)/gi,''); } element = $(element); var currentStyle = element.currentStyle; if ((currentStyle && !currentStyle.hasLayout) || (!currentStyle && element.style.zoom == 'normal')) element.style.zoom = 1; var filter = element.getStyle('filter'), style = element.style; if (value == 1 || value === '') { (filter = stripAlpha(filter)) ? style.filter = filter : style.removeAttribute('filter'); return element; } else if (value < 0.00001) value = 0; style.filter = stripAlpha(filter) + 'alpha(opacity=' + (value * 100) + ')'; return element; }; Element._attributeTranslations = (function(){ var classProp = 'className'; var forProp = 'for'; var el = document.createElement('div'); el.setAttribute(classProp, 'x'); if (el.className !== 'x') { el.setAttribute('class', 'x'); if (el.className === 'x') { classProp = 'class'; } } el = null; el = document.createElement('label'); el.setAttribute(forProp, 'x'); if (el.htmlFor !== 'x') { el.setAttribute('htmlFor', 'x'); if (el.htmlFor === 'x') { forProp = 'htmlFor'; } } el = null; return { read: { names: { 'class': classProp, 'className': classProp, 'for': forProp, 'htmlFor': forProp }, values: { _getAttr: function(element, attribute) { return element.getAttribute(attribute); }, _getAttr2: function(element, attribute) { return element.getAttribute(attribute, 2); }, _getAttrNode: function(element, attribute) { var node = element.getAttributeNode(attribute); return node ? node.value : ""; }, _getEv: (function(){ var el = document.createElement('div'); el.onclick = Prototype.emptyFunction; var value = el.getAttribute('onclick'); var f; if (String(value).indexOf('{') > -1) { f = function(element, attribute) { attribute = element.getAttribute(attribute); if (!attribute) return null; attribute = attribute.toString(); attribute = attribute.split('{')[1]; attribute = attribute.split('}')[0]; return attribute.strip(); }; } else if (value === '') { f = function(element, attribute) { attribute = element.getAttribute(attribute); if (!attribute) return null; return attribute.strip(); }; } el = null; return f; })(), _flag: function(element, attribute) { return $(element).hasAttribute(attribute) ? attribute : null; }, style: function(element) { return element.style.cssText.toLowerCase(); }, title: function(element) { return element.title; } } } } })(); Element._attributeTranslations.write = { names: Object.extend({ cellpadding: 'cellPadding', cellspacing: 'cellSpacing' }, Element._attributeTranslations.read.names), values: { checked: function(element, value) { element.checked = !!value; }, style: function(element, value) { element.style.cssText = value ? value : ''; } } }; Element._attributeTranslations.has = {}; $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; Element._attributeTranslations.has[attr.toLowerCase()] = attr; }); (function(v) { Object.extend(v, { href: v._getAttr2, src: v._getAttr2, type: v._getAttr, action: v._getAttrNode, disabled: v._flag, checked: v._flag, readonly: v._flag, multiple: v._flag, onload: v._getEv, onunload: v._getEv, onclick: v._getEv, ondblclick: v._getEv, onmousedown: v._getEv, onmouseup: v._getEv, onmouseover: v._getEv, onmousemove: v._getEv, onmouseout: v._getEv, onfocus: v._getEv, onblur: v._getEv, onkeypress: v._getEv, onkeydown: v._getEv, onkeyup: v._getEv, onsubmit: v._getEv, onreset: v._getEv, onselect: v._getEv, onchange: v._getEv }); })(Element._attributeTranslations.read.values); if (Prototype.BrowserFeatures.ElementExtensions) { (function() { function _descendants(element) { var nodes = element.getElementsByTagName('*'), results = []; for (var i = 0, node; node = nodes[i]; i++) if (node.tagName !== "!") // Filter out comment nodes. results.push(node); return results; } Element.Methods.down = function(element, expression, index) { element = $(element); if (arguments.length == 1) return element.firstDescendant(); return Object.isNumber(expression) ? _descendants(element)[expression] : Element.select(element, expression)[index || 0]; } })(); } } else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1) ? 0.999999 : (value === '') ? '' : (value < 0.00001) ? 0 : value; return element; }; } else if (Prototype.Browser.WebKit) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; if (value == 1) if(element.tagName.toUpperCase() == 'IMG' && element.width) { element.width++; element.width--; } else try { var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n); } catch (e) { } return element; }; Element.Methods.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break; element = element.offsetParent; } while (element); return Element._returnOffset(valueL, valueT); }; } if ('outerHTML' in document.documentElement) { Element.Methods.replace = function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { element.parentNode.replaceChild(content, element); return element; } content = Object.toHTML(content); var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); if (Element._insertionTranslations.tags[tagName]) { var nextSibling = element.next(); var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); parent.removeChild(element); if (nextSibling) fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); else fragments.each(function(node) { parent.appendChild(node) }); } else element.outerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element; }; } Element._returnOffset = function(l, t) { var result = [l, t]; result.left = l; result.top = t; return result; }; Element._getContentFromAnonymousElement = function(tagName, html) { var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; if (t) { div.innerHTML = t[0] + html + t[1]; t[2].times(function() { div = div.firstChild }); } else div.innerHTML = html; return $A(div.childNodes); }; Element._insertionTranslations = { before: function(element, node) { element.parentNode.insertBefore(node, element); }, top: function(element, node) { element.insertBefore(node, element.firstChild); }, bottom: function(element, node) { element.appendChild(node); }, after: function(element, node) { element.parentNode.insertBefore(node, element.nextSibling); }, tags: { TABLE: ['', '
', 1], TBODY: ['', '
', 2], TR: ['', '
', 3], TD: ['
', '
', 4], SELECT: ['', 1] } }; (function() { var tags = Element._insertionTranslations.tags; Object.extend(tags, { THEAD: tags.TBODY, TFOOT: tags.TBODY, TH: tags.TD }); })(); Element.Methods.Simulated = { hasAttribute: function(element, attribute) { attribute = Element._attributeTranslations.has[attribute] || attribute; var node = $(element).getAttributeNode(attribute); return !!(node && node.specified); } }; Element.Methods.ByTag = { }; Object.extend(Element, Element.Methods); (function(div) { if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { window.HTMLElement = { }; window.HTMLElement.prototype = div['__proto__']; Prototype.BrowserFeatures.ElementExtensions = true; } div = null; })(document.createElement('div')) Element.extend = (function() { function checkDeficiency(tagName) { if (typeof window.Element != 'undefined') { var proto = window.Element.prototype; if (proto) { var id = '_' + (Math.random()+'').slice(2); var el = document.createElement(tagName); proto[id] = 'x'; var isBuggy = (el[id] !== 'x'); delete proto[id]; el = null; return isBuggy; } } return false; } function extendElementWith(element, methods) { for (var property in methods) { var value = methods[property]; if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize(); } } var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); if (Prototype.BrowserFeatures.SpecificElementExtensions) { if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { return function(element) { if (element && typeof element._extendedByPrototype == 'undefined') { var t = element.tagName; if (t && (/^(?:object|applet|embed)$/i.test(t))) { extendElementWith(element, Element.Methods); extendElementWith(element, Element.Methods.Simulated); extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); } } return element; } } return Prototype.K; } var Methods = { }, ByTag = Element.Methods.ByTag; var extend = Object.extend(function(element) { if (!element || typeof element._extendedByPrototype != 'undefined' || element.nodeType != 1 || element == window) return element; var methods = Object.clone(Methods), tagName = element.tagName.toUpperCase(); if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); extendElementWith(element, methods); element._extendedByPrototype = Prototype.emptyFunction; return element; }, { refresh: function() { if (!Prototype.BrowserFeatures.ElementExtensions) { Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated); } } }); extend.refresh(); return extend; })(); Element.hasAttribute = function(element, attribute) { if (element.hasAttribute) return element.hasAttribute(attribute); return Element.Methods.Simulated.hasAttribute(element, attribute); }; Element.addMethods = function(methods) { var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; if (!methods) { Object.extend(Form, Form.Methods); Object.extend(Form.Element, Form.Element.Methods); Object.extend(Element.Methods.ByTag, { "FORM": Object.clone(Form.Methods), "INPUT": Object.clone(Form.Element.Methods), "SELECT": Object.clone(Form.Element.Methods), "TEXTAREA": Object.clone(Form.Element.Methods) }); } if (arguments.length == 2) { var tagName = methods; methods = arguments[1]; } if (!tagName) Object.extend(Element.Methods, methods || { }); else { if (Object.isArray(tagName)) tagName.each(extend); else extend(tagName); } function extend(tagName) { tagName = tagName.toUpperCase(); if (!Element.Methods.ByTag[tagName]) Element.Methods.ByTag[tagName] = { }; Object.extend(Element.Methods.ByTag[tagName], methods); } function copy(methods, destination, onlyIfAbsent) { onlyIfAbsent = onlyIfAbsent || false; for (var property in methods) { var value = methods[property]; if (!Object.isFunction(value)) continue; if (!onlyIfAbsent || !(property in destination)) destination[property] = value.methodize(); } } function findDOMClass(tagName) { var klass; var trans = { "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": "FrameSet", "IFRAME": "IFrame" }; if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName.capitalize() + 'Element'; if (window[klass]) return window[klass]; var element = document.createElement(tagName); var proto = element['__proto__'] || element.constructor.prototype; element = null; return proto; } var elementPrototype = window.HTMLElement ? HTMLElement.prototype : Element.prototype; if (F.ElementExtensions) { copy(Element.Methods, elementPrototype); copy(Element.Methods.Simulated, elementPrototype, true); } if (F.SpecificElementExtensions) { for (var tag in Element.Methods.ByTag) { var klass = findDOMClass(tag); if (Object.isUndefined(klass)) continue; copy(T[tag], klass.prototype); } } Object.extend(Element, Element.Methods); delete Element.ByTag; if (Element.extend.refresh) Element.extend.refresh(); Element.cache = { }; }; document.viewport = { getDimensions: function() { return { width: this.getWidth(), height: this.getHeight() }; }, getScrollOffsets: function() { return Element._returnOffset( window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); } }; (function(viewport) { var B = Prototype.Browser, doc = document, element, property = {}; function getRootElement() { if (B.WebKit && !doc.evaluate) return document; if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) return document.body; return document.documentElement; } function define(D) { if (!element) element = getRootElement(); property[D] = 'client' + D; viewport['get' + D] = function() { return element[property[D]] }; return viewport['get' + D](); } viewport.getWidth = define.curry('Width'); viewport.getHeight = define.curry('Height'); })(document.viewport); Element.Storage = { UID: 1 }; Element.addMethods({ getStorage: function(element) { if (!(element = $(element))) return; var uid; if (element === window) { uid = 0; } else { if (typeof element._prototypeUID === "undefined") element._prototypeUID = [Element.Storage.UID++]; uid = element._prototypeUID[0]; } if (!Element.Storage[uid]) Element.Storage[uid] = $H(); return Element.Storage[uid]; }, store: function(element, key, value) { if (!(element = $(element))) return; if (arguments.length === 2) { Element.getStorage(element).update(key); } else { Element.getStorage(element).set(key, value); } return element; }, retrieve: function(element, key, defaultValue) { if (!(element = $(element))) return; var hash = Element.getStorage(element), value = hash.get(key); if (Object.isUndefined(value)) { hash.set(key, defaultValue); value = defaultValue; } return value; }, clone: function(element, deep) { if (!(element = $(element))) return; var clone = element.cloneNode(deep); clone._prototypeUID = void 0; if (deep) { var descendants = Element.select(clone, '*'), i = descendants.length; while (i--) { descendants[i]._prototypeUID = void 0; } } return Element.extend(clone); } }); /* Portions of the Selector class are derived from Jack Slocum's DomQuery, * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style * license. Please see http://www.yui-ext.com/ for more information. */ var Selector = Class.create({ initialize: function(expression) { this.expression = expression.strip(); if (this.shouldUseSelectorsAPI()) { this.mode = 'selectorsAPI'; } else if (this.shouldUseXPath()) { this.mode = 'xpath'; this.compileXPathMatcher(); } else { this.mode = "normal"; this.compileMatcher(); } }, shouldUseXPath: (function() { var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ var isBuggy = false; if (document.evaluate && window.XPathResult) { var el = document.createElement('div'); el.innerHTML = '
'; var xpath = ".//*[local-name()='ul' or local-name()='UL']" + "//*[local-name()='li' or local-name()='LI']"; var result = document.evaluate(xpath, el, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); isBuggy = (result.snapshotLength !== 2); el = null; } return isBuggy; })(); return function() { if (!Prototype.BrowserFeatures.XPath) return false; var e = this.expression; if (Prototype.Browser.WebKit && (e.include("-of-type") || e.include(":empty"))) return false; if ((/(\[[\w-]*?:|:checked)/).test(e)) return false; if (IS_DESCENDANT_SELECTOR_BUGGY) return false; return true; } })(), shouldUseSelectorsAPI: function() { if (!Prototype.BrowserFeatures.SelectorsAPI) return false; if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; if (!Selector._div) Selector._div = new Element('div'); try { Selector._div.querySelector(this.expression); } catch(e) { return false; } return true; }, compileMatcher: function() { var e = this.expression, ps = Selector.patterns, h = Selector.handlers, c = Selector.criteria, le, p, m, len = ps.length, name; if (Selector._cache[e]) { this.matcher = Selector._cache[e]; return; } this.matcher = ["this.matcher = function(root) {", "var r = root, h = Selector.handlers, c = false, n;"]; while (e && le != e && (/\S/).test(e)) { le = e; for (var i = 0; i"; } }); if (Prototype.BrowserFeatures.SelectorsAPI && document.compatMode === 'BackCompat') { Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ var div = document.createElement('div'), span = document.createElement('span'); div.id = "prototype_test_id"; span.className = 'Test'; div.appendChild(span); var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); div = span = null; return isIgnored; })(); } Object.extend(Selector, { _cache: { }, xpath: { descendant: "//*", child: "/*", adjacent: "/following-sibling::*[1]", laterSibling: '/following-sibling::*', tagName: function(m) { if (m[1] == '*') return ''; return "[local-name()='" + m[1].toLowerCase() + "' or local-name()='" + m[1].toUpperCase() + "']"; }, className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", id: "[@id='#{1}']", attrPresence: function(m) { m[1] = m[1].toLowerCase(); return new Template("[@#{1}]").evaluate(m); }, attr: function(m) { m[1] = m[1].toLowerCase(); m[3] = m[5] || m[6]; return new Template(Selector.xpath.operators[m[2]]).evaluate(m); }, pseudo: function(m) { var h = Selector.xpath.pseudos[m[1]]; if (!h) return ''; if (Object.isFunction(h)) return h(m); return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); }, operators: { '=': "[@#{1}='#{3}']", '!=': "[@#{1}!='#{3}']", '^=': "[starts-with(@#{1}, '#{3}')]", '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", '*=': "[contains(@#{1}, '#{3}')]", '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" }, pseudos: { 'first-child': '[not(preceding-sibling::*)]', 'last-child': '[not(following-sibling::*)]', 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 'empty': "[count(*) = 0 and (count(text()) = 0)]", 'checked': "[@checked]", 'disabled': "[(@disabled) and (@type!='hidden')]", 'enabled': "[not(@disabled) and (@type!='hidden')]", 'not': function(m) { var e = m[6], p = Selector.patterns, x = Selector.xpath, le, v, len = p.length, name; var exclusion = []; while (e && le != e && (/\S/).test(e)) { le = e; for (var i = 0; i= 0)]"; return new Template(predicate).evaluate({ fragment: fragment, a: a, b: b }); } } } }, criteria: { tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', className: 'n = h.className(n, r, "#{1}", c); c = false;', id: 'n = h.id(n, r, "#{1}", c); c = false;', attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', attr: function(m) { m[3] = (m[5] || m[6]); return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); }, pseudo: function(m) { if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); }, descendant: 'c = "descendant";', child: 'c = "child";', adjacent: 'c = "adjacent";', laterSibling: 'c = "laterSibling";' }, patterns: [ { name: 'laterSibling', re: /^\s*~\s*/ }, { name: 'child', re: /^\s*>\s*/ }, { name: 'adjacent', re: /^\s*\+\s*/ }, { name: 'descendant', re: /^\s/ }, { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } ], assertions: { tagName: function(element, matches) { return matches[1].toUpperCase() == element.tagName.toUpperCase(); }, className: function(element, matches) { return Element.hasClassName(element, matches[1]); }, id: function(element, matches) { return element.id === matches[1]; }, attrPresence: function(element, matches) { return Element.hasAttribute(element, matches[1]); }, attr: function(element, matches) { var nodeValue = Element.readAttribute(element, matches[1]); return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); } }, handlers: { concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) a.push(node); return a; }, mark: function(nodes) { var _true = Prototype.emptyFunction; for (var i = 0, node; node = nodes[i]; i++) node._countedByPrototype = _true; return nodes; }, unmark: (function(){ var PROPERTIES_ATTRIBUTES_MAP = (function(){ var el = document.createElement('div'), isBuggy = false, propName = '_countedByPrototype', value = 'x' el[propName] = value; isBuggy = (el.getAttribute(propName) === value); el = null; return isBuggy; })(); return PROPERTIES_ATTRIBUTES_MAP ? function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node.removeAttribute('_countedByPrototype'); return nodes; } : function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node._countedByPrototype = void 0; return nodes; } })(), index: function(parentNode, reverse, ofType) { parentNode._countedByPrototype = Prototype.emptyFunction; if (reverse) { for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { var node = nodes[i]; if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; } } else { for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; } }, unique: function(nodes) { if (nodes.length == 0) return nodes; var results = [], n; for (var i = 0, l = nodes.length; i < l; i++) if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { n._countedByPrototype = Prototype.emptyFunction; results.push(Element.extend(n)); } return Selector.handlers.unmark(results); }, descendant: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName('*')); return results; }, child: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) { for (var j = 0, child; child = node.childNodes[j]; j++) if (child.nodeType == 1 && child.tagName != '!') results.push(child); } return results; }, adjacent: function(nodes) { for (var i = 0, results = [], node; node = nodes[i]; i++) { var next = this.nextElementSibling(node); if (next) results.push(next); } return results; }, laterSibling: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, Element.nextSiblings(node)); return results; }, nextElementSibling: function(node) { while (node = node.nextSibling) if (node.nodeType == 1) return node; return null; }, previousElementSibling: function(node) { while (node = node.previousSibling) if (node.nodeType == 1) return node; return null; }, tagName: function(nodes, root, tagName, combinator) { var uTagName = tagName.toUpperCase(); var results = [], h = Selector.handlers; if (nodes) { if (combinator) { if (combinator == "descendant") { for (var i = 0, node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName(tagName)); return results; } else nodes = this[combinator](nodes); if (tagName == "*") return nodes; } for (var i = 0, node; node = nodes[i]; i++) if (node.tagName.toUpperCase() === uTagName) results.push(node); return results; } else return root.getElementsByTagName(tagName); }, id: function(nodes, root, id, combinator) { var targetNode = $(id), h = Selector.handlers; if (root == document) { if (!targetNode) return []; if (!nodes) return [targetNode]; } else { if (!root.sourceIndex || root.sourceIndex < 1) { var nodes = root.getElementsByTagName('*'); for (var j = 0, node; node = nodes[j]; j++) { if (node.id === id) return [node]; } } } if (nodes) { if (combinator) { if (combinator == 'child') { for (var i = 0, node; node = nodes[i]; i++) if (targetNode.parentNode == node) return [targetNode]; } else if (combinator == 'descendant') { for (var i = 0, node; node = nodes[i]; i++) if (Element.descendantOf(targetNode, node)) return [targetNode]; } else if (combinator == 'adjacent') { for (var i = 0, node; node = nodes[i]; i++) if (Selector.handlers.previousElementSibling(targetNode) == node) return [targetNode]; } else nodes = h[combinator](nodes); } for (var i = 0, node; node = nodes[i]; i++) if (node == targetNode) return [targetNode]; return []; } return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; }, className: function(nodes, root, className, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); return Selector.handlers.byClassName(nodes, root, className); }, byClassName: function(nodes, root, className) { if (!nodes) nodes = Selector.handlers.descendant([root]); var needle = ' ' + className + ' '; for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { nodeClassName = node.className; if (nodeClassName.length == 0) continue; if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) results.push(node); } return results; }, attrPresence: function(nodes, root, attr, combinator) { if (!nodes) nodes = root.getElementsByTagName("*"); if (nodes && combinator) nodes = this[combinator](nodes); var results = []; for (var i = 0, node; node = nodes[i]; i++) if (Element.hasAttribute(node, attr)) results.push(node); return results; }, attr: function(nodes, root, attr, value, operator, combinator) { if (!nodes) nodes = root.getElementsByTagName("*"); if (nodes && combinator) nodes = this[combinator](nodes); var handler = Selector.operators[operator], results = []; for (var i = 0, node; node = nodes[i]; i++) { var nodeValue = Element.readAttribute(node, attr); if (nodeValue === null) continue; if (handler(nodeValue, value)) results.push(node); } return results; }, pseudo: function(nodes, name, value, root, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); if (!nodes) nodes = root.getElementsByTagName("*"); return Selector.pseudos[name](nodes, value, root); } }, pseudos: { 'first-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.previousElementSibling(node)) continue; results.push(node); } return results; }, 'last-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.nextElementSibling(node)) continue; results.push(node); } return results; }, 'only-child': function(nodes, value, root) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) results.push(node); return results; }, 'nth-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root); }, 'nth-last-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true); }, 'nth-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, false, true); }, 'nth-last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true, true); }, 'first-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, false, true); }, 'last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, true, true); }, 'only-of-type': function(nodes, formula, root) { var p = Selector.pseudos; return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); }, getIndices: function(a, b, total) { if (a == 0) return b > 0 ? [b] : []; return $R(1, total).inject([], function(memo, i) { if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); return memo; }); }, nth: function(nodes, formula, root, reverse, ofType) { if (nodes.length == 0) return []; if (formula == 'even') formula = '2n+0'; if (formula == 'odd') formula = '2n+1'; var h = Selector.handlers, results = [], indexed = [], m; h.mark(nodes); for (var i = 0, node; node = nodes[i]; i++) { if (!node.parentNode._countedByPrototype) { h.index(node.parentNode, reverse, ofType); indexed.push(node.parentNode); } } if (formula.match(/^\d+$/)) { // just a number formula = Number(formula); for (var i = 0, node; node = nodes[i]; i++) if (node.nodeIndex == formula) results.push(node); } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b if (m[1] == "-") m[1] = -1; var a = m[1] ? Number(m[1]) : 1; var b = m[2] ? Number(m[2]) : 0; var indices = Selector.pseudos.getIndices(a, b, nodes.length); for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { for (var j = 0; j < l; j++) if (node.nodeIndex == indices[j]) results.push(node); } } h.unmark(nodes); h.unmark(indexed); return results; }, 'empty': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (node.tagName == '!' || node.firstChild) continue; results.push(node); } return results; }, 'not': function(nodes, selector, root) { var h = Selector.handlers, selectorType, m; var exclusions = new Selector(selector).findElements(root); h.mark(exclusions); for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node._countedByPrototype) results.push(node); h.unmark(exclusions); return results; }, 'enabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node.disabled && (!node.type || node.type !== 'hidden')) results.push(node); return results; }, 'disabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.disabled) results.push(node); return results; }, 'checked': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.checked) results.push(node); return results; } }, operators: { '=': function(nv, v) { return nv == v; }, '!=': function(nv, v) { return nv != v; }, '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + '-').include('-' + (v || "").toUpperCase() + '-'); } }, split: function(expression) { var expressions = []; expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { expressions.push(m[1].strip()); }); return expressions; }, matchElements: function(elements, expression) { var matches = $$(expression), h = Selector.handlers; h.mark(matches); for (var i = 0, results = [], element; element = elements[i]; i++) if (element._countedByPrototype) results.push(element); h.unmark(matches); return results; }, findElement: function(elements, expression, index) { if (Object.isNumber(expression)) { index = expression; expression = false; } return Selector.matchElements(elements, expression || '*')[index || 0]; }, findChildElements: function(element, expressions) { expressions = Selector.split(expressions.join(',')); var results = [], h = Selector.handlers; for (var i = 0, l = expressions.length, selector; i < l; i++) { selector = new Selector(expressions[i].strip()); h.concat(results, selector.findElements(element)); } return (l > 1) ? h.unique(results) : results; } }); if (Prototype.Browser.IE) { Object.extend(Selector.handlers, { concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) if (node.tagName !== "!") a.push(node); return a; } }); } function $$() { return Selector.findChildElements(document, $A(arguments)); } var Form = { reset: function(form) { form = $(form); form.reset(); return form; }, serializeElements: function(elements, options) { if (typeof options != 'object') options = { hash: !!options }; else if (Object.isUndefined(options.hash)) options.hash = true; var key, value, submitted = false, submit = options.submit; var data = elements.inject({ }, function(result, element) { if (!element.disabled && element.name) { key = element.name; value = $(element).getValue(); if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) { if (key in result) { if (!Object.isArray(result[key])) result[key] = [result[key]]; result[key].push(value); } else result[key] = value; } } return result; }); return options.hash ? data : Object.toQueryString(data); } }; Form.Methods = { serialize: function(form, options) { return Form.serializeElements(Form.getElements(form), options); }, getElements: function(form) { var elements = $(form).getElementsByTagName('*'), element, arr = [ ], serializers = Form.Element.Serializers; for (var i = 0; element = elements[i]; i++) { arr.push(element); } return arr.inject([], function(elements, child) { if (serializers[child.tagName.toLowerCase()]) elements.push(Element.extend(child)); return elements; }) }, getInputs: function(form, typeName, name) { form = $(form); var inputs = form.getElementsByTagName('input'); if (!typeName && !name) return $A(inputs).map(Element.extend); for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { var input = inputs[i]; if ((typeName && input.type != typeName) || (name && input.name != name)) continue; matchingInputs.push(Element.extend(input)); } return matchingInputs; }, disable: function(form) { form = $(form); Form.getElements(form).invoke('disable'); return form; }, enable: function(form) { form = $(form); Form.getElements(form).invoke('enable'); return form; }, findFirstElement: function(form) { var elements = $(form).getElements().findAll(function(element) { return 'hidden' != element.type && !element.disabled; }); var firstByIndex = elements.findAll(function(element) { return element.hasAttribute('tabIndex') && element.tabIndex >= 0; }).sortBy(function(element) { return element.tabIndex }).first(); return firstByIndex ? firstByIndex : elements.find(function(element) { return /^(?:input|select|textarea)$/i.test(element.tagName); }); }, focusFirstElement: function(form) { form = $(form); form.findFirstElement().activate(); return form; }, request: function(form, options) { form = $(form), options = Object.clone(options || { }); var params = options.parameters, action = form.readAttribute('action') || ''; if (action.blank()) action = window.location.href; options.parameters = form.serialize(true); if (params) { if (Object.isString(params)) params = params.toQueryParams(); Object.extend(options.parameters, params); } if (form.hasAttribute('method') && !options.method) options.method = form.method; return new Ajax.Request(action, options); } }; /*--------------------------------------------------------------------------*/ Form.Element = { focus: function(element) { $(element).focus(); return element; }, select: function(element) { $(element).select(); return element; } }; Form.Element.Methods = { serialize: function(element) { element = $(element); if (!element.disabled && element.name) { var value = element.getValue(); if (value != undefined) { var pair = { }; pair[element.name] = value; return Object.toQueryString(pair); } } return ''; }, getValue: function(element) { element = $(element); var method = element.tagName.toLowerCase(); return Form.Element.Serializers[method](element); }, setValue: function(element, value) { element = $(element); var method = element.tagName.toLowerCase(); Form.Element.Serializers[method](element, value); return element; }, clear: function(element) { $(element).value = ''; return element; }, present: function(element) { return $(element).value != ''; }, activate: function(element) { element = $(element); try { element.focus(); if (element.select && (element.tagName.toLowerCase() != 'input' || !(/^(?:button|reset|submit)$/i.test(element.type)))) element.select(); } catch (e) { } return element; }, disable: function(element) { element = $(element); element.disabled = true; return element; }, enable: function(element) { element = $(element); element.disabled = false; return element; } }; /*--------------------------------------------------------------------------*/ var Field = Form.Element; var $F = Form.Element.Methods.getValue; /*--------------------------------------------------------------------------*/ Form.Element.Serializers = { input: function(element, value) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': return Form.Element.Serializers.inputSelector(element, value); default: return Form.Element.Serializers.textarea(element, value); } }, inputSelector: function(element, value) { if (Object.isUndefined(value)) return element.checked ? element.value : null; else element.checked = !!value; }, textarea: function(element, value) { if (Object.isUndefined(value)) return element.value; else element.value = value; }, select: function(element, value) { if (Object.isUndefined(value)) return this[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element); else { var opt, currentValue, single = !Object.isArray(value); for (var i = 0, length = element.length; i < length; i++) { opt = element.options[i]; currentValue = this.optionValue(opt); if (single) { if (currentValue == value) { opt.selected = true; return; } } else opt.selected = value.include(currentValue); } } }, selectOne: function(element) { var index = element.selectedIndex; return index >= 0 ? this.optionValue(element.options[index]) : null; }, selectMany: function(element) { var values, length = element.length; if (!length) return null; for (var i = 0, values = []; i < length; i++) { var opt = element.options[i]; if (opt.selected) values.push(this.optionValue(opt)); } return values; }, optionValue: function(opt) { return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; } }; /*--------------------------------------------------------------------------*/ Abstract.TimedObserver = Class.create(PeriodicalExecuter, { initialize: function($super, element, frequency, callback) { $super(callback, frequency); this.element = $(element); this.lastValue = this.getValue(); }, execute: function() { var value = this.getValue(); if (Object.isString(this.lastValue) && Object.isString(value) ? this.lastValue != value : String(this.lastValue) != String(value)) { this.callback(this.element, value); this.lastValue = value; } } }); Form.Element.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); Form.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.serialize(this.element); } }); /*--------------------------------------------------------------------------*/ Abstract.EventObserver = Class.create({ initialize: function(element, callback) { this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else this.registerCallback(this.element); }, onElementEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value; } }, registerFormCallbacks: function() { Form.getElements(this.element).each(this.registerCallback, this); }, registerCallback: function(element) { if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': Event.observe(element, 'click', this.onElementEvent.bind(this)); break; default: Event.observe(element, 'change', this.onElementEvent.bind(this)); break; } } } }); Form.Element.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.Element.getValue(this.element); } }); Form.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.serialize(this.element); } }); (function() { var Event = { KEY_BACKSPACE: 8, KEY_TAB: 9, KEY_RETURN: 13, KEY_ESC: 27, KEY_LEFT: 37, KEY_UP: 38, KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, KEY_HOME: 36, KEY_END: 35, KEY_PAGEUP: 33, KEY_PAGEDOWN: 34, KEY_INSERT: 45, cache: {} }; var docEl = document.documentElement; var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl && 'onmouseleave' in docEl; var _isButton; if (Prototype.Browser.IE) { var buttonMap = { 0: 1, 1: 4, 2: 2 }; _isButton = function(event, code) { return event.button === buttonMap[code]; }; } else if (Prototype.Browser.WebKit) { _isButton = function(event, code) { switch (code) { case 0: return event.which == 1 && !event.metaKey; case 1: return event.which == 1 && event.metaKey; default: return false; } }; } else { _isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code); }; } function isLeftClick(event) { return _isButton(event, 0) } function isMiddleClick(event) { return _isButton(event, 1) } function isRightClick(event) { return _isButton(event, 2) } function element(event) { event = Event.extend(event); var node = event.target, type = event.type, currentTarget = event.currentTarget; if (currentTarget && currentTarget.tagName) { if (type === 'load' || type === 'error' || (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' && currentTarget.type === 'radio')) node = currentTarget; } if (node.nodeType == Node.TEXT_NODE) node = node.parentNode; return Element.extend(node); } function findElement(event, expression) { var element = Event.element(event); if (!expression) return element; var elements = [element].concat(element.ancestors()); return Selector.findElement(elements, expression, 0); } function pointer(event) { return { x: pointerX(event), y: pointerY(event) }; } function pointerX(event) { var docElement = document.documentElement, body = document.body || { scrollLeft: 0 }; return event.pageX || (event.clientX + (docElement.scrollLeft || body.scrollLeft) - (docElement.clientLeft || 0)); } function pointerY(event) { var docElement = document.documentElement, body = document.body || { scrollTop: 0 }; return event.pageY || (event.clientY + (docElement.scrollTop || body.scrollTop) - (docElement.clientTop || 0)); } function stop(event) { Event.extend(event); event.preventDefault(); event.stopPropagation(); event.stopped = true; } Event.Methods = { isLeftClick: isLeftClick, isMiddleClick: isMiddleClick, isRightClick: isRightClick, element: element, findElement: findElement, pointer: pointer, pointerX: pointerX, pointerY: pointerY, stop: stop }; var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { m[name] = Event.Methods[name].methodize(); return m; }); if (Prototype.Browser.IE) { function _relatedTarget(event) { var element; switch (event.type) { case 'mouseover': element = event.fromElement; break; case 'mouseout': element = event.toElement; break; default: return null; } return Element.extend(element); } Object.extend(methods, { stopPropagation: function() { this.cancelBubble = true }, preventDefault: function() { this.returnValue = false }, inspect: function() { return '[object Event]' } }); Event.extend = function(event, element) { if (!event) return false; if (event._extendedByPrototype) return event; event._extendedByPrototype = Prototype.emptyFunction; var pointer = Event.pointer(event); Object.extend(event, { target: event.srcElement || element, relatedTarget: _relatedTarget(event), pageX: pointer.x, pageY: pointer.y }); return Object.extend(event, methods); }; } else { Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; Object.extend(Event.prototype, methods); Event.extend = Prototype.K; } function _createResponder(element, eventName, handler) { var registry = Element.retrieve(element, 'prototype_event_registry'); if (Object.isUndefined(registry)) { CACHE.push(element); registry = Element.retrieve(element, 'prototype_event_registry', $H()); } var respondersForEvent = registry.get(eventName); if (Object.isUndefined(respondersForEvent)) { respondersForEvent = []; registry.set(eventName, respondersForEvent); } if (respondersForEvent.pluck('handler').include(handler)) return false; var responder; if (eventName.include(":")) { responder = function(event) { if (Object.isUndefined(event.eventName)) return false; if (event.eventName !== eventName) return false; Event.extend(event, element); handler.call(element, event); }; } else { if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && (eventName === "mouseenter" || eventName === "mouseleave")) { if (eventName === "mouseenter" || eventName === "mouseleave") { responder = function(event) { Event.extend(event, element); var parent = event.relatedTarget; while (parent && parent !== element) { try { parent = parent.parentNode; } catch(e) { parent = element; } } if (parent === element) return; handler.call(element, event); }; } } else { responder = function(event) { Event.extend(event, element); handler.call(element, event); }; } } responder.handler = handler; respondersForEvent.push(responder); return responder; } function _destroyCache() { for (var i = 0, length = CACHE.length; i < length; i++) { Event.stopObserving(CACHE[i]); CACHE[i] = null; } } var CACHE = []; if (Prototype.Browser.IE) window.attachEvent('onunload', _destroyCache); if (Prototype.Browser.WebKit) window.addEventListener('unload', Prototype.emptyFunction, false); var _getDOMEventName = Prototype.K; if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { _getDOMEventName = function(eventName) { var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; return eventName in translations ? translations[eventName] : eventName; }; } function observe(element, eventName, handler) { element = $(element); var responder = _createResponder(element, eventName, handler); if (!responder) return element; if (eventName.include(':')) { if (element.addEventListener) element.addEventListener("dataavailable", responder, false); else { element.attachEvent("ondataavailable", responder); element.attachEvent("onfilterchange", responder); } } else { var actualEventName = _getDOMEventName(eventName); if (element.addEventListener) element.addEventListener(actualEventName, responder, false); else element.attachEvent("on" + actualEventName, responder); } return element; } function stopObserving(element, eventName, handler) { element = $(element); var registry = Element.retrieve(element, 'prototype_event_registry'); if (Object.isUndefined(registry)) return element; if (eventName && !handler) { var responders = registry.get(eventName); if (Object.isUndefined(responders)) return element; responders.each( function(r) { Element.stopObserving(element, eventName, r.handler); }); return element; } else if (!eventName) { registry.each( function(pair) { var eventName = pair.key, responders = pair.value; responders.each( function(r) { Element.stopObserving(element, eventName, r.handler); }); }); return element; } var responders = registry.get(eventName); if (!responders) return; var responder = responders.find( function(r) { return r.handler === handler; }); if (!responder) return element; var actualEventName = _getDOMEventName(eventName); if (eventName.include(':')) { if (element.removeEventListener) element.removeEventListener("dataavailable", responder, false); else { element.detachEvent("ondataavailable", responder); element.detachEvent("onfilterchange", responder); } } else { if (element.removeEventListener) element.removeEventListener(actualEventName, responder, false); else element.detachEvent('on' + actualEventName, responder); } registry.set(eventName, responders.without(responder)); return element; } function fire(element, eventName, memo, bubble) { element = $(element); if (Object.isUndefined(bubble)) bubble = true; if (element == document && document.createEvent && !element.dispatchEvent) element = document.documentElement; var event; if (document.createEvent) { event = document.createEvent('HTMLEvents'); event.initEvent('dataavailable', true, true); } else { event = document.createEventObject(); event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; } event.eventName = eventName; event.memo = memo || { }; if (document.createEvent) element.dispatchEvent(event); else element.fireEvent(event.eventType, event); return Event.extend(event); } Object.extend(Event, Event.Methods); Object.extend(Event, { fire: fire, observe: observe, stopObserving: stopObserving }); Element.addMethods({ fire: fire, observe: observe, stopObserving: stopObserving }); Object.extend(document, { fire: fire.methodize(), observe: observe.methodize(), stopObserving: stopObserving.methodize(), loaded: false }); if (window.Event) Object.extend(window.Event, Event); else window.Event = Event; })(); (function() { /* Support for the DOMContentLoaded event is based on work by Dan Webb, Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ var timer; function fireContentLoadedEvent() { if (document.loaded) return; if (timer) window.clearTimeout(timer); document.loaded = true; document.fire('dom:loaded'); } function checkReadyState() { if (document.readyState === 'complete') { document.stopObserving('readystatechange', checkReadyState); fireContentLoadedEvent(); } } function pollDoScroll() { try { document.documentElement.doScroll('left'); } catch(e) { timer = pollDoScroll.defer(); return; } fireContentLoadedEvent(); } if (document.addEventListener) { document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); } else { document.observe('readystatechange', checkReadyState); if (window == top) timer = pollDoScroll.defer(); } Event.observe(window, 'load', fireContentLoadedEvent); })(); Element.addMethods(); /*------------------------------- DEPRECATED -------------------------------*/ Hash.toQueryString = Object.toQueryString; var Toggle = { display: Element.toggle }; Element.Methods.childOf = Element.Methods.descendantOf; var Insertion = { Before: function(element, content) { return Element.insert(element, {before:content}); }, Top: function(element, content) { return Element.insert(element, {top:content}); }, Bottom: function(element, content) { return Element.insert(element, {bottom:content}); }, After: function(element, content) { return Element.insert(element, {after:content}); } }; var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); var Position = { includeScrollOffsets: false, prepare: function() { this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; this.deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; }, within: function(element, x, y) { if (this.includeScrollOffsets) return this.withinIncludingScrolloffsets(element, x, y); this.xcomp = x; this.ycomp = y; this.offset = Element.cumulativeOffset(element); return (y >= this.offset[1] && y < this.offset[1] + element.offsetHeight && x >= this.offset[0] && x < this.offset[0] + element.offsetWidth); }, withinIncludingScrolloffsets: function(element, x, y) { var offsetcache = Element.cumulativeScrollOffset(element); this.xcomp = x + offsetcache[0] - this.deltaX; this.ycomp = y + offsetcache[1] - this.deltaY; this.offset = Element.cumulativeOffset(element); return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + element.offsetHeight && this.xcomp >= this.offset[0] && this.xcomp < this.offset[0] + element.offsetWidth); }, overlap: function(mode, element) { if (!mode) return 0; if (mode == 'vertical') return ((this.offset[1] + element.offsetHeight) - this.ycomp) / element.offsetHeight; if (mode == 'horizontal') return ((this.offset[0] + element.offsetWidth) - this.xcomp) / element.offsetWidth; }, cumulativeOffset: Element.Methods.cumulativeOffset, positionedOffset: Element.Methods.positionedOffset, absolutize: function(element) { Position.prepare(); return Element.absolutize(element); }, relativize: function(element) { Position.prepare(); return Element.relativize(element); }, realOffset: Element.Methods.cumulativeScrollOffset, offsetParent: Element.Methods.getOffsetParent, page: Element.Methods.viewportOffset, clone: function(source, target, options) { options = options || { }; return Element.clonePosition(target, source, options); } }; /*--------------------------------------------------------------------------*/ if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ function iter(name) { return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; } instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? function(element, className) { className = className.toString().strip(); var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); return cond ? document._getElementsByXPath('.//*' + cond, element) : []; } : function(element, className) { className = className.toString().strip(); var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); if (!classNames && !className) return elements; var nodes = $(element).getElementsByTagName('*'); className = ' ' + className + ' '; for (var i = 0, child, cn; child = nodes[i]; i++) { if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || (classNames && classNames.all(function(name) { return !name.toString().blank() && cn.include(' ' + name + ' '); })))) elements.push(Element.extend(child)); } return elements; }; return function(className, parentElement) { return $(parentElement || document.body).getElementsByClassName(className); }; }(Element.Methods); /*--------------------------------------------------------------------------*/ Element.ClassNames = Class.create(); Element.ClassNames.prototype = { initialize: function(element) { this.element = $(element); }, _each: function(iterator) { this.element.className.split(/\s+/).select(function(name) { return name.length > 0; })._each(iterator); }, set: function(className) { this.element.className = className; }, add: function(classNameToAdd) { if (this.include(classNameToAdd)) return; this.set($A(this).concat(classNameToAdd).join(' ')); }, remove: function(classNameToRemove) { if (!this.include(classNameToRemove)) return; this.set($A(this).without(classNameToRemove).join(' ')); }, toString: function() { return $A(this).join(' '); } }; Object.extend(Element.ClassNames.prototype, Enumerable); /*--------------------------------------------------------------------------*/ mlpost-0.8.2/examples/radar.ml000066400000000000000000000016171306046515300163100ustar00rootroot00000000000000open Mlpost open Command open Num open Color open Box (*parse <> *) (*parse <> <> *) let _ = List.iter (fun (name,fig) -> Metapost.emit name (Picture.scale (Num.bp 3.) fig)) [ "radar1", radar1; "radar2", radar2; ] mlpost-0.8.2/examples/real_plot.ml000066400000000000000000000021611306046515300171730ustar00rootroot00000000000000open Mlpost open Real_plot open Printf (*parse <> *) (*parse < if f < 0. then None else Some (sqrt f)) "sqrt"; curve ceil "ceil"; curve floor "floor"; curve sin "sin"; curve_l [(fun f -> if f <= 0. then None else Some (1./.f)); (fun f -> if f >= 0. then None else Some (1./.f))] "$\\frac{1}{x}$"; ] in draw ~label:(fun x -> x) ~ymax:5. ~ymin:(-.5.) ~xmin:(-.5.) ~xmax:5. ~pitch:(0.01) ~width:(Num.cm 6.) ~height:(Num.cm 4.) graph (*parse >> < curve (fun f -> f**(1./.float_of_int i)) i) [2;3;4;8;12;15] in draw ~label:(sprintf "$\\sqrt[%i]{x}$") ~xmin:0. ~xmax:5. ~pitch:(0.01) ~width:(Num.cm 6.) ~height:(Num.cm 4.) curves (*parse >> *) let () = List.iter (fun (name,fig) -> Metapost.emit name (Picture.scale (Num.bp 3.) fig)) ["real_plot1",real_plot1; "real_plot2",real_plot2] mlpost-0.8.2/examples/style.css000066400000000000000000000017571306046515300165440ustar00rootroot00000000000000code,pre { color:black;background-color:white }a.Cannot { color:black;text-decoration:none }.Cannot:hover { background-color: #b4eeb4; } .Cbar, .Cdo, .Cdone, .Cdownto, .Celse, .Cfor, .Cif, .Clazy, .Cmatch, .Cnew, .Cor, .Cthen, .Cto, .Ctry, .Cwhen, .Cwhile, .Cwith { color: #77aaaa; } .Cassert, .Cinclude, .Copen { color: #cc9900; } .Cstring { color: #aa4444; } .Cand, .Cas, .Cclass, .Cconstraint, .Cexception, .Cexternal, .Cfun, .Cfunction, .Cfunctor, .Cin, .Cinherit, .Cinitializer, .Clet, .Cmethod, .Cmodule, .Cmutable, .Cof, .Cprivate, .Crec, .Ctype, .Cval, .Cvirtual { color: green; } .Cbackground { background-color: white; } .Craise { color: red; } .Cconstructor { color: #0033cc; } .Ccomment { color: #990000; } .Calphakeyword, .Casr, .Cland, .Clor, .Clsl, .Clsr, .Clxor, .Cmod { color: #808080; } .Clinenum { color: black; background-color: silver; } .Cbegin, .Cend, .Cobject, .Csig, .Cstruct { color: #990099; } .Cfalse, .Cnonalphakeyword, .Cquotation, .Ctrue { } .table { float:left; margin:5px;}mlpost-0.8.2/examples/terms.ml000066400000000000000000000072741306046515300163560ustar00rootroot00000000000000 (** Drawing terms using module [Triangle] *) open Mlpost open Num open Command open Color open Triangle let pen = Pen.scale 2. Pen.default let fill = lightred let test ~left ~right = let t = T.create ~pen ~fill ~left ~right ~depth:(bp 40.) () in T.draw ~debug:true t ++ Command.dotlabel ~pos:`Top (Picture.tex "n") (Box.north t) ++ Command.dotlabel ~pos:`Bot (Picture.tex "s") (Box.south t) ++ Command.dotlabel ~pos:`Left (Picture.tex "w") (Box.west t) ++ Command.dotlabel ~pos:`Right (Picture.tex "e") (Box.east t) ++ Command.dotlabel ~pos:`Topleft (Picture.tex "r") (T.root t) ++ Command.dotlabel ~pos:`Bottomleft (Picture.tex "bl") (T.bottom_left t) ++ Command.dotlabel ~pos:`Bottomright (Picture.tex "br") (T.bottom_right t) ++ nop let () = Metapost.emit "term-50-50" (test 50. 50.) let () = Metapost.emit "term-20-80" (test 20. 80.) let () = Metapost.emit "term--20-50" (test (-20.) (50.)) let x = let t = T.create ~fill:white ~depth:(bp 13.) () in T.tex_root_label "$x$" t let t40 = T.create ~left:0.5 ~depth:(bp 40.) () let anchor1 = let t1 = T.tex_label ~depth:0.5 "$\\sigma$" t40 in let t2 = T.anchor ~depth:1.0 ~x:0.3 t1 x in let t3 = T.anchor ~depth:1.0 ~x:0.7 t1 x in T.draw t1 ++ T.draw t2 ++ T.draw t3 let () = Metapost.emit "anchor1" anchor1 let pose = let t1 = T.pose_left ~x:0.2 t40 x in let t2 = T.pose_right ~x:0.8 t40 x in let t3 = T.pose_right ~x:0.95 ~depth:1.2 t40 (T.create ~fill:lightred ~depth:13. ()) in T.draw t40 ++ T.draw t1 ++ T.draw t2 ++ T.draw t3 let () = Metapost.emit "pose" pose let redex1 = let t1 = T.create ~left:0.5 ~depth:(bp 40.) () in let t1 = T.tex_root_label "$t$" t1 in let t = T.tex ~dx:2. ~dy:2. ~fill:lightred "$r$" in let t = T.tex_root_label "\\footnotesize$p$" t in let t = T.anchor ~depth:0.8 ~x:0.3 t1 t in T.draw t1 ++ T.draw t let () = Metapost.emit "redex1" redex1 let label1 = let t = T.create ~left:0.5 ~depth:(bp 40.) () in let t = T.tex_label "$\\sigma t$" t in T.draw t let () = Metapost.emit "label1" label1 let pic1 = let t = T.tex ~pen ~fill:lightred "TOT" in T.draw t let () = Metapost.emit "pic1" pic1 let x_depth = let t = T.create ~left:20. ~right:60. ~depth:70. () in let r = T.root t in let depth = 0.7 in let x0 = T.x_depth ~depth ~x:0. t in let x1 = T.x_depth ~depth ~x:1. t in let x = T.x_depth ~depth ~x:0.7 t in let p01 = Path.pathp [T.x_depth ~depth ~x:(-0.5) t; T.x_depth ~depth ~x:(1.5) t] in let p = Point.add r (Point.mult 1.8 (Point.sub x r)) in let pd = Path.pathp [r; p] in let b = T.x_depth ~depth:1. ~x:0.7 t in T.draw t ++ Command.dotlabel ~pos:`Topleft (Picture.tex "0") x0 ++ Command.dotlabel ~pos:`Topright (Picture.tex "1") x1 ++ Command.dotlabel ~pos:`Bottomleft (Picture.tex "x") x ++ Command.dotlabel ~pos:`Topleft (Picture.tex "0") r ++ Command.dotlabel ~pos:`Bottomleft (Picture.tex "1") b ++ Command.draw ~color:purple p01 ++ Command.draw ~color:red pd ++ nop let () = Metapost.emit "x_depth" x_depth let baader_138 = let t = T.create ~depth:50. ~width:120. () in let t = T.tex_label ~depth:0.35 "\\rmfamily$l_1$" t in let x = T.create ~depth:48. () in let x = T.tex_root_label "\\footnotesize$x$" x in let sl ?fill () = let s = T.create ?fill ~depth:24. () in T.tex_label "\\footnotesize$\\sigma_2\\l_2$" s in let s = sl () and sf = sl ~fill:lightred () in let sf = T.tex_label "\\footnotesize$\\sigma_2\\l_2$" sf in let x1 = T.anchor ~x:0.1 t x in let x1s = T.pose x1 s in let x2 = T.anchor ~x:0.5 t x in let x2s = T.pose x2 sf in let x3 = T.anchor ~x:0.9 t x in let x3s = T.pose x3 s in Command.iterl T.draw [t; x1; x1s; x2; x2s; x3; x3s] let () = Metapost.emit "baader_138" baader_138 mlpost-0.8.2/examples/tex.ml000066400000000000000000000006411306046515300160130ustar00rootroot00000000000000open Mlpost open Concrete open Command open Picture open CPoint let s = "Bonjour les amis $42_{la reponse}$" let p = let t = tex s in let bs = baselines s in let {x = left} = cpoint_of_point (west t) in let {x = right} = cpoint_of_point (east t) in let pl = List.map (fun e -> Path.path [left,e;right,e]) bs in let pl = List.map Path.draw pl in seq (t::pl) let () = Metapost.emit "baselines" p mlpost-0.8.2/examples/tree.ml000066400000000000000000000107271306046515300161600ustar00rootroot00000000000000open Mlpost open Box open Tree let sprintf = Format.sprintf (*parse <> *) (*parse <> <> <> <> <> <> <> <> < leaf (texint n) | n -> node ~arrow_style:Undirected (texint n) [fib (n-1); fib (n-2)] let tree9 = draw (fib 5) (*parse >> < Node (0, []) | n -> let (Node (_,l) as t) = bin (n-1) in Node (n, t :: l) let rec trans (Node (n,l)) = node ~arrow_style:Undirected (tex (sprintf "${2^{%d}}$" n)) (List.map trans l) let tree10 = draw (trans (bin 4)) (*parse >> < Node (point, []) | n -> let (Node (p,l) as t) = bin (n-1) in Node (p, t :: l) let rec to_tree (Node (b,l)) = node ~arrow_style:Undirected ~valign:`Right b (List.map to_tree l) let tree11 = draw (to_tree (bin 5)) (*parse >> < Tree.node e (List.map to_tree l) let node i e l = Node ([Aft i,tex e],l) let place_not_simple t = let module P = Place(Overlays_Boxlike(Box)) in let bplace t = Tree.to_box (to_tree t) in P.gen_place ~place:bplace t let tree_adv_draw t i = let keep e = try Some (assoq i e) with Not_found -> None in let t = filter_option keep t in let t_arrow = gen_draw_arrows Command.nop ~style:Helpers.draw_simple_arrow ~corner:Box.corner t in (Tree_adv.draw (fun x -> x) t) ++ (fold (++) Command.nop t_arrow) let mytree_placed = let t = node 0 "A" [ node 0 "B" [node 0 "D" [];node 0 "E" []]; node 0 "C" [node 1 "F" [];node 2 "G" []]] in place_not_simple t let tree12 = tree_adv_draw mytree_placed 0 (*parse >> <> <> *) let _ = List.iter (fun (name,fig) -> Metapost.emit name (Picture.scale (Num.bp 3.) fig)) [ "tree1", tree1; "tree2", tree2; "tree3", tree3; "tree4", tree4; "tree5", tree5; "tree6", tree6; "tree7", tree7; "tree8", tree8; "tree9", tree9; "tree10", tree10; "tree11", tree11; "tree12", tree12; "tree13", tree13; "tree14", tree14; ] mlpost-0.8.2/file.ml000066400000000000000000000122621306046515300143160ustar00rootroot00000000000000module LowLevel = struct (** delete a directory that may contain files *) let rmdir dir = Array.iter (fun x -> Sys.remove (Filename.concat dir x)) (Sys.readdir dir); Unix.rmdir dir (** copy a file to another *) let copy src dest = let cin = open_in src and cout = open_out dest and buff = String.make 1024 ' ' and n = ref 0 in while n := input cin buff 0 1024; !n <> 0 do output cout buff 0 !n done; close_in cin; close_out cout (** rename a file *) let move src dest = try Unix.rename src dest with Unix.Unix_error (Unix.EXDEV,_,_) -> copy src dest let read_from fn f = let c = open_in fn in let r = f c in close_in c; r let write_to filename f = let chan = open_out filename in let r = f chan in close_out chan; r let write_to_formatted filename f = write_to filename (fun chan -> let fmt = Format.formatter_of_out_channel chan in let r = f fmt in Format.fprintf fmt "@?"; r) let exists = Sys.file_exists let rm = Sys.remove end (* Filename.dir_sep in Ocaml >= 3.11.2 *) let dir_sep = match Sys.os_type with | "Cygwin" | "Unix" -> '/' | "Win32" -> '\\' | _ -> assert false let dir_sep_string = String.make 1 dir_sep module Dir = struct type t = { dirs : string list ; is_relative : bool } (* the type t is a stack of directories, innermost is on top *) let print_sep fmt () = Format.pp_print_char fmt dir_sep let to_string s = let prefix = if s.is_relative then "" else "/" in Misc.sprintf "%s%a" prefix (Misc.print_list print_sep Format.pp_print_string) (List.rev s.dirs) let rec eat_dirsep_back i s = if s.[i] = dir_sep then eat_dirsep_back (i-1) s else i let rec eat_dirsep_forw i s = if s.[i] = dir_sep then eat_dirsep_forw (i+1) s else i let split_sep s = let l = String.length s in if l = 0 then [] else let rec aux acc i = let i = eat_dirsep_forw i s in try let j = String.index_from s i dir_sep in let dir = String.sub s i (j-i) in let acc = dir::acc in if j = l-1 then acc else aux acc (j+1) with Not_found -> let j = eat_dirsep_back (l-1) s in (String.sub s i (j-i+1)) :: acc in aux [] 0 let from_string s = let f = { dirs = split_sep s; is_relative = Filename.is_relative s } in f let concat d1 d2 = assert d2.is_relative; { d1 with dirs = d2.dirs @ d1.dirs } let temp = from_string Filename.temp_dir_name let mk t rights = Unix.mkdir (to_string t) rights let ch t = Sys.chdir (to_string t) let cwd () = from_string (Sys.getcwd ()) let empty = { dirs = []; is_relative = true } let rm d = LowLevel.rmdir (to_string d) let compare = Pervasives.compare (* this one is actually difficult ... for now we just compare the elements *) end type t = { dir: Dir.t ; bn : string ; ext : string option } let dir t = t.dir let extension t = match t.ext with | Some s -> s | None -> "" let basename t = t.bn let file_to_string bn ext = match ext with | None -> bn | Some ext -> Misc.sprintf "%s.%s" bn ext let to_string t = let dir = Dir.to_string t.dir in let sep = if String.length dir <> 0 && dir.[String.length dir-1] <> '/' then "/" else "" in Misc.sprintf "%s%s%s" (Dir.to_string t.dir) sep (file_to_string t.bn t.ext) let debug_to_string t = Misc.sprintf "(%s,%s,%s)" (Dir.to_string t.dir) t.bn (extension t) exception Found of int let split_ext s = let l = String.length s in if s.[l-1] = '.' || s.[l-1] = dir_sep then s, None else try let i = String.rindex_from s (l-1) '.' in String.sub s 0 i, Some (String.sub s (i+1) (l-i-1)) with Not_found -> s, None let from_string s = let d = Dir.from_string s in match d.Dir.dirs with | [] -> { dir = d; bn = ""; ext = None } | fn::dirs -> let bn,ext = split_ext fn in { dir = { Dir.dirs = dirs; is_relative = d.Dir.is_relative}; bn = bn; ext = ext } let place d t = { t with dir = d } let concat d t = { t with dir = Dir.concat d t.dir } let append t s = { t with bn = t.bn ^ s } let prepend t s = { t with bn = s ^ t.bn } let set_ext t s = let ext = if s = "" then None else Some s in { t with ext = ext } let clear_dir t = { t with dir = Dir.empty } let compare a b = let c = Pervasives.compare a.bn b.bn in if c <> 0 then c else let c = Pervasives.compare a.ext b.ext in if c<> 0 then c else Dir.compare a.dir b.dir module Map = Map.Make(struct type t' = t type t = t' let compare = compare end) (** wrappers for low level functions *) let move a b = LowLevel.move (to_string a) (to_string b) let copy a b = LowLevel.copy (to_string a) (to_string b) let read_from t f = LowLevel.read_from (to_string t) f let write_to t f = LowLevel.write_to (to_string t) f let write_to_formatted t f = LowLevel.write_to_formatted (to_string t) f let exists t = LowLevel.exists (to_string t) let rm t = LowLevel.rm (to_string t) let open_out t = open_out (to_string t) let open_in t = open_in (to_string t) let open_in_gen f i t = open_in_gen f i (to_string t) let mk ?(dir = Dir.empty) bn ext = let ext = if ext = "" then None else Some ext in { dir = dir ; bn = bn ; ext = ext } mlpost-0.8.2/file.mli000066400000000000000000000036661306046515300144770ustar00rootroot00000000000000module LowLevel : sig val move : string -> string -> unit val copy : string -> string -> unit val rmdir : string -> unit val rm : string -> unit val read_from : string -> (in_channel -> 'a) -> 'a val write_to : string -> (out_channel -> 'a) -> 'a val write_to_formatted : string -> (Format.formatter -> 'a) -> 'a end val dir_sep : char val dir_sep_string : string (* Filename.dir_sep in Ocaml >= 3.11.2 *) module Dir : sig type t val compare : t -> t -> int val rm : t -> unit val concat : t -> t -> t val from_string : string -> t val to_string : t -> string val mk : t -> int -> unit val temp : t val empty : t val ch : t -> unit val cwd : unit -> t end type t (** a file name, including directory information *) val mk : ?dir:Dir.t -> string -> string -> t (** give a directory, a base name and an extension, and obtain a file name *) val from_string : string -> t val to_string : t -> string val debug_to_string : t -> string val place : Dir.t -> t -> t (** replace the current directory information of the file by the one given *) val concat : Dir.t -> t -> t (** concat directory information given to the one of the file *) val append : t -> string -> t val prepend : t -> string -> t (** append string to file name - do not use this for file extensions *) val move : t -> t -> unit (** move a file to another place *) val copy : t -> t -> unit val read_from : t -> (in_channel -> 'a) -> 'a val compare : t -> t -> int val basename : t -> string val extension : t -> string val dir : t -> Dir.t val exists : t -> bool val rm : t -> unit val open_out : t -> out_channel val open_in : t -> in_channel val open_in_gen : open_flag list -> int -> t -> in_channel val clear_dir : t -> t val set_ext : t -> string -> t (** clear extension if passed empty string *) val write_to : t -> (out_channel -> 'a) -> 'a val write_to_formatted : t -> (Format.formatter -> 'a) -> 'a module Map : Map.S with type key = t mlpost-0.8.2/generate.ml000066400000000000000000000060761306046515300151770ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** copied from File to remove dependency *) let write_to filename f = let chan = open_out filename in let r = f chan in close_out chan; r let write_to_formatted filename f = write_to filename (fun chan -> let fmt = Format.formatter_of_out_channel chan in let r = f fmt in Format.fprintf fmt "@?"; r) open Format let minipage fmt coef i tmpl sep suf = fprintf fmt "@[\\begin{minipage}[tb]{%f\\textwidth}@\n" coef; fprintf fmt "@[\\begin{center}@\n"; fprintf fmt "\\includegraphics[width=\\textwidth,height=\\textwidth,keepaspectratio]{%s%s%i%s}" tmpl sep i suf; fprintf fmt "@]@\n\\end{center}@\n"; fprintf fmt "@]@\n\\end{minipage}@\n" let generate_tex ?(pdf=false) tf tmpl1 tmpl2 l = let suf = if pdf then ".mps" else "" in let sep = if pdf then "-" else "." in write_to_formatted tf (fun fmt -> fprintf fmt "\\documentclass[a4paper]{article}@."; fprintf fmt "\\usepackage[]{graphicx}@."; fprintf fmt "@[\\begin{document}@."; List.iter (fun (i,_) -> fprintf fmt "@\n %i" i; minipage fmt 0.5 i tmpl1 sep suf; minipage fmt 0.5 i tmpl2 sep suf; fprintf fmt "@\n \\vspace{3cm}@\n" ) l ; fprintf fmt "@]@\n\\end{document}@.") let generate_tex_cairo tf tmpl1 tmpl2 tmpl3 l = write_to_formatted tf (fun fmt -> fprintf fmt "\\documentclass[a4paper]{article}@."; fprintf fmt "\\usepackage[]{graphicx}@."; fprintf fmt "@[\\begin{document}@."; List.iter (fun (i,_) -> fprintf fmt "@\n %i" i; minipage fmt 0.3 i tmpl1 "-" ".mps"; minipage fmt 0.3 i tmpl2 "-" ".mps"; minipage fmt 0.3 i tmpl3 "-" ".pdf"; fprintf fmt "@\n \\vspace{3cm}@\n" ) l ; fprintf fmt "@]@\n\\end{document}@.") mlpost-0.8.2/gui/000077500000000000000000000000001306046515300136265ustar00rootroot00000000000000mlpost-0.8.2/gui/_tags000066400000000000000000000001051306046515300146420ustar00rootroot00000000000000 : pkg_lablgtk2, use_unix, use_thread, pkg_lablgnomecanvasmlpost-0.8.2/gui/example.tex000066400000000000000000000003101306046515300157750ustar00rootroot00000000000000\documentclass{article} \usepackage{graphicx} \pagestyle{empty} \begin{document} \includegraphics[scale=3]{example.1} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: mlpost-0.8.2/gui/fig.ml000066400000000000000000000040721306046515300147300ustar00rootroot00000000000000open Mlpost open Num open Path open Command module Edit = struct open Glexer let file = "fig.edit" let elements = ref [] let table = Hashtbl.create 17 let () = if Sys.file_exists file then begin elements := Glexer.read_file file; let add = function | Num (s,_) | Point (s,_,_) as e -> Hashtbl.add table s e in List.iter add !elements end let mk_num = function | Pt -> Num.pt | Cm -> Num.cm | Mm -> Num.mm | Bp -> Num.bp | Inch -> Num.inch let num s v dimension = try match Hashtbl.find table s with | Num (_, (f, dim)) -> mk_num dim f | Point _ -> invalid_arg ("already a point of name " ^ s) with Not_found -> let e = Num (s, (v, dimension)) in elements := e :: !elements; Hashtbl.add table s e; mk_num dimension v let point s v1 dim1 v2 dim2 = try match Hashtbl.find table s with | Num _ -> invalid_arg ("already a num of name " ^ s) | Point (_,(n1,d1),(n2,d2)) -> Point.pt (mk_num d1 n1,mk_num d2 n2) with Not_found -> let e = Point (s, (v1,dim1), (v2,dim2)) in elements := e :: !elements; Hashtbl.add table s e; Point.pt(mk_num dim1 v1,mk_num dim2 v2) let () = at_exit (fun () -> Glexer.write_file file !elements) end (* Exemple d'utilisation de Gmlpost *) open Color (* un histogramme *) let fill = [lightblue; lightgreen; lightyellow; lightred] (* le padding est une valeur éditable *) let padding = Edit.num "padding" 5. Glexer.Bp let hist = Hist.simple ~width:(bp 50.) ~height:(bp 100.) ~fill ~padding [1.;2.;3.;4.] (* et sa légende *) let leg = Legend.legend [lightblue, "2006"; lightgreen, "2007"; lightyellow, "2008"; lightred, "2009"] (* la légende est positionnée au point p1 qui est éditable *) let p1 = Edit.point "legend" 100. Glexer.Bp 100. Glexer.Bp let pic = Command.draw_pic (Picture.shift p1 (Picture.scale (bp 0.5) leg)) (* la figure est l'ensemble de l'histogramme et de sa légende *) let example = hist++pic let () = Metapost.emit "example" example mlpost-0.8.2/gui/glexer.mll000066400000000000000000000037711306046515300156320ustar00rootroot00000000000000 { open Format type dimension = | Pt | Cm | Mm | Bp | Inch type value = float * dimension type elt = | Num of string * value | Point of string * value * value let elements = ref [] let add_elt e = elements := e :: !elements let dim_of_string = function | "pt" -> Pt | "bp" -> Bp | "cm" -> Cm | "mm" -> Mm | "inch" -> Inch | _ -> assert false } let space = [' ' '\t' '\n' '\r'] let number = '-'? ['0'-'9']+ '.' ['0'-'9']* | '-'? ['0'-'9']* '.' ['0'-'9']+ let dimension = "pt" | "bp" | "cm" | "mm" | "inch" let string = '"' [^ '"']* '"' rule read = parse | '#' [^ '\n']* '\n' { read lexbuf } | "num" space* (string as s) space* (number as n) space* (dimension as d) { let s = String.sub s 1 ((String.length s )-2) in eprintf "Glexer: s=%s n='%s'@." s n; add_elt (Num (s, (float_of_string n, dim_of_string d))); read lexbuf } | "point" space* (string as s) space* (number as n1) space* (dimension as d1) space* ',' space* (number as n2) space* (dimension as d2) {let s = String.sub s 1 ((String.length s )-2) in add_elt (Point (s, (float_of_string n1, dim_of_string d1), (float_of_string n2, dim_of_string d2))); read lexbuf } | _ { read lexbuf } | eof { () } { let read_file f = eprintf "****read_file****@."; let c = open_in f in let lb = Lexing.from_channel c in elements := []; read lb; close_in c; List.rev !elements let string_of_dim = function | Pt -> "pt" | Bp -> "bp" | Cm -> "cm" | Mm -> "mm" | Inch -> "inch" let print_value fmt (f, d) = fprintf fmt "%f %s" f (string_of_dim d) let write_file f el = let c = open_out f in let fmt = formatter_of_out_channel c in let write = function | Num (s, v) -> fprintf fmt "num \"%s\" %a@." s print_value v | Point (s, v1, v2) -> fprintf fmt "point \"%s\" %a, %a@." s print_value v1 print_value v2 in List.iter write el; fprintf fmt "@."; close_out c } mlpost-0.8.2/gui/gmlpost.ml000066400000000000000000000235461306046515300156570ustar00rootroot00000000000000open GMain open GdkKeysyms open Glexer open Format let () = ignore (GtkMain.Main.init ()) let usage () = eprintf "usage: gmlpost file.ml fig-name@."; exit 1 let ml_file, fig_name = if Array.length Sys.argv <> 3 then usage (); let f = Sys.argv.(1) in if not (Sys.file_exists f && Filename.check_suffix f ".ml") then usage (); f, Sys.argv.(2) (* run the mlpost file and create PNG image *) let sys_command cmd = let c = Sys.command cmd in eprintf "%s@." cmd; if c <> 0 then begin eprintf "command '%s' failed with exit code %d@." cmd c; exit 1 end (* size parameters *) let xmin = ref (-1.) let xmax = ref (1.) let ymin = ref (-1.) let ymax = ref (1.) let dx = ref 2. let dy = ref 2. let pic_w = ref 1. let pic_h = ref 1. let set_bbox xmi ymi xma yma = xmin := xmi; xmax := xma; ymin := ymi; ymax := yma; dx := !xmax -. !xmin; dy := !ymax -. !ymin let update_bbox () = let file = fig_name ^ ".1" in let c = open_in file in try while true do let s = input_line c in try Scanf.sscanf s "%%%%HiResBoundingBox: %f %f %f %f" (fun a b c d -> set_bbox a b c d; raise Exit) with Scanf.Scan_failure _ -> () done with | End_of_file -> eprintf "warning: could not find the bounding box in %s @." file; close_in c | Exit -> close_in c let png_file = fig_name ^ ".png" let make_png () = let dvi_file = fig_name^".dvi" in let ps_file = fig_name^".ps" in sys_command ("mlpost -ps -ccopt glexer.cmo " ^ ml_file); sys_command ("latex "^fig_name^" > /dev/null"); sys_command ("dvips -E "^dvi_file^" > /dev/null"); sys_command ("convert "^ps_file^" "^png_file^" > /dev/null"); update_bbox () let () = make_png () let edit_file = Filename.chop_suffix ml_file ".ml" ^ ".edit" let elements = Glexer.read_file edit_file let pointstable = Hashtbl.create 17 let rec init_table = function |[],_,_|_,[],_|_,_,[]|Point _::_ ,_::[],_-> () | Num _::r,_::sps,ps -> init_table (r,sps,ps) | Point (s,(_,d1),(_,d2))::r,sp1::sp2::sps,p::ps -> Hashtbl.add pointstable s ((sp1,d1,sp2,d2),p) ; init_table (r,sps,ps) let spins = ref [] let points = ref [] let z = ref 1. let belong x y = (x>0. && x< !pic_w && y>0. && y< !pic_h) (*------------------------------------------------------------------------*) let rec go_string fmt = function |[],_|_,[]|Point _::_,_::[] -> () | Num (s,(_,d))::r,sp::sps -> let n = sp#value in fprintf fmt "num \"%s\" %f %s \n" s n (string_of_dim d); go_string fmt (r,sps) | Point (s,(_,d1),(_,d2))::r,sp1::sp2::sps -> let n1 = sp1#value in let n2 = sp2#value in fprintf fmt "point \"%s\" %f %s , %f %s \n" s n1 (string_of_dim d1) n2 (string_of_dim d2); go_string fmt (r,sps) let write_edit ()= let f = open_out edit_file in let fmt = formatter_of_out_channel f in go_string fmt (elements,!spins); fprintf fmt "@?"; close_out f let bp_of_dim n = function |Bp -> n |Pt -> n *. 0.99626 |Cm -> n *. 28.34645 |Mm -> n *. 2.83464 |Inch -> n *. 72. let dim_of_bp n = function |Bp -> n |Pt -> n /. 0.99626 |Cm -> n /. 28.34645 |Mm -> n /. 2.83464 |Inch -> n /. 72. let update_points _ ((sp1,d1,sp2,d2),p) = let v1 = bp_of_dim sp1#value d1 in let v2 = bp_of_dim sp2#value d2 in let x = (v1 -. !xmin) *. !pic_w /. !dx in let y = (!ymax -. v2) *. !pic_h /. !dy in p#set [ `X1 (x -. 3.) ; `Y1 (y -. 3.) ; `X2 (x +. 3.) ; `Y2 (y +. 3.) ]; () let refresh canvas pic () = eprintf "@.------------------------------refresh------------------------------@."; write_edit (); make_png (); let pixbuf = GdkPixbuf.from_file png_file in pic#set [`PIXBUF pixbuf]; pic_w := float_of_int (GdkPixbuf.get_width pixbuf); pic_h := float_of_int (GdkPixbuf.get_height pixbuf); (*mise a l'echelle de tous les points au cas ou il y aurait un changement de bbox*) Hashtbl.iter update_points pointstable; eprintf "refresh:@."; eprintf " xmin = %f@." !xmin; eprintf " xmax = %f@." !xmax; eprintf " ymin = %f@." !ymin; eprintf " ymax = %f@." !ymax; eprintf " png = %f x %f pixels@." !pic_w !pic_h; () (*------------------------------------------------------------------------*) let highlight_point item ev = begin match ev with | `ENTER_NOTIFY _ -> item#set [ `FILL_COLOR "red" ] | `LEAVE_NOTIFY ev -> let state = GdkEvent.Crossing.state ev in if not (Gdk.Convert.test_modifier `BUTTON1 state) then item#set [`FILL_COLOR "black" ] | `BUTTON_PRESS ev -> let curs = Gdk.Cursor.create `FLEUR in item#grab [`POINTER_MOTION; `BUTTON_RELEASE] curs (GdkEvent.Button.time ev) | `BUTTON_RELEASE ev -> item#ungrab (GdkEvent.Button.time ev) | _ -> () end ; false let move_point x y s item ev = begin match ev with | `MOTION_NOTIFY ev -> let state = GdkEvent.Motion.state ev in let x = GdkEvent.Motion.x ev in let y = GdkEvent.Motion.y ev in if Gdk.Convert.test_modifier `BUTTON1 state && (belong x y) then begin let (sp1,d1,sp2,d2),_ = Hashtbl.find pointstable s in let x = dim_of_bp x d1 in let y = dim_of_bp y d2 in sp1#set_value (!xmin+.(x*. !dx/. !pic_w)); sp2#set_value (!ymax-.(y*. !dy/. !pic_h)); item#set [ `X1 (x -. 3.) ; `Y1 (y -. 3.) ; `X2 (x +. 3.) ; `Y2 (y +. 3.) ] end | `BUTTON_RELEASE ev -> eprintf "toto@."; | _ -> () end ; false let draw_point root s n1 n2 d1 d2 = let v1 = bp_of_dim n1 d1 in let v2 = bp_of_dim n2 d2 in let x = (v1 -. !xmin) *. !pic_w /. !dx in let y = (!ymax -. v2) *. !pic_h /. !dy in let point = GnoCanvas.ellipse ~x1:(x-.3.) ~x2:(x+.3.) ~y1:(y-.3.) ~y2:(y+.3.) ~props:[ `FILL_COLOR "black" ; `OUTLINE_COLOR "black" ; `WIDTH_PIXELS 0 ] root in let sigs = point#connect in ignore( sigs#event (highlight_point point) ); sigs#event (move_point x y s point); points := point::!points; () (*------------------------------------------------------------------------*) let point_of_spin s sb () = let n = sb#value in try let (sb1,d1,_,d2),p = Hashtbl.find pointstable s in if (sb == sb1) then begin let v = bp_of_dim n d1 in let n = (v -. !xmin) *. !pic_w /. !dx in p#set [ `X1 (n -. 3.) ; `X2 (n +. 3.) ] end else begin let v = bp_of_dim n d2 in let n = (!ymax -. v) *. !pic_h /. !dy in p#set [ `Y1 (n -. 3.) ; `Y2 (n +. 3.) ] end with Not_found -> () let init_spin_bounds = function |Bp -> (-150.),150.,0.5 |Pt -> (-150.),150.,0.5 |Cm -> (-50.),50.,0.1 |Mm -> (-500.),500.,1. |Inch -> (-3.),3.,0.05 let left_part_lign pic vbox vbox2 vbox3 s n d s' = GMisc.label ~text:(s^s') ~packing:vbox#add (); GMisc.label ~text:(string_of_dim d) ~packing:vbox3#add (); let sb = GEdit.spin_button ~packing:vbox2#add ~digits:2 ~numeric:true ~wrap:true () in let lower,upper,step_incr = init_spin_bounds d in sb#adjustment#set_bounds ~lower ~upper ~step_incr (); sb#set_value n; sb#adjustment#connect#value_changed ~callback:(point_of_spin s sb); spins := sb::!spins; () let left_part pic vbox vbox2 vbox3 root = function | Num (s,(n,d)) -> left_part_lign pic vbox vbox2 vbox3 s n d " :" | Point (s,(n1,d1),(n2,d2)) -> left_part_lign pic vbox vbox2 vbox3 s n1 d1 " xpart :" ; left_part_lign pic vbox vbox2 vbox3 s n2 d2 " ypart :" ; draw_point root s n1 n2 d1 d2 let zoom canvas zoo = z:= zoo; canvas#set_pixels_per_unit !z (*------------------------------------------------------------------------*) (* *) let main () = let window = GWindow.window ~title:"GMLPost" () in let vb = GPack.vbox ~spacing:10 ~packing:window#add () in (* Menu bar *) let menubar = GMenu.menu_bar ~packing:vb#pack () in window#connect#destroy ~callback:write_edit ; window#connect#destroy ~callback:Main.quit ; let hbox = GPack.hbox ~spacing:10 ~packing:vb#add () in let scrolled_window = GBin.scrolled_window ~width:350 ~border_width: 10 ~hpolicy: `AUTOMATIC ~packing: hbox#add () in let hbox2 = GPack.hbox ~spacing:10 ~packing:scrolled_window#add_with_viewport () in (* Partie Canvas *) let pixbuf = GdkPixbuf.from_file png_file in pic_w := float_of_int (GdkPixbuf.get_width pixbuf); pic_h := float_of_int (GdkPixbuf.get_height pixbuf); let scrolled_canvas = GBin.scrolled_window ~width:500 ~height:500 ~border_width: 10 ~hpolicy: `AUTOMATIC ~packing:hbox#add () in let canvas = GnoCanvas.canvas ~width:(int_of_float (!pic_w)) ~height:(int_of_float (!pic_h)) ~packing:scrolled_canvas#add_with_viewport () in canvas#set_scroll_region 0. 0. !pic_w !pic_h ; let root = canvas#root in let pic = GnoCanvas.pixbuf root ~pixbuf in let factory = new GMenu.factory menubar in let accel_group = factory#accel_group in let file_menu = factory#add_submenu "File" in let zoom_menu = factory#add_submenu "Zoom" in (* File menu *) let factory = new GMenu.factory file_menu ~accel_group in factory#add_item "Refresh" ~key:_r ~callback: (refresh canvas pic); let factory = new GMenu.factory file_menu ~accel_group in factory#add_item "Quit" ~key:_Q ~callback: Main.quit; (* Zoom *) let factory = new GMenu.factory zoom_menu ~accel_group in factory#add_item "50%" ~callback:(fun()->zoom canvas 0.5); factory#add_item "75%" ~callback:(fun()->zoom canvas 0.75); factory#add_item "100%" ~callback:(fun()->zoom canvas 1.); factory#add_item "125%" ~callback:(fun()->zoom canvas 1.25); factory#add_item "150%" ~callback:(fun()->zoom canvas 1.5); window#add_accel_group accel_group; let vbox = GPack.vbox ~spacing:10 ~packing:hbox2#add () in let vbox2 = GPack.vbox ~spacing:10 ~packing:hbox2#add () in let vbox3 = GPack.vbox ~spacing:10 ~packing:hbox2#add () in List.iter (left_part pic vbox vbox2 vbox3 root) elements; spins := List.rev !spins; points := List.rev !points; init_table (elements,!spins,!points); window#show (); Main.main (); ;; main () mlpost-0.8.2/handbookgraphs.ml000066400000000000000000000233141306046515300163710ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Mlpost open Command open Picture module H = Helpers open Num open Num.Infix open Point open Path module MP = MetaPath let draw1 = 1, seq [ draw (path ~style:jLine [20.,20.; 0.,0.; 0.,30.; 30.,0.; 0.,0.])] let z0 = 0.,0. let z1 = 60.,40. let z2 = 40.,90. let z3 = 10.,70. let z4 = 30.,50. let l1 = z0::z1::z2::z3::z4::[] let labels1 = seq [H.dotlabels ~pos:`North ["0";"2";"4"] (map_bp [z0;z2;z4]); dotlabel ~pos:`West (tex "3") (bpp z3); dotlabel ~pos:`Southeast (tex "1") (bpp z1) ] let draw3 = 3, seq [ draw (path ~style:jCurve l1); labels1 ] let draw4a, draw4b = let labels = seq [ H.dotlabels ~pos:`North ["2";"4"] (map_bp [z2;z4]); H.dotlabels ~pos:`West ["0";"3"] (map_bp [z0;z3]); dotlabel ~pos:`Southeast (tex "1") (bpp z1) ] in (104, seq [ draw (path ~cycle:jCurve l1); labels]) , (204, seq [ draw (Path.append ~style:jLine (path [z0;z1;z2;z3]) (path ~style:jLine [z4;z0]) ); labels ]) (* no easy alternative way to draw this one, and that's fine *) let l1dirs = List.map (knot) l1 let lcontrols = [(26.8, -1.8), (51.4,14.6); (67.1, 61.), (59.8,84.6); (25.4, 94.), (10.5,84.5); (9.6, 58.8), (18.8,49.6)] let lcontrolsbp = List.map (fun (a,b) -> jControls (bpp a) (bpp b)) lcontrols let draw5 = 5, seq [ draw (jointpath l1 lcontrolsbp) ; (let hull = List.fold_left2 (fun acc (c1, c2) f -> f::c2::c1::acc) [0.,0.] lcontrols (List.tl l1) in (* As long as we dont have the dashed lines : gray *) draw ~dashed:(Dash.scaled 0.5 Dash.evenly) (path ~style:jLine (List.rev hull))) ; labels1 ] let draw6 = 6, seq [ draw (pathk [ knot z0; knot ~r:(vec up) z1; knot ~r:(vec left) z2; knot z3; knot z4] ); labels1 ] let lex = MP.knot ~r:(vec (dir 45.)) (0.,0.) let rex a = MP.knot ~l:(vec (dir (10.*.a))) ~scale:cm (6., 0.) let draw7 = 7, seq [Command.iter 0 9 (fun a -> let p = MP.concat (MP.start lex) ~style:jCurve (rex (float_of_int (-a))) in draw (MP.to_path p) ) ] let draw8 = 8, seq [Command.iter 0 7 (fun a -> let p = MP.concat (MP.start lex) ~style:jCurve (rex (float_of_int a)) in draw (MP.to_path p) ) ] let z0 = (-1., 0.) let z1 = (0., 0.2) let z2 = ( 1., 0.) let labels9 = H.dotlabels ~pos:`South ["0";"1";"2"] (map_in [z0;z1;z2]) let z0 = knot ~r:(vec up) ~scale:inch z0 let z1 = knot ~r:(vec right) ~scale:inch z1 let z2 = knot ~r:(vec down) ~scale:inch z2 let draw9a = 109, seq [draw (pathk [z0;z1;z2]); labels9 ] let draw9b = 209, seq [draw (pathk ~style:jCurveNoInflex [z0;z1;z2]); labels9 ] let u l = 1.5 /. 10. *. l let z0 = (u (-5.)), 0. let z1 = (u (-3.)),u 2. let z2 = (u 3.),u 2. let z3 = (u 5.),u 0. let l1 = [z0;z1;z2;z3] let labels10 = H.dotlabels ~pos:`South ["0";"1";"2";"3"] (map_in l1) let draw10a = 110, seq [draw (path ~scale:inch l1); labels10 ] let draw10b = 210, seq [ draw (jointpath ~scale:inch l1 [jCurve; jTension 1.3 1.3; jCurve] ); labels10 ] let draw10c = 310, seq [ draw (jointpath ~scale:inch l1 [jCurve; jTension 1.5 1.0; jCurve] ); labels10 ] let u l = 1.4 /. 10. *. l let z0 = u (2.), u (-5.) let z1 = 0., 0. let z2 = u 2., u 5. let cl = [0.; 1.; 2.; infinity] let u l = 1.4 /. 10. *. l let z0 = u (2.), u (-5.) let z1 = 0., 0. let z2 = u 2., u 5. let cl = [0.; 1.; 2.; infinity] let pat c = [ knot ~r:(curl c) ~scale:inch z0 ; knot ~scale:inch z1; knot ~l:(curl c) ~scale:inch z2 ] let draw11 = let numbers = [111; 211; 311; 411] in let labels11 = H.dotlabels ~pos:`East ["0";"1";"2"] (map_in [z0;z1;z2]) in List.map2 (fun c n -> n, seq [draw (pathk (pat c) ); labels11 ] ) cl numbers let draw17 = let a, b = Num.inch (0.7), Num.inch (0.5) in let z0 = p (0.,0.) in let z1 = pt (a, zero) and z3 = pt (neg a, zero) in let z2 = pt (zero, b) and z4 = pt (zero, neg b) in 17, seq [draw (pathp ~cycle:jCurve [z1;z2;z3;z4]); draw (pathp ~style:jLine [z1; z0; z2]); label ~pos:`North (tex "a") (segment 0.5 z0 z1); label ~pos:`West (tex "b") (segment 0.5 z0 z2); dotlabel ~pos:`South (tex "(0,0)") z0 ] let draw18 = let u = Num.cm in let pen = Pen.scale one Pen.circle in let rec pg = function | 0 -> MP.start (MP.knot ~r:(vec up) ~scale:u (0.,0.)) | n -> let f = (float_of_int n /. 2.) in MP.concat ~style:jCurve (pg (n-1)) (MP.knot ~scale:u (f, sqrt f)) in 18, seq [draw (pathn ~style:jLine [(zero,u 2.); (zero,zero); (u 4.,zero)]); draw ~pen (MP.to_path (pg 8)); label ~pos:`Southeast (tex "$ \\sqrt x$") (pt (u 3., u (sqrt 3.))); label ~pos:`South (tex "$x$") (pt (u 2., zero)); label ~pos:`Southwest (tex "$y$") (pt (zero, u 1.))] let draw19 = let ux, uy = Num.inch 0.01, Num.inch 0.6 in let dux, duy = 120. *./ ux, 4. *./ uy in let pen = Pen.scale one Pen.circle in let axey = Picture.transform [Transform.rotated 90.] (tex "axe $y$") in let rec pg = function | 0 -> start (knotn ~r:(vec right) (zero,uy)) | n -> let k = (float_of_int n)*.15. in concat ~style:jCurve (pg (n-1)) (knotn (k *./ ux, 2. /. (1. +. (cos (Num.deg2rad k))) *./ uy)) in 19, [draw (pathn ~style:jLine [(zero,duy); (zero,zero); (dux,zero)]); draw ~pen (pg 8); label ~pos:`South (tex "axe $x$") (pt (60.*./ux, zero)); label ~pos:`West axey (pt (zero, 2.*./uy)); label ~pos:`West (tex "$\\displaystyle y={2\\over1+\\cos x}$") (pt (dux, duy))] (** Cette version de draw21 est assez cool mais ne marche pas car la largeur du trait est scalée avec la figure... *) (* let draw21 = *) (* let path = transform t halfcircle in *) (* let r = Vec (p (Num.bp (-.1.), Num.bp (-.2.))) in *) (* let fillp = *) (* cycle (Vec up) JCurve (concat path JCurve (C.p ~r ~scale:C.CM (0.,0.))) in *) (* 21, [fill fillp; draw (transform t fullcircle)] *) let draw21 = let mp d pt = knot ~r:(vec d) ~scale:cm pt in let kl = [mp down (-1.,0.); mp right (0.,-1.); mp up (1.,0.)] in let path = pathk kl in let r = p (-.1., -.2.) in let fillp = cycle ~dir:(vec up) (concat path (mp r (0.,0.))) in let fullp = cycle (concat path (mp left (0.,1.))) in 21, seq [fill fillp; draw fullp] let draw22 = let a = Path.scale (cm 2.) fullcircle in let aa = Path.scale (cm 2.) halfcircle in let b = Path.shift (pt (zero, Num.cm 1.)) a in let pa = label (tex "$A$") (pt (zero, Num.cm (-0.5))) in let pb= label (tex "$B$") (pt (zero, Num.cm 1.5)) in let ab = build_cycle [aa; b] in let pic = (seq [fill ~color:(Color.gray 0.7) a; fill ~color:(Color.gray 0.7) b; fill ~color:(Color.gray 0.4) ab; fill ~color:Color.white (bbox pa); pa; fill ~color:Color.white (bbox pb); pb; label ~pos:`West (tex "$U$") (p ~scale:Num.cm (-1.,0.5)); ]) in 22, seq [pic; draw (bbox pic)] let draw40 = let k1 = knot ~r:(curl 0.) ~scale:Num.pt (0.,0.) in let k2 = knot ~scale:Num.pt (5., -3.) in let k3 = knot ~scale:Num.pt ~l:(curl 0.) (10.,0.) in let p1 = pathk [k1;k2;k3] in let p2 = append p1 (Path.shift (p ~scale:Num.pt (10.,0.)) (Path.yscale (neg one) p1)) in let p2 = Misc.fold_from_to (fun acc i -> append acc (Path.shift (p ~scale:Num.pt (float_of_int i *. 20.,0.)) p2)) p2 1 3 in let cmd = Command.iter 0 8 (fun i -> draw (Path.shift (p ~scale:Num.pt (0., float_of_int i *. 10.)) p2)) in let pth = Path.scale (Num.pt 72.) (Path.shift (p (0.5, 0.5)) fullcircle) in let pic' = Picture.clip cmd pth in 40, seq [pic'; draw pth] let min = -100. let max = 100. let b = (cycle ~style:jLine (path ~style:jLine [(min,min);(max,min);(max,max);(min,max)])) (* Pour avoir une echelle *) let embed (id,p) = id,seq [draw b;p] let figs = (*List.map embed*) [ draw1; draw3; draw4a; draw4b;draw5; draw6; draw7; draw8; draw9a; draw9b; draw10a; draw10b;draw10c ] @ draw11 @ [ draw17; draw18; draw21; draw40; (* draw22; *) ] let mpostfile = "testmanualMP" let cairostfile = "testmanual_cairo" let texfile = "testmanual.tex" let _ = Sys.chdir "test"; let nfig = List.map (fun (i,f) -> mpostfile^"-"^(string_of_int i), f) figs in if Cairost.supported then begin (* Metapost.generate mpostfile nfig; *) Mps.generate nfig; Cairost.generate_pdfs cairostfile figs; Generate.generate_tex_cairo texfile "manual/manual" "testmanualMP" "testmanual_cairo" figs; end else begin Metapost.generate mpostfile nfig; Generate.generate_tex ~pdf:true texfile "manual/manual" "testmanualMP" figs; end mlpost-0.8.2/hash.ml000066400000000000000000000124471306046515300143270ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* type color = | RGB of float * float * float | CMYK of float * float * float * float | Gray of float type name = string type corner = N | S | W | E | NE | NW | SW | SE type piccorner = UL | UR | LL | LR *) open Hashtbl open Types let combine n acc = acc * 65599 + n let combine2 n acc1 acc2 = combine n (combine acc1 acc2) let combine3 n acc1 acc2 acc3 = combine n (combine acc1 (combine acc2 acc3)) let combine4 n acc1 acc2 acc3 acc4 = combine n (combine3 acc1 acc2 acc3 acc4) type position = | Pcenter | Pleft | Pright | Ptop | Pbot | Pupleft | Pupright | Plowleft | Plowright let rec num = function | F f -> combine 1 (hash f) | NXPart p -> combine 2 (point p) | NYPart p -> combine 3 (point p) | NAdd(n,m) -> combine2 4 (num n) (num m) | NMinus(n,m) -> combine2 5 (num n) (num m) | NMult(n,m) -> combine2 6 (num n) (num m) | NDiv(n,m) -> combine2 7 (num n) (num m) | NMax(n,m) -> combine2 8 (num n) (num m) | NMin(n,m) -> combine2 9 (num n) (num m) | NGMean(n,m) -> combine2 10 (num n) (num m) | NLength p -> combine 11 (path p) and point = function | PTPair(n,m) -> combine2 12 (num n) (num m) | PTPicCorner(p,pc) -> combine2 13 (picture p) (hash pc) | PTPointOf(f,p) -> combine2 14 (hash f) (path p) | PTDirectionOf(f,p) -> combine2 15 (hash f) (path p) | PTAdd(p,q) -> combine2 16 (point p) (point q) | PTSub(p,q) -> combine2 17 (point p) (point q) | PTMult(n,q) -> combine2 18 (num n) (point q) | PTRotated(f,p) -> combine2 19 (hash f) (point p) | PTTransformed(p,l) -> List.fold_left (fun acc t -> combine2 21 acc (transform t)) (combine 20 (point p)) l (* and on_off = On of num | Off of num *) and direction = function | Vec p -> combine 61 (point p) | Curl f -> combine 62 (hash f) | NoDir -> 63 and joint = hash (* | JLine | JCurve | JCurveNoInflex | JTension of float * float | JControls of point * point *) and knot(d1,p,d2) = combine3 64 (direction d1) (point p) (direction d2) and path = function | PAConcat(k,j,p) -> combine3 22 (knot k) (joint j) (path p) | PACycle(d,j,p) -> combine3 23 (direction d) (joint j) (path p) | PAFullCircle -> 24 | PAHalfCircle -> 25 | PAQuarterCircle -> 26 | PAUnitSquare -> 27 | PATransformed(p,l) -> List.fold_left (fun acc t -> combine2 28 acc (transform t)) (combine 29 (path p)) l | PAKnot k -> combine 30 (knot k) | PAAppend(p1,j,p2) -> combine3 31 (path p1) (joint j) (path p2) | PACutAfter(p,q) -> combine2 32 (path p) (path q) | PACutBefore(p,q) -> combine2 33 (path p) (path q) | PABuildCycle l -> List.fold_left (fun acc t -> combine2 35 acc (path t)) 34 l | PASub(f1,f2,p) -> combine3 36 (hash f1) (hash f2) (path p) | PABBox p -> combine 37 (picture p) and transform = function | TRRotated f -> combine 52 (hash f) | TRScaled n -> combine 53 (num n) | TRShifted p -> combine 57 (point p) | TRSlanted n -> combine 54 (num n) | TRXscaled n -> combine 55 (num n) | TRYscaled n -> combine 56 (num n) | TRZscaled p -> combine 58 (point p) | TRReflect(p,q) -> combine2 59 (point p) (point q) | TRRotateAround(p,q) -> combine2 60 (point p) (hash q) and picture = function | PITex s -> combine 38 (hash s) | PIMake c -> combine 39 (command c) | PITransform(l,p) -> List.fold_left (fun acc t -> combine2 40 acc (transform t)) (combine 41 (picture p)) l | PIClip(p,q) -> combine2 42 (picture p) (path q) and dash = hash (* | DEvenly | DWithdots | DScaled of float * dash | DShifted of point * dash | DPattern of on_off list *) and pen = hash (* | PenCircle | PenSquare | PenFromPath of path | PenTransformed of pen * transform list *) and command = function | CDraw(pa,c,p,d) -> combine4 43 (path pa) (hash c) (hash p) (hash d) | CDrawArrow(pa,c,p,d) -> combine4 44 (path pa) (hash c) (hash p) (hash d) | CDrawPic p -> combine 45 (picture p) | CFill(p,c) -> combine2 46 (path p) (hash c) | CLabel(pic,pos,poi) -> combine3 47 (picture pic) (hash pos) (point poi) | CDotLabel(pic,pos,poi) -> combine3 48 (picture pic) (hash pos) (point poi) | CLoop(n,m,_) -> combine2 49 n m | CSeq l -> List.fold_left (fun acc t -> combine2 50 acc (command t)) 51 l mlpost-0.8.2/hashcons.ml000066400000000000000000000215771306046515300152160ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* * hashcons: hash tables for hash consing * Copyright (C) 2000 Jean-Christophe FILLIATRE * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2, as published by the Free Software Foundation. * * 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 Library General Public License version 2 for more details * (enclosed in the file LGPL). *) (*s Hash tables for hash-consing. (Some code is borrowed from the ocaml standard library, which is copyright 1996 INRIA.) *) type 'a hash_consed = { hkey : int; tag : int; node : 'a } let gentag = let r = ref 0 in fun () -> incr r; !r type 'a t = { mutable table : 'a hash_consed Weak.t array; mutable totsize : int; (* sum of the bucket sizes *) mutable limit : int; (* max ratio totsize/table length *) } let create sz = let sz = if sz < 7 then 7 else sz in let sz = if sz > Sys.max_array_length then Sys.max_array_length else sz in let emptybucket = Weak.create 0 in { table = Array.create sz emptybucket; totsize = 0; limit = 3; } let clear t = let emptybucket = Weak.create 0 in for i = 0 to Array.length t.table - 1 do t.table.(i) <- emptybucket done; t.totsize <- 0; t.limit <- 3 let fold f t init = let rec fold_bucket i b accu = if i >= Weak.length b then accu else match Weak.get b i with | Some v -> fold_bucket (i+1) b (f v accu) | None -> fold_bucket (i+1) b accu in Array.fold_right (fold_bucket 0) t.table init let iter f t = let rec iter_bucket i b = if i >= Weak.length b then () else match Weak.get b i with | Some v -> f v; iter_bucket (i+1) b | None -> iter_bucket (i+1) b in Array.iter (iter_bucket 0) t.table let count t = let rec count_bucket i b accu = if i >= Weak.length b then accu else count_bucket (i+1) b (accu + (if Weak.check b i then 1 else 0)) in Array.fold_right (count_bucket 0) t.table 0 let next_sz n = min (3*n/2 + 3) (Sys.max_array_length - 1) let rec resize t = let oldlen = Array.length t.table in let newlen = next_sz oldlen in if newlen > oldlen then begin let newt = create newlen in newt.limit <- t.limit + 100; (* prevent resizing of newt *) fold (fun d () -> add newt d) t (); t.table <- newt.table; t.limit <- t.limit + 2; end and add t d = let index = d.hkey mod (Array.length t.table) in let bucket = t.table.(index) in let sz = Weak.length bucket in let rec loop i = if i >= sz then begin let newsz = min (sz + 3) (Sys.max_array_length - 1) in if newsz <= sz then failwith "Hashcons.Make: hash bucket cannot grow more"; let newbucket = Weak.create newsz in Weak.blit bucket 0 newbucket 0 sz; Weak.set newbucket i (Some d); t.table.(index) <- newbucket; t.totsize <- t.totsize + (newsz - sz); if t.totsize > t.limit * Array.length t.table then resize t; end else begin if Weak.check bucket i then loop (i+1) else Weak.set bucket i (Some d) end in loop 0 let hashcons t d = let hkey = Hashtbl.hash d in let index = hkey mod (Array.length t.table) in let bucket = t.table.(index) in let sz = Weak.length bucket in let rec loop i = if i >= sz then begin let hnode = { hkey = hkey; tag = gentag (); node = d } in add t hnode; hnode end else begin match Weak.get_copy bucket i with | Some v when v.node = d -> begin match Weak.get bucket i with | Some v -> v | None -> loop (i+1) end | _ -> loop (i+1) end in loop 0 let stats t = let len = Array.length t.table in let lens = Array.map Weak.length t.table in Array.sort compare lens; let totlen = Array.fold_left ( + ) 0 lens in (len, count t, totlen, lens.(0), lens.(len/2), lens.(len-1)) (* Functorial interface *) module type HashedType = sig type t val equal : t -> t -> bool val hash : t -> int end module type S = sig type key type t val create : int -> t val clear : t -> unit val hashcons : t -> key -> key hash_consed val iter : (key hash_consed -> unit) -> t -> unit val stats : t -> int * int * int * int * int * int end module Make(H : HashedType) : (S with type key = H.t) = struct type key = H.t type data = H.t hash_consed type t = { mutable table : data Weak.t array; mutable totsize : int; (* sum of the bucket sizes *) mutable limit : int; (* max ratio totsize/table length *) } let emptybucket = Weak.create 0 let create sz = let sz = if sz < 7 then 7 else sz in let sz = if sz > Sys.max_array_length then Sys.max_array_length else sz in { table = Array.create sz emptybucket; totsize = 0; limit = 3; } let clear t = for i = 0 to Array.length t.table - 1 do t.table.(i) <- emptybucket done; t.totsize <- 0; t.limit <- 3 let fold f t init = let rec fold_bucket i b accu = if i >= Weak.length b then accu else match Weak.get b i with | Some v -> fold_bucket (i+1) b (f v accu) | None -> fold_bucket (i+1) b accu in Array.fold_right (fold_bucket 0) t.table init let iter f t = let rec iter_bucket i b = if i >= Weak.length b then () else match Weak.get b i with | Some v -> f v; iter_bucket (i+1) b | None -> iter_bucket (i+1) b in Array.iter (iter_bucket 0) t.table let count t = let rec count_bucket i b accu = if i >= Weak.length b then accu else count_bucket (i+1) b (accu + (if Weak.check b i then 1 else 0)) in Array.fold_right (count_bucket 0) t.table 0 let next_sz n = min (3*n/2 + 3) (Sys.max_array_length - 1) let rec resize t = let oldlen = Array.length t.table in let newlen = next_sz oldlen in if newlen > oldlen then begin let newt = create newlen in newt.limit <- t.limit + 100; (* prevent resizing of newt *) fold (fun d () -> add newt d) t (); t.table <- newt.table; t.limit <- t.limit + 2; end and add t d = let index = d.hkey mod (Array.length t.table) in let bucket = t.table.(index) in let sz = Weak.length bucket in let rec loop i = if i >= sz then begin let newsz = min (sz + 3) (Sys.max_array_length - 1) in if newsz <= sz then failwith "Hashcons.Make: hash bucket cannot grow more"; let newbucket = Weak.create newsz in Weak.blit bucket 0 newbucket 0 sz; Weak.set newbucket i (Some d); t.table.(index) <- newbucket; t.totsize <- t.totsize + (newsz - sz); if t.totsize > t.limit * Array.length t.table then resize t; end else begin if Weak.check bucket i then loop (i+1) else Weak.set bucket i (Some d) end in loop 0 let hashcons t d = let hkey = H.hash d in let index = hkey mod (Array.length t.table) in let bucket = t.table.(index) in let sz = Weak.length bucket in let rec loop i = if i >= sz then begin let hnode = { hkey = hkey; tag = gentag (); node = d } in add t hnode; hnode end else begin match Weak.get_copy bucket i with | Some v when H.equal v.node d -> begin match Weak.get bucket i with | Some v -> v | None -> loop (i+1) end | _ -> loop (i+1) end in loop 0 let stats t = let len = Array.length t.table in let lens = Array.map Weak.length t.table in Array.sort compare lens; let totlen = Array.fold_left ( + ) 0 lens in (len, count t, totlen, lens.(0), lens.(len/2), lens.(len-1)) end mlpost-0.8.2/hashcons.mli000066400000000000000000000074361306046515300153650ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* * hashcons: hash tables for hash consing * Copyright (C) 2000 Jean-Christophe FILLIATRE * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2, as published by the Free Software Foundation. * * 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 Library General Public License version 2 for more details * (enclosed in the file LGPL). *) (*s Hash tables for hash consing. Hash consed values are of the following type [hash_consed]. The field [tag] contains a unique integer (for values hash consed with the same table). The field [hkey] contains the hash key of the value (without modulo) for possible use in other hash tables (and internally when hash consing tables are resized). The field [node] contains the value itself. Hash consing tables are using weak pointers, so that values that are no more referenced from anywhere else can be erased by the GC. *) type 'a hash_consed = private { hkey : int; tag : int; node : 'a } (*s Generic part, using ocaml generic equality and hash function. *) type 'a t val create : int -> 'a t (** [create n] creates an empty table of initial size [n]. The table will grow as needed. *) val clear : 'a t -> unit (** Removes all elements from the table. *) val hashcons : 'a t -> 'a -> 'a hash_consed (** [hashcons t n] hash-cons the value [n] using table [t] i.e. returns any existing value in [t] equal to [n], if any; otherwise, allocates a new one hash-consed value of node [n] and returns it. As a consequence the returned value is physically equal to any equal value already hash-consed using table [t]. *) val iter : ('a hash_consed -> unit) -> 'a t -> unit (** [iter f t] iterates [f] over all elements of [t]. *) val stats : 'a t -> int * int * int * int * int * int (** Return statistics on the table. The numbers are, in order: table length, number of entries, sum of bucket lengths, smallest bucket length, median bucket length, biggest bucket length. *) (*s Functorial interface. *) module type HashedType = sig type t val equal : t -> t -> bool val hash : t -> int end module type S = sig type key type t val create : int -> t val clear : t -> unit val hashcons : t -> key -> key hash_consed val iter : (key hash_consed -> unit) -> t -> unit val stats : t -> int * int * int * int * int * int end module Make(H : HashedType) : (S with type key = H.t) mlpost-0.8.2/headache_config.txt000066400000000000000000000007721306046515300166600ustar00rootroot00000000000000# Objective Caml source | ".*\\.ml[il4]?" -> frame open:"(*" line:"*" close:"*)" | ".*\\.ml[il4]?\\.in" -> frame open:"(*" line:"*" close:"*)" | ".*\\.mly" -> frame open:"/*" line:"*" close:"*/" # C source | ".*\\.c" -> frame open:"/*" line:"*" close:"*/" # Misc | "configure.in" -> frame open:"#" line:"#" close:"#" | "Makefile.in" -> frame open:"#" line:"#" close:"#" | "Makefile" -> frame open:"#" line:"#" close:"#" | "README.*" -> frame open:"*" line:"*" close:"*" | "META.in" -> no mlpost-0.8.2/header.txt000066400000000000000000000007731306046515300150420ustar00rootroot00000000000000 Copyright (C) Johannes Kanig, Stephane Lescuyer Jean-Christophe Filliatre, Romain Bardou and Francois Bobot This software is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2.1, with the special exception on linking described in file LICENSE. This software 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. mlpost-0.8.2/helpers.ml000066400000000000000000000076621306046515300150510ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Path open Point open Num open Box open Command (* puts labels at given points with given text *) let dotlabels ?(pos=`Center) ls lp = seq (List.map2 (fun s p -> dotlabel ~pos:pos (Picture.tex s) p) ls lp) let draw_simple_arrow ?color ?pen ?dashed ?style ?outd ?ind ?sep a b = Arrow.simple ?color ?pen ?dashed (Box.strip ?sep (Arrow.simple_point_point ?style ?outd ?ind a b)) let draw_label_arrow ?color ?pen ?dashed ?style ?outd ?ind ?pos ?sep lab a b = let p = Arrow.simple_point_point ?style ?outd ?ind ?sep a b in Arrow.simple ?color ?pen ?dashed p ++ label ?pos lab (Path.point 0.5 p) let draw_labelbox_arrow ?color ?pen ?dashed ?style ?outd ?ind ?pos ?sep lab a b = draw_label_arrow ?color ?pen ?dashed ?style ?outd ?ind ?pos ?sep (Picture.make (Box.draw lab)) a b let subboxes within a b = match within with | None -> a,b | Some x -> Box.sub a x, Box.sub b x let box_arrow ?within ?color ?pen ?dashed ?style ?outd ?ind ?sep a b = let a, b = subboxes within a b in Arrow.simple ?color ?pen ?dashed (Box.cpath ?style ?outd ?ind ?sep a b) let box_line ?within ?color ?pen ?dashed ?style ?outd ?ind ?sep a b = let a, b = subboxes within a b in draw ?color ?pen ?dashed (Box.cpath ?style ?outd ?ind ?sep a b) let box_label_line ?within ?color ?pen ?dashed ?style ?outd ?ind ?sep ?pos lab a b = let a, b = subboxes within a b in let p = Box.cpath ?style ?outd ?ind ?sep a b in draw ?color ?pen ?dashed p ++ label ?pos lab (Path.point 0.5 p) let box_label_arrow ?within ?color ?pen ?dashed ?style ?outd ?ind ?sep ?pos lab a b = let a, b = subboxes within a b in let p = Box.cpath ?style ?outd ?ind ?sep a b in Arrow.simple ?color ?pen ?dashed p ++ label ?pos lab (Path.point 0.5 p) (* TODO unify all these functions *) let box_labelbox_arrow ?within ?color ?pen ?dashed ?style ?outd ?ind ?sep ?pos lab a b = box_label_arrow ?within ?color ?pen ?dashed ?style ?outd ?ind ?sep ?pos (Picture.make (Box.draw lab)) a b let pointer_start_pen = Pen.scale (Num.bp 4.) Pen.circle let box_pointer_arrow ?within ?color ?pen ?dashed ?style ?outd ?ind a b = let a, b = subboxes within a b in let r,l = outd, ind in let p = Path.pathk ?style [Path.knotp ?r (ctr a); Path.knotp ?l (ctr b)] in let p = Path.cut_after (bpath b) p in Command.draw ~pen:pointer_start_pen (pathp [Path.point 0. p]) ++ Arrow.simple ?color ?pen ?dashed p (*** let hboxjoin ?color ?pen ?dashed ?dx ?dy ?pos ?spacing pl = (* align the pictures in pl, put them in boxes and connect these boxes *) let bl = Box.halign_to_box ?dx ?pos ?spacing pl in match bl with | [] -> nop | hd::tl -> let cmd,_ = List.fold_left (fun (cmd,b1) b2 -> Box.draw b2 ++ box_arrow ?color ?pen ?dashed b1 b2 ++ cmd,b2 ) (Box.draw hd,hd) tl in cmd ***) mlpost-0.8.2/hist.ml000066400000000000000000000227001306046515300143440ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Command open Color open Box open Num open Point open Path type 'a labels = Values | User of 'a list type path_3D = Prems of (Path.t*Path.t*Color.t) |PasPrems of (Path.t*Color.t) module Q = Misc.Q let max l = let rec max_aux acc = function |[]->acc |x::res-> if (x>acc) then max_aux x res else max_aux acc res in max_aux (List.hd l) l let maxlist l = let rec max_aux acc = function |[]->acc |x::res -> let m= max x in if (m>acc) then max_aux m res else max_aux acc res in max_aux (max (List.hd l)) l (* Valeur maximale dans un histogramme cumulé *) let maxcumul l = let rec list_aux acc l = match l with |[] -> acc |x::res -> list_aux ((List.fold_left (fun acc x -> acc+.x) 0. x)::acc) res in max (list_aux [] l) (* Ne fonctionne que si b est une hbox qui contient au moins une boite *) let move_hbox cumul cpt scalex b = let p = Box.south_west b in Box.shift (Point.pt (multf (float cpt) scalex,zero)) (Box.shift (Point.sub Point.origin p) b) let default_vlabel i _ = Some (Picture.tex (string_of_int i)) let laxe ~nbcol ?(vlabel=default_vlabel) padding scalex scaley hcaption vcaption valmax nbval = let hlabel i x = None in let axe = Plot.mk_skeleton (nbval/nbcol) (int_of_float valmax) (addn (multf (float nbcol) scalex) padding) scaley in Plot.draw_axes ?hcaption ?vcaption ~vlabel ~hlabel ~ticks:None axe let rec draw_perspect acc = function |Prems (p1,p2,c)::r -> draw_perspect ((fill ~color:c p1)++(fill ~color:c p2)++(Command.draw p1)++(Command.draw p2)++acc) r |PasPrems (p,c)::r -> draw_perspect ((fill ~color:c p)++(Command.draw p)++acc) r |[] -> acc (* Construit les composantes 3D à partir d'un vecteur, d'une boite et d'une couleur *) let perspect scale derns b c = let c = match c with |None -> Color.white |Some i -> i in let nw = north_west b in let ne = north_east b in let se = south_east b in let dep = divf scale 3. in let p1 = [nw;ne;pt ((addn (xpart ne) dep),(addn (ypart ne) dep)); pt ((addn (xpart nw) dep),(addn (ypart nw) dep))] in let p2 = [ne;se;pt ((addn (xpart se) dep),(addn (ypart se) dep)); pt ((addn (xpart ne) dep),(addn (ypart ne) dep))] in let path1 = pathp ~cycle:jLine ~style:jLine p1 in let path2 = pathp ~cycle:jLine ~style:jLine p2 in (* (fill ~color:c path1) ++ (fill ~color:c path2) ++ *) (* (Command.draw path1) ++ (Command.draw path2) *) if derns then Prems (path1,path2,c) else PasPrems(path2,c) let rec mk_perspect2 acc prems scale hb i j l = match l with |x::res -> let b = Box.nth j (Box.nth i hb) in let paths = perspect scale prems b (get_fill b) in mk_perspect2 (paths::acc) false scale hb i (j+1) res |[]-> acc let box_perspect scale hb l = let rec mk_perspect acc scale hb i l = match l with |x::res -> mk_perspect ((mk_perspect2 [] true scale hb i 0 x)@acc) scale hb (i+1) res |[] -> acc in mk_perspect [] scale hb 0 l (* Gère la position du label pour qu'elle soit cohérente *) let label_direction poslab x = match Types.vreduce poslab with | `North -> if x < 0. then (`South,Box.south) else (`South,Box.north) | `South -> if x < 0. then (`North,Box.south) else (`South,Box.north) | `Center -> (`Center,Box.ctr) let rec mk_labels2 acc poslab i j hb l l2= match l,l2 with |x::res,x2::res2 -> let sens,haut = label_direction poslab x2 in let b = Box.nth j (Box.nth i hb) in mk_labels2 (acc++ Command.label ~pos:sens x (haut b)) poslab i (j+1) hb res res2 |[],[]-> acc |_,_ -> failwith "Both datas and labels lists must have the same size" (* Positionne les labels sur chaque élément de l'histogramme *) let box_labels lab hb l = let rec mk_labels acc poslab i hb l l2= match l,l2 with |x::res,x2::res2 -> mk_labels (acc++mk_labels2 Command.nop poslab i 0 hb (List.rev x) (List.rev x2)) poslab (i+1) hb res res2 |[],[]-> acc |_,_ -> failwith "Both datas and labels lists must have the same size" in match lab with |(poslab,Values) -> let picl2 l = List.map (fun x -> Picture.tex (string_of_float x)) l in let picl l = List.map (fun x -> picl2 x) l in mk_labels nop poslab 0 hb (picl l) l |(poslab,User pl) -> mk_labels nop poslab 0 hb pl l (* Positionne les labels sous chaque barre *) let hist_labels hlab hb = let rec mk_labels acc i hlab = match hlab with |x::res -> mk_labels (acc ++ (Command.label ~pos:`South x) (Box.south (Box.nth i hb))) (i+1) res |[]-> acc in mk_labels nop 0 hlab (* Fonction de dessin d'histogramme *) let hist ~cumul width height padding fill perspective scalex scaley ?histlabel ?hlabel cpt l = let rec consvbox boxs = function |[],cq -> vbox boxs,cq |x::res, cq -> let c, cq = Q.pop cq in let b = (set_fill c (set_stroke black (empty ~width:scalex ~height:(multf x scaley) ()))) in consvbox (b::boxs) (res, Q.push c cq) in let rec fct_hist boxs =function |[],_ -> hbox ~pos:`South ~padding:padding (List.rev boxs) |x::res,collist -> let lavbox,listcol = consvbox [] (x,collist) in fct_hist (lavbox::boxs) (res, if cumul then collist else listcol) in let fcth = (fct_hist [] (l,fill)) in let hb = move_hbox cumul cpt scalex fcth in let persp = if perspective then draw_perspect nop (box_perspect scalex hb l) else nop in let labels = match histlabel with | None -> nop | Some lab -> (box_labels lab hb l) in persp ++ Box.draw hb ++ labels ++ (match hlabel with | None -> nop | Some hlab -> (hist_labels hlab hb)) let drawing_parameters width height ?padding nbval valmax nbcol= let padding = match padding with |None -> divf width (4. *. float nbval) |Some i -> i in let scalex = divf (subn width (multf (float ((nbval - 1)/nbcol)) padding)) (float nbval) in let scaley = divf height valmax in scalex, scaley, padding (* Histogramme classique *) let simple ?(width=bp 100.) ?(height=bp 200.) ?padding ?(fill=[lightblue]) ?(perspective=false) ?hcaption ?vcaption ?histlabel ?vlabel ?hlabel l = let histlabel = match histlabel with | None -> None | Some (_, Values) as h -> h | Some (p, User l) -> Some (p, User (List.map (fun x -> [x]) l)) in let valmax = max l in let nbval = List.length l in let scalex, scaley, padding = drawing_parameters width height ?padding nbval valmax 1 in let cq = Q.of_list fill in let l = List.map (fun x -> [x]) l in (hist ~cumul:false width height padding cq perspective scalex scaley ?histlabel ?hlabel 0 l) ++ (laxe ~nbcol:1 padding scalex scaley hcaption vcaption valmax nbval ?vlabel) (* Histogramme de comparaison *) let compare ?(width=bp 100.) ?(height=bp 200.) ?padding ?(fill=[lightblue;red]) ?(perspective=false) ?hcaption ?vcaption ?histlabel ?vlabel ?hlabel l = let nblist = List.length l in let valmax = maxlist l in let nbval = List.fold_left (fun acc x -> (List.length x)+acc) 0 l in let scalex, scaley, padding = drawing_parameters width height ?padding nbval valmax nblist in let rec fct_hist bhlabel c cpt =function |[],_ -> c |x::res,cq -> let col, rescol = Q.pop cq in let x = List.map (fun x -> [x]) x in if (bhlabel) then fct_hist false (c ++ (hist ?hlabel ?histlabel ~cumul:false width height (addn padding (multn (bp ((float_of_int) (nblist-1))) scalex)) (Q.push col Q.empty) perspective scalex scaley cpt x)) (cpt+1) (res, Q.push col rescol) else fct_hist false (c ++ (hist ?histlabel ~cumul:false width height (addn padding (multn (bp ((float_of_int) (nblist-1))) scalex)) (Q.push col Q.empty) perspective scalex scaley cpt x)) (cpt+1) (res, Q.push col rescol) in (fct_hist true nop 0 (l, Q.of_list fill)) ++ (laxe ~nbcol:nblist padding scalex scaley hcaption vcaption valmax nbval ?vlabel) (* Histogramme cumulé *) let stack ?(width=bp 100.) ?(height=bp 200.) ?padding ?(fill=[lightblue;red;green]) ?(perspective=false) ?hcaption ?vcaption ?histlabel ?vlabel ?hlabel l = let nblist = List.length l in let valmax = maxcumul l in let nbval = nblist in let scalex, scaley, padding = drawing_parameters width height ?padding nbval valmax 1 in (hist ~cumul:true width height padding (Q.of_list fill) perspective scalex scaley ?histlabel ?hlabel 0 l) ++ (laxe ~nbcol:1 padding scalex scaley hcaption vcaption valmax nbval ?vlabel) mlpost-0.8.2/latex/000077500000000000000000000000001306046515300141575ustar00rootroot00000000000000mlpost-0.8.2/latex/README000066400000000000000000000004071306046515300150400ustar00rootroot00000000000000If you want to include external images in a figure, you need to put the *.sty and *.tex files at a place that is visible for latex/pdflatex, and you have to include the following lines in your LaTeX file: \usepackage{specials} \LoadMetaPostSpecialExtensions mlpost-0.8.2/latex/beamer_mlpost.sty000066400000000000000000000001351306046515300175500ustar00rootroot00000000000000\newcommand<>{\includesomegraphics}[2][]{\includegraphics#3[#1]{#2\the\beamer@slideinframe}} mlpost-0.8.2/latex/specials.sty000066400000000000000000000023031306046515300165210ustar00rootroot00000000000000% This file % Adds support for extended MetaPost features (transparency) \def\LoadMetaPostSpecialExtensions{% \AtBeginDocument{% \edef\@tempa{% \catcode`\noexpand\=\the\catcode`\= % \catcode`\noexpand\!\the\catcode`\! % \catcode`\noexpand\@\the\catcode`\@ % \catcode`\noexpand\?\the\catcode`\? % }% \@makeother\=% \IfFileExists{supp-pdf}{% \IfFileExists{supp-mis}{% \IfFileExists{supp-mpe}{% \input{supp-mis}% \input{supp-mpe}% \input{supp-mpe_mod}% \MPcmykcolorstrue \MPspotcolorstrue \chardef\makeMPintoPDFobject=1 % }{% \GPT@warn{% Cannot enable MetaPost Special Extensions,\MessageBreak because supp-mpe.tex is missing% }% }% }{% \GPT@warn{% Cannot enable MetaPost Special Extensions,\MessageBreak because supp-mis.tex is missing% }% }% }{% \GPT@warn{% Cannot enable support for MetaPost images,\MessageBreak because supp-pdf.tex is missing% }% }% \@tempa }% } \ifx\@onlypreamble\@undefined \else \@onlypreamble\LoadMetaPostSpecialExtensions \fi mlpost-0.8.2/latex/supp-mpe_mod.tex000066400000000000000000000167061306046515300173200ustar00rootroot00000000000000%Modification of supp-mpe.tex to allow the indirect transformation of % an image %This trick use a square which replace the image in the metapost computation. %mp-spec must be modified: % addto p contour unitsquare scaled 0 ; % is replaced by : % addto p contour unitsquare transformed t ; \unprotect %Accept more than one insertion of the same image \defineMPspecial{10} {\setxvalue{mps:gr:\gMPs8}% {\noexpand\handleMPfigurespecial {\gMPs1}{\gMPs2}{\gMPs3}{\gMPs4}{\gMPs5}{\gMPs6}{\gMPs7}% % \noexpand\setxvalue{mps:gr:\gMPs8}{} }} % \Specialstrigimage isn't 0 only if we parse the square which % replace an image. \newcount{\Specialstrigimage} \Specialstrigimage=0 % The affine part of the matrix of transformation \def\Specialsmataa{}\def\Specialsmatab{}\def\Specialsmatac{} \def\Specialsmatba{}\def\Specialsmatbb{}\def\Specialsmatbc{} % The filename of the current image \def\Specialsfile{} % An usual trick from trig.sty which remove the unit of a dimen {\catcode`t=12\catcode`p=12\gdef\noPT#1pt{#1}} \def\Specialsrempt#1{\expandafter\noPT\the#1\space} % Extract from the path of the square the correct information, ie the % corner of the square % Twice the same function because I 'm not a good tex programmer. \newdimen{\specialstmp} \newdimen{\specialsdumb} \def\SpecialsgetnormalMPsegmenta { \ifcase\getMPkeyword\relax %\PDFcode{\!MPgMPs1 \!MPgMPs2 l}% \edef\myx{\!MPgMPs1} \edef\myy{\!MPgMPs2} \or %\PDFcode{\!MPgMPs1 \!MPgMPs2 \!MPgMPs3 \!MPgMPs4 \!MPgMPs5 \!MPgMPs6 c}% \edef\myx{\!MPgMPs5} \edef\myy{\!MPgMPs6} \or %\PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l}% \edef\myx{\!MPgMPs5} \edef\myy{\!MPgMPs6} \or %\edef\lastMPmoveX{\gMPs1}% evt \!MP here %\edef\lastMPmoveY{\gMPs2}% %\PDFcode{\!MP\lastMPmoveX\space \!MP\lastMPmoveY\space m}% \fi \specialstmp=\Specialsmatac pt \multiply\specialstmp by -1 \specialsdumb=\myx pt \advance\specialstmp by \specialsdumb \global\edef\Specialsmataa{\Specialsrempt\specialstmp} \specialstmp=\Specialsmatbc pt \multiply\specialstmp by -1 \specialsdumb=\myy pt \advance\specialstmp by \specialsdumb \global\edef\Specialsmatba{\Specialsrempt\specialstmp} } \def\SpecialsgetnormalMPsegmentb { \ifcase\getMPkeyword\relax %\PDFcode{\!MPgMPs1 \!MPgMPs2 l}% \edef\myx{\!MPgMPs1} \edef\myy{\!MPgMPs2} \or %\PDFcode{\!MPgMPs1 \!MPgMPs2 \!MPgMPs3 \!MPgMPs4 \!MPgMPs5 \!MPgMPs6 c}% \edef\myx{\!MPgMPs5} \edef\myy{\!MPgMPs6} \or %\PDFcode{\!MP\lastMPmoveX\space\!MP\lastMPmoveY\space l}% \edef\myx{\!MPgMPs5} \edef\myy{\!MPgMPs6} \or %\edef\lastMPmoveX{\gMPs1}% evt \!MP here %\edef\lastMPmoveY{\gMPs2}% %\PDFcode{\!MP\lastMPmoveX\space \!MP\lastMPmoveY\space m}% \fi \specialstmp=\Specialsmatac pt \multiply\specialstmp by -1 \specialsdumb=\myx pt \advance\specialstmp by \specialsdumb \global\edef\Specialsmatab{\Specialsrempt\specialstmp} \specialstmp=\Specialsmatbc pt \multiply\specialstmp by -1 \specialsdumb=\myy pt \advance\specialstmp by \specialsdumb \global\edef\Specialsmatbb{\Specialsrempt\specialstmp} } % Replace the true output function by a filter. It replace the square % by the corresponding image \let\normalPDFcode\PDFcode %%\def\normalPDFcode#1{\donormalPDFcode{#1}} %%\def\PDFcode#1{ % Extract the information from the path %% \ifcase\Specialstrigimage %% % Usually do nothing %% \or %The first move is exactly the translation %% %part of the translation %% \global\edef\Specialsmatac{\gMPs1} %% \global\edef\Specialsmatbc{\gMPs2} %% \or %The second point is the first column of the matrix minus %% %the translation %% \SpecialsgetnormalMPsegmenta %% \or %The Third give only redondant informations %% \or %The second point is the second column of the matrix minus %% %the translation %% \SpecialsgetnormalMPsegmentb %% \else %Sometimes the first point %% \fi % Output the information %% \ifnum\Specialstrigimage=0\relax % Usually the function do nothing %% \normalPDFcode{#1}% %% \else %% % During the parsing of the square : %% \if f#1 %% % The fill instruction is the end of the path %% \global\Specialstrigimage=0 %% % We output the transformation %% \normalPDFcode{q \Specialsmataa\space\Specialsmatba\space\Specialsmatab\space\Specialsmatbb\space\Specialsmatac\space\Specialsmatbc\space cm}% %% % I don't know why this translation is now needed... %% \normalPDFcode{q 1 0 0 1 0 1 cm}% %% \rlap{\getvalue\Specialsfile}% %% \normalPDFcode{Q}% %% \normalPDFcode{Q}% %% \else %% %Otherwise we look for the next point of the path %% \global\advance\Specialstrigimage by \plusone %% \fi %% \fi %%} \let\normalfinishMPpath\finishMPpath \def\finishMPpath { \ifnum\Specialstrigimage=0\relax \normalfinishMPpath \else \global\Specialstrigimage=0 %\global\let\PDFcode\normalPDFcode % We output the transformation \PDFcode{q \Specialsmataa\space\Specialsmatba\space\Specialsmatab\space\Specialsmatbb\space\Specialsmatac\space\Specialsmatbc\space cm}% % I don't know why this translation is now needed... \PDFcode{q 1 0 0 1 0 1 cm}% \rlap{\getvalue\Specialsfile}% \PDFcode{Q}% \PDFcode{Q}% \fi } \let\normalflushnormalMPsegment\flushnormalMPsegment \def\flushnormalMPsegment { %Extract the information from the path \ifcase\Specialstrigimage \or %The first move is exactly the translation %part of the translation \global\edef\Specialsmatac{\gMPs1} \global\edef\Specialsmatbc{\gMPs2} \or %The second point is the first column of the matrix minus %the translation \SpecialsgetnormalMPsegmenta \or %The Third give only redondant informations \or %The second point is the second column of the matrix minus %the translation \SpecialsgetnormalMPsegmentb \else %Sometimes the first point \fi \ifnum\Specialstrigimage=0\relax \normalflushnormalMPsegment \else \global\advance\Specialstrigimage by \plusone \fi } \def\vide#1{} \def\handleMPfigurespecial#1#2#3#4#5#6#7% todo : combine with ext fig {\vbox to \zeropoint {\vss \hbox to \zeropoint {\ifcase\pdfoutput\or % will be hooked into the special driver \doiffileelse{#7} {\doifundefinedelse{mps:x:#7} {\immediate\pdfximage\!!width\onebasepoint\!!height\onebasepoint{#7}% \setxvalue{mps:x:#7}{\pdfrefximage\the\pdflastximage}\message{[not reusing]}}% {\message{[reusing figure #7]}}% %We save the filename of the current image \global\edef\Specialsfile{mps:x:#7}% %\PDFcode{q #1 #2 #3 #4 #5 #6 cm}% %\rlap{\getvalue\Specialsfile}% %\PDFcode{Q}% %And we start the parsing of the square \global\Specialstrigimage=1 \global\let\closeMPpath\relax } {\message{[unknown figure #7]}}% \fi \hss}}} \protect \endinput mlpost-0.8.2/legend.ml000077500000000000000000000036361306046515300146450ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Command open Box open Color let rec mklegend ensstroke colstroke fill vb1 = function |[] -> set_fill fill (set_stroke ensstroke ( box (tabularl ~hpadding:(Num.bp 10.) ~vpadding:(Num.bp 10.) (List.rev vb1)))) |(col,text)::res -> let c = set_fill col (set_stroke colstroke ( empty ~width:(Num.bp 20.) ~height:(Num.bp 10.) ())) in mklegend ensstroke colstroke fill ([c;tex text]::vb1) res let legend ?ensstroke ?colstroke ?fill l = let ensstroke = match ensstroke with |None-> Color.white |Some i -> i in let colstroke = match colstroke with |None-> Color.white |Some i -> i in let fill = match fill with |None-> Color.white |Some i -> i in Picture.make (Box.draw (mklegend ensstroke colstroke fill [] l)) mlpost-0.8.2/mPprint.ml000066400000000000000000000205651306046515300150350ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format open Misc open Concrete_types open Types module C = Compiled_types module M = Matrix let externalimage_dimension filename : float * float = let inch = Unix.open_process_in ("identify -format \"%h\\n%w\" "^filename) in try let h = float_of_string (input_line inch) in let w = float_of_string (input_line inch) in (h,w) with End_of_file | Failure "float_of_string" -> invalid_arg "Unknown external image" let name = pp_print_string let piccorner fmt p = match corner_reduce p with | `Northwest -> fprintf fmt "ulcorner" | `Northeast -> fprintf fmt "urcorner" | `Southwest -> fprintf fmt "llcorner" | `Southeast -> fprintf fmt "lrcorner" let position fmt p = match pos_reduce p with | `Center -> fprintf fmt "" | `West -> fprintf fmt ".lft" | `East -> fprintf fmt ".rt" | `North -> fprintf fmt ".top" | `South -> fprintf fmt ".bot" | `Northwest -> fprintf fmt ".ulft" | `Northeast -> fprintf fmt ".urt" | `Southwest -> fprintf fmt ".llft" | `Southeast -> fprintf fmt ".lrt" let rec num fmt f = if f = infinity then fprintf fmt "infinity" else if f > 4095. then fprintf fmt "%g" 4095. else if abs_float f < 0.0001 then fprintf fmt "0" else fprintf fmt "%g" f and float fmt = num fmt (* One bug : rgb and transparent can collide : rgb(0.123 0.003 0.001) et rgba(1,1,1,1) since this is encoding lie the first one *) and scolor fmt = function | RGB (r,g,b) -> fprintf fmt "(%a, %a , %a@,)" float r float g float b | CMYK (c,m,y,k) -> fprintf fmt "(%a, %a, %a, %a@,)" float c float m float y float k | Gray f -> fprintf fmt "%a * white" float f and color fmt = function | OPAQUE c -> scolor fmt c | TRANSPARENT (f,c) -> fprintf fmt "transparent (1,%a,%a@,)" float f scolor c (* 1 is the "normal" mode *) and point fmt { Point_lib.x = x ; y = y } = fprintf fmt "(%a,@ %a@,)" num x num y and transform fmt t = fprintf fmt "transformed %s" t and picture fmt = function | C.PITex s -> fprintf fmt "btex %s etex" s | C.PITransformed (p, tr) -> fprintf fmt "((%a) %a@,)" picture p transform tr | C.PIName n -> pp_print_string fmt n and path fmt = function C.PAScope p -> fprintf fmt "(%a@,)" path p | C.PAFullCircle -> fprintf fmt "fullcircle" | C.PAHalfCircle -> fprintf fmt "halfcircle" | C.PAQuarterCircle -> fprintf fmt "quartercircle" | C.PAUnitSquare -> fprintf fmt "unitsquare" | C.PATransformed (p,tr) -> fprintf fmt "((%a) %a@,)" path p transform tr | C.PAAppend (p1,j,p2) -> fprintf fmt "%a %a@ %a" path p1 joint j path p2 | C.PACycle (d,j,p) -> fprintf fmt "%a %a %acycle" path p joint j direction d | C.PAConcat (k,j,p) -> fprintf fmt "%a %a@ %a" path p joint j knot k | C.PAKnot k -> knot fmt k | C.PACutAfter (p1, p2) -> fprintf fmt "%a cutafter (%a)@ " path p2 path p1 | C.PACutBefore (p1, p2) -> fprintf fmt "%a cutbefore (%a)@ " path p2 path p1 | C.PABuildCycle l -> fprintf fmt "buildcycle(%a@,)" (Misc.print_list comma path) l | C.PASub (f1, f2, p) -> fprintf fmt "subpath(%a,%a) of %a" num f1 num f2 name p | C.PABBox p -> fprintf fmt "bbox %a" picture p | C.PAName n -> pp_print_string fmt n and joint fmt = function | C.JLine -> fprintf fmt "--" | C.JCurve -> fprintf fmt ".." | C.JCurveNoInflex -> fprintf fmt "..." | C.JTension (a,b) -> fprintf fmt "..tension %a and %a .." float a float b | C.JControls (a,b) -> fprintf fmt "..controls %a and %a .." point a point b and direction fmt = function | C.NoDir -> () | C.Vec p -> fprintf fmt "{%a}" point p (* Why there is not the same thing than in Num?*) | C.Curl f -> fprintf fmt "{curl %a}" float f and knot fmt (d1,p,d2) = fprintf fmt "%a%a%a" direction d1 point p direction d2 and dash fmt = function | C.DEvenly -> fprintf fmt "evenly" | C.DWithdots -> fprintf fmt "withdots" | C.DScaled (s, d) -> fprintf fmt "%a scaled %a" dash d num s | C.DShifted (p, d) -> fprintf fmt "%a shifted %a" dash d point p | C.DPattern l -> fprintf fmt "dashpattern("; List.iter (fun p -> let p,n = match p with C.On n -> "on", n | C.Off n -> "off", n in fprintf fmt "%s %a " p num n) l; fprintf fmt ")" and pen fmt = function | C.PenCircle -> fprintf fmt "pencircle" | C.PenSquare -> fprintf fmt "pensquare" | C.PenFromPath p -> fprintf fmt "makepen (%a@,)" path p | C.PenTransformed (p,tr) -> fprintf fmt "%a %a" pen p transform tr and command fmt = function | C.CDraw (pa, c, pe, dashed) -> fprintf fmt "@[draw@ %a@,%a@,%a@,%a;@]@\n" path pa (print_option " withcolor " color) c (print_option " withpen " pen) pe (print_option " dashed " dash) dashed | C.CDrawArrow (pa, c, pe, dashed) -> fprintf fmt "drawarrow %a%a%a%a;@\n" path pa (print_option " withcolor " color) c (print_option " withpen " pen) pe (print_option " dashed " dash) dashed | C.CFill (pa, c) -> fprintf fmt "fill %a%a;@\n" path pa (print_option " withcolor " color) c | C.CLabel (pic,pos,p) -> fprintf fmt "label%a(%a,@ %a); @\n" position pos picture pic point p | C.CDotLabel (pic,pos,p) -> fprintf fmt "@[dotlabel%a(%a,@ %a);@]@\n" position pos picture pic point p | C.CDrawPic p -> fprintf fmt "draw %a;@\n" picture p | C.CSeq l -> List.iter (fun c -> command fmt c) l | C.CDeclPath (n, p) -> fprintf fmt "path %s ;@\n%s = %a;@\n" n n path p | C.CDeclPoint (n, p) -> fprintf fmt "pair %s ;@\n%s = %a;@\n" n n point p | C.CDeclNum (n, nm) -> fprintf fmt "numeric %s ;@\n%s = %a;@\n" n n num nm | C.CSimplePic (pn1, pexpr) -> fprintf fmt "picture %s;@\n" pn1; fprintf fmt "%s := %a;@\n" pn1 picture pexpr; | C.CDefPic (pic, cmd) -> (* Declpic (savepic, currentpicture); * Assign (currentpicture, nullpicture); * cmd; * Assign (pic, currentpicture); * Assign (currentpicture, savepic) *) let savepic = Name.picture () in fprintf fmt "picture %s, %s ;@\n" savepic pic; fprintf fmt "%s = currentpicture;@\n" savepic; fprintf fmt "currentpicture := nullpicture;@\n"; command fmt cmd; fprintf fmt "%s = currentpicture;@\n" pic; fprintf fmt "currentpicture := %s;@\n" savepic | C.CDefTrans (n,t) -> fprintf fmt "transform %s ;@\n\ xpart %s = %a;@\n\ ypart %s = %a;@\n\ xxpart %s = %a;@\n\ xypart %s = %a;@\n\ yxpart %s = %a;@\n\ yypart %s = %a;@\n@." n n num t.M.x0 n num t.M.y0 n num t.M.xx n num t.M.xy n num t.M.yx n num t.M.yy | C.CClip (pic,pth) -> fprintf fmt "clip %s to %a;@\n" pic path pth | C.CExternalImage (filename, spec) -> match spec with | `Exact (h,w) -> fprintf fmt "externalfigure \"%s\" xyscaled (%a,%a);@\n" filename num w num h | ((`None as spec) | (`Height _ as spec)| (`Width _ as spec)| (`Inside _ as spec)) -> let fh,fw = externalimage_dimension filename in let printext h w = fprintf fmt "externalfigure \"%s\" xyscaled (%a,%a);@\n" filename num w num h in match spec with | `None -> printext fh fw | `Height h -> printext h ((fw/.fh) *. h) | `Width w -> printext ((fh/.fw) *. w) w | `Inside (h,w) -> let w = min (h *. (fw/.fh)) w in printext ((fh/.fw) *. w) w mlpost-0.8.2/metaPath.ml000066400000000000000000000073751306046515300151530ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module S = Point open Types module BaseDefs = struct type direction = Types.direction let vec = mkVec let curl = mkCurl let noDir = mkNoDir type joint = Types.joint let jLine = mkJLine let jCurve = mkJCurve let jCurveNoInflex = mkJCurveNoInflex let jTension = mkJTension let jControls = mkJControls type knot = Types.knot (* the intention is to add new knots in front, * i. e. the list has to be reversed for printing *) let of_path p = mkMPAofPA p let of_metapath p = mkPAofMPA p let to_path = of_metapath let to_metapath = of_path let start k = mkMPAKnot k let metacycle d j p = mkMPACycle d j p let fullcircle = mkPAFullCircle let halfcircle = mkPAHalfCircle let quartercircle = mkPAQuarterCircle let unitsquare = mkPAUnitSquare let cut_after p1 p2 = mkPACutAfter p1 p2 let cut_before p1 p2 = mkPACutBefore p1 p2 let build_cycle l = mkPABuildCycle l let subpath (f1: float) (f2: float) p = mkPASub f1 f2 p (* let point (f: float) p = mkPTPointOf f p *) (* let direction (f: float) p = mkPTDirectionOf f p *) let subpathn = subpath let length p = let p = Compute.path p in float (Spline_lib.length p) let defaultjoint = jCurve let defaultdir = noDir end include BaseDefs type t = metapath type path = Types.path let knotp ?(l=defaultdir) ?(r=defaultdir) p = Types.mkKnot l p r let knot ?(l) ?(r) ?(scale) p = knotp ?l (S.p ?scale p) ?r let knotn ?(l) ?(r) p = knotp ?l (S.pt p) ?r let knotlist = List.map (fun (x,y,z) -> Types.mkKnot x y z) let cycle ?(dir=defaultdir) ?(style=defaultjoint) p = metacycle dir style p let concat ?(style=defaultjoint) p k = mkMPAConcat k style p (* construct a path with a given style from a knot list *) let pathk ?(style) = function | [] -> failwith "empty path is not allowed" | (x::xs) -> List.fold_left (fun p knot -> concat ?style p knot) (start x) xs let pathp ?(style) l = pathk ?style (List.map (knotp) l) let pathn ?(style) l = pathp ?style (List.map (Point.pt) l) let path ?(style) ?(scale) l = let sc = S.ptlist ?scale in pathp ?style (sc l) (* construct a path with knot list and joint list *) let jointpathk lp lj = try List.fold_left2 (fun acc j k -> mkMPAConcat k j acc) (start (List.hd lp)) lj (List.tl lp) with Invalid_argument _ -> invalid_arg "jointpathk : the list of knot must \ be one more than the list of join" let jointpathp lp lj = jointpathk (List.map (knotp) lp) lj let jointpathn lp lj = jointpathk (List.map knotn lp) lj let jointpath ?(scale) lp lj = jointpathk (List.map (knot ?scale) lp) lj let append ?(style=defaultjoint) p1 p2 = mkMPAAppend p1 style p2 mlpost-0.8.2/metapost.ml000066400000000000000000000163061306046515300152360ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format let print fmt i c = (* resetting is actually not needed; variables other than x,y are not local to figures *) (* Compile.reset (); *) let () = Duplicate.commandpic c in let c = Compile.commandpic_cmd c in fprintf fmt "@[beginfig(%d)@\n @[%a@] endfig;@]@." i MPprint.command c let print_prelude s fmt () = fprintf fmt "input metafun.mp ; %% some initializations and auxiliary macros %% macros that support special features @\n"; fprintf fmt "prologues := 0;@\n"; fprintf fmt "mpprocset := 0;@\n"; fprintf fmt "verbatimtex@\n"; fprintf fmt "%%&latex@\n"; fprintf fmt "%s" s; fprintf fmt "\\begin{document}@\n"; fprintf fmt "etex@\n" (* fprintf fmt "input boxes;@\n" *) (** take a list of figures [l] and write the code to the formatter in argument *) let mp bn ?prelude l = let prelude = match prelude with | None -> Defaults.get_prelude () | Some s -> s in let f = File.set_ext (File.from_string bn) "mp" in File.write_to_formatted f (fun fmt -> print_prelude prelude fmt (); let i = ref 1 in let m = List.fold_left (fun acc (t,f) -> let acc = Misc.IntMap.add !i t acc in print fmt !i f; incr i; acc) Misc.IntMap.empty l in fprintf fmt "end@."; f,m) (* batch processing *) let dump_tex ?prelude f = let c = open_out (f ^ ".tex") in let fmt = formatter_of_out_channel c in begin match prelude with | None -> fprintf fmt "\\documentclass[a4paper]{article}" | Some s -> fprintf fmt "%s@\n" s end; fprintf fmt "\\usepackage{graphicx}"; fprintf fmt "%%%%%%%% %% For specials in mps \\LoadMetaPostSpecialExtensions %%%%%%%% "; fprintf fmt "\\begin{document}@\n"; fprintf fmt "\\begin{center}@\n"; Queue.iter (fun (s,_) -> fprintf fmt "\\hrulefill\\verb!%s!\\hrulefill\\\\[1em]@\n" s; fprintf fmt "\\includegraphics{%s}\\\\@\n" (File.to_string (File.set_ext (File.from_string s) "mps")); fprintf fmt "\\hrulefill\\\\@\n@\n\\medskip@\n";) Defaults.figures; fprintf fmt "\\end{center}@\n"; fprintf fmt "\\end{document}@."; close_out c let call_latex ?inv ?outv ?verbose f = let cmd = Misc.sprintf "latex -interaction=nonstopmode %s" f in Misc.call_cmd ?inv ?outv ?verbose cmd let call_mpost ?inv ?outv ?verbose f = let cmd = Misc.sprintf "mpost -interaction=nonstopmode %s" (File.to_string f) in Misc.call_cmd ?inv ?outv ?verbose cmd let print_latex_error () = if Sys.file_exists "mpxerr.tex" then begin Printf.printf "############################################################\n"; Printf.printf "LaTeX has found an error in your file. Here is its output:\n"; ignore (call_latex ~outv:true "mpxerr.tex") end (* else Printf.printf "There were (ignored) errors during the execution of metapost. \ Execute with option -v to see the errors.\n" *) let mps ?prelude ?(verbose=false) bn figl = if figl <> [] then let targets = List.map (fun (bn,_) -> File.set_ext (File.from_string bn) "mps") figl in let f, m = mp bn ?prelude figl in let s = call_mpost ~verbose f in if s <> 0 then print_latex_error (); Misc.IntMap.iter (fun k to_ -> let from = File.set_ext f (string_of_int k) in let to_ = File.mk to_ "mps" in File.move from to_) m; targets else [] let call_mptopdf ?inv ?outv ?verbose f = (** assume that f is ps file or sth like that *) ignore (Misc.call_cmd ?inv ?outv ?verbose (sprintf "mptopdf %s" (File.to_string f))); let out = File.set_ext f "pdf" in File.move (File.append out ("-"^File.extension f)) out; out let call_convert ?inv ?outv ?verbose from to_ = ignore (Misc.call_cmd ?inv ?outv ?verbose (sprintf "convert -density 600x600 \"%s\" \"%s\"" (File.to_string from) (File.to_string to_))); to_ let pdf ?prelude ?verbose bn figl = let l = mps ?prelude ?verbose bn figl in List.map (fun f -> call_mptopdf ?verbose f) l let png ?prelude ?verbose bn figl = let pdfl = pdf ?prelude ?verbose bn figl in List.map (fun f -> call_convert ?verbose f (File.set_ext f "png")) pdfl let wrap_tempdir f suffix ?prelude ?verbose ?clean bn figl = let do_ from_ to_ = (** first copy necessary files, then do your work *) List.iter (fun f -> File.copy (File.place from_ f) (File.place to_ f)) (Defaults.get_required_files ()); let l = f ?prelude ?verbose bn figl in l, l in Metapost_tool.tempdir ?clean "mlpost" ("metapost-"^suffix) do_ let temp_mp ?prelude ?(verbose=false) ?(clean=true) = mp ?prelude let temp_mps = wrap_tempdir mps "mps" let temp_pdf = wrap_tempdir pdf "pdf" let temp_png = wrap_tempdir png "png" let wrap_dump f ?prelude ?verbose ?clean bn = let bn = Filename.basename bn in ignore (f ?prelude ?verbose ?clean bn (Defaults.emited ())) let dump_mp = wrap_dump temp_mp let dump_mps = wrap_dump temp_mps let dump_pdf = wrap_dump temp_pdf let dump_png = wrap_dump temp_png let generate ?prelude ?verbose ?clean bn figl = ignore (temp_mps ?prelude ?verbose ?clean bn figl) let slideshow l k = let l = List.map Picture.make l in let l' = Command.seq (List.map (fun p -> Command.draw ~color:Color.white (Picture.bbox p)) l) in let x = ref (k-1) in List.map (fun p -> incr x; !x, Command.seq [l'; Command.draw_pic p]) l let emit_slideshow s l = let l = slideshow l 0 in List.iter (fun (i,fig) -> Defaults.emit (s^(string_of_int i)) fig) l let dumpable () = Queue.iter (fun (s,_) -> Printf.printf "%s\n" s) Defaults.figures let depend myname = Queue.iter (fun (s,_) -> Printf.printf "%s" (File.to_string (File.mk s "fmlpost"))) Defaults.figures; Printf.printf " : %s.cmlpost\n" myname (* compatibility *) let read_prelude_from_tex_file = Metapost_tool.read_prelude_from_tex_file let emit = Defaults.emit let dump ?prelude ?(pdf = false) ?(eps = false) ?verbose ?clean s = if pdf then dump_pdf ?prelude ?verbose ?clean s else dump_mps ?prelude ?verbose ?clean s let set_filename_prefix = Defaults.set_filename_prefix type job = Defaults.job type jobs = Defaults.jobs mlpost-0.8.2/metapost.mli000066400000000000000000000044221306046515300154030ustar00rootroot00000000000000(* type job = File.t * Types.commandpic type jobs = job list (** A queue of jobs; TODO move this to another module *) val figures : job Queue.t val emited : unit -> jobs val emit : string -> Types.commandpic -> unit *) val generate : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> (string * Types.commandpic) list -> unit (** Generate files of corresponding type, using the argument of type [jobs], and return information about the created files *) val mp : string -> ?prelude:string -> Defaults.jobs -> File.t * string Misc.IntMap.t val mps : ?prelude:string -> ?verbose:bool -> string -> Defaults.jobs -> File.t list val pdf : ?prelude:string -> ?verbose:bool -> string -> Defaults.jobs -> File.t list val png : ?prelude:string -> ?verbose:bool -> string -> Defaults.jobs -> File.t list (** Same as above, but use a temporary directory *) val temp_mp : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> Defaults.jobs -> File.t * string Misc.IntMap.t val temp_mps : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> Defaults.jobs -> File.t list val temp_pdf : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> Defaults.jobs -> File.t list val temp_png : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> Defaults.jobs -> File.t list (** Same as above, but use a temporary directory and take jobs from the job queue *) val dump_mp : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val dump_mps : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val dump_png : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val dump_pdf : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val dump_tex : ?prelude:string -> string -> unit val slideshow : Types.commandpic list -> int -> (int * Types.commandpic) list val emit_slideshow : string -> Types.commandpic list -> unit val dumpable : unit -> unit val depend : string -> unit (* compatibility *) val read_prelude_from_tex_file : string -> string val emit : string -> Types.commandpic -> unit val dump : ?prelude:string -> ?pdf:bool -> ?eps:bool -> ?verbose:bool -> ?clean:bool -> string -> unit val set_filename_prefix : string -> unit type job = Defaults.job type jobs = Defaults.jobs mlpost-0.8.2/metapost_tool.ml000066400000000000000000000046321306046515300162720ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) let read_prelude_from_tex_file file = File.LowLevel.read_from file (fun c -> Scan_prelude.scan (Lexing.from_channel c)) let rnd_state = Random.State.make_self_init () (** create a temporary directory *) let rec create_temp_dir prefix suffix = try let i = Random.State.int rnd_state 10000 in let dir = File.Dir.from_string (Printf.sprintf "%s%i%s" prefix i suffix) in let dirname = File.Dir.concat File.Dir.temp dir in File.Dir.mk dirname 0o700; dirname with Unix.Unix_error (Unix.EEXIST, _, _) -> create_temp_dir prefix suffix (** create a temporary directory and call function [f] within. * [f] has to return a result [res] and a list of files [files] that are * copied from the [tmpdir] to the [workdir] *) let tempdir ?(clean=true) prefix suffix f = let tmpdir = create_temp_dir prefix suffix in let workdir = File.Dir.cwd () in File.Dir.ch tmpdir; let res, files = f workdir tmpdir in File.Dir.ch workdir; List.iter (fun r -> let from = File.place tmpdir r in let to_ = File.place workdir r in File.move from to_) files; if clean then File.Dir.rm tmpdir; res let append_dir dir suffix = let dir = if Filename.check_suffix dir File.dir_sep_string then Filename.chop_suffix dir File.dir_sep_string else dir in dir^suffix mlpost-0.8.2/misc.ml000066400000000000000000000115371306046515300143360ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) let id x = x let print_option start printer fmt = function | None -> () | Some o -> Format.fprintf fmt "%s%a " start printer o let date_string () = let tm = Unix.gmtime (Unix.time ()) in Printf.sprintf "%d/%d/%d, %d:%d:%d" (tm.Unix.tm_mon + 1) tm.Unix.tm_mday (tm.Unix.tm_year + 1900) tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec let rec print_list sep prf fmt = function | [] -> () | [x] -> prf fmt x | (x::xs) -> prf fmt x; sep fmt (); print_list sep prf fmt xs let print_iter1 iter sep print fmt l = let first = ref true in iter (fun x -> if !first then first := false else sep fmt (); print fmt x ) l let print_iter2 iter sep1 sep2 print1 print2 fmt l = let first = ref true in iter (fun x y -> if !first then first := false else sep1 fmt (); print1 fmt x;sep2 fmt (); print2 fmt y) l let space fmt () = Format.fprintf fmt "@ " let comma fmt () = Format.fprintf fmt ",@ " let semicolon fmt () = Format.fprintf fmt ";@ " let newline fmt () = Format.fprintf fmt "@\n " let nothing _fmt _ = () let print_int32 fmt i = Format.fprintf fmt "%ld" i let rec fold_from_to f acc a b = if a <= b then fold_from_to f (f acc a) (a+1) b else acc let sprintf s = let buf = Buffer.create 1024 in let fmt = Format.formatter_of_buffer buf in Format.kfprintf (fun _ -> Format.pp_print_flush fmt (); Buffer.contents buf) fmt s (*Filename.generic_quote*) let generic_quote whatquote quotequote s = let l = String.length s in let b = Buffer.create (l + 20) in for i = 0 to l - 1 do if s.[i] = whatquote then Buffer.add_string b quotequote else Buffer.add_char b s.[i] done; Buffer.contents b let generic_quote_list lwqq s = let l = String.length s in let b = Buffer.create (l + 20) in for i = 0 to l - 1 do if List.mem_assoc s.[i] lwqq then Buffer.add_string b (List.assoc s.[i] lwqq) else Buffer.add_char b s.[i] done; Buffer.contents b let call_cmd ?(inv=false) ?(outv=false) ?(verbose=false) cmd = (* inv = true -> print command line * outv = true -> print command output * verbose = true -> both *) if inv || verbose then Format.printf "+ %s@." cmd; let (outc,inc,errc) as proc = Unix.open_process_full cmd (Unix.environment ()) in close_out inc; let out_descr = Unix.descr_of_in_channel outc and err_descr = Unix.descr_of_in_channel errc in (* using Unix.select as in OCaml PLEAC *) let selector = ref [ out_descr ; err_descr ] in let buf = String.create 1024 in while !selector <> [] do let can_read, _, _ = Unix.select !selector [] [] 1.0 in List.iter (fun fh -> let ret = Unix.read fh buf 0 1024 in if ret = 0 then selector := List.filter (fun fh' -> fh <> fh') !selector; if outv || verbose then if fh = err_descr then ignore (Unix.write Unix.stderr buf 0 ret) else ignore (Unix.write Unix.stdout buf 0 ret)) can_read done; let status = Unix.close_process_full proc in flush stdout; flush stderr; match status with | Unix.WEXITED n -> if n > 124 then begin Printf.eprintf "command %s has aborted with exit code: %d@\n" cmd n; exit n end; n | _ -> exit 1 (* persistent queues *) module Q = struct type 'a t = 'a list * 'a list exception Empty let empty = [], [] let push x (i, o) = (x :: i, o) let pop = function | [], [] -> raise Empty | (i, x :: o) -> x, (i, o) | (i, []) -> match List.rev i with | x :: o -> x, ([], o) | [] -> assert false let of_list l = List.fold_left (fun q c -> push c q) empty l end module StringMap = Map.Make(String) module IntMap = Map.Make(struct type t = int let compare = Pervasives.compare end) mlpost-0.8.2/mlpost.1000066400000000000000000000057721306046515300144550ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .TH MLPOST 1 "August 2009" .\" Please adjust this date whenever revising the manpage. .SH NAME mlpost \- wrapper around OCaml and Metapost for the Mlpost library .SH SYNOPSIS .B mlpost .RI [options] " files"... .SH DESCRIPTION .PP \fBmlpost\fP is a program that compiles OCaml files to PostScript or PDF files using the Mlpost library. .SH OPTIONS .TP .B \-pdf Generate .mps files (default) .TP .B \-mp Generate .mp files .TP .B \-png Generate .png files .TP .B \-ps Generate .1 files .TP .B \-latex Scan the LaTeX prelude .TP .B \-eps Generate encapsulated postscript files .TP .B \-xpdf WYSIWYG mode using xpdf remote server (the name of the remote server is "mlpost") .TP .B \-v Be a bit more verbose. Otherwise nothing is printed except in case of error. .TP .B \-ocamlbuild Use ocamlbuild to compile .TP .B \-native Compile to native code .TP .B \-ccopt "" Pass to the Ocaml compiler .TP .B \-execopt "" Pass to the compiled program .TP .B \-version Print Mlpost version and exit .TP .B \-no\-magic Do not parse mlpost options, do not call Metapost.dump .TP .B \-depend output dependency lines in a format suitable for the make(1) utility .TP .B \-contrib "" compile with the specified contrib .TP .B \-dumpable output one name of dumpable file by line. So it print all the figures which will be created by the .ml file. .TP .B \-get\-include\-compile {cmxa|cma|dir|file} output the libraries which are needed by the library Mlpost if you want not to use the mlpost tool : .IP \- cmxa print the needed cmxa file (opt version) \- cma print the needed cma file (byte version) \- dir print the directories needed to be include \- file print the file name inside this directory without extension .TP .B \-compile\-name Keep the compiled version of the .ml file and name it . .TP .B \-dont\-execute Don't execute the mlfile. So mlpost generates no figures. With this option you can check that a file compile without wasting time to generate the figures. The options \-dont\-execute and \-compile\-name can be used in conjunction to create a program which generates some figures according to some command line options. .TP .B \-dont\-clean Don't remove intermediates files. The metapost backend use some intermediates files which are removed without this option. .TP .B \-cairo Use the cairo backend instead of metapost .TP .B \-t1disasm Set the program used to decrypt PostScript Type 1 font, only with cairo (default built-in one). This option will disappear soon. .TP .B \-help, \-\-help Display the list of options .SH SEE ALSO .BR mpost (1), .BR ocamlc (1), .BR xpdf (1). .br .SH AUTHOR Mlpost was written by Romain Bardou, François Bobot, Johannes Kanig, Stéphane Lescuyer and Jean-Christophe Filliâtre. .PP This manual page was written by Stéphane Glondu and completed by the Mlpost authors for the Debian project (but may be used by others). mlpost-0.8.2/mlpost.el000066400000000000000000000002401306046515300146760ustar00rootroot00000000000000(defun mlpost () "launch a remote xpdf for use with mlpost -xpdf" (interactive) (call-process "xpdf" nil 0 nil "-remote" "mlpost" "_mlpost.pdf") ) mlpost-0.8.2/mlpost.mli000066400000000000000000002712751306046515300151010ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module Signature : sig type point module type Boxlike = sig type t val width : t -> float val height : t -> float val set_pos : point -> t -> t end end module File : sig type t val from_string : string -> t val to_string : t -> string end module Ctypes : sig IFDEF CAIRO THEN type matrix = Cairo.matrix = { xx : float; yx : float; xy : float; yy : float; x0 : float; y0 : float;} type point = Cairo.point = {x : float; y : float} ELSE type matrix = { xx : float; yx : float; xy : float; yy : float; x0 : float; y0 : float;} type point = {x : float; y : float} END end (** {2 Interfaces to basic Metapost datatypes} *) (** Abstract numeric values *) module Num : sig (** Numerics are a symbolic representation of numeric values. In many cases, but not always, an object of type {!Num.t} is intended to be a length in some unit. In addition, values of type {!Num.t} may actually be unknown to Mlpost. This is why there is no function that gives back a [float]. *) type t = float (** The Mlpost numeric type is an abstract datatype *) (** {2 Conversion functions} *) val of_float : float -> t (** Convert a float into a {!Num.t} *) val bp : float -> t (** The base unit in Mlpost is bp. *) val pt : float -> t (** pt are PostScript points. This is the same unit as the pt unit in TeX *) val cm : float -> t val mm : float -> t val inch : float -> t (** The following are units dependent of the font used *) val em : float -> t (** the width of an "m" *) val ex : float -> t (** the height of an "x" *) (** {2 Useful operations on Nums} *) val addn : t -> t -> t val subn : t -> t -> t val multn : t -> t -> t val multf : float -> t -> t val divf : t -> float -> t val neg : t -> t val divn : t -> t -> t val maxn : t -> t -> t val minn : t -> t -> t val gmean : t -> t -> t (** the geometric mean of two nums : sqrt(a * a + b * b) *) val if_null : t -> t -> t -> t (** if_null n n1 n2 is equal to n1 if n is null, n2 othewise *) (** {3 Infix operators} *) module Infix : sig (** Infix symbols for convenience *) val (+/) : t -> t -> t (** alias for {!Num.addn} *) val (-/) : t -> t -> t (** alias for {!Num.subn} *) val ( */) : t -> t -> t (** alias for {!Num.multn} *) val (//) : t -> t -> t (** alias for {!Num.divn} *) val ( *./): float -> t -> t (** alias for {!Num.multf} *) val (/./): t -> float -> t (** alias for {!Num.divf} *) end (** {2 Useful constants and functions} *) val zero : t val one : t val two : t (** Shortcuts for [bp 0.], [bp 1.] and [bp 2.]. *) val pi : float (** 3 .14159 *) val deg2rad : float -> float (** Converts degrees into radians *) type scale = float -> t module Scale : sig val bp : float -> scale val pt : float -> scale val cm : float -> scale val mm : float -> scale val inch : float -> scale end end (** Definitions of many colors *) module Color : sig (** Colors *) type t (** the abstract type of colors *) val default : t (** the default color is black *) val rgb : float -> float -> float -> t (** [rgb r g b] constructs the color that corresponds to the color code RGB(r,g,b) *) val rgb8 : int -> int -> int -> t (** similar to [rgb], but takes integers between 0 and 255 as argument *) val cmyk : float -> float -> float -> float -> t (** [cmyk c m y k] constructs the color that corresponds to the color code CMYK(c,m,y,k) *) (** WARNING : If you use transparency with .mps file in your latex document you need to add : \LoadMetaPostSpecialExtensions in the preamble *) val rgba : float -> float -> float -> float -> t (** similar to [rgb], but takes the factor of transparency *) val rgba : float -> float -> float -> float -> t (** similar to [rgb], but takes the factor of transparency *) val rgb8a : int -> int -> int -> int -> t (** similar to [rgb8], but takes the factor of transparency *) val cmyka : float -> float -> float -> float -> float -> t (** similar to [cmyk], but takes the factor of transparency *) val is_opaque : t -> bool (** test if the color is opaque *) val opaque : t -> t (** make a color opaque *) val transparent : float -> t -> t (** [transparent f c] multiplies by f the factor of transparency of c *) val hsv : float -> float -> float -> t (** hsv h s v convert an hsv color to an rgb. 0 <= h < 360, 0 <= s,v <= 1*) (** {3 color generator} *) val color_gen : float -> float -> (unit -> t) (* color_gen s v creates a generator of colors which return a different color (with saturation s and value v) each time it is called. The goal is to have colors with a good contrast between them. For given s and v the resutl is deterministically *) (** {2 Predefined Colors} *) (** {3 base colors} *) val white : t val black : t val red : t val blue : t val green : t val cyan : t val yellow : t val magenta : t (** {3 lighter colors} *) val lightred : t val lightblue : t val lightgreen : t val lightcyan : t val lightyellow : t val lightmagenta : t (** {3 grays} *) val gray : float -> t val lightgray : t val mediumgray : t val darkgray : t (** {3 additional colors} *) val orange : t val purple : t (** {3 X11-named Colors} *) val color : string -> t (** [color n] returns the RGB color associated to name [n] (as defined in /etc/X11/rgb.txt). Raises [Not_found] if [n] does not correspond to a color. See {{:http://en.wikipedia.org/wiki/X11_color_names} this list} for an overview.*) end (** Points in the plane *) module rec Point : sig (** The abstract type for points *) type t = Signature.point (** Construct a point from two numeric values *) val pt : Num.t * Num.t -> t (** The following functions create points of length 1. They are especially useful to specify directions with [Path.Vec] *) (** [dir f] is the point at angle [f] on the unit circle. [f] shall be given in degrees *) val dir : float -> t (** The unitary vectors pointing up, down, left and right *) val up : t val down : t val left : t val right : t val origin : t val length : t -> Num.t (** [length p] is the length of vector from the origin to [p] *) val xpart : t -> Num.t (** [xpart p] is the x coordinate of point [p] *) val ypart : t -> Num.t (** [ypart p] is the y coordinate of point [p] *) (** {2 Operations on points} *) val transform : Transform.t -> t -> t (** Apply a transformation to a point *) val segment : float -> t -> t -> t (** [segment f p1 p2] is the point [(1-f)p1 + fp2]. Stated otherwise, if [p1] is at [0.] and [p2] is at [1.], return the point that lies at [f] *) val add : t -> t -> t val shift : t -> t -> t (** Sum two points *) val sub : t -> t -> t (** Substract two points *) val mult : Num.t -> t -> t val scale : Num.t -> t -> t (** Multiply a point by a scalar *) val rotate : float -> t -> t (** Rotate a point by an angle in degrees *) (** [rotate_around p1 f p2] rotates [p2] around [p1] by an angle [f] in degrees *) val rotate_around : t -> float -> t -> t (** Scales the X coordinate of a point by a scalar *) val xscale : Num.t -> t -> t (** Scales the Y coordinate of a point by a scalar *) val yscale : Num.t -> t -> t (** Normalize the vector represented by the point. The origin becomes the origin *) val normalize : t -> t (** {2 Convenient constructors} *) (** The following functions build a point at a given scale (see {!Num.t} for scales) *) val bpp : float * float -> t val inp : float * float -> t val cmp : float * float -> t val mmp : float * float -> t val ptp : float * float -> t (** Same as the previous functions but build list of points *) val map_bp : (float * float) list -> t list val map_in: (float * float) list -> t list val map_cm: (float * float) list -> t list val map_mm: (float * float) list -> t list val map_pt: (float * float) list -> t list (** Builds a point from a pair of floats @param scale a scaling function to be applied to each float; see {!Num.t} for scaling functions for usual units *) val p : ?scale:(float -> Num.t) -> float * float -> t (** Same as [p], but builds a list of points *) val ptlist : ?scale:(float -> Num.t) -> (float * float) list -> t list val draw : ?brush:Brush.t -> ?color:Color.t -> ?pen:Pen.t -> t -> Command.t (** Draw a point @param color the color of the point; default is black @param pen the pen used to draw the pen; default is [Brush.Pen.default]*) end (** MetaPaths: gradually build a path with constraints, get a real path at thxe end. *) and MetaPath : sig (** MetaPaths are the objects used to describe lines, curves, and more generally almost everything that is drawn with Mlpost. A path ([Path.t]) is defined by points and control points. A metapath is defined by points (knots) and constraints on the links between the points. A metapath is an easy way to define a path gradually with only a few points, and apply heuristics afterwards to transform it into a real path (using [of_metapath]). *) (** A [direction] is used to put constraints on metapaths: {ul {- [vec p] defines a direction by a point (interpreted as a vector)} {- [curl f] changes the curling factor of the extremity of a metapath; higher curling factor means flatter curves} {- [noDir] means no particular direction} } *) type direction = Path.direction val vec : Point.t -> direction val curl : float -> direction val noDir : direction (** A [knot] is the basic element of a metapath, and is simply a point with an incoming and outgoing direction constraint *) type knot = Path.knot (** Build a knot from a point; the optional arguments are the incoming directions.Warning they are going in the same direction. *) val knotp : ?l:direction -> ?r:direction -> Point.t -> knot val knotlist : (direction * Point.t * direction) list -> knot list (** A joint is the connection between two knots in a metapath. It is either {ul {- [jLine] for a straight line} {- [jCurve] for a spline curve} {- [jCurveNoInflex] to avoid inflexion points} {- [jTension f1 f2] to specify "tension" on the joint; [jCurve] uses a default tension of 1. Higher tension means less "wild" curves} {- [jControls p1 p2] to explicitely specify control points}} *) type joint = Path.joint val jLine : joint val jCurve : joint val jCurveNoInflex : joint val jTension : float -> float -> joint val jControls : Point.t -> Point.t -> joint (** The abstract type of metapaths *) type t type path = Path.t (** In all the functions below : - noDir is the default direction - jCurve is the default joint *) (** {2 Labelled metapath constructors} *) (** Build a knot from a pair of floats @param l an incoming direction @param r an outgoing direction @param scale a scaling factor applied to the floats *) val knot : ?l:direction -> ?r:direction -> ?scale:(float -> Num.t) -> float * float -> knot (** Build a knot from a Num.t pair; the optional arguments are as in {!knot} *) val knotn : ?l:direction -> ?r:direction -> Num.t * Num.t -> knot (** Build a metapath from a list of pairs of floats @param style the joint style used for all joints in the metapath @param cycle if given, the metapath is closed using the given style @param scale permits to scale the whole metapath *) val path : ?style:joint -> ?scale:(float -> Num.t) -> (float * float) list -> t (** Same as [metapath], but uses a [Num.t] list *) val pathn : ?style:joint -> (Num.t * Num.t) list -> t (** Same as [metapath], but uses a knot list *) val pathk : ?style:joint -> knot list -> t (** Same as [metapath] but uses a point list *) val pathp : ?style:joint -> Point.t list -> t (** Build a metapath from [n] knots and [n-1] joints *) val jointpathk : knot list -> joint list -> t (** Build a metapath from [n] points and [n-1] joints, with default directions *) val jointpathp : Point.t list -> joint list -> t val jointpathn : (Num.t * Num.t) list -> joint list -> t (** Build a metapath from [n] float_pairs and [n-1] joints, with default directions *) val jointpath : ?scale:(float -> Num.t) -> (float * float) list -> joint list -> t (** Close a metapath using direction [dir] and style [style] *) val cycle : ?dir:direction -> ?style:joint -> t -> path (** {2 Primitive metapath constructors} *) (** Add a knot at the end of a metapath *) val concat : ?style:joint -> t -> knot -> t (** Create a simple metapath with one knot *) val start : knot -> t (** Append a metapath to another using joint [style] *) val append : ?style:joint -> t -> t -> t (** {2 Predefined values} *) (** The default joint style ([JCurve]) *) val defaultjoint : joint (** {2 Conversions} *) (** Compute the control point of the path for a good looking result according to the constraint on the direction, tension, curve *) val to_path : t -> path (** Obtain a metapath from a path with exactly the same control point. p = of_metapath (of_path p) is true but not the opposite.*) val of_path : path -> t end (** Fixed Paths *) and Path : sig (** Paths are the objects used to describe lines, curves, and more generally almost everything that is drawn with Mlpost *) (** A [direction] is used to put constraints on paths: {ul {- [vec p] defines a direction by a point (interpreted as a vector)} {- [curl f] changes the curling factor of the extremity of a path; higher curling factor means flatter curves} {- [noDir] means no particular direction} } *) type direction val vec : Point.t -> direction val curl : float -> direction val noDir : direction (** A [knot] is the basic element of a path, and is simply a point with an incoming and outgoing direction constraint *) type knot (** Build a knot from a point; the optional arguments are the incoming directions. Warning they are going in the same direction. *) val knotp : ?l:direction -> ?r:direction -> Point.t -> knot val knotlist : (direction * Point.t * direction) list -> knot list (** A joint is the connection between two knots in a path. It is either {ul {- [jLine] for a straight line} {- [jCurve] for a spline curve} {- [jCurveNoInflex] to avoid inflexion points} {- [jTension f1 f2] to specify "tension" on the joint; [jCurve] uses a default tension of 1. Higher tension means less "wild" curves} {- [jControls p1 p2] to explicitely specify control points}} *) type joint val jLine : joint val jCurve : joint val jCurveNoInflex : joint val jTension : float -> float -> joint val jControls : Point.t -> Point.t -> joint (** The abstract type of paths *) type t (** In all the functions below : - noDir is the default direction - jCurve is the default joint *) (** {2 Labelled path constructors} *) (** Build a knot from a pair of floats @param l an incoming direction @param r an outgoing direction @param scale a scaling factor applied to the floats *) val knot : ?l:direction -> ?r:direction -> ?scale:(float -> Num.t) -> float * float -> knot (** Build a knot from a Num.t pair; the optional arguments are as in {!knot} *) val knotn : ?l:direction -> ?r:direction -> Num.t * Num.t -> knot (** Build a path from a list of pairs of floats @param style the joint style used for all joints in the path @param cycle if given, the path is closed using the given style @param scale permits to scale the whole path *) val path : ?style:joint -> ?cycle:joint -> ?scale:(float -> Num.t) -> (float * float) list -> t (** Same as [path], but uses a [Num.t] list *) val pathn : ?style:joint -> ?cycle:joint -> (Num.t * Num.t) list -> t (** Same as [path], but uses a knot list *) val pathk : ?style:joint -> ?cycle:joint -> knot list -> t (** Same as [path] but uses a point list *) val pathp : ?style:joint -> ?cycle:joint -> Point.t list -> t (** Build a path from [n] knots and [n-1] joints *) val jointpathk : knot list -> joint list -> t (** Build a path from [n] points and [n-1] joints, with default directions *) val jointpathp : Point.t list -> joint list -> t val jointpathn : (Num.t * Num.t) list -> joint list -> t (** Build a path from [n] float_pairs and [n-1] joints, with default directions *) val jointpath : ?scale:(float -> Num.t) -> (float * float) list -> joint list -> t (** Close a path using direction [dir] and style [style] *) val cycle : ?dir:direction -> ?style:joint -> t -> t (** {2 Primitive path constructors} *) (** Add a knot at the end of a path *) val concat : ?style:joint -> t -> knot -> t (** Create a simple path with one knot *) val start : knot -> t (** Append a path to another using joint [style] *) val append : ?style:joint -> t -> t -> t (** {2 More complex constructions on paths} *) (** Number of nodes in a path, minus one. *) val length : t -> Num.t (** [point f p] returns a certain point on the path [p]; [f] is given "in control points": [0.] means the first control point, [1.] the second and so on; intermediate values are accepted. *) val point : float -> t -> Point.t (** Same as [point] but for a [Num.t]. *) val pointn : Num.t -> t -> Point.t (** [direction f p] returns the direction of the tangent at [point f p]. *) val direction : float -> t -> Point.t (** Same as [direction] but for a [Num.t]. *) val directionn : Num.t -> t -> Point.t (** [subpath start end path] selects the subpath of [path] that lies between [start] and [end]. [start] and [end] are given in control points, as in {!point}. *) val subpath : float -> float -> t -> t (** Same as [subpathn] but using [Num.t]. *) val subpathn : Num.t -> Num.t -> t -> t (** Apply a transformation to a path *) val transform : Transform.t -> t -> t val scale : Num.t -> t -> t val rotate : float -> t -> t val shift : Point.t -> t -> t val yscale : Num.t -> t -> t val xscale : Num.t -> t -> t (** Shortcuts for transformations of Paths *) (** [cut_after p1 p2] cuts [p2] after the intersection with [p1]. To memorize the order of the arguments, you can read: "cut after [p1]" *) val cut_after : t -> t -> t (** Same as {!cut_after}, but cuts before *) val cut_before: t -> t -> t (** [strip n p] removes two segments of length [n] at each end of path [p] *) val strip : Num.t -> t -> t (** Build a cycle from a set of intersecting paths *) val build_cycle : t list -> t (** {2 Predefined values} *) (** The default joint style ([JCurve]) *) val defaultjoint : joint (** A full circle of radius 1 and centered on the origin *) val fullcircle : t (** The upper half of [fullcircle] *) val halfcircle : t (** The right half of [halfcircle] *) val quartercircle: t (** A full square of size 1 and centered on the origin *) val unitsquare: t (** {2 Conversions} *) type metapath = MetaPath.t (** Compute the control point of the path for a good looking result according to the constraint on the direction, tension, curve *) val of_metapath : metapath -> t (** Obtain a metapath from a path with exactly the same control point. p = of_metapath (of_path p) is true but not the opposite.*) val to_metapath : t -> metapath (** {2 Smart path } *) type orientation = | Up | Down | Left | Right | Upn of Num.t | Downn of Num.t | Leftn of Num.t | Rightn of Num.t val smart_path : ?style:joint -> orientation list -> Point.t -> Point.t -> t val draw : ?brush:Brush.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> t -> Command.t (** Draw a path @param brush the brush used to draw the path; the next argument redefined this one @param color the color of the path; default is black @param pen the pen used to draw the path; default is [Brush.Pen.default] @param dashed if given, the path is drawn using that dash_style. *) val fill : ?color:Color.t -> t -> Command.t (** Fill a contour given by a closed path @param color the color used to fill the area; default is black *) end (**/**) (** Pens: change the way lines are drawn in Mlpost *) and Pen : sig (** Pens are used to change the the way lines are drawn in Mlpost *) type t (** The abstract type of pens *) val transform : Transform.t -> t -> t (** Apply a transformation to pens *) val default : t (** The default pen; it corresponds to [Pen.scale (Num.bp 0.5) Pen.circle] *) val circle : t (** A circular pen of diameter 1 bp *) val square : t (** A pen in form of a square, of length 1 bp *) val from_path : Path.t -> t (** Construct a pen from a closed path *) val scale : Num.t -> t -> t val rotate : float -> t -> t val shift : Point.t -> t -> t val yscale : Num.t -> t -> t val xscale : Num.t -> t -> t (** Shortcuts for transformations of pens *) end (** Dash patterns *) and Dash : sig (** This module permits to define dash patterns, that are used to draw lines in different styles *) type t = Brush.Dash.t (** The abstract type of dash patterns *) val evenly : t (** The pattern composed of evenly spaced dashes *) val withdots : t (** The pattern composed of evenly spaced dots *) val scaled : float -> t -> t (** Scale a dash pattern *) val shifted : Point.t -> t -> t (** Shift a dash pattern *) type on_off val on : Num.t -> on_off val off : Num.t -> on_off val pattern : on_off list -> t (** This function, together with the type [on_off] permits to construct custom dash patterns, by giving a list of [on] / [off] constructors, with corresponding lengths *) end (**/**) (** Brushes : change the way lines are drawn in Mlpost *) and Brush : sig (** Pens: change the way lines look like in Mlpost *) module Pen : sig (** Pens are used to change the the way lines are drawn in Mlpost *) type t (**/**) = Pen.t (**/**) (** The abstract type of pens *) val transform : Transform.t -> t -> t (** Apply a transformation to pens *) val default : t (** The default pen; it corresponds to [Pen.scale (Num.bp 0.5) Pen.circle] *) val circle : t (** A circular pen of diameter 1 bp *) val square : t (** A pen in form of a square, of length 1 bp *) val from_path : Path.t -> t (** Construct a pen from a closed path *) val scale : Num.t -> t -> t val rotate : float -> t -> t val shift : Point.t -> t -> t val yscale : Num.t -> t -> t val xscale : Num.t -> t -> t (** Shortcuts for transformations of pens *) end (** Dash patterns *) module Dash : sig (** This module permits to define dash patterns, that are used to draw lines in different styles *) type t (** The abstract type of dash patterns *) val evenly : t (** The pattern composed of evenly spaced dashes *) val withdots : t (** The pattern composed of evenly spaced dots *) val scaled : Num.t -> t -> t (** Scale a dash pattern *) val shifted : Point.t -> t -> t (** Shift a dash pattern *) type on_off val on : Num.t -> on_off val off : Num.t -> on_off val pattern : on_off list -> t (** This function, together with the type [on_off] permits to construct custom dash patterns, by giving a list of [on] / [off] constructors, with corresponding lengths *) end type t val t : ?color:Color.t -> ?pen:Pen.t -> ?dash:Dash.t -> ?scale:Num.t -> ?brush:t -> unit -> t (** [t ~color ~pen ~dash ~scale ~brush] create a brush with color [color] if TODO *) val pen : t -> Pen.t option val dash : t -> Dash.t option val color : t -> Color.t option (** {2 Brushes with Predefined Colors} *) type brush_colored = ?pen:Pen.t -> ?dash:Dash.t -> ?scale:Num.t -> ?brush:t -> unit -> t (** {3 base colors} *) val white : brush_colored val black : brush_colored val red : brush_colored val blue : brush_colored val green : brush_colored val cyan : brush_colored val yellow : brush_colored val magenta : brush_colored (** {3 lighter colors} *) val lightred : brush_colored val lightblue : brush_colored val lightgreen : brush_colored val lightcyan : brush_colored val lightyellow : brush_colored val lightmagenta : brush_colored (** {3 grays} *) val gray : float -> brush_colored val lightgray : brush_colored val mediumgray : brush_colored val darkgray : brush_colored (** {3 additional colors} *) val orange : brush_colored val purple : brush_colored end (** Apply linear transformations to objects in Mlpost *) and Transform : sig (** Transformations are an important way to modify objects in Mlpost. Objects can be scaled, shifted, rotated, etc, and any combination of these transformations is possible. Currently, transformations can be applied to Pictures, Pens and Paths. *) type t' (** The abstract type of a single transformation *) val scaled : Num.t -> t' (** Scale an object by a constant factor. @param scale a scaling function to be applied to each float; see {!Num.t} for scaling functions for usual units. This makes only sense when the object to be transformed is given in "bp" units *) val rotated : float -> t' (** Rotate an object by an angle given in degrees *) val shifted : Point.t -> t' (** Shift an object with respect to a point *) val slanted : Num.t -> t' (** Slant an object: the point [(x,y)] becomes [(x+ay,y)], with slanting factor [a] *) val xscaled : Num.t -> t' (** Scale an object by a constant factor, but only in the [x] direction *) val yscaled : Num.t -> t' (** Scale an object by a constant factor, but only in the [y] direction *) val zscaled : Point.t -> t' (** Zscaled multiplies points of the object by the given point, using "complex" multiplication: [(x,y) * (a,b) = (ax - by, bx + ay)]; its effect is to rotate and scale so as to map [(1,0)] into [(a,b)] *) val reflect : Point.t -> Point.t -> t' (** Reflect an object with respect to the line that goes through the two given points *) val rotate_around : Point.t -> float -> t' (** Rotate an object by an angle given in degrees, around a given point *) type matrix = Ctypes.matrix val explicit : matrix -> t' type t = t' list (** A transformation is a list of single transformations *) val id : t (** The identity transformation *) end (** Functions to manipulate commands as if they were pictures *) and Picture : sig (** Pictures are a powerful way to reuse and modify parts of a figure *) type t = Command.t (** The abstract type of pictures *) val make : Command.t -> t (** Make a picture from a drawing command *) val tex : string -> t (** Take a string in Latex format and transform it into a picture *) val transform : Transform.t -> t -> t (** Apply a transformation to a picture *) val bbox : t -> Path.t (** Get the bounding box of a picture (with default padding, as in MetaPost) *) val corner_bbox : ?dx:Num.t -> ?dy:Num.t -> t -> Path.t (** Get the bounding box of a picture, according to its corners and supplied padding [dx] and [dy]. *) val center : Point.t -> t -> t (** Place a picture centered at some point *) val place_up_left : Point.t -> t -> t (** Place a picture with its upper left corner at some point *) val place_up_right : Point.t -> t -> t (** Place a picture with its upper right corner at some point *) val place_bot_left : Point.t -> t -> t (** Place a picture with its bottom left corner at some point *) val place_bot_right : Point.t -> t -> t (** Place a picture with its bottom right corner at some point *) val beside : t -> t -> t (** [beside p1 p2] returns a picture in which [p2] is placed right to [p1] *) val below : t -> t -> t (** [below p1 p2] returns a picture in which [p2] is placed below [p1] *) (** {2 Special points of the bounding box of a picture} *) val ctr : t -> Point.t (** @img ctr.png *) val north : t -> Point.t (** @img north.png *) val south : t -> Point.t (** @img south.png *) val west : t -> Point.t (** @img west.png *) val east : t -> Point.t (** @img east.png *) val north_west : t -> Point.t (** @img north_west.png *) val south_west : t -> Point.t (** @img south_west.png *) val north_east : t -> Point.t (** @img north_east.png *) val south_east : t -> Point.t (** @img south_east.png *) val corner : Command.position -> t -> Point.t (** {2 Special points of the bounding box of a picture (Deprecated)} *) (** These have been superseded by the preceding functions *) val ulcorner : t -> Point.t val llcorner : t -> Point.t val urcorner : t -> Point.t val lrcorner : t -> Point.t val clip : t -> Path.t -> t (** [clip pic path] limits [pic] to the cyclic path [path]; all elements outside of [path] are cut off. *) (** {2 Dimensions} *) val width : t -> Num.t val height : t -> Num.t (** Predefined Transformations *) val scale : Num.t -> t -> t val rotate : float -> t -> t val shift : Point.t -> t -> t val yscale : Num.t -> t -> t val xscale : Num.t -> t -> t val spin : float -> t -> t type escaped = [`Backslash|`Underscore] val escape_latex : escaped list -> string -> string val escape_all : string -> string val set_pos : Point.t -> t -> t (** alias of center *) end (** Basic drawing commands *) and Command : sig (** General Commands to build figures *) type t (** The abstract commands type *) (* val logo : figure (** The Mlpost logo. *) *) (** {2 Drawing Commands} *) val draw : ?brush:Brush.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> Path.t -> t (** Draw a path @param color the color of the path; default is black @param pen the pen used to draw the path; default is [Brush.Pen.default] @param dashed if given, the path is drawn using that dash_style. *) (* val draw_arrow : ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> Path.t -> t (** Draw a path with an arrow head; the optional arguments are the same as for {!draw} *) *) val fill : ?color:Color.t -> Path.t -> t (** Fill a contour given by a closed path @param color the color used to fill the area; default is black *) val draw_pic : Picture.t -> t (** draws a picture *) val externalimage : string -> [ `None | `Width of Num.t (** keep the proportion of the image *) | `Height of Num.t | `Inside of Num.t * Num.t (** must be inside a box of this height and width *) | `Exact of Num.t * Num.t] -> t (** insert an image given its filename - *EXPERIMENTAL* *) (** {2 Manipulating Commands} *) val nop : t (** A command that has no effect *) val append : t -> t -> t (** Append two commands to form a compound command *) val (++) : t -> t -> t (** Abbreviation for [append] *) val seq : t list -> t (** Group a list of commands to a single command *) val iter : int -> int -> (int -> t) -> t (** [iter m n f] builds a command that corresponds to the sequence of commands [f m; f (m+1); ... ; f(n)] *) val iterl : ('a -> t) -> 'a list -> t (** [iterl f l] builds a command that corresponds to the sequence of commands [f x1; f x2; ... ; f xn] for [l = [x1;x2;...;xn]] *) (** {2 Labels} *) type hposition = [ | `Center | `West | `East | `Left | `Right ] type vposition = [ `Center | `North | `South | `Top | `Bot | `Bottom ] type position = [ | hposition | vposition | `Northwest | `Northeast | `Southwest | `Southeast | `Upperleft | `Upperright | `Lowerleft | `Lowerright | `Topleft | `Topright | `Bottomleft | `Bottomright | `Upleft | `Upright | `Lowleft | `Lowright ] (** Positions - they are used at many places in Mlpost to indicate a direction or position. *) (** [label ~pos:`West pic p] puts picture [pic] at the left of the point [p] *) val label : ?pos:position -> Picture.t -> Point.t -> t (** Works like [label], but puts a dot at point [p] as well *) val dotlabel : ?pos:position -> Picture.t -> Point.t -> t end (** {2 Advanced graphical components} *) (** Rectangles, Circles, etc. *) module Shapes : sig (** Various Basic Geometric Shapes *) val round_rect : Num.t -> Num.t -> Num.t -> Num.t -> Path.t (** [round_rect w h rx ry] returns a rectangle of width [w] and height [h] with rounded corners. The rounded corners are arcs of an ellipse of radii [rx] and [ry]. [rx] (resp. [ry]) should be positive and smaller than [w/2] (resp. [h/2]). *) val rectangle : Num.t -> Num.t -> Path.t (** [rectangle w h] returns a rectangle of width [w] and height [h]. *) val ellipse : Num.t -> Num.t -> Path.t (** [ellipse rx ry] returns an ellipse of great axis [rx] and small axis [ry]. The ellipse is centered on the origin and aligned with the x axis. @param fill the color with which to fill the ellipse ; if no color is provided, it is not filled. @param stroke the color with which the ellipse's outline shall be drawn ; default is black. @param thickness the thickness of the pen used to draw the outline ; 1. is default *) val circle : Num.t -> Path.t val patatoid : Num.t -> Num.t -> Path.t (** See {!Box.patatoid}. *) val patatoid2 : Num.t -> Num.t -> Path.t (** See {!Box.patatoid2}. *) (* val arc_ellipse : ?fill:Color.t -> ?stroke:Color.t -> ?thickness:float -> ?close:bool -> Num.t -> Num.t -> float -> float -> Picture.t (** [arc_ellipse rx ry th1 th2] draws an arc of the ellipse of great axis [rx] and small axis [ry] starting at angle [th1] and ending at angle [th2] (in radians). The ellipse is centered on the origin and aligned with the x axis. @param fill the colod with which to fill the ellipse ; if no color is provided, it is not filled. @param stroke the color with which the ellipse's outline shall be drawn ; default is black. @param thickness the thickness of the pen used to draw the outline ; 1. is default @param close if true, the extremities of the arc are joined to the origin by straight lines, thus closing path. If [fill] is provided, then [close] will be true by default ; otherwise it is false. *) *) end (** A Box is a rectangle with some content and a (not necessarily rectangular) frame. Boxes can be placed, aligned and modified. *) module Box : sig (** Boxes *) (** The abstract type of boxes *) type t (** {2 Creating boxes} *) type style = | Rect | Circle | RoundRect | Patatoid | Patatoid2 | Ellipse | RoundBox | Custom of (Num.t -> Num.t -> Num.t * Num.t * Path.t) type 'a box_creator = ?dx:Num.t -> ?dy:Num.t -> ?name:string -> ?brush:Brush.t -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> 'a -> t (** All functions used to create boxes take the following optional parameters : [dx] (resp. [dy]) is the horizontal (resp. vertical) padding between the box border and its contents ; [name], if present, is associated with the box and can be used to retrieve it using [get] ; [stroke] is the color used to draw the outline of the box ; when equal to [None], the outline will not be drawn ; [pen] is the pen used to draw the box's outline, if absent [Brush.Pen.default] is used ; [fill], if present, is the color used to fill the box. *) val empty : ?width:Num.t -> ?height:Num.t -> ?style:style -> ?name:string -> ?brush:Brush.t -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> unit -> t (** the empty box *) val empty_from_box : ?style:style -> ?name:string -> ?brush:Brush.t -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> t -> t (** the empty box with the same position and dimension as the box *) val pic : ?style:style -> Picture.t box_creator (** [pic p] creates a new box containing the picture [p] *) val path : ?style:style -> Path.t box_creator (** [path p] creates a new box containing the path [p] *) val tex : ?style:style -> string box_creator (** [tex s] creates a new box containing the LaTeX string [s] @img tex.png *) val box : ?style:style -> t box_creator (** [box b] creates a new box containing the box [b] *) val circle : t box_creator (** [circle pic] creates a circle box containing the picture [pic]. Optional padding is given by arguments [dx] and [dy]; default is 2bp. @img circle.png *) val ellipse : t box_creator (** [ellipse pic] creates a elliptic box containing the picture [pic]. Optional padding is given by arguments [dx] and [dy]; default is 2bp @img ellipse.png *) val rect : t box_creator (** [rect pic] creates a rectangular box containing the picture [pic]. Optional padding is given by arguments [dx] and [dy]; default is 2bp. @img rect.png *) val round_rect : t box_creator (** [round_rect pic] creates a rectangular box containing the picture [pic], with rounded corners. Optional padding is given by [dx] and [dy]; default is 2bp @img round_rect.png *) val patatoid : t box_creator (** [patatoid pic] creates an undefined, vaguely rectangular box containing the picture [pic]. It may happen that the content overlaps with the box. @img patatoid.png *) val patatoid2 : t box_creator (** [patatoid2 pic] creates an undefined, vaguely rectangular box containing the picture [pic], which is guaranteed to be fully contained in the patatoid. *) val round_box : t box_creator (*** val round_rect_gen : ?dx:Num.t -> ?dy:Num.t -> ?rx:Num.t -> ?ry:Num.t -> Point.t -> Picture.t -> t (** [round_rect_gen p pic] creates a rectangular box of center [p] and of contents [pic], with rounded corners of radii [rx] and [ry]. Optional padding is given by [dx] and [dy] ; default is 2bp *) ***) (** Get the bounding path of a box *) val bpath : t -> Path.t (** Set the bounding path of a box *) val set_bpath : Path.t -> t -> t (** {2 Special points on a box} *) val ctr : t -> Point.t (** @img ctr.png *) val north : t -> Point.t (** @img north.png *) val south : t -> Point.t (** @img south.png *) val west : t -> Point.t (** @img west.png *) val east : t -> Point.t (** @img east.png *) val north_west : t -> Point.t (** @img north_west.png *) val south_west : t -> Point.t (** @img south_west.png *) val north_east : t -> Point.t (** @img north_east.png *) val south_east : t -> Point.t (** @img south_east.png *) type vposition = [ |Command.vposition | `Custom of t -> Num.t] type hposition = [ |Command.hposition | `Custom of t -> Num.t] type position = [ |Command.position | `Custom of t -> Point.t] val corner : position -> t -> Point.t val opposite_position : position -> position (** Return the opposite position of a position (west for east, southeast for northwest, center for center, ...). *) (** {2 Operators} *) val height : t -> Num.t (** return the height of the box @img height.png *) val width : t -> Num.t (** return the width of the box @img width.png *) val shift : Point.t -> t -> t (** [shift pt x] shifts the box [x] about the point [pt] @img shift.png *) val center : Point.t -> t -> t (** [center pt x] centers the box [x] at the point [pt] @img center.png *) val draw : ?debug:bool -> t -> Command.t (** Draws a box @param debug if set to to true, the bounding path and the center of the box are drawn as well, default is false *) val group : ?style:style -> t list box_creator (** [group bl] groups a list of boxes [bl] into a single box *) (** {2 Boxes alignment} *) val halign : ?pos:vposition -> Num.t -> t list -> t list (** [halign ~pos y l] vertically moves the boxes in [l] such that the vertical position given by [pos] is equal to [y]. The default value of [pos] is `Center, so by default this function moves each box such that the y coordinate of its center is [y]. The horizontal position of each box is unchanged. @img halign.png *) val valign : ?pos:hposition -> Num.t -> t list -> t list (** the vertical counterpart of [valign]. *) val hplace : ?padding:Num.t -> ?pos:position -> ?min_width:Num.t -> ?same_width:bool -> t list -> t list (** [hplace l] places the boxes of [l] horizontally, from left to right following the order of list elements, without changing their vertical position. @param min_width minimum width of all boxes; default is zero @param same_width if [true], all boxes are of same width, and at least of [min_width]; default is false @img hplace.png *) val vplace : ?padding:Num.t -> ?pos:position -> ?min_height:Num.t -> ?same_height:bool -> t list -> t list (** the vertical counterpart of [hplace] *) val hbox : ?padding:Num.t -> ?pos:position -> ?style:style -> ?min_width:Num.t -> ?same_width:bool -> t list box_creator (** places the given boxes horizontally, aligning them horizontally, and returns a box containing these boxes as sub-components. Leave the first box at its place. [hbox l] actually gives the same result as [group (hplace (halign l))]. @param padding horizontal padding used to separate the boxes; defaults to 0 @param pos used to determine the way boxes are aligned; defaults to [`Center] @img hbox.png *) val hbox_list : ?padding:Num.t -> ?pos:position -> ?min_width:Num.t -> ?same_width:bool -> t list -> t list (** as [hbox], but does not group the resulting boxes into a surrounding box; it returns the list of placed boxes instead. [hbox_list l] is equal to [hplace (halign l)]. *) val vbox : ?padding:Num.t -> ?pos:position -> ?style:style -> ?min_height:Num.t -> ?same_height:bool -> t list box_creator (** aligns the given boxes vertically and returns a box containing these boxes as sub-components. Leave the first box at its place. @param padding vertical padding used to separate the boxes @param pos used to determine the way boxes are aligned *) val vbox_list : ?padding:Num.t -> ?pos:position -> ?min_height:Num.t -> ?same_height:bool -> t list -> t list (* as vbox_list, but does not group the resulting boxes into a surrounding box *) val tabular : ?hpadding:Num.t -> ?vpadding:Num.t -> ?pos:Command.position -> ?style:style -> ?name:string -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> t array array -> t (** aligns the given boxes both vertically and horizontally and returns a box containing all these boxes (with rows as first sub-components, and then individual boxes as sub-components of each row). Columns (resp. rows) are separated by [hpadding] (resp. [vpadding]); both default to 0. Alignment within columns and rows is controlled using [pos]. The arrays for rows must have the same lengths; otherwise [Invalid_argument] is raised. *) val tabularl : ?hpadding:Num.t -> ?vpadding:Num.t -> ?pos:Command.position -> ?style:style -> ?name:string -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> t list list -> t (** similar to [tabular], but using lists instead of arrays *) val tabulari : ?hpadding:Num.t -> ?vpadding:Num.t -> ?pos:Command.position -> ?style:style -> ?name:string -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> int -> int -> (int -> int -> t) -> t (** similar to [tabular], but using a matrix defined with a function *) val hblock : ?padding:Num.t -> ?pos:Command.position -> ?name:string -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?min_width:Num.t -> ?same_width:bool -> t list -> t (** [hblock bl] aligns the boxes of [bl] horizontally and surround them with new rectangular boxes of the same height; all these new boxes are packed together into the returned box. @param min_width minimum width of all boxes; default is zero @param same_width if [true], all boxes are of same width, and at least of [min_width]; default is false*) val vblock : ?padding:Num.t -> ?pos:Command.position -> ?name:string -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?min_height:Num.t -> ?same_height:bool -> t list -> t (** similar to [hblock], with vertical alignment. @param min_height minimum height of all boxes; default is zero @param same_height if [true], all boxes are of same height, and at least of [min_height]; default is false*) val grid : ?hpadding:Num.t -> ?vpadding:Num.t -> ?pos:Command.position -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> t array array -> t (** Aligns the given boxes in a way that is similar to [hblock] and [vblock]: boxes are aligned in a grid where all cells have the same size. Each one of these cells is a box containing the original corresponding box. *) val gridl : ?hpadding:Num.t -> ?vpadding:Num.t -> ?pos:Command.position -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> t list list -> t (** similar to [grid], but using lists instead of arrays *) val gridi : ?hpadding:Num.t -> ?vpadding:Num.t -> ?pos:Command.position -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> int -> int -> (int -> int -> t) -> t (** similar to [gridi], but using a matrix defined with a function *) val place : position -> ?pos: position -> ?padding: Num.t -> t -> t -> t (** Place a box relatively to another box. [place `East a] is a function which places a box at the east of [a]. Thus, [place `East a b] returns a copy of [b] placed at the east of [a]. [place posa ~pos: posb ~padding a b] returns a new box [c] which is obtained by moving [b] to place the [posa] point of [a] on top of the [posb] point of [b], and then padding the result by [padding] in direction [posa]. Default value of [posb] is the opposite direction of [posa] wrt. the center (see {!opposite_position}). Default value of [padding] is zero. The padding argument multiplies a unit vector which goes from the center of [a] to the corner of [a] indicated by [posa]. This effectively places point [posa] of [a] at exactly [padding] units of point [posb] of [b], in direction [posa]. This also means that for diagonal directions, the actual direction will change according to the width / height ratio of [a]. *) val relative : t -> t -> t (** After using one of the previous function which give you a group [g] of box from multiple box (one of them must be [b]), you can use [relative b g] to translate [g] so that [b] inside [g] is at the same place than before. Indeed it's just {!sub} and a translation. {!relative} is really useful when someone make a slideshow from a succession of figures. *) (** {2 Sub-boxes accessors} *) val nth : int -> t -> t (** [nth i b] returns the [i]-th sub-box of [b]. The first sub-box has index 0. Raises [Invalid_argument] if there is no such sub-box. *) val get : string -> t -> t (** [get n b] returns the sub-box of [b] of name [n], if any, and raises [Invalid_argument] otherwise. The behavior is not specified if [b] contains several sub-boxes with name [n]. *) val sub : t -> t -> t (** [sub b1 b] returns the sub-box of [b] which has the same name as [b1], if any, and raises [Invalid_argument] otherwise. The behavior is not specified if [b] contains several sub-boxes with the name of [b1]. *) val elts : t -> t array (** [elts b] returns the sub-boxes of [b]; returns the empty array for the empty box or a box containing a picture. *) (** {2 Specials Points} *) val setp : string -> Point.t -> t -> t val getp : string -> t -> Point.t val getpx : string -> t -> Num.t val getpy : string -> t -> Num.t (** {2 Box properties} *) val get_fill : t -> Color.t option val set_fill : Color.t -> t -> t val get_stroke : t -> Color.t option val set_stroke : Color.t -> t -> t val clear_stroke : t -> t val get_name : t -> string option val set_name : string -> t -> t val get_pen : t -> Pen.t option val set_pen : Pen.t -> t -> t val set_height : Command.vposition -> Num.t -> t -> t val set_width : Command.hposition -> Num.t -> t -> t val get_dash : t -> Dash.t option val set_dash : Dash.t -> t -> t val clear_dash : t -> t val set_height2 : vposition -> Num.t -> vposition -> Num.t -> t -> t (** set_height2 `North y1 `South y2 b return the box b with its height and center chosen such as the ordinate of the top (because of `North) of the box is at y1 and the ordinate of its south is at y2*) val set_width2 : hposition -> Num.t -> hposition -> Num.t-> t -> t val set_size : Command.position -> width:Num.t -> height:Num.t -> t -> t val same_height : ?pos:vposition -> t list -> t list val same_width : ?pos:hposition -> t list -> t list val same_size : ?pos:position -> t list -> t list val henlarge : t list -> t list (** [henlarge l] set the west boundaries of the box in [l] to the westest boundaries of the box in [l]. same for the east boundaries *) val venlarge : t list -> t list (** same as {!henlarge} for vertical boundaries *) val set_post_draw : (t -> Command.t) -> t -> t val add_post_draw : (t -> Command.t) -> t -> t val clear_post_draw : t -> t val set_pre_draw : (t -> Command.t) -> t -> t val clear_pre_draw : t -> t (** {2 Misc.} *) val shadow : t -> t val cpath : ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> t -> t -> Path.t (** the path that connects 2 boxes and stops at the box boundaries *) val cpath_left : ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> t -> Point.t -> Path.t (** the path that connects a box and a point and stops at the box boundaries *) val cpath_right : ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> Point.t -> t -> Path.t (** the path that connects a box and a point and stops at the box boundaries *) val transform : Transform.t -> t -> t val scale : Num.t -> t -> t val rotate : float -> t -> t val shift : Point.t -> t -> t val yscale : Num.t -> t -> t val xscale : Num.t -> t -> t (** {2 Boxlike : An argument for functor of object that are similar to box} *) val set_pos : Point.t -> t -> t (** same as center *) end (** Tree-like, triangular shapes, with a root on top and an horizontal bottom line. *) module Triangle : sig type t = Box.t (** A triangular shape is a box. In the following, we simply call it a "triangle". *) val create: ?brush:Brush.t -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> ?left:float -> ?right:float -> ?width:Num.t -> depth:Num.t -> unit -> Box.t (** [create depth] creates a triangular shape of depth [depth]. The width is equal to [depth], unless specified using [width]. [left] and [right] control the horizontal position of the root; they default to [0.5] i.e. the root is centered. Negative values for [left] and [right] are allowed. *) val pic: ?brush:Brush.t -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> ?dx:float -> ?dy:float -> Picture.t -> t (** builds a triangle surrounding a picture *) val tex: ?brush:Brush.t -> ?stroke:Color.t option -> ?pen:Pen.t -> ?dash:Dash.t -> ?fill:Color.t -> ?dx:float -> ?dy:float -> string -> t (** builds a triangle surrounding a LaTeX label *) val root: t -> Point.t val bottom_left: t -> Point.t val bottom_right: t -> Point.t (** Special points in a triangle. *) val draw: ?debug:bool -> t -> Command.t val root_label: ?pos:Command.position -> Picture.t -> t -> t val tex_root_label: ?pos:Command.position -> string -> t -> t (** Attach a label to the root. *) val x_depth: ?x:float -> ?depth:float -> t -> Point.t (** a point inside a triangle is denoted using two coordinates [x] and [depth]. Coordinate [x] controls horizontal placement, with 0.0 for left and 1.0 for right (negative values are allowed). Coordinate [depth] controls vertical placement, with 0.0 for root and 1.0 for bottom line (negative values are allowed). [x] defaults to [0.5] (centered) and [depth] defaults to [1.0] (bottom). *) val label: ?x:float -> ?depth:float -> ?pos:Command.position -> Picture.t -> t -> t val tex_label: ?x:float -> ?depth:float -> ?pos:Command.position -> string -> t -> t (** Attach a label to the point (x, depth). Coordinate [depth] defaults to 0.7, so that label is likely to fit nicely in the triangle (otherwise, you may consider using functions [pic] and [tex] above). *) val anchor: ?x:float -> ?depth:float -> t -> t -> t (** [anchor t2 t1] moves triangle [t1] at position (x, depth) in triangle [t2] *) val pose: ?x:float -> ?depth:float -> t -> t -> t (** [pose t2 t1] moves triangle [t1] so that its south point is at position (x, depth) in triangle [t2] *) val pose_left: ?x:float -> ?depth:float -> t -> t -> t val pose_right: ?x:float -> ?depth:float -> t -> t -> t (** similarly, using [bottom_left] and [bottom_right] instead of south point *) end (** Draw arrows and build new forms of arrows. *) module Arrow : sig (** Draw simple or complex arrows. *) (** To draw an arrow, choose your arrow [kind], then call the [draw] function (giving the path that the arrow will follow) or the [draw2] function (giving the starting and ending points of the arrow). If your favorite arrow [kind] does not exist, use the tools from this module to build your own! *) type kind (** The abstract type for arrow kinds. *) (** {2 Drawing Arrows} *) (** If you need to place a label which is not TeX but any picture, if you need to place it at a symbolic position on the path, or if you need to place more than one label, you cannot do it directly using the [draw] commands. First draw the arrow, then use functions such as {!Command.label}. *) val simple : ?color:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?dashed:Dash.t -> Path.t -> Command.t (** Draw a simple arrow following the given path. @param color the color of the arrow @param pen the pen to use to draw the body of the arrow @param dashed the dash pattern to use to draw the body of the arrow *) val draw: ?kind: kind -> ?tex: string -> ?pos: float -> ?anchor: Command.position -> Path.t -> Command.t (** Draw an arrow following the given path. @param kind the kind of arrow (default is {!triangle_full}) @param tex add a LaTeX label @param pos label position on the path @param anchor label anchor *) type ('a,'b) arrow_from_to = ?kind: kind -> ?tex: string -> ?pos: float -> ?anchor: Command.position -> ?style:Path.joint -> ?outd: Path.direction -> ?ind: Path.direction -> ?sep:Num.t -> 'a -> 'b -> Command.t (** {ul {- [kind] the kind of arrow (default is {!triangle_full})} {- [tex] add a LaTeX label} {- [pos] label position on the path} {- [anchor] label anchor} {- [outd] the outgoing direction, at the beginning of the arrow} {- [ind] the ingoing direction, at the end of the arrow} {- [sep] add a little separation of the given distance} } *) val point_to_point: (Point.t,Point.t) arrow_from_to (** Use [point_to_point a b] to draw an arrow from [a] to [b]. *) val box_to_box: (Box.t,Box.t) arrow_from_to (** Use [box_to_box] to draw an arrow from [a] to [b], stopping at the box boundaries. The arguments are the same as those of [point_to_point]. *) val point_to_box: (Point.t,Box.t) arrow_from_to (** Use [point_to_box] to draw an arrow from [a] to [b], stopping at the box boundaries. The arguments are the same as those of [point_to_point]. *) val box_to_point: (Box.t,Point.t) arrow_from_to (** Use [box_to_point] to draw an arrow from [a] to [b], stopping at the box boundaries. The arguments are the same as those of [point_to_point]. *) (** {2 Built-in Kinds} *) val classic: kind (** A simple arrow with one line and two straight lines for the head. *) val triangle: kind (** A simple arrow with a triangular head. Same as [classic] but with an extra line and some clipping. *) val triangle_full: kind (** A simple arrow with a triangular head filled with black. *) val implies: kind (** An arrow made of two parallel lines and a classic head. *) val iff: kind (** An arrow made of two parallel lines, a classic head and a classic foot. *) (** {2 Heads} *) type head_description (** The type of head descriptions (see [make_head] and [head] below). *) val make_head: ?cut: Path.t -> Command.t -> head_description (** Head description constructor. The command parameter is used to draw the head. @param cut a path that can be used to cut the arrow body lines (only used by heads and feet, not by belts) *) type head = Point.t -> Point.t -> head_description (** If [h] is a head, [h p d] returns a head description used to draw the head at point [p] with direction [d]. Direction [d] is normalized before being given to the function. *) val head_classic : ?color:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?angle:float -> ?size:Num.t -> head (** A simple head with two straight lines. @param color the color of the head; default is black @param pen the pen used to draw the head; default is [Brush.Pen.default] @param dashed if given, the head is drawn using that dash_style @param angle the angle between the two lines in degrees, default is 60 degrees @param size the length of the two lines, default is 4bp *) val head_triangle : ?color:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?angle:float -> ?size:Num.t -> head (** Same as [head_classic] except that the two lines are joined together to form a triangle. *) val head_triangle_full : ?color:Color.t -> ?angle:float -> ?size:Num.t -> head (** Same as [head_triangle] except that the triangle is not drawn (hence the absence of pen properties) but is filled with the given [color]. *) (** {2 Building Your Own Kinds} *) (** Start from the empty kind [empty] and add features to it using [add_line], [add_head], ... *) val empty: kind (** The empty kind with no line nor head. *) val add_line: ?brush:Brush.t -> ?dashed: Dash.t -> ?color: Color.t -> ?pen: Pen.t -> ?from_point: float -> ?to_point: float -> ?dist: Num.t -> kind -> kind (** Add a line to a body. The line will be parallel to the path used to draw the arrow. @param dashed the dash style used to draw the line (default is plain) @param color the color of the line (default is black) @param pen the pen used to draw the line (default is [Brush.Pen.default]) @param from_point from [0.] (foot of the arrow) to [1.] (head of the arrow), the line will start from this point @param to_point from [0.] (foot of the arrow) to [1.] (head of the arrow), the line will end at this point @param dist the distance between the path of the arrow and this line (positive values are on the right of the arrows) *) val add_head: ?head: head -> kind -> kind (** Add a head at the end of the arrow. @param head the kind of head to add (default is {!head_classic}) *) val add_foot: ?head: head -> kind -> kind (** Add a foot (an inverted head) at the beginning of the arrow. @param head the kind of head to add (default is {!head_classic}) *) val add_belt: ?clip: bool -> ?rev: bool -> ?point: float -> ?head: head -> kind -> kind (** Add an arrow head at any point of an arrow. @param clip if [true], the arrow lines will be clipped after the belt (or before if the [rev] is [true]) (default is [false]) @param rev if [true], the head will be drawn in the opposite direction (default is [false]) @param point the point where to draw the arrow ([0.] for the beginning, and [1.] for the end, or any number in-between) (default is [0.5]) @param head the kind of head to add (default is {!head_classic}) *) (** {2 Miscellaneous} *) (** Warning: the following functions might be either deleted, modified and / or moved somewhere else. Don't use them if you need some backward compatibility. *) val draw_thick : ?style:Path.joint -> ?boxed:bool -> ?line_color:Color.t -> ?fill_color:Color.t -> ?outd:Path.direction -> ?ind:Path.direction -> ?width:Num.t -> ?head_length:Num.t -> ?head_width:Num.t -> Point.t -> Point.t -> Command.t (** Draw a thick arrow. *) end (** {2 Helpers and Extensions} *) (** A few helper functions *) module Helpers : sig val dotlabels : ?pos:Command.position -> string list -> Point.t list -> Command.t val draw_simple_arrow : ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> Point.t -> Point.t -> Command.t val draw_label_arrow : ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?pos:Command.position -> ?sep:Num.t -> Picture.t -> Point.t -> Point.t -> Command.t val draw_labelbox_arrow : ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?pos:Command.position -> ?sep:Num.t -> Box.t -> Point.t -> Point.t -> Command.t val box_arrow : ?within:Box.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> Box.t -> Box.t -> Command.t (** Draw an arrow between two boxes. The options [pen], [dashed], [color] change the drawing of the arrow. [outd] and [ind] specify the outgoing and ingoing direction. [sep] specifies the distance of the arrow ends to both boxes. If [within] is set, the boxes will be searched within the box [within]. *) val box_line : ?within:Box.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> Box.t -> Box.t -> Command.t val box_label_arrow : ?within:Box.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> ?pos:Command.position -> Picture.t -> Box.t -> Box.t -> Command.t val box_label_line : ?within:Box.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> ?pos:Command.position -> Picture.t -> Box.t -> Box.t -> Command.t val box_labelbox_arrow : ?within:Box.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> ?sep:Num.t -> ?pos:Command.position -> Box.t -> Box.t -> Box.t -> Command.t val box_pointer_arrow : ?within:Box.t -> ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?style:Path.joint -> ?outd:Path.direction -> ?ind:Path.direction -> Box.t -> Box.t -> Command.t (*** val hboxjoin : ?color:Color.t -> ?pen:Pen.t -> ?dashed:Dash.t -> ?dx:Num.t -> ?dy:Num.t -> ?pos:Command.position -> ?spacing:Num.t -> Picture.t list -> Command.t ***) end (** Create and draw trees *) module Tree : sig (** This module provides high-level means for creating and drawing Trees *) type t (** The type of trees *) (** The style of arrows between nodes *) type arrow_style = Directed (** edges are directed and an arrow is drawn at the end of an edge *) | Undirected (** edges are undirected and no arrow is drawn *) (** There are several styles available for edges *) type edge_style = Straight (** edges are straight lines between nodes *) | Curve (** edges are curved lines between nodes *) | Square (** edges are straight lines and branch out from the sides of nodes *) | HalfSquare (** edges are straight lines and branch out from below nodes *) (** {2 Creation} *) val leaf : Box.t -> t (** [leaf b] creates a leaf with Box [b]. *) val node : ?ls:Num.t -> ?cs:Num.t -> ?arrow_style:arrow_style -> ?edge_style:edge_style -> ?stroke:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?sep:Num.t -> Box.t -> t list -> t (** [node label children] creates a node with label [label] and a list of children [children]. Default arrow_style is [Directed]. Default edge_style is [Straight]. - [ls] (level sep): vertical distance between levels. The default value is 1.0. A negative value draws the tree upward. - [cs] (children sep): horizontal distance between siblings. The default value is 0.2. Optional arguments are the same as in [leaf]. *) val nodel : ?ls:Num.t -> ?cs:Num.t -> ?arrow_style:arrow_style -> ?edge_style:edge_style -> ?stroke:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?sep:Num.t -> Box.t -> (t * (Command.position * Picture.t)) list -> t (** Similar to [node] but with labels on edges. Labels are taken into account only when [edge_style] is [Straight]. *) val bin : ?ls:Num.t -> ?cs:Num.t -> ?arrow_style:arrow_style -> ?edge_style:edge_style -> ?stroke:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?sep:Num.t -> Box.t -> t -> t -> t (** [bin label l r] creates a binary node with label [label] and children [l] and [r]. Optional arguments are the same as in [leaf]. *) val to_box : t -> Box.t val draw : ?debug:bool -> t -> Command.t module Simple : sig type t val leaf : Box.t -> t val node : ?ls:Num.t -> ?cs:Num.t -> ?arrow_style:arrow_style -> ?edge_style:edge_style -> ?stroke:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?sep:Num.t -> ?valign:Command.position -> ?halign:Command.position -> Box.t -> t list -> t (** a simple tree placement algorithm: align all subtrees horizontally , and place the parent node above. Default arrow_style is [Directed]. Default edge_style is [Straight]. @param ls (level sep): vertical distance between levels. The default value is 1.0. A negative value draws the tree upward. @param cs (children sep): horizontal distance between siblings. The default value is 0.2. @param halign change alignment of children (default: [`Top]) @param valign change alignment of parent node wrt. children (default: [`Children]) *) val bin : ?ls:Num.t -> ?cs:Num.t -> ?arrow_style:arrow_style -> ?edge_style:edge_style -> ?stroke:Color.t -> ?brush:Brush.t -> ?pen:Pen.t -> ?sep:Num.t -> Box.t -> t -> t -> t (* [bin t1 t2] is the same as [node [t1;t2] ] *) val to_box : t -> Box.t val draw : ?debug:bool -> t -> Command.t end end (** EXPERIMENTAL: A new way of placing trees. *) module Tree_adv : sig (** This module provides even more high-level means for placing trees. *) type 'a t = Node of 'a * 'a t list (** The type of polymorphic trees *) (** {2 Functions for placement} *) module Place (X : Signature.Boxlike) : sig val gen_place : place:(Box.t t -> Box.t) -> X.t t -> X.t t (** This is a generic function for placing trees, provided that the user can give us the following functions: @param place a function which knows how to place a tree of boxes - it should return a box where all the boxes of the input tree appear. *) val place : ?ls:Num.t -> ?cs:Num.t -> ?valign:Box.position -> ?halign:Box.position -> X.t t -> X.t t (** This is an instance of [gen_place] using the tree drawing algorithm from the module {!Tree}. *) end val gen_draw_arrows : 'c -> style:(Point.t -> Point.t -> 'c) -> corner:(Box.position -> 'a -> Point.t) -> 'a t -> 'c t (** draws arrows from a node to its children with a given style *) val draw : ('a -> Box.t) -> 'a t -> Command.t (** Draws a tree that has already been placed when one knows how to draw its elements. *) (** {2 Useful functions} *) val map : ('a -> 'b) -> 'a t -> 'b t (** apply a function everywhere in the tree *) val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t (** [map2 f] takes two trees of identical structure and applies the function [f] to every pair of nodes. Raise [Invalid_argument] if the trees do not have the same structure. *) val combine : 'a t -> 'b t -> ('a * 'b) t (** Transform a pair of trees into a tree of pairs. Raise [Invalid_argument] if the trees do not have the same structure. *) val split : ('a * 'b) t -> 'a t * 'b t (** Transform a tree of pairs into a pair of trees. *) val root_map : ('a option -> 'a -> 'b) -> 'a t -> 'b t (** [root_map f t] calls [f (Some father) node] for each node of [t] and its father. It calls [f None root], where [root] is the root of the once, once at the beginning. A tree having the same structure is built with the results. *) val map_children : ('a -> 'a list -> 'b) -> 'a t -> 'b t (** [map_children f t] calls [f node children] for each node of [t] and its children. A tree having the same structure is built with the results *) val fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a (** Traverse the tree in a bottom-up, left-to-right order *) val fold_child : ('a -> 'b -> 'b -> 'a) -> 'a -> 'b t -> 'a (** Traverse the pairs of parent-child in the tree in a bottom-up, left-to-right order *) val filter : ('a -> bool) -> 'a t -> 'a t (** filter f t If for a node n of t f n is false then it doesn't appear in the result as well as its descendants. If f is false for the root node, invalid_argument is raised *) val filter_option : ('a -> 'b option) -> 'a t -> 'b t (** Suppress a subtree depending on a condition on the node *) val wrap_corner_box : ('a -> Box.t) -> ( corner : (Box.position -> 'a -> Point.t) -> 'c) -> 'c (** [wrap_corner_box give_box f] returns [f] where its argument corner has been set *) (** Tools for overlay aware trees *) module Overlays : sig (** This module provides a type to associate an interval of time to a value, to control its visibility *) type interval = | Bet of int * int (** \[|a,b|\] *) | Bef of int (** \]|-oo,a|\] *) | Aft of int (** \[|a,+oo|\[ *) | Nev (** emptyset *) | Alw (** N *) (** This type describes an interval of discrete points of time *) val in_interval : int -> interval -> bool (** test if an integer is in an interval *) val min_interval : int -> interval -> int (** The minimum between the integer argument and the beginning of the interval; returns the integer argument in the cases [Nev] and [Alw] *) val max_interval : int -> interval -> int (** The dual of [min_interval] *) val min_tree : ('a -> interval) -> 'a t -> int (** The first moment of the tree to appear, not considering [Nev] and [Alw] *) val max_tree : ('a -> interval) -> 'a t -> int (** The last moment of the tree to appear, not considering [Nev] and [Alw] *) type 'a spec = (interval * 'a) list (** A spec is a list of objects associated with a visibility interval *) val assoq : int -> 'a spec -> 'a (** returns the first element which is visible in the specification; raises [Not_found] if no element is visible *) val max : ('a -> Num.t) -> ('b * 'a) list -> Num.t (** given a function to compute a numeric from an ['a], and a list of objects [('b,'a)], return the maximal numeric from that list; intended to be used with width and height functions for objects and with a ['a spec list] *) val set_pos : (Point.t -> 'a -> 'b) -> Point.t -> 'a spec -> 'b spec (** Given a function to move objects of type ['a], return a function to move functions of type ['a spec] *) end module Overlays_Boxlike (X : Signature.Boxlike): Signature.Boxlike with type t = X.t Overlays.spec end (** Create simple diagrams by placing objects in a table. Deprecated. *) module Diag : sig (** Diagrams. *) (** This module permits to create diagrams in a very simple and yet quite flexible fashion. It permits to specify content, form and color of nodes as well as color, form and labels of arrows between nodes. Nodes have to be placed by hand, though *) (** {2 Creation} *) type node (** The abstract type of nodes *) type node_style = Box.t -> Box.t (** The type for node styles; It corresponds to the type of the box creation functions in the {!Box} module *) val node : ?style:node_style -> ?fill:Color.t -> ?boxed:bool -> float -> float -> Box.t -> node (** Construct a node at a given position with a given content in Latex format and a box style *) type t (** The abstract type of diagrams *) val create : node list -> t (** Create a diagram that consists of the given nodes *) type dir = Up | Down | Left | Right | Angle of float val arrow : t -> ?lab:string -> ?line_width:Num.t -> ?boxed:bool -> ?line_color:Color.t -> ?fill_color:Color.t -> ?pos:Command.position -> ?head:bool -> ?dashed:Dash.t -> ?outd:dir -> ?ind:dir -> node -> node -> unit (** [arrow d n1 n2] adds an arrow between n1 and n2 in the diagram d, by side effect. @param lab The label of the arrow, in Latex format @param pos The position of the label, relative to the arrow @param line_width Draws a thick arrow of that width, if present (experimental) @param head If true, the arrow has a head. Otherwise, it's just a line. @param outd The outgoing direction of the arrow @param ind The ingoing direction of the arrow *) (** {2 Drawing} *) val draw : ?scale:(float -> Num.t) -> ?style:node_style -> ?boxed:bool -> ?fill:Color.t -> ?stroke:Color.t -> ?pen:Pen.t -> t -> Command.t (** Draws the diagram. @param scale The distance between nodes; default is 40 bp @param style The style of nodes: circular or rectangular (default is circular) @param boxed The border is drawn if set (default is true) @param fill The color to fill nodes @param stroke The color to draw arrows @param pen The pen used for arrows *) end (** A simple and limited way of plotting functions from int to int. *) module Plot : sig (** Plots. *) (** This module helps drawing grids and plotting functions. *) type skeleton (** The abstract skeleton for grids, axes and functions *) val mk_skeleton : int -> int -> Num.t -> Num.t -> skeleton (** [mk_skeleton w h dx dy] builds a skeleton of width [w] and height [h], each cell being [dx] units wide and [dy] units high. *) type labels = int -> Num.t -> Picture.t option type ticks = (Num.t * Pen.t) option type drawing = Stepwise | Normal val draw_grid : ?hdash:(int -> Dash.t) -> ?vdash:(int -> Dash.t) -> ?hpen:(int -> Pen.t) -> ?vpen:(int -> Pen.t) -> ?color:Color.t -> skeleton -> Command.t val draw_axes : ?hpen:Pen.t -> ?vpen:Pen.t -> ?hlabel:labels -> ?vlabel:labels -> ?ticks:ticks -> ?closed:bool -> ?hcaption:Picture.t -> ?vcaption:Picture.t -> skeleton -> Command.t val draw_simple_axes : ?hpen:Pen.t -> ?vpen:Pen.t -> string -> string -> skeleton -> Command.t val draw_func : ?pen:Pen.t -> ?drawing:drawing -> ?style:Path.joint -> ?dashed:Dash.t -> ?color:Color.t -> ?label:(Picture.t * Command.position * int) -> ?from_x:int -> ?to_x:int -> (int -> float) -> skeleton -> Command.t end (** A simple and limited way of plotting functions from float to float. *) module Real_plot : sig type 'a curve (** 'a store the information about : - the way the curve is drawn (style and color) - the label used in the legend *) val curve : (float -> float) -> 'a -> 'a curve (** create a curve from a function and some information of drawing *) val curve_opt : (float -> float option) -> 'a -> 'a curve (** create a curve from a function and some information of drawing. If the function return None the function is not defined on this value *) val curve_l : (float -> float option) list -> 'a -> 'a curve (** create a curve from multiple function and some information of drawing. The different functions symbolize different part of the curve which mustn't be connected *) val draw : ?logarithmic : bool -> (* use a logarithmic scale for ordinate *) ?curve_brush : ('a -> Brush.t) -> (* how to draw a curve *) ?label : ('a -> string) -> (* return the label to use in the legend. If no function is given the legend is not drawn *) ?ymin : float -> ?ymax : float -> xmin : float -> xmax : float -> pitch : float -> width : Num.t -> height : Num.t -> 'a curve list -> Command.t (* Draw a graph. If concrete is supported (Concrete.supported) the label of ticks on the axes will not overlap *) end (** Draw Bar diagrams (Histograms). *) module Hist : sig (** Histograms. *) (** This module draws histograms. *) type 'a labels = Values | User of 'a list val simple : ?width:Num.t -> ?height:Num.t -> ?padding:Num.t -> ?fill:Color.t list -> ?perspective: bool -> ?hcaption:Picture.t -> ?vcaption:Picture.t -> ?histlabel:Command.vposition * Picture.t labels -> ?vlabel:Plot.labels -> ?hlabel:Picture.t list -> float list -> Command.t (** [simple l] draws an histogram from a list [l] of floating-point values. @param width Total width of the histogram (default: 100 bp) @param height Total height for the histogram (default: 200 bp) @param fill The colors used to draw the successive blocks; it is used circularly @param padding Horizontal space between two blocks @param hcaption See module Plot @param vcaption See module Plot @param hlabel Labels for each block @param vlabel See module Plot @param histlabel Add a label to each block; the first component controls the placement of the label; the second component, of type [insideBox], controls the label itself, which is either the numerical value of the block (i.e. the float) or a user picture *) val compare : ?width:Num.t -> ?height:Num.t -> ?padding:Num.t -> ?fill:Color.t list -> ?perspective: bool -> ?hcaption:Picture.t -> ?vcaption:Picture.t -> ?histlabel:Command.vposition * Picture.t list labels -> ?vlabel:Plot.labels -> ?hlabel:Picture.t list -> float list list -> Command.t (** [compare l] draws a comparative histogram from a list [l] of floating-point lists. For optional arguments, see function [simple] above. *) val stack : ?width:Num.t -> ?height:Num.t -> ?padding:Num.t -> ?fill:Color.t list -> ?perspective: bool -> ?hcaption:Picture.t -> ?vcaption:Picture.t -> ?histlabel:Command.vposition * Picture.t list labels -> ?vlabel:Plot.labels -> ?hlabel:Picture.t list -> float list list -> Command.t (** [compare l] draws a stacked histogram from a list [l] of floating-point lists. For optional arguments, see function [simple] above. *) end (** Radar diagrams. *) module Radar : sig (** This module draws radar diagrams.*) val stack : ?radius:Num.t -> ?color:Color.t list -> ?pen:Pen.t -> ?style:Dash.t list -> ?ticks:float -> ?label:string list -> ?scale:float list -> float list list -> Picture.t (** [stack l] builds a picture from a list [l] of floating-point lists. The radars are all drawn on the same picture. Each sublist represents one radar datas. All sublists must have the same length. @param radius The radius of the whole picture @param pen The pen used to draw the radars @param color The colors used to draw each radar; it is used circularly @param style The dash-styles used to draw each radar; it is used circularly @param ticks The interval between each ticks along the axes (relative to the values) @param scale The size of every axe, relative to the values; when not specified, the maximal value along each axe is chosen *) val compare : ?radius:Num.t -> ?color:Color.t list -> ?fill:bool -> ?pen:Pen.t -> ?style:Dash.t list -> ?ticks:float -> ?label:string list -> ?scale:float list -> float list list -> Picture.t list (** [stack l] builds a list of pictures from a list [l] of floating-point lists. Each picture represents one radar, and all picture have the same size. Each sublist represents one radar datas, and all sublists must have the same length. For most optional arguments, see function [stack] above. @param fill Fill the radar with its color. *) end (** Build a legend for diagrams. *) module Legend : sig val legend : ?ensstroke:Color.t -> ?colstroke:Color.t -> ?fill:Color.t -> (Color.t * string) list -> Picture.t end (** {2 Metapost generation} *) (* Misc does not appear in the documentation *) (**/**) module Misc : sig val print_option : string -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a option -> unit val print_list : ('a -> unit -> 'b) -> ('a -> 'c -> unit) -> 'a -> 'c list -> unit val space : Format.formatter -> unit -> unit val comma : Format.formatter -> unit -> unit val fold_from_to : ('a -> int -> 'a) -> 'a -> int -> int -> 'a (** [fold_from_to f acc i j] is equivalent to [List.fold_left f acc [i; i +1; .. j] ], where i <= j *) val call_cmd : ?inv:bool -> ?outv:bool -> ?verbose:bool -> string -> int end (**/**) (** Functions to generate Metapost files *) module Metapost : sig (**/**) (** This code is deprecated. *) val set_filename_prefix : string -> unit (** Add to the filename given to the emit function this prefix. This function is here just for convenience *) (* I believe these functions were only used internally. Commented. *) (* val generate_mp : string -> ?prelude:string -> ?eps:bool -> (int * Command.t) list -> unit *) val generate : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> (string * Command.t) list -> unit val emit : string -> Command.t -> unit val dump : ?prelude:string -> ?pdf:bool -> ?eps:bool -> ?verbose:bool -> ?clean:bool -> string -> unit (** [dump ?prelude ?pdf f] builds a Metapost file [f.mp] for all figures, then runs Metapost on it, and renames figure files according to the names specified to [emit]. The file suffix is [.mps] if [pdf] is set, and [.1] otherwise. *) type job = string * Command.t type jobs = job list (** Generate files of corresponding type, using the argument of type [jobs], and return information about the created files *) (* (* FIXME export this function, too *) val mp : string -> ?prelude:string -> jobs -> File.t * string Misc.IntMap.t *) val mps : ?prelude:string -> ?verbose:bool -> string -> jobs -> File.t list val pdf : ?prelude:string -> ?verbose:bool -> string -> jobs -> File.t list val png : ?prelude:string -> ?verbose:bool -> string -> jobs -> File.t list (** Same as above, but use a temporary directory *) (* (* FIXME export this function, too *) val temp_mp : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> jobs -> File.t * string Misc.IntMap.t *) val temp_mps : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> jobs -> File.t list val temp_pdf : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> jobs -> File.t list val temp_png : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> jobs -> File.t list (** Same as above, but use a temporary directory and take jobs from the job queue *) val dump_mp : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val dump_mps : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val dump_png : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val dump_pdf : ?prelude:string -> ?verbose:bool -> ?clean:bool -> string -> unit val read_prelude_from_tex_file : string -> string (** read the prelude from a tex file, until the end of file or the text "\begin\{document\}" if it is outside a comment *) val dump_tex : ?prelude:string -> string -> unit (** [dump_tex ?prelude f] builds a LaTeX file [f.tex] for all the figures, using LaTeX prelude [prelude] if given. *) val slideshow : Command.t list -> int -> (int * Command.t) list (** takes a list of figures and returns a list of figures of exactly the same size (the size of the biggest figure). Shared objects are hopefully placed at the same absolute location across figures. The resulting figures are numbered with consecutive increasing integers, starting with the given value. *) val emit_slideshow : string -> Command.t list -> unit (** emit the list of figures as a slideshow, using the [slideshow] function.*) val dumpable : unit -> unit val depend : string -> unit (**/**) end (** Compute concrete values of numerics, points and paths; not always available *) module Concrete : sig val supported : bool (** The module of concrete points *) module CPoint : sig type t = Ctypes.point val add : t -> t -> t val sub : t -> t -> t val opp : t -> t val mult : float -> t -> t val div : t -> float -> t module Infix : sig val (+/) : t -> t -> t (** alias for {!Concrete.CPoint.add} *) val (-/) : t -> t -> t (** alias for {!Concrete.CPoint.sub} *) val ( */) : float -> t -> t (** alias for {!Concrete.CPoint.mult} *) val ( //) : t -> float -> t (** alias for {!Concrete.CPoint.div} *) end val print : Format.formatter -> t -> unit end (** Concrete Paths *) module CPath : sig (* A path is a succession of splines *) type t type abscissa = float val length : t -> float val is_closed : t -> bool val is_a_point : t -> CPoint.t option val intersection : t -> t -> (abscissa * abscissa) list (** intersection p1 p2 return a list of pair of abscissa. In each pairs (a1,a2), a1 (resp. a2) is the abscissa in p1 (resp. p2) of one intersection point between p1 and p2. Additionnal point of intersection (two point for only one real intersection) can appear in degenerate case. *) val one_intersection : t -> t -> (abscissa * abscissa) (** one_intersection p1 p2 return one of the intersections between p1 and p2 or raise Not_found if none exists*) val reverse : t -> t (** reverse p return the path p reversed *) val iter : (CPoint.t -> CPoint.t -> CPoint.t -> CPoint.t -> unit) -> t -> unit (** iter on all the splines of a path: iter f p applies f successively to the splines of p with : - the start point of the spline as first argument - the control point of the start point as second argument - the control point of the end point as third argument - the end point as fourth argument *) val fold_left : ('a -> CPoint.t -> CPoint.t -> CPoint.t -> CPoint.t -> 'a) -> 'a -> t -> 'a (** fold on all the splines of a path *) val cut_before : t -> t -> t val cut_after : t -> t -> t (** remove the part of a path before the first intersection or after the last*) val split : t -> abscissa -> t * t val subpath : t -> abscissa -> abscissa -> t val direction_of_abscissa : t -> abscissa -> CPoint.t val point_of_abscissa : t -> abscissa -> CPoint.t val bounding_box : t -> CPoint.t * CPoint.t val dist_min_point : t -> CPoint.t -> float * abscissa val dist_min_path : t -> t -> float * (abscissa * abscissa) val print : Format.formatter -> t -> unit end module CTransform : sig type t = Ctypes.matrix end (** {2 Compute the concrete value} *) val float_of_num : Num.t -> float val cpoint_of_point : Point.t -> CPoint.t val cpath_of_path : Path.t -> CPath.t val ctransform_of_transform : Transform.t -> CTransform.t (** {2 Compute the baselines of a tex} *) val baselines : string -> float list (** {2 Simple functions for the opposite operations} *) val num_of_float : float -> Num.t (** Same as [Num.bp]. *) val point_of_cpoint : CPoint.t -> Point.t val path_of_cpath : CPath.t -> Path.t val transform_of_ctransform : CTransform.t -> Transform.t (** {2 Some options (the mlpost tool takes care of them)} *) (** These functions are deprecated. *) val set_verbosity : bool -> unit (** (deprecated) *) val set_prelude : string -> unit (** (deprecated) [set_prelude filename] uses the prelude of the file filename for compilation of the tex snippets *) val set_prelude2 : string option -> unit (** (deprecated) [set_prelude2 prelude] uses this prelude for compilation of the tex snippets *) val set_t1disasm : string option -> unit (** (deprecated) *) end (** Use the Cairo backend to draw your figures; not always available *) module Cairost : sig val supported : bool val emit_pdf : ?msg_error:float -> string -> Command.t -> unit (* The optional argument set the replacement the figure by the text of the exception in a paragraph of width msg_error *) val emit_ps : string -> Command.t -> unit val emit_png : string -> Command.t -> unit val emit_svg : string -> Command.t -> unit val emit_pdfs : string -> Command.t list -> unit (** One figure by page *) val dump_pdf : unit -> unit val dump_ps : unit -> unit val dump_png : unit -> unit val dump_svg : unit -> unit val dump_pdfs : string -> unit (** Use the figures recorded by the function emit of metapost *) val generate_pdfs : string -> (int * Command.t) list -> unit IFDEF CAIRO THEN type cairo_t = Cairo.t ELSE type cairo_t END val emit_cairo : cairo_t -> float * float -> Command.t -> unit end (**/**) module Metapost_tool : sig val read_prelude_from_tex_file : string -> string end module Version : sig val version : string val date : string end module Mps : sig val dump: unit -> unit val generate : (string * Command.t) list -> unit end (**/**) module Defaults : sig val set_prelude : string -> unit val set_filename_prefix : string -> unit val set_required_files : string list -> unit val set_verbosity : bool -> unit val set_t1disasm : string option -> unit end mlpost-0.8.2/mlpost_cairo.mlpack000066400000000000000000000010531306046515300167250ustar00rootroot00000000000000Version Signature Num Point MetaPath Path Pen Dash Color Brush Box Transform Picture Arrow Command Triangle Helpers Tree Tree_adv Diag Plot Real_plot Shapes Misc Metapost MPprint Radar Hist Legend Cairost Metapost_tool Concrete Concrete_types Print Types Compile Compiled_types Duplicate Hashcons Icairost Picture_lib Spline Spline_lib Fonts Tfm Dvi Dvicairo Dviinterp Matrix Point_lib Compute Pfb_lexer Pfb_parser Map_lexer Map_parser Gentex Unionfind Metapath_lib Draw Ctypes Metric Mps Name Dvi_util Scan_prelude Fonts_type File Mlpost_ft Defaults mlpost-0.8.2/mlpost_concrete.mlpack000066400000000000000000000010071306046515300174310ustar00rootroot00000000000000Version Signature Num Point MetaPath Path Pen Dash Color Brush Box Transform Picture Arrow Command Triangle Helpers Tree Tree_adv Diag Plot Real_plot Shapes Misc Metapost MPprint Radar Hist Legend Cairost Concrete Concrete_types Print Types Compile Compiled_types Duplicate Hashcons Picture_lib Spline Spline_lib Fonts Tfm Dvi Dviinterp Matrix Point_lib Compute Pfb_lexer Pfb_parser Map_lexer Map_parser Gentex Unionfind Metapath_lib Ctypes Metapost_tool Metric Mps Name Dvi_util Scan_prelude Fonts_type File Defaults mlpost-0.8.2/mlpost_desc_options.ml000066400000000000000000000061301306046515300174630ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format open Arg let pdf = ref true let latex_file = ref None let set_latex_file f = if not (Sys.file_exists f) then begin eprintf "mlpost: %s: no such file@." f; exit 1 end; latex_file := Some f let xpdf = ref false let interactive = ref false let eps = ref false let verbose = ref false let cairo = ref false let t1disasm = ref None let depend = ref false let dumpable = ref false let dont_clean = ref false let mp = ref false let mps = ref false let png = ref false let svg = ref false let filename_prefix = ref "" let required_files : string list ref = ref [] let push_required s = required_files := s :: !required_files (* notuple please or change Tool.wrap_options *) let spec = (["-pdf", Set pdf, " Generate .mps files (default)"; "-mp", Set mp, " Generate .mp files"; "-png", Set png, " Generate .png files"; "-ps", Clear pdf, " Generate .1 files"; "-mps", Set mps, " Use the experimental Mps output"; "-svg", Set svg, " Generate .svg files (only with cairo)"; "-latex", String set_latex_file, " Scan the LaTeX prelude"; "-eps", Set eps, " Generate encapsulated postscript files"; "-xpdf", Set xpdf, " wysiwyg mode using xpdf remote server"; "-i", Set interactive, " wysiwyg mode using file _mlpost.pdf"; "-required", String push_required, " Specify files required by latex"; "-v", Set verbose, " be a bit more verbose"; "-depend", Set depend, " output dependency lines in a format suitable for the make(1) utility"; "-dumpable", Set dumpable, " output one name of dumpable file by line"; "-dont-clean", Set dont_clean, " Don't remove intermediate files"; "-cairo" , Set cairo, " Use the cairo backend instead of metapost"; "-prefix", String ((:=) filename_prefix), "Add to all the filename this prefix"; "-t1disasm" , String (fun s -> t1disasm := Some s), " Set the program used to decrypt PostScript Type 1 font, \ only with cairo (default built-in one)"]) mlpost-0.8.2/mlpost_no.mlpack000066400000000000000000000005201306046515300162420ustar00rootroot00000000000000Version Signature Num Point MetaPath Path Pen Dash Color Brush Box Transform Picture Arrow Command Triangle Helpers Tree Tree_adv Diag Plot Real_plot Shapes Misc Metapost MPprint Radar Hist Legend Cairost Concrete Print Types Compile Compiled_types Duplicate Hashcons Metapost_tool Name Dvi_util Scan_prelude Fonts_type File Defaults mlpost-0.8.2/mlpost_nolablgtk.odocl000066400000000000000000000000211306046515300174300ustar00rootroot00000000000000Mlpost Mlpost_dotmlpost-0.8.2/mlpost_options.ml000066400000000000000000000071531306046515300164730ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Mlpost open Mlpost_desc_options let call_cmd = Misc.call_cmd let () = let user_opts = Queue.create () in let user_opt = ("--", Arg.Rest (fun s -> Queue.add s user_opts), "The option given to the program") in Arg.parse (Arg.align (user_opt::spec)) (fun s -> raise (Arg.Bad "No anonymous option among the mlpost options, \ begin by -- for the user options")) "A program compiled with mlpost"; (* Replace the mlpost argument by the user one *) for i = 1 to (Array.length Sys.argv) - 1 do if Queue.is_empty user_opts then Sys.argv.(i) <- "" else Sys.argv.(i) <- Queue.pop user_opts done; (* And reset the current of Arg *) Arg.current := 0; let prelude = match !latex_file with | None -> None | Some f -> let s = Metapost_tool.read_prelude_from_tex_file f in Defaults.set_prelude s; Some s in let verbose = !verbose in Defaults.set_filename_prefix !filename_prefix; Defaults.set_required_files !required_files; Defaults.set_verbosity verbose; Defaults.set_t1disasm !t1disasm; let bn = Filename.concat (Sys.getcwd ()) (Filename.basename (Sys.argv.(0))) in let do_at_exit () = if !cairo then begin if not (!xpdf || !interactive) then if !png then Cairost.dump_png () else if !svg then Cairost.dump_svg () else if !pdf then Cairost.dump_pdf () else Cairost.dump_ps () else Cairost.dump_pdfs "_mlpost" end else begin if !mp && not (!xpdf || !interactive) then Metapost.dump_mp ?prelude bn else if !png && not (!xpdf || !interactive) then Metapost.dump_png ?prelude ~verbose ~clean:(not !dont_clean) bn else if !mps then Mps.dump () else Metapost.dump ?prelude ~verbose ~clean:(not !dont_clean) bn; if !xpdf || !interactive then begin Metapost.dump_tex ?prelude "_mlpost"; begin try Sys.remove "_mlpost.aux" with _ -> () end; ignore (call_cmd ~verbose "pdflatex _mlpost.tex"); end end; if !xpdf then begin if call_cmd ~verbose "fuser _mlpost.pdf" = 0 then ignore (call_cmd ~verbose "xpdf -remote mlpost -reload") else ignore (call_cmd ~verbose "setsid xpdf -remote mlpost _mlpost.pdf &") end; in (* When an exit is fired inside do_at_exit the function seems to be run again *) let done_once = ref false in at_exit (fun () -> if not !done_once then (done_once := true; do_at_exit ())) mlpost-0.8.2/mlpost_options.mli000066400000000000000000000032041306046515300166350ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Provide command-line options and dump figures. *) (** When you link with this module, command-line options of the Mlpost tool are added to your program. If you want to use your own options you have to give them after a ["--"] argument. This module will replace all arguments before this ["--"] (included) by [""], and then shift all remaining arguments to the beginning. This module also calls [dump] when your program exits. This produces the files of the figures you [emit]ed. *) mlpost-0.8.2/mlpost_options.mllib000066400000000000000000000000171306046515300171520ustar00rootroot00000000000000Mlpost_options mlpost-0.8.2/mlpost_yeslablgtk.odocl000066400000000000000000000000401306046515300176150ustar00rootroot00000000000000Mlpost Mlpost_dot Mlpost_lablgtkmlpost-0.8.2/multi-examples/000077500000000000000000000000001306046515300160105ustar00rootroot00000000000000mlpost-0.8.2/multi-examples/Makefile000066400000000000000000000011501306046515300174450ustar00rootroot00000000000000MLFILES := $(shell echo *.ml) MLFILES := $(MLFILES:myocamlbuild.ml=) MLFILES := $(MLFILES:examples.ml=) BUILD = _build/ OCAMLBUILD := ocamlbuild ifeq ($(TERM), dumb) OCAMLBUILD := $(OCAMLBUILD) -classic-display endif ifneq ($(BUILD), _build/) OCAMLBUILD := $(OCAMLBUILD) -build-dir $(BUILD) endif HTML = $(BUILD)examples.html all: $(OCAMLBUILD) $(MLFILES:.ml=.htmlpart) echo "Mlpost Examples" > $(HTML) echo "

Mlpost Examples

" >> $(HTML) cat $(BUILD)*.htmlpart >> $(HTML) echo "" >> $(HTML) clean: $(OCAMLBUILD) -clean rm -f *~ .PHONY: allmlpost-0.8.2/multi-examples/_tags000066400000000000000000000000161306046515300170250ustar00rootroot00000000000000<*>: use_unix mlpost-0.8.2/multi-examples/all.template000066400000000000000000000003041306046515300203120ustar00rootroot00000000000000\documentclass{article} \usepackage{graphicx} \pagestyle{empty} \begin{document} \includegraphics[scale=3]{all.1} \end{document} %%% Local Variables: %%% mode: latex %%% TeX-master: t %%% End: mlpost-0.8.2/multi-examples/arrows.ml000066400000000000000000000055721306046515300176700ustar00rootroot00000000000000open Examples open Mlpost open Command let w = 2. let a = Point.pt (Num.cm 0., Num.cm 0.) let b = Point.pt (Num.cm w, Num.cm 0.) let c = Point.pt (Num.cm 0., Num.cm w) let d = Point.pt (Num.cm w, Num.cm w) let up = Path.vec Point.up let down = Path.vec Point.down let left = Path.vec Point.left let right = Path.vec Point.right let double_headed = Arrow.add_foot Arrow.classic let multiple_headed = Arrow.add_foot ~head: Arrow.head_triangle (Arrow.add_belt ~point: 0.25 ~head: (Arrow.head_triangle ~size: (Num.bp 10.)) (Arrow.add_belt ~point: 0.5 ~head: Arrow.head_triangle_full (Arrow.add_belt ~point: 0.75 ~head: (Arrow.head_triangle_full ~angle: 140.) (Arrow.add_head ~head: (Arrow.head_triangle ~size: (Num.bp 15.)) (Arrow.add_line Arrow.empty))))) let serial_lines = Arrow.add_head (Arrow.add_line ~to_point: 0.10 ~pen: (Pen.scale (Num.bp 5.) Pen.square) (Arrow.add_line ~from_point: 0.10 ~to_point: 0.33 (Arrow.add_line ~from_point: 0.33 ~to_point: 0.66 ~dashed: Dash.withdots (Arrow.add_line ~from_point: 0.66 ~dashed: Dash.evenly Arrow.empty)))) let () = emit (Arrow.point_to_point a d); emit (Arrow.point_to_point b c); emit (Arrow.point_to_point c b); emit (Arrow.point_to_point a b); (* Some curved arrows *) emit (Arrow.point_to_point ~outd: up a d); emit (Arrow.point_to_point ~outd: up b c); emit (Arrow.point_to_point ~outd: right c b); emit (Arrow.point_to_point ~outd: up a b); (* Some double-headed arrows *) emit (Arrow.point_to_point ~kind: double_headed a d); emit (Arrow.point_to_point ~kind: double_headed ~outd: right c b); (* Some multiple-headed arrows *) emit (Arrow.point_to_point ~kind: multiple_headed a d); emit (Arrow.point_to_point ~kind: multiple_headed ~outd: right c b); (* Some arrows with multiple serial lines *) emit (Arrow.point_to_point ~kind: serial_lines a d); emit (Arrow.point_to_point ~kind: serial_lines ~outd: right c b); (* Some "implies" and "iff" *) emit (Arrow.point_to_point ~kind: Arrow.implies a d); emit (Arrow.point_to_point ~kind: Arrow.implies ~outd: right c b); emit (Arrow.point_to_point ~kind: Arrow.implies ~outd: up ~ind: up a b); emit (Arrow.point_to_point ~kind: Arrow.iff a d); emit (Arrow.point_to_point ~kind: Arrow.iff ~outd: right c b); emit (Arrow.point_to_point ~kind: Arrow.iff ~outd: up ~ind: up a b); (* A straight thick arrow *) emit (Arrow.draw_thick a d); emit (Arrow.draw_thick b c); emit (Arrow.draw_thick c b); emit (Arrow.draw_thick a b); (* Some curved thick arrows *) emit (Arrow.draw_thick ~outd: up a d); emit (Arrow.draw_thick ~outd: up b c); emit (Arrow.draw_thick ~outd: right c b); emit (Arrow.draw_thick ~outd: up a b); (* A snake thick arrow *) emit (Arrow.draw_thick ~outd: up ~ind: up a b); dump () mlpost-0.8.2/multi-examples/examples.ml000066400000000000000000000005401306046515300201570ustar00rootroot00000000000000open Mlpost let emit, dump = let base_name = Filename.chop_extension Sys.argv.(0) in let emit = let cnt = ref 0 in fun f -> incr cnt; Metapost.emit (Printf.sprintf "%s-%0.4d" base_name !cnt) f in let dump = let base_name = Filename.chop_extension Sys.argv.(0) in fun () -> Metapost.dump base_name in emit, dump mlpost-0.8.2/multi-examples/myocamlbuild.ml000066400000000000000000000051451306046515300210300ustar00rootroot00000000000000open Ocamlbuild_plugin open Command open Pathname let find_files base = let lbase = String.length base in let files = Array.to_list (readdir ".") in let files = List.filter begin fun f -> check_extension f "1" && String.sub f 0 lbase = base end files in List.sort String.compare files let shell x = Printf.ksprintf (fun s -> Cmd(Sh s)) x let line f x = Printf.ksprintf (fun s -> Cmd(Sh("echo \""^s^"\" >> "^f))) x let () = dispatch begin function | After_rules -> rule ".byte -> .htmlpart" ~prod: "%.htmlpart" ~deps: ["%.byte"; "all.template"] begin fun env build -> (* Execute the program *) Command.execute (Cmd(S[A(env "./%.byte"); Sh "> /dev/null"])); (* DELETE "> /dev/null" IF YOU WANT TO DEBUG *) (* List its .1 files *) let files = find_files (env "%-") in let files = List.map Filename.chop_extension files in let files = List.map (fun f -> f ^ ".png") files in (* Compile .png files *) List.iter Outcome.ignore_good (build (List.map (fun x -> [x]) files)); (* Produce the .htmlpart file *) let f = env "%.htmlpart" in Seq [ shell "echo > %s" f; line f "

%s:

" (env "%.ml"); Seq (List.map (fun png -> line f "" png) files); ] end; rule ".byte -> .1" ~prod: "%(base)-%(num).1" ~dep: "%(base).byte" begin fun env _ -> Cmd(A(env "./%(base).byte")) end; rule ".1 -> .dvi" ~prod: "%.dvi" (* ~dep: "%.1" (* IGNORE THIS TO MAKE THE .htmlpart RULE WORK *) *) begin fun env _ -> let base = env "%" in let sed = Sh(Printf.sprintf "sed -e 's/all/%s/' all.template > %s.tex" base base) in let latex = S[ A "latex"; A "-interaction"; A "nonstopmode"; A "-file-line-error"; A "-halt-on-error"; A base; Sh "> /dev/null"; (* DELETE THIS IF YOU WANT TO DEBUG *) ] in Seq[Cmd sed; Cmd latex] end; rule ".dvi -> .ps" ~prod: "%.ps" ~dep: "%.dvi" begin fun env _ -> Cmd(S[A "dvips"; A "-q"; A "-E"; A(env "%.dvi"); A "-o"]) end; rule ".ps -> png" ~prod: "%.png" ~dep: "%.ps" begin fun env _ -> Cmd(S[A "convert"; A(env "%.ps"); A(env "%.png")]) end; flag ["ocaml"; "compile"] (S [A "-I";A "../../_build"; A "mlpost.cma"]); flag ["ocaml"; "link"] (A "../../_build/mlpost.cma") | _ -> () end mlpost-0.8.2/myocamlbuild.ml.in000066400000000000000000000203711306046515300164650ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) # 18 "myocamlbuild.ml.in" open Ocamlbuild_plugin open Command (* Configuration section should be done in configure *) let freetype_lib = "-lfreetype" let freetype_lib2 = "-lz" (* let zlib_libdir = "-L/usr/lib64" (* for x86-64 Linux *) *) let freetype_include = "-I/usr/include/freetype2" let tagcairo = ref false let tagconcrete = ref false let packages_cairo = ["cairo","@CAIROLIB@","cairo"; ] let packages () = let acc = [ "lablgtk2","@LABLGTK2LIB@","lablgtk"; "lablgnomecanvas","@LABLGTK2LIB@","lablgnomecanvas"; ] in if !tagconcrete then ("bitstring","@BITSTRINGLIB@","bitstring") :: acc else acc let gen_def_string () = let l = [] in let l = if !tagconcrete then "-D CONCRETE" :: l else l in let l = if !tagcairo then "-D CAIRO"::l else l in l let string_flatten l = List.fold_left (fun acc s -> acc ^ " " ^ s) "" l let syntaxes () = let bitstring_entry = let cmd = "@CAMLP4O@ -I @BITSTRINGLIB@ bitstring.cma \ bitstring_persistent.cma pa_bitstring.cmo" in "bitstring", cmd, cmd in let s = string_flatten (gen_def_string ()) in let compile_cmd = "@CAMLP4O@ Camlp4MacroParser.cmo " ^ s in let doc_cmd = "./myocamlmacroparser.byte " ^ s in let mymacroparser_entry = "mymacroparser",compile_cmd, doc_cmd in let macro_entry = "macro", compile_cmd, compile_cmd in [ bitstring_entry ; mymacroparser_entry ; macro_entry ] let img_doc_prod = ["circle";"rect";"ellipse";"round_rect"; "patatoid";"tex";"ctr";"north";"south"; "west";"east";"north_west";"south_west"; "north_east";"south_east";"width";"height"; "shift";"center";"halign"; "hplace"; "hbox"; ] let _ = dispatch begin function | Before_options -> Options.include_dirs := "concrete"::"dvi"::"backend"::"gui"::!Options.include_dirs; Options.exclude_dirs := "presentations"::"papers"::"examples":: "contrib/dot/_build"::"contrib/lablgtk/_build":: "test"::!Options.exclude_dirs; Options.ocamldoc := S[A"@OCAMLDOC@"] | Before_rules -> tagcairo := Ocamlbuild_pack.Configuration.has_tag "cairo_yes"; tagconcrete := Ocamlbuild_pack.Configuration.has_tag "concrete_yes"; let yesnofile_rule file yesno ext = rule (file^" generation for "^yesno) ~deps:[file^yesno^ext] ~prod:(file^ext) (fun _ _ -> cp (file^yesno^ext) (file^ext)) in if !tagcairo then begin yesnofile_rule "mlpost" "_cairo" ".mlpack"; end else begin if !tagconcrete then begin yesnofile_rule "mlpost" "_concrete" ".mlpack"; end else begin yesnofile_rule "mlpost" "_no" ".mlpack"; end end; yesnofile_rule "mlpost" "_@LABLGTK2@lablgtk" ".odocl"; let copy file1 file2 = rule (" copy from "^file1^"to "^file2) ~deps:[file1] ~prod:(file2) (fun _ _ -> cp file1 file2) in copy "contrib/dot/mlpost_dot.mli" "mlpost_dot.mli"; copy "contrib/lablgtk/mlpost_lablgtk.mli" "mlpost_lablgtk.mli"; (**doc *) rule "generation of the documentation" ~prod:"doc/index.html" ~deps:["mlpost.docdir/html.stamp";"img/stamp"] (fun _ _ -> Cmd(Sh "rm -rf doc && cp -r mlpost.docdir doc && cp -r img doc")); flag ["ocaml"; "compile"; "use_ocamldoc"] & S[A"-I"; A "+ocamldoc"]; dep ["ocaml";"doc"] ["customdoc/img.cmo"]; dep ["ocaml"; "syntax_mymacroparser"] ["myocamlmacroparser.byte"]; flag ["ocaml";"doc"] & S([A"-hide" ; A "Mlpost"; A"-g"; A "customdoc/img.cmo"] @ (if "@LABLGTK2@" = "yes" then [A"-I"; A"@LABLGTK2LIB@"] else [])); rule "generation of the images for the documentation" ~prod:"img/image.png" ~stamp:"img/stamp" ~deps:(List.map (fun x -> "img/"^x^".png") img_doc_prod) (fun _ _ -> Nop); (** For img *) rule "produce image in img from img_doc.ml" ~prods: (List.map (fun x -> "img/"^x^".mps") img_doc_prod) ~dep: "customdoc/img_doc.byte" begin fun env _ -> Cmd(Sh "mkdir -p img/ && cd img/ && ../customdoc/img_doc.byte \ >> /dev/null && cd ..") end; (** conversion of images *) rule ".mps -> .dvi" ~prod: "%.dvi" ~deps: ["%.mps";"customdoc/all.template"] begin fun env _ -> let base = env "%" in let dirname = Pathname.dirname base in let basename = Pathname.basename base in let sed = Sh(Printf.sprintf "sed -e 's/all/%s/' customdoc/all.template > %s.tex" basename base) in let latex = S[ A "cd" ; P dirname; Sh " && "; A "latex"; A "-interaction"; A "nonstopmode"; A "-file-line-error"; A "-halt-on-error"; A basename; Sh "> /dev/null"; (* DELETE THIS IF YOU WANT TO DEBUG *) ] in Seq[Cmd sed; Cmd latex] end; rule ".dvi -> .ps" ~prod: "%.ps" ~dep: "%.dvi" (fun env _ -> let base = env "%.dvi" in let dirname = Pathname.dirname base in let basename = Pathname.basename base in Cmd(S[A "cd" ; P dirname; Sh " && "; A "dvips"; A "-q"; A "-E"; A basename; A "-o"])); rule ".ps -> png" ~prod: "%.png" ~dep: "%.ps" (fun env _ -> Cmd(S[A "convert"; A(env "%.ps"); A(env "%.png")])); | After_rules -> ocaml_lib "mlpost_ft"; if !tagcairo then ocaml_lib ~extern:true ~tag_name:("use_cairo_bigarray") "bigarray"; (* When one compile C code using the zlib *) flag ["c"; "compile"; "include_freetype"] (S[A"-ccopt"; A freetype_include]); flag ["link"; "ocaml"; "library"; "use_freetype"] (S[A"-cclib"; A freetype_lib ; A"-cclib"; A freetype_lib2]); (* ml lib *) flag ["link"; "library"; "ocaml"; "byte"; "use_libmlpost_ft"] (S[A"-dllpath";A "backend"; A"-dllib"; A"dllmlpost_ft"; A"-cclib"; A"-Lbackend"; A"-I"; A"backend"]); flag ["link"; "ocaml"; "byte"; "use_libmlpost_ft"] (S[A"-dllpath";A "../backend"; A"-dllib"; A"dllmlpost_ft"; A"-cclib"; A"-Lbackend"; A "-I"; A"backend"]); flag ["link"; "library"; "ocaml"; "native"; "use_libmlpost_ft"] (S[A"-cclib"; A"-lmlpost_ft"]); (* When ocaml link something that use the libmlpost, then one need that file to be up to date. *) (* dep ["link"; "ocaml"; "use_libmlpost_ft"] ["backend/libmlpost_ft.a"]; *) List.iter (fun (pkg,dir,file) -> ocaml_lib ~extern:true ~tag_name:("pkg_"^pkg) ~dir file; flag ["ocaml"; "pack"; "pkg_"^pkg] & S[A"-I"; P dir]; flag ["ocaml"; "doc"; "pkg_"^pkg ] & S[A"-I"; P dir]) (let p = packages () in if !tagcairo then packages_cairo@p else p); List.iter (fun (syntax,pp, doc) -> flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-pp"; A pp]; flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-pp"; A pp]; flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-pp"; A doc];) (syntaxes ()); | _ -> () end mlpost-0.8.2/myocamlmacroparser.mll000066400000000000000000000067561306046515300174660ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This is an implementation of a macro preprocessor compatible with the * Camlp4Macroparser. *) (* it currently only supports IFDEF statements: IFDEF THEN [ ELSE ] (END | ENDIF) *) { let b = Buffer.create 1024 let symbol_table : (string, unit) Hashtbl.t = Hashtbl.create 17 let char = Buffer.add_char b let def = Hashtbl.mem symbol_table let add_symbol s = Hashtbl.add symbol_table s () let linenr = ref 0 let newline () = incr linenr let ksprintf k s = let buf = Buffer.create 1024 in let fmt = Format.formatter_of_buffer buf in Format.kfprintf (fun _ -> Format.pp_print_flush fmt (); k (Buffer.contents buf)) fmt s let error s = ksprintf (fun s -> Format.eprintf "parse error on line %d: %s" !linenr s; (exit 1 : unit)) s let fn = ref None let args = [ "-D", Arg.String add_symbol, " mark as defined" ] let usage = "Usage: myocamlmacroparser inputfile" let _ = Arg.parse args (fun s -> fn := Some s) usage } let alpha = [ 'A' - 'Z' 'a' - 'z' '0' - '9' ] let other = ( alpha | '_') let endif = "END" | "ENDIF" let blank = [ ' ' '\t' '\n' ] let uident = alpha other* rule normal = parse | "IFDEF" blank* (uident as id) blank* "THEN" { (if def id then thenbranch lexbuf else skiptoelse lexbuf : unit) } | ("ELSE" | "THEN" | endif as s) { error "unexpected token: %s" s } | eof { () } | _ as c { char c ; normal lexbuf } and thenbranch = parse | "ELSE" { skiptoend lexbuf } | endif { normal lexbuf } | ("THEN" as s) { error "unexpected token: %s" s } | eof { error "unexpected end of file" } | _ as c { char c; thenbranch lexbuf } and skiptoelse = parse | "ELSE" { elsebranch lexbuf } | endif { normal lexbuf } | eof { error "unexpected end of file" } | _ { skiptoelse lexbuf } and skiptoend = parse | endif { normal lexbuf } | eof { error "unexpected end of file" } | _ { skiptoend lexbuf } and elsebranch = parse | endif { normal lexbuf } | ("ELSE" | "THEN" as s) { error "unexpected token: %s" s } | eof { error "unexpected end of file" } | _ as c { char c; elsebranch lexbuf } { let _ = let cin = match !fn with | None -> stdin | Some s -> open_in s in normal (Lexing.from_channel cin); close_in cin; Buffer.output_buffer stdout b } mlpost-0.8.2/name.ml000066400000000000000000000033501306046515300143150ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type t = string let create prefix = let r = ref 0 in fun () -> incr r; prefix ^ string_of_int !r let node = create "node" let rec alpha i = if 0 <= i && i <= 22 then String.make 1 (Char.chr (Char.code 'a' + i)) else alpha (i / 22) ^ alpha (i mod 22) let path = let r = ref 0 in fun () -> incr r; "path" ^ alpha !r let picture = let r = ref 0 in fun () -> incr r; "pic" ^ alpha !r let point = let r = ref 0 in fun () -> incr r; "pot" ^ alpha !r let num = let r = ref 0 in fun () -> incr r; "num" ^ alpha !r let transform = let r = ref 0 in fun () -> incr r; "trans" ^ alpha !r mlpost-0.8.2/num.ml000066400000000000000000000051551306046515300142010ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types open Hashcons type t = float let zero = 0. let one = 1. let minus_one = (-.1.) let two = 2. let of_float = Misc.id let num_of_int = float let bp f = f let pt f = 0.99626 *. f let cm f = 28.34645 *. f let mm f = 2.83464 *. f let inch f = 72. *. f let pi = 3.1415926535897932384626433832795029 let pi_div_180 = pi /. 180.0 let deg2rad f = pi_div_180 *. f let is_zero f = abs_float f < 0.0001 type scale = float -> t let addn = (+.) let subn = (-.) let multn = ( *.) let multf = multn let divn = (/.) let divf x f = divn x f let maxn = max let minn = min let gmean f1 f2 = sqrt (f1 *. f1 +. f2 *. f2 ) let fold_max f = List.fold_left (fun w p -> maxn w (f p)) let fold_min f = List.fold_left (fun w p -> minn w (f p)) let if_null n n1 n2 = if is_zero n then n1 else n2 module Scale = struct let bp x y = bp (x *. y) let pt x y = pt (x *. y) let cm x y = cm (x *. y) let mm x y = mm (x *. y) let inch x y = inch (x *. y) end module Infix = struct let (+/) = addn let (-/) = subn let ( */) = multn let (//) = divn let ( *./) = multf let (/./) = divf end let neg x = 0. -. x let abs = abs_float (* TeX units *) let xlength p = let xmin,_,xmax, _ = Gentex.get_dimen_pt (Gentex.create p) in xmax -. xmin let ylength p = let _,ymin,_, ymax = Gentex.get_dimen_pt (Gentex.create p) in ymax -. ymin let pic s = mkPicture (mkPITex s) let em_factor () = xlength "m" let ex_factor () = ylength "x" let em f = f *. em_factor () let ex f = f *. ex_factor () mlpost-0.8.2/ocamlbuild.Makefile000066400000000000000000000127731306046515300166260ustar00rootroot00000000000000########################################################################## # # # Copyright (C) Johannes Kanig, Stephane Lescuyer # # Jean-Christophe Filliatre, Romain Bardou and Francois Bobot # # # # This software is free software; you can redistribute it and/or # # modify it under the terms of the GNU Library General Public # # License version 2.1, with the special exception on linking # # described in file LICENSE. # # # # This software 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. # # # ########################################################################## TESTS = handbookgraphs.cmx othergraphs.cmx tests.cmx ifeq "$(OCAMLBEST)" "opt" TOOL= tool.native else TOOL= tool.byte OBOPTS += -byte-plugin endif ifeq "$(TERM)" "dumb" OCAMLBUILD_DISPLAY= -classic-display else OCAMLBUILD_DISPLAY= endif DTYPES = -tag bin_annot OCAMLBUILD := $(OCAMLBUILDBIN) $(OBOPTS) -no-links $(DTYPES) $(TAGS) $(OCAMLBUILD_DISPLAY) -classic-display -log "build.log" BUILD := _build/ CMI := mlpost_options.cmi CMA := mlpost.cma mlpost_desc_options.cma mlpost_options.cma $(CMI) CMXA := mlpost.cmxa mlpost_desc_options.cmxa mlpost_options.cmxa OBJ := mlpost_desc_options$(LIBEXT) mlpost_options$(LIBEXT) #FixMe Should be done only when cairo/freetype is in the mood EXTDLL = .so DLL := backend/dllmlpost_ft$(EXTDLL) backend/libmlpost_ft.a ifeq "$(OCAMLBEST)" "opt" all: $(OCAMLBUILD) $(CMA) $(CMXA) $(TOOL) $(DLL) lib: $(OCAMLBUILD) $(CMA) $(CMXA) $(DLL) LIB_EXT=.cma .cmxa .cmi else all: $(OCAMLBUILD) $(CMA) $(TOOL) $(DLL) lib: $(OCAMLBUILD) $(CMA) $(DLL) LIB_EXT=.cma .cmi endif byte : $(OCAMLBUILD) $(CMA) tool.byte opt : $(OCAMLBUILD) $(CMXA) tool.native check: all $(TESTS) check-examples tool.byte: $(OCAMLBUILD) tool.byte tool.opt: $(OCAMLBUILD) tool.native LOCALMLPOST:=$(BUILD)tool.native -libdir $(BUILD) -v -ps -native -ccopt "-I $(BUILD)/backend" tests: tests.ml $(LOCALMLPOST) -xpdf tests.ml testbox: testbox.ml $(OCAMLBUILD) testbox.native $(BUILD)/testbox.native make -C test testbox $(PSVIEWER) test/testbox.ps tests.pdf: tests.ml $(OCAMLBUILD) tests.native $(BUILD)/tests.native make -C test tests.pdf $(PDFVIEWER) test/tests.pdf tests.byte: tests.ml $(OCAMLBUILD) tests.byte $(BUILD)/tests.byte make -C test tests $(PSVIEWER) test/tests.ps handbook.pdf : handbookgraphs.ml $(OCAMLBUILD) generate.cmx $(LOCALMLPOST) -no-magic -ccopt "generate.cmx" handbookgraphs.ml make -C test manual make -C test/manual mpost handbook: handbook.pdf $(PDFVIEWER) test/testmanual.pdf other.pdf : othergraphs.ml $(OCAMLBUILD) generate.cmx $(LOCALMLPOST) -no-magic -ccopt "generate.cmx" othergraphs.ml make -C test other make -C test/othergraphs mpost other: other.pdf $(PDFVIEWER) test/othergraphs.pdf other.byte: othergraphs.ml $(OCAMLBUILD) othergraphs.byte $(BUILD)/othergraphs.byte make -C test other make -C test/othergraphs mpost $(PSVIEWER) test/othergraphs.ps .PHONY: check-examples examples SUBDIRMLPOST:=../$(BUILD)tool.native -libdir ../$(BUILD) -v -ps -native -ccopt "-I ../$(BUILD)/backend" MAKEEXAMPLES=$(MAKE) -C examples MLPOST='$(SUBDIRMLPOST)' check-examples: mlpost.cma tool.opt $(MAKEEXAMPLES) boxes.dummy $(MAKEEXAMPLES) paths.dummy $(MAKEEXAMPLES) tree.dummy $(MAKEEXAMPLES) terms.dummy $(MAKEEXAMPLES) label.dummy make -C multi-examples examples: tool.opt $(MAKEEXAMPLES) examples-contrib: tool.opt $(MAKEEXAMPLES) contrib examples-html: tool.opt $(MAKEEXAMPLES) html # Contrib contrib: dot-contrib lablgtk-contrib dot-contrib : lib @echo "make: Entering directory \`$(shell pwd)/contrib/dot'" cd contrib/dot && $(OCAMLBUILDBIN) $(DTYPES) -cflags -I,$(shell pwd)/_build $(addprefix mlpost_dot,$(LIB_EXT)) && cd ../.. ln -sf contrib/dot/_build _build_dot ifeq "$(LABLGTK2)$(CAIROLABLGTK2)" "yesyes" lablgtk-contrib : lib @echo "make: Entering directory \`$(shell pwd)/contrib/lablgtk'" cd contrib/lablgtk && $(OCAMLBUILDBIN) $(DTYPES) -cflags -I,$(shell pwd)/_build \ -cflags -I,$(LABLGTK2LIB) \ -cflags -I,$(CAIROLABLGTK2LIB) \ $(addprefix mlpost_lablgtk,$(LIB_EXT)) && cd ../.. ln -sf contrib/lablgtk/_build _build_lablgtk else lablgtk-contrib : @echo "lablgtk2 or cairo.lablgtk2 hasn't been found I can't make mlpost_lablgtk" endif clean-contrib: cd contrib/dot && $(OCAMLBUILDBIN) -clean && cd ../.. cd contrib/lablgtk && $(OCAMLBUILDBIN) -clean && cd ../.. # GUI .PHONY: gui gui/gmlpost.native gui/glexer.cmo gui/glexer.cmi gui: gui/gmlpost.native gui/glexer.cmo gui/gmlpost.native: $(OCAMLBUILD) gui/gmlpost.native gui/gmlpost.byte: $(OCAMLBUILD) gui/gmlpost.byte gui/glexer.cmo: $(OCAMLBUILD) gui/glexer.cmo # building the doc ################## .PHONY: doc doc: rm -f doc $(OCAMLBUILD) doc/index.html ln -s _build/doc doc # clean ####### clean:: rm -rf doc rm -f test.dvi test.ps *.exe $(OCAMLBUILD) -clean cleaner:: clean make -C test clean make -C multi-examples clean make -C www clean make -C examples clean dist-clean distclean:: clean rm -f Makefile config.cache config.log config.status META version.ml myocamlbuild.ml mlpost-0.8.2/opam/000077500000000000000000000000001306046515300137765ustar00rootroot00000000000000mlpost-0.8.2/opam/descr000066400000000000000000000000261306046515300150170ustar00rootroot00000000000000Interface to Metapost mlpost-0.8.2/opam/files/000077500000000000000000000000001306046515300151005ustar00rootroot00000000000000mlpost-0.8.2/opam/files/run_autoconf_if_needed.ml000066400000000000000000000001311306046515300221110ustar00rootroot00000000000000 let () = if not (Sys.file_exists "configure") then exit (Sys.command "autoconf") mlpost-0.8.2/opam/findlib000066400000000000000000000000411306046515300153230ustar00rootroot00000000000000mlpost mlpost_dot mlpost_lablgtk mlpost-0.8.2/opam/opam000066400000000000000000000014501306046515300146550ustar00rootroot00000000000000opam-version: "1" maintainer: "filliatr@lri.fr" authors: [ "Romain Bardou" "Francois Bobot" "Jean-Christophe Filliâtre" "Johannes Kanig" "Stephane Lescuyer" ] license: "GNU Library General Public License version 2.1" build: [ ["ocaml" "run_autoconf_if_needed.ml"] #when used in pinned mode the configure *can* not yet be generated ["./configure" "--prefix" prefix "--mandir" man] [make] [make "install"] [make "contrib"] [make "install-contrib"] ] remove: [ ["ocaml" "run_autoconf_if_needed.ml"] #when used in pinned mode the configure *can* not yet be generated ["./configure" "--prefix" prefix] [make "uninstall"] [make "uninstall-contrib"] ] depends: [ "ocamlfind" "bitstring" "cairo" {= "1.2.0"} ] depexts: [ [["debian"] ["autoconf"]] [["ubuntu"] ["autoconf"]] ] mlpost-0.8.2/othergraphs.ml000066400000000000000000000165241306046515300157320ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Mlpost open Num open Box open Command open Point open Path module Co = Color module P = Pen module T = Transform module N = Num module H = Helpers let a = 0., 0. let b = 1., 0. let c = 0., 1. let l = [a ; b ; c] let d1 = 1, draw (path ~style:jLine ~scale:N.cm l) let d2 = 2, draw (path ~style:jLine ~scale:N.cm ~cycle:jLine l) let d4 = let pen = Pen.scale (bp 4.) Pen.circle in 4, draw ~pen (path ~scale:N.cm [a]) let d5 = 5, let pen = Pen.scale (bp 4.) P.circle in seq [ draw (path ~style:jLine ~scale:N.cm ~cycle:jLine l); seq (List.map (fun point -> draw ~pen (path ~scale:N.cm [point])) l) ] let d7 = 7, let a , b, c = cmp a, cmp b, cmp c in seq [draw (path ~style:jLine ~scale:N.cm ~cycle:jLine l) ; draw (pathp [ segment 0.5 a b ; c]) ; draw (pathp [ segment 0.5 b c ; a]) ; draw (pathp [ segment 0.5 c a ; b]) ; ] let d12 = 12, let pen = Pen.scale two Pen.circle in let cl = List.map Color.gray [0.8;0.6;0.4] in seq (List.map2 (fun (a,b) color -> draw ~pen ~color (path ~style:jLine ~scale:N.cm [a;b])) [a,b;b,c;c,a] cl) let triangle = path ~scale:N.cm ~style:jLine ~cycle:jLine [(0.,0.);(1.,0.);(0.,1.)] let d20 = 20, fill ~color:(Color.gray 0.8) triangle let d21 = 21, seq [fill ~color:(Color.gray 0.8) triangle; draw triangle] let d22 = let pen = Pen.scale two Pen.circle in 22, seq [fill ~color:(Color.gray 0.8) triangle; draw ~pen triangle] let d23 = let pen = Pen.scale two Pen.circle in 23, seq [draw ~pen triangle; fill ~color:(Color.gray 0.8) triangle] let d60 = let a = p ~scale:N.cm (0.,0.) in let b = p ~scale:N.cm ((-0.5), 1.) in let c = p ~scale:N.cm (2., 1.5) in let d = p ~scale:N.cm (1.5, 0.) in let pen = Pen.scale two Pen.circle in seq [ draw ~pen (jointpathp [a;d] [jControls b c]); draw ~color:(Co.gray 0.8) (pathp ~style:jLine [b;c]); H.draw_simple_arrow a b; H.draw_simple_arrow d c; ] let d111 = let a = Path.shift (p ~scale:N.cm (0.5, 0.)) (Path.scale (N.cm 2.) fullcircle) in let t = [T.rotated 120.] in let b = transform t a in let c = transform t b in seq (List.map (fun (color, p) -> fill ~color p) [ Co.red, a ; Co.green, b; Co.blue, c; Co.yellow, build_cycle [a;b]; Co.cyan, build_cycle [b;c]; Co.magenta, build_cycle [c;a]; Co.white, build_cycle [a;b;c] ] @ List.map draw [a;b;c]) let deuxpi = 2.*.3.14159 let d130 = let sq = path ~style:jLine ~scale:N.cm ~cycle:jLine [(0.,0.);(2.,0.);(2.,2.);(0.,2.)] in (** on peut pas utiliser la resolution de MetaPost donc on construit la transform à la main.. :-/ *) let ratio = sqrt (3.28 /. 4.) in let angle = atan (0.2 /. 1.8) *. 360. /. deuxpi in let v = pt (Num.cm 0.2, Num.cm 0.) in let t = [T.rotated angle; T.scaled (bp ratio); T.shifted v] in let rec apply acc = function 0 -> acc | n -> apply (transform t acc) (n-1) in let cmd i = let p = apply sq (2*i) in seq [fill ~color:(Color.gray 0.8) p; fill ~color:Color.white (transform t p)] in 130, iter 0 49 cmd let d140 = let cmd i = let s = 1. -. ((float_of_int i) *. 0.01) in fill ~color:(Color.gray s) (Path.scale (Num.cm (2.*.s)) fullcircle) in 140, seq [iter 0 99 cmd; draw ~pen:(Pen.scale two Pen.circle) (Path.scale (Num.cm 2.) fullcircle)] let d149 = let step = deuxpi /. 720. in let couleur x = let dblx = 2.*.x in if x > 0.5 then Color.rgb (dblx-.1.) 0. (2.-.dblx) else Color.rgb (1.-.dblx) 0. dblx in let pt angle = (2.*.sin(2.*.angle), 2.*.cos(3.*.angle)) in let pen = Pen.scale two Pen.circle in let cmd i = let angle = step *. (float_of_int i) in draw ~color:(couleur (angle /. deuxpi)) ~pen (path ~scale:N.cm [pt angle]) in 149,Command.iter 0 719 cmd let d195 = let n = 8 and u x = 5.*. (float_of_int x) in let un = u n and u1 = u 1 and udemi = (u 1) /. 5. in let color = Color.gray 0.8 in let t i j = T.shifted (pt (Num.mm (u i), Num.mm (u j))) in let row i = let col j = if (i+j) mod 2 = 1 then let strip k = let kf = (float_of_int k) *. udemi in let umk = u1 -. kf in let udp = kf +. udemi and udm = umk -. udemi in let l = if k mod 2 = 1 then [(kf,0.); (u1,umk); (u1,udm); (udp,0.)] else [(0.,kf); (umk,u1); (udm,u1); (0.,udp)] in fill ~color (transform [t i j] (path ~style:jLine ~scale:N.mm ~cycle:jLine l)) in Command.iter 0 4 strip else Command.nop in Command.iter 0 (n-1) col in let grid i = let ui = u i in seq [draw (path ~style:jLine ~scale:N.mm [(0.,ui); (un, ui)]); draw (path ~style:jLine ~scale:N.mm [(ui,0.); (ui, un)])] in 195, seq [Command.iter 0 (n-1) row; Command.iter 0 (n) grid] let d267 = let tex = tex ~stroke:(Some Color.black) in let rose = Color.rgb 1. 0.5 0.5 in let a = tex ~fill:rose ~style:RoundBox "D\\'ebut" in let b = Box.shift (cmp (2., 0.)) (tex ~fill:rose ~style:RoundBox "Fin") in let path angle a b = cut_after (bpath b) (cut_before (bpath a) (jointpathk [knotp ~r:(vec (dir angle)) (Box.ctr a); knotp ~r:(vec (dir (-. angle))) (Box.ctr b)] [jCurve])) in seq [Box.draw a; Box.draw b; Arrow.simple (path 45. a b); Arrow.simple (path (-135.) b a)] let min = -1. let max = 1. let b = cycle ~style:jLine (path ~style:jLine [(min,min);(max,min);(max,max);(min,max)]) (* Pour avoir une echelle *) let embed (id,p) = id,seq [p;draw b;fill ~color:Color.white b] let figs = [ d1; d2; d7; d12; d20; d21; d22; d23; 60, d60; d130; d140; d195; 267,d267; d4;d5; d149; (* 111, d111; *) ] let mpostfile = "othergraphs" let cairostfile = "testother_cairo" let texfile = "othergraphs.tex" let _ = Sys.chdir "test"; let nfig = List.map (fun (i,f) -> mpostfile^"-"^(string_of_int i), f) figs in if Cairost.supported then begin Mps.generate nfig; Cairost.generate_pdfs cairostfile figs; Generate.generate_tex_cairo texfile "othergraphs/mpost" "othergraphs" "testother_cairo" figs; end else begin Metapost.generate mpostfile nfig; Generate.generate_tex ~pdf:true texfile "othergraphs/mpost" "othergraphs" figs; end mlpost-0.8.2/papers/000077500000000000000000000000001306046515300143345ustar00rootroot00000000000000mlpost-0.8.2/papers/jfla2009/000077500000000000000000000000001306046515300155635ustar00rootroot00000000000000mlpost-0.8.2/papers/jfla2009/Makefile000066400000000000000000000021561306046515300172270ustar00rootroot00000000000000 all: hermann-pp.pdf PDFLATEX:=pdflatex -interaction="errorstopmode" WWW=/users/demons/filliatr/WWW main-pp.pdf: main-pp.tex biblio.bib figures.mp figmp.mps yannick1.mps florence.mps pdflatex $< bibtex main-pp pdflatex $< bibtex main-pp pdflatex $< pdflatex $< hermann-pp.pdf: hermann-pp.tex biblio.bib figures.mp figmp.mps yannick1.mps florence.mps $(PDFLATEX) $< # bibtex hermann-pp # $(PDFLATEX) $< # bibtex hermann-pp # $(PDFLATEX) $< # $(PDFLATEX) $< slides.pdf: slides.tex figures.mp alt_ergo.mp pdflatex $< %-pp.tex: pp.ml %.tex ocaml $^ > $@ wc: grep -iw frametitle slides.tex | wc -l %.mp: %.ml ../../_build/tool.native -ccopt "-I ../../" -pdf -latex main.tex $^ figmp.mps: figmp.mp mpost figmp.mp end mv figmp.1 figmp.mps yannick1.mps: yannick1.1 cp $^ $@ florence.mps: florence.1 cp $^ $@ main-pp.dvi: main-pp.tex latex $^ pp.ml: pp.mll ocamllex pp.mll print: main-pp.ps lpr $^ export: main-pp.pdf cp -f main-pp.pdf $(WWW)/publis/mlpost-fra.pdf clean: rm -f *~ *.aux *.log *.bbl *.blg *.mps rm -f main-pp.dvi main-pp.ps figures.mp rm -f mpxerr.dvi mpxerr.tex main-pp.pdf mlpost-0.8.2/papers/jfla2009/actes.sty000066400000000000000000000321411306046515300174240ustar00rootroot00000000000000% LaTeX Style for Actes de colloques % Version gnrique pour la srie ``Actes de colloques''. % In the documentation examples are given for the workshop WAGA, % ``International Workshop of Attribute Grammars and their Applications'' % P.Weis 2007. Gnration avec htmlc. % P.Weis entretien 2000 2001 2002 2003 2004 2005 2006. % P.Weis & E.Duris (01/99) Migration from jfla99 style to waga99 style. % P.Weis (change 98 en 99). Adaptation \`a Latex2e, documentation. % C.Queinnec (change 97 en 98) ainsi que le mois. % C.Queinnec (pour 97, parametre pour date) % B.Serpette (Guy Lapalme pour 96) % Origine: % Richard Furuta December 9, 1987 % (adapte pour Bigre - Ph Louarn & J.Andre 88-89, 91) % ---------------------------------------------------------------------- % Author's instructions % ---------------------------------------------------------------------- % In order to ease the proceedings publishing and the printout process, we ask % authors to respect the following instructions. Thanks for your attention. % % 1) create a directory named by the first author of your article % For instance: ``firstauthor'' % % 2) down-load this actes.sty file and put it into this directory. % % 3) in this directory, copy one of the latex squeleton files given below, % that you will fill in with your own latex text (see example in the % squeleton). Save this file with the same name. % For instance: ``firstauthor.tex'' % % 4) put into the directory ``firstauthor'' all other required files, for % instance postscript files for images and specific latex style files. % % 5) once the file ``firstauthor.tex'' is complete, and before the % real submission: % % - include your bibliography directly in your latex file (from the % .bbl file). % % - compile ``firstauthor.tex'' and verify the layout of your paper. % % - from the parent directory, create one single tar file % ``firstauthor.tar'' which contains all the files inside your % directory. Then, gzip and uuencode it. % For instance: % cd ..; tar cf firstauthor.tar ./firstauthor % gzip [--best] firstauthor.tar % uuencode firstauthor.tar.gz firstauthor.tar.gz > firstauthor.tar.gz.uu % % 6) Finally send this single tar file ``firstauthor.tar.gz.uu'' % to (colloque name address, for instance WAGA-subm@inria.fr), % before the (deadline). % %--------------------------------------------------------------------- % A squeleton (example) of your latex file ``firstauthor.tex'' % Copy this code as ``firstauthor.tex'' file and fill it. %--------------------------------------------------------------------- %% If you are writing in english and using new latex: latex2e % \documentclass[twoside]{article} % \usepackage{actes} % %% Title page... % \title{The title of your article} % \author{G. McHulott$^1$ % \& E. Massinture$^2$} % %% Headers for other pages... % \titlehead{Short title of your article} % for odd pages % \authorhead{McHulott \& Massinture} % for even pages % \affiliation{\begin{tabular}{rr} % for institute(s) % \\ 1: Laboratoire d'Informatique de l'\'Ecole UniTechnique, % \\ 99999 Petit Oiseau CEDEX, France % \\ {\tt mchulott@info.unitechnique.fr} % \\ 2: Universit\'e de Par-ici,CP 6666, Montr\'eal, Qu\'ebec, % \\ {\tt massinture@uparici.qc} % \end{tabular}} % % \begin{document} % \setcounter{page}{1} % \maketitle % % Here is the place for your text... % % % And do NOT FORGET to include your bibliography for submission % \begin{thebibliography}{10} % \bibitem{...} % \end{thebibliography} % % \pagebreak % \thispagestyle{colloquetitle} % \cleardoublepage % \end{document} %% If you are writing in english using old latex % \documentstyle[twoside,actes]{article} % %% Title page... % \title{The title of your article} % \author{G. McHulott$^1$ % \& E. Massinture$^2$} % %% Headers for other pages % \titlehead{Short title of your article} % for odd pages % \authorhead{McHulott \& Massinture} % for even pages % \affiliation{\begin{tabular}{rr} % for institute(s) % \\ 1: Laboratoire d'Informatique de l'\'Ecole UniTechnique, % \\ 99999 Petit Oiseau CEDEX, France % \\ {\tt mchulott@info.unitechnique.fr} % \\ 2: Universit\'e de Par-ici,CP 6666, Montr\'eal, Qu\'ebec, % \\ {\tt massinture@uparici.qc} % \end{tabular}} % % \begin{document} % \setcounter{page}{1} % \maketitle % % Here is the place for your text... % % % And do NOT FORGET to include your bibliography for submission % \begin{thebibliography}{10} % \bibitem{...} % \end{thebibliography} % % \pagebreak % \thispagestyle{colloquetitle} % \cleardoublepage % \end{document} % ---------------------------------------------------------------------- % End of author's instructions % ---------------------------------------------------------------------- %---------------------------------------------------------------------- % Mode d'emploi pour les auteurs. %---------------------------------------------------------------------- %% Si vous crivez en franais en utilisant latex2e, %% voici le squelette du corps de votre article sans le texte! % Si vous tes en Latex2e % \documentclass[twoside]{article} % \usepackage[latin1]{inputenc} % \usepackage[T1]{fontenc} % \usepackage{actes} % \usepackage{french} % \title{ le titre de votre article } % \author{G. McHulott$^1$ % \& E. Massinture$^2$} % % les titres de haut de pages % \titlehead{Titre de l'article en quelques mots}% a droite (page impaire) % \authorhead{McHulott \& Massinture}% a gauche (page paire) % \affiliation{\begin{tabular}{rr} % \\ 1: Laboratoire d'Informatique de l'\'Ecole UniTechnique, % \\ 99999 Petit Oiseau CEDEX, France % \\ {\tt mchulott@info.unitechnique.fr} % \\ 2: Universit\'e de Par-ici,CP 6666, Montr\'eal, Qu\'ebec, % \\ {\tt massinture@uparici.qc} % \end{tabular}} % % \begin{document} % \setcounter{page}{1} % \maketitle % Ici commence votre texte % % % La bibliographie % \begin{thebibliography}{10} % N'oubliez pas de l'inclure lors % \bibitem{...} % de votre soumission. % \end{thebibliography} % % \pagebreak % \thispagestyle{colloquetitle} % \cleardoublepage % \end{document} %% Si vous crivez en franais en utilisant le latex traditionnel, %% voici le squelette du corps de votre article sans le texte! % \documentstyle[french,frtypo,twoside,actes]{article} % \title{Le titre de votre article } % \author{G. McHulott$^1$ % \& E. Massinture$^2$} % les titres de haut de pages % \titlehead{Titre de l'article en quelques mots}% a droite (page impaire) % \authorhead{McHulott \& Massinture}% a gauche (page paire) % \affiliation{\begin{tabular}{rr} % \\ 1: Laboratoire d'Informatique de l'\'Ecole UniTechnique, % \\ 99999 Petit Oiseau CEDEX, France % \\ {\tt mchulott@info.unitechnique.fr} % \\ 2: Universit\'e de Par-ici,CP 6666, Montr\'eal, Qu\'ebec, % \\ {\tt massinture@uparici.qc} % \end{tabular}} % .... % \begin{document} % \setcounter{page}{1} % \maketitle % %Ici commence votre texte % % % La bibliographie % \begin{thebibliography}{10} % N'oubliez pas de l'inclure lors % \bibitem{...} % de votre soumission. % \end{thebibliography} % % \pagebreak % \thispagestyle{colloquetitle} % \cleardoublepage % \end{document} % ---------------------------------------------------------------------- % Editor's instructions % ---------------------------------------------------------------------- %% To fit to the colloque or conference at hand, you may have to change the %% following macros: % % Namecolloque, Namecolloqueplain % Yearcolloque, Yearcolloqueplain % Monthcolloque, the month of the colloque % % ---------------------------------------------------------------------- % End of Editor's instructions % ---------------------------------------------------------------------- % LaTeX Style for Actes de colloques % beginning of actes.sty \def\Namecolloque{JFLA} \def\Namecolloqueplain{Journ\'ees Francophones des Langages Applicatifs} \def\Yearcolloque{09} \def\Yearcolloqueplain{2009} \def\Monthcolloque{janvier} \ds@twoside %%%%%%%%%%%%%%%%%%%% The sizes %%%%%%%%%%%%%%%%%%%% \oddsidemargin 0.21cm % (21 - (2*2.54) - textwidth)/2 \evensidemargin 0.21cm \marginparwidth 0cm \marginparsep 0pt \topmargin 0.7cm \headheight 0cm \headsep 0.5cm \textheight 22cm \textwidth 15.5cm \topskip 0.7cm \footskip 0.7cm %\footnotesep 8.4pt \parindent 0.5cm \parskip 0.1cm \hfuzz2pt \tolerance3500 \pretolerance3500 \hbadness10000 \hyphenpenalty50 \exhyphenpenalty50 %%%%%%%%%%%%%%%%%%%% Style of the first page of each paper %%%%%%%%%%%%%%%%%%%% \def\DateC#1{\gdef\D@teC{#1}} \DateC{\Monthcolloque{} \Yearcolloqueplain{} -- \Namecolloqueplain{} -- \Namecolloque\Yearcolloque{}% } \def\ps@colloquetitle{\let\@mkboth\@gobbletwo% \def\@oddhead{ \vbox to\headheight {\vfil \hbox to\headwidth{\footnotesize \D@teC} \vskip 4pt \hbox to\headwidth{\hrulefill} }} \def\@oddfoot{\rm\hfil\thepage\hfil} \let\@evenhead\@oddhead \let\@evenfoot\@oddfoot} \thispagestyle{colloquetitle} %%%%%%%%%%%%%%%%%%%% Style of other pages %%%%%%%%%%%%%%%%%%%% \def\authorhead#1{\gdef\@authorhead{#1}} \def\titlehead#1{\gdef\@titlehead{#1}} \newlength{\headwidth}\setlength{\headwidth}{\textwidth} \addtolength{\headwidth}{-1pt} \def\ps@colloque{\let\@mkboth\@gobbletwo% \def\@oddhead{ \vbox to\headheight {\vfil \hbox to\headwidth{\rm\normalsize\hfil{\@titlehead}} \vskip 4pt \hbox to\headwidth{\hrulefill} }} \def\@oddfoot{\rm\hfil\thepage\hfil} \def\@evenhead{ \vbox to\headheight {\vfil \hbox to\headwidth{\rm\normalsize{\@authorhead}\hfil} \vskip 4pt \hbox to\headwidth{\hrulefill} }} \let\@evenfoot\@oddfoot} %%%%%%%%%%%%%%%%%%%% Title %%%%%%%%%%%%%%%%%%%% \def\affiliation#1{\gdef\@affiliation{#1}} \def\titlesize{\@setsize\titlesize{25pt}\xxpt\@xxpt} % title large \def\authsize{\@setsize\authsize{14pt}\xipt\@xipt} % author size \def\affilsize{\@setsize\affilsize{12pt}\xpt\@xpt} % affiliation % title needs adjusting, no date in title \def\@maketitle{\newpage \null \vspace*{-20pt} \begin{flushright} {\titlesize \@title \par} \vskip 10pt % Vertical space after title. 8pt \hrule height 1.5pt % one point rule \vskip 14pt % 14 points below rule (adjusted for baseline) {\authsize \@author \par} % there should be 18 pts between author and affiliation baselines \vskip 6pt % Vertical space after author. 18pt - 6pt {\affilsize\it \@affiliation \par} \end{flushright} \par \vskip 16pt} % Vertical space after title. 26pt - 10pt \def\maketitle{\par \begingroup \def\thefootnote{\fnsymbol{footnote}} \def\@makefnmark{\hbox to 0pt{$^{\@thefnmark}$\hss}} \if@twocolumn \twocolumn[\@maketitle] \else \newpage \global\@topnum\z@ \@maketitle \fi\thispagestyle{colloquetitle}\@thanks \endgroup \setcounter{footnote}{0} \let\maketitle\relax \let\@maketitle\relax \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\let\thanks\relax} %%%%%%%%%%%%%%%%%%%% environnement "abst" %%%%%%%%%%%%%%%%%%%% \def\abstsize{\@setsize\abstsize{11pt}\viiipt\@viiipt} % for abstract \def\abst{\list{}{\leftmargin0pc}\abstsize\item[]} \def\endabst{\endlist\vskip-7pt} %%%%%%%%%%%%%%%%%%%% need a period after section numbers %%%%%%%%%%%%%%%%%%%% \def\@sect#1#2#3#4#5#6[#7]#8{\ifnum #2>\c@secnumdepth \def\@svsec{}\else \refstepcounter{#1}\edef\@svsec{\csname the#1\endcsname{.}\hskip 1em }\fi \@tempskipa #5\relax \ifdim \@tempskipa>\z@ \begingroup #6\relax \@hangfrom{\hskip #3\relax\@svsec}{\interlinepenalty \@M #8\par} \endgroup \csname #1mark\endcsname{#7}\addcontentsline {toc}{#1}{\ifnum #2>\c@secnumdepth \else \protect\numberline{\csname the#1\endcsname}\fi #7}\else \def\@svsechd{#6\hskip #3\@svsec #8\csname #1mark\endcsname {#7}\addcontentsline {toc}{#1}{\ifnum #2>\c@secnumdepth \else \protect\numberline{\csname the#1\endcsname}\fi #7}}\fi \@xsect{#5}} \pagestyle{colloque} \thispagestyle{colloquetitle} \def\abstractname{R\'esum\'e} \def\refname{Bibliographie} \endinput % end of actes.sty mlpost-0.8.2/papers/jfla2009/alt_ergo.ml000066400000000000000000000023021306046515300177060ustar00rootroot00000000000000 open Mlpost open Num open Box open Color let fill = rgb8 253 215 117 let node s = round_rect ~stroke:None ~name:s (round_rect ~fill (tex ("\\sf " ^ s))) let hbox = hbox ~padding:(bp 20.) let vbox = vbox ~padding:(bp 20.) let alt_ergo = let b1 = vbox [hbox [node "SMT parser"; node "Why parser"]; node "Typing"] in let b2 = round_rect ~dx:(bp 20.) ~dy:(bp 5.) ~fill:(color "blanched almond") (hbox ~pos:`Bot [vbox [node "SAT-solver"; hbox [node "Matching"; node "CC(X)"]]; vbox [tex "\\sf main loop"; node "UF(X)"]]) in let c_typing = ctr (get "Typing" b1) in let c_sat = ctr (get "SAT-solver" b2) in let v = Point.add (Point.sub c_sat c_typing) (Point.pt (zero, bp 40.)) in let b = group [shift v b1; b2] in let arrow x y = Helpers.box_arrow (get x b) (get y b) in [draw b; arrow "SMT parser" "Typing"; arrow "Why parser" "Typing"; arrow "Typing" "SAT-solver"; arrow "SAT-solver" "Matching"; arrow "SAT-solver" "CC(X)"; arrow "Matching" "CC(X)"; arrow "CC(X)" "UF(X)"; ] let () = Metapost.emit "alt_ergo" (Command.seq alt_ergo) (* Local Variables: compile-command: "mlpost -latex slides.tex -xpdf alt_ergo.ml" End: *) mlpost-0.8.2/papers/jfla2009/bardou-mac.tex000066400000000000000000001552131306046515300203260ustar00rootroot00000000000000\documentclass[nofirstpagebreak,empty,11pt]{studia-Hermann2} %\documentclass[nofirstpagebreak,empty,cropmarks]{studia-Hermann} %\usepackage[applemac]{inputenc} %\usepackage[german,french]{babel} \usepackage[applemac]{inputenc} %%% Commandes spcifiques l'article \newcommand{\cfsect}[1]{(\textit{cf.} section~\ref{#1})} \newcommand{\cfsectpage}[1]{(\textit{cf.} section~\ref{#1}, page~\pageref{#1})} \providecommand{\figureref}[1]{\figname~\ref{#1}} \providecommand{\cftab}[1]{(\textit{cf.} tableau~\ref{#1})} \newcommand{\cmd}[1]{{\upshape\texttt{\symbol{"5C}#1}}} %=============================================================== \usepackage[top=1.5cm, left=2cm, right=2cm, bottom=2cm]{geometry} \geometry{paperwidth=15cm, paperheight=22cm} \usepackage[cross,a4,center]{crop} %====================================================== \usepackage{alltt,url,graphicx} \usepackage[french]{babel} \usepackage{mflogo} \usepackage{tikz} % macros \newcommand{\ocaml}{OCaml} \newcommand{\camllight}{Caml Light} \newcommand{\asymptote}{\textsf{Asymptote}} \newcommand{\mlpost}{\textsc{Mlpost}} \newcommand{\metapost}{\MP} \newcommand{\fmpost}{\textit{functional} \metapost} \newcommand{\metafont}{\MF} \newcommand{\nomdetikz}{\textsf{TikZ}} \newcommand{\pstricks}{\textsf{PSTricks}} \newcommand{\dia}{\textsf{Dia}} \newcommand{\xfig}{\textsf{Xfig}} \newcommand{\postscript}{PostScript} \newcommand{\mlpictex}{mlP\hspace{-0.2em}\raisebox{-0.2em}{i}\hspace{-0.1em}c\hspace{-0.1em}\TeX} \proceedings{JFLA09}{-} \title[Faire bonne figure avec \mlpost]{Faire bonne figure avec \mlpost} \author{R. Bardou \andauthor J.-C. Fillitre \andauthor J. Kanig \andauthor S. Lescuyer} \address{ ProVal / INRIA Saclay -- le-de-France\\ 91893 Orsay Cedex, France\\ LRI / CNRS -- Universit Paris Sud\\ 91405 Orsay Cedex, France\\[3pt] {\tt \{bardou,filliatr,kanig,lescuyer\}@lri.fr} } \resume{Cet article prsente \mlpost, une bibliothque \ocaml\ de dessin scientifique. Elle s'appuie sur \metapost, qui permet notamment d'inclure des fragments \LaTeX\ dans les figures. \ocaml\ offre une alternative sduisante aux langages de macros \LaTeX, aux langages spcialiss ou mme aux outils graphiques. En particulier, l'utilisateur de \mlpost\ bnficie de toute l'expressivit d'\ocaml\ et de son typage statique. Enfin \mlpost\ propose un style dclaratif qui diffre de celui, souvent impratif, des outils existants.} \abstract{This article introduces \mlpost, an \ocaml\ library for scientific drawing. It is based on \metapost, which allows inclusion of \LaTeX\ fragments. \ocaml\ is an appealing alternative to \LaTeX\ macro languages, dedicated languages and even to graphic tools. In particular, \mlpost\ users benefit from \ocaml's expressiveness and static typing. Finally, \mlpost\ features a declarative style, which differs from the imperative style of most existing tools. } \motscles{dessin scientifique, programmation fonctionnelle, \metapost, \ocaml} \keywords{scientific drawing, functional programming, \metapost, \ocaml} % \title{Faire bonne figure avec \mlpost} % \author{R. Bardou$^1$ % \& J.-C. Fillitre$^1$ % \& J. Kanig$^1$ % \& S. Lescuyer$^1$} % \titlehead{Faire bonne figure avec \mlpost}% a droite (page impaire) % \authorhead{Bardou \& Fillitre \& Kanig \& Lescuyer}% a gauche (page paire) % \affiliation{\begin{tabular}{rr} % \\ 1: ProVal / INRIA Saclay -- Île-de-France % \\ 91893 Orsay Cedex, France % \\ LRI / CNRS -- Universit Paris Sud % \\ 91405 Orsay Cedex, France % \\ {\tt \{bardou,filliatr,kanig,lescuyer\}@lri.fr} % \end{tabular}} \begin{document} \maketitle % \begin{abstract} % Cet article prsente \mlpost, une bibliothque \ocaml\ de dessin % scientifique. Elle s'appuie sur \metapost, qui permet notamment % d'inclure des fragments \LaTeX\ dans les figures. \ocaml\ offre une % alternative sduisante aux langages de macros \LaTeX, aux langages % spcialiss ou mme aux outils graphiques. En particulier, % l'utilisateur de \mlpost\ bnficie de toute l'expressivit % d'\ocaml\ et de son typage statique. Enfin \mlpost\ propose un style % dclaratif qui diffre de celui, souvent impratif, des outils existants. % \end{abstract} % TODO ? : expliquer comment fait \metapost pour inclure du \LaTeX % TODO : expliquer les labels \section{Introduction} Lors de la rdaction de documents nature scientifique (articles, cours, livres, etc.), il est trs souvent ncessaire de raliser des figures. Ces figures permettent d'agrmenter le texte en illustrant aussi bien les objets dont il est question dans le document que les liens qui existent entre eux et facilitent ainsi leur comprhension. Elles sont donc un composant fondamental au caractre didactique de tels documents, mais leur ralisation est souvent fastidieuse. En particulier, il est souvent ncessaire d'y inclure des lments mis en forme par \LaTeX\ (formules, etc.), ce que bon nombre de logiciels de dessin ne permettent pas. Ainsi, on peut souhaiter raliser un schma tel que celui-ci \begin{center} \includegraphics[width=\textwidth]{yannick1.mps} \end{center} en attachant de l'importance au fait que des expressions comme $a_1+s_1-1$ apparaissent exactement comme dans le corps du document. Il existe plusieurs familles d'outils pour raliser des figures intgrer dans un document \LaTeX~: \begin{itemize} \item des interfaces graphiques disposant d'une sortie \LaTeX, telles que \dia~\cite{dia} ou \xfig~\cite{xfig} ; \item des bibliothques \LaTeX, telles que \pstricks~\cite{pstricks} ou encore \nomdetikz~\cite{tikz} ; \item des outils externes en ligne de commande, tel que \metapost~\cite{metapost}. \end{itemize} % Il faudrait d'ailleurs dj que ces logiciels de dessin soient vectoriels % ce qui n'est pas forcment le cas. Chaque famille a ses avantages et ses inconvnients. Les interfaces graphiques sont les plus accessibles, notamment pour un placement rapide et intuitif des diffrents lments de la figure, mais l'intgration de texte mis en forme par \LaTeX\ est dlicate. Dans le cas de \xfig\ et de \dia, la taille des lments \LaTeX\ n'est pas connue lors de l'dition de la figure ; en outre, dans le cas de \dia, l'intgration de \LaTeX\ dans une figure ncessite de l'exporter sous forme de macros \nomdetikz\ et d'diter le rsultat. %% TODO : RAPPELER QUE PSTRICKS NE MARCHE PAS AVEC PDFLATEX ! Les bibliothques \LaTeX\ telles que \pstricks\ ou \nomdetikz\ offrent l'intgration la plus naturelle avec \LaTeX. En particulier, elles permettent de combiner arbitrairement lments graphiques et textes \LaTeX\ \begin{tikzpicture}[baseline=(a.base)] \path[use as bounding box] (0,0) node[draw,style=dashed] (a) {comme ceci}; \draw[->] (a) .. controls +(-2cm,1cm) and +(-2cm,-0cm) .. (a); \end{tikzpicture}. En revanche, elles demandent d'apprendre un certain nombre de macros et de notations et souffrent surtout des dfauts inhrents \LaTeX~: \begin{itemize} \item des erreurs dtectes uniquement l'interprtation, peu claires et parfois mal localises ; \item un langage \emph{de programmation} peu commode (syntaxe obscure, absence de typage, code difficile structurer). \end{itemize} Ces inconvnients sont notamment un frein au dveloppement de bibliothques de haut niveau au dessus de ces langages ainsi qu' la rutilisation de figures. \metapost\ se prsente comme une alternative ces bibliothques \LaTeX, en proposant un langage de programmation part entire spcialis dans la construction de figures contenant des lments \LaTeX. Il permet notamment de manipuler symboliquement la taille et la position de ces lments et de les relier de manire implicite par des quations. En revanche, le langage de \metapost\ s'inspire de celui de \metafont~\cite{metafont} et prsente, l'exception de la syntaxe, les dfauts soulevs ci-dessus. La figure~\ref{fig:metapost} donne un exemple de programme/figure ralis avec \metapost. \begin{figure}[t] \vspace*{1em} \begin{minipage}{.3\linewidth} \includegraphics{figmp.mps} \end{minipage} \begin{minipage}{.7\linewidth} \small \begin{alltt} vardef koch(expr A,B,n) = save C; pair C; C = A rotatedaround(1/3[A,B], 120); if n>0: koch( A, 1/3[A,B], n-1); koch( 1/3[A,B], C, n-1); koch( C, 2/3[A,B], n-1); koch( 2/3[A,B], B, n-1); else: draw A--1/3[A,B]--C--2/3[A,B]--B; fi; enddef; z0=(4cm,0); z1=z0 rotated 120; z2=z1 rotated 120; koch( z0, z1, 4 ); koch( z1, z2, 4 ); koch( z2, z0, 4 ); \end{alltt} \end{minipage} \caption{Exemple de figure \metapost}\label{fig:metapost} \end{figure} % Dans un souci d'exhaustivit, nous devons aussi mentionner % \asymptote~\cite{asymptote}, galement un langage ddi la cration % de figures. Nous n'allons pas rentrer dans les dtails de cet outil % car nous ne considrons plus les langages ddis par la suite. Une alternative sduisante aux solutions prcdentes consiste utiliser un langage de programmation existant. Ainsi l'utilisateur n'a pas apprendre un langage spcialis et il bnficie d'autre part de tous les avantages d'un langage de programmation moderne : erreurs dtectes la compilation, types de donnes complexes, structuration, etc. Toute la difficult rside alors dans la manipulation des lments \LaTeX, notamment la prise en compte de leur taille dans l'laboration de la figure. Si on considre la famille des langages fonctionnels, on peut citer au moins deux exemples de telle intgration : \begin{itemize} \item \mlpictex~\cite{mlpictex} est\footnote{\`{A} notre connaissance, \mlpictex\ n'est plus distribu.} un ensemble de macros \LaTeX\ permettant d'inclure du code \camllight\ arbitraire dans un document \LaTeX. Ce code s'appuie sur une bibliothque de dessin \postscript~\cite{postscript} et peut faire rfrence des lments \LaTeX, ainsi qu' leur taille. \item \fmpost~\cite{fmpost} est une bibliothque Haskell~\cite{haskell} produisant du code \metapost. C'est une approche lgre qui rutilise les capacits graphiques de \metapost\ et substitue Haskell au langage de programmation de \metapost. \end{itemize} Cet article prsente \mlpost, un outil qui adopte l'approche de \fmpost\ en utilisant \ocaml~\cite{ocaml} comme langage hte. La premire partie de l'article prsente les choix de conception de \mlpost\ travers un certain nombre d'exemples. La seconde partie dtaille ensuite l'architecture logicielle de \mlpost. \mlpost\ est librement distribu l'adresse \url{http://mlpost.lri.fr}. Toutes les figures de cet article ont t faites avec \mlpost, l'exception des exemples pour \metapost\ et \nomdetikz. %%% CONS % pas de baseline % pas de mlange entre LaTeX et les graphiques \section{Principes et exemples}\label{exemples} \subsection{Principes} \subsubsection{Botes.} Les briques de base de \mlpost\ sont les \textit{botes} : une bote est un moyen d'encapsuler n'importe quel lment de dessin au sein d'un contour, qui peut tre effectivement trac ou non. On peut construire la bote vide, des botes avec du \LaTeX\ arbitraire, etc. Ces botes peuvent ensuite tre manipules : imbrication arbitraire, placement une position prcise, alignement de plusieurs botes, flches reliant plusieurs botes entre elles, cration de tableaux, etc. Plusieurs botes peuvent aussi tre regroupes au sein d'une seule afin de pouvoir les dplacer ensemble. L'exemple suivant montre deux botes simples, la deuxime tant dplace un centimtre vers la droite en utilisant la fonction \verb|shift|. \medskip \begin{minipage}%{0.18\linewidth} {0.15\linewidth} \includegraphics{simple.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{alltt} [ Box.draw (Box.tex "\ensuremath{\backslash}\ensuremath{\backslash}LaTeX"); Box.draw (Box.shift(Point.pt (cm 1.,zero)) (circle (empty ()))) ] \end{alltt} \end{minipage} \medskip\noindent Une figure \mlpost\ est simplement une liste de commandes de dessin. Ci-dessus, elle est rduite deux occurrences de \texttt{Box.draw}, la commande qui dessine une bote. % Notez que par dfaut, le contour de la bote contenant du \LaTeX n'a % pas t trac, alors que celui de la bote vide a t trac. \subsubsection{Placement relatif.} Un principe que nous avons suivi lors de la conception de \mlpost{} est de favoriser un placement relatif des objets plutt qu'absolu. Ceci permet d'obtenir des figures plus robustes. En effet, imaginons que l'on veuille placer une bote $A$ \emph{droite} d'une bote $B$. Une premire possibilit serait de spcifier les positions approximativement, par exemple en donnant les abscisses 0 cm pour $A$ et 2 cm pour $B$. Cependant, si on change d'avis sur le contenu de $A$ et que la taille de cette bote change, $A$ risque alors de se superposer $B$. Il faut alors replacer toutes les botes de la figure manuellement. Pour viter a, \mlpost\ propose diverses mthodes pour placer les botes \emph{les unes par rapport aux autres}. On gagne alors du temps lors de la cration et lors des modifications de la figure. L'exemple suivant utilise l'alignement horizontal \verb|hbox|, o l'argument optionnel \texttt{padding} permet de spcifier l'espacement horizontal entre deux botes : \medskip \begin{minipage}{0.2\linewidth} \includegraphics{align.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{alltt} [ Box.draw (Box.hbox ~padding:(cm 1.) [Box.tex "\ensuremath{\backslash}\ensuremath{\backslash}LaTeX"; circle (empty ())]) ] \end{alltt} \end{minipage} \medskip\noindent Nous revenons plus en dtail sur les botes et leur implmentation dans la section~\ref{subsec:boxes}. \subsubsection{Persistance.} Un autre choix que nous avons fait est celui de la persistance~\cite{persistance} : lorsqu'un attribut d'une bote (positionnement, couleur, etc.) est modifi, on obtient une nouvelle bote, identique la premire sauf en l'attribut chang. En faisant le choix de structures de donnes persistantes, nous permettons l'ancienne bote, avec ses attributs inchangs, d'tre prserve et encore accessible. Ainsi, on peut rutiliser plus facilement une bote plusieurs endroits du dessin, avec des attributs diffrents. Dans l'exemple suivant, on a utilis trois instances de la mme bote \texttt{b}, dont le contour est trac pour la deuxime. \medskip \begin{minipage}{0.19\linewidth} \includegraphics{persistance.mps} \end{minipage} \begin{minipage}{0.78\linewidth} \small\begin{alltt} let b = Box.hbox ~padding:(cm 1.) [Box.tex "\ensuremath{\backslash}\ensuremath{\backslash}LaTeX"; circle (empty ())] in [ Box.draw (Box.vbox [b; set_stroke Color.black b; b]) ] \end{alltt} \end{minipage} %TODO exemple ici qui introduit les noms des boites et les avantages / %inconvnients de la persistance \subsection{Exemples} Dans cette section, nous montrons quelques applications immdiates des botes de \mlpost. % blocs mmoire (listes, etc.) -- JCF % introduire Box.vblock % introduire les noms de boites \subsubsection{Reprsentation de la mmoire.} Un besoin rcurrent lorsque l'on enseigne l'algorithmique ou les concepts lis un langage de programmation consiste illustrer la structure des donnes en mmoire par des schmas de la forme \begin{center} \includegraphics{list123.mps} \end{center} Deux lments sont ncessaires : le dessin des blocs d'une part et le dessin des pointeurs d'autre part. Pour raliser les blocs, on utilise la fonction \texttt{Box.hblock} qui aligne des botes horizontalement, leur donne une hauteur commune et trace leur contour. Voici un exemple : \medskip \begin{minipage}{0.15\linewidth} \includegraphics{simple_block.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{alltt} let b = Box.hblock ~pos:`Bot [Box.tex "a"; Box.tex "b"; Box.tex "C"] in [ Box.draw b ] \end{alltt} \end{minipage} \medskip\noindent \`{A} l'aide de \texttt{Box.hblock}, on peut facilement crire une fonction \texttt{cons} qui construit un bloc de taille 2, dont le premier lment contient un texte \LaTeX\ arbitraire \texttt{hd} et le second est soit vide, soit le symbole $\bot$, selon la valeur du boolen \texttt{tl} : \begin{alltt} let cons hd tl = let p1 = Box.tex ~name:"hd" hd in let p2 = Box.tex ~name:"tl" (if tl then "" else "\ensuremath{\backslash}\ensuremath{\backslash}ensuremath\{\ensuremath{\backslash}\ensuremath{\backslash}bot\}") in Box.hblock [p1; p2] \end{alltt} L'argument optionnel \texttt{\~{}name} permet de nommer les sous-botes, de manire pouvoir y accder facilement par la suite. \'Ecrivons maintenant une fonction \texttt{pointer\_arrow} pour matrialiser les pointeurs. Il s'agit de tracer une flche entre deux botes donnes \texttt{a} et \texttt{b}. Pour cela, on commence par construire un chemin \texttt{p} reliant les centres de \texttt{a} et \texttt{b}, que l'on tronque l'endroit o il intersecte le bord de la bote \texttt{b} (avec la fonction \texttt{Path.cut\_after}). Puis on trace l'origine de la flche l'aide d'un chemin rduit un point (le centre de \texttt{a}) et la flche proprement dite l'aide du chemin \texttt{p}. \medskip \begin{minipage}{0.15\linewidth} \includegraphics{block_arrow.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{alltt} let pointer_arrow a b = let p = pathp [Box.ctr a; Box.ctr b] in let p = Path.cut_after (Box.bpath b) p in let pen = Pen.scale (bp 4.) Pen.circle in Command.draw ~pen (pathp [Box.ctr a]) ++ draw_arrow p \end{alltt} \end{minipage} %XXX virer ++ ? \medskip\noindent On utilise ici le symbole infixe \texttt{++} qui permet de concatner des commandes de dessin. On utilise d'autre part \texttt{bp}, qui est une unit propre \metapost, proche du point \postscript. Nous avons maintenant tous les lments ncessaires pour crire une fonction \texttt{draw\_list} qui prend en argument une liste \ocaml\ de fragments \LaTeX\ et ralise l'illustration correspondante. On commence par construire les diffrents blocs constituant la liste : \begin{alltt} let draw_list l = let rec make = function | [] \ensuremath{\rightarrow} [] | [x] \ensuremath{\rightarrow} [cons x false] | x :: l \ensuremath{\rightarrow} cons x true :: make l in \end{alltt} Puis on aligne ces blocs avec \texttt{Box.hbox}, en insrant de l'espace horizontal avec l'option \texttt{padding} : \begin{alltt} let l = hbox ~padding:(bp 30.) (make l) in \end{alltt} Pour dessiner les pointeurs, il suffit de parcourir la liste des botes (qui ont t places) et d'utiliser la fonction \texttt{pointer\_arrow} prcdente sur chaque paire de botes conscutives : \begin{alltt} let rec arrows = function | [] | [\_{}] \ensuremath{\rightarrow} nop | b1 :: (b2 :: \_{} as l) \ensuremath{\rightarrow} {\small pointer_arrow(Box.get "tl" b1)(Box.get "hd"b2) } ++ arrows l in \end{alltt} On utilise ici la fonction \texttt{Box.get} qui permet de rcuprer une sous-bote par son nom. On accde ainsi aux botes nommes respectivement \verb!"hd"! et \verb!"tl"! qui ont t cres par la fonction \texttt{cons} puis encapsules dans d'autres botes par les fonctions d'alignement. Enfin, on dessine les botes avec \texttt{Box.draw}, puis les flches avec la fonction \texttt{arrows} : \begin{alltt} [ Box.draw l;arrows (Array.to_list (Box.elts l))] \end{alltt} On peut tester avec \begin{alltt} draw_list {\small(List.map (fun n \ensuremath{\rightarrow} Printf.sprintf "$\ensuremath{\backslash}\ensuremath{\backslash}sqrt\{\%{}d\}$" n) [1;2;3;4])} \end{alltt} qui donne bien le rsultat attendu : \begin{center} \includegraphics{another_list.mps} \end{center} % De manire gnrale, les % fonctions \texttt{Box.tex} et \texttt{Box.box}, ainsi que toutes les % autres fonctions de cration de botes, disposent d'arguments % optionnels \texttt{dx} et \texttt{dy} permettant de spcifier les % marges sparant le contenu du contour de la bote. \subsubsection{Diagrammes de classes.} Avec la fonction \texttt{Box.vblock}, analogue pour l'alignement vertical de la fonction \texttt{Box.hblock} introduite ci-dessus, il est facile de dessiner des diagrammes UML. Supposons que l'on veuille dessiner des schmas de classes tels que : \begin{center} \includegraphics{uml_client.mps} \end{center} Pour cela, introduisons une fonction \texttt{classblock} qui attend le nom de la classe ainsi que la liste des attributs et des mthodes. \begin{alltt} let classblock name attr_list method_list = let vbox = Box.vbox ~pos:`Left in Box.vblock ~pos:`Left ~name [ tex ("\{\ensuremath{\backslash}\ensuremath{\backslash}bf " ^ name ^ "\}"); vbox (List.map tex attr_list); vbox (List.map tex method_list) ] \end{alltt} Ici, le nom \texttt{name} de la classe est utilis la fois pour dsigner le schma dans le diagramme (l'argument labelis \url{~name} de \texttt{Box.vblock}) et comme titre du schma cr. Les attributs et les mthodes sont aligns verticalement indpendamment, puis on aligne le titre et les deux nouvelles botes obtenues en les encadrant\footnote{Notez qu'au contraire de {\tt hbox} et {\tt vbox}, les fonctions {\tt hblock} et {\tt vblock} tracent par dfaut le contour de leurs sous-botes.}. On peut maintenant s'en servir pour dessiner un petit diagramme de classes : \medskip \begin{minipage}{0.3\linewidth} \includegraphics[width=0.9\linewidth]{uml.mps} \end{minipage} \begin{minipage}{0.6\linewidth} \small\begin{alltt} let a = classblock "BankAccount" [ "balance : Dollars = $0$"] [ "deposit ..."; ... ] in let b = classblock "Client" [ "name : String"; ...] [] in let diag = Box.vbox ~padding:(cm 1.) [a;b] in [ Box.draw diag; box_label_arrow ~pos:`Left (Picture.tex "owns") (get "Client" diag) (get "BankAccount" diag) ] \end{alltt} \end{minipage} \vspace{1em} Ici, on a d'abord cr deux schmas de classe avec la fonction \texttt{classblock}. Ces schmas sont ensuite aligns verticalement, et une flche avec une tiquette est dessine entre ces deux classes avec \texttt{box\_label\_arrow}. Le code pour cette figure est conceptuellement trs simple, ne contient aucun placement absolu et ne dpasse pas les 15 lignes de code. % automate -- RB \subsubsection{Automates.}\label{sec:automates} La thorie des langages est un domaine o l'on a rapidement besoin de dessiner des automates. Illustrons une faon d'utiliser \mlpost\ dans ce but. Nous allons dfinir les fonctions suivantes : \begin{itemize} \item \texttt{state} pour crer un tat ; \item \texttt{final} pour transformer un tat en un tat final ; \item \texttt{initial} pour dessiner une flche entrante sur un tat initial ; \item \texttt{transition} pour dessiner une transition d'un tat un autre ; \item \texttt{loop} pour dessiner une transition d'un tat vers lui-mme. \end{itemize} On choisit de reprsenter les tats par des botes \mlpost. La fonction \texttt{state} est juste une sp\-ci\-ali\-sa\-tion de la fonction {\tt Box.tex} un contour circulaire, dfinie par l'application partielle suivante: \begin{alltt} let state = Box.tex ~style:Circle ~stroke:(Some Color.black) \end{alltt} Le paramtre \texttt{stroke} permet de spcifier si le contour doit tre trac et, le cas chant, dans quelle couleur. De manire similaire, la fonction \texttt{final} est une spcialisation de la fonction {\tt Box.box} dont le rle consiste rajouter un cercle autour d'une bote : \begin{alltt} let final = Box.box ~style:Circle \end{alltt} On peut dj placer des tats, finaux ou non, et les dessiner. Pour le placement, on utilise les fonctions d'alignement horizontal et vertical \texttt{Box.hbox} et \texttt{Box.vbox}. On suit donc le principe consistant placer les objets de faon relative, les uns par rapport aux autres. \begin{minipage}{0.15\linewidth} \vspace{1em} \includegraphics{automate_1.mps} \end{minipage} \begin{minipage}{0.7\linewidth} \begin{alltt} let states = Box.vbox ~padding:(cm 0.8) [ Box.hbox ~padding:(cm 1.4) [ state ~name:"alpha" "$\ensuremath{\backslash}\ensuremath{\backslash}alpha$"; state ~name:"beta" "$\ensuremath{\backslash}\ensuremath{\backslash}beta$" ]; final ~name:"gamma" (state "$\ensuremath{\backslash}\ensuremath{\backslash}gamma$") ] in [ Box.draw states ] \end{alltt} \end{minipage} \medskip\noindent On note que l'ensemble des tats est lui-mme une bote, \texttt{states}, contenant les tats comme autant de sous-botes nommes. La fonction \texttt{initial} appose une flche entrante un tat. Il s'agit donc d'une fonction qui prend le nom d'un tat \texttt{q} et qui renvoie une commande dessinant une flche vers \texttt{q}. On pourrait aussi renvoyer une bote sans contour contenant \texttt{q} et la flche, ce qui permettrait d'utiliser \texttt{initial} de la mme faon que \texttt{final}. Cependant, la bote obtenue n'aurait pas la mme taille et la mme forme que \texttt{q}, ce qui poserait des problmes pour placer \texttt{q} ou pour dessiner des transitions vers ou partir de \texttt{q}. \begin{alltt} let initial (states : Box.t) name : Command.t = let q = Box.get name states in let p = Box.west q in Arrow.draw (Path.pathp [Point.shift p(Point.pt(cm (-0.3),zero)); p]) \end{alltt} La fonction accde la bote \texttt{q} par son nom \texttt{name} dans la bote \texttt{states} et dtermine le point d'arrive de la flche avec \texttt{Box.west}. On pourrait gnraliser cette fonction pour spcifier la position de la flche. La fonction \texttt{transition} dessine une flche d'un tat un autre. Cette fonction prend deux arguments optionnels \texttt{outd} et \texttt{ind} pour spcifier, en degrs, la direction sortante et la direction entrante de la flche. On doit les convertir en vecteurs directeurs pour les passer\footnote{Nous utilisons ici une fonctionnalit d'\ocaml{} qui permet d'accder des arguments optionnels sans spcifier leur valeur par dfaut, sous la forme d'un type {\tt option}. Nous passons ensuite directement ces valeurs de type {\tt option}, en tant qu'arguments optionnels, la fonction {\tt cpath} par la syntaxe {\tt cpath ?outd ?ind x y}.} \texttt{cpath}, qui calcule un chemin allant du bord d'une bote au bord d'une autre bote. Ce chemin est ensuite donn la fonction \texttt{Arrow.draw} qui trace la flche en plaant une tiquette \texttt{tex} la position \texttt{pos}. {\small \begin{alltt} let transition states tex pos?outd?ind x_name y_name = let x = Box.get x_name states and y = Box.get y_name states in let outd = match outd with | None \ensuremath{\rightarrow} None | Some a \ensuremath{\rightarrow} Some (vec (dir a)) in let ind = match ind with | None \ensuremath{\rightarrow} None | Some a \ensuremath{\rightarrow} Some (vec (dir a)) in Arrow.draw ~tex ~pos (cpath ?outd ?ind x y) \end{alltt} } La fonction \texttt{loop} est similaire la fonction \texttt{transition}, mais elle doit calculer un chemin plus complexe. En effet, \texttt{cpath} appliqu deux botes identiques renvoie un chemin vide et on ne peut donc pas l'utiliser. \`{A} la place, on calcule un point $A$ suffisamment loign de la bote et on trace un chemin qui part du centre, qui passe par $A$ puis qui revient au centre. On utilise au passage la fonction \texttt{knotp} qui permet de spcifier un point avec une tangente, et \texttt{pathk} qui transforme une liste de tels points en un chemin. \begin{minipage}{0.25\linewidth} \includegraphics{loop_explain.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \small\begin{alltt} let loop states tex name = let box = Box.get name states in let a = Point.shift (Box.south box) (Point.pt (cm 0., cm (-0.4))) in let c = Box.ctr box in let p = Path.pathk [ knotp ~r:(vec (dir 225.)) c; knotp a; knotp ~l:(vec (dir 135.)) c; ] in let bp = Box.bpath box in Arrow.draw ~tex ~pos:`Bot (cut_after bp (cut_before bp p)) \end{alltt} \end{minipage} Ici encore, on pourrait gnraliser cette fonction pour spcifier la position de la flche. On peut maintenant dessiner facilement des automates en utilisant cette bibliothque. \medskip \begin{minipage}{0.2\linewidth} \includegraphics{automate.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \small\begin{alltt} let automate = let states = ... in [ Box.draw states; transition states "a" `Lowleft "alpha" "gamma"; transition states "b" `Lowright "gamma" "beta"; transition states "c" `Top ~outd:25. ~ind:335. "alpha" "beta"; transition states "d" `Bot ~outd:205. ~ind:155. "beta" "alpha"; loop states "e" "gamma"; initial states "alpha" ] \end{alltt} \end{minipage} \subsection{Exemples utilisant des calculs en \ocaml} Cette section illustre l'un des avantages de \mlpost: la capacit de dessiner directement un objet que l'on a calcul/programm en \ocaml. % plot -- SL \subsubsection{Graphe de fonction.} Un exemple simple de dessin rsultant d'un calcul est celui du graphe d'une fonction. \mlpost\ fournit un module \texttt{Plot} cet effet. La figure suivante montre un exemple basique d'utilisation de cette extension : \medskip \begin{minipage}{0.22\linewidth} \includegraphics[width=0.9\linewidth]{graph_sqrt.mps} \end{minipage} \begin{minipage}{0.65\linewidth} \small\begin{alltt} let u = cm 1. in let sk = Plot.mk_skeleton 4 3 u u in let label = Picture.tex "$y=...$", `Upleft, 3 in let f x = sqrt (float x +. 0.5) in [ Plot.draw_func ~label f sk; Plot.draw_simple_axes "$x$" "$y$" sk ] \end{alltt} \end{minipage} \medskip\noindent La fonction \texttt{mk\_skeleton} permet de construire un cannevas de 4 units sur 3, qui est l'objet de base de l'extension \texttt{Plot}. Il est alors possible de dessiner un graphe de fonction et des axes au sein de ce cannevas, comme illustr ci-dessus. L'extension dispose de beaucoup d'options (trac de la grille, affichage des abscisses et ordonnes, diffrents types de graphes de fonctions) qui permettent de raliser des figures plus complexes, telle que celle dcrite dans le paragraphe suivant. \subsubsection{Abstractions d'horloges dans un systme synchrone flot-de-donnes.} L'exemple ci-dessous, ralis par Florence Plateau, provient d'un problme rel~\cite{MandelPlateau08} et illustre un certain nombre des possibilits de l'extension \texttt{Plot}. % % Ainsi les fonctions illustres sur cette figure ont t codes comme des fonctions \ocaml{} standard. De plus, la ligne intermdiaire dans la partie situe sous le graphe principal, et dnote par $w_2$, reprsente les discontinuits de la fonction $f_{w_2}$ du graphe principal. Cette ligne est calcule \textit{directement} partir de la fonction $f_{w_2}$ ; si l'on dcide de changer la fonction $f_{w_2}$, la ligne $w_2$ sera mise jour automatiquement. Cela est galement vrai pour certaines tiquettes de la figure, comme l'abscisse $[w_2]_5$. Ceci offre une flexiblit trs intressante lors de la phase de dveloppement d'une telle figure. \begin{figure}[h] \centering \begin{center} \medskip \includegraphics{florence.mps} \end{center} %\caption{expliquer de quoi a parle} \label{fig:florence} \end{figure} \subsubsection{Bresenham.} \`{A} titre de dernier exemple, supposons que l'on veuille illustrer l'algorithme de trac de segment de Bresenham~\cite{bresenham}, par exemple sur le segment reliant le point $(x_1,y_1)=(0,0)$ au point $(x_2,y_2)=(9,6)$. Pour cela, on commence par stocker le rsultat de l'algorithme dans un tableau \texttt{bresenham\_data}, tel que $\texttt{bresenham\_data.(}x\texttt{)}$ donne l'ordonne du point d'abscisse $x$. \begin{alltt} let x2 = 9 and y2 = 6 let bresenham_data = Array.create (x2+1) 0 let () = \emph{(* remplissage du tableau a *)} \emph{(* avec l'algorithme de Bresenham *)} ... \end{alltt} On peut alors raliser la figure trs facilement, l'aide de la fonction \texttt{Box.gridi} fournie par \mlpost, qui construit une matrice de botes alignes partir d'une largeur, d'une hauteur et d'une fonction construisant la bote $(i,j)$, d'une manire analogue \texttt{Array.create\_matrix}. \medskip \begin{minipage}{0.26\linewidth} \vspace*{1em} \hspace*{-1.4em}\includegraphics[width=1.2\textwidth]{bresenham0.mps} \end{minipage} \begin{minipage}{0.7\linewidth} \vspace*{0.8em} \small\begin{alltt} let width = bp 6. and height = bp 6. in let g = Box.gridi (x2+1) (y2+1) (fun i j \ensuremath{\rightarrow} let fill = if bresenham_data.(i) = y2 - j then Some Color.red else None in Box.rect ?fill (Box.empty ~width ~height ())) in [ Box.draw g ] \end{alltt} \end{minipage} \medskip\noindent Les botes sont des botes vides de 6 points de ct, cres avec \texttt{Box.empty}. Pour les botes correspondant des points dessins par l'algorithme de Bresenham, on indique que la bote doit tre remplie en rouge, l'aide de l'argument optionnel \texttt{fill}. Pour parachever la figure, on va ajouter des tiquettes indiquant les coordonnes des deux extrmits du segment. Pour placer une tiquette ct de la case $(i,j)$, on rcupre la bote correspondante l'aide de \texttt{Box.nth}, puis on rcupre un point particulier de cette bote (par exemple le point au milieu en bas avec \texttt{Box.south}), puis enfin on trace l'tiquette avec \texttt{Command.label}. \medskip \begin{minipage}{0.26\linewidth} \vspace*{0.8em} \hspace*{-1.4em}\includegraphics[width=1.2\textwidth]{bresenham.mps} \end{minipage} \begin{minipage}{0.7\linewidth}\small \begin{alltt} let bresenham = let width = bp 6. and height = bp 6. in let g = ... in let get i j = Box.nth i (Box.nth (y2-j) g) in let label pos s point i j = Command.label ~pos (Picture.tex s) (point (get i j)) in [ Box.draw g; label `Bot "0" Box.south 0 0; label `Bot "$x_2$" Box.south x2 0; label `Left "0" Box.west 0 0; label `Left "$y_2$" Box.west 0 y2 ] \end{alltt} \end{minipage} \section{Architecture logicielle}\label{archi} La figure~\ref{fig:etapes} montre le fonctionnement de \mlpost. Tout d'abord, \mlpost\ est un outil de gnration de fichier \metapost\ sous forme de bibliothque \ocaml. \`{A} l'aide de cette bibliothque, l'utilisateur crit un programme qui, l'excution, construit un arbre de syntaxe abstraite \metapost. Cet arbre est imprim dans un fichier \verb|figure.mp| qui est lu par \metapost\ pour gnrer un ou plusieurs fichiers \postscript\footnote{Ces fichiers n'ont pas le suffixe \texttt{.ps} car il leur manque l'en-tte.}. L'inclusion de ces figures dans un document \LaTeX{} se fait simplement en utilisant la commande \verb|\includegraphics| du package \textsf{graphicx}. Pour compiler le document \LaTeX{} avec {\tt pdflatex}, il suffit de changer l'extension des figures gnres, ce qu'une option de l'outil \mlpost{} permet de faire facilement. \begin{figure}[h] \begin{center} \includegraphics[width=\textwidth]{stages.mps} \end{center} \caption{Architecture de \mlpost}\label{fig:etapes} \end{figure} Il est important de noter que le fichier \metapost\ de sortie n'est pas obtenu par {\em compilation} du code source \ocaml, mais par une \emph{excution} du programme qui construit un arbre de syntaxe abstraite \metapost. Cette mthode a l'inconvnient qu'une boucle ou itration dans le programme de dpart sera traduite par une suite de commandes obtenues par le droulement de la boucle, et non par une construction de boucle du langage cible. Ceci tant dit, dans notre cas, le cot supplmentaire est faible, puisque \metapost\ droule galement les boucles dans les fichiers \postscript\ de sortie. % schma de l'architecture \begin{figure}[ht] \begin{center} ~\\[0.5em] \includegraphics{architecture.mps} \end{center} \vspace*{-1em} \caption{Architecture de \mlpost}\label{fig:archi} \end{figure} L'architecture gnrale de \mlpost{} est schmatise en figure~\ref{fig:archi}. Au niveau le plus bas se trouvent les interfaces correspondant aux types primitifs de \metapost. Ce sont ces objets qui sont {\it in fine} traduits en du code \metapost, et nous les dcrivons de manire plus dtaille dans la section~\ref{subsec:types}. La couche intermdiaire contient des lments que nous estimons tre de bas niveau mais qui ne sont pas prsents dans \metapost : ils sont propres \mlpost\ et ont t construits partir de la couche infrieure. Les sections~\ref{subsec:boxes} et \ref{subsec:arrows} reviennent plus en dtail sur deux de ces modules, respectivement \texttt{Box} et \texttt{Arrow}. Enfin, on trouve au plus haut niveau des modules tels que le module \texttt{Plot} prsent dans la section prcdente. L'intgralit des modules de \mlpost\ est empaquete dans un module \texttt{Mlpost}, afin de ne pas polluer l'espace de noms d'\ocaml. \subsection{Types primitifs de \metapost}\label{subsec:types} La couche de bas niveau de \mlpost\ est une interface fidle \metapost. Elle comporte tous les types de base de \metapost~: \begin{description} \item[Le type numrique (module \texttt{Num})] reprsente des longueurs. En premire approximation, ce type pourrait tre assimil au type \texttt{float} d'\ocaml, mais certaines valeurs, telle que la taille d'un lment \LaTeX, ne sont connues qu' l'interprtation du fichier \metapost. La plupart des calculs sont donc effectus de manire symbolique et le type \texttt{Num.t} doit donc tre abstrait. \item[Le type point (module \texttt{Point})] reprsente des points dans l'espace deux dimensions. Pour les mmes raisons que les numriques, les points ne sont pas simplement des paires de flottants, mais doivent tre reprsents de manire symbolique. Le type \texttt{Point.t} est galement utilis pour reprsenter les vecteurs. \item[Les chemins (module \texttt{Path})] sont des lignes reprsentes par des courbes de Bzier. Ils sont la base de tout dessin \metapost. Toutes les possibilits de construction de chemin dans \metapost\ ont t interfaces. On peut dessiner des lignes droites ou des lignes courbes en prcisant les points de contrle, la tension de la courbe, etc. \item[Les transformations (module \texttt{Transform})] permettent d'appliquer une transformation linaire un objet quelconque. Il est ainsi possible de dplacer des objets, les redimensionner, les faire pivoter ou encore combiner toutes ces transformations. \item[Les plumes (module \texttt{Pen})] permettent de choisir l'paisseur et la forme du stylo utilis pour dessiner les chemins. \item[Les figures (module \texttt{Picture})] permettent de rassembler plusieurs lments graphiques en un seul, qu'il s'agisse d'lments \LaTeX\ ou de commandes de dessin arbitraires. Le type \texttt{Picture.t} permet de traiter une figure arbitrairement complexe comme un objet de base que l'on peut copier, transformer, etc. Le module \texttt{Picture} permet galement de dcouper une figure l'aide d'une surface dcrite par un chemin clos (\textit{clipping}). \end{description} Les autres types \metapost\ (chanes de caractres, boolens, couleurs) sont directement reprsents en \ocaml. L'interface de \mlpost\ contient aussi un module \texttt{Command} qui dfinit le type des commandes \metapost : commandes de dessin, de remplissage, itrations, squences, etc. \subsubsection{Dpendances circulaires.} La ralisation de ces modules de bas niveau prsente quelques difficults. Premirement, la plupart des modules prsents sont {\em a priori} mutuellement rcursifs : par exemple, les transformations s'appliquent tous les autres objets, donc chaque module contient une fonction \begin{alltt} val transform : Transform.t \ensuremath{\rightarrow} t \ensuremath{\rightarrow} t \end{alltt} o le type \texttt{t} reprsente le type principal du module en question. D'un autre ct, les transformations sont elles-mmes construites l'aide de numriques et de points: \begin{alltt} val shifted : Point.t \ensuremath{\rightarrow} t \end{alltt} o \texttt{t} est le type des transformations. Des dpendances circulaires existent aussi entre types et sont aggraves par la reprsentation symbolique des objets (par exemple, les projections \texttt{xpart} et \texttt{ypart} du module \texttt{Point} doivent retourner des numriques et non des flottants). Nous souhaitons raliser ces diffrents modules dans des fichiers diffrents mais \ocaml\ ne permet pas de dpendances circulaires entre des fichiers. Notre solution consiste dfinir tous les \emph{types} dans un seul fichier \texttt{types.mli}. Chaque module fait maintenant rfrence ce fichier. Par exemple, dans le fichier \texttt{path.ml}, qui fournit l'implmentation du module \texttt{Path}, on trouvera \begin{alltt} type t = Types.path \end{alltt} La dpendance circulaire entre les modules est ainsi casse de manire trs classique. En revanche, on souhaite cacher l'existence du module \texttt{Types} pour les deux raisons suivantes : \begin{itemize} \item la clart des messages d'erreur ; \item la clart de la documentation gnre par \texttt{ocamldoc}. \end{itemize} On souhaite donc rtablir la circularit entre les modules au sein de l'interface du module \texttt{Mlpost}. Pour cela, on crit un unique fichier \texttt{mlpost.mli} qui contient les dfinitions des signatures des modules exporter : \medskip \begin{minipage}{0.3\textwidth} \small\begin{alltt} module rec Point : sig type t val xpart : t \ensuremath{\rightarrow} Num.t ... end and Num : sig type t ... end and Path : sig type t ... end ... \end{alltt} \end{minipage} \begin{minipage}{0.6\textwidth} \includegraphics[width=1\textwidth]{deps.mps} \end{minipage} Toutes ces signatures sont dclares de manire mutuellement rcursive. La signature de \texttt{Point} peut ainsi faire rfrence \texttt{Path} et inversement. On notera que les types tels que \texttt{Point.t} sont maintenant abstraits dans l'interface, rendant invisible l'existence du module \texttt{Types}. Par ailleurs, les implmentations de ces modules sont contenues dans des fichiers indpendants \texttt{num.ml}, \texttt{point.ml}, etc., qui sont compils avec l'option {\tt -for-pack Mlpost}. Cet agencement est en outre trs pratique pour la documentation de l'API : c'est uniquement le fichier \texttt{mlpost.mli} qui sert d'entre l'outil \texttt{ocamldoc}. \subsubsection{Hash-consing et traduction vers \metapost.} Le choix d'une reprsentation symbolique de la plupart des objets impose des efforts supplmentaires pour minimiser l'utilisation de la mmoire et la taille des fichiers \metapost\ de sortie. En effet, l'arbre de syntaxe abstraite (AST) contient beaucoup de n\oe uds identiques mais construits de manire diffrente, qui prennent donc inutilement de la place aussi bien en mmoire que dans le fichier \metapost\ gnr. C'est d'autant plus gnant que \metapost\ devra lire ce fichier et passera donc davantage de temps sur des calculs rpts. Pour y remdier, nous utilisons la technique du {\em hash-consing}~\cite{ConchonFilliatre06wml} applique l'arbre de syntaxe abstraite. Cette technique permet de partager des valeurs structurellement gales. Elle utilise une table de hachage globale qui stocke toutes les valeurs dj cres. Avant de crer un nouvel objet, on regarde dans cette table si un objet structurellement gal existe dj. Pour que le calcul de la valeur de hachage soit efficace, chaque (sous-)terme vient avec sa valeur de hachage. Le partage ralis est maximal, ce qui permet de substituer l'galit physique (\texttt{==}) l'galit structurelle (\texttt{=}). Cette technique diminue l'utilisation de la mmoire, mais ne change rien {\em a priori} la taille des fichiers gnrs. La structure hash-conse {\em ralise} le partage, mais elle ne sait pas quels sont les n\oe uds effectivement utiliss au moins deux fois. Pour cela, on ralise un simple parcours en profondeur de la structure, en comptant les occurrences de chaque n\oe ud. Il est nanmoins possible de rencontrer une nouvelle fois un sous-n\oe ud d'une structure, comme le montre l'exemple ci-dessous : \begin{center} \includegraphics[scale=1.5]{sharing.mps} \end{center} \noindent Dans cette configuration, le n\oe ud $f$ est rellement utilis deux fois, alors que le n\oe ud $e$ n'est utilis qu'une seule fois, par le n\oe ud $d$, mme si celui-ci est utilis deux fois son tour. Autrement dit, on comptabilise pour chaque n\oe ud le nombre de flches incidentes. Aprs cette analyse, la gnration du fichier \metapost\ devient trs simple : il suffit de traverser de nouveau l'arbre de syntaxe abstraite et, quand on visite un n\oe ud qui est utilis au moins deux fois, on construit une dfinition \metapost\ pour cet objet. Il faut nanmoins prendre en compte les particularits syntaxiques de \metapost\ telles que la prcdence inhabituelle des oprateurs arithmtiques et la restriction de l'application de certaines constructions des variables. De cette faon, on arrive avoir du code \metapost\ relativement petit\footnote{En l'absence de boucles \texttt{for} et de macros dans le code \metapost, nous avons observ, sans avoir fait de tests trs exhaustifs, une taille du code gnr du mme ordre de grandeur que celle du code \metapost\ crit la main.}, malgr la dlgation des calculs \metapost. \subsection{Botes}\label{subsec:boxes} Comme nous l'avons illustr dj maintes fois, les botes de \mlpost\ peuvent tre rduites de simples objets \LaTeX\ ou bien tre constitues d'un ensemble d'autres botes. Le type des botes est donc un type rcursif de la forme suivante : \begin{alltt} type t = \{ name : string option; width : Num.t; height : Num.t; pen : Pen.t option; ... desc : desc; \} and desc = | Emp | Pic of Picture.t | Grp of t array \ensuremath{\times} t Smap.t \end{alltt} Chaque bote est ventuellement nomme (champ \texttt{name}), possde un certain nombre d'attributs (position, taille, couleur, bordure, remplissage, etc.) et sa nature est donne par le champ \texttt{desc}. Ce dernier indique s'il s'agit d'une bote vide, d'une image ou bien d'une bote composite. Dans ce dernier cas, les sous-botes sont contenues dans un tableau, qui est accompagn d'une table (ralise par le module \texttt{Smap}) permettant un accs plus rapide une sous-bote par son nom. Le dessin d'une bote est immdiat. On trace d'une part son contour et d'autre part son contenu. Ce dernier est soit une bote atomique directement dessine l'aide de \texttt{Command.draw\_pic}, soit une bote composite dont le dessin est tout simplement obtenu en dessinant rcursivement chaque sous-bote. Pour raliser les diverses fonctions de placement, on commence par crire une fonction de translation d'une bote par un vecteur donn : \begin{alltt} Box.shift : Point.t \ensuremath{\rightarrow} Box.t \ensuremath{\rightarrow} Box.t \end{alltt} Cette fonction est naturellement rcursive sur la structure de la bote. Il est important de noter que cette fonction renvoie une \emph{nouvelle} bote, sans altrer son argument (les botes sont persistantes). Une fois cette fonction donne, il est ais de raliser les fonctions \texttt{Box.hbox}, \texttt{Box.hblock}, etc. \subsection{Flches} \label{subsec:arrows} %% RB \metapost\ ne propose qu'un seul type de flche. Une flche \metapost\ suit un chemin arbitraire mais son trac est limit aux diffrents styles de trait (plume et pointills) et la tte de flche est toujours la mme : \begin{center} \includegraphics[width=\textwidth]{arrow_metapost.mps} \end{center} Avec \mlpost, l'utilisateur peut crer ses propres catgories de flches l'aide du module \texttt{Arrow}. Celui-ci propose deux types : \begin{itemize} \item Le type \texttt{head} dcrit comment dessiner une tte de flche. Les lments de type \texttt{head} sont des fonctions prenant en argument la position et la direction de la tte de flche et renvoyant une commande dessinant la tte de flche. \item Le type abstrait \texttt{kind} dcrit une catgorie de flche. Une catgorie dcrit les diffrents lments dans le dessin d'une flche, les ttes de flche pouvant en ralit tre places n'importe o le long de la flche. Pour construire une nouvelle catgorie, on part de la catgorie vide et on ajoute des traits et des ttes. \end{itemize} La fonction \texttt{draw} permet de dessiner une flche d'une catgorie donne en suivant un chemin donn. Les flches sont alors dessines en utilisant les primitives de \metapost. Ceci a l'inconvnient d'utiliser plus de ressources mais permet d'imaginer de nombreuses catgories de flches. On peut en particulier retrouver les flches de \metapost. On part d'un corps vide et on lui ajoute un trait normal sur toute la longueur. On ajoute enfin une tte triangulaire remplie, et on obtient : \medskip \begin{minipage}{0.2\linewidth} \includegraphics{arrow_simple.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \begin{alltt} let kind = Arrow.add_head ~head:Arrow.head_triangle_full (Arrow.add_line Arrow.empty) in [ Arrow.draw ~kind (...path...) ] \end{alltt} \end{minipage} \medskip La section~\ref{sec:automates} contient une figure dcrivant le fonctionnement de la fonction \texttt{loop}. Pour les besoins de cette figure, on a cr un type de flche spcial, compos d'un dbut et d'une fin en pointills et avec une tte place diffremment : \begin{center} \includegraphics[width=\textwidth]{arrow_loop_explain.mps} \end{center} Le code permettant d'obtenir cette catgorie de flche est le suivant : {\small \begin{alltt} let kind = Arrow.add_belt ~point:0.9 (Arrow.add_line ~dashed:Dash.evenly ~to_point:0.1 (Arrow.add_line ~dashed:Dash.evenly ~from_point:0.9 (Arrow.add_line ~from_point:0.1 ~to_point:0.9 Arrow.empty))) \end{alltt} } \section{Conclusion}\label{conclusion} Nous avons prsent \mlpost, une bibliothque \ocaml\ au dessus de \metapost. Nous esprons avoir convaincu le lecteur des avantages que la prsentation sous forme de bibliothque apporte : familiarit avec le langage pour les programmeurs \ocaml, typage fort, des constructions de programmation de haut niveau, des dessins rsultants de calculs arbitraires, etc. \mlpost\ fournit volontairement un nombre restreint de primitives, car l'utilisateur peut aisment construire des extensions au dessus de \mlpost. En cela, \mlpost\ diffre de bibliothques \LaTeX\ telles que \nomdetikz\ ou \pstricks, o de trs nombreuses fonctionnalits sont fournies mais o il est trs difficile d'en ajouter pour qui ne matrise pas \TeX. L'une des forces de \mlpost\ est de proposer un style dclaratif, l o la majorit des bibliothques graphiques propose un style impratif. Ceci permet en particulier un \emph{partage} immdiat de sous-lments dans une ou plusieurs figures. Une autre force de \mlpost\ est le typage statique directement hrit d'\ocaml. On vite ainsi l'immense majorit des erreurs l'excution de \metapost, souvent cryptiques. Il reste nanmoins les erreurs ventuellement contenues dans les extraits de \LaTeX\ ou les erreurs de nature gomtrique telles que le remplissage d'un chemin en forme de 8. Nous pourrions envisager d'utiliser des types \ocaml\ plus prcis, par exemple pour distinguer les chemins clos et non clos ou encore les points et les vecteurs. Il reste une fonctionnalit intressante de \metapost\ qui n'est pas interface dans \mlpost~: la rsolution d'quations linaires. Il y a deux raisons cela. D'une part, les quations servent souvent au placement implicite, et \mlpost\ fournit une alternative sous la forme de fonctions d'alignement de botes. D'autre part, la rsolution d'quations de \metapost\ procde de manire imprative et il n'est pas simple de l'intgrer dans le contexte dclaratif qui est le ntre. Ceci tant dit, il serait intressant d'explorer des mthodes de placement plus automatiques que celles que nous proposons, par exemple inspires de la manire dont \TeX{} mets en page lignes, pages et paragraphes. Enfin, il est important de noter que \mlpost\ n'est pas li \metapost\ de manire intrinsque. On pourrait facilement ajouter une sortie \nomdetikz, ou mme directement une sortie \postscript\ condition d'utiliser une technique similaire celle de \metapost\ pour l'inclusion de \LaTeX. \medskip \noindent \vbox{ \begin{center} \includegraphics[width=0.3\textwidth]{ford.mps} \medskip \begin{minipage}{0.7\textwidth} \begin{center} \bf Remerciements \end{center} \centering Les auteurs tiennent remercier Florence Plateau, Yannick Moy et Claude March pour leur contribution \mlpost, Sylvie Boldo pour la suggestion du titre de l'article et les relecteurs pour leurs remarques. \end{minipage} \medskip \includegraphics[angle=180,width=0.3\textwidth]{ford.mps} \end{center} } % La bibliographie % N'oubliez pas de l'inclure lors de votre soumission. \begin{thebibliography}{10} \bibitem{haskell} {Le langage Haskell}. \newblock \url{http://www.haskell.org/}. \bibitem{ocaml} {Le langage Objective Caml}. \newblock \url{http://caml.inria.fr/}. \bibitem{bresenham} Jack~E. Bresenham. \newblock Algorithm for computer control of a digital plotter. \newblock {\em IBM Systems Journal}, 4(1):25--30, January 1965. \bibitem{mlpictex} Emmanuel Chailloux and Asc\'ander Su\'arez. \newblock {\mlpictex}, a picture environment for {\LaTeX}. \newblock In {\em Workshop on {ML}}, pages 79--90, 1994. \bibitem{MandelPlateau08} Albert Cohen, Louis Mandel, Florence Plateau, and Marc Pouzet. \newblock {Abstraction of Clocks in Synchronous Data-flow Systems}. \newblock In {\em The Sixth ASIAN Symposium on Programming Languages and Systems (APLAS)}, Bangalore, India, December 2008. \bibitem{ConchonFilliatre06wml} Sylvain Conchon and Jean-Christophe Filli\^atre. \newblock {Type-Safe Modular Hash-Consing}. \newblock In {\em ACM SIGPLAN Workshop on ML}, Portland, Oregon, September 2006. \bibitem{persistance} J.~R. Driscoll, N.~Sarnak, D.~D. Sleator, and R.~E. Tarjan. \newblock {Making Data Structures Persistent}. \newblock {\em Journal of Computer and System Sciences}, 38(1):86--124, 1989. \bibitem{pstricks} T.~Van~Zandt et~al. \newblock {PSTricks}. \newblock \url{http://tug.org/PSTricks/}. \bibitem{fmpost} Meik Hellmund, Ralf Hinze, Joachim Korittky, Marco Kuhlmann, Ferenc W\'agner, and Peter Simons. \newblock {\fmpost}. \newblock \url{http://cryp.to/funcmp/}. \bibitem{metapost} John Hobby. \newblock \metapost, 1994. \newblock \url{http://plan9.bell-labs.com/who/hobby/MetaPost.html}. \bibitem{metafont} Donald~E. Knuth. \newblock {\em The {\metafont} Book}. \newblock Addison-Wesley, 1984. \bibitem{dia} Alexander Larsson. \newblock {Dia}. \newblock \url{http://live.gnome.org/Dia}. \bibitem{postscript} Glenn~C. Reid. \newblock {\em {PostScript Language Program Design}}. \newblock Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA, 1988. \bibitem{xfig} Brian~V. Smith. \newblock {Xfig}. \newblock \url{http://www.xfig.org/}. \bibitem{tikz} Till Tantau. \newblock {PGF and TikZ -- Graphic systems for \TeX}. \newblock \url{http://sourceforge.net/projects/pgf/}. \end{thebibliography} %\bibliographystyle{plain} %\bibliography{./biblio} \vfill %\pagebreak %\thispagestyle{colloquetitle} %\cleardoublepage \end{document} % Local Variables: % coding: iso-latin-1 % ispell-local-dictionary: "francais" % End: mlpost-0.8.2/papers/jfla2009/biblio.bib000066400000000000000000000066431306046515300175120ustar00rootroot00000000000000@book{metafont, author = {Donald E. Knuth}, title = {The {\metafont} Book}, year = {1984}, publisher = {Addison-Wesley}, } @Misc{metapost, author = {John Hobby}, title = {\metapost}, year = {1994}, note = {\url{http://plan9.bell-labs.com/who/hobby/MetaPost.html}}, url = {http://plan9.bell-labs.com/who/hobby/MetaPost.html}, } @Misc{fmpost, author = {Meik Hellmund and Ralf Hinze and Joachim Korittky and Marco Kuhlmann and Ferenc W\'agner and Peter Simons}, title = {{\fmpost}}, note = {\url{http://cryp.to/funcmp/}}, url = {http://cryp.to/funcmp/} } @inproceedings{mlpictex, author = "Emmanuel Chailloux and Asc\'ander Su\'arez", title = "{\mlpictex}, A Picture Environment for {\LaTeX}", pages = {79--90}, year = {1994}, booktitle = "Workshop on {ML}" } @Misc{tikz, author = {Till Tantau}, title = {{PGF and TikZ -- Graphic systems for \TeX}}, note = {\url{http://sourceforge.net/projects/pgf/}} } @Misc{dia, author = {Alexander Larsson}, title = {{Dia}}, note = {\url{http://live.gnome.org/Dia}} } @Misc{xfig, author = {Brian V. Smith}, title = {{Xfig}}, note = {\url{http://www.xfig.org/}} } @Misc{pstricks, author = {T. Van Zandt et al.}, title = {{PSTricks}}, note = {\url{http://tug.org/PSTricks/}} } @Misc{asymptote, author = {Andy Hammerlindl and John Bowman and Tom Prince}, title = {Asymptote}, note = {\url{http://asymptote.sourceforge.net/}} } @InProceedings{ConchonFilliatre06wml, author = {Sylvain Conchon and Jean-Christophe Filli\^atre}, title = {{Type-Safe Modular Hash-Consing}}, booktitle = {ACM SIGPLAN Workshop on ML}, address = {Portland, Oregon}, topics = {team, lri}, type_publi = {icolcomlec}, type_digiteo = {conf_isbn}, month = sep, year = 2006, url = {http://www.lri.fr/~filliatr/ftp/publis/hash-consing2.ps.gz}, x-equipes = {demons PROVAL}, x-type = {article}, x-support = {actes}, x-cle-support = {ML}, } @inproceedings{MandelPlateau08, author = {Albert Cohen and Louis Mandel and Florence Plateau and Marc Pouzet}, title = {{Abstraction of Clocks in Synchronous Data-flow Systems}}, booktitle = {The Sixth ASIAN Symposium on Programming Languages and Systems (APLAS)}, year = 2008, month = {December}, date = {9--11}, address = { Bangalore, India}, type_publi = {icolcomlec}, x-equipes = {demons PROVAL EXT}, x-type = {article}, x-support = {actes}, x-cle-support = {APLAS}, topics = {team} } @Article{persistance, author = {J. R. Driscoll and N. Sarnak and D. D. Sleator and R. E. Tarjan}, title = {{Making Data Structures Persistent}}, journal = {Journal of Computer and System Sciences}, year = 1989, volume = 38, number = 1, pages = {86--124} } @Article{bresenham, author = {Jack E. Bresenham}, title = {Algorithm for computer control of a digital plotter}, journal = {IBM Systems Journal}, year = 1965, volume = 4, number = 1, pages = {25--30}, month = {January} } @misc{ocaml, title = {{Le langage Objective Caml}}, note = {\url{http://caml.inria.fr/}} } @misc{haskell, title = {{Le langage Haskell}}, note = {\url{http://www.haskell.org/}} } @book{postscript, author = {Glenn C. Reid}, title = {{PostScript Language Program Design}}, year = {1988}, isbn = {0201143968}, publisher = {Addison-Wesley Longman Publishing Co., Inc.}, address = {Boston, MA, USA}, } mlpost-0.8.2/papers/jfla2009/demo.ml000066400000000000000000000011611306046515300170400ustar00rootroot00000000000000open Mlpost open Num open Box let fig = let b = hbox ~padding:(bp 20.) ~pos:`Bot [circle (tex "A"); vbox [round_rect (tex "B"); tex "\\LaTeX"]] in let b = round_rect ~stroke:(Some Color.red) b in draw (vbox [b;b;b]) let () = Metapost.emit "fig" fig let triple x = [x;x;x] let nine x = triple (triple x) let u = bp 10. let sudoku = let e = rect (empty ~width:u ~height:u ()) in let b = tabularl ~hpadding:zero ~vpadding:zero (nine e) in let pen = Pen.scale (pt 1.5) Pen.circle in let b = rect ~pen ~dx:zero ~dy:zero b in draw (tabularl (nine b)) let () = Metapost.emit "sudoku" sudoku mlpost-0.8.2/papers/jfla2009/figmp.mp000066400000000000000000000007231306046515300172250ustar00rootroot00000000000000beginfig(1) u:=2cm; vardef koch(expr A,B,n) = save C; pair C; C = A rotatedaround(1/3[A,B], 120); if n>0: koch( A, 1/3[A,B], n-1); koch( 1/3[A,B], C, n-1); koch( C, 2/3[A,B], n-1); koch( 2/3[A,B], B, n-1); else: draw A--1/3[A,B]--C--2/3[A,B]--B; fi; enddef; z0=(u,0); z1=z0 rotated 120; z2=z1 rotated 120; koch( z0, z1, 4 ); koch( z1, z2, 4 ); koch( z2, z0, 4 ); endfig; mlpost-0.8.2/papers/jfla2009/figures.ml000066400000000000000000000615141306046515300175700ustar00rootroot00000000000000 (* figures pour l'article JFLA *) open Mlpost open Command open Picture open Path open Helpers open Num open Num.Infix open Point open Box let draw_arrow = Arrow.simple (* Stphane *) (** the old ugly version *) (* let graph_sqrt = *) (* let u = Num.cm in *) (* let pen = Pen.circle ~tr:[Transform.scaled one] () in *) (* let rec pg = function *) (* | 0 -> start (knot ~r:(vec up) ~scale:u (0.,0.)) *) (* | n -> let f = (float_of_int n /. 2.) in *) (* concat ~style:jCurve (pg (n-1)) (knot ~scale:u (f, sqrt f)) *) (* in *) (* [draw (pathn ~style:jLine [(zero,u 2.); (zero,zero); (u 4.,zero)]); *) (* draw ~pen (pg 8); *) (* label ~pos:`Lowright (tex "$ \\sqrt x$") (pt (u 3., u (sqrt 3.))); *) (* label ~pos:`Bot (tex "$x$") (pt (u 2., zero)); *) (* label ~pos:`Lowleft (tex "$y$") (pt (zero, u 1.))] *) (** the new short one :) *) let graph_sqrt = let u = cm 1. in let sk = Plot.mk_skeleton 4 3 u u in let label = Picture.tex "$y=\\sqrt{x+\\frac{1}{2}}$", `Upleft, 3 in let graph = Plot.draw_func ~label (fun x -> sqrt (float x +. 0.5)) sk in seq [graph; Plot.draw_simple_axes "$x$" "$y$" sk] let architecture = let mk_box fill name m = let m = "{\\tt " ^ m ^ "}" in Box.tex ~stroke:(Some Color.black) ~style:RoundRect ~dx:(bp 5.) ~dy:(bp 5.) ~name ~fill m in let mk_unbox name m = Box.tex ~style:RoundRect ~stroke:None ~dx:(bp 5.) ~dy:(bp 5.) ~name m in (* les types de base *) let fill = Color.color "salmon" in let num = mk_box fill "num" "Num" in let point = mk_box fill "point" "Point" in let path = mk_box fill "path" "Path" in let dots = mk_unbox "dots" "$\\ldots$" in let cmd = mk_box fill "cmd" "Command" in let basictypes = Box.hbox ~padding:(mm 2.) [num; point; path; dots; cmd] in (* compile *) let compile = mk_unbox "compile" "\\tt Compile" in let compile_ext = let dx = (Box.width basictypes -/ Box.width compile) /./ 2. in Box.hbox ~style:RoundRect ~dx ~fill ~stroke:(Some Color.black) [compile] in (* metapost *) let metapost = mk_unbox "metapost" "\\metapost" in let metapost_ext = let dx = (Box.width basictypes -/ Box.width metapost) /./ 2. in Box.hbox ~name:"mpost_ext" ~style:Rect ~dx ~stroke:(Some Color.black) [metapost] in (* composants avancs *) let fill = Color.color "pink" in let box_ = mk_box fill "box" "\\phantom{p}Box\\phantom{p}" in let shapes = mk_box fill "shapes" "\\phantom{p}Shapes\\phantom{p}" in let arrows = mk_box fill "arrow" "\\phantom{p}Arrow\\phantom{p}" in let advanced = Box.hbox ~pos:`Bot ~padding:(mm 2.) [box_; shapes; arrows] in (* extensions *) let fill = Color.color "blanched almond" in let tree = mk_box fill "tree" "\\phantom{g}Tree\\phantom{g}" in let diag = mk_box fill "diag" "\\phantom{g}Diag\\phantom{g}" in let plot = mk_box fill "plot" "\\phantom{g}Plot\\phantom{g}" in let extensions = Box.hbox ~pos:`Bot ~padding:(mm 2.) [tree; diag; plot] in (* wrapping *) let pyramid = let pen = Pen.scale (Num.bp 1.0) Pen.square in Box.vbox ~padding:(mm 2.) ~pen ~dx:(bp 5.) ~dy:(bp 5.) ~style:RoundRect ~stroke:(Some Color.black) [extensions; advanced; basictypes; compile_ext; metapost_ext] in let mlpost = mk_unbox "mlpost" "\\tt Mlpost" in let mlpost_ext = let dx = (Box.width pyramid -/ Box.width mlpost) /./ 2. in Box.hbox ~dx [mlpost] in let full = Box.vbox ~padding:(mm (-1.)) [mlpost_ext; pyramid] in let _ = Box.set_stroke Color.black (Box.nth 1 full) in (* arrows *) let arrows = let mp = Box.get "mpost_ext" full in List.map (fun n -> Helpers.box_label_arrow ~outd:(Path.vec Point.down) ~pos:`Bot (Picture.make Command.nop) (Box.get n full) mp) (* une variante *) (* let mp = Box.get "metapost" full in *) (* List.map *) (* (fun n -> Helpers.box_arrow *) (* (Box.get n full) mp) *) ["num"; "point"; "path"; "dots"; "cmd"] in seq [seq arrows; Box.draw full] (* Romain *) open Num let state = Box.tex ~style:Circle ~stroke:(Some Color.black) let final = Box.box ~style:Circle let transition states tex anchor ?outd ?ind x_name y_name = let x = Box.get x_name states and y = Box.get y_name states in let outd = match outd with None -> None | Some a -> Some (vec (dir a)) in let ind = match ind with None -> None | Some a -> Some (vec (dir a)) in Arrow.draw ~tex ~anchor (cpath ?outd ?ind x y) (*let loop box = let c = Box.ctr box in let a = Point.shift c (pt (cm 0., cm (-0.8))) in let p = Path.pathk [ knotp ~r: (vec (dir 225.)) c; knotp a; knotp ~l: (vec (dir 135.)) c; ] in let bp = Box.bpath box in cut_after bp (cut_before bp p)*) (* let loop states tex pos name = let box = Box.get name states in let fdir, angle, x, y = match pos with | `Top -> Box.north, 0., 0., 0.4 | `Left -> Box.west, 90., (-0.4), 0. | `Bot -> Box.south, 180., 0., (-0.4) | `Right -> Box.north, 270., 0.4, 0. in let a = Point.shift (fdir box) (Point.pt (cm x, cm y)) in let c = Box.ctr box in let p = Path.pathk [ knotp ~r: (vec (dir (angle +. 45.))) c; knotp a; knotp ~l: (vec (dir (angle -. 45.))) c; ] in let bp = Box.bpath box in Arrow.draw ~tex ~pos: (pos :> Command.position) (cut_after bp (cut_before bp p)) *) let loop states tex name = let box = Box.get name states in let a = Point.shift (Box.south box) (Point.pt (cm 0., cm (-0.4))) in let c = Box.ctr box in let p = Path.pathk [ knotp ~r: (vec (dir 225.)) c; knotp a; knotp ~l: (vec (dir 135.)) c; ] in let bp = Box.bpath box in Arrow.draw ~tex ~anchor:`Bot (cut_after bp (cut_before bp p)) let arrow_loop_explain_kind = Arrow.add_belt ~point: 0.9 (Arrow.add_line ~dashed: Dash.evenly ~to_point: 0.1 (Arrow.add_line ~dashed: Dash.evenly ~from_point: 0.9 (Arrow.add_line ~from_point: 0.1 ~to_point: 0.9 Arrow.empty))) let loop_explain = let construct_pattern = Dash.pattern [Dash.on (bp 0.2); Dash.off (bp 1.)] in let arc_arrow = Arrow.add_head ~head: (Arrow.head_classic ~dashed: construct_pattern) (Arrow.add_line ~dashed: construct_pattern Arrow.empty) in let s = state "~~~~~~~~~~~" in let pt x y = Point.pt (cm x, cm y) in let p x y = Point.shift (Box.ctr s) (pt x y) in let a_pos = p 0. (-2.) in let angle = 180. in let c = Box.ctr s in let arrow_path = Path.pathk [ knotp ~r: (vec (dir (angle +. 45.))) c; knotp a_pos; knotp ~l: (vec (dir (angle -. 45.))) c; ] in let vert = Path.pathk [ knotp (p 0. 2.); knotp (p 0. (-3.)); ] in let len = 1.2 in let diag1 = Path.pathk [ knotp (p len len); knotp (p (-.len) (-.len)); ] in let diag2 = Path.pathk [ knotp (p len (-.len)); knotp (p (-.len) len); ] in let construct = Command.draw ~dashed: construct_pattern in let circle = Path.shift (pt 0.64 0.) (Path.scale (cm 2.) Path.fullcircle) in let arc = cut_before vert (cut_after diag2 (cut_after vert circle)) in seq [ Box.draw s; Command.dotlabel ~pos: `Lowleft (Picture.tex "$A$") a_pos; Arrow.draw ~kind: arrow_loop_explain_kind arrow_path; construct vert; construct diag1; construct diag2; Arrow.draw ~tex: "$45^{\\circ}$" ~anchor: `Upleft ~kind: arc_arrow arc; ] (* let initial states pos name = let x = Box.get name states in let p = match pos with | `Left -> Box.west x | `Right -> Box.east x | `Top -> Box.north x | `Bot -> Box.south x in Arrow.draw (Path.pathp [ Point.shift p (Point.pt (cm (-0.3), zero)); p ]) *) let initial (states : Box.t) (name : string) : Command.t = let b = Box.get name states in let p = Box.west b in Arrow.draw (Path.pathp [ Point.shift p (Point.pt (cm (-0.3), zero)); p ]) let automate_1 = let states = Box.vbox ~padding:(cm 0.8) [ Box.hbox ~padding:(cm 1.4) [ state ~name:"alpha" "$\\alpha$"; state "$\\beta$" ]; final (state "$\\gamma$") ] in Box.draw states let automate = let states = Box.vbox ~padding: (cm 0.8) [ Box.hbox ~padding: (cm 1.4) [ state ~name: "alpha" "$\\alpha$"; state ~name: "beta" "$\\beta$" ]; final ~name: "gamma" (state "$\\gamma$") ] in seq [ Box.draw states; transition states "a" `Lowleft "alpha" "gamma"; transition states "b" `Lowright "gamma" "beta"; transition states "c" `Top ~outd: 25. ~ind: 335. "alpha" "beta"; transition states "d" `Bot ~outd: 205. ~ind: 155. "beta" "alpha"; loop states "e" "gamma"; initial states "alpha" ] let arrow_metapost = seq [Helpers.draw_simple_arrow ~outd:(vec (dir 90.)) ~ind:(vec (dir 90.)) (Point.pt (cm 0., cm 0.5)) (Point.pt (cm 2., cm 0.5)); Helpers.draw_simple_arrow (Point.pt (cm 4., cm 0.5)) (Point.pt (cm 6., cm 0.5)); Helpers.draw_simple_arrow ~dashed:Dash.evenly ~outd:(vec (dir 90.)) (Point.pt (cm 8., cm 0.)) (Point.pt (cm 10., cm 0.)); Helpers.draw_simple_arrow ~pen:(Pen.scale (bp 2.5) Pen.square) (Point.pt (cm 12., cm 0.)) (Point.pt (cm 14., cm 1.))] let arrow_demo_path = Path.pathp [ Point.pt (zero, zero); (Point.pt (cm 2., zero)); ] let arrow_simple = Arrow.draw ~kind: Arrow.triangle_full arrow_demo_path let arrow_loop_explain = let pt x y = Point.pt (cm x, cm y) in let draw2 = Arrow.point_to_point ~kind: arrow_loop_explain_kind in seq [ draw2 ~outd:(vec (dir 45.)) ~ind: (vec (dir 45.)) (pt 0. 0.25) (pt 3. 0.25); draw2 (pt 5. 0.25) (pt 8. 0.25); draw2 ~outd:(vec (dir 45.)) (pt 10. 0.) (pt 13. 0.); ] (* Johannes *) open Box let uml_client, uml = let classblock name attr_list method_list = let vbox = Box.vbox ~pos:`Left in Box.vblock ~pos:`Left ~name [ tex ("{\\bf " ^ name ^ "}"); vbox (List.map tex attr_list); vbox (List.map tex method_list) ] in let a = classblock "BankAccount" [ "balance : Dollars = $0$"] ["deposit (amount : Dollars)"; "withdraw (amount : Dollars)" ] in let b = classblock "Client" ["name : String"; "address : String" ] [] in let diag = Box.vbox ~padding:(cm 1.) [a;b] in Box.draw b, seq [ Box.draw diag; box_label_arrow ~pos:`Left (Picture.tex "owns") (get "Client" diag) (get "BankAccount" diag) ] open Tree let sharing = let tex s = tex ~name:s ~style:Circle ~dx:two ~dy:two s in let tree = bin (tex "a") (bin (tex "b") (leaf (tex "c")) (bin (tex "d") (leaf (tex "e")) (leaf (tex "f")) ) ) (node (tex "g") [leaf (tex "h")]) in let tree = to_box tree in seq [ Box.draw tree; box_arrow (get "h" tree) (get "f" tree); box_arrow (get "g" tree) (get "d" tree); ] let arrowpic = pic ~stroke:None (Picture.make (draw_arrow (Path.path ~scale:cm [0.,0.; 0.,-1.]))) let harrowpic = pic ~stroke:None ~name:"harrow" (Picture.make (draw_arrow (Path.path ~scale:cm [0.,0.; 1.,0.]))) let texttt s = tex ("{\\tt "^s^"}") let sharingcompile = let code = Box.vbox ~pos:`Left (List.map texttt ["path f = ...;"; "path d = ...e...f...;"; "..."]) in let b = Box.hbox ~padding:(cm 2.) (List.map (fun (b,name) -> Box.box ~dx:(cm 0.5) ~name ~stroke:None b) [ Box.pic ~stroke:None (Picture.make sharing), "tree"; code, "code"; ]) in let arrow x y = box_arrow (get x b) (get y b) in seq [Box.draw b; arrow "tree" "code" ] let stages = let dx = bp 5. and dy = bp 5. in let tex' = tex ~style:RoundRect ~dx ~dy in let tex = tex' ~stroke:(Some Color.black) in let box name = box ~stroke:None ~dx:(mm 2.) ~name in let fml = box "fml" (tex "figure.ml") in let fmp = box "fmp" (tex "figure.mp") in let ps = box "ps" (vbox ~stroke:(Some Color.black) ~style:RoundRect ~dx ~dy [tex' "figure.1"; tex' "(\\postscript)"]) in let all = hbox ~padding:(cm 3.5) [fml; fmp; ps ] in seq [ Box.draw all; box_labelbox_arrow ~pos:`Top (vbox [tex "\\ocaml"; arrowpic; tex' "compiler \\& ex\\'ecuter"]) (get "fml" all) (get "fmp" all); box_labelbox_arrow ~pos:`Top (vbox [tex "\\metapost"; arrowpic; tex' "interpr\\'eter" ] ) (get "fmp" all) (get "ps" all); ] let simple = seq [ Box.draw (tex "\\LaTeX"); Box.draw (shift (Point.pt (cm 1., zero)) (circle (empty ()))) ] let align = seq [ Box.draw (hbox ~padding:(cm 1.) [tex "\\LaTeX"; circle (empty ())]) ] let persistance = let b = hbox ~padding:(cm 1.) [tex "\\LaTeX"; circle (empty ())] in Box.draw (vbox [b; set_stroke Color.black b; b]) (* Bresenham (JCF) *) (* the data to plot are computed here *) let x2 = 9 let y2 = 6 let bresenham_data = let a = Array.create (x2+1) 0 in let y = ref 0 in let e = ref (2 * y2 - x2) in for x = 0 to x2 do a.(x) <- !y; if !e < 0 then e := !e + 2 * y2 else begin y := !y + 1; e := !e + 2 * (y2 - x2) end done; a (* drawing *) let stroke = Some Color.black let width = bp 10. and height = bp 10. let bresenham0 = let g = Box.gridi (x2+1) (y2+1) (fun i j -> let fill = if bresenham_data.(i) = y2-j then Some Color.red else None in Box.empty ~width ~height ?fill ~stroke ()) in Box.draw g let bresenham = let g = Box.gridi (x2+1) (y2+1) (fun i j -> let fill = if bresenham_data.(i) = y2-j then Some Color.red else None in Box.empty ~width ~height ?fill ~stroke ()) in let get i j = Box.nth i (Box.nth (y2-j) g) in let label pos s point i j = Command.label ~pos (Picture.tex s) (point (get i j)) in seq [Box.draw g; label `Bot "0" Box.south 0 0; label `Bot "$x_2$" Box.south x2 0; label `Left "0" Box.west 0 0; label `Left "$y_2$" Box.west 0 y2] (* cercles de Ford (merci Claude) *) let ford n = let u x = Num.bp (200.0 *. x) in let circle x y r = Command.draw ~color:Color.black (Path.shift (Point.pt (u x, u y)) (Path.scale (u (2.*.r)) fullcircle)) in let rec aux acc p1 q1 p2 q2 = let p = p1 + p2 in let q = q1 + q2 in if q>n then acc else let fq = float q in let fr = 0.5 /. fq /. fq in let acc = circle (float p /. fq) fr fr :: acc in let acc = aux acc p1 q1 p q in aux acc p q p2 q2 in let l = aux [] 0 1 1 1 in let pic = Picture.make (Command.seq l) in Picture.scale (Num.bp 30.0) pic (* blocks mmoire *) let simple_block = let b = Box.hblock ~pos:`Bot [Box.tex "a"; Box.tex "b"; Box.tex "C"] in Box.draw b let pointer_arrow a b = let p = pathp [Box.ctr a; Box.ctr b] in let p = Path.cut_after (Box.bpath b) p in let pen = Pen.scale (Num.bp 4.) Pen.circle in Command.draw ~pen (pathp [Box.ctr a]) ++ draw_arrow p let block_arrow = let a = Box.empty ~width:(bp 10.) ~height:(bp 10.) ~stroke:(Some Color.black) () in let g = Box.hbox ~padding:(cm 1.) [a;a] in seq [Box.draw g; pointer_arrow (Box.nth 0 g) (Box.nth 1 g)] let cons hd tl = let p1 = tex ~name:"hd" hd in let p2 = if tl then empty ~name:"tl" ~width:(bp 10.) () else tex ~name:"tl" "\\ensuremath{\\bot}" in hblock [p1; p2] let draw_list l = let rec make = function | [] -> assert false | [x] -> [cons x false] | x :: l -> cons x true :: make l in let l = hbox ~padding:(Num.bp 30.) (make l) in let rec arrows = function | [] | [_] -> nop | b1 :: (b2 :: _ as l) -> pointer_arrow (Box.get "tl" b1) (Box.get "hd" b2) ++ arrows l in seq [Box.draw l; arrows (Array.to_list (Box.elts l))] let list123 = draw_list ["1";"2";"3"] let another_list = draw_list (List.map (fun n -> Printf.sprintf "$\\sqrt{%d}$" n) [1;2;3;4]) let deps = let node s = Box.round_rect ~name:s ~dx:zero (Box.tex ("{\\tt\\phantom{p}" ^ s ^ "\\phantom{p}}")) in let ellipsis = Box.tex ~name:"..." "\\phantom{p}\\dots\\phantom{lp}" in let b = vbox ~padding:(bp 30.) [node "mlpost.mli"; hbox~padding:(bp 25.) [node "num.ml"; node "point.ml"; ellipsis; node "path.ml"]; node "types.mli"] in let arrow b1 b2 = box_arrow (Box.get b1 b) (Box.get b2 b) in seq [Box.draw b; iterl (fun s -> arrow "mlpost.mli" s ++ arrow s "types.mli") ["num.ml"; "point.ml"; "path.ml"; "..."]] let sous_typage = let tt s = Box.tex ~name:s ("\\tt `" ^ s) in let b = tabularl ~hpadding:(bp 10.) ~vpadding:(bp 10.) [[tt "Upleft"; tt "Top"; tt "Upright"]; [tt "Left"; tt "Center"; tt "Right" ]; [tt "Lowleft";tt "Bot"; tt "Lowright" ]] in let group l color = let bl = Box.group ~style:RoundRect (List.map (fun s -> Box.get s b) l) in Command.draw ~color (bpath bl) in seq [group ["Left"; "Center"; "Right"] Color.red; group ["Top"; "Center"; "Bot"] Color.blue; Box.draw b; ] let texttt x = "\\texttt{"^x^"}" let circularity = let box x = Box.tex ~name: x ~style: Box.RoundRect ~stroke: (Some Color.orange) ~fill: Color.yellow ~dx: (Num.cm 0.1) ~dy: (Num.cm 0.1) x in let dir x = Path.vec (Point.dir x) in let transform = box "Transform" in let point = box "Point" in let picture = box "Picture" in let command = box "Command" in let circ x y = Box.vbox ~padding: (Num.cm 0.75) [x; y] in let hbox = Box.hbox ~padding: (Num.cm 2.5) [circ transform point; circ picture command] in let arrow_down x y tex = let x = Box.get x hbox in let y = Box.get y hbox in let tex = texttt tex in Arrow.draw ~tex ~anchor: `Left (Box.cpath ~outd: (dir 225.) x y) in let arrow_up x y tex = let x = Box.get x hbox in let y = Box.get y hbox in let tex = texttt tex in Arrow.draw ~tex ~anchor: `Right (Box.cpath ~outd: (dir 45.) y x) in seq [ Box.draw hbox; arrow_down "Transform" "Point" "shifted"; arrow_up "Transform" "Point" "transform"; arrow_down "Picture" "Command" "make"; arrow_up "Picture" "Command" "draw\\_pic"; ] let circularity_solution = let box title contents = Box.vbox ~pos: `Left [ Box.tex (texttt title); contents; ] in let box_tex title contents = let contents = List.map (fun line -> Box.tex (texttt line)) contents in box title (Box.vbox ~name: title ~pos: `Left ~style: RoundRect ~stroke: (Some Color.orange) ~fill: (Color.rgb8 255 255 150) contents) in let box_hbox title contents = box title (Box.hbox ~pos: `Top ~padding: (Num.cm 0.1) ~dx: (Num.cm 0.1) ~dy: (Num.cm 0.1) ~style: RoundRect ~stroke: (Some Color.red) ~fill: (Color.rgb8 255 255 210) contents) in let mlpost_mli = box_tex "mlpost.mli" ["module rec Num: sig ... end~~~~~~~~~~~"; "and Point: ..."] in let num_ml = box_tex "num.ml" ["type t = ..."; "let cm = ..."] in let color_ml = box_tex "color.ml" ["type t = ..."] in let box_ml = box_tex "box.ml" ["type t = ..."] in let types_mli = box_tex "types.mli" ["type num = ..."; "and point = ..."; "and box = ..."] in let mlpost = box_hbox "Mlpost" [num_ml; color_ml; box_ml] in let all = Box.vbox ~padding: (Num.cm 0.2) [mlpost_mli; mlpost; types_mli] in let arrow dir x y = let x = Box.get x all in let y = Box.get y all in Arrow.draw (Box.cpath ~outd: (Path.vec (Point.dir dir)) x y) in seq [ Box.draw all; arrow 270. "num.ml" "types.mli"; arrow 320. "color.ml" "types.mli"; arrow 270. "box.ml" "types.mli"; ] let () = Metapost.emit "sous_typage" sous_typage let () = Metapost.emit "automate_1" automate_1 let () = Metapost.emit "automate" automate let () = Metapost.emit "loop_explain" loop_explain let () = Metapost.emit "uml_client" uml_client let () = Metapost.emit "uml" uml let () = Metapost.emit "graph_sqrt" graph_sqrt let () = Metapost.emit "architecture" architecture let () = Metapost.emit "bresenham0" bresenham0 let () = Metapost.emit "bresenham" bresenham let () = Metapost.emit "sharing" sharing let () = Metapost.emit "tree_compile" sharingcompile let () = Metapost.emit "arrow_metapost" arrow_metapost let () = Metapost.emit "arrow_simple" arrow_simple let () = Metapost.emit "arrow_loop_explain" arrow_loop_explain let () = Metapost.emit "stages" stages let () = Metapost.emit "simple" simple let () = Metapost.emit "align" align let () = Metapost.emit "persistance" persistance let () = Metapost.emit "ford" (Command.draw_pic (ford 17)) let () = Metapost.emit "simple_block" simple_block let () = Metapost.emit "block_arrow" block_arrow let () = Metapost.emit "list123" list123 let () = Metapost.emit "another_list" another_list let () = Metapost.emit "deps" deps let () = Metapost.emit "circularity" circularity let () = Metapost.emit "circularity_solution" circularity_solution open Box let pen = Pen.scale (Num.bp 4.) Pen.circle let text = tex ~stroke:None ~dx:zero let texttt ?fill ?name s = text ?fill ?name ("\\texttt{" ^ s ^ "}") let pointer_arrow ?outd ?ind a b = let r = outd and l = ind in let p = pathk [knotp ?r (Box.ctr a); knotp ?l (Box.ctr b)] in let p = cut_after (Box.bpath b) p in Command.draw ~pen (pathp [Box.ctr a]) ++ draw_arrow p let self_arrow a b = let b = nth 0 b in let ya = ypart (ctr a) in let xb = xpart (ctr b) in let xright = xpart (ctr a) +/ multf 0.7 (width a) in let ytop = ypart (ctr b) +/ multf 1.1 (height b) in let p = pathk ~style:jLine [knotp (ctr a); knotp (Point.pt (xright, ya)); knotp (Point.pt (xright, ytop)); knotp (Point.pt (xb, ytop)); knotp (north b)] in let p = cut_after (Box.bpath b) p in Command.draw ~pen (pathp [Box.ctr a]) ++ draw_arrow p let closure1 = let height = bp 10. in let pointer ?name () = empty ?name ~width:(bp 15.) ~height () in let b = hbox ~padding:(bp 50.) ~pos:`Top [ vbox ~padding:(bp 30.) [hbox ~padding:(bp 20.) ~pos:`Top [texttt ~name:"pow" "pow"; vblock ~name:"closure pow" [tex "code"; pointer ()]]; hbox ~padding:(bp 20.) ~pos:`Top [texttt ~name:"sum" "sum"; vblock ~name:"closure sum" [tex "code"; tex "\\small 0.001"; pointer (); pointer ()]]; ]; vbox ~padding:(bp 15.) [ texttt ~name:"f" "f"; vblock ~name:"closure f" [tex "code"; texttt "n"; pointer ()]; ] ] in let arrow ?outd ?ind (x,i) (y,j) = pointer_arrow ?outd ?ind (nth i (get x b)) (nth j (get y b)) in let self_arrow x i = self_arrow (nth i (get x b)) (get x b) in let label s x i = Command.label ~pos:`Left (Picture.tex ("\\tt\\tiny " ^ s)) (Box.west (nth i (get x b))) in [Box.draw b; Helpers.box_arrow (get "pow" b) (nth 0 (get "closure pow" b)); self_arrow "closure pow" 1; label "pow" "closure pow" 1; Helpers.box_arrow (get "f" b) (nth 0 (get "closure f" b)); arrow ~outd:(vec left) ~ind:(vec left) ("closure f",2) ("closure pow",0); label "i" "closure f" 1; label "pow" "closure f" 2; Helpers.box_arrow (get "sum" b) (nth 0 (get "closure sum" b)); self_arrow "closure sum" 3; label "sum" "closure sum" 3; label "eps" "closure sum" 1; label "f" "closure sum" 2; arrow ~outd:(vec right) ~ind:(vec right) ("closure sum",2) ("closure f",0); ] let () = Metapost.emit "closure1" (seq closure1) open Tree let mlposttree = let tex = tex ~stroke:(Some Color.black) ~style:RoundRect in let leaf s = leaf (Box.tex s) in let node s = node ~arrow_style:Undirected (tex s) in [draw (node "\\mlpost" [node "\\ocaml" [leaf "\\dots"; leaf "\\dots"]; node "\\metapost" [node "\\LaTeX" []; leaf "\\dots"]])] let () = Metapost.emit "mlposttree" (seq mlposttree) let why_platform = let tabular l = "{\\begin{tabular}{l}" ^ String.concat " \\\\ " l ^ "\\end{tabular}}" in let dx = bp 5. and dy = bp 5. in let space ~name b = rect ~stroke:None ~name ~dx ~dy b in let green s = space ~name:s (round_rect ~dx ~dy ~stroke:None ~fill:Color.lightgreen (tex s)) in let pink s = space ~name:s (shadow (rect ~dx ~dy ~fill:(Color.color "light pink") (tex ("\\large\\sf " ^ s)))) in let interactive = tex ~name:"interactive" (tabular ["Interactive provers"; "(Coq, PVS,"; "Isabelle/HOL, etc.)"]) in let automatic = tex ~name:"automatic" (tabular ["Automatic provers"; "(Alt-Ergo, Simplify,"; "Yices, Z3, CVC3, etc.)"]) in let b = tabularl ~hpadding:(bp 20.) ~vpadding:(bp 30.) [[green "Annotated C programs"; empty (); green "JML-annotated Java programs"]; [pink "Caduceus"; green "Why program"; pink "Krakatoa";]; [empty (); pink "Why"; empty ()]; [interactive; green "verification conditions"; automatic]] in let arrow x y = let p = Box.cpath (get x b) (get y b) in Arrow.draw_thick ~line_color:Color.red ~width:(bp 4.) ~head_width:(bp 10.) ~fill_color:Color.red (Path.point 0. p) (Path.point 1. p) in [Box.draw b; arrow "Annotated C programs" "Caduceus"; arrow "Caduceus" "Why program"; arrow "JML-annotated Java programs" "Krakatoa"; arrow "Krakatoa" "Why program"; arrow "Why program" "Why"; arrow "Why" "verification conditions"; arrow "verification conditions" "interactive"; arrow "verification conditions" "automatic"; ] let () = Metapost.emit "why_platform" (seq why_platform) (* Local Variables: compile-command: "make figures.mp" End: *) mlpost-0.8.2/papers/jfla2009/figures_flo/000077500000000000000000000000001306046515300200675ustar00rootroot00000000000000mlpost-0.8.2/papers/jfla2009/figures_flo/automate_jfla.1000077500000000000000000000302451306046515300227730ustar00rootroot00000000000000%!PS %%BoundingBox: -12 -12 172 117 %%Creator: MetaPost %%CreationDate: 2009.01.29:1232 %%Pages: 1 %*Font: cmr10 9.96265 9.96265 30:fc %*Font: cmmi10 9.96265 9.96265 3b:8 %*Font: cmtt10 9.96265 9.96265 30:c %%EndProlog %%Page: 1 1 %%HiResBoundingBox: -11.44525 -11.44525 171.44525 116.73615 1 setgray newpath 131.19525 96 moveto 131.19525 98.9693 130.01553 101.81662 127.91608 103.91608 curveto 125.81662 106.01553 122.9693 107.19525 120 107.19525 curveto 117.0307 107.19525 114.18338 106.01553 112.08392 103.91608 curveto 109.98447 101.81662 108.80475 98.9693 108.80475 96 curveto 108.80475 93.0307 109.98447 90.18338 112.08392 88.08392 curveto 114.18338 85.98447 117.0307 84.80475 120 84.80475 curveto 122.9693 84.80475 125.81662 85.98447 127.91608 88.08392 curveto 130.01553 90.18338 131.19525 93.0307 131.19525 96 curveto closepath fill 0 setgray 112.80475 93.75839 moveto (4) cmr10 9.96265 fshow 117.78604 93.75839 moveto (;) cmmi10 9.96265 fshow 122.21385 93.75839 moveto (3) cmr10 9.96265 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinejoin 10 setmiterlimit newpath 131.19525 96 moveto 131.19525 98.9693 130.01553 101.81662 127.91608 103.91608 curveto 125.81662 106.01553 122.9693 107.19525 120 107.19525 curveto 117.0307 107.19525 114.18338 106.01553 112.08392 103.91608 curveto 109.98447 101.81662 108.80475 98.9693 108.80475 96 curveto 108.80475 93.0307 109.98447 90.18338 112.08392 88.08392 curveto 114.18338 85.98447 117.0307 84.80475 120 84.80475 curveto 122.9693 84.80475 125.81662 85.98447 127.91608 88.08392 curveto 130.01553 90.18338 131.19525 93.0307 131.19525 96 curveto closepath stroke 1 setgray newpath 51.19525 64 moveto 51.19525 66.9693 50.01553 69.81662 47.91608 71.91608 curveto 45.81662 74.01553 42.9693 75.19525 40 75.19525 curveto 37.0307 75.19525 34.18338 74.01553 32.08392 71.91608 curveto 29.98447 69.81662 28.80475 66.9693 28.80475 64 curveto 28.80475 61.0307 29.98447 58.18338 32.08392 56.08392 curveto 34.18338 53.98447 37.0307 52.80475 40 52.80475 curveto 42.9693 52.80475 45.81662 53.98447 47.91608 56.08392 curveto 50.01553 58.18338 51.19525 61.0307 51.19525 64 curveto closepath fill 0 setgray 32.80475 61.75839 moveto (2) cmr10 9.96265 fshow 37.78604 61.75839 moveto (;) cmmi10 9.96265 fshow 42.21385 61.75839 moveto (2) cmr10 9.96265 fshow newpath 51.19525 64 moveto 51.19525 66.9693 50.01553 69.81662 47.91608 71.91608 curveto 45.81662 74.01553 42.9693 75.19525 40 75.19525 curveto 37.0307 75.19525 34.18338 74.01553 32.08392 71.91608 curveto 29.98447 69.81662 28.80475 66.9693 28.80475 64 curveto 28.80475 61.0307 29.98447 58.18338 32.08392 56.08392 curveto 34.18338 53.98447 37.0307 52.80475 40 52.80475 curveto 42.9693 52.80475 45.81662 53.98447 47.91608 56.08392 curveto 50.01553 58.18338 51.19525 61.0307 51.19525 64 curveto closepath stroke 1 setgray newpath 11.19525 32 moveto 11.19525 34.9693 10.01553 37.81662 7.91608 39.91608 curveto 5.81662 42.01553 2.9693 43.19525 0 43.19525 curveto -2.9693 43.19525 -5.81662 42.01553 -7.91608 39.91608 curveto -10.01553 37.81662 -11.19525 34.9693 -11.19525 32 curveto -11.19525 29.0307 -10.01553 26.18338 -7.91608 24.08392 curveto -5.81662 21.98447 -2.9693 20.80475 0 20.80475 curveto 2.9693 20.80475 5.81662 21.98447 7.91608 24.08392 curveto 10.01553 26.18338 11.19525 29.0307 11.19525 32 curveto closepath fill 0 setgray -7.19525 29.75839 moveto (1) cmr10 9.96265 fshow -2.21396 29.75839 moveto (;) cmmi10 9.96265 fshow 2.21385 29.75839 moveto (1) cmr10 9.96265 fshow newpath 11.19525 32 moveto 11.19525 34.9693 10.01553 37.81662 7.91608 39.91608 curveto 5.81662 42.01553 2.9693 43.19525 0 43.19525 curveto -2.9693 43.19525 -5.81662 42.01553 -7.91608 39.91608 curveto -10.01553 37.81662 -11.19525 34.9693 -11.19525 32 curveto -11.19525 29.0307 -10.01553 26.18338 -7.91608 24.08392 curveto -5.81662 21.98447 -2.9693 20.80475 0 20.80475 curveto 2.9693 20.80475 5.81662 21.98447 7.91608 24.08392 curveto 10.01553 26.18338 11.19525 29.0307 11.19525 32 curveto closepath stroke 1 setgray newpath 171.19525 96 moveto 171.19525 98.9693 170.01553 101.81662 167.91608 103.91608 curveto 165.81662 106.01553 162.9693 107.19525 160 107.19525 curveto 157.0307 107.19525 154.18338 106.01553 152.08392 103.91608 curveto 149.98447 101.81662 148.80475 98.9693 148.80475 96 curveto 148.80475 93.0307 149.98447 90.18338 152.08392 88.08392 curveto 154.18338 85.98447 157.0307 84.80475 160 84.80475 curveto 162.9693 84.80475 165.81662 85.98447 167.91608 88.08392 curveto 170.01553 90.18338 171.19525 93.0307 171.19525 96 curveto closepath fill 0 setgray 152.80475 93.75839 moveto (5) cmr10 9.96265 fshow 157.78604 93.75839 moveto (;) cmmi10 9.96265 fshow 162.21385 93.75839 moveto (3) cmr10 9.96265 fshow newpath 171.19525 96 moveto 171.19525 98.9693 170.01553 101.81662 167.91608 103.91608 curveto 165.81662 106.01553 162.9693 107.19525 160 107.19525 curveto 157.0307 107.19525 154.18338 106.01553 152.08392 103.91608 curveto 149.98447 101.81662 148.80475 98.9693 148.80475 96 curveto 148.80475 93.0307 149.98447 90.18338 152.08392 88.08392 curveto 154.18338 85.98447 157.0307 84.80475 160 84.80475 curveto 162.9693 84.80475 165.81662 85.98447 167.91608 88.08392 curveto 170.01553 90.18338 171.19525 93.0307 171.19525 96 curveto closepath stroke 1 setgray newpath 131.19525 64 moveto 131.19525 66.9693 130.01553 69.81662 127.91608 71.91608 curveto 125.81662 74.01553 122.9693 75.19525 120 75.19525 curveto 117.0307 75.19525 114.18338 74.01553 112.08392 71.91608 curveto 109.98447 69.81662 108.80475 66.9693 108.80475 64 curveto 108.80475 61.0307 109.98447 58.18338 112.08392 56.08392 curveto 114.18338 53.98447 117.0307 52.80475 120 52.80475 curveto 122.9693 52.80475 125.81662 53.98447 127.91608 56.08392 curveto 130.01553 58.18338 131.19525 61.0307 131.19525 64 curveto closepath fill 0 setgray 112.80475 61.75839 moveto (4) cmr10 9.96265 fshow 117.78604 61.75839 moveto (;) cmmi10 9.96265 fshow 122.21385 61.75839 moveto (2) cmr10 9.96265 fshow newpath 131.19525 64 moveto 131.19525 66.9693 130.01553 69.81662 127.91608 71.91608 curveto 125.81662 74.01553 122.9693 75.19525 120 75.19525 curveto 117.0307 75.19525 114.18338 74.01553 112.08392 71.91608 curveto 109.98447 69.81662 108.80475 66.9693 108.80475 64 curveto 108.80475 61.0307 109.98447 58.18338 112.08392 56.08392 curveto 114.18338 53.98447 117.0307 52.80475 120 52.80475 curveto 122.9693 52.80475 125.81662 53.98447 127.91608 56.08392 curveto 130.01553 58.18338 131.19525 61.0307 131.19525 64 curveto closepath stroke 1 setgray newpath 91.19525 64 moveto 91.19525 66.9693 90.01553 69.81662 87.91608 71.91608 curveto 85.81662 74.01553 82.9693 75.19525 80 75.19525 curveto 77.0307 75.19525 74.18338 74.01553 72.08392 71.91608 curveto 69.98447 69.81662 68.80475 66.9693 68.80475 64 curveto 68.80475 61.0307 69.98447 58.18338 72.08392 56.08392 curveto 74.18338 53.98447 77.0307 52.80475 80 52.80475 curveto 82.9693 52.80475 85.81662 53.98447 87.91608 56.08392 curveto 90.01553 58.18338 91.19525 61.0307 91.19525 64 curveto closepath fill 0 setgray 72.80475 61.75839 moveto (3) cmr10 9.96265 fshow 77.78604 61.75839 moveto (;) cmmi10 9.96265 fshow 82.21385 61.75839 moveto (2) cmr10 9.96265 fshow newpath 91.19525 64 moveto 91.19525 66.9693 90.01553 69.81662 87.91608 71.91608 curveto 85.81662 74.01553 82.9693 75.19525 80 75.19525 curveto 77.0307 75.19525 74.18338 74.01553 72.08392 71.91608 curveto 69.98447 69.81662 68.80475 66.9693 68.80475 64 curveto 68.80475 61.0307 69.98447 58.18338 72.08392 56.08392 curveto 74.18338 53.98447 77.0307 52.80475 80 52.80475 curveto 82.9693 52.80475 85.81662 53.98447 87.91608 56.08392 curveto 90.01553 58.18338 91.19525 61.0307 91.19525 64 curveto closepath stroke 1 setgray newpath 51.19525 32 moveto 51.19525 34.9693 50.01553 37.81662 47.91608 39.91608 curveto 45.81662 42.01553 42.9693 43.19525 40 43.19525 curveto 37.0307 43.19525 34.18338 42.01553 32.08392 39.91608 curveto 29.98447 37.81662 28.80475 34.9693 28.80475 32 curveto 28.80475 29.0307 29.98447 26.18338 32.08392 24.08392 curveto 34.18338 21.98447 37.0307 20.80475 40 20.80475 curveto 42.9693 20.80475 45.81662 21.98447 47.91608 24.08392 curveto 50.01553 26.18338 51.19525 29.0307 51.19525 32 curveto closepath fill 0 setgray 32.80475 29.75839 moveto (2) cmr10 9.96265 fshow 37.78604 29.75839 moveto (;) cmmi10 9.96265 fshow 42.21385 29.75839 moveto (1) cmr10 9.96265 fshow newpath 51.19525 32 moveto 51.19525 34.9693 50.01553 37.81662 47.91608 39.91608 curveto 45.81662 42.01553 42.9693 43.19525 40 43.19525 curveto 37.0307 43.19525 34.18338 42.01553 32.08392 39.91608 curveto 29.98447 37.81662 28.80475 34.9693 28.80475 32 curveto 28.80475 29.0307 29.98447 26.18338 32.08392 24.08392 curveto 34.18338 21.98447 37.0307 20.80475 40 20.80475 curveto 42.9693 20.80475 45.81662 21.98447 47.91608 24.08392 curveto 50.01553 26.18338 51.19525 29.0307 51.19525 32 curveto closepath stroke 0.9 setgray newpath 11.19525 0 moveto 11.19525 2.9693 10.01553 5.81662 7.91608 7.91608 curveto 5.81662 10.01553 2.9693 11.19525 0 11.19525 curveto -2.9693 11.19525 -5.81662 10.01553 -7.91608 7.91608 curveto -10.01553 5.81662 -11.19525 2.9693 -11.19525 0 curveto -11.19525 -2.9693 -10.01553 -5.81662 -7.91608 -7.91608 curveto -5.81662 -10.01553 -2.9693 -11.19525 0 -11.19525 curveto 2.9693 -11.19525 5.81662 -10.01553 7.91608 -7.91608 curveto 10.01553 -5.81662 11.19525 -2.9693 11.19525 0 curveto closepath fill 0 setgray -7.19525 -2.24161 moveto (1) cmr10 9.96265 fshow -2.21396 -2.24161 moveto (;) cmmi10 9.96265 fshow 2.21385 -2.24161 moveto (0) cmr10 9.96265 fshow newpath 11.19525 0 moveto 11.19525 2.9693 10.01553 5.81662 7.91608 7.91608 curveto 5.81662 10.01553 2.9693 11.19525 0 11.19525 curveto -2.9693 11.19525 -5.81662 10.01553 -7.91608 7.91608 curveto -10.01553 5.81662 -11.19525 2.9693 -11.19525 0 curveto -11.19525 -2.9693 -10.01553 -5.81662 -7.91608 -7.91608 curveto -5.81662 -10.01553 -2.9693 -11.19525 0 -11.19525 curveto 2.9693 -11.19525 5.81662 -10.01553 7.91608 -7.91608 curveto 10.01553 -5.81662 11.19525 -2.9693 11.19525 0 curveto closepath stroke 1 setlinecap newpath 8.74205 6.99367 moveto 31.25832 25.00665 lineto stroke newpath 29.3289 21.50287 moveto 31.25832 25.00665 lineto 27.41646 23.89346 lineto closepath gsave fill grestore stroke 17.38504 19.00017 moveto (1) cmtt10 9.96265 fshow newpath 48.74205 38.99367 moveto 71.25832 57.00665 lineto stroke newpath 69.3289 53.50287 moveto 71.25832 57.00665 lineto 67.41646 55.89346 lineto closepath gsave fill grestore stroke 57.38504 51.00017 moveto (1) cmtt10 9.96265 fshow newpath 91.19507 64 moveto 108.80478 64 lineto stroke newpath 105.10938 62.46928 moveto 108.80478 64 lineto 105.10938 65.53072 lineto closepath gsave fill grestore stroke 97.38477 67 moveto (0) cmtt10 9.96265 fshow newpath 88.74205 70.99367 moveto 111.25832 89.00665 lineto stroke newpath 109.3289 85.50287 moveto 111.25832 89.00665 lineto 107.41646 87.89346 lineto closepath gsave fill grestore stroke 97.38504 83.00017 moveto (1) cmtt10 9.96265 fshow newpath 128.74205 70.99367 moveto 151.25832 89.00665 lineto stroke newpath 149.3289 85.50287 moveto 151.25832 89.00665 lineto 147.41646 87.89346 lineto closepath gsave fill grestore stroke 137.38504 83.00017 moveto (1) cmtt10 9.96265 fshow newpath 150.98024 102.62878 moveto 101.41603 134.25754 32.63745 104.47418 4.24364 42.35884 curveto stroke newpath 4.4452 46.35355 moveto 4.35916 45.02777 4.29187 43.69606 4.24364 42.35884 curveto 5.22333 43.27028 6.21259 44.16434 7.21089 45.04095 curveto closepath gsave fill grestore stroke 67.05786 110.64784 moveto (1) cmtt10 9.96265 fshow newpath 11.19507 32 moveto 28.80478 32 lineto stroke newpath 25.10938 30.46928 moveto 28.80478 32 lineto 25.10938 33.53072 lineto closepath gsave fill grestore stroke 17.38477 35 moveto (0) cmtt10 9.96265 fshow newpath 8.74205 38.99367 moveto 31.25832 57.00665 lineto stroke newpath 29.3289 53.50287 moveto 31.25832 57.00665 lineto 27.41646 55.89346 lineto closepath gsave fill grestore stroke 17.38504 51.00017 moveto (1) cmtt10 9.96265 fshow newpath 51.19507 64 moveto 68.80478 64 lineto stroke newpath 65.10938 62.46928 moveto 68.80478 64 lineto 65.10938 65.53072 lineto closepath gsave fill grestore stroke 57.38477 67 moveto (0) cmtt10 9.96265 fshow newpath 131.19507 96 moveto 148.80478 96 lineto stroke newpath 145.10938 94.46928 moveto 148.80478 96 lineto 145.10938 97.53072 lineto closepath gsave fill grestore stroke 137.38477 99 moveto (0) cmtt10 9.96265 fshow showpage %%EOF mlpost-0.8.2/papers/jfla2009/figures_flo/automate_jfla.mps000077500000000000000000000302451306046515300234320ustar00rootroot00000000000000%!PS %%BoundingBox: -12 -12 172 117 %%Creator: MetaPost %%CreationDate: 2009.01.29:1232 %%Pages: 1 %*Font: cmr10 9.96265 9.96265 30:fc %*Font: cmmi10 9.96265 9.96265 3b:8 %*Font: cmtt10 9.96265 9.96265 30:c %%EndProlog %%Page: 1 1 %%HiResBoundingBox: -11.44525 -11.44525 171.44525 116.73615 1 setgray newpath 131.19525 96 moveto 131.19525 98.9693 130.01553 101.81662 127.91608 103.91608 curveto 125.81662 106.01553 122.9693 107.19525 120 107.19525 curveto 117.0307 107.19525 114.18338 106.01553 112.08392 103.91608 curveto 109.98447 101.81662 108.80475 98.9693 108.80475 96 curveto 108.80475 93.0307 109.98447 90.18338 112.08392 88.08392 curveto 114.18338 85.98447 117.0307 84.80475 120 84.80475 curveto 122.9693 84.80475 125.81662 85.98447 127.91608 88.08392 curveto 130.01553 90.18338 131.19525 93.0307 131.19525 96 curveto closepath fill 0 setgray 112.80475 93.75839 moveto (4) cmr10 9.96265 fshow 117.78604 93.75839 moveto (;) cmmi10 9.96265 fshow 122.21385 93.75839 moveto (3) cmr10 9.96265 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinejoin 10 setmiterlimit newpath 131.19525 96 moveto 131.19525 98.9693 130.01553 101.81662 127.91608 103.91608 curveto 125.81662 106.01553 122.9693 107.19525 120 107.19525 curveto 117.0307 107.19525 114.18338 106.01553 112.08392 103.91608 curveto 109.98447 101.81662 108.80475 98.9693 108.80475 96 curveto 108.80475 93.0307 109.98447 90.18338 112.08392 88.08392 curveto 114.18338 85.98447 117.0307 84.80475 120 84.80475 curveto 122.9693 84.80475 125.81662 85.98447 127.91608 88.08392 curveto 130.01553 90.18338 131.19525 93.0307 131.19525 96 curveto closepath stroke 1 setgray newpath 51.19525 64 moveto 51.19525 66.9693 50.01553 69.81662 47.91608 71.91608 curveto 45.81662 74.01553 42.9693 75.19525 40 75.19525 curveto 37.0307 75.19525 34.18338 74.01553 32.08392 71.91608 curveto 29.98447 69.81662 28.80475 66.9693 28.80475 64 curveto 28.80475 61.0307 29.98447 58.18338 32.08392 56.08392 curveto 34.18338 53.98447 37.0307 52.80475 40 52.80475 curveto 42.9693 52.80475 45.81662 53.98447 47.91608 56.08392 curveto 50.01553 58.18338 51.19525 61.0307 51.19525 64 curveto closepath fill 0 setgray 32.80475 61.75839 moveto (2) cmr10 9.96265 fshow 37.78604 61.75839 moveto (;) cmmi10 9.96265 fshow 42.21385 61.75839 moveto (2) cmr10 9.96265 fshow newpath 51.19525 64 moveto 51.19525 66.9693 50.01553 69.81662 47.91608 71.91608 curveto 45.81662 74.01553 42.9693 75.19525 40 75.19525 curveto 37.0307 75.19525 34.18338 74.01553 32.08392 71.91608 curveto 29.98447 69.81662 28.80475 66.9693 28.80475 64 curveto 28.80475 61.0307 29.98447 58.18338 32.08392 56.08392 curveto 34.18338 53.98447 37.0307 52.80475 40 52.80475 curveto 42.9693 52.80475 45.81662 53.98447 47.91608 56.08392 curveto 50.01553 58.18338 51.19525 61.0307 51.19525 64 curveto closepath stroke 1 setgray newpath 11.19525 32 moveto 11.19525 34.9693 10.01553 37.81662 7.91608 39.91608 curveto 5.81662 42.01553 2.9693 43.19525 0 43.19525 curveto -2.9693 43.19525 -5.81662 42.01553 -7.91608 39.91608 curveto -10.01553 37.81662 -11.19525 34.9693 -11.19525 32 curveto -11.19525 29.0307 -10.01553 26.18338 -7.91608 24.08392 curveto -5.81662 21.98447 -2.9693 20.80475 0 20.80475 curveto 2.9693 20.80475 5.81662 21.98447 7.91608 24.08392 curveto 10.01553 26.18338 11.19525 29.0307 11.19525 32 curveto closepath fill 0 setgray -7.19525 29.75839 moveto (1) cmr10 9.96265 fshow -2.21396 29.75839 moveto (;) cmmi10 9.96265 fshow 2.21385 29.75839 moveto (1) cmr10 9.96265 fshow newpath 11.19525 32 moveto 11.19525 34.9693 10.01553 37.81662 7.91608 39.91608 curveto 5.81662 42.01553 2.9693 43.19525 0 43.19525 curveto -2.9693 43.19525 -5.81662 42.01553 -7.91608 39.91608 curveto -10.01553 37.81662 -11.19525 34.9693 -11.19525 32 curveto -11.19525 29.0307 -10.01553 26.18338 -7.91608 24.08392 curveto -5.81662 21.98447 -2.9693 20.80475 0 20.80475 curveto 2.9693 20.80475 5.81662 21.98447 7.91608 24.08392 curveto 10.01553 26.18338 11.19525 29.0307 11.19525 32 curveto closepath stroke 1 setgray newpath 171.19525 96 moveto 171.19525 98.9693 170.01553 101.81662 167.91608 103.91608 curveto 165.81662 106.01553 162.9693 107.19525 160 107.19525 curveto 157.0307 107.19525 154.18338 106.01553 152.08392 103.91608 curveto 149.98447 101.81662 148.80475 98.9693 148.80475 96 curveto 148.80475 93.0307 149.98447 90.18338 152.08392 88.08392 curveto 154.18338 85.98447 157.0307 84.80475 160 84.80475 curveto 162.9693 84.80475 165.81662 85.98447 167.91608 88.08392 curveto 170.01553 90.18338 171.19525 93.0307 171.19525 96 curveto closepath fill 0 setgray 152.80475 93.75839 moveto (5) cmr10 9.96265 fshow 157.78604 93.75839 moveto (;) cmmi10 9.96265 fshow 162.21385 93.75839 moveto (3) cmr10 9.96265 fshow newpath 171.19525 96 moveto 171.19525 98.9693 170.01553 101.81662 167.91608 103.91608 curveto 165.81662 106.01553 162.9693 107.19525 160 107.19525 curveto 157.0307 107.19525 154.18338 106.01553 152.08392 103.91608 curveto 149.98447 101.81662 148.80475 98.9693 148.80475 96 curveto 148.80475 93.0307 149.98447 90.18338 152.08392 88.08392 curveto 154.18338 85.98447 157.0307 84.80475 160 84.80475 curveto 162.9693 84.80475 165.81662 85.98447 167.91608 88.08392 curveto 170.01553 90.18338 171.19525 93.0307 171.19525 96 curveto closepath stroke 1 setgray newpath 131.19525 64 moveto 131.19525 66.9693 130.01553 69.81662 127.91608 71.91608 curveto 125.81662 74.01553 122.9693 75.19525 120 75.19525 curveto 117.0307 75.19525 114.18338 74.01553 112.08392 71.91608 curveto 109.98447 69.81662 108.80475 66.9693 108.80475 64 curveto 108.80475 61.0307 109.98447 58.18338 112.08392 56.08392 curveto 114.18338 53.98447 117.0307 52.80475 120 52.80475 curveto 122.9693 52.80475 125.81662 53.98447 127.91608 56.08392 curveto 130.01553 58.18338 131.19525 61.0307 131.19525 64 curveto closepath fill 0 setgray 112.80475 61.75839 moveto (4) cmr10 9.96265 fshow 117.78604 61.75839 moveto (;) cmmi10 9.96265 fshow 122.21385 61.75839 moveto (2) cmr10 9.96265 fshow newpath 131.19525 64 moveto 131.19525 66.9693 130.01553 69.81662 127.91608 71.91608 curveto 125.81662 74.01553 122.9693 75.19525 120 75.19525 curveto 117.0307 75.19525 114.18338 74.01553 112.08392 71.91608 curveto 109.98447 69.81662 108.80475 66.9693 108.80475 64 curveto 108.80475 61.0307 109.98447 58.18338 112.08392 56.08392 curveto 114.18338 53.98447 117.0307 52.80475 120 52.80475 curveto 122.9693 52.80475 125.81662 53.98447 127.91608 56.08392 curveto 130.01553 58.18338 131.19525 61.0307 131.19525 64 curveto closepath stroke 1 setgray newpath 91.19525 64 moveto 91.19525 66.9693 90.01553 69.81662 87.91608 71.91608 curveto 85.81662 74.01553 82.9693 75.19525 80 75.19525 curveto 77.0307 75.19525 74.18338 74.01553 72.08392 71.91608 curveto 69.98447 69.81662 68.80475 66.9693 68.80475 64 curveto 68.80475 61.0307 69.98447 58.18338 72.08392 56.08392 curveto 74.18338 53.98447 77.0307 52.80475 80 52.80475 curveto 82.9693 52.80475 85.81662 53.98447 87.91608 56.08392 curveto 90.01553 58.18338 91.19525 61.0307 91.19525 64 curveto closepath fill 0 setgray 72.80475 61.75839 moveto (3) cmr10 9.96265 fshow 77.78604 61.75839 moveto (;) cmmi10 9.96265 fshow 82.21385 61.75839 moveto (2) cmr10 9.96265 fshow newpath 91.19525 64 moveto 91.19525 66.9693 90.01553 69.81662 87.91608 71.91608 curveto 85.81662 74.01553 82.9693 75.19525 80 75.19525 curveto 77.0307 75.19525 74.18338 74.01553 72.08392 71.91608 curveto 69.98447 69.81662 68.80475 66.9693 68.80475 64 curveto 68.80475 61.0307 69.98447 58.18338 72.08392 56.08392 curveto 74.18338 53.98447 77.0307 52.80475 80 52.80475 curveto 82.9693 52.80475 85.81662 53.98447 87.91608 56.08392 curveto 90.01553 58.18338 91.19525 61.0307 91.19525 64 curveto closepath stroke 1 setgray newpath 51.19525 32 moveto 51.19525 34.9693 50.01553 37.81662 47.91608 39.91608 curveto 45.81662 42.01553 42.9693 43.19525 40 43.19525 curveto 37.0307 43.19525 34.18338 42.01553 32.08392 39.91608 curveto 29.98447 37.81662 28.80475 34.9693 28.80475 32 curveto 28.80475 29.0307 29.98447 26.18338 32.08392 24.08392 curveto 34.18338 21.98447 37.0307 20.80475 40 20.80475 curveto 42.9693 20.80475 45.81662 21.98447 47.91608 24.08392 curveto 50.01553 26.18338 51.19525 29.0307 51.19525 32 curveto closepath fill 0 setgray 32.80475 29.75839 moveto (2) cmr10 9.96265 fshow 37.78604 29.75839 moveto (;) cmmi10 9.96265 fshow 42.21385 29.75839 moveto (1) cmr10 9.96265 fshow newpath 51.19525 32 moveto 51.19525 34.9693 50.01553 37.81662 47.91608 39.91608 curveto 45.81662 42.01553 42.9693 43.19525 40 43.19525 curveto 37.0307 43.19525 34.18338 42.01553 32.08392 39.91608 curveto 29.98447 37.81662 28.80475 34.9693 28.80475 32 curveto 28.80475 29.0307 29.98447 26.18338 32.08392 24.08392 curveto 34.18338 21.98447 37.0307 20.80475 40 20.80475 curveto 42.9693 20.80475 45.81662 21.98447 47.91608 24.08392 curveto 50.01553 26.18338 51.19525 29.0307 51.19525 32 curveto closepath stroke 0.9 setgray newpath 11.19525 0 moveto 11.19525 2.9693 10.01553 5.81662 7.91608 7.91608 curveto 5.81662 10.01553 2.9693 11.19525 0 11.19525 curveto -2.9693 11.19525 -5.81662 10.01553 -7.91608 7.91608 curveto -10.01553 5.81662 -11.19525 2.9693 -11.19525 0 curveto -11.19525 -2.9693 -10.01553 -5.81662 -7.91608 -7.91608 curveto -5.81662 -10.01553 -2.9693 -11.19525 0 -11.19525 curveto 2.9693 -11.19525 5.81662 -10.01553 7.91608 -7.91608 curveto 10.01553 -5.81662 11.19525 -2.9693 11.19525 0 curveto closepath fill 0 setgray -7.19525 -2.24161 moveto (1) cmr10 9.96265 fshow -2.21396 -2.24161 moveto (;) cmmi10 9.96265 fshow 2.21385 -2.24161 moveto (0) cmr10 9.96265 fshow newpath 11.19525 0 moveto 11.19525 2.9693 10.01553 5.81662 7.91608 7.91608 curveto 5.81662 10.01553 2.9693 11.19525 0 11.19525 curveto -2.9693 11.19525 -5.81662 10.01553 -7.91608 7.91608 curveto -10.01553 5.81662 -11.19525 2.9693 -11.19525 0 curveto -11.19525 -2.9693 -10.01553 -5.81662 -7.91608 -7.91608 curveto -5.81662 -10.01553 -2.9693 -11.19525 0 -11.19525 curveto 2.9693 -11.19525 5.81662 -10.01553 7.91608 -7.91608 curveto 10.01553 -5.81662 11.19525 -2.9693 11.19525 0 curveto closepath stroke 1 setlinecap newpath 8.74205 6.99367 moveto 31.25832 25.00665 lineto stroke newpath 29.3289 21.50287 moveto 31.25832 25.00665 lineto 27.41646 23.89346 lineto closepath gsave fill grestore stroke 17.38504 19.00017 moveto (1) cmtt10 9.96265 fshow newpath 48.74205 38.99367 moveto 71.25832 57.00665 lineto stroke newpath 69.3289 53.50287 moveto 71.25832 57.00665 lineto 67.41646 55.89346 lineto closepath gsave fill grestore stroke 57.38504 51.00017 moveto (1) cmtt10 9.96265 fshow newpath 91.19507 64 moveto 108.80478 64 lineto stroke newpath 105.10938 62.46928 moveto 108.80478 64 lineto 105.10938 65.53072 lineto closepath gsave fill grestore stroke 97.38477 67 moveto (0) cmtt10 9.96265 fshow newpath 88.74205 70.99367 moveto 111.25832 89.00665 lineto stroke newpath 109.3289 85.50287 moveto 111.25832 89.00665 lineto 107.41646 87.89346 lineto closepath gsave fill grestore stroke 97.38504 83.00017 moveto (1) cmtt10 9.96265 fshow newpath 128.74205 70.99367 moveto 151.25832 89.00665 lineto stroke newpath 149.3289 85.50287 moveto 151.25832 89.00665 lineto 147.41646 87.89346 lineto closepath gsave fill grestore stroke 137.38504 83.00017 moveto (1) cmtt10 9.96265 fshow newpath 150.98024 102.62878 moveto 101.41603 134.25754 32.63745 104.47418 4.24364 42.35884 curveto stroke newpath 4.4452 46.35355 moveto 4.35916 45.02777 4.29187 43.69606 4.24364 42.35884 curveto 5.22333 43.27028 6.21259 44.16434 7.21089 45.04095 curveto closepath gsave fill grestore stroke 67.05786 110.64784 moveto (1) cmtt10 9.96265 fshow newpath 11.19507 32 moveto 28.80478 32 lineto stroke newpath 25.10938 30.46928 moveto 28.80478 32 lineto 25.10938 33.53072 lineto closepath gsave fill grestore stroke 17.38477 35 moveto (0) cmtt10 9.96265 fshow newpath 8.74205 38.99367 moveto 31.25832 57.00665 lineto stroke newpath 29.3289 53.50287 moveto 31.25832 57.00665 lineto 27.41646 55.89346 lineto closepath gsave fill grestore stroke 17.38504 51.00017 moveto (1) cmtt10 9.96265 fshow newpath 51.19507 64 moveto 68.80478 64 lineto stroke newpath 65.10938 62.46928 moveto 68.80478 64 lineto 65.10938 65.53072 lineto closepath gsave fill grestore stroke 57.38477 67 moveto (0) cmtt10 9.96265 fshow newpath 131.19507 96 moveto 148.80478 96 lineto stroke newpath 145.10938 94.46928 moveto 148.80478 96 lineto 145.10938 97.53072 lineto closepath gsave fill grestore stroke 137.38477 99 moveto (0) cmtt10 9.96265 fshow showpage %%EOF mlpost-0.8.2/papers/jfla2009/figures_flo/chrono2_0_aplas.1000077500000000000000000000346671306046515300231450ustar00rootroot00000000000000%!PS %%BoundingBox: -90 -104 286 143 %%Creator: MetaPost %%CreationDate: 2008.12.10:0659 %%Pages: 1 %*Font: cmss10 9.96265 9.96265 49:840000cc0e78 %*Font: cmr10 9.96265 9.96265 32:d1 %*Font: cmsy10 9.96265 9.96265 4f:8 %*Font: cmmi7 6.97385 6.97385 77:8 %*Font: cmr5 4.98132 4.98132 32:8 %*Font: cmmi12 14.34616 11.95517 3b:8000000002 %*Font: cmr12 14.34616 11.95517 3d:8 %*Font: cmex10 14.34624 9.96265 00:f %*Font: cmmi10 9.96265 9.96265 77:8 %*Font: cmr7 6.97385 6.97385 32:8 %*Font: cmss10 7.99994 9.96265 30:ffc %*Font: cmr10 7.99994 9.96265 3d:8 %*Font: cmsy10 13.47153 9.96265 67:8 %*Font: cmmi10 7.99994 9.96265 44:800080008 %*Font: cmr7 5.59996 6.97385 33:a2 %%EndProlog %%Page: 1 1 0.65 setgray 0 0.4 dtransform truncate idtransform setlinewidth pop [0 1.7501 ] 0.87506 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 140 moveto 189 140 lineto stroke newpath 0 120 moveto 189 120 lineto stroke newpath 0 100 moveto 189 100 lineto stroke newpath 0 80 moveto 189 80 lineto stroke newpath 0 60 moveto 189 60 lineto stroke newpath 0 40 moveto 189 40 lineto stroke newpath 0 20 moveto 189 20 lineto stroke newpath 0 0 moveto 189 0 lineto stroke 0.4 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 140 lineto stroke newpath 173.25 0 moveto 173.25 140 lineto stroke newpath 157.5 0 moveto 157.5 140 lineto stroke newpath 141.75 0 moveto 141.75 140 lineto stroke newpath 126 0 moveto 126 140 lineto stroke newpath 110.25 0 moveto 110.25 140 lineto stroke newpath 94.5 0 moveto 94.5 140 lineto stroke newpath 78.75 0 moveto 78.75 140 lineto stroke newpath 63 0 moveto 63 140 lineto stroke newpath 47.25 0 moveto 47.25 140 lineto stroke newpath 31.5 0 moveto 31.5 140 lineto stroke newpath 15.75 0 moveto 15.75 140 lineto stroke newpath 0 0 moveto 0 140 lineto stroke 0 setgray 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash newpath 0 0 moveto 189 0 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 0 moveto 0 140 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 140 moveto 189 140 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 140 lineto stroke 154.21701 -17.72218 moveto (Instants) cmss10 9.96265 fshow gsave [0 1 -1 0 -9.5592 71.48232 ] concat 0 0 moveto (Numb) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -9.5592 97.02551 ] concat 0 0 moveto (er) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -9.5592 108.17812 ] concat 0 0 moveto (of) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -9.5592 119.52452 ] concat 0 0 moveto (ones) cmss10 9.96265 fshow grestore 185 -8.24443 moveto (12) cmss10 7.99994 fshow newpath 189 0 moveto 189 5 lineto stroke newpath 189 140 moveto 189 135 lineto stroke 169.25 -8.24443 moveto (11) cmss10 7.99994 fshow newpath 173.25 0 moveto 173.25 5 lineto stroke newpath 173.25 140 moveto 173.25 135 lineto stroke 153.5 -8.24443 moveto (10) cmss10 7.99994 fshow newpath 157.5 0 moveto 157.5 5 lineto stroke newpath 157.5 140 moveto 157.5 135 lineto stroke 139.75002 -8.24443 moveto (9) cmss10 7.99994 fshow newpath 141.75 0 moveto 141.75 5 lineto stroke newpath 141.75 140 moveto 141.75 135 lineto stroke 124.00002 -8.24443 moveto (8) cmss10 7.99994 fshow newpath 126 0 moveto 126 5 lineto stroke newpath 126 140 moveto 126 135 lineto stroke 108.25002 -8.24443 moveto (7) cmss10 7.99994 fshow newpath 110.25 0 moveto 110.25 5 lineto stroke newpath 110.25 140 moveto 110.25 135 lineto stroke 92.50002 -8.24443 moveto (6) cmss10 7.99994 fshow newpath 94.5 0 moveto 94.5 5 lineto stroke newpath 94.5 140 moveto 94.5 135 lineto stroke 76.75002 -8.24443 moveto (5) cmss10 7.99994 fshow newpath 78.75 0 moveto 78.75 5 lineto stroke newpath 78.75 140 moveto 78.75 135 lineto stroke 61.00002 -8.24443 moveto (4) cmss10 7.99994 fshow newpath 63 0 moveto 63 5 lineto stroke newpath 63 140 moveto 63 135 lineto stroke 45.25002 -8.24443 moveto (3) cmss10 7.99994 fshow newpath 47.25 0 moveto 47.25 5 lineto stroke newpath 47.25 140 moveto 47.25 135 lineto stroke 29.50002 -8.24443 moveto (2) cmss10 7.99994 fshow newpath 31.5 0 moveto 31.5 5 lineto stroke newpath 31.5 140 moveto 31.5 135 lineto stroke 13.75002 -8.24443 moveto (1) cmss10 7.99994 fshow newpath 15.75 0 moveto 15.75 5 lineto stroke newpath 15.75 140 moveto 15.75 135 lineto stroke -1.99998 -8.24443 moveto (0) cmss10 7.99994 fshow newpath 0 0 moveto 0 5 lineto stroke newpath 0 140 moveto 0 135 lineto stroke -6.99995 137.37778 moveto (7) cmss10 7.99994 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 140 moveto 3.9375 140 lineto stroke newpath 189 140 moveto 184 140 lineto stroke -6.99995 117.37778 moveto (6) cmss10 7.99994 fshow newpath 0 120 moveto 3.9375 120 lineto stroke newpath 189 120 moveto 184 120 lineto stroke -6.99995 97.37778 moveto (5) cmss10 7.99994 fshow newpath 0 100 moveto 3.9375 100 lineto stroke newpath 189 100 moveto 184 100 lineto stroke -6.99995 77.37778 moveto (4) cmss10 7.99994 fshow newpath 0 80 moveto 3.9375 80 lineto stroke newpath 189 80 moveto 184 80 lineto stroke -6.99995 57.37778 moveto (3) cmss10 7.99994 fshow newpath 0 60 moveto 3.9375 60 lineto stroke newpath 189 60 moveto 184 60 lineto stroke -6.99995 37.37778 moveto (2) cmss10 7.99994 fshow newpath 0 40 moveto 3.9375 40 lineto stroke newpath 189 40 moveto 184 40 lineto stroke -6.99995 17.37778 moveto (1) cmss10 7.99994 fshow newpath 0 20 moveto 3.9375 20 lineto stroke newpath 189 20 moveto 184 20 lineto stroke -6.99995 -2.62222 moveto (0) cmss10 7.99994 fshow newpath 0 0 moveto 3.9375 0 lineto stroke newpath 189 0 moveto 184 0 lineto stroke 0.6 0 0.6 setrgbcolor 168.8188 124.59059 moveto (O) cmsy10 9.96265 fshow 176.7502 123.09619 moveto (w) cmmi7 6.97385 fshow 182.5136 122.09999 moveto (2) cmr5 4.98132 fshow gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 189 120 moveto 189 120 lineto 173.25 120 lineto 173.25 120 lineto 157.5 120 lineto 157.5 100 lineto 141.75 100 lineto 141.75 80 lineto 126 80 lineto 126 60 lineto 110.25 60 lineto 110.25 60 lineto 94.5 60 lineto 94.5 60 lineto 78.75 60 lineto 78.75 40 lineto 63 40 lineto 63 20 lineto 47.25 20 lineto 47.25 0 lineto 31.5 0 lineto 31.5 0 lineto 15.75 0 lineto 15.75 0 lineto 0 0 lineto 0 0 lineto stroke grestore gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 124 moveto 173.25 112 lineto 157.5 100 lineto 141.75 88 lineto 126 76 lineto 110.25 64 lineto 94.5 52 lineto 78.75 40 lineto 63 28 lineto 47.25 16 lineto 31.5 4 lineto 15.75 -8 lineto 0 -20 lineto stroke grestore gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 108 moveto 173.25 96 lineto 157.5 84 lineto 141.75 72 lineto 126 60 lineto 110.25 48 lineto 94.5 36 lineto 78.75 24 lineto 63 12 lineto 47.25 0 lineto 31.5 -12 lineto 15.75 -24 lineto 0 -36 lineto stroke grestore 0.6 0 0.6 setrgbcolor gsave [0.73953 0 0 1.20544 191.09999 112.15985 ] concat 0 0 moveto (g) cmsy10 13.47153 fshow grestore 197.4 113.12129 moveto (a) cmmi12 14.34616 fshow 204.7739 110.96939 moveto (2) cmr10 9.96265 fshow 214.23839 113.12129 moveto (=) cmr12 14.34616 fshow 229.14899 124.74179 moveto (\002) cmex10 14.34624 fshow 236.3221 118.7699 moveto (5) cmr10 9.96265 fshow 0 0.5738 dtransform truncate idtransform setlinewidth pop [] 0 setdash 0 setlinecap 1 setlinejoin 10 setmiterlimit newpath 236.3221 116.7078 moveto 241.30339 116.7078 lineto stroke 236.3221 108.1742 moveto (3) cmr10 9.96265 fshow 242.4989 113.12129 moveto (;) cmmi12 14.34616 fshow 249.9874 118.7699 moveto (9) cmr10 9.96265 fshow newpath 249.9874 116.7078 moveto 254.96869 116.7078 lineto stroke 249.9874 108.1742 moveto (3) cmr10 9.96265 fshow 256.16429 124.74179 moveto (\003) cmex10 14.34624 fshow 264.53279 124.74179 moveto (\000) cmex10 14.34624 fshow 272.3037 118.7699 moveto (5) cmr10 9.96265 fshow newpath 272.3037 116.7078 moveto 277.2851 116.7078 lineto stroke 272.3037 108.1742 moveto (3) cmr10 9.96265 fshow 278.48059 124.74179 moveto (\001) cmex10 14.34624 fshow 0 setgray 0 1.25 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 0 -50 moveto 189 -50 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -50 moveto 0 -47.6 lineto stroke newpath 15.75 -50 moveto 15.75 -47.6 lineto stroke newpath 31.5 -50 moveto 31.5 -47.6 lineto stroke newpath 47.25 -50 moveto 47.25 -47.6 lineto stroke newpath 63 -50 moveto 63 -47.6 lineto stroke newpath 78.75 -50 moveto 78.75 -47.6 lineto stroke newpath 94.5 -50 moveto 94.5 -47.6 lineto stroke newpath 110.25 -50 moveto 110.25 -47.6 lineto stroke newpath 126 -50 moveto 126 -47.6 lineto stroke newpath 141.75 -50 moveto 141.75 -47.6 lineto stroke newpath 157.5 -50 moveto 157.5 -47.6 lineto stroke newpath 173.25 -50 moveto 173.25 -47.6 lineto stroke newpath 189 -50 moveto 189 -47.6 lineto stroke newpath 26.25 -50 moveto 26.25 -38 lineto stroke newpath 52.5 -50 moveto 52.5 -38 lineto stroke newpath 78.75 -50 moveto 78.75 -38 lineto stroke newpath 105 -50 moveto 105 -38 lineto stroke newpath 131.25 -50 moveto 131.25 -38 lineto stroke newpath 157.5 -50 moveto 157.5 -38 lineto stroke newpath 183.75 -50 moveto 183.75 -38 lineto stroke 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 0 -68 moveto 189 -68 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -68 moveto 0 -65.6 lineto stroke newpath 15.75 -68 moveto 15.75 -65.6 lineto stroke newpath 31.5 -68 moveto 31.5 -65.6 lineto stroke newpath 47.25 -68 moveto 47.25 -65.6 lineto stroke newpath 63 -68 moveto 63 -65.6 lineto stroke newpath 78.75 -68 moveto 78.75 -65.6 lineto stroke newpath 94.5 -68 moveto 94.5 -65.6 lineto stroke newpath 110.25 -68 moveto 110.25 -65.6 lineto stroke newpath 126 -68 moveto 126 -65.6 lineto stroke newpath 141.75 -68 moveto 141.75 -65.6 lineto stroke newpath 157.5 -68 moveto 157.5 -65.6 lineto stroke newpath 173.25 -68 moveto 173.25 -65.6 lineto stroke newpath 189 -68 moveto 189 -65.6 lineto stroke -13.7018 -64.40561 moveto (w) cmmi10 9.96265 fshow -6.5694 -65.90001 moveto (2) cmr7 6.97385 fshow newpath 47.25 -68 moveto 47.25 -56 lineto stroke newpath 63 -68 moveto 63 -56 lineto stroke newpath 78.75 -68 moveto 78.75 -56 lineto stroke newpath 126 -68 moveto 126 -56 lineto stroke newpath 141.75 -68 moveto 141.75 -56 lineto stroke newpath 157.5 -68 moveto 157.5 -56 lineto stroke 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 0 -86 moveto 189 -86 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -86 moveto 0 -83.6 lineto stroke newpath 15.75 -86 moveto 15.75 -83.6 lineto stroke newpath 31.5 -86 moveto 31.5 -83.6 lineto stroke newpath 47.25 -86 moveto 47.25 -83.6 lineto stroke newpath 63 -86 moveto 63 -83.6 lineto stroke newpath 78.75 -86 moveto 78.75 -83.6 lineto stroke newpath 94.5 -86 moveto 94.5 -83.6 lineto stroke newpath 110.25 -86 moveto 110.25 -83.6 lineto stroke newpath 126 -86 moveto 126 -83.6 lineto stroke newpath 141.75 -86 moveto 141.75 -83.6 lineto stroke newpath 157.5 -86 moveto 157.5 -83.6 lineto stroke newpath 173.25 -86 moveto 173.25 -83.6 lineto stroke newpath 189 -86 moveto 189 -83.6 lineto stroke newpath 47.25 -86 moveto 47.25 -74 lineto stroke newpath 73.5 -86 moveto 73.5 -74 lineto stroke newpath 99.75 -86 moveto 99.75 -74 lineto stroke newpath 126 -86 moveto 126 -74 lineto stroke newpath 152.25 -86 moveto 152.25 -74 lineto stroke newpath 178.5 -86 moveto 178.5 -74 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 -39.2 moveto 3.46419 -37.19995 lineto stroke newpath 0 -39.2 moveto 3.46419 -41.20004 lineto stroke newpath 0 -39.2 moveto 26.25 -39.2 lineto stroke newpath 26.25 -39.2 moveto 22.78581 -41.20004 lineto stroke newpath 26.25 -39.2 moveto 22.78581 -37.19995 lineto stroke 3.15538 -33.4413 moveto (d) cmmi10 7.99994 fshow 9.54143 -33.4413 moveto (=) cmr10 7.99994 fshow 18.9457 -30.29147 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 18.9457 -31.44128 moveto 22.13463 -31.44128 lineto stroke 18.9457 -36.19998 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 26.25 -39.2 moveto 52.5 -39.2 lineto stroke newpath 48.80464 -40.7307 moveto 52.5 -39.2 lineto 48.80464 -37.6693 lineto closepath gsave fill grestore stroke newpath 52.5 -39.2 moveto 26.25 -39.2 lineto stroke newpath 29.94536 -37.6693 moveto 26.25 -39.2 lineto 29.94536 -40.7307 lineto closepath gsave fill grestore stroke 28.59428 -33.4413 moveto (T) cmmi10 7.99994 fshow 36.60255 -33.4413 moveto (=) cmr10 7.99994 fshow 46.00688 -30.29147 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 46.00688 -31.44128 moveto 49.19574 -31.44128 lineto stroke 46.00688 -36.19998 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 0 -90.8 moveto 3.4641 -88.8 lineto stroke newpath 0 -90.8 moveto 3.4641 -92.8 lineto stroke newpath 0 -90.8 moveto 47.25 -90.8 lineto stroke newpath 47.25 -90.8 moveto 43.7859 -92.8 lineto stroke newpath 47.25 -90.8 moveto 43.7859 -88.8 lineto stroke 12.31454 -100.55872 moveto (D) cmmi10 7.99994 fshow 21.38219 -100.55872 moveto (=) cmr10 7.99994 fshow 30.78654 -97.40889 moveto (9) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 30.78654 -98.5587 moveto 33.97539 -98.5587 lineto stroke 30.78654 -103.3174 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 47.25 -90.8 moveto 73.5 -90.8 lineto stroke newpath 69.80464 -92.3307 moveto 73.5 -90.8 lineto 69.80464 -89.2693 lineto closepath gsave fill grestore stroke newpath 73.5 -90.8 moveto 47.25 -90.8 lineto stroke newpath 50.94536 -89.2693 moveto 47.25 -90.8 lineto 50.94536 -92.3307 lineto closepath gsave fill grestore stroke 49.59428 -100.55872 moveto (T) cmmi10 7.99994 fshow 57.60255 -100.55872 moveto (=) cmr10 7.99994 fshow 67.00688 -97.40889 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 67.00688 -98.5587 moveto 70.19574 -98.5587 lineto stroke 67.00688 -103.3174 moveto (3) cmr7 5.59996 fshow showpage %%EOF mlpost-0.8.2/papers/jfla2009/figures_flo/chrono2_0_aplas.mps000077500000000000000000000346671306046515300236040ustar00rootroot00000000000000%!PS %%BoundingBox: -90 -104 286 143 %%Creator: MetaPost %%CreationDate: 2008.12.10:0659 %%Pages: 1 %*Font: cmss10 9.96265 9.96265 49:840000cc0e78 %*Font: cmr10 9.96265 9.96265 32:d1 %*Font: cmsy10 9.96265 9.96265 4f:8 %*Font: cmmi7 6.97385 6.97385 77:8 %*Font: cmr5 4.98132 4.98132 32:8 %*Font: cmmi12 14.34616 11.95517 3b:8000000002 %*Font: cmr12 14.34616 11.95517 3d:8 %*Font: cmex10 14.34624 9.96265 00:f %*Font: cmmi10 9.96265 9.96265 77:8 %*Font: cmr7 6.97385 6.97385 32:8 %*Font: cmss10 7.99994 9.96265 30:ffc %*Font: cmr10 7.99994 9.96265 3d:8 %*Font: cmsy10 13.47153 9.96265 67:8 %*Font: cmmi10 7.99994 9.96265 44:800080008 %*Font: cmr7 5.59996 6.97385 33:a2 %%EndProlog %%Page: 1 1 0.65 setgray 0 0.4 dtransform truncate idtransform setlinewidth pop [0 1.7501 ] 0.87506 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 140 moveto 189 140 lineto stroke newpath 0 120 moveto 189 120 lineto stroke newpath 0 100 moveto 189 100 lineto stroke newpath 0 80 moveto 189 80 lineto stroke newpath 0 60 moveto 189 60 lineto stroke newpath 0 40 moveto 189 40 lineto stroke newpath 0 20 moveto 189 20 lineto stroke newpath 0 0 moveto 189 0 lineto stroke 0.4 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 140 lineto stroke newpath 173.25 0 moveto 173.25 140 lineto stroke newpath 157.5 0 moveto 157.5 140 lineto stroke newpath 141.75 0 moveto 141.75 140 lineto stroke newpath 126 0 moveto 126 140 lineto stroke newpath 110.25 0 moveto 110.25 140 lineto stroke newpath 94.5 0 moveto 94.5 140 lineto stroke newpath 78.75 0 moveto 78.75 140 lineto stroke newpath 63 0 moveto 63 140 lineto stroke newpath 47.25 0 moveto 47.25 140 lineto stroke newpath 31.5 0 moveto 31.5 140 lineto stroke newpath 15.75 0 moveto 15.75 140 lineto stroke newpath 0 0 moveto 0 140 lineto stroke 0 setgray 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash newpath 0 0 moveto 189 0 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 0 moveto 0 140 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 140 moveto 189 140 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 140 lineto stroke 154.21701 -17.72218 moveto (Instants) cmss10 9.96265 fshow gsave [0 1 -1 0 -9.5592 71.48232 ] concat 0 0 moveto (Numb) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -9.5592 97.02551 ] concat 0 0 moveto (er) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -9.5592 108.17812 ] concat 0 0 moveto (of) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -9.5592 119.52452 ] concat 0 0 moveto (ones) cmss10 9.96265 fshow grestore 185 -8.24443 moveto (12) cmss10 7.99994 fshow newpath 189 0 moveto 189 5 lineto stroke newpath 189 140 moveto 189 135 lineto stroke 169.25 -8.24443 moveto (11) cmss10 7.99994 fshow newpath 173.25 0 moveto 173.25 5 lineto stroke newpath 173.25 140 moveto 173.25 135 lineto stroke 153.5 -8.24443 moveto (10) cmss10 7.99994 fshow newpath 157.5 0 moveto 157.5 5 lineto stroke newpath 157.5 140 moveto 157.5 135 lineto stroke 139.75002 -8.24443 moveto (9) cmss10 7.99994 fshow newpath 141.75 0 moveto 141.75 5 lineto stroke newpath 141.75 140 moveto 141.75 135 lineto stroke 124.00002 -8.24443 moveto (8) cmss10 7.99994 fshow newpath 126 0 moveto 126 5 lineto stroke newpath 126 140 moveto 126 135 lineto stroke 108.25002 -8.24443 moveto (7) cmss10 7.99994 fshow newpath 110.25 0 moveto 110.25 5 lineto stroke newpath 110.25 140 moveto 110.25 135 lineto stroke 92.50002 -8.24443 moveto (6) cmss10 7.99994 fshow newpath 94.5 0 moveto 94.5 5 lineto stroke newpath 94.5 140 moveto 94.5 135 lineto stroke 76.75002 -8.24443 moveto (5) cmss10 7.99994 fshow newpath 78.75 0 moveto 78.75 5 lineto stroke newpath 78.75 140 moveto 78.75 135 lineto stroke 61.00002 -8.24443 moveto (4) cmss10 7.99994 fshow newpath 63 0 moveto 63 5 lineto stroke newpath 63 140 moveto 63 135 lineto stroke 45.25002 -8.24443 moveto (3) cmss10 7.99994 fshow newpath 47.25 0 moveto 47.25 5 lineto stroke newpath 47.25 140 moveto 47.25 135 lineto stroke 29.50002 -8.24443 moveto (2) cmss10 7.99994 fshow newpath 31.5 0 moveto 31.5 5 lineto stroke newpath 31.5 140 moveto 31.5 135 lineto stroke 13.75002 -8.24443 moveto (1) cmss10 7.99994 fshow newpath 15.75 0 moveto 15.75 5 lineto stroke newpath 15.75 140 moveto 15.75 135 lineto stroke -1.99998 -8.24443 moveto (0) cmss10 7.99994 fshow newpath 0 0 moveto 0 5 lineto stroke newpath 0 140 moveto 0 135 lineto stroke -6.99995 137.37778 moveto (7) cmss10 7.99994 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 140 moveto 3.9375 140 lineto stroke newpath 189 140 moveto 184 140 lineto stroke -6.99995 117.37778 moveto (6) cmss10 7.99994 fshow newpath 0 120 moveto 3.9375 120 lineto stroke newpath 189 120 moveto 184 120 lineto stroke -6.99995 97.37778 moveto (5) cmss10 7.99994 fshow newpath 0 100 moveto 3.9375 100 lineto stroke newpath 189 100 moveto 184 100 lineto stroke -6.99995 77.37778 moveto (4) cmss10 7.99994 fshow newpath 0 80 moveto 3.9375 80 lineto stroke newpath 189 80 moveto 184 80 lineto stroke -6.99995 57.37778 moveto (3) cmss10 7.99994 fshow newpath 0 60 moveto 3.9375 60 lineto stroke newpath 189 60 moveto 184 60 lineto stroke -6.99995 37.37778 moveto (2) cmss10 7.99994 fshow newpath 0 40 moveto 3.9375 40 lineto stroke newpath 189 40 moveto 184 40 lineto stroke -6.99995 17.37778 moveto (1) cmss10 7.99994 fshow newpath 0 20 moveto 3.9375 20 lineto stroke newpath 189 20 moveto 184 20 lineto stroke -6.99995 -2.62222 moveto (0) cmss10 7.99994 fshow newpath 0 0 moveto 3.9375 0 lineto stroke newpath 189 0 moveto 184 0 lineto stroke 0.6 0 0.6 setrgbcolor 168.8188 124.59059 moveto (O) cmsy10 9.96265 fshow 176.7502 123.09619 moveto (w) cmmi7 6.97385 fshow 182.5136 122.09999 moveto (2) cmr5 4.98132 fshow gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 189 120 moveto 189 120 lineto 173.25 120 lineto 173.25 120 lineto 157.5 120 lineto 157.5 100 lineto 141.75 100 lineto 141.75 80 lineto 126 80 lineto 126 60 lineto 110.25 60 lineto 110.25 60 lineto 94.5 60 lineto 94.5 60 lineto 78.75 60 lineto 78.75 40 lineto 63 40 lineto 63 20 lineto 47.25 20 lineto 47.25 0 lineto 31.5 0 lineto 31.5 0 lineto 15.75 0 lineto 15.75 0 lineto 0 0 lineto 0 0 lineto stroke grestore gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 124 moveto 173.25 112 lineto 157.5 100 lineto 141.75 88 lineto 126 76 lineto 110.25 64 lineto 94.5 52 lineto 78.75 40 lineto 63 28 lineto 47.25 16 lineto 31.5 4 lineto 15.75 -8 lineto 0 -20 lineto stroke grestore gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 108 moveto 173.25 96 lineto 157.5 84 lineto 141.75 72 lineto 126 60 lineto 110.25 48 lineto 94.5 36 lineto 78.75 24 lineto 63 12 lineto 47.25 0 lineto 31.5 -12 lineto 15.75 -24 lineto 0 -36 lineto stroke grestore 0.6 0 0.6 setrgbcolor gsave [0.73953 0 0 1.20544 191.09999 112.15985 ] concat 0 0 moveto (g) cmsy10 13.47153 fshow grestore 197.4 113.12129 moveto (a) cmmi12 14.34616 fshow 204.7739 110.96939 moveto (2) cmr10 9.96265 fshow 214.23839 113.12129 moveto (=) cmr12 14.34616 fshow 229.14899 124.74179 moveto (\002) cmex10 14.34624 fshow 236.3221 118.7699 moveto (5) cmr10 9.96265 fshow 0 0.5738 dtransform truncate idtransform setlinewidth pop [] 0 setdash 0 setlinecap 1 setlinejoin 10 setmiterlimit newpath 236.3221 116.7078 moveto 241.30339 116.7078 lineto stroke 236.3221 108.1742 moveto (3) cmr10 9.96265 fshow 242.4989 113.12129 moveto (;) cmmi12 14.34616 fshow 249.9874 118.7699 moveto (9) cmr10 9.96265 fshow newpath 249.9874 116.7078 moveto 254.96869 116.7078 lineto stroke 249.9874 108.1742 moveto (3) cmr10 9.96265 fshow 256.16429 124.74179 moveto (\003) cmex10 14.34624 fshow 264.53279 124.74179 moveto (\000) cmex10 14.34624 fshow 272.3037 118.7699 moveto (5) cmr10 9.96265 fshow newpath 272.3037 116.7078 moveto 277.2851 116.7078 lineto stroke 272.3037 108.1742 moveto (3) cmr10 9.96265 fshow 278.48059 124.74179 moveto (\001) cmex10 14.34624 fshow 0 setgray 0 1.25 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 0 -50 moveto 189 -50 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -50 moveto 0 -47.6 lineto stroke newpath 15.75 -50 moveto 15.75 -47.6 lineto stroke newpath 31.5 -50 moveto 31.5 -47.6 lineto stroke newpath 47.25 -50 moveto 47.25 -47.6 lineto stroke newpath 63 -50 moveto 63 -47.6 lineto stroke newpath 78.75 -50 moveto 78.75 -47.6 lineto stroke newpath 94.5 -50 moveto 94.5 -47.6 lineto stroke newpath 110.25 -50 moveto 110.25 -47.6 lineto stroke newpath 126 -50 moveto 126 -47.6 lineto stroke newpath 141.75 -50 moveto 141.75 -47.6 lineto stroke newpath 157.5 -50 moveto 157.5 -47.6 lineto stroke newpath 173.25 -50 moveto 173.25 -47.6 lineto stroke newpath 189 -50 moveto 189 -47.6 lineto stroke newpath 26.25 -50 moveto 26.25 -38 lineto stroke newpath 52.5 -50 moveto 52.5 -38 lineto stroke newpath 78.75 -50 moveto 78.75 -38 lineto stroke newpath 105 -50 moveto 105 -38 lineto stroke newpath 131.25 -50 moveto 131.25 -38 lineto stroke newpath 157.5 -50 moveto 157.5 -38 lineto stroke newpath 183.75 -50 moveto 183.75 -38 lineto stroke 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 0 -68 moveto 189 -68 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -68 moveto 0 -65.6 lineto stroke newpath 15.75 -68 moveto 15.75 -65.6 lineto stroke newpath 31.5 -68 moveto 31.5 -65.6 lineto stroke newpath 47.25 -68 moveto 47.25 -65.6 lineto stroke newpath 63 -68 moveto 63 -65.6 lineto stroke newpath 78.75 -68 moveto 78.75 -65.6 lineto stroke newpath 94.5 -68 moveto 94.5 -65.6 lineto stroke newpath 110.25 -68 moveto 110.25 -65.6 lineto stroke newpath 126 -68 moveto 126 -65.6 lineto stroke newpath 141.75 -68 moveto 141.75 -65.6 lineto stroke newpath 157.5 -68 moveto 157.5 -65.6 lineto stroke newpath 173.25 -68 moveto 173.25 -65.6 lineto stroke newpath 189 -68 moveto 189 -65.6 lineto stroke -13.7018 -64.40561 moveto (w) cmmi10 9.96265 fshow -6.5694 -65.90001 moveto (2) cmr7 6.97385 fshow newpath 47.25 -68 moveto 47.25 -56 lineto stroke newpath 63 -68 moveto 63 -56 lineto stroke newpath 78.75 -68 moveto 78.75 -56 lineto stroke newpath 126 -68 moveto 126 -56 lineto stroke newpath 141.75 -68 moveto 141.75 -56 lineto stroke newpath 157.5 -68 moveto 157.5 -56 lineto stroke 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 0 -86 moveto 189 -86 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -86 moveto 0 -83.6 lineto stroke newpath 15.75 -86 moveto 15.75 -83.6 lineto stroke newpath 31.5 -86 moveto 31.5 -83.6 lineto stroke newpath 47.25 -86 moveto 47.25 -83.6 lineto stroke newpath 63 -86 moveto 63 -83.6 lineto stroke newpath 78.75 -86 moveto 78.75 -83.6 lineto stroke newpath 94.5 -86 moveto 94.5 -83.6 lineto stroke newpath 110.25 -86 moveto 110.25 -83.6 lineto stroke newpath 126 -86 moveto 126 -83.6 lineto stroke newpath 141.75 -86 moveto 141.75 -83.6 lineto stroke newpath 157.5 -86 moveto 157.5 -83.6 lineto stroke newpath 173.25 -86 moveto 173.25 -83.6 lineto stroke newpath 189 -86 moveto 189 -83.6 lineto stroke newpath 47.25 -86 moveto 47.25 -74 lineto stroke newpath 73.5 -86 moveto 73.5 -74 lineto stroke newpath 99.75 -86 moveto 99.75 -74 lineto stroke newpath 126 -86 moveto 126 -74 lineto stroke newpath 152.25 -86 moveto 152.25 -74 lineto stroke newpath 178.5 -86 moveto 178.5 -74 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 -39.2 moveto 3.46419 -37.19995 lineto stroke newpath 0 -39.2 moveto 3.46419 -41.20004 lineto stroke newpath 0 -39.2 moveto 26.25 -39.2 lineto stroke newpath 26.25 -39.2 moveto 22.78581 -41.20004 lineto stroke newpath 26.25 -39.2 moveto 22.78581 -37.19995 lineto stroke 3.15538 -33.4413 moveto (d) cmmi10 7.99994 fshow 9.54143 -33.4413 moveto (=) cmr10 7.99994 fshow 18.9457 -30.29147 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 18.9457 -31.44128 moveto 22.13463 -31.44128 lineto stroke 18.9457 -36.19998 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 26.25 -39.2 moveto 52.5 -39.2 lineto stroke newpath 48.80464 -40.7307 moveto 52.5 -39.2 lineto 48.80464 -37.6693 lineto closepath gsave fill grestore stroke newpath 52.5 -39.2 moveto 26.25 -39.2 lineto stroke newpath 29.94536 -37.6693 moveto 26.25 -39.2 lineto 29.94536 -40.7307 lineto closepath gsave fill grestore stroke 28.59428 -33.4413 moveto (T) cmmi10 7.99994 fshow 36.60255 -33.4413 moveto (=) cmr10 7.99994 fshow 46.00688 -30.29147 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 46.00688 -31.44128 moveto 49.19574 -31.44128 lineto stroke 46.00688 -36.19998 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 0 -90.8 moveto 3.4641 -88.8 lineto stroke newpath 0 -90.8 moveto 3.4641 -92.8 lineto stroke newpath 0 -90.8 moveto 47.25 -90.8 lineto stroke newpath 47.25 -90.8 moveto 43.7859 -92.8 lineto stroke newpath 47.25 -90.8 moveto 43.7859 -88.8 lineto stroke 12.31454 -100.55872 moveto (D) cmmi10 7.99994 fshow 21.38219 -100.55872 moveto (=) cmr10 7.99994 fshow 30.78654 -97.40889 moveto (9) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 30.78654 -98.5587 moveto 33.97539 -98.5587 lineto stroke 30.78654 -103.3174 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 47.25 -90.8 moveto 73.5 -90.8 lineto stroke newpath 69.80464 -92.3307 moveto 73.5 -90.8 lineto 69.80464 -89.2693 lineto closepath gsave fill grestore stroke newpath 73.5 -90.8 moveto 47.25 -90.8 lineto stroke newpath 50.94536 -89.2693 moveto 47.25 -90.8 lineto 50.94536 -92.3307 lineto closepath gsave fill grestore stroke 49.59428 -100.55872 moveto (T) cmmi10 7.99994 fshow 57.60255 -100.55872 moveto (=) cmr10 7.99994 fshow 67.00688 -97.40889 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 67.00688 -98.5587 moveto 70.19574 -98.5587 lineto stroke 67.00688 -103.3174 moveto (3) cmr7 5.59996 fshow showpage %%EOF mlpost-0.8.2/papers/jfla2009/figures_flo/chrono2_1.1000077500000000000000000000256351306046515300217610ustar00rootroot00000000000000%!PS %%BoundingBox: -18 -20 294 184 %%Creator: MetaPost %%CreationDate: 2009.01.29:1232 %%Pages: 1 %*Font: cmr10 9.96265 9.96265 31:ec %*Font: cmss10 9.96265 9.96265 30:ffc00042000066073c %*Font: cmsy10 9.96265 9.96265 4f:8 %*Font: cmmi7 6.97385 6.97385 77:8 %*Font: cmr5 4.98132 4.98132 31:c %*Font: cmmi12 14.34616 11.95517 3b:8000000002 %*Font: cmr12 14.34616 11.95517 3d:8 %*Font: cmex10 14.34624 9.96265 00:c %*Font: cmsy10 14.34624 9.96265 00:8 %%EndProlog %%Page: 1 1 %%HiResBoundingBox: -17.45905 -19.00885 293.9191 183.26555 0.65 setgray 0 0.4 dtransform truncate idtransform setlinewidth pop [0 1.7501 ] 0.87506 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 180 moveto 189 180 lineto stroke newpath 0 160 moveto 189 160 lineto stroke newpath 0 140 moveto 189 140 lineto stroke newpath 0 120 moveto 189 120 lineto stroke newpath 0 100 moveto 189 100 lineto stroke newpath 0 80 moveto 189 80 lineto stroke newpath 0 60 moveto 189 60 lineto stroke newpath 0 40 moveto 189 40 lineto stroke newpath 0 20 moveto 189 20 lineto stroke newpath 0 0 moveto 189 0 lineto stroke 0.4 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 180 lineto stroke newpath 173.25 0 moveto 173.25 180 lineto stroke newpath 157.5 0 moveto 157.5 180 lineto stroke newpath 141.75 0 moveto 141.75 180 lineto stroke newpath 126 0 moveto 126 180 lineto stroke newpath 110.25 0 moveto 110.25 180 lineto stroke newpath 94.5 0 moveto 94.5 180 lineto stroke newpath 78.75 0 moveto 78.75 180 lineto stroke newpath 63 0 moveto 63 180 lineto stroke newpath 47.25 0 moveto 47.25 180 lineto stroke newpath 31.5 0 moveto 31.5 180 lineto stroke newpath 15.75 0 moveto 15.75 180 lineto stroke newpath 0 0 moveto 0 180 lineto stroke 0 setgray 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash newpath 0 0 moveto 189 0 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 0 moveto 0 180 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 180 moveto 189 180 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 180 lineto stroke 154.21701 -19.00885 moveto (Instants) cmss10 9.96265 fshow gsave [0 1 -1 0 -10.54054 111.48232 ] concat 0 0 moveto (Numb) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -10.54054 137.02551 ] concat 0 0 moveto (er) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -10.54054 148.17812 ] concat 0 0 moveto (of) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -10.54054 159.52452 ] concat 0 0 moveto (ones) cmss10 9.96265 fshow grestore 184.01865 -9.5311 moveto (12) cmss10 9.96265 fshow newpath 189 0 moveto 189 5 lineto stroke newpath 189 180 moveto 189 175 lineto stroke 168.26865 -9.5311 moveto (11) cmss10 9.96265 fshow newpath 173.25 0 moveto 173.25 5 lineto stroke newpath 173.25 180 moveto 173.25 175 lineto stroke 152.51865 -9.5311 moveto (10) cmss10 9.96265 fshow newpath 157.5 0 moveto 157.5 5 lineto stroke newpath 157.5 180 moveto 157.5 175 lineto stroke 139.25935 -9.5311 moveto (9) cmss10 9.96265 fshow newpath 141.75 0 moveto 141.75 5 lineto stroke newpath 141.75 180 moveto 141.75 175 lineto stroke 123.50935 -9.5311 moveto (8) cmss10 9.96265 fshow newpath 126 0 moveto 126 5 lineto stroke newpath 126 180 moveto 126 175 lineto stroke 107.75935 -9.5311 moveto (7) cmss10 9.96265 fshow newpath 110.25 0 moveto 110.25 5 lineto stroke newpath 110.25 180 moveto 110.25 175 lineto stroke 92.00935 -9.5311 moveto (6) cmss10 9.96265 fshow newpath 94.5 0 moveto 94.5 5 lineto stroke newpath 94.5 180 moveto 94.5 175 lineto stroke 76.25935 -9.5311 moveto (5) cmss10 9.96265 fshow newpath 78.75 0 moveto 78.75 5 lineto stroke newpath 78.75 180 moveto 78.75 175 lineto stroke 60.50935 -9.5311 moveto (4) cmss10 9.96265 fshow newpath 63 0 moveto 63 5 lineto stroke newpath 63 180 moveto 63 175 lineto stroke 44.75935 -9.5311 moveto (3) cmss10 9.96265 fshow newpath 47.25 0 moveto 47.25 5 lineto stroke newpath 47.25 180 moveto 47.25 175 lineto stroke 29.00935 -9.5311 moveto (2) cmss10 9.96265 fshow newpath 31.5 0 moveto 31.5 5 lineto stroke newpath 31.5 180 moveto 31.5 175 lineto stroke 13.25935 -9.5311 moveto (1) cmss10 9.96265 fshow newpath 15.75 0 moveto 15.75 5 lineto stroke newpath 15.75 180 moveto 15.75 175 lineto stroke -2.49065 -9.5311 moveto (0) cmss10 9.96265 fshow newpath 0 0 moveto 0 5 lineto stroke newpath 0 180 moveto 0 175 lineto stroke -7.9813 176.73445 moveto (9) cmss10 9.96265 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 180 moveto 3.9375 180 lineto stroke newpath 189 180 moveto 184 180 lineto stroke -7.9813 156.73445 moveto (8) cmss10 9.96265 fshow newpath 0 160 moveto 3.9375 160 lineto stroke newpath 189 160 moveto 184 160 lineto stroke -7.9813 136.73445 moveto (7) cmss10 9.96265 fshow newpath 0 140 moveto 3.9375 140 lineto stroke newpath 189 140 moveto 184 140 lineto stroke -7.9813 116.73445 moveto (6) cmss10 9.96265 fshow newpath 0 120 moveto 3.9375 120 lineto stroke newpath 189 120 moveto 184 120 lineto stroke -7.9813 96.73445 moveto (5) cmss10 9.96265 fshow newpath 0 100 moveto 3.9375 100 lineto stroke newpath 189 100 moveto 184 100 lineto stroke -7.9813 76.73445 moveto (4) cmss10 9.96265 fshow newpath 0 80 moveto 3.9375 80 lineto stroke newpath 189 80 moveto 184 80 lineto stroke -7.9813 56.73445 moveto (3) cmss10 9.96265 fshow newpath 0 60 moveto 3.9375 60 lineto stroke newpath 189 60 moveto 184 60 lineto stroke -7.9813 36.73445 moveto (2) cmss10 9.96265 fshow newpath 0 40 moveto 3.9375 40 lineto stroke newpath 189 40 moveto 184 40 lineto stroke -7.9813 16.73445 moveto (1) cmss10 9.96265 fshow newpath 0 20 moveto 3.9375 20 lineto stroke newpath 189 20 moveto 184 20 lineto stroke -7.9813 -3.26555 moveto (0) cmss10 9.96265 fshow newpath 0 0 moveto 3.9375 0 lineto stroke newpath 189 0 moveto 184 0 lineto stroke gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0 1 setrgbcolor 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 189 160 moveto 189 160 lineto 173.25 160 lineto 173.25 140 lineto 157.5 140 lineto 157.5 120 lineto 141.75 120 lineto 141.75 100 lineto 126 100 lineto 126 100 lineto 110.25 100 lineto 110.25 100 lineto 94.5 100 lineto 94.5 80 lineto 78.75 80 lineto 78.75 60 lineto 63 60 lineto 63 40 lineto 47.25 40 lineto 47.25 40 lineto 31.5 40 lineto 31.5 20 lineto 15.75 20 lineto 15.75 0 lineto 0 0 lineto 0 0 lineto stroke grestore 0 0 1 setrgbcolor 168.9344 165.4906 moveto (O) cmsy10 9.96265 fshow 176.8658 163.9962 moveto (w) cmmi7 6.97385 fshow 182.6292 163 moveto (1) cmr5 4.98132 fshow gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0.75 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 156 moveto 173.25 144 lineto 157.5 132 lineto 141.75 120 lineto 126 108 lineto 110.25 96 lineto 94.5 84 lineto 78.75 72 lineto 63 60 lineto 47.25 48 lineto 31.5 36 lineto 15.75 24 lineto 0 12 lineto stroke grestore gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0 1 setrgbcolor 0 0.75 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 148 moveto 173.25 136 lineto 157.5 124 lineto 141.75 112 lineto 126 100 lineto 110.25 88 lineto 94.5 76 lineto 78.75 64 lineto 63 52 lineto 47.25 40 lineto 31.5 28 lineto 15.75 16 lineto 0 4 lineto stroke grestore 0 0 1 setrgbcolor 192 150.4135 moveto (a) cmmi12 14.34616 fshow 199.3739 148.2616 moveto (1) cmr10 9.96265 fshow 208.8384 150.4135 moveto (=) cmr12 14.34616 fshow 223.749 162.034 moveto (\000) cmex10 14.34624 fshow 231.5198 156.0621 moveto (1) cmr10 9.96265 fshow 0 0.5738 dtransform truncate idtransform setlinewidth pop [] 0 setdash 0 setlinecap 1 setlinejoin 10 setmiterlimit newpath 231.5198 154 moveto 236.5012 154 lineto stroke 231.5198 145.4664 moveto (5) cmr10 9.96265 fshow 237.6967 150.4135 moveto (;) cmmi12 14.34616 fshow 245.1852 156.0621 moveto (3) cmr10 9.96265 fshow newpath 245.1852 154 moveto 250.1665 154 lineto stroke 245.1852 145.4664 moveto (5) cmr10 9.96265 fshow 251.362 150.4135 moveto (;) cmmi12 14.34616 fshow 258.8505 156.0621 moveto (3) cmr10 9.96265 fshow newpath 258.8505 154 moveto 263.8318 154 lineto stroke 258.8505 145.4664 moveto (5) cmr10 9.96265 fshow 265.0274 162.034 moveto (\001) cmex10 14.34624 fshow gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 1.25 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 189 120 moveto 189 120 lineto 173.25 120 lineto 173.25 100 lineto 157.5 100 lineto 157.5 100 lineto 141.75 100 lineto 141.75 80 lineto 126 80 lineto 126 60 lineto 110.25 60 lineto 110.25 60 lineto 94.5 60 lineto 94.5 40 lineto 78.75 40 lineto 78.75 40 lineto 63 40 lineto 63 20 lineto 47.25 20 lineto 47.25 0 lineto 31.5 0 lineto 31.5 0 lineto 15.75 0 lineto 15.75 0 lineto 0 0 lineto 0 0 lineto stroke grestore 0.6 0 0.6 setrgbcolor 168.9344 125.4906 moveto (O) cmsy10 9.96265 fshow 176.8658 123.9962 moveto (w) cmmi7 6.97385 fshow 182.6292 123 moveto (2) cmr5 4.98132 fshow gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0.75 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 120 moveto 173.25 108 lineto 157.5 96 lineto 141.75 84 lineto 126 72 lineto 110.25 60 lineto 94.5 48 lineto 78.75 36 lineto 63 24 lineto 47.25 12 lineto 31.5 0 lineto 15.75 -12 lineto 0 -24 lineto stroke grestore gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 0.75 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 120 moveto 173.25 108 lineto 157.5 96 lineto 141.75 84 lineto 126 72 lineto 110.25 60 lineto 94.5 48 lineto 78.75 36 lineto 63 24 lineto 47.25 12 lineto 31.5 0 lineto 15.75 -12 lineto 0 -24 lineto stroke grestore 0.6 0 0.6 setrgbcolor 192 118.4135 moveto (a) cmmi12 14.34616 fshow 199.3739 116.2616 moveto (2) cmr10 9.96265 fshow 208.8384 118.4135 moveto (=) cmr12 14.34616 fshow 223.749 130.034 moveto (\000) cmex10 14.34624 fshow 230.3243 118.4135 moveto (\000) cmsy10 14.34624 fshow 242.678 124.0621 moveto (6) cmr10 9.96265 fshow 0 0.5738 dtransform truncate idtransform setlinewidth pop [] 0 setdash 0 setlinecap 1 setlinejoin 10 setmiterlimit newpath 242.678 122 moveto 247.6593 122 lineto stroke 242.678 113.4664 moveto (5) cmr10 9.96265 fshow 248.8549 118.4135 moveto (;) cmmi12 14.34616 fshow 255.1478 118.4135 moveto (\000) cmsy10 14.34624 fshow 267.5015 124.0621 moveto (6) cmr10 9.96265 fshow newpath 267.5015 122 moveto 272.4829 122 lineto stroke 267.5015 113.4664 moveto (5) cmr10 9.96265 fshow 273.6784 118.4135 moveto (;) cmmi12 14.34616 fshow 281.1669 124.0621 moveto (3) cmr10 9.96265 fshow newpath 281.1669 122 moveto 286.1482 122 lineto stroke 281.1669 113.4664 moveto (5) cmr10 9.96265 fshow 287.3437 130.034 moveto (\001) cmex10 14.34624 fshow showpage %%EOF mlpost-0.8.2/papers/jfla2009/figures_flo/chrono2_1.mps000077500000000000000000000256351306046515300224200ustar00rootroot00000000000000%!PS %%BoundingBox: -18 -20 294 184 %%Creator: MetaPost %%CreationDate: 2009.01.29:1232 %%Pages: 1 %*Font: cmr10 9.96265 9.96265 31:ec %*Font: cmss10 9.96265 9.96265 30:ffc00042000066073c %*Font: cmsy10 9.96265 9.96265 4f:8 %*Font: cmmi7 6.97385 6.97385 77:8 %*Font: cmr5 4.98132 4.98132 31:c %*Font: cmmi12 14.34616 11.95517 3b:8000000002 %*Font: cmr12 14.34616 11.95517 3d:8 %*Font: cmex10 14.34624 9.96265 00:c %*Font: cmsy10 14.34624 9.96265 00:8 %%EndProlog %%Page: 1 1 %%HiResBoundingBox: -17.45905 -19.00885 293.9191 183.26555 0.65 setgray 0 0.4 dtransform truncate idtransform setlinewidth pop [0 1.7501 ] 0.87506 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 180 moveto 189 180 lineto stroke newpath 0 160 moveto 189 160 lineto stroke newpath 0 140 moveto 189 140 lineto stroke newpath 0 120 moveto 189 120 lineto stroke newpath 0 100 moveto 189 100 lineto stroke newpath 0 80 moveto 189 80 lineto stroke newpath 0 60 moveto 189 60 lineto stroke newpath 0 40 moveto 189 40 lineto stroke newpath 0 20 moveto 189 20 lineto stroke newpath 0 0 moveto 189 0 lineto stroke 0.4 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 180 lineto stroke newpath 173.25 0 moveto 173.25 180 lineto stroke newpath 157.5 0 moveto 157.5 180 lineto stroke newpath 141.75 0 moveto 141.75 180 lineto stroke newpath 126 0 moveto 126 180 lineto stroke newpath 110.25 0 moveto 110.25 180 lineto stroke newpath 94.5 0 moveto 94.5 180 lineto stroke newpath 78.75 0 moveto 78.75 180 lineto stroke newpath 63 0 moveto 63 180 lineto stroke newpath 47.25 0 moveto 47.25 180 lineto stroke newpath 31.5 0 moveto 31.5 180 lineto stroke newpath 15.75 0 moveto 15.75 180 lineto stroke newpath 0 0 moveto 0 180 lineto stroke 0 setgray 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash newpath 0 0 moveto 189 0 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 0 moveto 0 180 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 180 moveto 189 180 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 180 lineto stroke 154.21701 -19.00885 moveto (Instants) cmss10 9.96265 fshow gsave [0 1 -1 0 -10.54054 111.48232 ] concat 0 0 moveto (Numb) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -10.54054 137.02551 ] concat 0 0 moveto (er) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -10.54054 148.17812 ] concat 0 0 moveto (of) cmss10 9.96265 fshow grestore gsave [0 1 -1 0 -10.54054 159.52452 ] concat 0 0 moveto (ones) cmss10 9.96265 fshow grestore 184.01865 -9.5311 moveto (12) cmss10 9.96265 fshow newpath 189 0 moveto 189 5 lineto stroke newpath 189 180 moveto 189 175 lineto stroke 168.26865 -9.5311 moveto (11) cmss10 9.96265 fshow newpath 173.25 0 moveto 173.25 5 lineto stroke newpath 173.25 180 moveto 173.25 175 lineto stroke 152.51865 -9.5311 moveto (10) cmss10 9.96265 fshow newpath 157.5 0 moveto 157.5 5 lineto stroke newpath 157.5 180 moveto 157.5 175 lineto stroke 139.25935 -9.5311 moveto (9) cmss10 9.96265 fshow newpath 141.75 0 moveto 141.75 5 lineto stroke newpath 141.75 180 moveto 141.75 175 lineto stroke 123.50935 -9.5311 moveto (8) cmss10 9.96265 fshow newpath 126 0 moveto 126 5 lineto stroke newpath 126 180 moveto 126 175 lineto stroke 107.75935 -9.5311 moveto (7) cmss10 9.96265 fshow newpath 110.25 0 moveto 110.25 5 lineto stroke newpath 110.25 180 moveto 110.25 175 lineto stroke 92.00935 -9.5311 moveto (6) cmss10 9.96265 fshow newpath 94.5 0 moveto 94.5 5 lineto stroke newpath 94.5 180 moveto 94.5 175 lineto stroke 76.25935 -9.5311 moveto (5) cmss10 9.96265 fshow newpath 78.75 0 moveto 78.75 5 lineto stroke newpath 78.75 180 moveto 78.75 175 lineto stroke 60.50935 -9.5311 moveto (4) cmss10 9.96265 fshow newpath 63 0 moveto 63 5 lineto stroke newpath 63 180 moveto 63 175 lineto stroke 44.75935 -9.5311 moveto (3) cmss10 9.96265 fshow newpath 47.25 0 moveto 47.25 5 lineto stroke newpath 47.25 180 moveto 47.25 175 lineto stroke 29.00935 -9.5311 moveto (2) cmss10 9.96265 fshow newpath 31.5 0 moveto 31.5 5 lineto stroke newpath 31.5 180 moveto 31.5 175 lineto stroke 13.25935 -9.5311 moveto (1) cmss10 9.96265 fshow newpath 15.75 0 moveto 15.75 5 lineto stroke newpath 15.75 180 moveto 15.75 175 lineto stroke -2.49065 -9.5311 moveto (0) cmss10 9.96265 fshow newpath 0 0 moveto 0 5 lineto stroke newpath 0 180 moveto 0 175 lineto stroke -7.9813 176.73445 moveto (9) cmss10 9.96265 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 180 moveto 3.9375 180 lineto stroke newpath 189 180 moveto 184 180 lineto stroke -7.9813 156.73445 moveto (8) cmss10 9.96265 fshow newpath 0 160 moveto 3.9375 160 lineto stroke newpath 189 160 moveto 184 160 lineto stroke -7.9813 136.73445 moveto (7) cmss10 9.96265 fshow newpath 0 140 moveto 3.9375 140 lineto stroke newpath 189 140 moveto 184 140 lineto stroke -7.9813 116.73445 moveto (6) cmss10 9.96265 fshow newpath 0 120 moveto 3.9375 120 lineto stroke newpath 189 120 moveto 184 120 lineto stroke -7.9813 96.73445 moveto (5) cmss10 9.96265 fshow newpath 0 100 moveto 3.9375 100 lineto stroke newpath 189 100 moveto 184 100 lineto stroke -7.9813 76.73445 moveto (4) cmss10 9.96265 fshow newpath 0 80 moveto 3.9375 80 lineto stroke newpath 189 80 moveto 184 80 lineto stroke -7.9813 56.73445 moveto (3) cmss10 9.96265 fshow newpath 0 60 moveto 3.9375 60 lineto stroke newpath 189 60 moveto 184 60 lineto stroke -7.9813 36.73445 moveto (2) cmss10 9.96265 fshow newpath 0 40 moveto 3.9375 40 lineto stroke newpath 189 40 moveto 184 40 lineto stroke -7.9813 16.73445 moveto (1) cmss10 9.96265 fshow newpath 0 20 moveto 3.9375 20 lineto stroke newpath 189 20 moveto 184 20 lineto stroke -7.9813 -3.26555 moveto (0) cmss10 9.96265 fshow newpath 0 0 moveto 3.9375 0 lineto stroke newpath 189 0 moveto 184 0 lineto stroke gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0 1 setrgbcolor 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 189 160 moveto 189 160 lineto 173.25 160 lineto 173.25 140 lineto 157.5 140 lineto 157.5 120 lineto 141.75 120 lineto 141.75 100 lineto 126 100 lineto 126 100 lineto 110.25 100 lineto 110.25 100 lineto 94.5 100 lineto 94.5 80 lineto 78.75 80 lineto 78.75 60 lineto 63 60 lineto 63 40 lineto 47.25 40 lineto 47.25 40 lineto 31.5 40 lineto 31.5 20 lineto 15.75 20 lineto 15.75 0 lineto 0 0 lineto 0 0 lineto stroke grestore 0 0 1 setrgbcolor 168.9344 165.4906 moveto (O) cmsy10 9.96265 fshow 176.8658 163.9962 moveto (w) cmmi7 6.97385 fshow 182.6292 163 moveto (1) cmr5 4.98132 fshow gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0.75 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 156 moveto 173.25 144 lineto 157.5 132 lineto 141.75 120 lineto 126 108 lineto 110.25 96 lineto 94.5 84 lineto 78.75 72 lineto 63 60 lineto 47.25 48 lineto 31.5 36 lineto 15.75 24 lineto 0 12 lineto stroke grestore gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0 1 setrgbcolor 0 0.75 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 148 moveto 173.25 136 lineto 157.5 124 lineto 141.75 112 lineto 126 100 lineto 110.25 88 lineto 94.5 76 lineto 78.75 64 lineto 63 52 lineto 47.25 40 lineto 31.5 28 lineto 15.75 16 lineto 0 4 lineto stroke grestore 0 0 1 setrgbcolor 192 150.4135 moveto (a) cmmi12 14.34616 fshow 199.3739 148.2616 moveto (1) cmr10 9.96265 fshow 208.8384 150.4135 moveto (=) cmr12 14.34616 fshow 223.749 162.034 moveto (\000) cmex10 14.34624 fshow 231.5198 156.0621 moveto (1) cmr10 9.96265 fshow 0 0.5738 dtransform truncate idtransform setlinewidth pop [] 0 setdash 0 setlinecap 1 setlinejoin 10 setmiterlimit newpath 231.5198 154 moveto 236.5012 154 lineto stroke 231.5198 145.4664 moveto (5) cmr10 9.96265 fshow 237.6967 150.4135 moveto (;) cmmi12 14.34616 fshow 245.1852 156.0621 moveto (3) cmr10 9.96265 fshow newpath 245.1852 154 moveto 250.1665 154 lineto stroke 245.1852 145.4664 moveto (5) cmr10 9.96265 fshow 251.362 150.4135 moveto (;) cmmi12 14.34616 fshow 258.8505 156.0621 moveto (3) cmr10 9.96265 fshow newpath 258.8505 154 moveto 263.8318 154 lineto stroke 258.8505 145.4664 moveto (5) cmr10 9.96265 fshow 265.0274 162.034 moveto (\001) cmex10 14.34624 fshow gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 1.25 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 189 120 moveto 189 120 lineto 173.25 120 lineto 173.25 100 lineto 157.5 100 lineto 157.5 100 lineto 141.75 100 lineto 141.75 80 lineto 126 80 lineto 126 60 lineto 110.25 60 lineto 110.25 60 lineto 94.5 60 lineto 94.5 40 lineto 78.75 40 lineto 78.75 40 lineto 63 40 lineto 63 20 lineto 47.25 20 lineto 47.25 0 lineto 31.5 0 lineto 31.5 0 lineto 15.75 0 lineto 15.75 0 lineto 0 0 lineto 0 0 lineto stroke grestore 0.6 0 0.6 setrgbcolor 168.9344 125.4906 moveto (O) cmsy10 9.96265 fshow 176.8658 123.9962 moveto (w) cmmi7 6.97385 fshow 182.6292 123 moveto (2) cmr5 4.98132 fshow gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0 0.75 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 120 moveto 173.25 108 lineto 157.5 96 lineto 141.75 84 lineto 126 72 lineto 110.25 60 lineto 94.5 48 lineto 78.75 36 lineto 63 24 lineto 47.25 12 lineto 31.5 0 lineto 15.75 -12 lineto 0 -24 lineto stroke grestore gsave newpath 0 180 moveto 0 0 lineto 189 0 lineto 189 180 lineto closepath clip 0.6 0 0.6 setrgbcolor 0 0.75 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 120 moveto 173.25 108 lineto 157.5 96 lineto 141.75 84 lineto 126 72 lineto 110.25 60 lineto 94.5 48 lineto 78.75 36 lineto 63 24 lineto 47.25 12 lineto 31.5 0 lineto 15.75 -12 lineto 0 -24 lineto stroke grestore 0.6 0 0.6 setrgbcolor 192 118.4135 moveto (a) cmmi12 14.34616 fshow 199.3739 116.2616 moveto (2) cmr10 9.96265 fshow 208.8384 118.4135 moveto (=) cmr12 14.34616 fshow 223.749 130.034 moveto (\000) cmex10 14.34624 fshow 230.3243 118.4135 moveto (\000) cmsy10 14.34624 fshow 242.678 124.0621 moveto (6) cmr10 9.96265 fshow 0 0.5738 dtransform truncate idtransform setlinewidth pop [] 0 setdash 0 setlinecap 1 setlinejoin 10 setmiterlimit newpath 242.678 122 moveto 247.6593 122 lineto stroke 242.678 113.4664 moveto (5) cmr10 9.96265 fshow 248.8549 118.4135 moveto (;) cmmi12 14.34616 fshow 255.1478 118.4135 moveto (\000) cmsy10 14.34624 fshow 267.5015 124.0621 moveto (6) cmr10 9.96265 fshow newpath 267.5015 122 moveto 272.4829 122 lineto stroke 267.5015 113.4664 moveto (5) cmr10 9.96265 fshow 273.6784 118.4135 moveto (;) cmmi12 14.34616 fshow 281.1669 124.0621 moveto (3) cmr10 9.96265 fshow newpath 281.1669 122 moveto 286.1482 122 lineto stroke 281.1669 113.4664 moveto (5) cmr10 9.96265 fshow 287.3437 130.034 moveto (\001) cmex10 14.34624 fshow showpage %%EOF mlpost-0.8.2/papers/jfla2009/florence.1000066400000000000000000000374411306046515300174530ustar00rootroot00000000000000%!PS %%BoundingBox: -15 -104 208 152 %%Creator: MetaPost %%CreationDate: 2008.10.01:1254 %%Pages: 1 %*Font: cmr10 7.99994 9.96265 30:ffc40042001466073c %*Font: cmr7 5.59996 6.97385 32:d1 %*Font: cmsy10 9.96265 9.96265 66:8 %*Font: cmmi10 9.96265 9.96265 61:84 %*Font: cmmi7 6.97385 6.97385 77:8 %*Font: cmr5 4.98132 4.98132 31:c %*Font: cmr7 6.97385 6.97385 31:c %*Font: cmsy10 13.47153 9.96265 67:8 %*Font: cmmi10 7.99994 9.96265 44:8000800080001 %%EndProlog %%Page: 1 1 0.65 setgray 0 0.4 dtransform truncate idtransform setlinewidth pop [0 1.7501 ] 0.87506 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 140 moveto 189 140 lineto stroke newpath 0 120 moveto 189 120 lineto stroke newpath 0 100 moveto 189 100 lineto stroke newpath 0 80 moveto 189 80 lineto stroke newpath 0 60 moveto 189 60 lineto stroke newpath 0 40 moveto 189 40 lineto stroke newpath 0 20 moveto 189 20 lineto stroke newpath 0 0 moveto 189 0 lineto stroke 0.4 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 140 lineto stroke newpath 173.25 0 moveto 173.25 140 lineto stroke newpath 157.5 0 moveto 157.5 140 lineto stroke newpath 141.75 0 moveto 141.75 140 lineto stroke newpath 126 0 moveto 126 140 lineto stroke newpath 110.25 0 moveto 110.25 140 lineto stroke newpath 94.5 0 moveto 94.5 140 lineto stroke newpath 78.75 0 moveto 78.75 140 lineto stroke newpath 63 0 moveto 63 140 lineto stroke newpath 47.25 0 moveto 47.25 140 lineto stroke newpath 31.5 0 moveto 31.5 140 lineto stroke newpath 15.75 0 moveto 15.75 140 lineto stroke newpath 0 0 moveto 0 140 lineto stroke 0 setgray 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash newpath 0 0 moveto 189 0 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 0 moveto 0 140 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 140 moveto 189 140 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 189 0 moveto 189 140 lineto stroke 158.8113 -15.45544 moveto (Instan) cmr10 7.99994 fshow 180.63338 -15.45544 moveto (ts) cmr10 7.99994 fshow gsave [0 1 -1 0 -8.8777 82.72253 ] concat 0 0 moveto (Num) cmr10 7.99994 fshow grestore gsave [0 1 -1 0 -8.8777 99.61134 ] concat 0 0 moveto (b) cmr10 7.99994 fshow grestore gsave [0 1 -1 0 -8.8777 104.27802 ] concat 0 0 moveto (er) cmr10 7.99994 fshow grestore gsave [0 1 -1 0 -8.8777 113.63345 ] concat 0 0 moveto (of) cmr10 7.99994 fshow grestore gsave [0 1 -1 0 -8.8777 122.74455 ] concat 0 0 moveto (ones) cmr10 7.99994 fshow grestore 185 -8.15553 moveto (12) cmr10 7.99994 fshow newpath 189 0 moveto 189 5 lineto stroke newpath 189 140 moveto 189 135 lineto stroke 169.25 -8.15553 moveto (11) cmr10 7.99994 fshow newpath 173.25 0 moveto 173.25 5 lineto stroke newpath 173.25 140 moveto 173.25 135 lineto stroke 153.5 -8.15553 moveto (10) cmr10 7.99994 fshow newpath 157.5 0 moveto 157.5 5 lineto stroke newpath 157.5 140 moveto 157.5 135 lineto stroke 139.75002 -8.15553 moveto (9) cmr10 7.99994 fshow newpath 141.75 0 moveto 141.75 5 lineto stroke newpath 141.75 140 moveto 141.75 135 lineto stroke 124.00002 -8.15553 moveto (8) cmr10 7.99994 fshow newpath 126 0 moveto 126 5 lineto stroke newpath 126 140 moveto 126 135 lineto stroke 108.25002 -8.15553 moveto (7) cmr10 7.99994 fshow newpath 110.25 0 moveto 110.25 5 lineto stroke newpath 110.25 140 moveto 110.25 135 lineto stroke 92.50002 -8.15553 moveto (6) cmr10 7.99994 fshow newpath 94.5 0 moveto 94.5 5 lineto stroke newpath 94.5 140 moveto 94.5 135 lineto stroke 76.75002 -8.15553 moveto (5) cmr10 7.99994 fshow newpath 78.75 0 moveto 78.75 5 lineto stroke newpath 78.75 140 moveto 78.75 135 lineto stroke 61.00002 -8.15553 moveto (4) cmr10 7.99994 fshow newpath 63 0 moveto 63 5 lineto stroke newpath 63 140 moveto 63 135 lineto stroke 45.25002 -8.15553 moveto (3) cmr10 7.99994 fshow newpath 47.25 0 moveto 47.25 5 lineto stroke newpath 47.25 140 moveto 47.25 135 lineto stroke 29.50002 -8.15553 moveto (2) cmr10 7.99994 fshow newpath 31.5 0 moveto 31.5 5 lineto stroke newpath 31.5 140 moveto 31.5 135 lineto stroke 13.75002 -8.15553 moveto (1) cmr10 7.99994 fshow newpath 15.75 0 moveto 15.75 5 lineto stroke newpath 15.75 140 moveto 15.75 135 lineto stroke -1.99998 -8.15553 moveto (0) cmr10 7.99994 fshow newpath 0 0 moveto 0 5 lineto stroke newpath 0 140 moveto 0 135 lineto stroke -6.99995 137.42223 moveto (7) cmr10 7.99994 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 140 moveto 3.9375 140 lineto stroke newpath 189 140 moveto 184 140 lineto stroke -6.99995 117.42223 moveto (6) cmr10 7.99994 fshow newpath 0 120 moveto 3.9375 120 lineto stroke newpath 189 120 moveto 184 120 lineto stroke -6.99995 97.42223 moveto (5) cmr10 7.99994 fshow newpath 0 100 moveto 3.9375 100 lineto stroke newpath 189 100 moveto 184 100 lineto stroke -6.99995 77.42223 moveto (4) cmr10 7.99994 fshow newpath 0 80 moveto 3.9375 80 lineto stroke newpath 189 80 moveto 184 80 lineto stroke -6.99995 57.42223 moveto (3) cmr10 7.99994 fshow newpath 0 60 moveto 3.9375 60 lineto stroke newpath 189 60 moveto 184 60 lineto stroke -6.99995 37.42223 moveto (2) cmr10 7.99994 fshow newpath 0 40 moveto 3.9375 40 lineto stroke newpath 189 40 moveto 184 40 lineto stroke -6.99995 17.42223 moveto (1) cmr10 7.99994 fshow newpath 0 20 moveto 3.9375 20 lineto stroke newpath 189 20 moveto 184 20 lineto stroke -6.99995 -2.57777 moveto (0) cmr10 7.99994 fshow newpath 0 0 moveto 3.9375 0 lineto stroke newpath 189 0 moveto 184 0 lineto stroke 128.09999 124.59059 moveto (f) cmmi10 9.96265 fshow 132.97758 123.09619 moveto (w) cmmi7 6.97385 fshow 138.741 122.09999 moveto (1) cmr5 4.98132 fshow gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 1.5 dtransform truncate idtransform setlinewidth pop newpath 189 160 moveto 189 160 lineto 173.25 160 lineto 173.25 140 lineto 157.5 140 lineto 157.5 120 lineto 141.75 120 lineto 141.75 120 lineto 126 120 lineto 126 100 lineto 110.25 100 lineto 110.25 100 lineto 94.5 100 lineto 94.5 80 lineto 78.75 80 lineto 78.75 60 lineto 63 60 lineto 63 60 lineto 47.25 60 lineto 47.25 40 lineto 31.5 40 lineto 31.5 40 lineto 15.75 40 lineto 15.75 20 lineto 0 20 lineto 0 0 lineto stroke grestore 0 setgray 171.8726 124.59059 moveto (f) cmmi10 9.96265 fshow 176.7502 123.09619 moveto (w) cmmi7 6.97385 fshow 182.51361 122.09999 moveto (2) cmr5 4.98132 fshow gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 1.5 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 120 moveto 189 120 lineto 173.25 120 lineto 173.25 120 lineto 157.5 120 lineto 157.5 100 lineto 141.75 100 lineto 141.75 80 lineto 126 80 lineto 126 60 lineto 110.25 60 lineto 110.25 60 lineto 94.5 60 lineto 94.5 60 lineto 78.75 60 lineto 78.75 40 lineto 63 40 lineto 63 20 lineto 47.25 20 lineto 47.25 0 lineto 31.5 0 lineto 31.5 0 lineto 15.75 0 lineto 15.75 0 lineto 0 0 lineto 0 0 lineto stroke grestore 0 setgray 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 141.75 -20 moveto 141.75 -10 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 143.28073 -13.69543 moveto 141.75 -10 lineto 140.21927 -13.69543 lineto closepath gsave fill grestore stroke 133.07526 -26.99997 moveto ([) cmr10 7.99994 fshow 135.29745 -26.99997 moveto (w) cmmi10 7.99994 fshow 141.02473 -28.19997 moveto (2) cmr7 5.59996 fshow 144.61363 -26.99997 moveto (]) cmr10 7.99994 fshow 146.83583 -28.19997 moveto (5) cmr7 5.59996 fshow gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash newpath 189 152 moveto 173.25 140 lineto 157.5 128 lineto 141.75 116 lineto 126 104 lineto 110.25 92 lineto 94.5 80 lineto 78.75 68 lineto 63 56 lineto 47.25 44 lineto 31.5 32 lineto 15.75 20 lineto 0 8 lineto stroke grestore gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 setgray 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 144 moveto 173.25 132 lineto 157.5 120 lineto 141.75 108 lineto 126 96 lineto 110.25 84 lineto 94.5 72 lineto 78.75 60 lineto 63 48 lineto 47.25 36 lineto 31.5 24 lineto 15.75 12 lineto 0 0 lineto stroke grestore 0 setgray gsave [0 -1 1 0 176.2657 145.08128 ] concat 0 0 moveto (f) cmsy10 9.96265 fshow grestore 175.34999 147.59439 moveto (a) cmmi10 9.96265 fshow 180.61609 146.09999 moveto (1) cmr7 6.97385 fshow gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 124 moveto 173.25 112 lineto 157.5 100 lineto 141.75 88 lineto 126 76 lineto 110.25 64 lineto 94.5 52 lineto 78.75 40 lineto 63 28 lineto 47.25 16 lineto 31.5 4 lineto 15.75 -8 lineto 0 -20 lineto stroke grestore gsave newpath 0 140 moveto 0 0 lineto 189 0 lineto 189 140 lineto closepath clip 0 setgray 0 0.25 dtransform truncate idtransform setlinewidth pop [2.69998 2.69998 ] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 189 108 moveto 173.25 96 lineto 157.5 84 lineto 141.75 72 lineto 126 60 lineto 110.25 48 lineto 94.5 36 lineto 78.75 24 lineto 63 12 lineto 47.25 0 lineto 31.5 -12 lineto 15.75 -24 lineto 0 -36 lineto stroke grestore 0 setgray gsave [0.73953 0 0 1.20544 191.09999 112.15985 ] concat 0 0 moveto (g) cmsy10 13.47153 fshow grestore 197.4 113.59439 moveto (a) cmmi10 9.96265 fshow 202.66609 112.09999 moveto (2) cmr7 6.97385 fshow 0 1.25 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 -50 moveto 189 -50 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -50 moveto 0 -47.6 lineto stroke newpath 15.75 -50 moveto 15.75 -47.6 lineto stroke newpath 31.5 -50 moveto 31.5 -47.6 lineto stroke newpath 47.25 -50 moveto 47.25 -47.6 lineto stroke newpath 63 -50 moveto 63 -47.6 lineto stroke newpath 78.75 -50 moveto 78.75 -47.6 lineto stroke newpath 94.5 -50 moveto 94.5 -47.6 lineto stroke newpath 110.25 -50 moveto 110.25 -47.6 lineto stroke newpath 126 -50 moveto 126 -47.6 lineto stroke newpath 141.75 -50 moveto 141.75 -47.6 lineto stroke newpath 157.5 -50 moveto 157.5 -47.6 lineto stroke newpath 173.25 -50 moveto 173.25 -47.6 lineto stroke newpath 189 -50 moveto 189 -47.6 lineto stroke newpath 26.25 -50 moveto 26.25 -38 lineto stroke newpath 52.5 -50 moveto 52.5 -38 lineto stroke newpath 78.75 -50 moveto 78.75 -38 lineto stroke newpath 105 -50 moveto 105 -38 lineto stroke newpath 131.25 -50 moveto 131.25 -38 lineto stroke newpath 157.5 -50 moveto 157.5 -38 lineto stroke newpath 183.75 -50 moveto 183.75 -38 lineto stroke 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 0 -68 moveto 189 -68 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -68 moveto 0 -65.6 lineto stroke newpath 15.75 -68 moveto 15.75 -65.6 lineto stroke newpath 31.5 -68 moveto 31.5 -65.6 lineto stroke newpath 47.25 -68 moveto 47.25 -65.6 lineto stroke newpath 63 -68 moveto 63 -65.6 lineto stroke newpath 78.75 -68 moveto 78.75 -65.6 lineto stroke newpath 94.5 -68 moveto 94.5 -65.6 lineto stroke newpath 110.25 -68 moveto 110.25 -65.6 lineto stroke newpath 126 -68 moveto 126 -65.6 lineto stroke newpath 141.75 -68 moveto 141.75 -65.6 lineto stroke newpath 157.5 -68 moveto 157.5 -65.6 lineto stroke newpath 173.25 -68 moveto 173.25 -65.6 lineto stroke newpath 189 -68 moveto 189 -65.6 lineto stroke -11.41617 -64.70001 moveto (w) cmmi10 7.99994 fshow -5.68889 -65.90001 moveto (2) cmr7 5.59996 fshow newpath 47.25 -68 moveto 47.25 -56 lineto stroke newpath 63 -68 moveto 63 -56 lineto stroke newpath 78.75 -68 moveto 78.75 -56 lineto stroke newpath 126 -68 moveto 126 -56 lineto stroke newpath 141.75 -68 moveto 141.75 -56 lineto stroke newpath 157.5 -68 moveto 157.5 -56 lineto stroke 0 1.25 dtransform truncate idtransform setlinewidth pop newpath 0 -86 moveto 189 -86 lineto stroke 1.25 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 0 -86 moveto 0 -83.6 lineto stroke newpath 15.75 -86 moveto 15.75 -83.6 lineto stroke newpath 31.5 -86 moveto 31.5 -83.6 lineto stroke newpath 47.25 -86 moveto 47.25 -83.6 lineto stroke newpath 63 -86 moveto 63 -83.6 lineto stroke newpath 78.75 -86 moveto 78.75 -83.6 lineto stroke newpath 94.5 -86 moveto 94.5 -83.6 lineto stroke newpath 110.25 -86 moveto 110.25 -83.6 lineto stroke newpath 126 -86 moveto 126 -83.6 lineto stroke newpath 141.75 -86 moveto 141.75 -83.6 lineto stroke newpath 157.5 -86 moveto 157.5 -83.6 lineto stroke newpath 173.25 -86 moveto 173.25 -83.6 lineto stroke newpath 189 -86 moveto 189 -83.6 lineto stroke newpath 47.25 -86 moveto 47.25 -74 lineto stroke newpath 73.5 -86 moveto 73.5 -74 lineto stroke newpath 99.75 -86 moveto 99.75 -74 lineto stroke newpath 126 -86 moveto 126 -74 lineto stroke newpath 152.25 -86 moveto 152.25 -74 lineto stroke newpath 178.5 -86 moveto 178.5 -74 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 0 -39.2 moveto 3.46419 -37.19995 lineto stroke newpath 0 -39.2 moveto 3.46419 -41.20004 lineto stroke newpath 0 -39.2 moveto 26.25 -39.2 lineto stroke newpath 26.25 -39.2 moveto 22.78581 -41.20004 lineto stroke newpath 26.25 -39.2 moveto 22.78581 -37.19995 lineto stroke 3.15538 -33.4413 moveto (d) cmmi10 7.99994 fshow 9.54143 -33.4413 moveto (=) cmr10 7.99994 fshow 18.9457 -30.29147 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 18.9457 -31.44128 moveto 22.13463 -31.44128 lineto stroke 18.9457 -36.19998 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 26.25 -39.2 moveto 52.5 -39.2 lineto stroke newpath 48.80464 -40.7307 moveto 52.5 -39.2 lineto 48.80464 -37.6693 lineto closepath gsave fill grestore stroke newpath 52.5 -39.2 moveto 26.25 -39.2 lineto stroke newpath 29.94536 -37.6693 moveto 26.25 -39.2 lineto 29.94536 -40.7307 lineto closepath gsave fill grestore stroke 28.59428 -33.4413 moveto (T) cmmi10 7.99994 fshow 36.60255 -33.4413 moveto (=) cmr10 7.99994 fshow 46.00688 -30.29147 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 46.00688 -31.44128 moveto 49.19574 -31.44128 lineto stroke 46.00688 -36.19998 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 0 -90.8 moveto 3.4641 -88.8 lineto stroke newpath 0 -90.8 moveto 3.4641 -92.8 lineto stroke newpath 0 -90.8 moveto 47.25 -90.8 lineto stroke newpath 47.25 -90.8 moveto 43.7859 -92.8 lineto stroke newpath 47.25 -90.8 moveto 43.7859 -88.8 lineto stroke 12.31454 -100.55872 moveto (D) cmmi10 7.99994 fshow 21.38219 -100.55872 moveto (=) cmr10 7.99994 fshow 30.78654 -97.40889 moveto (9) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 30.78654 -98.5587 moveto 33.97539 -98.5587 lineto stroke 30.78654 -103.3174 moveto (3) cmr7 5.59996 fshow 0 0.5 dtransform truncate idtransform setlinewidth pop 1 setlinecap newpath 47.25 -90.8 moveto 73.5 -90.8 lineto stroke newpath 69.80464 -92.3307 moveto 73.5 -90.8 lineto 69.80464 -89.2693 lineto closepath gsave fill grestore stroke newpath 73.5 -90.8 moveto 47.25 -90.8 lineto stroke newpath 50.94536 -89.2693 moveto 47.25 -90.8 lineto 50.94536 -92.3307 lineto closepath gsave fill grestore stroke 49.59428 -100.55872 moveto (T) cmmi10 7.99994 fshow 57.60255 -100.55872 moveto (=) cmr10 7.99994 fshow 67.00688 -97.40889 moveto (5) cmr7 5.59996 fshow 0 0.31999 dtransform truncate idtransform setlinewidth pop 0 setlinecap newpath 67.00688 -98.5587 moveto 70.19574 -98.5587 lineto stroke 67.00688 -103.3174 moveto (3) cmr7 5.59996 fshow showpage %%EOF mlpost-0.8.2/papers/jfla2009/hermann.tex000066400000000000000000001535051306046515300177460ustar00rootroot00000000000000\documentclass[twoside]{studia-Hermann} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{alltt,url,graphicx} \usepackage[french]{babel} \usepackage{mflogo} \usepackage{tikz} % macros \newcommand{\ocaml}{OCaml} \newcommand{\camllight}{Caml Light} \newcommand{\asymptote}{\textsf{Asymptote}} \newcommand{\mlpost}{\textsc{Mlpost}} \newcommand{\metapost}{\MP} \newcommand{\fmpost}{\textit{functional} \metapost} \newcommand{\metafont}{\MF} \newcommand{\nomdetikz}{\textsf{TikZ}} \newcommand{\pstricks}{\textsf{PSTricks}} \newcommand{\dia}{\textsf{Dia}} \newcommand{\xfig}{\textsf{Xfig}} \newcommand{\postscript}{PostScript} \newcommand{\mlpictex}{mlP\hspace{-0.2em}\raisebox{-0.2em}{i}\hspace{-0.1em}c\hspace{-0.1em}\TeX} \proceedings{JFLA09}{-} \title[Faire bonne figure avec \mlpost]{Faire bonne figure avec \mlpost} \author{R. Bardou \andauthor J.-C. Filliâtre \andauthor J. Kanig \andauthor S. Lescuyer} \address{ ProVal / INRIA Saclay -- Île-de-France\\ 91893 Orsay Cedex, France\\ LRI / CNRS -- Université Paris Sud\\ 91405 Orsay Cedex, France\\[3pt] {\tt \{bardou,filliatr,kanig,lescuyer\}@lri.fr} } \resume{Cet article présente \mlpost, une bibliothèque \ocaml\ de dessin scientifique. Elle s'appuie sur \metapost, qui permet notamment d'inclure des fragments \LaTeX\ dans les figures. \ocaml\ offre une alternative séduisante aux langages de macros \LaTeX, aux langages spécialisés ou même aux outils graphiques. En particulier, l'utilisateur de \mlpost\ bénéficie de toute l'expressivité d'\ocaml\ et de son typage statique. Enfin \mlpost\ propose un style déclaratif qui diffère de celui, souvent impératif, des outils existants.} \abstract{This article introduces \mlpost, an \ocaml\ library for scientific drawing. It is based on \metapost, which allows inclusion of \LaTeX\ fragments. \ocaml\ is an appealing alternative to \LaTeX\ macro languages, dedicated languages and even to graphic tools. In particular, \mlpost\ users benefit from \ocaml's expressiveness and static typing. Finally, \mlpost\ features a declarative style, which differs from the imperative style of most existing tools. } \motscles{dessin scientifique, programmation fonctionnelle, \metapost, \ocaml} \keywords{scientific drawing, functional programming, \metapost, \ocaml} % \title{Faire bonne figure avec \mlpost} % \author{R. Bardou$^1$ % \& J.-C. Filliâtre$^1$ % \& J. Kanig$^1$ % \& S. Lescuyer$^1$} % \titlehead{Faire bonne figure avec \mlpost}% a droite (page impaire) % \authorhead{Bardou \& Filliâtre \& Kanig \& Lescuyer}% a gauche (page paire) % \affiliation{\begin{tabular}{rr} % \\ 1: ProVal / INRIA Saclay -- Île-de-France % \\ 91893 Orsay Cedex, France % \\ LRI / CNRS -- Université Paris Sud % \\ 91405 Orsay Cedex, France % \\ {\tt \{bardou,filliatr,kanig,lescuyer\}@lri.fr} % \end{tabular}} \begin{document} \maketitle % \begin{abstract} % Cet article présente \mlpost, une bibliothèque \ocaml\ de dessin % scientifique. Elle s'appuie sur \metapost, qui permet notamment % d'inclure des fragments \LaTeX\ dans les figures. \ocaml\ offre une % alternative séduisante aux langages de macros \LaTeX, aux langages % spécialisés ou même aux outils graphiques. En particulier, % l'utilisateur de \mlpost\ bénéficie de toute l'expressivité % d'\ocaml\ et de son typage statique. Enfin \mlpost\ propose un style % déclaratif qui diffère de celui, souvent impératif, des outils existants. % \end{abstract} % TODO ? : expliquer comment fait \metapost pour inclure du \LaTeX % TODO : expliquer les labels \section{Introduction} Lors de la rédaction de documents à nature scientifique (articles, cours, livres, etc.), il est très souvent nécessaire de réaliser des figures. Ces figures permettent d'agrémenter le texte en illustrant aussi bien les objets dont il est question dans le document que les liens qui existent entre eux et facilitent ainsi leur compréhension. Elles sont donc un composant fondamental au caractère didactique de tels documents, mais leur réalisation est souvent fastidieuse. En particulier, il est souvent nécessaire d'y inclure des éléments mis en forme par \LaTeX\ (formules, etc.), ce que bon nombre de logiciels de dessin ne permettent pas. Ainsi, on peut souhaiter réaliser un schéma tel que celui-ci \begin{center} \includegraphics[width=\textwidth]{yannick1.mps} \end{center} en attachant de l'importance au fait que des expressions comme $a_1+s_1-1$ apparaissent exactement comme dans le corps du document. Il existe plusieurs familles d'outils pour réaliser des figures à intégrer dans un document \LaTeX~: \begin{itemize} \item des interfaces graphiques disposant d'une sortie \LaTeX, telles que \dia~\cite{dia} ou \xfig~\cite{xfig} ; \item des bibliothèques \LaTeX, telles que \pstricks~\cite{pstricks} ou encore \nomdetikz~\cite{tikz} ; \item des outils externes en ligne de commande, tel que \metapost~\cite{metapost}. \end{itemize} % Il faudrait d'ailleurs déjà que ces logiciels de dessin soient vectoriels % ce qui n'est pas forcément le cas. Chaque famille a ses avantages et ses inconvénients. Les interfaces graphiques sont les plus accessibles, notamment pour un placement rapide et intuitif des différents éléments de la figure, mais l'intégration de texte mis en forme par \LaTeX\ est délicate. Dans le cas de \xfig\ et de \dia, la taille des éléments \LaTeX\ n'est pas connue lors de l'édition de la figure ; en outre, dans le cas de \dia, l'intégration de \LaTeX\ dans une figure nécessite de l'exporter sous forme de macros \nomdetikz\ et d'éditer le résultat. %% TODO : RAPPELER QUE PSTRICKS NE MARCHE PAS AVEC PDFLATEX ! Les bibliothèques \LaTeX\ telles que \pstricks\ ou \nomdetikz\ offrent l'intégration la plus naturelle avec \LaTeX. En particulier, elles permettent de combiner arbitrairement éléments graphiques et textes \LaTeX\ \begin{tikzpicture}[baseline=(a.base)] \path[use as bounding box] (0,0) node[draw,style=dashed] (a) {comme ceci}; \draw[->] (a) .. controls +(-2cm,1cm) and +(-2cm,-0cm) .. (a); \end{tikzpicture}. En revanche, elles demandent d'apprendre un certain nombre de macros et de notations et souffrent surtout des défauts inhérents à \LaTeX~: \begin{itemize} \item des erreurs détectées uniquement à l'interprétation, peu claires et parfois mal localisées ; \item un langage \emph{de programmation} peu commode (syntaxe obscure, absence de typage, code difficile à structurer). \end{itemize} Ces inconvénients sont notamment un frein au développement de bibliothèques de haut niveau au dessus de ces langages ainsi qu'à la réutilisation de figures. \metapost\ se présente comme une alternative à ces bibliothèques \LaTeX, en proposant un langage de programmation à part entière spécialisé dans la construction de figures contenant des éléments \LaTeX. Il permet notamment de manipuler symboliquement la taille et la position de ces éléments et de les relier de manière implicite par des équations. En revanche, le langage de \metapost\ s'inspire de celui de \metafont~\cite{metafont} et présente, à l'exception de la syntaxe, les défauts soulevés ci-dessus. La figure~\ref{fig:metapost} donne un exemple de programme/figure réalisé avec \metapost. \begin{figure}[t] \vspace*{1em} \begin{minipage}{.3\linewidth} \includegraphics{figmp.mps} \end{minipage} \begin{minipage}{.7\linewidth} \small \begin{alltt} vardef koch(expr A,B,n) = save C; pair C; C = A rotatedaround(1/3[A,B], 120); if n>0: koch( A, 1/3[A,B], n-1); koch( 1/3[A,B], C, n-1); koch( C, 2/3[A,B], n-1); koch( 2/3[A,B], B, n-1); else: draw A--1/3[A,B]--C--2/3[A,B]--B; fi; enddef; z0=(4cm,0); z1=z0 rotated 120; z2=z1 rotated 120; koch( z0, z1, 4 ); koch( z1, z2, 4 ); koch( z2, z0, 4 ); \end{alltt} \end{minipage} \caption{Exemple de figure \metapost}\label{fig:metapost} \end{figure} % Dans un souci d'exhaustivité, nous devons aussi mentionner % \asymptote~\cite{asymptote}, également un langage dédié à la création % de figures. Nous n'allons pas rentrer dans les détails de cet outil % car nous ne considérons plus les langages dédiés par la suite. Une alternative séduisante aux solutions précédentes consiste à utiliser un langage de programmation existant. Ainsi l'utilisateur n'a pas à apprendre un langage spécialisé et il bénéficie d'autre part de tous les avantages d'un langage de programmation moderne : erreurs détectées à la compilation, types de données complexes, structuration, etc. Toute la difficulté réside alors dans la manipulation des éléments \LaTeX, notamment la prise en compte de leur taille dans l'élaboration de la figure. Si on considère la famille des langages fonctionnels, on peut citer au moins deux exemples de telle intégration : \begin{itemize} \item \mlpictex~\cite{mlpictex} est\footnote{À notre connaissance, \mlpictex\ n'est plus distribué.} un ensemble de macros \LaTeX\ permettant d'inclure du code \camllight\ arbitraire dans un document \LaTeX. Ce code s'appuie sur une bibliothèque de dessin \postscript~\cite{postscript} et peut faire référence à des éléments \LaTeX, ainsi qu'à leur taille. \item \fmpost~\cite{fmpost} est une bibliothèque Haskell~\cite{haskell} produisant du code \metapost. C'est une approche légère qui réutilise les capacités graphiques de \metapost\ et substitue Haskell au langage de programmation de \metapost. \end{itemize} Cet article présente \mlpost, un outil qui adopte l'approche de \fmpost\ en utilisant \ocaml~\cite{ocaml} comme langage hôte. La première partie de l'article présente les choix de conception de \mlpost\ à travers un certain nombre d'exemples. La seconde partie détaille ensuite l'architecture logicielle de \mlpost. \mlpost\ est librement distribué à l'adresse \url{http://mlpost.lri.fr}. Toutes les figures de cet article ont été faites avec \mlpost, à l'exception des exemples pour \metapost\ et \nomdetikz. %%% CONS % pas de baseline % pas de mélange entre LaTeX et les graphiques \section{Principes et exemples}\label{exemples} \subsection{Principes} \paragraph{Boîtes.} Les briques de base de \mlpost\ sont les \textit{boîtes} : une boîte est un moyen d'encapsuler n'importe quel élément de dessin au sein d'un contour, qui peut être effectivement tracé ou non. On peut construire la boîte vide, des boîtes avec du \LaTeX\ arbitraire, etc. Ces boîtes peuvent ensuite être manipulées : imbrication arbitraire, placement à une position précise, alignement de plusieurs boîtes, flèches reliant plusieurs boîtes entre elles, création de tableaux, etc. Plusieurs boîtes peuvent aussi être regroupées au sein d'une seule afin de pouvoir les déplacer ensemble. L'exemple suivant montre deux boîtes simples, la deuxième étant déplacée un centimètre vers la droite en utilisant la fonction \verb|shift|. \medskip \begin{minipage}{0.18\linewidth} \includegraphics{simple.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} [ Box.draw (Box.tex "\\LaTeX"); Box.draw (Box.shift (Point.pt (cm 1., zero)) (circle (empty ()))) ] \end{ocaml} \end{minipage} \medskip\noindent Une figure \mlpost\ est simplement une liste de commandes de dessin. Ci-dessus, elle est réduite à deux occurrences de \texttt{Box.draw}, la commande qui dessine une boîte. % Notez que par défaut, le contour de la boîte contenant du \LaTeX n'a % pas été tracé, alors que celui de la boîte vide a été tracé. \paragraph{Placement relatif.} Un principe que nous avons suivi lors de la conception de \mlpost{} est de favoriser un placement relatif des objets plutôt qu'absolu. Ceci permet d'obtenir des figures plus robustes. En effet, imaginons que l'on veuille placer une boîte $A$ à \emph{droite} d'une boîte $B$. Une première possibilité serait de spécifier les positions approximativement, par exemple en donnant les abscisses 0 cm pour $A$ et 2 cm pour $B$. Cependant, si on change d'avis sur le contenu de $A$ et que la taille de cette boîte change, $A$ risque alors de se superposer à $B$. Il faut alors replacer toutes les boîtes de la figure manuellement. Pour éviter ça, \mlpost\ propose diverses méthodes pour placer les boîtes \emph{les unes par rapport aux autres}. On gagne alors du temps lors de la création et lors des modifications de la figure. L'exemple suivant utilise l'alignement horizontal \verb|hbox|, où l'argument optionnel \texttt{padding} permet de spécifier l'espacement horizontal entre deux boîtes : \medskip \begin{minipage}{0.2\linewidth} \includegraphics{align.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} [ Box.draw (Box.hbox ~padding:(cm 1.) [Box.tex "\\LaTeX"; circle (empty ())]) ] \end{ocaml} \end{minipage} \medskip\noindent Nous revenons plus en détail sur les boîtes et leur implémentation dans la section~\ref{subsec:boxes}. \paragraph{Persistance.} Un autre choix que nous avons fait est celui de la persistance~\cite{persistance} : lorsqu'un attribut d'une boîte (positionnement, couleur, etc.) est modifié, on obtient une nouvelle boîte, identique à la première sauf en l'attribut changé. En faisant le choix de structures de données persistantes, nous permettons à l'ancienne boîte, avec ses attributs inchangés, d'être préservée et encore accessible. Ainsi, on peut réutiliser plus facilement une boîte à plusieurs endroits du dessin, avec des attributs différents. Dans l'exemple suivant, on a utilisé trois instances de la même boîte \texttt{b}, dont le contour est tracé pour la deuxième. \medskip \begin{minipage}{0.22\linewidth} \includegraphics{persistance.mps} \end{minipage} \begin{minipage}{0.78\linewidth} \small\begin{ocaml} let b = Box.hbox ~padding:(cm 1.) [Box.tex "\\LaTeX"; circle (empty ())] in [ Box.draw (Box.vbox [b; set_stroke Color.black b; b]) ] \end{ocaml} \end{minipage} %TODO exemple ici qui introduit les noms des boites et les avantages / %inconvénients de la persistance \subsection{Exemples} Dans cette section, nous montrons quelques applications immédiates des boîtes de \mlpost. % blocs mémoire (listes, etc.) -- JCF % introduire Box.vblock % introduire les noms de boites \paragraph{Représentation de la mémoire.} Un besoin récurrent lorsque l'on enseigne l'algorithmique ou les concepts liés à un langage de programmation consiste à illustrer la structure des données en mémoire par des schémas de la forme \begin{center} \includegraphics{list123.mps} \end{center} Deux éléments sont nécessaires : le dessin des blocs d'une part et le dessin des pointeurs d'autre part. Pour réaliser les blocs, on utilise la fonction \texttt{Box.hblock} qui aligne des boîtes horizontalement, leur donne une hauteur commune et trace leur contour. Voici un exemple : \medskip \begin{minipage}{0.15\linewidth} \includegraphics{simple_block.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} let b = Box.hblock ~pos:`Bot [Box.tex "a"; Box.tex "b"; Box.tex "C"] in [ Box.draw b ] \end{ocaml} \end{minipage} \medskip\noindent À l'aide de \texttt{Box.hblock}, on peut facilement écrire une fonction \texttt{cons} qui construit un bloc de taille 2, dont le premier élément contient un texte \LaTeX\ arbitraire \texttt{hd} et le second est soit vide, soit le symbole $\bot$, selon la valeur du booléen \texttt{tl} : \begin{ocaml} let cons hd tl = let p1 = Box.tex ~name:"hd" hd in let p2 = Box.tex ~name:"tl" (if tl then "" else "\\ensuremath{\\bot}") in Box.hblock [p1; p2] \end{ocaml} L'argument optionnel \texttt{\~{}name} permet de nommer les sous-boîtes, de manière à pouvoir y accéder facilement par la suite. Écrivons maintenant une fonction \texttt{pointer\_arrow} pour matérialiser les pointeurs. Il s'agit de tracer une flèche entre deux boîtes données \texttt{a} et \texttt{b}. Pour cela, on commence par construire un chemin \texttt{p} reliant les centres de \texttt{a} et \texttt{b}, que l'on tronque à l'endroit où il intersecte le bord de la boîte \texttt{b} (avec la fonction \texttt{Path.cut\_after}). Puis on trace l'origine de la flèche à l'aide d'un chemin réduit à un point (le centre de \texttt{a}) et la flèche proprement dite à l'aide du chemin \texttt{p}. \medskip \begin{minipage}{0.2\linewidth} \includegraphics{block_arrow.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} let pointer_arrow a b = let p = pathp [Box.ctr a; Box.ctr b] in let p = Path.cut_after (Box.bpath b) p in let pen = Pen.scale (bp 4.) Pen.circle in Command.draw ~pen (pathp [Box.ctr a]) ++ draw_arrow p \end{ocaml} \end{minipage} %XXX virer ++ ? \medskip\noindent On utilise ici le symbole infixe \texttt{++} qui permet de concaténer des commandes de dessin. On utilise d'autre part \texttt{bp}, qui est une unité propre à \metapost, proche du point \postscript. Nous avons maintenant tous les éléments nécessaires pour écrire une fonction \texttt{draw\_list} qui prend en argument une liste \ocaml\ de fragments \LaTeX\ et réalise l'illustration correspondante. On commence par construire les différents blocs constituant la liste : \begin{ocaml} let draw_list l = let rec make = function | [] -> [] | [x] -> [cons x false] | x :: l -> cons x true :: make l in \end{ocaml} Puis on aligne ces blocs avec \texttt{Box.hbox}, en insérant de l'espace horizontal avec l'option \texttt{padding} : \begin{ocaml} let l = hbox ~padding:(bp 30.) (make l) in \end{ocaml} Pour dessiner les pointeurs, il suffit de parcourir la liste des boîtes (qui ont été placées) et d'utiliser la fonction \texttt{pointer\_arrow} précédente sur chaque paire de boîtes consécutives : \begin{ocaml} let rec arrows = function | [] | [_] -> nop | b1 :: (b2 :: _ as l) -> pointer_arrow (Box.get "tl" b1) (Box.get "hd" b2) ++ arrows l in \end{ocaml} On utilise ici la fonction \texttt{Box.get} qui permet de récupérer une sous-boîte par son nom. On accède ainsi aux boîtes nommées respectivement \verb!"hd"! et \verb!"tl"! qui ont été créées par la fonction \texttt{cons} puis encapsulées dans d'autres boîtes par les fonctions d'alignement. Enfin, on dessine les boîtes avec \texttt{Box.draw}, puis les flèches avec la fonction \texttt{arrows} : \begin{ocaml} [ Box.draw l; arrows (Array.to_list (Box.elts l)) ] \end{ocaml} On peut tester avec \begin{ocaml} draw_list (List.map (fun n -> Printf.sprintf "$\\sqrt{%d}$" n) [1;2;3;4]) \end{ocaml} qui donne bien le résultat attendu : \begin{center} \includegraphics{another_list.mps} \end{center} % De manière générale, les % fonctions \texttt{Box.tex} et \texttt{Box.box}, ainsi que toutes les % autres fonctions de création de boîtes, disposent d'arguments % optionnels \texttt{dx} et \texttt{dy} permettant de spécifier les % marges séparant le contenu du contour de la boîte. \paragraph{Diagrammes de classes.} Avec la fonction \texttt{Box.vblock}, analogue pour l'alignement vertical de la fonction \texttt{Box.hblock} introduite ci-dessus, il est facile de dessiner des diagrammes UML. Supposons que l'on veuille dessiner des schémas de classes tels que : \begin{center} \includegraphics{uml_client.mps} \end{center} Pour cela, introduisons une fonction \texttt{classblock} qui attend le nom de la classe ainsi que la liste des attributs et des méthodes. \begin{ocaml} let classblock name attr_list method_list = let vbox = Box.vbox ~pos:`Left in Box.vblock ~pos:`Left ~name [ tex ("{\\bf " ^ name ^ "}"); vbox (List.map tex attr_list); vbox (List.map tex method_list) ] \end{ocaml} Ici, le nom \texttt{name} de la classe est utilisé à la fois pour désigner le schéma dans le diagramme (l'argument labelisé \url{~name} de \texttt{Box.vblock}) et comme titre du schéma créé. Les attributs et les méthodes sont alignés verticalement indépendamment, puis on aligne le titre et les deux nouvelles boîtes obtenues en les encadrant\footnote{Notez qu'au contraire de {\tt hbox} et {\tt vbox}, les fonctions {\tt hblock} et {\tt vblock} tracent par défaut le contour de leurs sous-boîtes.}. On peut maintenant s'en servir pour dessiner un petit diagramme de classes : \medskip \begin{minipage}{0.38\linewidth} \includegraphics[width=0.9\linewidth]{uml.mps} \end{minipage} \begin{minipage}{0.6\linewidth} \small\begin{ocaml} let a = classblock "BankAccount" [ "balance : Dollars = $0$"] [ "deposit ..."; ... ] in let b = classblock "Client" [ "name : String"; ...] [] in let diag = Box.vbox ~padding:(cm 1.) [a;b] in [ Box.draw diag; box_label_arrow ~pos:`Left (Picture.tex "owns") (get "Client" diag) (get "BankAccount" diag) ] \end{ocaml} \end{minipage} \vspace{1em} Ici, on a d'abord créé deux schémas de classe avec la fonction \texttt{classblock}. Ces schémas sont ensuite alignés verticalement, et une flèche avec une étiquette est dessinée entre ces deux classes avec \texttt{box\_label\_arrow}. Le code pour cette figure est conceptuellement très simple, ne contient aucun placement absolu et ne dépasse pas les 15 lignes de code. % automate -- RB \paragraph{Automates.}\label{sec:automates} La théorie des langages est un domaine où l'on a rapidement besoin de dessiner des automates. Illustrons une façon d'utiliser \mlpost\ dans ce but. Nous allons définir les fonctions suivantes : \begin{itemize} \item \texttt{state} pour créer un état ; \item \texttt{final} pour transformer un état en un état final ; \item \texttt{initial} pour dessiner une flèche entrante sur un état initial ; \item \texttt{transition} pour dessiner une transition d'un état à un autre ; \item \texttt{loop} pour dessiner une transition d'un état vers lui-même. \end{itemize} On choisit de représenter les états par des boîtes \mlpost. La fonction \texttt{state} est juste une spé\-ci\-ali\-sa\-tion de la fonction {\tt Box.tex} à un contour circulaire, définie par l'application partielle suivante: \begin{ocaml} let state = Box.tex ~style:Circle ~stroke:(Some Color.black) \end{ocaml} Le paramètre \texttt{stroke} permet de spécifier si le contour doit être tracé et, le cas échéant, dans quelle couleur. De manière similaire, la fonction \texttt{final} est une spécialisation de la fonction {\tt Box.box} dont le rôle consiste à rajouter un cercle autour d'une boîte : \begin{ocaml} let final = Box.box ~style:Circle \end{ocaml} On peut déjà placer des états, finaux ou non, et les dessiner. Pour le placement, on utilise les fonctions d'alignement horizontal et vertical \texttt{Box.hbox} et \texttt{Box.vbox}. On suit donc le principe consistant à placer les objets de façon relative, les uns par rapport aux autres. \begin{minipage}{0.2\linewidth} \includegraphics{automate_1.mps} \end{minipage} \begin{minipage}{0.7\linewidth} \begin{ocaml} let states = Box.vbox ~padding:(cm 0.8) [ Box.hbox ~padding:(cm 1.4) [ state ~name:"alpha" "$\\alpha$"; state ~name:"beta" "$\\beta$" ]; final ~name:"gamma" (state "$\\gamma$") ] in [ Box.draw states ] \end{ocaml} \end{minipage} \medskip\noindent On note que l'ensemble des états est lui-même une boîte, \texttt{states}, contenant les états comme autant de sous-boîtes nommées. La fonction \texttt{initial} appose une flèche entrante à un état. Il s'agit donc d'une fonction qui prend le nom d'un état \texttt{q} et qui renvoie une commande dessinant une flèche vers \texttt{q}. On pourrait aussi renvoyer une boîte sans contour contenant \texttt{q} et la flèche, ce qui permettrait d'utiliser \texttt{initial} de la même façon que \texttt{final}. Cependant, la boîte obtenue n'aurait pas la même taille et la même forme que \texttt{q}, ce qui poserait des problèmes pour placer \texttt{q} ou pour dessiner des transitions vers ou à partir de \texttt{q}. \begin{ocaml} let initial (states : Box.t) name : Command.t = let q = Box.get name states in let p = Box.west q in Arrow.draw (Path.pathp [Point.shift p (Point.pt (cm (-0.3), zero)); p]) \end{ocaml} La fonction accède à la boîte \texttt{q} par son nom \texttt{name} dans la boîte \texttt{states} et détermine le point d'arrivée de la flèche avec \texttt{Box.west}. On pourrait généraliser cette fonction pour spécifier la position de la flèche. La fonction \texttt{transition} dessine une flèche d'un état à un autre. Cette fonction prend deux arguments optionnels \texttt{outd} et \texttt{ind} pour spécifier, en degrés, la direction sortante et la direction entrante de la flèche. On doit les convertir en vecteurs directeurs pour les passer\footnote{Nous utilisons ici une fonctionnalité d'\ocaml{} qui permet d'accéder à des arguments optionnels sans spécifier leur valeur par défaut, sous la forme d'un type {\tt option}. Nous passons ensuite directement ces valeurs de type {\tt option}, en tant qu'arguments optionnels, à la fonction {\tt cpath} par la syntaxe {\tt cpath ?outd ?ind x y}.} à \texttt{cpath}, qui calcule un chemin allant du bord d'une boîte au bord d'une autre boîte. Ce chemin est ensuite donné à la fonction \texttt{Arrow.draw} qui trace la flèche en plaçant une étiquette \texttt{tex} à la position \texttt{pos}. \begin{ocaml} let transition states tex pos ?outd ?ind x_name y_name = let x = Box.get x_name states and y = Box.get y_name states in let outd = match outd with | None -> None | Some a -> Some (vec (dir a)) in let ind = match ind with | None -> None | Some a -> Some (vec (dir a)) in Arrow.draw ~tex ~pos (cpath ?outd ?ind x y) \end{ocaml} La fonction \texttt{loop} est similaire à la fonction \texttt{transition}, mais elle doit calculer un chemin plus complexe. En effet, \texttt{cpath} appliqué à deux boîtes identiques renvoie un chemin vide et on ne peut donc pas l'utiliser. À la place, on calcule un point $A$ suffisamment éloigné de la boîte et on trace un chemin qui part du centre, qui passe par $A$ puis qui revient au centre. On utilise au passage la fonction \texttt{knotp} qui permet de spécifier un point avec une tangente, et \texttt{pathk} qui transforme une liste de tels points en un chemin. \begin{minipage}{0.3\linewidth} \includegraphics{loop_explain.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \small\begin{ocaml} let loop states tex name = let box = Box.get name states in let a = Point.shift (Box.south box) (Point.pt (cm 0., cm (-0.4))) in let c = Box.ctr box in let p = Path.pathk [ knotp ~r:(vec (dir 225.)) c; knotp a; knotp ~l:(vec (dir 135.)) c; ] in let bp = Box.bpath box in Arrow.draw ~tex ~pos:`Bot (cut_after bp (cut_before bp p)) \end{ocaml} \end{minipage} Ici encore, on pourrait généraliser cette fonction pour spécifier la position de la flèche. On peut maintenant dessiner facilement des automates en utilisant cette bibliothèque. \medskip \begin{minipage}{0.2\linewidth} \includegraphics{automate.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \small\begin{ocaml} let automate = let states = ... in [ Box.draw states; transition states "a" `Lowleft "alpha" "gamma"; transition states "b" `Lowright "gamma" "beta"; transition states "c" `Top ~outd:25. ~ind:335. "alpha" "beta"; transition states "d" `Bot ~outd:205. ~ind:155. "beta" "alpha"; loop states "e" "gamma"; initial states "alpha" ] \end{ocaml} \end{minipage} \subsection{Exemples utilisant des calculs en \ocaml} Cette section illustre l'un des avantages de \mlpost: la capacité de dessiner directement un objet que l'on a calculé/programmé en \ocaml. % plot -- SL \paragraph{Graphe de fonction.} Un exemple simple de dessin résultant d'un calcul est celui du graphe d'une fonction. \mlpost\ fournit un module \texttt{Plot} à cet effet. La figure suivante montre un exemple basique d'utilisation de cette extension : \medskip \begin{minipage}{0.28\linewidth} \includegraphics[width=0.9\linewidth]{graph_sqrt.mps} \end{minipage} \begin{minipage}{0.65\linewidth} \small\begin{ocaml} let u = cm 1. in let sk = Plot.mk_skeleton 4 3 u u in let label = Picture.tex "$y=...$", `Upleft, 3 in let f x = sqrt (float x +. 0.5) in [ Plot.draw_func ~label f sk; Plot.draw_simple_axes "$x$" "$y$" sk ] \end{ocaml} \end{minipage} \medskip\noindent La fonction \texttt{mk\_skeleton} permet de construire un cannevas de 4 unités sur 3, qui est l'objet de base de l'extension \texttt{Plot}. Il est alors possible de dessiner un graphe de fonction et des axes au sein de ce cannevas, comme illustré ci-dessus. L'extension dispose de beaucoup d'options (tracé de la grille, affichage des abscisses et ordonnées, différents types de graphes de fonctions) qui permettent de réaliser des figures plus complexes, telle que celle décrite dans le paragraphe suivant. \paragraph{Abstractions d'horloges dans un système synchrone flot-de-données.} L'exemple ci-dessous, réalisé par Florence Plateau, provient d'un problème réel~\cite{MandelPlateau08} et illustre un certain nombre des possibilités de l'extension \texttt{Plot}. % % Ainsi les fonctions illustrées sur cette figure ont été codées comme des fonctions \ocaml{} standard. De plus, la ligne intermédiaire dans la partie située sous le graphe principal, et dénotée par $w_2$, représente les discontinuités de la fonction $f_{w_2}$ du graphe principal. Cette ligne est calculée \textit{directement} à partir de la fonction $f_{w_2}$ ; si l'on décide de changer la fonction $f_{w_2}$, la ligne $w_2$ sera mise à jour automatiquement. Cela est également vrai pour certaines étiquettes de la figure, comme l'abscisse $[w_2]_5$. Ceci offre une flexiblité très intéressante lors de la phase de développement d'une telle figure. \begin{figure}[h] \centering \begin{center} \medskip \includegraphics{florence.mps} \end{center} %\caption{expliquer de quoi ça parle} \label{fig:florence} \end{figure} \paragraph{Bresenham.} À titre de dernier exemple, supposons que l'on veuille illustrer l'algorithme de tracé de segment de Bresenham~\cite{bresenham}, par exemple sur le segment reliant le point $(x_1,y_1)=(0,0)$ au point $(x_2,y_2)=(9,6)$. Pour cela, on commence par stocker le résultat de l'algorithme dans un tableau \texttt{bresenham\_data}, tel que $\texttt{bresenham\_data.(}x\texttt{)}$ donne l'ordonnée du point d'abscisse $x$. \begin{ocaml} let x2 = 9 and y2 = 6 let bresenham_data = Array.create (x2+1) 0 let () = (* remplissage du tableau a *) (* avec l'algorithme de Bresenham *) ... \end{ocaml} On peut alors réaliser la figure très facilement, à l'aide de la fonction \texttt{Box.gridi} fournie par \mlpost, qui construit une matrice de boîtes alignées à partir d'une largeur, d'une hauteur et d'une fonction construisant la boîte $(i,j)$, d'une manière analogue à \texttt{Array.create\_matrix}. \medskip \begin{minipage}{0.32\linewidth} \includegraphics{bresenham0.mps} \end{minipage} \begin{minipage}{0.7\linewidth} \vspace*{0.8em} \small\begin{ocaml} let width = bp 6. and height = bp 6. in let g = Box.gridi (x2+1) (y2+1) (fun i j -> let fill = if bresenham_data.(i) = y2 - j then Some Color.red else None in Box.rect ?fill (Box.empty ~width ~height ())) in [ Box.draw g ] \end{ocaml} \end{minipage} \medskip\noindent Les boîtes sont des boîtes vides de 6 points de côté, créées avec \texttt{Box.empty}. Pour les boîtes correspondant à des points dessinés par l'algorithme de Bresenham, on indique que la boîte doit être remplie en rouge, à l'aide de l'argument optionnel \texttt{fill}. Pour parachever la figure, on va ajouter des étiquettes indiquant les coordonnées des deux extrémités du segment. Pour placer une étiquette à côté de la case $(i,j)$, on récupère la boîte correspondante à l'aide de \texttt{Box.nth}, puis on récupère un point particulier de cette boîte (par exemple le point au milieu en bas avec \texttt{Box.south}), puis enfin on trace l'étiquette avec \texttt{Command.label}. \medskip \begin{minipage}{0.28\linewidth} \vspace*{0.8em} \hspace*{-1.4em}\includegraphics{bresenham.mps} \end{minipage} \begin{minipage}{0.7\linewidth}\small \begin{ocaml} let bresenham = let width = bp 6. and height = bp 6. in let g = ... in let get i j = Box.nth i (Box.nth (y2-j) g) in let label pos s point i j = Command.label ~pos (Picture.tex s) (point (get i j)) in [ Box.draw g; label `Bot "0" Box.south 0 0; label `Bot "$x_2$" Box.south x2 0; label `Left "0" Box.west 0 0; label `Left "$y_2$" Box.west 0 y2 ] \end{ocaml} \end{minipage} \section{Architecture logicielle}\label{archi} La figure~\ref{fig:etapes} montre le fonctionnement de \mlpost. Tout d'abord, \mlpost\ est un outil de génération de fichier \metapost\ sous forme de bibliothèque \ocaml. À l'aide de cette bibliothèque, l'utilisateur écrit un programme qui, à l'exécution, construit un arbre de syntaxe abstraite \metapost. Cet arbre est imprimé dans un fichier \verb|figure.mp| qui est lu par \metapost\ pour générer un ou plusieurs fichiers \postscript\footnote{Ces fichiers n'ont pas le suffixe \texttt{.ps} car il leur manque l'en-tête.}. L'inclusion de ces figures dans un document \LaTeX{} se fait simplement en utilisant la commande \verb|\includegraphics| du package \textsf{graphicx}. Pour compiler le document \LaTeX{} avec {\tt pdflatex}, il suffit de changer l'extension des figures générées, ce qu'une option de l'outil \mlpost{} permet de faire facilement. \begin{figure}[h] \begin{center} \includegraphics[width=\textwidth]{stages.mps} \end{center} \caption{Architecture de \mlpost}\label{fig:etapes} \end{figure} Il est important de noter que le fichier \metapost\ de sortie n'est pas obtenu par {\em compilation} du code source \ocaml, mais par une \emph{exécution} du programme qui construit un arbre de syntaxe abstraite \metapost. Cette méthode a l'inconvénient qu'une boucle ou itération dans le programme de départ sera traduite par une suite de commandes obtenues par le déroulement de la boucle, et non par une construction de boucle du langage cible. Ceci étant dit, dans notre cas, le coût supplémentaire est faible, puisque \metapost\ déroule également les boucles dans les fichiers \postscript\ de sortie. % schéma de l'architecture \begin{figure}[ht] \begin{center} ~\\[0.5em] \includegraphics{architecture.mps} \end{center} \vspace*{-1em} \caption{Architecture de \mlpost}\label{fig:archi} \end{figure} L'architecture générale de \mlpost{} est schématisée en figure~\ref{fig:archi}. Au niveau le plus bas se trouvent les interfaces correspondant aux types primitifs de \metapost. Ce sont ces objets qui sont {\it in fine} traduits en du code \metapost, et nous les décrivons de manière plus détaillée dans la section~\ref{subsec:types}. La couche intermédiaire contient des éléments que nous estimons être de bas niveau mais qui ne sont pas présents dans \metapost : ils sont propres à \mlpost\ et ont été construits à partir de la couche inférieure. Les sections~\ref{subsec:boxes} et \ref{subsec:arrows} reviennent plus en détail sur deux de ces modules, respectivement \texttt{Box} et \texttt{Arrow}. Enfin, on trouve au plus haut niveau des modules tels que le module \texttt{Plot} présenté dans la section précédente. L'intégralité des modules de \mlpost\ est empaquetée dans un module \texttt{Mlpost}, afin de ne pas polluer l'espace de noms d'\ocaml. \subsection{Types primitifs de \metapost}\label{subsec:types} La couche de bas niveau de \mlpost\ est une interface fidèle à \metapost. Elle comporte tous les types de base de \metapost~: \begin{description} \item[Le type numérique (module \texttt{Num})] représente des longueurs. En première approximation, ce type pourrait être assimilé au type \texttt{float} d'\ocaml, mais certaines valeurs, telle que la taille d'un élément \LaTeX, ne sont connues qu'à l'interprétation du fichier \metapost. La plupart des calculs sont donc effectués de manière symbolique et le type \texttt{Num.t} doit donc être abstrait. \item[Le type point (module \texttt{Point})] représente des points dans l'espace à deux dimensions. Pour les mêmes raisons que les numériques, les points ne sont pas simplement des paires de flottants, mais doivent être représentés de manière symbolique. Le type \texttt{Point.t} est également utilisé pour représenter les vecteurs. \item[Les chemins (module \texttt{Path})] sont des lignes représentées par des courbes de Bézier. Ils sont à la base de tout dessin \metapost. Toutes les possibilités de construction de chemin dans \metapost\ ont été interfacées. On peut dessiner des lignes droites ou des lignes courbes en précisant les points de contrôle, la tension de la courbe, etc. \item[Les transformations (module \texttt{Transform})] permettent d'appliquer une transformation linéaire à un objet quelconque. Il est ainsi possible de déplacer des objets, les redimensionner, les faire pivoter ou encore combiner toutes ces transformations. \item[Les plumes (module \texttt{Pen})] permettent de choisir l'épaisseur et la forme du stylo utilisé pour dessiner les chemins. \item[Les figures (module \texttt{Picture})] permettent de rassembler plusieurs éléments graphiques en un seul, qu'il s'agisse d'éléments \LaTeX\ ou de commandes de dessin arbitraires. Le type \texttt{Picture.t} permet de traiter une figure arbitrairement complexe comme un objet de base que l'on peut copier, transformer, etc. Le module \texttt{Picture} permet également de découper une figure à l'aide d'une surface décrite par un chemin clos (\textit{clipping}). \end{description} Les autres types \metapost\ (chaînes de caractères, booléens, couleurs) sont directement représentés en \ocaml. L'interface de \mlpost\ contient aussi un module \texttt{Command} qui définit le type des commandes \metapost : commandes de dessin, de remplissage, itérations, séquences, etc. \paragraph{Dépendances circulaires.} La réalisation de ces modules de bas niveau présente quelques difficultés. Premièrement, la plupart des modules présentés sont {\em a priori} mutuellement récursifs : par exemple, les transformations s'appliquent à tous les autres objets, donc chaque module contient une fonction \begin{ocaml} val transform : Transform.t -> t -> t \end{ocaml} où le type \texttt{t} représente le type principal du module en question. D'un autre côté, les transformations sont elles-mêmes construites à l'aide de numériques et de points: \begin{ocaml} val shifted : Point.t -> t \end{ocaml} où \texttt{t} est le type des transformations. Des dépendances circulaires existent aussi entre types et sont aggravées par la représentation symbolique des objets (par exemple, les projections \texttt{xpart} et \texttt{ypart} du module \texttt{Point} doivent retourner des numériques et non des flottants). Nous souhaitons réaliser ces différents modules dans des fichiers différents mais \ocaml\ ne permet pas de dépendances circulaires entre des fichiers. Notre solution consiste à définir tous les \emph{types} dans un seul fichier \texttt{types.mli}. Chaque module fait maintenant référence à ce fichier. Par exemple, dans le fichier \texttt{path.ml}, qui fournit l'implémentation du module \texttt{Path}, on trouvera \begin{ocaml} type t = Types.path \end{ocaml} La dépendance circulaire entre les modules est ainsi cassée de manière très classique. En revanche, on souhaite cacher l'existence du module \texttt{Types} pour les deux raisons suivantes : \begin{itemize} \item la clarté des messages d'erreur ; \item la clarté de la documentation générée par \texttt{ocamldoc}. \end{itemize} On souhaite donc rétablir la circularité entre les modules au sein de l'interface du module \texttt{Mlpost}. Pour cela, on écrit un unique fichier \texttt{mlpost.mli} qui contient les définitions des signatures des modules à exporter : \medskip \begin{minipage}{0.3\textwidth} \small\begin{ocaml} module rec Point : sig type t val xpart : t -> Num.t ... end and Num : sig type t ... end and Path : sig type t ... end ... \end{ocaml} \end{minipage} \begin{minipage}{0.6\textwidth} \includegraphics[width=1\textwidth]{deps.mps} \end{minipage} Toutes ces signatures sont déclarées de manière mutuellement récursive. La signature de \texttt{Point} peut ainsi faire référence à \texttt{Path} et inversement. On notera que les types tels que \texttt{Point.t} sont maintenant abstraits dans l'interface, rendant invisible l'existence du module \texttt{Types}. Par ailleurs, les implémentations de ces modules sont contenues dans des fichiers indépendants \texttt{num.ml}, \texttt{point.ml}, etc., qui sont compilés avec l'option {\tt -for-pack Mlpost}. Cet agencement est en outre très pratique pour la documentation de l'API : c'est uniquement le fichier \texttt{mlpost.mli} qui sert d'entrée à l'outil \texttt{ocamldoc}. \paragraph{Hash-consing et traduction vers \metapost.} Le choix d'une représentation symbolique de la plupart des objets impose des efforts supplémentaires pour minimiser l'utilisation de la mémoire et la taille des fichiers \metapost\ de sortie. En effet, l'arbre de syntaxe abstraite (AST) contient beaucoup de n\oe uds identiques mais construits de manière différente, qui prennent donc inutilement de la place aussi bien en mémoire que dans le fichier \metapost\ généré. C'est d'autant plus gênant que \metapost\ devra lire ce fichier et passera donc davantage de temps sur des calculs répétés. Pour y remédier, nous utilisons la technique du {\em hash-consing}~\cite{ConchonFilliatre06wml} appliquée à l'arbre de syntaxe abstraite. Cette technique permet de partager des valeurs structurellement égales. Elle utilise une table de hachage globale qui stocke toutes les valeurs déjà créées. Avant de créer un nouvel objet, on regarde dans cette table si un objet structurellement égal existe déjà. Pour que le calcul de la valeur de hachage soit efficace, chaque (sous-)terme vient avec sa valeur de hachage. Le partage réalisé est maximal, ce qui permet de substituer l'égalité physique (\texttt{==}) à l'égalité structurelle (\texttt{=}). Cette technique diminue l'utilisation de la mémoire, mais ne change rien {\em a priori} à la taille des fichiers générés. La structure hash-consée {\em réalise} le partage, mais elle ne sait pas quels sont les n\oe uds effectivement utilisés au moins deux fois. Pour cela, on réalise un simple parcours en profondeur de la structure, en comptant les occurrences de chaque n\oe ud. Il est néanmoins possible de rencontrer une nouvelle fois un sous-n\oe ud d'une structure, comme le montre l'exemple ci-dessous : \begin{center} \includegraphics[scale=1.5]{sharing.mps} \end{center} \noindent Dans cette configuration, le n\oe ud $f$ est réellement utilisé deux fois, alors que le n\oe ud $e$ n'est utilisé qu'une seule fois, par le n\oe ud $d$, même si celui-ci est utilisé deux fois à son tour. Autrement dit, on comptabilise pour chaque n\oe ud le nombre de flèches incidentes. Après cette analyse, la génération du fichier \metapost\ devient très simple : il suffit de traverser de nouveau l'arbre de syntaxe abstraite et, quand on visite un n\oe ud qui est utilisé au moins deux fois, on construit une définition \metapost\ pour cet objet. Il faut néanmoins prendre en compte les particularités syntaxiques de \metapost\ telles que la précédence inhabituelle des opérateurs arithmétiques et la restriction de l'application de certaines constructions à des variables. De cette façon, on arrive à avoir du code \metapost\ relativement petit\footnote{En l'absence de boucles \texttt{for} et de macros dans le code \metapost, nous avons observé, sans avoir fait de tests très exhaustifs, une taille du code généré du même ordre de grandeur que celle du code \metapost\ écrit à la main.}, malgré la délégation des calculs à \metapost. \subsection{Boîtes}\label{subsec:boxes} Comme nous l'avons illustré déjà maintes fois, les boîtes de \mlpost\ peuvent être réduites à de simples objets \LaTeX\ ou bien être constituées d'un ensemble d'autres boîtes. Le type des boîtes est donc un type récursif de la forme suivante : \begin{ocaml} type t = { name : string option; width : Num.t; height : Num.t; pen : Pen.t option; ... desc : desc; } and desc = | Emp | Pic of Picture.t | Grp of t array * t Smap.t \end{ocaml} Chaque boîte est éventuellement nommée (champ \texttt{name}), possède un certain nombre d'attributs (position, taille, couleur, bordure, remplissage, etc.) et sa nature est donnée par le champ \texttt{desc}. Ce dernier indique s'il s'agit d'une boîte vide, d'une image ou bien d'une boîte composite. Dans ce dernier cas, les sous-boîtes sont contenues dans un tableau, qui est accompagné d'une table (réalisée par le module \texttt{Smap}) permettant un accès plus rapide à une sous-boîte par son nom. Le dessin d'une boîte est immédiat. On trace d'une part son contour et d'autre part son contenu. Ce dernier est soit une boîte atomique directement dessinée à l'aide de \texttt{Command.draw\_pic}, soit une boîte composite dont le dessin est tout simplement obtenu en dessinant récursivement chaque sous-boîte. Pour réaliser les diverses fonctions de placement, on commence par écrire une fonction de translation d'une boîte par un vecteur donné : \begin{ocaml} Box.shift : Point.t -> Box.t -> Box.t \end{ocaml} Cette fonction est naturellement récursive sur la structure de la boîte. Il est important de noter que cette fonction renvoie une \emph{nouvelle} boîte, sans altérer son argument (les boîtes sont persistantes). Une fois cette fonction donnée, il est aisé de réaliser les fonctions \texttt{Box.hbox}, \texttt{Box.hblock}, etc. \subsection{Flèches} \label{subsec:arrows} %% RB \metapost\ ne propose qu'un seul type de flèche. Une flèche \metapost\ suit un chemin arbitraire mais son tracé est limité aux différents styles de trait (plume et pointillés) et la tête de flèche est toujours la même : \begin{center} \includegraphics[width=\textwidth]{arrow_metapost.mps} \end{center} Avec \mlpost, l'utilisateur peut créer ses propres catégories de flèches à l'aide du module \texttt{Arrow}. Celui-ci propose deux types : \begin{itemize} \item Le type \texttt{head} décrit comment dessiner une tête de flèche. Les éléments de type \texttt{head} sont des fonctions prenant en argument la position et la direction de la tête de flèche et renvoyant une commande dessinant la tête de flèche. \item Le type abstrait \texttt{kind} décrit une catégorie de flèche. Une catégorie décrit les différents éléments dans le dessin d'une flèche, les têtes de flèche pouvant en réalité être placées n'importe où le long de la flèche. Pour construire une nouvelle catégorie, on part de la catégorie vide et on ajoute des traits et des têtes. \end{itemize} La fonction \texttt{draw} permet de dessiner une flèche d'une catégorie donnée en suivant un chemin donné. Les flèches sont alors dessinées en utilisant les primitives de \metapost. Ceci a l'inconvénient d'utiliser plus de ressources mais permet d'imaginer de nombreuses catégories de flèches. On peut en particulier retrouver les flèches de \metapost. On part d'un corps vide et on lui ajoute un trait normal sur toute la longueur. On ajoute enfin une tête triangulaire remplie, et on obtient : \medskip \begin{minipage}{0.2\linewidth} \includegraphics{arrow_simple.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \begin{ocaml} let kind = Arrow.add_head ~head:Arrow.head_triangle_full (Arrow.add_line Arrow.empty) in [ Arrow.draw ~kind (...path...) ] \end{ocaml} \end{minipage} \medskip La section~\ref{sec:automates} contient une figure décrivant le fonctionnement de la fonction \texttt{loop}. Pour les besoins de cette figure, on a créé un type de flèche spécial, composé d'un début et d'une fin en pointillés et avec une tête placée différemment : \begin{center} \includegraphics[width=\textwidth]{arrow_loop_explain.mps} \end{center} Le code permettant d'obtenir cette catégorie de flèche est le suivant : {\small \begin{ocaml} let kind = Arrow.add_belt ~point:0.9 (Arrow.add_line ~dashed:Dash.evenly ~to_point:0.1 (Arrow.add_line ~dashed:Dash.evenly ~from_point:0.9 (Arrow.add_line ~from_point:0.1 ~to_point:0.9 Arrow.empty))) \end{ocaml} } \section{Conclusion}\label{conclusion} Nous avons présenté \mlpost, une bibliothèque \ocaml\ au dessus de \metapost. Nous espérons avoir convaincu le lecteur des avantages que la présentation sous forme de bibliothèque apporte : familiarité avec le langage pour les programmeurs \ocaml, typage fort, des constructions de programmation de haut niveau, des dessins résultants de calculs arbitraires, etc. \mlpost\ fournit volontairement un nombre restreint de primitives, car l'utilisateur peut aisément construire des extensions au dessus de \mlpost. En cela, \mlpost\ diffère de bibliothèques \LaTeX\ telles que \nomdetikz\ ou \pstricks, où de très nombreuses fonctionnalités sont fournies mais où il est très difficile d'en ajouter pour qui ne maîtrise pas \TeX. L'une des forces de \mlpost\ est de proposer un style déclaratif, là où la majorité des bibliothèques graphiques propose un style impératif. Ceci permet en particulier un \emph{partage} immédiat de sous-éléments dans une ou plusieurs figures. Une autre force de \mlpost\ est le typage statique directement hérité d'\ocaml. On évite ainsi l'immense majorité des erreurs à l'exécution de \metapost, souvent cryptiques. Il reste néanmoins les erreurs éventuellement contenues dans les extraits de \LaTeX\ ou les erreurs de nature géométrique telles que le remplissage d'un chemin en forme de 8. Nous pourrions envisager d'utiliser des types \ocaml\ plus précis, par exemple pour distinguer les chemins clos et non clos ou encore les points et les vecteurs. Il reste une fonctionnalité intéressante de \metapost\ qui n'est pas interfacée dans \mlpost~: la résolution d'équations linéaires. Il y a deux raisons à cela. D'une part, les équations servent souvent au placement implicite, et \mlpost\ fournit une alternative sous la forme de fonctions d'alignement de boîtes. D'autre part, la résolution d'équations de \metapost\ procède de manière impérative et il n'est pas simple de l'intégrer dans le contexte déclaratif qui est le nôtre. Ceci étant dit, il serait intéressant d'explorer des méthodes de placement plus automatiques que celles que nous proposons, par exemple inspirées de la manière dont \TeX{} mets en page lignes, pages et paragraphes. Enfin, il est important de noter que \mlpost\ n'est pas lié à \metapost\ de manière intrinsèque. On pourrait facilement ajouter une sortie \nomdetikz, ou même directement une sortie \postscript\ à condition d'utiliser une technique similaire à celle de \metapost\ pour l'inclusion de \LaTeX. \medskip \noindent \vbox{ \begin{center} \includegraphics[width=0.3\textwidth]{ford.mps} \medskip \begin{minipage}{0.7\textwidth} \begin{center} \bf Remerciements \end{center} \centering Les auteurs tiennent à remercier Florence Plateau, Yannick Moy et Claude Marché pour leur contribution à \mlpost, Sylvie Boldo pour la suggestion du titre de l'article et les relecteurs pour leurs remarques. \end{minipage} \medskip \includegraphics[angle=180,width=0.3\textwidth]{ford.mps} \end{center} } % La bibliographie % N'oubliez pas de l'inclure lors de votre soumission. \begin{thebibliography}{10} \bibitem{haskell} {Le langage Haskell}. \newblock \url{http://www.haskell.org/}. \bibitem{ocaml} {Le langage Objective Caml}. \newblock \url{http://caml.inria.fr/}. \bibitem{bresenham} Jack~E. Bresenham. \newblock Algorithm for computer control of a digital plotter. \newblock {\em IBM Systems Journal}, 4(1):25--30, January 1965. \bibitem{mlpictex} Emmanuel Chailloux and Asc\'ander Su\'arez. \newblock {\mlpictex}, a picture environment for {\LaTeX}. \newblock In {\em Workshop on {ML}}, pages 79--90, 1994. \bibitem{MandelPlateau08} Albert Cohen, Louis Mandel, Florence Plateau, and Marc Pouzet. \newblock {Abstraction of Clocks in Synchronous Data-flow Systems}. \newblock In {\em The Sixth ASIAN Symposium on Programming Languages and Systems (APLAS)}, Bangalore, India, December 2008. \bibitem{ConchonFilliatre06wml} Sylvain Conchon and Jean-Christophe Filli\^atre. \newblock {Type-Safe Modular Hash-Consing}. \newblock In {\em ACM SIGPLAN Workshop on ML}, Portland, Oregon, September 2006. \bibitem{persistance} J.~R. Driscoll, N.~Sarnak, D.~D. Sleator, and R.~E. Tarjan. \newblock {Making Data Structures Persistent}. \newblock {\em Journal of Computer and System Sciences}, 38(1):86--124, 1989. \bibitem{pstricks} T.~Van~Zandt et~al. \newblock {PSTricks}. \newblock \url{http://tug.org/PSTricks/}. \bibitem{fmpost} Meik Hellmund, Ralf Hinze, Joachim Korittky, Marco Kuhlmann, Ferenc W\'agner, and Peter Simons. \newblock {\fmpost}. \newblock \url{http://cryp.to/funcmp/}. \bibitem{metapost} John Hobby. \newblock \metapost, 1994. \newblock \url{http://plan9.bell-labs.com/who/hobby/MetaPost.html}. \bibitem{metafont} Donald~E. Knuth. \newblock {\em The {\metafont} Book}. \newblock Addison-Wesley, 1984. \bibitem{dia} Alexander Larsson. \newblock {Dia}. \newblock \url{http://live.gnome.org/Dia}. \bibitem{postscript} Glenn~C. Reid. \newblock {\em {PostScript Language Program Design}}. \newblock Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA, 1988. \bibitem{xfig} Brian~V. Smith. \newblock {Xfig}. \newblock \url{http://www.xfig.org/}. \bibitem{tikz} Till Tantau. \newblock {PGF and TikZ -- Graphic systems for \TeX}. \newblock \url{http://sourceforge.net/projects/pgf/}. \end{thebibliography} %\bibliographystyle{plain} %\bibliography{./biblio} \vfill %\pagebreak %\thispagestyle{colloquetitle} %\cleardoublepage \end{document} % Local Variables: % coding: iso-latin-1 % ispell-local-dictionary: "francais" % End: mlpost-0.8.2/papers/jfla2009/main.tex000066400000000000000000001415741306046515300172450ustar00rootroot00000000000000\documentclass[twoside]{article} \usepackage[latin1]{inputenc} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage{actes,alltt,url,graphicx} \usepackage[french]{babel} \usepackage{mflogo} \usepackage{tikz} % macros \newcommand{\ocaml}{OCaml} \newcommand{\camllight}{Caml Light} \newcommand{\asymptote}{\textsf{Asymptote}} \newcommand{\mlpost}{\textsc{Mlpost}} \newcommand{\metapost}{\MP} \newcommand{\fmpost}{\textit{functional} \metapost} \newcommand{\metafont}{\MF} \newcommand{\nomdetikz}{\textsf{TikZ}} \newcommand{\pstricks}{\textsf{PSTricks}} \newcommand{\dia}{\textsf{Dia}} \newcommand{\xfig}{\textsf{Xfig}} \newcommand{\postscript}{PostScript} \newcommand{\mlpictex}{mlP\hspace{-0.2em}\raisebox{-0.2em}{i}\hspace{-0.1em}c\hspace{-0.1em}\TeX} \title{Faire bonne figure avec \mlpost} \author{R. Bardou$^1$ \& J.-C. Fillitre$^1$ \& J. Kanig$^1$ \& S. Lescuyer$^1$} \titlehead{Faire bonne figure avec \mlpost}% a droite (page impaire) \authorhead{Bardou \& Fillitre \& Kanig \& Lescuyer}% a gauche (page paire) \affiliation{\begin{tabular}{rr} \\ 1: ProVal / INRIA Saclay -- le-de-France \\ 91893 Orsay Cedex, France \\ LRI / CNRS -- Universit Paris Sud \\ 91405 Orsay Cedex, France \\ {\tt \{bardou,filliatr,kanig,lescuyer\}@lri.fr} \end{tabular}} \begin{document} \setcounter{page}{1} \maketitle \begin{abstract} Cet article prsente \mlpost, une bibliothque \ocaml\ de dessin scientifique. Elle s'appuie sur \metapost, qui permet notamment d'inclure des fragments \LaTeX\ dans les figures. \ocaml\ offre une alternative sduisante aux langages de macros \LaTeX, aux langages spcialiss ou mme aux outils graphiques. En particulier, l'utilisateur de \mlpost\ bnficie de toute l'expressivit d'\ocaml\ et de son typage statique. Enfin \mlpost\ propose un style dclaratif qui diffre de celui, souvent impratif, des outils existants. \end{abstract} % TODO ? : expliquer comment fait \metapost pour inclure du \LaTeX % TODO : expliquer les labels \section{Introduction} Lors de la rdaction de documents nature scientifique (articles, cours, livres, etc.), il est trs souvent ncessaire de raliser des figures. Ces figures permettent d'agrmenter le texte en illustrant aussi bien les objets dont il est question dans le document que les liens qui existent entre eux et facilitent ainsi leur comprhension. Elles sont donc un composant fondamental au caractre didactique de tels documents, mais leur ralisation est souvent fastidieuse. En particulier, il est souvent ncessaire d'y inclure des lments mis en forme par \LaTeX\ (formules, etc.), ce que bon nombre de logiciels de dessin ne permettent pas. Ainsi, on peut souhaiter raliser un schma tel que celui-ci \begin{center} \includegraphics{yannick1.mps} \end{center} en attachant de l'importance au fait que des expressions comme $a_1+s_1-1$ apparaissent exactement comme dans le corps du document. Il existe plusieurs familles d'outils pour raliser des figures intgrer dans un document \LaTeX~: \begin{itemize} \item des interfaces graphiques disposant d'une sortie \LaTeX, telles que \dia~\cite{dia} ou \xfig~\cite{xfig} ; \item des bibliothques \LaTeX, telles que \pstricks~\cite{pstricks} ou encore \nomdetikz~\cite{tikz} ; \item des outils externes en ligne de commande, tel que \metapost~\cite{metapost}. \end{itemize} % Il faudrait d'ailleurs dj que ces logiciels de dessin soient vectoriels % ce qui n'est pas forcment le cas. Chaque famille a ses avantages et ses inconvnients. Les interfaces graphiques sont les plus accessibles, notamment pour un placement rapide et intuitif des diffrents lments de la figure, mais l'intgration de texte mis en forme par \LaTeX\ est dlicate. Dans le cas de \xfig\ et de \dia, la taille des lments \LaTeX\ n'est pas connue lors de l'dition de la figure ; en outre, dans le cas de \dia, l'intgration de \LaTeX\ dans une figure ncessite de l'exporter sous forme de macros \nomdetikz\ et d'diter le rsultat. %% TODO : RAPPELER QUE PSTRICKS NE MARCHE PAS AVEC PDFLATEX ! Les bibliothques \LaTeX\ telles que \pstricks\ ou \nomdetikz\ offrent l'intgration la plus naturelle avec \LaTeX. En particulier, elles permettent de combiner arbitrairement lments graphiques et textes \LaTeX\ \begin{tikzpicture}[baseline=(a.base)] \path[use as bounding box] (0,0) node[draw,style=dashed] (a) {comme ceci}; \draw[->] (a) .. controls +(-2cm,1cm) and +(-2cm,-0cm) .. (a); \end{tikzpicture}. En revanche, elles demandent d'apprendre un certain nombre de macros et de notations et souffrent surtout des dfauts inhrents \LaTeX~: \begin{itemize} \item des erreurs dtectes uniquement l'interprtation, peu claires et parfois mal localises ; \item un langage \emph{de programmation} peu commode (syntaxe obscure, absence de typage, code difficile structurer). \end{itemize} Ces inconvnients sont notamment un frein au dveloppement de bibliothques de haut niveau au dessus de ces langages ainsi qu' la rutilisation de figures. \metapost\ se prsente comme une alternative ces bibliothques \LaTeX, en proposant un langage de programmation part entire spcialis dans la construction de figures contenant des lments \LaTeX. Il permet notamment de manipuler symboliquement la taille et la position de ces lments et de les relier de manire implicite par des quations. En revanche, le langage de \metapost\ s'inspire de celui de \metafont~\cite{metafont} et prsente, l'exception de la syntaxe, les dfauts soulevs ci-dessus. La figure~\ref{fig:metapost} donne un exemple de programme/figure ralis avec \metapost. \begin{figure}[t] \vspace*{1em} \begin{minipage}{.3\linewidth} \includegraphics{figmp.mps} \end{minipage} \begin{minipage}{.7\linewidth} \small \begin{alltt} vardef koch(expr A,B,n) = save C; pair C; C = A rotatedaround(1/3[A,B], 120); if n>0: koch( A, 1/3[A,B], n-1); koch( 1/3[A,B], C, n-1); koch( C, 2/3[A,B], n-1); koch( 2/3[A,B], B, n-1); else: draw A--1/3[A,B]--C--2/3[A,B]--B; fi; enddef; z0=(4cm,0); z1=z0 rotated 120; z2=z1 rotated 120; koch( z0, z1, 4 ); koch( z1, z2, 4 ); koch( z2, z0, 4 ); \end{alltt} \end{minipage} \caption{Exemple de figure \metapost}\label{fig:metapost} \end{figure} % Dans un souci d'exhaustivit, nous devons aussi mentionner % \asymptote~\cite{asymptote}, galement un langage ddi la cration % de figures. Nous n'allons pas rentrer dans les dtails de cet outil % car nous ne considrons plus les langages ddis par la suite. Une alternative sduisante aux solutions prcdentes consiste utiliser un langage de programmation existant. Ainsi l'utilisateur n'a pas apprendre un langage spcialis et il bnficie d'autre part de tous les avantages d'un langage de programmation moderne : erreurs dtectes la compilation, types de donnes complexes, structuration, etc. Toute la difficult rside alors dans la manipulation des lments \LaTeX, notamment la prise en compte de leur taille dans l'laboration de la figure. Si on considre la famille des langages fonctionnels, on peut citer au moins deux exemples de telle intgration : \begin{itemize} \item \mlpictex~\cite{mlpictex} est\footnote{ notre connaissance, \mlpictex\ n'est plus distribu.} un ensemble de macros \LaTeX\ permettant d'inclure du code \camllight\ arbitraire dans un document \LaTeX. Ce code s'appuie sur une bibliothque de dessin \postscript~\cite{postscript} et peut faire rfrence des lments \LaTeX, ainsi qu' leur taille. \item \fmpost~\cite{fmpost} est une bibliothque Haskell~\cite{haskell} produisant du code \metapost. C'est une approche lgre qui rutilise les capacits graphiques de \metapost\ et substitue Haskell au langage de programmation de \metapost. \end{itemize} Cet article prsente \mlpost, un outil qui adopte l'approche de \fmpost\ en utilisant \ocaml~\cite{ocaml} comme langage hte. La premire partie de l'article prsente les choix de conception de \mlpost\ travers un certain nombre d'exemples. La seconde partie dtaille ensuite l'architecture logicielle de \mlpost. \mlpost\ est librement distribu l'adresse \url{http://mlpost.lri.fr}. Toutes les figures de cet article ont t faites avec \mlpost, l'exception des exemples pour \metapost\ et \nomdetikz. %%% CONS % pas de baseline % pas de mlange entre LaTeX et les graphiques \section{Principes et exemples}\label{exemples} \subsection{Principes} \paragraph{Botes.} Les briques de base de \mlpost\ sont les \textit{botes} : une bote est un moyen d'encapsuler n'importe quel lment de dessin au sein d'un contour, qui peut tre effectivement trac ou non. On peut construire la bote vide, des botes avec du \LaTeX\ arbitraire, etc. Ces botes peuvent ensuite tre manipules : imbrication arbitraire, placement une position prcise, alignement de plusieurs botes, flches reliant plusieurs botes entre elles, cration de tableaux, etc. Plusieurs botes peuvent aussi tre regroupes au sein d'une seule afin de pouvoir les dplacer ensemble. L'exemple suivant montre deux botes simples, la deuxime tant dplace un centimtre vers la droite en utilisant la fonction \verb|shift|. \medskip \begin{minipage}{0.2\linewidth} \includegraphics{simple.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} [ Box.draw (Box.tex "\\LaTeX"); Box.draw (Box.shift (Point.pt (cm 1., zero)) (circle (empty ()))) ] \end{ocaml} \end{minipage} \medskip\noindent Une figure \mlpost\ est simplement une liste de commandes de dessin. Ci-dessus, elle est rduite deux occurrences de \texttt{Box.draw}, la commande qui dessine une bote. % Notez que par dfaut, le contour de la bote contenant du \LaTeX n'a % pas t trac, alors que celui de la bote vide a t trac. \paragraph{Placement relatif.} Un principe que nous avons suivi lors de la conception de \mlpost{} est de favoriser un placement relatif des objets plutt qu'absolu. Ceci permet d'obtenir des figures plus robustes. En effet, imaginons que l'on veuille placer une bote $A$ \emph{droite} d'une bote $B$. Une premire possibilit serait de spcifier les positions approximativement, par exemple en donnant les abscisses 0 cm pour $A$ et 2 cm pour $B$. Cependant, si on change d'avis sur le contenu de $A$ et que la taille de cette bote change, $A$ risque alors de se superposer $B$. Il faut alors replacer toutes les botes de la figure manuellement. Pour viter a, \mlpost\ propose diverses mthodes pour placer les botes \emph{les unes par rapport aux autres}. On gagne alors du temps lors de la cration et lors des modifications de la figure. L'exemple suivant utilise l'alignement horizontal \verb|hbox|, o l'argument optionnel \texttt{padding} permet de spcifier l'espacement horizontal entre deux botes : \medskip \begin{minipage}{0.2\linewidth} \includegraphics{align.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} [ Box.draw (Box.hbox ~padding:(cm 1.) [Box.tex "\\LaTeX"; circle (empty ())]) ] \end{ocaml} \end{minipage} \medskip\noindent Nous revenons plus en dtail sur les botes et leur implmentation dans la section~\ref{subsec:boxes}. \paragraph{Persistance.} Un autre choix que nous avons fait est celui de la persistance~\cite{persistance} : lorsqu'un attribut d'une bote (positionnement, couleur, etc.) est modifi, on obtient une nouvelle bote, identique la premire sauf en l'attribut chang. En faisant le choix de structures de donnes persistantes, nous permettons l'ancienne bote, avec ses attributs inchangs, d'tre prserve et encore accessible. Ainsi, on peut rutiliser plus facilement une bote plusieurs endroits du dessin, avec des attributs diffrents. Dans l'exemple suivant, on a utilis trois instances de la mme bote \texttt{b}, dont le contour est trac pour la deuxime. \medskip \begin{minipage}{0.2\linewidth} \includegraphics{persistance.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} let b = Box.hbox ~padding:(cm 1.) [Box.tex "\\LaTeX"; circle (empty ())] in [ Box.draw (Box.vbox [b; set_stroke Color.black b; b]) ] \end{ocaml} \end{minipage} %TODO exemple ici qui introduit les noms des boites et les avantages / %inconvnients de la persistance \subsection{Exemples} Dans cette section, nous montrons quelques applications immdiates des botes de \mlpost. % blocs mmoire (listes, etc.) -- JCF % introduire Box.vblock % introduire les noms de boites \paragraph{Reprsentation de la mmoire.} Un besoin rcurrent lorsque l'on enseigne l'algorithmique ou les concepts lis un langage de programmation consiste illustrer la structure des donnes en mmoire par des schmas de la forme \begin{center} \includegraphics{list123.mps} \end{center} Deux lments sont ncessaires : le dessin des blocs d'une part et le dessin des pointeurs d'autre part. Pour raliser les blocs, on utilise la fonction \texttt{Box.hblock} qui aligne des botes horizontalement, leur donne une hauteur commune et trace leur contour. Voici un exemple : \medskip \begin{minipage}{0.15\linewidth} \includegraphics{simple_block.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} let b = Box.hblock ~pos:`Bot [Box.tex "a"; Box.tex "b"; Box.tex "C"] in [ Box.draw b ] \end{ocaml} \end{minipage} \medskip\noindent l'aide de \texttt{Box.hblock}, on peut facilement crire une fonction \texttt{cons} qui construit un bloc de taille 2, dont le premier lment contient un texte \LaTeX\ arbitraire \texttt{hd} et le second est soit vide, soit le symbole $\bot$, selon la valeur du boolen \texttt{tl} : \begin{ocaml} let cons hd tl = let p1 = Box.tex ~name:"hd" hd in let p2 = Box.tex ~name:"tl" (if tl then "" else "\\ensuremath{\\bot}") in Box.hblock [p1; p2] \end{ocaml} L'argument optionnel \texttt{\~{}name} permet de nommer les sous-botes, de manire pouvoir y accder facilement par la suite. crivons maintenant une fonction \texttt{pointer\_arrow} pour matrialiser les pointeurs. Il s'agit de tracer une flche entre deux botes donnes \texttt{a} et \texttt{b}. Pour cela, on commence par construire un chemin \texttt{p} reliant les centres de \texttt{a} et \texttt{b}, que l'on tronque l'endroit o il intersecte le bord de la bote \texttt{b} (avec la fonction \texttt{Path.cut\_after}). Puis on trace l'origine de la flche l'aide d'un chemin rduit un point (le centre de \texttt{a}) et la flche proprement dite l'aide du chemin \texttt{p}. \medskip \begin{minipage}{0.2\linewidth} \includegraphics{block_arrow.mps} \end{minipage} \begin{minipage}{0.8\linewidth} \small\begin{ocaml} let pointer_arrow a b = let p = pathp [Box.ctr a; Box.ctr b] in let p = Path.cut_after (Box.bpath b) p in let pen = Pen.scale (bp 4.) Pen.circle in Command.draw ~pen (pathp [Box.ctr a]) ++ draw_arrow p \end{ocaml} \end{minipage} %XXX virer ++ ? \medskip\noindent On utilise ici le symbole infixe \texttt{++} qui permet de concatner des commandes de dessin. On utilise d'autre part \texttt{bp}, qui est une unit propre \metapost, proche du point \postscript. Nous avons maintenant tous les lments ncessaires pour crire une fonction \texttt{draw\_list} qui prend en argument une liste \ocaml\ de fragments \LaTeX\ et ralise l'illustration correspondante. On commence par construire les diffrents blocs constituant la liste : \begin{ocaml} let draw_list l = let rec make = function | [] -> [] | [x] -> [cons x false] | x :: l -> cons x true :: make l in \end{ocaml} Puis on aligne ces blocs avec \texttt{Box.hbox}, en insrant de l'espace horizontal avec l'option \texttt{padding} : \begin{ocaml} let l = hbox ~padding:(bp 30.) (make l) in \end{ocaml} Pour dessiner les pointeurs, il suffit de parcourir la liste des botes (qui ont t places) et d'utiliser la fonction \texttt{pointer\_arrow} prcdente sur chaque paire de botes conscutives : \begin{ocaml} let rec arrows = function | [] | [_] -> nop | b1 :: (b2 :: _ as l) -> pointer_arrow (Box.get "tl" b1) (Box.get "hd" b2) ++ arrows l in \end{ocaml} On utilise ici la fonction \texttt{Box.get} qui permet de rcuprer une sous-bote par son nom. On accde ainsi aux botes nommes respectivement \verb!"hd"! et \verb!"tl"! qui ont t cres par la fonction \texttt{cons} puis encapsules dans d'autres botes par les fonctions d'alignement. Enfin, on dessine les botes avec \texttt{Box.draw}, puis les flches avec la fonction \texttt{arrows} : \begin{ocaml} [ Box.draw l; arrows (Array.to_list (Box.elts l)) ] \end{ocaml} On peut tester avec \begin{ocaml} draw_list (List.map (fun n -> Printf.sprintf "$\\sqrt{%d}$" n) [1;2;3;4]) \end{ocaml} qui donne bien le rsultat attendu : \begin{center} \includegraphics{another_list.mps} \end{center} % De manire gnrale, les % fonctions \texttt{Box.tex} et \texttt{Box.box}, ainsi que toutes les % autres fonctions de cration de botes, disposent d'arguments % optionnels \texttt{dx} et \texttt{dy} permettant de spcifier les % marges sparant le contenu du contour de la bote. \paragraph{Diagrammes de classes.} Avec la fonction \texttt{Box.vblock}, analogue pour l'alignement vertical de la fonction \texttt{Box.hblock} introduite ci-dessus, il est facile de dessiner des diagrammes UML. Supposons que l'on veuille dessiner des schmas de classes tels que : \begin{center} \includegraphics{uml_client.mps} \end{center} Pour cela, introduisons une fonction \texttt{classblock} qui attend le nom de la classe ainsi que la liste des attributs et des mthodes. \begin{ocaml} let classblock name attr_list method_list = let vbox = Box.vbox ~pos:`Left in Box.vblock ~pos:`Left ~name [ tex ("{\\bf " ^ name ^ "}"); vbox (List.map tex attr_list); vbox (List.map tex method_list) ] \end{ocaml} Ici, le nom \texttt{name} de la classe est utilis la fois pour dsigner le schma dans le diagramme (l'argument labelis \url{~name} de \texttt{Box.vblock}) et comme titre du schma cr. Les attributs et les mthodes sont aligns verticalement indpendamment, puis on aligne le titre et les deux nouvelles botes obtenues en les encadrant\footnote{Notez qu'au contraire de {\tt hbox} et {\tt vbox}, les fonctions {\tt hblock} et {\tt vblock} tracent par dfaut le contour de leurs sous-botes.}. On peut maintenant s'en servir pour dessiner un petit diagramme de classes : \medskip \begin{minipage}{0.35\linewidth} \includegraphics{uml.mps} \end{minipage} \begin{minipage}{0.6\linewidth} \small\begin{ocaml} let a = classblock "BankAccount" [ "balance : Dollars = $0$"] [ "deposit (amount : Dollars)"; "withdraw (amount : Dollars)" ] in let b = classblock "Client" [ "name : String"; "address : String" ] [] in let diag = Box.vbox ~padding:(cm 1.) [a;b] in [ Box.draw diag; box_label_arrow ~pos:`Left (Picture.tex "owns") (get "Client" diag) (get "BankAccount" diag) ] \end{ocaml} \end{minipage} \vspace{1em} Ici, on a d'abord cr deux schmas de classe avec la fonction \texttt{classblock}. Ces schmas sont ensuite aligns verticalement, et une flche avec une tiquette est dessine entre ces deux classes avec \texttt{box\_label\_arrow}. Le code pour cette figure est conceptuellement trs simple, ne contient aucun placement absolu et ne dpasse pas les 15 lignes de code. % automate -- RB \paragraph{Automates.}\label{sec:automates} La thorie des langages est un domaine o l'on a rapidement besoin de dessiner des automates. Illustrons une faon d'utiliser \mlpost\ dans ce but. Nous allons dfinir les fonctions suivantes : \begin{itemize} \item \texttt{state} pour crer un tat ; \item \texttt{final} pour transformer un tat en un tat final ; \item \texttt{initial} pour dessiner une flche entrante sur un tat initial ; \item \texttt{transition} pour dessiner une transition d'un tat un autre ; \item \texttt{loop} pour dessiner une transition d'un tat vers lui-mme. \end{itemize} On choisit de reprsenter les tats par des botes \mlpost. La fonction \texttt{state} est juste une sp\-ci\-ali\-sa\-tion de la fonction {\tt Box.tex} un contour circulaire, dfinie par l'application partielle suivante: \begin{ocaml} let state = Box.tex ~style:Circle ~stroke:(Some Color.black) \end{ocaml} Le paramtre \texttt{stroke} permet de spcifier si le contour doit tre trac et, le cas chant, dans quelle couleur. De manire similaire, la fonction \texttt{final} est une spcialisation de la fonction {\tt Box.box} dont le rle consiste rajouter un cercle autour d'une bote : \begin{ocaml} let final = Box.box ~style:Circle \end{ocaml} On peut dj placer des tats, finaux ou non, et les dessiner. Pour le placement, on utilise les fonctions d'alignement horizontal et vertical \texttt{Box.hbox} et \texttt{Box.vbox}. On suit donc le principe consistant placer les objets de faon relative, les uns par rapport aux autres. \begin{minipage}{0.2\linewidth} \includegraphics{automate_1.mps} \end{minipage} \begin{minipage}{0.7\linewidth} \begin{ocaml} let states = Box.vbox ~padding:(cm 0.8) [ Box.hbox ~padding:(cm 1.4) [ state ~name:"alpha" "$\\alpha$"; state ~name:"beta" "$\\beta$" ]; final ~name:"gamma" (state "$\\gamma$") ] in [ Box.draw states ] \end{ocaml} \end{minipage} \medskip\noindent On note que l'ensemble des tats est lui-mme une bote, \texttt{states}, contenant les tats comme autant de sous-botes nommes. La fonction \texttt{initial} appose une flche entrante un tat. Il s'agit donc d'une fonction qui prend le nom d'un tat \texttt{q} et qui renvoie une commande dessinant une flche vers \texttt{q}. On pourrait aussi renvoyer une bote sans contour contenant \texttt{q} et la flche, ce qui permettrait d'utiliser \texttt{initial} de la mme faon que \texttt{final}. Cependant, la bote obtenue n'aurait pas la mme taille et la mme forme que \texttt{q}, ce qui poserait des problmes pour placer \texttt{q} ou pour dessiner des transitions vers ou partir de \texttt{q}. \begin{ocaml} let initial (states : Box.t) (name : string) : Command.t = let q = Box.get name states in let p = Box.west q in Arrow.draw (Path.pathp [Point.shift p (Point.pt (cm (-0.3), zero)); p]) \end{ocaml} La fonction accde la bote \texttt{q} par son nom \texttt{name} dans la bote \texttt{states} et dtermine le point d'arrive de la flche avec \texttt{Box.west}. On pourrait gnraliser cette fonction pour spcifier la position de la flche. La fonction \texttt{transition} dessine une flche d'un tat un autre. Cette fonction prend deux arguments optionnels \texttt{outd} et \texttt{ind} pour spcifier, en degrs, la direction sortante et la direction entrante de la flche. On doit les convertir en vecteurs directeurs pour les passer\footnote{Nous utilisons ici une fonctionnalit d'\ocaml{} qui permet d'accder des arguments optionnels sans spcifier leur valeur par dfaut, sous la forme d'un type {\tt option}. Nous passons ensuite directement ces valeurs de type {\tt option}, en tant qu'arguments optionnels, la fonction {\tt cpath} par la syntaxe {\tt cpath ?outd ?ind x y}.} \texttt{cpath}, qui calcule un chemin allant du bord d'une bote au bord d'une autre bote. Ce chemin est ensuite donn la fonction \texttt{Arrow.draw} qui trace la flche en plaant une tiquette \texttt{tex} la position \texttt{pos}. \begin{ocaml} let transition states tex pos ?outd ?ind x_name y_name = let x = Box.get x_name states and y = Box.get y_name states in let outd = match outd with None -> None | Some a -> Some (vec (dir a)) in let ind = match ind with None -> None | Some a -> Some (vec (dir a)) in Arrow.draw ~tex ~pos (cpath ?outd ?ind x y) \end{ocaml} La fonction \texttt{loop} est similaire la fonction \texttt{transition}, mais elle doit calculer un chemin plus complexe. En effet, \texttt{cpath} appliqu deux botes identiques renvoie un chemin vide et on ne peut donc pas l'utiliser. la place, on calcule un point $A$ suffisamment loign de la bote et on trace un chemin qui part du centre, qui passe par $A$ puis qui revient au centre. On utilise au passage la fonction \texttt{knotp} qui permet de spcifier un point avec une tangente, et \texttt{pathk} qui transforme une liste de tels points en un chemin. \begin{minipage}{0.2\linewidth} \includegraphics{loop_explain.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \small\begin{ocaml} let loop states tex name = let box = Box.get name states in let a = Point.shift (Box.south box) (Point.pt (cm 0., cm (-0.4))) in let c = Box.ctr box in let p = Path.pathk [ knotp ~r:(vec (dir 225.)) c; knotp a; knotp ~l:(vec (dir 135.)) c; ] in let bp = Box.bpath box in Arrow.draw ~tex ~pos:`Bot (cut_after bp (cut_before bp p)) \end{ocaml} \end{minipage} Ici encore, on pourrait gnraliser cette fonction pour spcifier la position de la flche. On peut maintenant dessiner facilement des automates en utilisant cette bibliothque. \medskip \begin{minipage}{0.2\linewidth} \includegraphics{automate.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \small\begin{ocaml} let automate = let states = ... in [ Box.draw states; transition states "a" `Lowleft "alpha" "gamma"; transition states "b" `Lowright "gamma" "beta"; transition states "c" `Top ~outd:25. ~ind:335. "alpha" "beta"; transition states "d" `Bot ~outd:205. ~ind:155. "beta" "alpha"; loop states "e" "gamma"; initial states "alpha" ] \end{ocaml} \end{minipage} \subsection{Exemples utilisant des calculs en \ocaml} Cette section illustre l'un des avantages de \mlpost: la capacit de dessiner directement un objet que l'on a calcul/programm en \ocaml. % plot -- SL \paragraph{Graphe de fonction.} Un exemple simple de dessin rsultant d'un calcul est celui du graphe d'une fonction. \mlpost\ fournit un module \texttt{Plot} cet effet. La figure suivante montre un exemple basique d'utilisation de cette extension : \medskip \begin{minipage}{0.35\linewidth} \includegraphics{graph_sqrt.mps} \end{minipage} \begin{minipage}{0.65\linewidth} \small\begin{ocaml} let u = cm 1. in let sk = Plot.mk_skeleton 4 3 u u in let label = Picture.tex "$y=\\sqrt{x+\\frac{1}{2}}$", `Upleft, 3 in let f x = sqrt (float x +. 0.5) in let graph = Plot.draw_func ~label f sk in [ graph; Plot.draw_simple_axes "$x$" "$y$" sk ] \end{ocaml} \end{minipage} \medskip\noindent La fonction \texttt{mk\_skeleton} permet de construire un cannevas de 4 units sur 3, qui est l'objet de base de l'extension \texttt{Plot}. Il est alors possible de dessiner un graphe de fonction et des axes au sein de ce cannevas, comme illustr ci-dessus. L'extension dispose de beaucoup d'options (trac de la grille, affichage des abscisses et ordonnes, diffrents types de graphes de fonctions) qui permettent de raliser des figures plus complexes, telle que celle dcrite dans le paragraphe suivant. \paragraph{Abstractions d'horloges dans un systme synchrone flot-de-donnes.} L'exemple ci-dessous, ralis par Florence Plateau, provient d'un problme rel~\cite{MandelPlateau08} et illustre un certain nombre des possibilits de l'extension \texttt{Plot}. % % Ainsi les fonctions illustres sur cette figure ont t codes comme des fonctions \ocaml{} standard. De plus, la ligne intermdiaire dans la partie situe sous le graphe principal, et dnote par $w_2$, reprsente les discontinuits de la fonction $f_{w_2}$ du graphe principal. Cette ligne est calcule \textit{directement} partir de la fonction $f_{w_2}$ ; si l'on dcide de changer la fonction $f_{w_2}$, la ligne $w_2$ sera mise jour automatiquement. Cela est galement vrai pour certaines tiquettes de la figure, comme l'abscisse $[w_2]_5$. Ceci offre une flexiblit trs intressante lors de la phase de dveloppement d'une telle figure. \begin{figure}[h] \centering \begin{center} \medskip \includegraphics{florence.mps} \end{center} %\caption{expliquer de quoi a parle} \label{fig:florence} \end{figure} \paragraph{Bresenham.} titre de dernier exemple, supposons que l'on veuille illustrer l'algorithme de trac de segment de Bresenham~\cite{bresenham}, par exemple sur le segment reliant le point $(x_1,y_1)=(0,0)$ au point $(x_2,y_2)=(9,6)$. Pour cela, on commence par stocker le rsultat de l'algorithme dans un tableau \texttt{bresenham\_data}, tel que $\texttt{bresenham\_data.(}x\texttt{)}$ donne l'ordonne du point d'abscisse $x$. \begin{ocaml} let x2 = 9 and y2 = 6 let bresenham_data = Array.create (x2+1) 0 let () = (* remplissage du tableau a avec l'algorithme de Bresenham *) ... \end{ocaml} On peut alors raliser la figure trs facilement, l'aide de la fonction \texttt{Box.gridi} fournie par \mlpost, qui construit une matrice de botes alignes partir d'une largeur, d'une hauteur et d'une fonction construisant la bote $(i,j)$, d'une manire analogue \texttt{Array.create\_matrix}. \medskip \begin{minipage}{0.3\linewidth} \includegraphics{bresenham0.mps} \end{minipage} \begin{minipage}{0.7\linewidth} \vspace*{0.8em} \begin{ocaml} let width = bp 6. and height = bp 6. in let g = Box.gridi (x2+1) (y2+1) (fun i j -> let fill = if bresenham_data.(i) = y2 - j then Some Color.red else None in Box.rect ?fill (Box.empty ~width ~height ())) in [ Box.draw g ] \end{ocaml} \end{minipage} \medskip\noindent Les botes sont des botes vides de 6 points de ct, cres avec \texttt{Box.empty}. Pour les botes correspondant des points dessins par l'algorithme de Bresenham, on indique que la bote doit tre remplie en rouge, l'aide de l'argument optionnel \texttt{fill}. Pour parachever la figure, on va ajouter des tiquettes indiquant les coordonnes des deux extrmits du segment. Pour placer une tiquette ct de la case $(i,j)$, on rcupre la bote correspondante l'aide de \texttt{Box.nth}, puis on rcupre un point particulier de cette bote (par exemple le point au milieu en bas avec \texttt{Box.south}), puis enfin on trace l'tiquette avec \texttt{Command.label}. \medskip \begin{minipage}{0.22\linewidth} \vspace*{0.8em} \hspace*{-1.4em}\includegraphics{bresenham.mps} \end{minipage} \begin{minipage}{0.7\linewidth}\small \begin{ocaml} let bresenham = let width = bp 6. and height = bp 6. in let g = ... in let get i j = Box.nth i (Box.nth (y2-j) g) in let label pos s point i j = Command.label ~pos (Picture.tex s) (point (get i j)) in [ Box.draw g; label `Bot "0" Box.south 0 0; label `Bot "$x_2$" Box.south x2 0; label `Left "0" Box.west 0 0; label `Left "$y_2$" Box.west 0 y2 ] \end{ocaml} \end{minipage} \section{Architecture logicielle}\label{archi} La figure~\ref{fig:etapes} montre le fonctionnement de \mlpost. Tout d'abord, \mlpost\ est un outil de gnration de fichier \metapost\ sous forme de bibliothque \ocaml. l'aide de cette bibliothque, l'utilisateur crit un programme qui, l'excution, construit un arbre de syntaxe abstraite \metapost. Cet arbre est imprim dans un fichier \verb|figure.mp| qui est lu par \metapost\ pour gnrer un ou plusieurs fichiers \postscript\footnote{Ces fichiers n'ont pas le suffixe \texttt{.ps} car il leur manque l'en-tte.}. L'inclusion de ces figures dans un document \LaTeX{} se fait simplement en utilisant la commande \verb|\includegraphics| du package \textsf{graphicx}. Pour compiler le document \LaTeX{} avec {\tt pdflatex}, il suffit de changer l'extension des figures gnres, ce qu'une option de l'outil \mlpost{} permet de faire facilement. \begin{figure}[h] \begin{center} \includegraphics{stages.mps} \end{center} \caption{Architecture de \mlpost}\label{fig:etapes} \end{figure} Il est important de noter que le fichier \metapost\ de sortie n'est pas obtenu par {\em compilation} du code source \ocaml, mais par une \emph{excution} du programme qui construit un arbre de syntaxe abstraite \metapost. Cette mthode a l'inconvnient qu'une boucle ou itration dans le programme de dpart sera traduite par une suite de commandes obtenues par le droulement de la boucle, et non par une construction de boucle du langage cible. Ceci tant dit, dans notre cas, le cot supplmentaire est faible, puisque \metapost\ droule galement les boucles dans les fichiers \postscript\ de sortie. % schma de l'architecture \begin{figure}[ht] \begin{center} ~\\[0.5em] \includegraphics{architecture.mps} \end{center} \vspace*{-1em} \caption{Architecture de \mlpost}\label{fig:archi} \end{figure} L'architecture gnrale de \mlpost{} est schmatise en figure~\ref{fig:archi}. Au niveau le plus bas se trouvent les interfaces correspondant aux types primitifs de \metapost. Ce sont ces objets qui sont {\it in fine} traduits en du code \metapost, et nous les dcrivons de manire plus dtaille dans la section~\ref{subsec:types}. La couche intermdiaire contient des lments que nous estimons tre de bas niveau mais qui ne sont pas prsents dans \metapost : ils sont propres \mlpost\ et ont t construits partir de la couche infrieure. Les sections~\ref{subsec:boxes} et \ref{subsec:arrows} reviennent plus en dtail sur deux de ces modules, respectivement \texttt{Box} et \texttt{Arrow}. Enfin, on trouve au plus haut niveau des modules tels que le module \texttt{Plot} prsent dans la section prcdente. L'intgralit des modules de \mlpost\ est empaquete dans un module \texttt{Mlpost}, afin de ne pas polluer l'espace de noms d'\ocaml. \subsection{Types primitifs de \metapost}\label{subsec:types} La couche de bas niveau de \mlpost\ est une interface fidle \metapost. Elle comporte tous les types de base de \metapost~: \begin{description} \item[Le type numrique (module \texttt{Num})] reprsente des longueurs. En premire approximation, ce type pourrait tre assimil au type \texttt{float} d'\ocaml, mais certaines valeurs, telle que la taille d'un lment \LaTeX, ne sont connues qu' l'interprtation du fichier \metapost. La plupart des calculs sont donc effectus de manire symbolique et le type \texttt{Num.t} doit donc tre abstrait. \item[Le type point (module \texttt{Point})] reprsente des points dans l'espace deux dimensions. Pour les mmes raisons que les numriques, les points ne sont pas simplement des paires de flottants, mais doivent tre reprsents de manire symbolique. Le type \texttt{Point.t} est galement utilis pour reprsenter les vecteurs. \item[Les chemins (module \texttt{Path})] sont des lignes reprsentes par des courbes de Bzier. Ils sont la base de tout dessin \metapost. Toutes les possibilits de construction de chemin dans \metapost\ ont t interfaces. On peut dessiner des lignes droites ou des lignes courbes en prcisant les points de contrle, la tension de la courbe, etc. \item[Les transformations (module \texttt{Transform})] permettent d'appliquer une transformation linaire un objet quelconque. Il est ainsi possible de dplacer des objets, les redimensionner, les faire pivoter ou encore combiner toutes ces transformations. \item[Les plumes (module \texttt{Pen})] permettent de choisir l'paisseur et la forme du stylo utilis pour dessiner les chemins. \item[Les figures (module \texttt{Picture})] permettent de rassembler plusieurs lments graphiques en un seul, qu'il s'agisse d'lments \LaTeX\ ou de commandes de dessin arbitraires. Le type \texttt{Picture.t} permet de traiter une figure arbitrairement complexe comme un objet de base que l'on peut copier, transformer, etc. Le module \texttt{Picture} permet galement de dcouper une figure l'aide d'une surface dcrite par un chemin clos (\textit{clipping}). \end{description} Les autres types \metapost\ (chanes de caractres, boolens, couleurs) sont directement reprsents en \ocaml. L'interface de \mlpost\ contient aussi un module \texttt{Command} qui dfinit le type des commandes \metapost : commandes de dessin, de remplissage, itrations, squences, etc. \paragraph{Dpendances circulaires.} La ralisation de ces modules de bas niveau prsente quelques difficults. Premirement, la plupart des modules prsents sont {\em a priori} mutuellement rcursifs : par exemple, les transformations s'appliquent tous les autres objets, donc chaque module contient une fonction \begin{ocaml} val transform : Transform.t -> t -> t \end{ocaml} o le type \texttt{t} reprsente le type principal du module en question. D'un autre ct, les transformations sont elles-mmes construites l'aide de numriques et de points: \begin{ocaml} val shifted : Point.t -> t \end{ocaml} o \texttt{t} est le type des transformations. Des dpendances circulaires existent aussi entre types et sont aggraves par la reprsentation symbolique des objets (par exemple, les projections \texttt{xpart} et \texttt{ypart} du module \texttt{Point} doivent retourner des numriques et non des flottants). Nous souhaitons raliser ces diffrents modules dans des fichiers diffrents mais \ocaml\ ne permet pas de dpendances circulaires entre des fichiers. Notre solution consiste dfinir tous les \emph{types} dans un seul fichier \texttt{types.mli}. Chaque module fait maintenant rfrence ce fichier. Par exemple, dans le fichier \texttt{path.ml}, qui fournit l'implmentation du module \texttt{Path}, on trouvera \begin{ocaml} type t = Types.path \end{ocaml} La dpendance circulaire entre les modules est ainsi casse de manire trs classique. En revanche, on souhaite cacher l'existence du module \texttt{Types} pour les deux raisons suivantes : \begin{itemize} \item la clart des messages d'erreur ; \item la clart de la documentation gnre par \texttt{ocamldoc}. \end{itemize} On souhaite donc rtablir la circularit entre les modules au sein de l'interface du module \texttt{Mlpost}. Pour cela, on crit un unique fichier \texttt{mlpost.mli} qui contient les dfinitions des signatures des modules exporter : \medskip \begin{minipage}{0.33\textwidth} \begin{ocaml} module rec Num : sig type t ... end and Point : sig type t val xpart : t -> Num.t ... end and Path : sig type t ... end ... \end{ocaml} \end{minipage} \begin{minipage}{0.65\textwidth} \includegraphics{deps.mps} \end{minipage} Toutes ces signatures sont dclares de manire mutuellement rcursive. La signature de \texttt{Point} peut ainsi faire rfrence \texttt{Path} et inversement. On notera que les types tels que \texttt{Point.t} sont maintenant abstraits dans l'interface, rendant invisible l'existence du module \texttt{Types}. Par ailleurs, les implmentations de ces modules sont contenues dans des fichiers indpendants \texttt{num.ml}, \texttt{point.ml}, etc., qui sont compils avec l'option {\tt -for-pack Mlpost}. Cet agencement est en outre trs pratique pour la documentation de l'API : c'est uniquement le fichier \texttt{mlpost.mli} qui sert d'entre l'outil \texttt{ocamldoc}. \paragraph{Hash-consing et traduction vers \metapost.} Le choix d'une reprsentation symbolique de la plupart des objets impose des efforts supplmentaires pour minimiser l'utilisation de la mmoire et la taille des fichiers \metapost\ de sortie. En effet, l'arbre de syntaxe abstraite (AST) contient beaucoup de n\oe uds identiques mais construits de manire diffrente, qui prennent donc inutilement de la place aussi bien en mmoire que dans le fichier \metapost\ gnr. C'est d'autant plus gnant que \metapost\ devra lire ce fichier et passera donc davantage de temps sur des calculs rpts. Pour y remdier, nous utilisons la technique du {\em hash-consing}~\cite{ConchonFilliatre06wml} applique l'arbre de syntaxe abstraite. Cette technique permet de partager des valeurs structurellement gales. Elle utilise une table de hachage globale qui stocke toutes les valeurs dj cres. Avant de crer un nouvel objet, on regarde dans cette table si un objet structurellement gal existe dj. Pour que le calcul de la valeur de hachage soit efficace, chaque (sous-)terme vient avec sa valeur de hachage. Le partage ralis est maximal, ce qui permet de substituer l'galit physique (\texttt{==}) l'galit structurelle (\texttt{=}). Cette technique diminue l'utilisation de la mmoire, mais ne change rien {\em a priori} la taille des fichiers gnrs. La structure hash-conse {\em ralise} le partage, mais elle ne sait pas quels sont les n\oe uds effectivement utiliss au moins deux fois. Pour cela, on ralise un simple parcours en profondeur de la structure, en comptant les occurrences de chaque n\oe ud. Il est nanmoins possible de rencontrer une nouvelle fois un sous-n\oe ud d'une structure, comme le montre l'exemple ci-dessous : \begin{center} \includegraphics[scale=1.5]{sharing.mps} \end{center} \noindent Dans cette configuration, le n\oe ud $f$ est rellement utilis deux fois, alors que le n\oe ud $e$ n'est utilis qu'une seule fois, par le n\oe ud $d$, mme si celui-ci est utilis deux fois son tour. Autrement dit, on comptabilise pour chaque n\oe ud le nombre de flches incidentes. Aprs cette analyse, la gnration du fichier \metapost\ devient trs simple : il suffit de traverser de nouveau l'arbre de syntaxe abstraite et, quand on visite un n\oe ud qui est utilis au moins deux fois, on construit une dfinition \metapost\ pour cet objet. Il faut nanmoins prendre en compte les particularits syntaxiques de \metapost\ telles que la prcdence inhabituelle des oprateurs arithmtiques et la restriction de l'application de certaines constructions des variables. De cette faon, on arrive avoir du code \metapost\ relativement petit\footnote{En l'absence de boucles \texttt{for} et de macros dans le code \metapost, nous avons observ, sans avoir fait de tests trs exhaustifs, une taille du code gnr du mme ordre de grandeur que celle du code \metapost\ crit la main.}, malgr la dlgation des calculs \metapost. \subsection{Botes}\label{subsec:boxes} Comme nous l'avons illustr dj maintes fois, les botes de \mlpost\ peuvent tre rduites de simples objets \LaTeX\ ou bien tre constitues d'un ensemble d'autres botes. Le type des botes est donc un type rcursif de la forme suivante : \begin{ocaml} type t = { name : string option; width : Num.t; height : Num.t; pen : Pen.t option; ... desc : desc; } and desc = | Emp | Pic of Picture.t | Grp of t array * t Smap.t \end{ocaml} Chaque bote est ventuellement nomme (champ \texttt{name}), possde un certain nombre d'attributs (position, taille, couleur, bordure, remplissage, etc.) et sa nature est donne par le champ \texttt{desc}. Ce dernier indique s'il s'agit d'une bote vide, d'une image ou bien d'une bote composite. Dans ce dernier cas, les sous-botes sont contenues dans un tableau, qui est accompagn d'une table (ralise par le module \texttt{Smap}) permettant un accs plus rapide une sous-bote par son nom. Le dessin d'une bote est immdiat. On trace d'une part son contour et d'autre part son contenu. Ce dernier est soit une bote atomique directement dessine l'aide de \texttt{Command.draw\_pic}, soit une bote composite dont le dessin est tout simplement obtenu en dessinant rcursivement chaque sous-bote. Pour raliser les diverses fonctions de placement, on commence par crire une fonction de translation d'une bote par un vecteur donn : \begin{ocaml} Box.shift : Point.t -> Box.t -> Box.t \end{ocaml} Cette fonction est naturellement rcursive sur la structure de la bote. Il est important de noter que cette fonction renvoie une \emph{nouvelle} bote, sans altrer son argument (les botes sont persistantes). Une fois cette fonction donne, il est ais de raliser les fonctions \texttt{Box.hbox}, \texttt{Box.hblock}, etc. \subsection{Flches} \label{subsec:arrows} %% RB \metapost\ ne propose qu'un seul type de flche. Une flche \metapost\ suit un chemin arbitraire mais son trac est limit aux diffrents styles de trait (plume et pointills) et la tte de flche est toujours la mme : \begin{center} \includegraphics{arrow_metapost.mps} \end{center} Avec \mlpost, l'utilisateur peut crer ses propres catgories de flches l'aide du module \texttt{Arrow}. Celui-ci propose deux types : \begin{itemize} \item Le type \texttt{head} dcrit comment dessiner une tte de flche. Les lments de type \texttt{head} sont des fonctions prenant en argument la position et la direction de la tte de flche et renvoyant une commande dessinant la tte de flche. \item Le type abstrait \texttt{kind} dcrit une catgorie de flche. Une catgorie dcrit les diffrents lments dans le dessin d'une flche, les ttes de flche pouvant en ralit tre places n'importe o le long de la flche. Pour construire une nouvelle catgorie, on part de la catgorie vide et on ajoute des traits et des ttes. \end{itemize} La fonction \texttt{draw} permet de dessiner une flche d'une catgorie donne en suivant un chemin donn. Les flches sont alors dessines en utilisant les primitives de \metapost. Ceci a l'inconvnient d'utiliser plus de ressources mais permet d'imaginer de nombreuses catgories de flches. On peut en particulier retrouver les flches de \metapost. On part d'un corps vide et on lui ajoute un trait normal sur toute la longueur. On ajoute enfin une tte triangulaire remplie, et on obtient : \medskip \begin{minipage}{0.2\linewidth} \includegraphics{arrow_simple.mps} \end{minipage} \begin{minipage}{0.2\linewidth} \begin{ocaml} let kind = Arrow.add_head ~head:Arrow.head_triangle_full (Arrow.add_line Arrow.empty) in [ Arrow.draw ~kind (...path...) ] \end{ocaml} \end{minipage} \medskip La section~\ref{sec:automates} contient une figure dcrivant le fonctionnement de la fonction \texttt{loop}. Pour les besoins de cette figure, on a cr un type de flche spcial, compos d'un dbut et d'une fin en pointills et avec une tte place diffremment : \begin{center} \includegraphics{arrow_loop_explain.mps} \end{center} Le code permettant d'obtenir cette catgorie de flche est le suivant : \begin{ocaml} let kind = Arrow.add_belt ~point:0.9 (Arrow.add_line ~dashed:Dash.evenly ~to_point:0.1 (Arrow.add_line ~dashed:Dash.evenly ~from_point:0.9 (Arrow.add_line ~from_point:0.1 ~to_point:0.9 Arrow.empty))) \end{ocaml} \section{Conclusion}\label{conclusion} Nous avons prsent \mlpost, une bibliothque \ocaml\ au dessus de \metapost. Nous esprons avoir convaincu le lecteur des avantages que la prsentation sous forme de bibliothque apporte : familiarit avec le langage pour les programmeurs \ocaml, typage fort, des constructions de programmation de haut niveau, des dessins rsultants de calculs arbitraires, etc. \mlpost\ fournit volontairement un nombre restreint de primitives, car l'utilisateur peut aisment construire des extensions au dessus de \mlpost. En cela, \mlpost\ diffre de bibliothques \LaTeX\ telles que \nomdetikz\ ou \pstricks, o de trs nombreuses fonctionnalits sont fournies mais o il est trs difficile d'en ajouter pour qui ne matrise pas \TeX. L'une des forces de \mlpost\ est de proposer un style dclaratif, l o la majorit des bibliothques graphiques propose un style impratif. Ceci permet en particulier un \emph{partage} immdiat de sous-lments dans une ou plusieurs figures. Une autre force de \mlpost\ est le typage statique directement hrit d'\ocaml. On vite ainsi l'immense majorit des erreurs l'excution de \metapost, souvent cryptiques. Il reste nanmoins les erreurs ventuellement contenues dans les extraits de \LaTeX\ ou les erreurs de nature gomtrique telles que le remplissage d'un chemin en forme de 8. Nous pourrions envisager d'utiliser des types \ocaml\ plus prcis, par exemple pour distinguer les chemins clos et non clos ou encore les points et les vecteurs. Il reste une fonctionnalit intressante de \metapost\ qui n'est pas interface dans \mlpost~: la rsolution d'quations linaires. Il y a deux raisons cela. D'une part, les quations servent souvent au placement implicite, et \mlpost\ fournit une alternative sous la forme de fonctions d'alignement de botes. D'autre part, la rsolution d'quations de \metapost\ procde de manire imprative et il n'est pas simple de l'intgrer dans le contexte dclaratif qui est le ntre. Ceci tant dit, il serait intressant d'explorer des mthodes de placement plus automatiques que celles que nous proposons, par exemple inspires de la manire dont \TeX{} mets en page lignes, pages et paragraphes. Enfin, il est important de noter que \mlpost\ n'est pas li \metapost\ de manire intrinsque. On pourrait facilement ajouter une sortie \nomdetikz, ou mme directement une sortie \postscript\ condition d'utiliser une technique similaire celle de \metapost\ pour l'inclusion de \LaTeX. \medskip \noindent \begin{center} \includegraphics[width=0.3\textwidth]{ford.mps} \medskip \begin{minipage}{0.7\textwidth} \begin{center} \bf Remerciements \end{center} \centering Les auteurs tiennent remercier Florence Plateau, Yannick Moy et Claude March pour leur contribution \mlpost, Sylvie Boldo pour la suggestion du titre de l'article et les relecteurs pour leurs remarques. \end{minipage} \medskip \includegraphics[angle=180,width=0.3\textwidth]{ford.mps} \end{center} % La bibliographie % N'oubliez pas de l'inclure lors de votre soumission. \bibliographystyle{plain} \bibliography{./biblio} \vfill \pagebreak \thispagestyle{colloquetitle} \cleardoublepage \end{document} % Local Variables: % coding: iso-latin-1 % ispell-local-dictionary: "francais" % End: mlpost-0.8.2/papers/jfla2009/pp.mll000066400000000000000000000107041306046515300167120ustar00rootroot00000000000000 (* prprocesseur pour les environnement ocaml (avec alltt) *) { open Lexing let slides = ref false let ocaml_keywords = let h = Hashtbl.create 97 in List.iter (fun s -> Hashtbl.add h s ()) [ "fun"; "match"; "with"; "begin"; "end"; "try"; "as"; "let"; "rec"; "in"; "function"; "if"; "then"; "else"; "sig"; "val"; "type"; "module"; "while"; "do"; "done"; ]; h let is_keyword s = Hashtbl.mem ocaml_keywords s } let space = [' ' '\t'] let ident = ['a'-'z' 'A'-'Z' '_'] ['a'-'z' 'A'-'Z' '_' '0'-'9']* rule alltt = parse | '{' { print_string "\\{"; alltt lexbuf } | '}' { print_string "\\}"; alltt lexbuf } | '\\' { print_string "\\ensuremath{\\backslash}"; alltt lexbuf } | '#' { print_string "\\diese{}"; alltt lexbuf } | '_' { print_string "\\_{}"; alltt lexbuf } | '%' { print_string "\\%{}"; alltt lexbuf } | '&' { print_string "\\&{}"; alltt lexbuf } | '%' { print_string "\\%{}"; alltt lexbuf } | '\n' { print_string "\n"; alltt lexbuf } | "->" { print_string "\\ensuremath{\\rightarrow}"; alltt lexbuf } | "<-" { print_string "\\ensuremath{\\leftarrow}"; alltt lexbuf } | "=>" { print_string "\\ensuremath{\\Rightarrow}"; alltt lexbuf } | "<->" { print_string "\\ensuremath{\\leftrightarrow}"; alltt lexbuf } | '\n' "\\end{" ( "ocaml" | "coq" ) "}\n" { print_newline () } | "\\emph{" [^'}']* '}' { print_string (lexeme lexbuf); alltt lexbuf } | "(*" [^'\n']* "*)" as s { print_string "\\emph{"; print_string s; print_string "}"; alltt lexbuf } | eof { () } | "'a" { print_string "\\ensuremath{\\alpha}"; alltt lexbuf } | "*" { print_string "\\ensuremath{\\times}"; alltt lexbuf } | ident as s { if !slides && is_keyword s then begin print_string "{\\color{blue}"; print_string (lexeme lexbuf); print_string "}" end else print_string (lexeme lexbuf); alltt lexbuf } | _ { print_string (lexeme lexbuf); alltt lexbuf } and coq = parse | '{' { print_string "\\{"; coq lexbuf } | '}' { print_string "\\}"; coq lexbuf } | '\\' { print_string "\\ensuremath{\\backslash}"; coq lexbuf } | '#' { print_string "\\diese{}"; coq lexbuf } | '_' { print_string "\\_{}"; coq lexbuf } | '%' { print_string "\\%{}"; coq lexbuf } | '&' { print_string "\\&{}"; coq lexbuf } | '%' { print_string "\\%{}"; coq lexbuf } | '\n' { print_string "\n"; coq lexbuf } | "/\\" { print_string "\\ensuremath{\\land}"; coq lexbuf } | "\\/" { print_string "\\ensuremath{\\lor}"; coq lexbuf } | "->" { print_string "\\ensuremath{\\rightarrow}"; coq lexbuf } | "<=" { print_string "\\ensuremath{\\le}"; coq lexbuf } | "<" { print_string "\\ensuremath{<}"; coq lexbuf } | "=>" { print_string "\\ensuremath{\\Rightarrow}"; coq lexbuf } | "<->" { print_string "\\ensuremath{\\leftrightarrow}"; coq lexbuf } | '\n' "\\end{" ( "ocaml" | "coq" ) "}\n" { print_newline () } | "\\emph{" [^'}']* '}' { print_string (lexeme lexbuf); coq lexbuf } | eof { () } | "'a" { print_string "\\ensuremath{\\alpha}"; coq lexbuf } | "*" { print_string "\\ensuremath{\\times}"; coq lexbuf } | "forall" space* { print_string "\\ensuremath{\\forall}"; coq lexbuf } | "exists" space* { print_string "\\ensuremath{\\exists}"; coq lexbuf } (* une ou deux lettres, avec prime ou chiffre = variable *) | (['a'-'z'] '\''?) as s { print_string "\\ensuremath{"; print_string s; print_string "}"; coq lexbuf } | (['a'-'z'] as s) (['0'-'9'] as n) { print_string "\\varind{"; print_char s; print_string "}{"; print_char n; print_string "}"; coq lexbuf } (** | (['a'-'z']['a'-'z'] '\''?) as s { print_string "\\ensuremath{\\mathit{"; print_string s; print_string "}}"; coq lexbuf } **) | (ident '.' ident | ident) as s { if !slides && is_keyword s then begin print_string "{\\color{blue}"; print_string (lexeme lexbuf); print_string "}" end else print_string (lexeme lexbuf); coq lexbuf } | _ { print_string (lexeme lexbuf); coq lexbuf } and pp = parse | "\\begin{ocaml}\n" { print_endline "\\begin{alltt}"; alltt lexbuf; print_endline "\\end{alltt}"; pp lexbuf } | "\\begin{coq}\n" { print_endline "\\begin{alltt}"; coq lexbuf; print_endline "\\end{alltt}"; pp lexbuf } | eof { () } | _ { print_string (lexeme lexbuf); pp lexbuf } { let f = Sys.argv.(1) let () = slides := (String.length f > 6 && String.sub f 0 7 = "slides-") let cin = open_in f let lb = from_channel cin let _ = pp lb } mlpost-0.8.2/papers/jfla2009/rondscolores.mps000066400000000000000000000135731306046515300210310ustar00rootroot00000000000000%!PS %%BoundingBox: -36 -41 43 41 %%HiResBoundingBox: -35.6829 -40.87064 42.76965 40.87057 %%Creator: MetaPost 0.993 %%CreationDate: 2009.01.23:1515 %%Pages: 1 %%BeginProlog %%EndProlog %%Page: 1 1 %%HiResBoundingBox: -35.6829 -40.87064 42.76965 40.87057 1 0 0 setrgbcolor newpath 42.51965 0 moveto 42.51965 7.51828 39.53258 14.72774 34.21677 20.04356 curveto 28.90094 25.35938 21.69148 28.34645 14.1732 28.34645 curveto 6.65492 28.34645 -0.55453 25.35938 -5.87036 20.04356 curveto -11.18617 14.72774 -14.17325 7.51828 -14.17325 0 curveto -14.17325 -7.51828 -11.18617 -14.72774 -5.87036 -20.04356 curveto -0.55453 -25.35938 6.65492 -28.34645 14.1732 -28.34645 curveto 21.69148 -28.34645 28.90094 -25.35938 34.21677 -20.04356 curveto 39.53258 -14.72774 42.51965 -7.51828 42.51965 0 curveto closepath fill 0 1 0 setrgbcolor newpath -21.25983 36.8232 moveto -27.77087 33.06406 -32.52092 26.87244 -34.46667 19.61089 curveto -36.4124 12.34933 -35.39456 4.6122 -31.63542 -1.89885 curveto -27.87628 -8.40988 -21.68466 -13.15993 -14.42311 -15.10568 curveto -7.16153 -17.0514 0.57558 -16.03357 7.08662 -12.27443 curveto 13.59767 -8.51529 18.34772 -2.32365 20.29347 4.9379 curveto 22.2392 12.19945 21.22134 19.93658 17.4622 26.44762 curveto 13.70306 32.95866 7.51146 37.70871 0.24991 39.65446 curveto -7.01167 41.60019 -14.74878 40.58234 -21.25983 36.8232 curveto closepath fill 0 0 1 setrgbcolor newpath -21.26 -36.82321 moveto -14.74896 -40.58238 -7.01181 -41.60023 0.24977 -39.65456 curveto 7.51134 -37.70882 13.70299 -32.95879 17.46217 -26.44772 curveto 21.22133 -19.93669 22.2392 -12.19955 20.2935 -4.93797 curveto 18.34776 2.32362 13.59772 8.51524 7.08669 12.27443 curveto 0.57564 16.0336 -7.16151 17.05147 -14.4231 15.10576 curveto -21.68466 13.16003 -27.87631 8.40999 -31.63548 1.89894 curveto -35.39465 -4.6121 -36.41254 -12.34923 -34.46683 -19.61081 curveto -32.52107 -26.8724 -27.77104 -33.06403 -21.26 -36.82321 curveto closepath fill 1 1 0 setrgbcolor newpath 16.31918 28.26517 moveto 15.6076 28.31917 14.89182 28.34645 14.1732 28.34645 curveto 6.65492 28.34645 -0.55453 25.35938 -5.87036 20.04356 curveto -11.18617 14.72774 -14.17325 7.51828 -14.17325 0 curveto -14.17325 -5.74643 -12.4282 -11.31245 -9.23209 -15.9904 curveto -9.2321 -15.99045 lineto -3.58278 -16.41939 2.11005 -15.14764 7.08662 -12.27443 curveto 13.59767 -8.51529 18.34772 -2.32365 20.29347 4.9379 curveto 22.2392 12.19945 21.22134 19.93658 17.4622 26.44762 curveto 17.10297 27.06985 16.72151 27.67601 16.31903 28.26517 curveto closepath fill 0 1 1 setrgbcolor newpath -32.638 0.00026 moveto -32.32898 -0.64299 -31.99472 -1.27652 -31.63542 -1.89885 curveto -27.87628 -8.40988 -21.68466 -13.15993 -14.42311 -15.10568 curveto -7.16153 -17.0514 0.57558 -16.03357 7.08662 -12.27443 curveto 12.0632 -9.40121 16.01102 -5.10695 18.46419 -0.00003 curveto 18.46423 -0.00003 lineto 16.01106 5.10692 12.06325 9.40118 7.08669 12.27443 curveto 0.57564 16.0336 -7.16151 17.05147 -14.4231 15.10576 curveto -21.68466 13.16003 -27.87631 8.40999 -31.63548 1.89894 curveto -31.99474 1.2767 -32.32895 0.64326 -32.63792 0.00012 curveto closepath fill 1 0 1 setrgbcolor newpath 16.31895 -28.26527 moveto 16.72145 -27.67612 17.10292 -27.06996 17.46217 -26.44772 curveto 21.22133 -19.93669 22.2392 -12.19955 20.2935 -4.93797 curveto 18.34776 2.32362 13.59772 8.51524 7.08669 12.27443 curveto 2.1101 15.14767 -3.58276 16.41945 -9.23209 15.99051 curveto -9.23209 15.9904 lineto -12.4282 11.31245 -14.17325 5.74643 -14.17325 0 curveto -14.17325 -7.51828 -11.18617 -14.72774 -5.87036 -20.04356 curveto -0.55453 -25.35938 6.65492 -28.34645 14.1732 -28.34645 curveto 14.89182 -28.34645 15.6076 -28.31917 16.31918 -28.26517 curveto 16.32016 -28.26505 16.3184 -28.26613 16.31895 -28.26527 curveto closepath fill 1 1 1 setrgbcolor newpath -9.23209 15.9904 moveto -12.4282 11.31245 -14.17325 5.74643 -14.17325 0 curveto -14.17325 -5.74643 -12.4282 -11.31245 -9.23209 -15.9904 curveto -9.2321 -15.99045 lineto -3.58278 -16.41939 2.11005 -15.14764 7.08662 -12.27443 curveto 12.0632 -9.40121 16.01102 -5.10695 18.46419 -0.00003 curveto 18.46423 -0.00003 lineto 16.01106 5.10692 12.06325 9.40118 7.08669 12.27443 curveto 2.1101 15.14767 -3.58276 16.41945 -9.23209 15.99051 curveto closepath fill 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinejoin 10 setmiterlimit newpath 42.51965 0 moveto 42.51965 7.51828 39.53258 14.72774 34.21677 20.04356 curveto 28.90094 25.35938 21.69148 28.34645 14.1732 28.34645 curveto 6.65492 28.34645 -0.55453 25.35938 -5.87036 20.04356 curveto -11.18617 14.72774 -14.17325 7.51828 -14.17325 0 curveto -14.17325 -7.51828 -11.18617 -14.72774 -5.87036 -20.04356 curveto -0.55453 -25.35938 6.65492 -28.34645 14.1732 -28.34645 curveto 21.69148 -28.34645 28.90094 -25.35938 34.21677 -20.04356 curveto 39.53258 -14.72774 42.51965 -7.51828 42.51965 0 curveto closepath stroke newpath -21.25983 36.8232 moveto -27.77087 33.06406 -32.52092 26.87244 -34.46667 19.61089 curveto -36.4124 12.34933 -35.39456 4.6122 -31.63542 -1.89885 curveto -27.87628 -8.40988 -21.68466 -13.15993 -14.42311 -15.10568 curveto -7.16153 -17.0514 0.57558 -16.03357 7.08662 -12.27443 curveto 13.59767 -8.51529 18.34772 -2.32365 20.29347 4.9379 curveto 22.2392 12.19945 21.22134 19.93658 17.4622 26.44762 curveto 13.70306 32.95866 7.51146 37.70871 0.24991 39.65446 curveto -7.01167 41.60019 -14.74878 40.58234 -21.25983 36.8232 curveto closepath stroke newpath -21.26 -36.82321 moveto -14.74896 -40.58238 -7.01181 -41.60023 0.24977 -39.65456 curveto 7.51134 -37.70882 13.70299 -32.95879 17.46217 -26.44772 curveto 21.22133 -19.93669 22.2392 -12.19955 20.2935 -4.93797 curveto 18.34776 2.32362 13.59772 8.51524 7.08669 12.27443 curveto 0.57564 16.0336 -7.16151 17.05147 -14.4231 15.10576 curveto -21.68466 13.16003 -27.87631 8.40999 -31.63548 1.89894 curveto -35.39465 -4.6121 -36.41254 -12.34923 -34.46683 -19.61081 curveto -32.52107 -26.8724 -27.77104 -33.06403 -21.26 -36.82321 curveto closepath stroke showpage %%EOF mlpost-0.8.2/papers/jfla2009/slides.tex000066400000000000000000000212131306046515300175670ustar00rootroot00000000000000\documentclass[nodefaultblocks]{beamer} \usepackage[latin1]{inputenc} \usepackage[T1]{fontenc} \usepackage[french]{babel} \usepackage{mflogo,beamerthemesplit,alltt} \usepackage{tikz} \beamertemplatenavigationsymbolsempty %\usecolortheme{crane} \usetheme{Madrid} \newcommand{\ocaml}{OCaml} \newcommand{\camllight}{Caml Light} \newcommand{\fmpost}{\textit{functional} \metapost} \newcommand{\mlpost}{\textrm{\textsc{Mlpost}}} \newcommand{\metapost}{\MP} \newcommand{\nomdetikz}{\textsf{TikZ}} \newcommand{\pstricks}{\textsf{PSTricks}} \newcommand{\dia}{\textsf{Dia}} \newcommand{\xfig}{\textsf{Xfig}} \newcommand{\postscript}{PostScript} \newcommand{\mlpictex}{mlP\hspace{-0.2em}\raisebox{-0.2em}{i}\hspace{-0.1em}c\hspace{-0.1em}\TeX} \newcommand{\Item}{\bigskip\item} \newcommand{\bred}[1]{\alert{\textbf{#1}}} \let\emph\bred \title[Faire bonne figure avec \mlpost]{\LARGE Faire bonne figure avec \mlpost} \author[Bardou/Fillitre/Kanig/Lescuyer]{R. Bardou \& J.-C. Fillitre \& J. Kanig \& S. Lescuyer \\[1em] quipe ProVal \\[0.5em] INRIA Saclay -- le-de-France \\ CNRS / LRI Universit Paris-Sud } %\institute[proval]{ProVal} \date{JFLA --- 3 fvrier 2009} \begin{document} \begin{frame} \maketitle \begin{center} \includegraphics[width=0.3\textwidth]{ford.mps} \end{center} \end{frame} \begin{frame}\frametitle{Motivations 1/2} comment raliser de belles figures contenant des lments \LaTeX\ ? \vfill \begin{center} \includegraphics[width=\textwidth]{yannick1.mps} \end{center} \vfill \begin{center} \includegraphics{another_list.mps} \end{center} \end{frame} \begin{frame}\frametitle{Motivations 2/2} comment raliser des figures utilisant des calculs ? \vfill \begin{columns} \column{0.4\textwidth} \begin{center} \includegraphics{bresenham.mps}\\ \medskip l'algorithme de Bresenham \end{center} \column{0.6\textwidth} \begin{center} \includegraphics[width=\textwidth]{figures_flo/chrono2_0_aplas.mps} \end{center} \end{columns} \end{frame} \begin{frame}\frametitle{Solutions existantes} \begin{itemize} \item interfaces graphiques : \dia, \xfig \begin{itemize} \item[$+$] simple utiliser (CQVVECQVO) \item[$-$] intgration d'lments \LaTeX\ difficile \item[$-$] pas d'automatisation possible \end{itemize} \Item bibliothques \LaTeX\ : \pstricks, \nomdetikz/PGF \begin{itemize} \item[$+$] intgration avec \LaTeX\ \begin{tikzpicture}[baseline=(a.base)] \path[use as bounding box] (0,0) node[draw,style=dashed] (a) {optimale}; \draw[->] (a) .. controls +(+2cm,-1cm) and +(+2cm,0cm) .. (a); \end{tikzpicture} \item[$-$] programmation difficile \end{itemize} \Item outils externes : \metapost \begin{itemize} \item[$+$] trs bonne intgration avec \LaTeX \item[$+$] langage spcifique \item[$-$] langage spcifique, avec de nombreux dfauts \end{itemize} \end{itemize} \end{frame} \begin{frame}\frametitle{Notre solution : \mlpost} \begin{block}{} Une bibliothque \ocaml{} base sur \MP \end{block} \begin{itemize} \item programmer sa figure en \ocaml{} \begin{itemize} \smallskip \item possibilit de dvelopper des extensions de haut niveau \smallskip \item se prmunir contre un certain nombre d'erreurs grce au typage \end{itemize} \medskip \item bonne intgration avec \LaTeX{} grce \MP % \item avoir l'occasion de venir aux JFLA ! \end{itemize} \begin{center} \includegraphics{mlposttree.mps} \end{center} un projet similaire utilisant Haskell : \fmpost \end{frame} \begin{frame}\frametitle{Fonctionnement de \mlpost} \begin{center} \includegraphics[width=\textwidth]{stages.mps} \bigskip \begin{minipage}{.35\textwidth} \begin{alltt}\small open Mlpost\\ let figure = draw ... \end{alltt} \end{minipage} \begin{minipage}{.33\textwidth} \begin{alltt}\small beginfig(1)\\ ~~draw ...;\\ ~~...\\ endfig; \end{alltt} \end{minipage} \begin{minipage}{.30\textwidth} \hfill\includegraphics[width=.9\textwidth]{rondscolores.mps} \end{minipage} \end{center} \end{frame} \begin{frame}\frametitle{} \begin{center} \Large\emph{dmo !} \end{center} \end{frame} \begin{frame}\frametitle{Choix de conception} \begin{itemize} \item \emph{persistance} \par \quad permet de rutiliser les lments d'une figure \Item \emph{arguments optionnels} \par \quad vite la pollution de l'espace de noms \par \quad exemple : \texttt{Box.empty} \Item une utilisation de \emph{variants polymorphes} \par \begin{center} \includegraphics{sous_typage.mps} \end{center} \Item \emph{minimalit de l'API} \par \quad effort limit de notre part / API cependant complte \end{itemize} \end{frame} \begin{frame}\frametitle{Architecture} \begin{center} \includegraphics[width=.8\textwidth]{architecture.mps} \end{center} \end{frame} \begin{frame}\frametitle{Problmes techniques} idalement, on souhaite interfacer les 7 types de \metapost\ dans 7 modules \ocaml\ diffrents \bigskip problme : il y a \emph{circularit } \begin{alltt} ~~Transform.shifted: Point.t -> Transform.t \\ ~~Point.transform: Transform.t -> Point.t -> Point.t \\ ~~... \\ ~~Picture.make : Command.t -> Picture.t \\ ~~Command.draw\_pic : Picture.t -> Command.t \\ ~~... \end{alltt} \begin{center} \includegraphics{circularity.mps} \end{center} \end{frame} \begin{frame}\frametitle{Solution} \begin{itemize} \item solution classique : tous les types dans un mme module (\texttt{types.mli}) \item tous les modules regroups dans un module \texttt{Mlpost} avec \texttt{-pack} \item une interface \texttt{mlpost.mli} ralise avec \texttt{module rec} \end{itemize} \vfill \begin{center} \includegraphics{circularity_solution.mps} \end{center} \end{frame} \begin{frame}\frametitle{Traduction vers \metapost} limitations de \metapost\ \begin{itemize} \item profondeur de l'arbre de syntaxe \item longueur des lignes \item nombre d'lments d'un mme type \end{itemize} \bigskip imposent une \emph{compilation} des expressions \metapost \begin{itemize} \item \textit{hash-consing} pour factoriser les sous-expressions communes \item introduction de variables intermdiaires \end{itemize} \begin{center} \includegraphics{tree_compile.mps} \end{center} \end{frame} \begin{frame}\frametitle{Applications d'\mlpost\ 1/5} \mlpost{} est dj utilis \begin{itemize} \item pour des articles et des prsentations (hier ici-mme) \end{itemize} \vfill \begin{center} \includegraphics[width=0.5\textwidth]{figures_flo/chrono2_1.mps} \includegraphics[width=0.4\textwidth]{figures_flo/automate_jfla.mps} \end{center} \end{frame} \begin{frame}\frametitle{Applications d'\mlpost\ 2/5} \begin{itemize} \item pour deux thses (une soutenue, une en cours) \end{itemize} \vfill \begin{center} \includegraphics[width=\textwidth]{yannick1.mps} \end{center} \end{frame} \begin{frame}\frametitle{Applications d'\mlpost\ 3/5} \begin{itemize} \item pour plusieurs posters ProVal \end{itemize} \begin{center} \includegraphics[width=0.9\textwidth]{why_platform.mps} \end{center} \end{frame} \begin{frame}\frametitle{Applications d'\mlpost\ 4/5} \begin{itemize} \item pour deux cours (U Paris Sud, ENS) \end{itemize} \begin{center} \includegraphics[width=0.6\textwidth]{closure1.mps} \end{center} \end{frame} \begin{frame}\frametitle{Applications d'\mlpost\ 5/5} \begin{itemize} \item pour le site web \url{http://alt-ergo.lri.fr} \end{itemize} \begin{center} \includegraphics{alt_ergo.mps} \end{center} \end{frame} \begin{frame}\frametitle{Limitations de cette approche} \begin{itemize} \item limitations hrites de \metapost \begin{itemize} \item exemple : nombre de n\oe uds par chemin limit \end{itemize} \item limitations de l'interprtation par \texttt{latex} \item calculs symboliques \begin{itemize} \item difficult pour crire des branchements, des boucles, etc. \end{itemize} \item rsolution d'quations linaires de \metapost\ non interface \begin{itemize} \item en partie remplac par le placement relatif des botes \end{itemize} \end{itemize} \bigskip \emph{une solution} : reprogrammer l'quivalent de \metapost \begin{itemize} \item interface avec \LaTeX \item calcul des courbes de Bzier \end{itemize} \end{frame} % TODO figure \begin{frame}\frametitle{ votre tour de faire bonne figure} \begin{center} \Large \url{http://mlpost.lri.fr/} \bigskip\bigskip utilisez-le ! \bigskip contribuez ! \end{center} \end{frame} \end{document} %%% Local Variables: %%% mode: latex %%% ispell-local-dictionary: "francais" %%% TeX-master: t %%% End: mlpost-0.8.2/papers/jfla2009/studia-Hermann.cls000066400000000000000000001706451306046515300211620ustar00rootroot00000000000000% LaTeX documentclass for studia publisher : %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx %% %% %% %% %% Fichier d'essais pour réglages .cls %% %% %% %% Cette version 2 de studia-Hermann est configurée pour les bibliographies "à la main" %% %% %% %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx % \def\PackageName{studia-Hermann} \def\PackageVersion{1.2} \def\firstversion{03/12/2007} \def\filedate{03/12/2007} \def\docdate{03/12/2007} % %%% Prélude %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %=== Identification Part % \NeedsTeXFormat{LaTeX2e} \def\fileversion{\PackageVersion} \ProvidesClass{\PackageName}[ \filedate \space Version:\space \PackageVersion \space ] \typeout{style Latex2e pour les articles ou actes Studia, Ivan Lavallée} \ProvidesFile{\PackageName.cls}[\filedate \space Version:\space \PackageVersion] %-------------------------------------------------------------------------------------------------------------------------------------- % % Initialisation du code % %-------------------------------------------------------------------------------------------------------------------------------------- % Définition des variables d'option et leur valeur par défaut % Les tests if ne comportent pas de `@' pour pouvoir être utilisés dans les documents % En particulier \iftreatise peut être utile \newif\iffrenchlang \frenchlangtrue % ouvrage en français, false => in english \newif\ifcropmarks \cropmarksfalse % affichage du contour de page et de corps du texte \newif\ifemptyheaders \emptyheadersfalse % aucun entéte de page, mais numérotation hors cadre \newif\iffirstbreak \firstbreaktrue % true => saut de page sur la page de titre \newif\iffleqn \fleqnfalse % true => formules mathématiques à gauche, sinon centrées %-------------------------------------------------------------------------------------------------------------------------------------- % % Declaration des options % %-------------------------------------------------------------------------------------------------------------------------------------- \DeclareOption{english}{% \typeout{studia-Hermann.cls : ``english'' option}% \frenchlangfalse } % Pour caler les formules "au fer" à gauche \DeclareOption{fleqn}{% \typeout{studia-Hermann.cls : ``fleqn'' option}% \PassOptionsToClass{fleqn}{article}% \fleqntrue% } % Permet de voir les limites de page et de texte \DeclareOption{cropmarks}{% \typeout{studia-Hermann.cls : ``cropmarks'' option}% \cropmarkstrue% } % Pour supprimer les entêtes de page \DeclareOption{empty}{% \typeout{studia-Hermann.cls : ``empty'' option}% \emptyheaderstrue % } % Permet de gérer le saut de premiére page \DeclareOption{nofirstpagebreak}{% \typeout{studia-Hermann.cls : ``nofirstpagebreak'' option}% \firstbreakfalse % } \DeclareOption*{\typeout{*** Option ``\CurrentOption'' inconnue ***\\ Syntaxe : documentclass[fleqn,english,cropmarks,empty,nofirstpagebreak]{studia-Hermann}}} \PassOptionsToClass{12pt,twoside}{article} %-------------------------------------------------------------------------------------------------------------------------------------- % % Exécution des options % %-------------------------------------------------------------------------------------------------------------------------------------- \ExecuteOptions{12pt} % Options par défaut \ProcessOptions % …évaluation des déclarations d'options %-------------------------------------------------------------------------------------------------------------------------------------- % % Blocs utilisés % %-------------------------------------------------------------------------------------------------------------------------------------- \LoadClass[a4paper]{article} \RequirePackage{ifthen} \RequirePackage{amsmath} \RequirePackage{amsfonts} \RequirePackage{amssymb} \RequirePackage[dvips]{graphicx} \RequirePackage[french,english]{babel} %-------------------------------------------------------------------------------------------------------------------------------------- % %%%%%%%%%%%%%%%%%%%%%%%%% Rajoutés par Ivan %%%%%%%%%%%%%% % %-------------------------------------------------------------------------------------------------------------------------------------- \usepackage{latexsym} \usepackage{amsmath} \usepackage[utf8]{inputenc} \usepackage{times} \usepackage{algorithm} \usepackage{tabularx} \usepackage{framed} \usepackage{ragged2e} % ------------------------------------------------------------------------------------------- % % Utilisation éventuelle de la couleur % % o0O0o % \usepackage{color} \definecolor{rouge}{rgb}{1,0,0} \definecolor{vert}{rgb}{0,1,0} \definecolor{bleu}{rgb}{0,0,1} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %--------------------------------------------------------------------------------------------------------------------------- % Attention ! avec babel, tout appel à \selectlanguage active un espacement spécial pour % les listes et redéfinit les noms de certaines entités (tablename, figurename.... % Mais on peut agir \let\ORIselectlanguage\selectlanguage \gdef\selectlanguage#1{\ORIselectlanguage{#1}\@mkstudia} \def\french{\selectlanguage{frenchb}\@mkstudia} \def\english{\selectlanguage{english}\@mkstudia} %%% Fin du prélude %%% Code des Commandes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % Dans l'ordre des sections de Consignes aux auteurs (cf. http://www.editions-studia.fr) % % ``Consignes aux auteurs ...'' % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -------------------------------------------------- <2. Présentation> --------------------------------------------------------- % Polices du corps du texte % L'encodage recommandé est T1, notamment pour les guillemets français % Mais certaines installations n'acceptent pas cet encodage ou nécessitent % trop de constructions de polices pour dvips ou xdvi : je ne l'impose pas % Il semble que les guillemets français puissent être obtenus par % \leftguillemets \rightguillemets même sans l'encodage T1. % En cas de problème avec certains caractères pour certaines polices % forcer l'encodage à T1 ou OT1 OU SUPPRIMER cet encodage. % - soit ici, %\usepackage[T1]{fontenc} %\usepackage[latin1]{inputenc} %\usepackage[latin]{inputenc} % - soit dans le prélude du document, par exemple avec \usepackage[T1]{fontenc} % Latex/Unix: Times romain \renewcommand{\rmdefault}{ptm} % Postscript Times \renewcommand{\sfdefault}{phv} % Postscript Helvetica \renewcommand{\ttdefault}{pcr} % Police Courier : un peu large \renewcommand{\ttdefault}{cmtt} % Police Latex tt : plus jolie et étroite, \newcommand{\FonteTexte}{\normalfont\fontsize{10}{12}\selectfont} \newlength{\interligne} % Ne change pas dans ce style: quand on parle \setlength{\interligne}{12pt} % d'une ligne blanche, c'est ça : 4.22mm % On peut utiliser cette commande dans le texte, par exemple % \setlength{\baselineskip}{1\interligne} pour revenir à l'espacement normal \newcommand{\@espace}{\hspace*{0.5em}} % <2.1. Format> -------------------------------------------------------------- %-------------------------------------------------------------------------------------------------------------------------------- % Dimensionnements %-------------------------------------------------------------------------------------------------------------------------------- % Page %-------------------------------------------------------------------------------------------------------------------------------- % Format des pages (pour papier a4 ou letter) % Rappel : A4 = 210mm x 297 mm USLETTER = 8.5in x 11in = 215.9mm * 279.4mm % soit USLETTER = 6mm de plus dans la marge droite et 17.6mm de moins dans le bas de page \setlength{\textwidth}{120mm} % 120mm = 341pt \setlength{\textheight}{190mm} % 190mm = 540pt (45 lignes * 12pt) = 189.78mm %-------------------------------------------------------------------------------------------------------------------------------- % % Texte % %-------------------------------------------------------------------------------------------------------------------------------- % <2.1.1 Marges et Format> --------------------------------------------------- %--- Dimensions horizontales \setlength{\hoffset}{-1in} % à ajuster par dvips selon imprimante % ancien \setlength{\oddsidemargin}{45mm} % pour que la marge de gauche % ancien \setlength{\evensidemargin}{45mm} % soit exactement de 45mm \setlength{\oddsidemargin}{40mm} \setlength{\evensidemargin}{40mm} \setlength{\marginparsep}{0mm} % % Largeur de la marge de droite pour papier: % - A4 : largeur papier = 210 mm => 210 - (120+45) = 45 mm % - Letter : 8.5in = 8.5*25.4mm = 215.9mm => 215.9-165 = 50.9mm %--- Dimensions verticales \setlength{\voffset}{-1in} % à ajuster selon imprimante pour que la marge % au dessus du texte (page 2) soit exactement % de 53.5mm \setlength{\topmargin}{44mm} % distance bord sup feuille au haut de l'en-tête \settoheight{\headheight}{2mm} % \setlength{\headsep}{7.5mm} % % 44mm + 2mm + 7.5mm = 53.5mm (marge au dessus du texte) %--- Tracé du cadre indiquant les bords du papier une fois l'article massicoté % au format des revues/actes Hermann (160mm x 240mm) % Ce tracé est obtenu par l'option \documentclass[cropmarks]{studia-Hermann} % (par défaut pas de tracé) et est commandé à partir de l'en-tête (picture). % L'avantage de ce système est de ne pas influencer la mise en page de Latex %-- Commandes utilisateur \newcommand{\CropMarksOn}{\renewcommand{\@DrawPageFrame}{\@PageFrame}} \newcommand{\CropMarksOff}{\renewcommand{\@DrawPageFrame}{}} %-- Primitives internes \newcommand{\@DrawPageFrame}{} \newcommand{\@PageFrame}{% \thinlines% \setlength{\unitlength}{1mm}% \begin{picture}(0,0)% % Les mesures sont faites à partir du point de référence qui est posé à gauche % de l'en-tête (7.5mm au dessus du texte) % Les dimensions des pages massicotées sont de 150 x 220 mm % Donc, en format A4, les bandes supprimées au dessus sont de (297-220)/2=38.5mm % => distance du coin supérieur gauche au dessus du point de référence: % 53.5mm -7.5mm =46mm ; 46mm-38.5mm = 7.5mm %\put(-20,17.5){\line(1,0){160}} % Ancien massicotage %\put(-20,17.5){\line(0,-1){240}} % % \put(140,17.5){\line(0,-1){240}} % % \put(-20,-222.5){\line(1,0){160}} % %-------------------------------------- Nouveau massicotage ---------------------- \put(-20,7.5){\line(1,0){160}} % Gère la ligne de massicotage supérieure \put(-15,17.5){\line(0,-1){240}} % Gère la ligne de massicotage gauche \put(135,17.5){\line(0,-1){240}} % Gère la ligne de massicotage droite \put(-20,-212.5){\line(1,0){160}} % Gère la ligne de massicotage inférieure \put(0,-7.5){\line(1,0){120}} % marque du bord supérieur du texte \put(0,-197.5){\line(1,0){120}} % 7.5+190 = 197.5mm: bas du texte \put(0,-7.7){\line(0,-1){190}} % côté gauche du texte \put(120,-7.5){\line(0,-1){190}} % côté droit du texte \end{picture}% }% \ifcropmarks \CropMarksOn \else \CropMarksOff \fi \flushbottom %-------------------------------------------------------------------------------------------------------------------------% % % % Style de la première page % % % %-------------------------------------------------------------------------------------------------------------------------% % hauteur du texte maximum: 170mm % pied de page pour la signature, à 194mm sous le point de référence, \newcommand{\@FonteEntete}{\normalfont\small} \newcommand{\ps@firstpage}{% % Une première page est normalement impaire, mais on définit les deux... \renewcommand{\@oddhead}{\parbox{\textwidth}{\@DrawPageFrame}}% \renewcommand{\@evenhead} { \parbox{\textwidth}{\@DrawPageFrame} }% % Le pied de page ne sert normnalement que pour la signature de l'article % dont la ligne de base est à 44mm du bord inférieur de la feuille A4 \setlength{\footskip}{10mm} % dist. bas du texte au bas du pied de page. % Ainsi le haut de l'entete de page et le bas % du pied de page sont tous les deux à 44mm du % bord de feuille A4 (et 26.4 mm en USLetter) \ifemptyheaders \renewcommand{\@oddfoot}{}% \renewcommand{\@evenfoot}{}% \else \renewcommand{\@oddfoot}{\parbox{\textwidth}{\raggedright\VAR@SignatureArticle}}% \renewcommand{\@evenfoot}{\parbox{\textwidth}{\raggedright\VAR@SignatureArticle}}% \fi }% firstpage style %-------------------------------------------------------------------------------------------------------- % Style des pages courantes %-------------------------------------------------------------------------------------------------------- \newcommand{\ps@otherpage}{% \ifemptyheaders % Au cas où il y aurait un pied de page, celui-ci doit sortir du cadre massicoté, % lequel est à 25mm sous le bas du texte. Donc 25+15mm=40mm \setlength{\footskip}{40mm} % réduire à 33mm pour USLETTER \renewcommand{\@evenhead}{\parbox{\textwidth}{\@DrawPageFrame}}% \renewcommand{\@oddhead}{\parbox{\textwidth}{\@DrawPageFrame}}% \renewcommand{\@evenfoot}{\@FonteEntete\thepage \hspace*{\fill}}% \renewcommand{\@oddfoot}{\hspace*{\fill}\@FonteEntete \thepage}% \else \renewcommand{\@evenhead}{% \parbox{\textwidth}{% \@DrawPageFrame\@FonteEntete\thepage\hspace{\@ESPage}\VAR@EnTeteG}}% \renewcommand{\@oddhead}{% \parbox{\textwidth}{% \@DrawPageFrame\hspace*{\fill}\@FonteEntete\VAR@EnTeteD% \hspace{\@ESPage}\thepage}}% \renewcommand{\@evenfoot}{}% \renewcommand{\@oddfoot}{}% \fi }% otherpage style \pagestyle{otherpage}% doit être placé après les définitions précédentes %-------------------------------------------------------------------------------------------------------- % 2.1.2. En-tête %-------------------------------------------------------------------------------------------------------- \newcommand{\FonteEnTete}{\normalfont\fontsize{9}{12}\selectfont}% Police des en-têtes \newcommand{\VAR@EnTeteG}{% \FonteEnTete% Nom de la revue ou conférence (à définir par \texttt{\@BS submitted ou \@BS toappear})} \newcommand{\VAR@EnTeteD}{% \FonteEnTete% Titre abrégé de l'article (à définir par \texttt{\@BS title[titre abrégé]\{titre\}})} %-------------------------------------------------------------------------------------------------------- % % 2.2 Titres et sous-titres % %-------------------------------------------------------------------------------------------------------- %-------------------------------------------------------------------------------------------------------- % % 2.2.1 Première page de l'article % %-------------------------------------------------------------------------------------------------------- \newcommand{\nofirstpagebreak}{\firstbreakfalse} \newcommand{\firstpagebreak}{\firstbreaktrue} \newcommand{\maketitlepage}{% % \@redefinitions% \setlength{\parskip}{0pt}% \setlength{\parindent}{0pt}% \thispagestyle{firstpage}% % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Block 1\iere page { % Sous-bloc Titre-Auteurs, adressses { \par{\FonteRubrique\hfill \VAR@rubrique \hfill} \par\vspace*{6pt}\@filet%Filet de tête de première page ;interlignage=épaisseur du filet % \par\vspace*{12pt}% \par\vspace*{6pt}% Distance du titre au filet \@Titre{\VAR@title}% + vspace de 2 lignes de 12 pts \@SousTitre{\VAR@subtitle}% + vspace de 2 lignes de 12 pts \@Auteurs{\VAR@author}% % \par\vspace*{1\interligne}% espace avant Adresse \par\vspace*{.5\interligne}% espace avant Adresse \@Adresse{\VAR@address}% \par\vspace*{1\interligne}% espace entre adresse et filet \par\@filet% \par\vspace*{2pt}% espace entre filet et le bloc } % Fin du "sous-bloc première page", c'est ce qui m'a permis de "découpler" la centration des auteurs et adresses des résumé et abstract \iffrenchlang \@Resume{\VAR@resume}% \par\vspace*{3pt}% \@Abstract{\VAR@abstract}% \par\vspace*{3pt}% \@MotsCles{\VAR@motscles}% \par\vspace*{3pt}% \@KeyWords{\VAR@keywords}% \else \@Abstract{\VAR@abstract}% \par\vspace*{3pt}% \@Resume{\VAR@resume}% \par\vspace*{3pt}% \@KeyWords{\VAR@keywords}% \par\vspace*{3pt}% \@MotsCles{\VAR@motscles}% \fi \FonteTexte% \par\vspace*{4pt}% \@filet% \setcounter{section}{0}% \setcounter{footnote}{0}% } % Terminaison du "Bloc de première page" % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \iffirstbreak \par\vspace*{\stretch{3}}\newpage% \else \par\vspace*{1\interligne} \fi % Pour éviter les interférences avec d'autres packages, il vaut mieux définir % les constantes suivantes après \begin{document}, par exemple ici. \setlength{\parindent}{5mm} % renfoncement (ou retrait) \setlength{\parskip}{6pt} % }%\maketitlepage \renewcommand{\maketitle}{\maketitlepage} \newcommand{\FonteTitreEdito}{% 18 points interligné 21.6pt (120% du corps) \rmfamily\upshape\fontsize{18}{21.6}\selectfont} \newcommand{\@Coordonnateurs}{Les Coordonnateurs} \newenvironment{editorial}[5]% % #1 rev % #2 Volume % #3 Numero % #4 Année % #5 Prénom \textsc{Nom} des rédacteurs de l'éditorial, séparés par des \\. % Exemple % \begin{editorial}{L'Objet}{6}{1}{2000}{Pascal \textsc{ANDRE}\\Roger \textsc{ROUSSEAU}} % texte de l'edito si possible sur deux pages au plus % \end{editorial} {%BEGIN \journal{#1}{#2}{#3}{#4}{-}{-}% \renewcommand{\@Coordonnateurs}{#5}% \thispagestyle{firstpage}% \renewcommand{\VAR@SignatureArticle}{}% \@shorttitle{Editorial}% \setlength{\parindent}{5mm} % renfoncement (ou retrait) \setlength{\parskip}{6pt} % conforme à la version du 8/9/99 des consignes \par\vspace*{2pt}\@filet %interlignage=épaisseur du filet \par\vspace*{20pt}% \begin{center}\FonteTitreEdito Editorial \end{center}% \par\vspace*{1\interligne}% \FonteTexte\itshape% }{%END \FonteTexte\upshape% \begin{flushright} \@Coordonnateurs \end{flushright} \newpage% } %-------------------------------------------------------------------------------------------------------% % % % 2.2.1.1. Titre et sous-titre % % % %-------------------------------------------------------------------------------------------------------% \renewcommand{\title}[2][]{ %usage: \title[shorttitle]{title} \ifthenelse{\equal{#1}{}}{%Y \@shorttitle{#2}% }{% \@shorttitle{#1}% } \renewcommand{\VAR@title}{#2} } %-------------------------------------------------------------------------------------------------------% % % % Titre Courant (ou abrégé) pour les en-têtes de pages impaires % % % %-------------------------------------------------------------------------------------------------------% \newcommand{\VAR@TitreAbrege}{Titre abrégé : % à définir par \texttt{\@backslashchar shorttitle\{...\}}} \newsavebox{\@shtitle} \newcommand{\@shorttitle}[1]{% % #1: Titre abrégé de l'article (moins de 40 caractères, pour en-tête) % test de la largeur < 55mm \sbox{\@shtitle}{\@FonteEntete #1}% \ifthenelse{\lengthtest{\wd\@shtitle > 55mm}}{% \@latex@error{short title defined by \@backslashchar title[short]{long} too long: (55mm max)}\@eha }{} \renewcommand{\VAR@TitreAbrege}{#1} } \def\subtitle#1{\renewcommand{\VAR@subtitle}{#1}} \def\author#1{\renewcommand{\VAR@author}{#1}} \def\address#1{\renewcommand{\VAR@address}{#1}} \def\abstract#1{\renewcommand{\VAR@abstract}{#1}} \def\motscles#1{\renewcommand{\VAR@motscles}{#1}} \def\keywords#1{\renewcommand{\VAR@keywords}{#1}} \def\resume#1{\renewcommand{\VAR@resume}{#1}} %-- Primitives internes \def\@BS{\symbol{"5C}} \def\@ARGS{\{\ldots\}} \def\@ARG#1{\{\normalfont\textit{#1}\}} \newcommand{\@filet}{\rule{\linewidth}{0.20pt}} %--- Signature et en-têtes de l'article : % peuvent être définis par \submitted, \journal ou \proceedings \newcommand{\FonteSignature}{\normalfont\fontsize{9pt}{10.8pt}\selectfont} \newcommand{\FonteRubrique}{% % \rmfamily\mdseries\scshape\fontsize{14pt}{16.8pt}\selectfont} \rmfamily\mdseries\fontsize{12pt}{14.4pt}\selectfont} \newcommand{\VAR@rubrique}{} \newcommand{\VAR@SignatureArticle}{} \newcommand{\VAR@NomRevue}{} \newcommand{\VAR@VolumeRevue}{} \newcommand{\VAR@NumeroRevue}{} \newcommand{\VAR@AnneeRevue}{} \newlength{\@ESPage}\setlength{\@ESPage}{4mm}% 5 espaces blancs \newcommand{\VAR@Pages}{} \newcommand{\VAR@NumeroSoumission}{} \newcommand{\VAR@NomActes}{} \newcommand{\VAR@TypeArticle}{revue} %Ancienne commande \iffalse \newcommand{\journal}[7][]{% pour article de revue % #1 [rubrique] % #2 {revue} % #3 {vol} % #4 {num} % #5 {annee} % #6 {1ere p.} % #7 {dern. page} \renewcommand{\VAR@TypeArticle}{revue}% \renewcommand{\VAR@rubrique}{\uppercase{#1}} \renewcommand{\VAR@NomRevue}{#2} \renewcommand{\VAR@VolumeRevue}{#3} \renewcommand{\VAR@NumeroRevue}{#4} \renewcommand{\VAR@AnneeRevue}{#5} % \renewcommand{\VAR@Pages}{#6} % \ifthenelse{\equal{\VAR@Pages}{-}}{%1re page inconnue % \setcounter{page}{1} % on augmente l'espace après numéro page pour permettre à l'éditeur de % surcharger le bon numéro % \setlength{\@ESPage}{6mm} % \renewcommand{\VAR@Pages}{} % } % {%1ere page donnée % \setcounter{page}{#6} % \renewcommand{\VAR@Pages}{, pages #6\ \`a #7} % } \ifthenelse{\equal{\VAR@NumeroRevue}{\LMO}}{%signature spéciale pour LMO \renewcommand{\VAR@SignatureArticle}{\FonteSignature % \VAR@NomRevue\ -- \VAR@VolumeRevue/\VAR@AnneeRevue. % \VAR@NumeroRevue'\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue\ -- % \VAR@VolumeRevue/\VAR@AnneeRevue. \VAR@NumeroRevue'\VAR@AnneeRevue} }{\ifthenelse{\equal{\VAR@NomRevue}{\LOBJET}}{% % spécial pour la revue L'objet : sans mot Volume, sans numéro \renewcommand{\VAR@SignatureArticle}{\FonteSignature% \VAR@NomRevue\ -- \VAR@VolumeRevue/\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue\ -- % \VAR@VolumeRevue/\VAR@AnneeRevue.} }{% Autres revues \ifthenelse{\equal{\VAR@NumeroRevue}{}}{%pas de numéro revue \renewcommand{\VAR@SignatureArticle}{\FonteSignature % \VAR@NomRevue -- \VAR@VolumeRevue/\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue. % Volume \VAR@VolumeRevue/\VAR@AnneeRevue} }{% numéro de revue présent, présentation normale, style TSI : \renewcommand{\VAR@SignatureArticle}{\FonteSignature % \VAR@NomRevue. Volume \VAR@VolumeRevue\ -- n$^\circ$ \VAR@NumeroRevue/\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue. % Volume \VAR@VolumeRevue\ -- n$^\circ$ \VAR@NumeroRevue/\VAR@AnneeRevue} }}} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} }%\journal #\fi \newcommand{\journal}[3]{% pour article de revue % #1 {revue. Volume 19 -- n∞ 1/2005,} % #2 {1ere p.} % #3 {dern. page} \renewcommand{\VAR@TypeArticle}{revue}% % \renewcommand{\VAR@rubrique}{\uppercase{#1}} \renewcommand{\VAR@NomRevue}{#1} % \renewcommand{\VAR@VolumeRevue}{#3} % \renewcommand{\VAR@NumeroRevue}{#4} % \renewcommand{\VAR@AnneeRevue}{#5} \renewcommand{\VAR@Pages}{#2} \ifthenelse{\equal{\VAR@Pages}{-}}{%1re page inconnue \setcounter{page}{1} % on augmente l'espace après numéro page pour permettre à l'éditeur de % surcharger le bon numéro \setlength{\@ESPage}{6mm} \renewcommand{\VAR@Pages}{} }{%1ere page donnée \setcounter{page}{#2} \renewcommand{\VAR@Pages}{, pages #2\ \`a #3} } \renewcommand{\VAR@SignatureArticle}{\FonteSignature\VAR@NomRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} }%\journal \newcommand{\proceedings}[2]{% pour article d'actes de conférence % usage: {#1} = nom de la conférence % {#2} = numéro de première page \renewcommand{\VAR@TypeArticle}{conference}% \renewcommand{\VAR@NomActes}{#1}% \renewcommand{\VAR@Pages}{#2}% \ifthenelse{\equal{\VAR@Pages}{-}}{%1re page inconnue \setcounter{page}{1} % on augmente l'espace après numéro page pour permettre à l'éditeur de % surcharger le bon numéro \setlength{\@ESPage}{6mm} }{%1ere page donnée \setcounter{page}{#2} } \renewcommand{\VAR@SignatureArticle}{} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomActes} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} } \newcommand{\submitted}[3][\today]{% Commun Actes ou Revue % usage: [#1] = date (par défaut \today) % {#2} = nom revue ou conférence % {#3} = numéro de soumission (le plus souvent de 1 à 3). \renewcommand{\VAR@NomRevue}{#2}% \renewcommand{\VAR@NumeroSoumission}{% \ifthenelse{\equal{#3}{1}}{1\iere~}{#3\ieme~}}% \renewcommand{\VAR@SignatureArticle}{% \FonteSignature\raggedright \VAR@NumeroSoumission soumission \`a \textit{\VAR@NomRevue}, le #1 } \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NumeroSoumission soumission \`a \textit{\VAR@NomRevue}} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} } %-------------------------------------------------------------------------------------------------------------------------------------- % % Noms prédéfinis de revues studia Science Publications % %-------------------------------------------------------------------------------------------------------------------------------------- %--------------------------------------------------------------------------------------------------------------------------------------% \newcommand{\SCU}{Studia Complexica Universalis} \newcommand{\SIU}{Studia Informatica Universalis} %--------------------------------------------------------------------------------------------------------------------------------------% %--- Titre de l'article \newcommand{\VAR@title}{Titre de l'article% {\par\renewcommand{\baselinestretch}{0.66}\par\FonteTexte%@@ \textit{A définir par la commande \texttt{\upshape\@BS title[} titre abrégé \texttt{\upshape]\{} titre complet \texttt{\upshape\}} sur une ou deux lignes coupées par \@BS\@BS.\\ Le sous-titre éventuel est défini sur une ou deux lignes par la commande\\ \texttt{\upshape\@BS subtitle\{} sous-titre complet \texttt{\upshape\}}.}}} \newcommand{\FonteTitre}{% 18 points interligné 21.6pt (120% du corps) % \rmfamily\bfseries\upshape\fontsize{18}{21.6}\selectfont} \rmfamily\bfseries\upshape\fontsize{18}{22}\selectfont} \newcommand{\@Titre}[1]{{% % #1: Titre complet de l'article (peut incorporer des `\\') %\setlength{\parskip}{0pt}\flushleft% \setlength{\parskip}{0pt}\center% \FonteTitre #1% \par\vspace*{10pt}% }} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Modifié %%%%%%%%%%%%% %--- Sous-Titre de l'article \newcommand{\VAR@subtitle}{} \newcommand{\FonteSousTitre}{% 14pt interligné 16.8pt (120% du corps) % \rmfamily\bfseries\upshape\fontsize{14}{16.8}\selectfont} \rmfamily\bfseries\upshape\fontsize{14}{17}\selectfont} \newcommand{\@SousTitre}[1]{{% % #1: Sous-titre de l'article dans une police plus petite (peut incorporer des `\\') \setlength{\parskip}{0pt}% \FonteSousTitre #1% % \par\vspace*{21.2pt}% 2 lignes = 24 pts - (16.8-14) \par\vspace*{2pt}% }} %------------------------------------------------------------------------------------------------------------ % Auteurs %------------------------------------------------------------------------------------------------------------ \newcommand{\FonteAuteur}{% 12pt interligné 14.4pt (120% du corps) \rmfamily\bfseries\upshape\fontsize{12}{14.4}\selectfont} \newcommand{\VAR@author}{% Auteur(s)\\ {\FonteTexte\textit{A définir par la commande \texttt{\upshape\@BS author\@ARGS}. Dans le cas de plusieurs auteurs, séparer chaque auteur par \texttt{\upshape\@BS andauthor}. Dans le cas d'adresses différentes des auteurs, indexer chaque auteur avec des astérisques comme \fup{*} ou \fup{**} obtenues par \texttt{\upshape\@BS fup\{*\}} ou \texttt{\upshape\@BS fup\{**\}}. }}} \newcommand{\@Auteurs}[1]{\center{% Là j'ai rajouté \center pour centrer auteurs et adresses mais ça \FonteAuteur #1% % } } \newcommand{\andauthor}{% % Tiret long maigre de séparation entre deux noms d'auteurs {\FonteTexte\mdseries --- }} %--- Adresse(s) de(s) auteur(s) \newcommand{\FonteAdresse}{\rmfamily\mdseries\itshape\fontsize{10}{12}\selectfont} \newcommand{\VAR@address}{Adresse :\\ {\FonteTexte\textit A définir sur plusieurs lignes par la commande \texttt{\upshape\@BS address\@ARGS}.\\ Email sur la dernière ligne.\\ Dans le cas d'adresses différentes des auteurs, indexer chaque auteur avec des astérisques comme \fup{*} ou \fup{**} obtenues par \texttt{\upshape\@BS fup\{*\}} ou \texttt{\upshape\@BS fup\{**\}}.\\ Voir aussi <<~Consignes aux auteurs~>> }} \newcommand{\@Adresse}[1]{\FonteAdresse #1} %--- Résumé et Abstract \newcommand{\FonteResume}{\rmfamily\mdseries\itshape\fontsize{9}{11}\selectfont} % Studia demande des petites capitales italiques postscript % Comme cette police n'existe pas sous Unix, % on utilise l'italique de Times en utilisant des capitales réduites de 2 points. % Si un utilisateur dispose d'une police en petites capitales italiques adaptée % à Times, il peut facilement faire l'adaptation. \newcommand{\FonteTitreResume}{% % \rmfamily\mdseries\itshape\fontsize{7}{11}\selectfont} \rmfamily\mdseries\itshape\fontsize{9}{10}\selectfont} \newcommand{\VAR@resume}{% {\FonteTexte\textit{A définir par la commande \texttt{\upshape\@BS resume\@ARGS}}}} \newcommand{\@TitreResume}[2]{\FonteTitreResume \noindent #1#2\FonteResume} \newcommand{\@Resume}[1]{{\french\@TitreResume{\bf R\'ESUM\'E}{.} #1}} %--- Abstract \newcommand{\VAR@abstract}{% {\FonteTexte\textit{A définir par la commande \texttt{\upshape\@BS abstract\@ARGS}}}} \newcommand{\@Abstract}[1]{{\english\@TitreResume{\bf ABSTRACT}{.} #1}} %--- Mots-clés \newcommand{\VAR@motscles}{% {\FonteTexte\textit{A définir par la commande \texttt{\upshape\@BS motscles\@ARGS}}}} \newcommand{\@MotsCles}[1]{{\french\@TitreResume{\bf MOTS-CL\'ES}{~:} #1}} %--- Keyswords \newcommand{\VAR@keywords}{% {\FonteTexte\textit{A définir par la commande \texttt{\upshape\@BS keywords\@ARGS}}}} \newcommand{\@KeyWords}[1]{{\english\@TitreResume{\bf KEYWORDS}{:} #1}} % <2.2.2 Titre des paragraphes ou titre d'´ inter ª (sections)>---------------- % cf \Latex Companion 2.3 pp 18-31 % Les définitions suivantes visent à donner la police particulière % exigée par studia uniquement dans les titres de section et non pas dans les % références. Ainsi, 2.2. apparaîtra en gras droit dans le titre et en % police normale dans les références par \label ... \ref. % Si l'on veut la même présentation dans les références de sections, % il faut tout simplement incorporer la définition voulue dans celle % de \thesection ... \thesubsection % On numérote jusqu'à la section de niveau 4 \setcounter{secnumdepth}{4} % Pour les titres de section sur plusieurs lignes, Hermann ne veut pas d'indentation \def\@hangfrom#1{% \setbox\@tempboxa\hbox{{#1}}% % \hangindent \wd\@tempboxa\noindent\box\@tempboxa %% ORIGINAL de latex.ltx \hangindent \wd 0 \noindent\box\@tempboxa %% MODIF } % Attention : les dimensions des interlignes before et after skip % doivent tenir compte du parskip qui est de 6pts et qui s'ajoute aux valeurs % indiquées %--- Niveau 1: section : gras, beforeskip = 2 lignes, afterskip = 1 ligne \newcommand{\FonteSectionI}{\normalsize\normalfont\bfseries\raggedright}% \renewcommand{\thesection}{\arabic{section}}% % Il faut enlever le parskip de 6pts aux valeurs des skips (2 lignes=24-6=18pts...) \renewcommand{\section}{% \renewcommand{\@seccntformat}[1]{\thesection.\hspace{0.5em}}% \@startsection{section}% % nom de l'inter {1}% % niveau de l'inter {0pt}% % l'indentation du titre et du texte suivant {18pt plus 2pt minus 2pt}% beforeskip {6pt plus 1pt minus 1 pt}% afterskip {\FonteSectionI}% % style } %--- Niveau 2: sous-section : gras+ital, beforeskip = 2 lignes, afterskip = 1 ligne \newcommand{\FonteSectionII}{\normalsize\normalfont\bfseries\itshape\raggedright}% \renewcommand{\thesubsection}{\thesection.\arabic{subsection}}% \renewcommand{\subsection}{% \renewcommand{\@seccntformat}[1]% {{\normalsize\normalfont\bfseries\thesubsection.\hspace{0.5em}}}% \@startsection% {subsection}% % nom de l'inter {2}% % niveau de l'inter {0pt}% % l'indentation du titre et du texte suivant {18pt plus 2 pt minus 1pt}% beforeskip {6pt plus 1pt minus 1pt} %afterskip {\FonteSectionII}}% % style %--- Niveau 3: sous-sous-section : italique, beforeskip=1 lignes, afterskip=1 ligne \newcommand{\FonteSectionIII}{\normalsize\normalfont\itshape\raggedright}% \renewcommand{\thesubsubsection}{\thesubsection.\arabic{subsubsection}}% \renewcommand{\subsubsection}{% \renewcommand{\@seccntformat}[1]{% {\normalsize\normalfont\thesubsubsection.\hspace{0.5em}}}% \@startsection% {subsubsection}% % nom de l'inter {3}% % niveau de l'inter {0mm}% % l'indentation du titre et du texte suivant {6pt plus 1pt minus 1pt} % beforeskip {0.1pt}% % afterskip (0pt supprimerait le passage à la ligne) {\FonteSectionIII}}% % style %--- Niveau 4: paragraphes: police normale, beforeskip=1 ligne, afterskip=1 ligne \newcommand{\FonteSectionIV}{\normalsize\normalfont\raggedright}% \renewcommand{\theparagraph}{\thesubsubsection.\arabic{paragraph}}% \renewcommand{\paragraph}{% \renewcommand{\@seccntformat}[1]{% {\normalsize\normalfont\theparagraph.\hspace{0.5em}}}% \@startsection% {paragraph}% % nom de l'inter {4}% % niveau de l'inter {0mm}% % l'indentation du titre et du texte suivant {6pt plus 1pt minus 1 pt}% beforeskip {0.1pt}% % afterskip (0pt supprimerait le passage à la ligne) {\FonteSectionIV}}% % style % 2.3 Alinéas % Disable single lines at the start of a paragraph \clubpenalty = 10000 % Disable single lines at the end of a paragraph \widowpenalty = 10000 \displaywidowpenalty = 10000 \sloppy \raggedbottom % 2.4 Notes de bas de page % corps 9pt/11pt, numérotation décimale % séparées du texte par 1 ligne blanche % filet maigre de 2.5 cm \newcommand{\FonteNoteBasPage}{\fontsize{9}{10.8}\selectfont\normalfont} \renewcommand{\footnotesize}{\FonteNoteBasPage} \addtolength{\skip\footins}{6pt} % = 12pt = 1 ligne avant le filet \renewcommand{\footnoterule}{% % Redéfinition du filet de notes de bas de page. % Doit avoit une hauteur totale virtuelle nulle (cf Latex Companion p. 72) \par\vspace*{-12.3pt}% Hauteur totale => donnera une hauteur virtuelle nulle \noindent\rule{2.5cm}{0.25pt}\vspace*{6pt} % => hauteur totale 9.3pt % Hauteur espace sous filet = 6pt } \setlength{\footnotesep}{2pt} % Espace vertical avant chaque note (strut) \newcommand{\@Myfnmark}{% Redéfinit la marque de footnote comme un indice % french.sty redéfinit bêtement \@makefntext => donc j'utilise une autre macro. \mbox{$\arabic{footnote}$. }% } \renewcommand{\@makefntext}[1]{% \noindent\@Myfnmark#1% }% \def\@thefnmark{\normalsize\arabic{footnote}} % %%% 2.6 Formules %%% % %--------------------------------------------------------------------------------------------------------------------------------------% % En mode standard, les modes equation, eqnarray et eqnarray* % fournissent bien une ligne blanche au dessus et au dessous et la numerotation % collée sur la marge de droite. % La seule adaptation est la numérotation [n] au lieu de (n). %\renewcommand{\@eqnnum}{\reset@font\rmfamily [\theequation]} %\renewcommand{\tagform@}[1]{\reset@font\rmfamily [#1]} % pour align %%%%%% retour au mode standard %%%%%%%%%%%%%%%%%%%%%%% % Définition des espaces avec l'option fleqn : % L'option fleqn (\documentclass[fleqn]...) place les formules indentées à % gauche. Par défaut, les formules sont centrées. \iffleqn %\setlength{\topsep}{1\baselineskip} % espace supplém. au dessus/dessous des formules. \setlength{\mathindent}{10mm} % indentation des formules \fi % Définition des espaces sans l'option fleqn : \setlength{\jot}{0.5\baselineskip} % espace entre les lignes de eqnarray \setlength{\abovedisplayskip}{0mm} % espace supplémentaire au dessus des longues formules \setlength{\abovedisplayshortskip}{0mm} % idem, formules courtes \setlength{\belowdisplayskip}{0mm} % espace supplémentaire au dessous des longues formules \setlength{\belowdisplayshortskip}{0mm} % idem, formules courtes %--- Utilitaires facultatifs % Utiliser la commande \eqncont pour terminer une ligne de formule % sur plusieurs lignes : supprime la numérotation + espace vertical plus serré. \newcommand{\eqncont}{\nonumber \\[0\baselineskip]} %%% Retardement du pagebreak % Pour retarder le passage automatique à la page suivante de 1 ou 2 lignes, % utiliser le couple de commandes \delaynewpage{nb lignes} ... \forcenewpage % Attention! cette technique est du bricolage, mais cependant indispensable % pour une présentation optimale d'un document. (indiquée par Lamport). % IL NE FAUT L'EMPLOYER QUE TOUT ¿ LA FIN, JUSTE AVANT L'IMPRESSION FINALE. % En principe ne pas retarder de plus de 2 lignes ! \newcommand{\delaynewpage}[1]{\enlargethispage{#1\baselineskip}} % ¿ utiliser sur la page à allonger, à un endroit bien visible % avant le premier paragraphe ou la figure à faire tenir sur la page. % Provoque une descente des notes de bas de page s'il y en a ! \newcommand{\forcenewpage}{\pagebreak\noindent} % ¿ utiliser à l'endroit précis où la coupure doit être forcée. % on peut placer cette commande en début de ligne, avec suite du texte % sur la ligne suivante pour faciliter son repérage % Listes -------------------------------------------------------------------------------------------------- % Espaces communs aux listes numérotées (enumerate) ou non (itemize) % Attention !!! Ces espacements ne peuvent être effectifs que si Babel ne les redéfinit % pas dans \@trivlist, comme il tente de l'imposer. Il faut ABSOLUMENT % exécuter \bbl@nonfrenchlistspacing avant le début du document (\AtBeginDocument). \def\mkstudialist{% \gdef\itemize{\studiaitemize}\gdef\enditemize{\endstudiaitemize}% \gdef\enumerate{\studiaenumerate}\gdef\endenumerate{\endstudiaenumerate}% } \newcommand{\studiaItemizeSpacing}{% % espacements horizontaux \leftmargin=0pt \labelsep=1mm \ifnum \@itemdepth < 2 % niveau 0 ou 1 \setlength{\itemindent}{\itemindenti} \listparindent=5mm \else % niveau 2 \itemindent=\itemindentii \listparindent=10mm \fi \labelwidth=0pt \rightmargin=0pt % espacements verticaux des listes \itemsep=0pt \topsep=0pt \parskip=6pt \partopsep=0pt \parsep=3pt % pénalités \sloppy% \widowpenalty4000%ligne isolée en début de page \clubpenalty4000%ligne isolée à la fin d'une page } \newcommand{\displaylistdimen}{ itemdepth: \the\@itemdepth ;\\ topsep: \the\topsep ;\\ itemsep: \the\itemsep ;\\ parskip: \the\parskip ;\\ partopsep: \the\partopsep ;\\ parsep: \the\parsep. } % Listes non numérotées (itemize) ------------------------------------------------------------------------- \newlength{\labelwidthi} % largeur de la boîte contenant le retrait de 5mm + tiret moyen \settowidth{\labelwidthi}{--} % environ 2mm, tiret moyen \addtolength{\labelwidthi}{5mm} % retrait + largeur du tiret moyen, environ 7mm \newlength{\itemindenti} % décalage du texte de 1ère ligne depuis marge gauche \setlength{\itemindenti}{\labelwidthi} % = labelwidthi \addtolength{\itemindenti}{1mm} % + labelsep \newlength{\labelwidthii} % largeur de la boîte contenant le retrait de 10mm + tiret court \settowidth{\labelwidthii}{-} % environ 1mm, tiret court \addtolength{\labelwidthii}{10mm} % retrait + largeur du tiret court, environ 11mm \newlength{\itemindentii} % décalage du texte de 1ère ligne depuis marge gauche \setlength{\itemindentii}{\labelwidthii} % = labelwidthii \addtolength{\itemindentii}{1mm} % + labelsep \newenvironment{studiaitemize}{% liste à deux niveaux seulement \ifnum \@itemdepth > 1 \@toodeep % ici, \@itemdepth = niveau -1 \else% \renewcommand{\labelitemi}{{\makebox[\labelwidthi][r]{--}}}% \renewcommand{\labelitemii}{{\makebox[\labelwidthii][r]{-}}}% \advance\@itemdepth \@ne% \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% \begin{list}% {\csname\@itemitem\endcsname}% {\def\makelabel##1{\llap{##1}}% ##1 signifie arg 1 de list et non de studiaitemize % définir les espaces ici et nulle part ailleursn \studiaItemizeSpacing % }%\item \displaylistdimen \fi}{\end{list}}% % Listes numérotées --------------------------------------------------------------------------------------- \newlength{\enumwidthi} % largeur de la boîte contenant le retrait de 5mm + n. \settowidth{\enumwidthi}{5)} % environ 2mm, chiffre le plus large \addtolength{\enumwidthi}{5mm} % retrait + largeur du tiret moyen, environ 7mm \newlength{\enumindenti} % décalage du texte de 1ère ligne depuis marge gauche \setlength{\enumindenti}{\enumwidthi} % = enumwidthi \addtolength{\enumindenti}{1mm} % + enumsep \newlength{\enumwidthii} % largeur de la boîte contenant le retrait de 10mm + tiret court \settowidth{\enumwidthii}{b)} % environ 1mm, tiret court \addtolength{\enumwidthii}{10mm} % retrait + largeur du tiret court, environ 11mm \newlength{\enumindentii} % décalage du texte de 1ère ligne depuis marge gauche \setlength{\enumindentii}{\enumwidthii} % = enumwidthii \addtolength{\enumindentii}{1mm} % + enumsep \newenvironment{studiaenumerate}{% enumération à un niveau \ifnum \@itemdepth >1 \@toodeep \else% \advance\@enumdepth \@ne% \advance\@itemdepth \@ne% \edef\@enumctr{enum\romannumeral\the\@enumdepth}% \begin{list}% {\csname label\@enumctr\endcsname}% {% \usecounter{\@enumctr}% \def\makelabel##1{\llap{##1}}% ##1 signifie arg 1 de list et non de studiaenumerate % définir les espaces horizontaux ici \studiaItemizeSpacing% \ifnum \@itemdepth =1 \setlength{\itemindent}{\enumindenti} \else \setlength{\itemindent}{\enumindentii} \fi \renewcommand{\labelenumi}{{\makebox[\labelwidthi][r]{\arabic{enumi})}}} \renewcommand{\labelenumii}{{\makebox[\labelwidthii][r]{\alph{enumii})}}}% } \fi}{\end{list}} %%%%%%%%%%%% OLD %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \def\ITEMIZE{% liste à 3 niveaux: labelitemi=``---'' \ifnum \@itemdepth >3 \@toodeep% \else% \renewcommand{\labelitemi}{{---}}% \renewcommand{\labelitemii}{\@labelindent{--}}% \renewcommand{\labelitemiii}{\@labelindent\@labelindent{-}}% \advance\@itemdepth \@ne% \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% \list% {\csname\@itemitem\endcsname}% {% \renewcommand{\@curlabel}{\csname\@itemitem\endcsname}% \def\makelabel##1{\llap{##1}}% \mkstudialist% }% \fi% } \let\endITEMIZE =\endlist % Redéfinition de quote pour réduire l'espace vertical à 6 pts \let\quoteORI\quote \let\endquoteORI\endquote \renewenvironment{quote}{% \par\vspace{-6pt}% \begin{quoteORI}% }{% \end{quoteORI}% \par\vspace{-6pt}% } %<2.8 Remarques ou notes> ----------------------------------------------------- \newcommand{\remark}[1]{{\setlength{\parskip}{0pt}% \par\noindent\textsc{\remarkname}.\ ---\ #1\\}} \newcommand{\note}[1]{{\setlength{\parskip}{0pt}% \par\noindent\textsc{\notename}.\ ---\ #1\\}} %< 2.8 bis Remarques francisée > -------------------------------------- \newcommand{\remarque}[1]{{\setlength{\parskip}{0pt}% \par\noindent\textsc{\remarkname}.\ ---\ #1\\}} %<2.9 Typographie> ------------------------------------------------------------ %<2.10 acknowledgements> --------------------------------------------------------- \newcommand{\acknowledgements}[1]{{ \setlength{\parskip}{0pt}% \par\vspace{2\interligne}\noindent% \FonteTexte \acknowledgementsname% \nopagebreak[4]% \par\vspace{1\interligne}#1% }} %< 2.11 Remerciements > -------------------------------------------------------- % J'ai francisé le commande ci-dessus, acknowledgement étant un mot barbare à manipuler pour des % frenchies --------------------------------------------------------------------------- \newcommand{\remerciements}[1]{{ \setlength{\parskip}{0pt}% \par\vspace{2\interligne}\noindent% \FonteTexte \acknowledgementsname% \nopagebreak[4]% \par\vspace{1\interligne}#1% }} %======================= Biblio à la main ======================================= % Code importé du package Harvard.sty pour obtenir des citations bibliographiques du style (Machin, 2001) %<2.13 Biographie> ---------------------------------------------------------------------- % Il faut 2 lignes au dessus de la première biographie et 1 ligne % de séparation entre les biographies. \newcommand{\@fonteBiographie}{% \rmfamily\mdseries\itshape\fontsize{9}{11}\selectfont} \newcommand{\@firstbiography}{yes} \newcommand{\biography}[2]{ % #1 = Nom de l'auteur, % #2 = biographie enchaînée derrière le nom d'auteur, typiquement % ´ est chercheur au laboratoire... ª \ifthenelse{\equal{\@firstbiography}{yes}}{% première biographie \renewcommand{\@firstbiography}{no}% \par\vspace{18pt}\noindent% + 6pt de \parskip }{% biographies suivantes \par\vspace{6pt}\noindent% + 6pt de \parskip }% {\@fonteBiographie \textbf{#1} #2 }} % <3. Remise des articles> --------------------------------------------------- % <3.1 Journal de bord> ------------------------------------------------------ \newcommand{\andeditor}{% mot `et' en police normale {{\FonteTexte et\ }}} \newcommand{\logbook}[3]{{% pour revues seulement % #1: date réception % #2: date révision % #3: rédacteur responsable \setlength{\parskip}{0pt}% \par\vspace{1\interligne}% \begin{flushright}% Article reçu le #1.\\ Version révisée le #2.\\ Rédacteur responsable~: \textsc{#3} \end{flushright}% }} % <3.2 Annexe pour le service de fabrication> ------------------------------------ \newcommand{\adressestudia}{ \begin{flushright} {\setlength{\parsep}{0mm} \fbox{\parbox{70mm}{ \begin{flushright} \textsc{Service \'Editorial -- Studia Universalis}\\ 41 rue Gay Lussac, 75005 Paris\\ Tél : 01-44-10-84/83\\ mel : contact@complexica.net\\ Serveur web : http://studia.complexica.net \end{flushright} }}} \end{flushright}} \newcommand{\VAR@titletranslation}{} \newcommand{\VAR@Phone}{} \newcommand{\VAR@Fax}{} \newcommand{\VAR@Email}{} \newcommand{\publisher}[3]{ % Pour construire la page d'annexe pour le service de fabrication % usage: {#1} = traduction du titre % {#2} = numero de téléphone des auteurs % {#3} = fax des auteurs % {#4} = Email des auteurs %\renewcommand{\VAR@titletranslation}{#1} \renewcommand{\VAR@Phone}{#1} \renewcommand{\VAR@Fax}{#2} \renewcommand{\VAR@Email}{#3} \let\myenddocument\enddocument \def\enddocument{ \pagebreak \pagestyle{empty}\enlargethispage{80mm} %\renewcommand{\@enddocumenthook}{ \parbox{\textwidth}{ \fbox{\parbox{\textwidth}{\begin{center} \textbf{\large ANNEXE POUR LA FABRICATION}\\ A FOURNIR PAR LES AUTEURS AVEC UN EXEMPLAIRE PAPIER\\ DE LEUR ARTICLE \end{center}}}\\[10mm] %\setcounter{section}{0} \ifthenelse{\equal{\VAR@TypeArticle}{revue}}{ \textsc{1. Article pour la revue~:} \begin{quote}\textit{\VAR@NomRevue}\end{quote}\vspace*{3mm} }{ \textsc{1. Article pour les actes~:} \begin{quote}\textit{\VAR@NomActes}\end{quote}\vspace*{3mm} } \textsc{2. Auteurs~:} \begin{quote}\textit{\VAR@author}\end{quote}\vspace*{3mm} \textsc{3. Titre de l'article~:} \begin{quote}\textit{\VAR@title}\end{quote}\vspace*{3mm} \textsc{4. Titre \underline{abrégé} pour le haut de page \underline{moins de 40 signes}~:} \begin{quote}\textit{\VAR@TitreAbrege}\end{quote}\vspace*{3mm} \textsc{5. Date de cette version~:} \begin{quote}\textit{\today}\end{quote}\vspace*{3mm} \textsc{6. Coordonnées des auteurs~:} \begin{itemize} \item adresse postale~: \begin{quote}\VAR@address\end{quote} \item téléphone~: \VAR@Phone \item télécopie~: \VAR@Fax \item e-mail~: \VAR@Email \end{itemize}\vspace*{3mm} \textsc{7. Logiciel utilisé pour la préparation de cet article~:} \begin{quote} \LaTeX, avec le fichier de style \texttt{\PackageName.cls}, \\ version~\PackageVersion\ du \filedate. \end{quote} %\vspace*{3mm} %\textsc{8. Formulaire de copyright~:} %\begin{quote} % Retourner le formulaire de copyright signé par les auteurs, téléchargé % sur~: % \texttt{http://www.revuesonline.com} % \end{quote}\vspace*{3mm} } \adressestudia \myenddocument}%\renewcommand{\@enddocumenthook} }%\publisher %%%-- Macros utilisées pour le paramétrage sur le langage %-- Macros identiques en francais et english \def\pagename{p.~} \def\pagesname{p.~}%@@normalement {pp.~} \def\etalter{\ et al.} \def\Inname{} \def\inname{} \def\editornames{Eds.} \def\editorname{Ed.} \def\Volumename{Vol.~} \def\volumename{vol.~} \def\notename{Note} \def\degree{$^\circ$}%@@ % Quelques macros utiles définies dans french \def\fup#1{\raisebox{0.55ex}{\protect\small #1\kern+.17em}}% \def\fsc{\scshape}% \def\@umer#1{$^{\mathrm #1}$\kern.2em\ignorespaces}% \def\numero{n\@umer{o}}% \def\numero{n\@umer{o}}% \def\Numero{N\@umer{o}}% \def\numeros{n\@umer{o}}% \def\Numeros{N\@umer{o}}% \def\fups#1{\raisebox{0.55ex}{{\scriptsize #1}}~}% \def\ier{\fups{er}}% \def\iere{\fups{re}}% \def\ieme{\fups{e}}% \def\iers{\fups{ers}}% \def\ieres{\fups{res}}% \def\iemes{\fups{es}}% %-- Macros différentes en francais et english % Doivent être redéfinies après chaque sélection de langage \def\initialisation{% \iffrenchlang % % \AutoSpaceBeforeFDP % \def\figurename{Figure}% \def\figname{\bf figure}% \def\tablename{Tableau}% \def\tabname{tableau}% \def\programname{Programme}% \def\progname{programme}% \def\studiaRefname{Bibliographie}% \def\andname{, } \def\acknowledgementsname{Remerciements} \def\remarkname{Remarque} \def\editionname{\'edition} \def\chaptername{chapitre} \def\technicalreportname{rapport}% valeur par défaut du champ type \def\numbername{\numero}%{n∞~} \def\Numbername{\Numero}%{N∞~} \def\ofname{de} \def\guilo{´~}% C. Queinnec \def\guilf{~ª}% C. Queinnec \def\Jan{janvier} \def\Feb{f\'evrier} \def\Mar{mars} \def\Apr{avril} \def\May{mai} \def\Jun{juin} \def\Jul{juillet} \def\Aug{ao\^ut} \def\Sep{septembre} \def\Oct{octobre} \def\Nov{novembre} \def\Dec{d\'ecembre} \else \def\figurename{Figure}% \def\figname{\bf figure}% \def\tablename{Table}% \def\tabname{table}% \def\programname{Program}% \def\progname{program}% \def\studiaRefname{References}% \def\andname{, } \def\acknowledgementsname{Acknowledgements} \def\remarkname{Remark} \def\editionname{edition} \def\chaptername{chapter} \def\technicalreportname{report }% valeur par défaut du champ type \def\numbername{num.~} \def\Numbername{Num.~} \def\ofname{of} \def\guilo{``} \def\guilf{''} \def\Jan{Jan. } \def\Feb{Feb. } \def\Mar{March } \def\Apr{April } \def\May{May } \def\Jun{June } \def\Jul{Jul. } \def\Aug{Aug. } \def\Sep{Sep. } \def\Oct{Oct. } \def\Nov{Nov. } \def\Dec{Dec. } \fi }%\initialisation \def\@mkstudia{% \mkstudialist \initialisation % dépend du langage } \AtBeginDocument{% \iffrenchlang % % \selectlanguage{frenchb}% \selectlanguage{french}% \else % \selectlanguage{english}% \fi% } %EOF %%%%%%%%%%%%%%%%%% Doc %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % version commune pour les articles de revue et d'actes studia % Seule différence entre les deux types d'article : % en version finale, utiliser \journal pour un article de revue et % \proceedings pour un article de conférence. % % Documentation résumée %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Toutes les commandes LaTex2e s'utilisent normalement y compris \maketitle remplacée % par \maketitlepage. Pour connaître les différentes commandes de définition de la % première page, IL SUFFIT DE COMMENCER UN ARTICLE PAR \maketitlepage : % les commandes à utiliser avant \maketitlepage s'afficheront par défaut. %%% Utilisation des options: % Langue utilisée pour l'article (français ou anglais) %\documentclass{studia-Hermann} % article en français avec le package babel %\documentclass[english]{studia-Hermann} % article en anglais (avec babel) % Numérotation des pages: par défaut, les pages sont numérotées avec les en-têtes % construits à partir des commandes \title, \submitted, \journal ou \proceedings % La signature de l'article apparait en bas de la 1ere page: elle est % construite par \submitted, \journal ou \proceedings % Option empty: ni signature, ni en-tête, ni pied de page... % Exemple: %\documentclass[empty]{studia-Hermann}\header{LMO'99} % remise finale art. français % Option nofirstpagebreak: pas de saut de page sur la page de titre % (non standard, pour certaines revues seulement) % Option cropmarks: tracé des contours de page et de corps du texte % (utile pour visualiser les problèmes éventuels de débordement de ligne ou page, % ne s'utilise qu'en mise au point finale). % Exemple: %\documentclass[cropmarks]{studia-Hermann} % article en français avec contour de page % Option fleqn: formules mathématiques cadrées à 2cm du bord gauche du corps du texte % (par défaut les formules sont centrées) Exemple: %\documentclass[fleqn]{studia-Hermann} % article en français avec formules à gauche % Mode d'emploi détaillé: % cf les fichiers doc-studia-Hermann.ltx et doc-studia-Hermann.ps %%% Liste des commandes utilisateur % Commandes spécifiques au style, avec nb d'arguments entre crochets % \title[1] % \subtitle[1] % \author[1] % \andauthor % \fup % \address[1] % \abstract[1] % \motscles[1] % \keywords[1] % \resume[1] % \maketitlepage % \nofirstpagebreak % \firstpagebreak %---- % \submitted[2] % \journal[8] % \proceedings[3] %---- % \acknowledgements[1] % \logbook[3] % \andeditor % \biography[2] %%% Utilitaires % \remark[1] % \note[1] % \bibliography % \CropMarksOn % \CropMarksOff % \eqncont % \delaynewpage[1] % \forcenewpage % \newenvironment{editorial}[5] % Commandes ou Environnements Latex redefinis % \rmdefault % \sfdefault % \ttdefault % \maketitle % alias \maketitlepage % \thesection % \section % \thesubsection % \subsection % \thesubsubsection % \subsubsection % \theparagraph % \paragraph % \footnotesize % \footnoterule % \newblock % \renewenvironment{thebibliography}[1] % \renewenvironment{itemize} % \renewenvironment{enumerate} % \newenvironment{ITEMIZE} % \renewenvironment{figure} % Compteurs entiers ou variables décimales Latex redéfinis % section: 0 % page: 1 % secnumdepth: 4 % topnumber: 2 % nb max de fig. en haut % bottomnumber: 1 % nb max de fig. en bas % totalnumber: 3 % nb max de fig. par page % \topfraction : 1 % fraction remplissage haut % \bottomfraction : 1 % fraction remplissage bas % \textfraction : 0 % fraction remplissage texte / page % \floatpagefraction: 0.8 % fraction remplissage floatpage % Fontes utilisables (utilisation rare) % \FonteTexte % \FonteEnTete % \FonteRubrique % \FonteSignature % \FonteTitre % \FonteSousTitre % \FonteAuteur % \FonteResume % \FonteTitreResume % \FonteSectionI % \FonteSectionII % \FonteSectionIII % \FonteSectionIV % \FonteNoteBasPage % \FonteTitreLegende % \FonteCaptionName % \FonteBibliographie % Paramètres de listes (Normalement, ne pas modifier) % \mkstudialist % Pour modifier les dimensions % \labelitemi % \labelitemii % \labelitemiii % \labelitemiv % Variables utilisables % \newlength{\interligne} mlpost-0.8.2/papers/jfla2009/studia-Hermann2.cls000066400000000000000000001700211306046515300212300ustar00rootroot00000000000000% LaTeX documentclass for studia publisher : %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx %% %% %% %% %% Fichier d'essais pour rglages .cls %% %% %% %% Cette version 2 de studia-Hermann est configure pour les bibliographies " la main" %% %% %% %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx %xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx % \def\PackageName{studia-Hermann} \def\PackageVersion{1.2} \def\firstversion{03/12/2007} \def\filedate{03/12/2007} \def\docdate{03/12/2007} % %%% Prlude %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %=== Identification Part % \NeedsTeXFormat{LaTeX2e} \def\fileversion{\PackageVersion} \ProvidesClass{\PackageName}[ \filedate \space Version:\space \PackageVersion \space ] \typeout{style Latex2e pour les articles ou actes Studia, Ivan Lavalle} \ProvidesFile{\PackageName.cls}[\filedate \space Version:\space \PackageVersion] %-------------------------------------------------------------------------------------------------------------------------------------- % % Initialisation du code % %-------------------------------------------------------------------------------------------------------------------------------------- % Dfinition des variables d'option et leur valeur par dfaut % Les tests if ne comportent pas de `@' pour pouvoir tre utiliss dans les documents % En particulier \iftreatise peut tre utile \newif\iffrenchlang \frenchlangtrue % ouvrage en franais, false => in english \newif\ifcropmarks \cropmarksfalse % affichage du contour de page et de corps du texte \newif\ifemptyheaders \emptyheadersfalse % aucun entte de page, mais numrotation hors cadre \newif\iffirstbreak \firstbreaktrue % true => saut de page sur la page de titre \newif\iffleqn \fleqnfalse % true => formules mathmatiques gauche, sinon centres %-------------------------------------------------------------------------------------------------------------------------------------- % % Declaration des options % %-------------------------------------------------------------------------------------------------------------------------------------- \DeclareOption{english}{% \typeout{studia-Hermann.cls : ``english'' option}% \frenchlangfalse } % Pour caler les formules "au fer" gauche \DeclareOption{fleqn}{% \typeout{studia-Hermann.cls : ``fleqn'' option}% \PassOptionsToClass{fleqn}{article}% \fleqntrue% } % Permet de voir les limites de page et de texte \DeclareOption{cropmarks}{% \typeout{studia-Hermann.cls : ``cropmarks'' option}% \cropmarkstrue% } % Pour supprimer les enttes de page \DeclareOption{empty}{% \typeout{studia-Hermann.cls : ``empty'' option}% \emptyheaderstrue % } % Permet de grer le saut de premire page \DeclareOption{nofirstpagebreak}{% \typeout{studia-Hermann.cls : ``nofirstpagebreak'' option}% \firstbreakfalse % } \DeclareOption*{\typeout{*** Option ``\CurrentOption'' inconnue ***\\ Syntaxe : documentclass[fleqn,english,cropmarks,empty,nofirstpagebreak]{studia-Hermann}}} \PassOptionsToClass{12pt,twoside}{article} %-------------------------------------------------------------------------------------------------------------------------------------- % % Excution des options % %-------------------------------------------------------------------------------------------------------------------------------------- \ExecuteOptions{12pt} % Options par dfaut \ProcessOptions % Ɏvaluation des dclarations d'options %-------------------------------------------------------------------------------------------------------------------------------------- % % Blocs utiliss % %-------------------------------------------------------------------------------------------------------------------------------------- \LoadClass[a4paper]{article} \RequirePackage{ifthen} \RequirePackage{amsmath} \RequirePackage{amsfonts} \RequirePackage{amssymb} \RequirePackage[dvips]{graphicx} \RequirePackage[french,english]{babel} %-------------------------------------------------------------------------------------------------------------------------------------- % %%%%%%%%%%%%%%%%%%%%%%%%% Rajouts par Ivan %%%%%%%%%%%%%% % %-------------------------------------------------------------------------------------------------------------------------------------- \usepackage{latexsym} \usepackage{amsmath} \usepackage[applemac]{inputenc} \usepackage{times} \usepackage{algorithm} \usepackage{tabularx} \usepackage{framed} \usepackage{ragged2e} % ------------------------------------------------------------------------------------------- % % Utilisation ventuelle de la couleur % % o0O0o % \usepackage{color} \definecolor{rouge}{rgb}{1,0,0} \definecolor{vert}{rgb}{0,1,0} \definecolor{bleu}{rgb}{0,0,1} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %--------------------------------------------------------------------------------------------------------------------------- % Attention ! avec babel, tout appel \selectlanguage active un espacement spcial pour % les listes et redfinit les noms de certaines entits (tablename, figurename.... % Mais on peut agir \let\ORIselectlanguage\selectlanguage \gdef\selectlanguage#1{\ORIselectlanguage{#1}\@mkstudia} \def\french{\selectlanguage{frenchb}\@mkstudia} \def\english{\selectlanguage{english}\@mkstudia} %%% Fin du prlude %%% Code des Commandes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % Dans l'ordre des sections de Consignes aux auteurs (cf. http://www.editions-studia.fr) % % ``Consignes aux auteurs ...'' % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -------------------------------------------------- <2. Prsentation> --------------------------------------------------------- % Polices du corps du texte % L'encodage recommand est T1, notamment pour les guillemets franais % Mais certaines installations n'acceptent pas cet encodage ou ncessitent % trop de constructions de polices pour dvips ou xdvi : je ne l'impose pas % Il semble que les guillemets franais puissent tre obtenus par % \leftguillemets \rightguillemets mme sans l'encodage T1. % En cas de problme avec certains caractres pour certaines polices % forcer l'encodage T1 ou OT1 OU SUPPRIMER cet encodage. % - soit ici, %\usepackage[T1]{fontenc} %\usepackage[latin1]{inputenc} %\usepackage[latin]{inputenc} % - soit dans le prlude du document, par exemple avec \usepackage[T1]{fontenc} % Latex/Unix: Times romain \renewcommand{\rmdefault}{ptm} % Postscript Times \renewcommand{\sfdefault}{phv} % Postscript Helvetica \renewcommand{\ttdefault}{pcr} % Police Courier : un peu large \renewcommand{\ttdefault}{cmtt} % Police Latex tt : plus jolie et troite, \newcommand{\FonteTexte}{\normalfont\fontsize{10}{12}\selectfont} \newlength{\interligne} % Ne change pas dans ce style: quand on parle \setlength{\interligne}{12pt} % d'une ligne blanche, c'est a : 4.22mm % On peut utiliser cette commande dans le texte, par exemple % \setlength{\baselineskip}{1\interligne} pour revenir l'espacement normal \newcommand{\@espace}{\hspace*{0.5em}} % <2.1. Format> -------------------------------------------------------------- %-------------------------------------------------------------------------------------------------------------------------------- % Dimensionnements %-------------------------------------------------------------------------------------------------------------------------------- % Page %-------------------------------------------------------------------------------------------------------------------------------- % Format des pages (pour papier a4 ou letter) % Rappel : A4 = 210mm x 297 mm USLETTER = 8.5in x 11in = 215.9mm * 279.4mm % soit USLETTER = 6mm de plus dans la marge droite et 17.6mm de moins dans le bas de page \setlength{\textwidth}{120mm} % 120mm = 341pt \setlength{\textheight}{190mm} % 190mm = 540pt (45 lignes * 12pt) = 189.78mm %-------------------------------------------------------------------------------------------------------------------------------- % % Texte % %-------------------------------------------------------------------------------------------------------------------------------- % <2.1.1 Marges et Format> --------------------------------------------------- %--- Dimensions horizontales \setlength{\hoffset}{-1in} % ajuster par dvips selon imprimante % ancien \setlength{\oddsidemargin}{45mm} % pour que la marge de gauche % ancien \setlength{\evensidemargin}{45mm} % soit exactement de 45mm \setlength{\oddsidemargin}{40mm} \setlength{\evensidemargin}{40mm} \setlength{\marginparsep}{0mm} % % Largeur de la marge de droite pour papier: % - A4 : largeur papier = 210 mm => 210 - (120+45) = 45 mm % - Letter : 8.5in = 8.5*25.4mm = 215.9mm => 215.9-165 = 50.9mm %--- Dimensions verticales \setlength{\voffset}{-1in} % ajuster selon imprimante pour que la marge % au dessus du texte (page 2) soit exactement % de 53.5mm \setlength{\topmargin}{44mm} % distance bord sup feuille au haut de l'en-tte \settoheight{\headheight}{2mm} % \setlength{\headsep}{7.5mm} % % 44mm + 2mm + 7.5mm = 53.5mm (marge au dessus du texte) %--- Trac du cadre indiquant les bords du papier une fois l'article massicot % au format des revues/actes Hermann (160mm x 240mm) % Ce trac est obtenu par l'option \documentclass[cropmarks]{studia-Hermann} % (par dfaut pas de trac) et est command partir de l'en-tte (picture). % L'avantage de ce systme est de ne pas influencer la mise en page de Latex %-- Commandes utilisateur \newcommand{\CropMarksOn}{\renewcommand{\@DrawPageFrame}{\@PageFrame}} \newcommand{\CropMarksOff}{\renewcommand{\@DrawPageFrame}{}} %-- Primitives internes \newcommand{\@DrawPageFrame}{} \newcommand{\@PageFrame}{% \thinlines% \setlength{\unitlength}{1mm}% \begin{picture}(0,0)% % Les mesures sont faites partir du point de rfrence qui est pos gauche % de l'en-tte (7.5mm au dessus du texte) % Les dimensions des pages massicotes sont de 150 x 220 mm % Donc, en format A4, les bandes supprimes au dessus sont de (297-220)/2=38.5mm % => distance du coin suprieur gauche au dessus du point de rfrence: % 53.5mm -7.5mm =46mm ; 46mm-38.5mm = 7.5mm %\put(-20,17.5){\line(1,0){160}} % Ancien massicotage %\put(-20,17.5){\line(0,-1){240}} % % \put(140,17.5){\line(0,-1){240}} % % \put(-20,-222.5){\line(1,0){160}} % %-------------------------------------- Nouveau massicotage ---------------------- \put(-20,7.5){\line(1,0){160}} % Gre la ligne de massicotage suprieure \put(-15,17.5){\line(0,-1){240}} % Gre la ligne de massicotage gauche \put(135,17.5){\line(0,-1){240}} % Gre la ligne de massicotage droite \put(-20,-212.5){\line(1,0){160}} % Gre la ligne de massicotage infrieure \put(0,-7.5){\line(1,0){120}} % marque du bord suprieur du texte \put(0,-197.5){\line(1,0){120}} % 7.5+190 = 197.5mm: bas du texte \put(0,-7.7){\line(0,-1){190}} % ct gauche du texte \put(120,-7.5){\line(0,-1){190}} % ct droit du texte \end{picture}% }% \ifcropmarks \CropMarksOn \else \CropMarksOff \fi \flushbottom %-------------------------------------------------------------------------------------------------------------------------% % % % Style de la premire page % % % %-------------------------------------------------------------------------------------------------------------------------% % hauteur du texte maximum: 170mm % pied de page pour la signature, 194mm sous le point de rfrence, \newcommand{\@FonteEntete}{\normalfont\small} \newcommand{\ps@firstpage}{% % Une premire page est normalement impaire, mais on dfinit les deux... \renewcommand{\@oddhead}{\parbox{\textwidth}{\@DrawPageFrame}}% \renewcommand{\@evenhead} { \parbox{\textwidth}{\@DrawPageFrame} }% % Le pied de page ne sert normnalement que pour la signature de l'article % dont la ligne de base est 44mm du bord infrieur de la feuille A4 \setlength{\footskip}{10mm} % dist. bas du texte au bas du pied de page. % Ainsi le haut de l'entete de page et le bas % du pied de page sont tous les deux 44mm du % bord de feuille A4 (et 26.4 mm en USLetter) \ifemptyheaders \renewcommand{\@oddfoot}{}% \renewcommand{\@evenfoot}{}% \else \renewcommand{\@oddfoot}{\parbox{\textwidth}{\raggedright\VAR@SignatureArticle}}% \renewcommand{\@evenfoot}{\parbox{\textwidth}{\raggedright\VAR@SignatureArticle}}% \fi }% firstpage style %-------------------------------------------------------------------------------------------------------- % Style des pages courantes %-------------------------------------------------------------------------------------------------------- \newcommand{\ps@otherpage}{% \ifemptyheaders % Au cas o il y aurait un pied de page, celui-ci doit sortir du cadre massicot, % lequel est 25mm sous le bas du texte. Donc 25+15mm=40mm \setlength{\footskip}{40mm} % rduire 33mm pour USLETTER \renewcommand{\@evenhead}{\parbox{\textwidth}{\@DrawPageFrame}}% \renewcommand{\@oddhead}{\parbox{\textwidth}{\@DrawPageFrame}}% \renewcommand{\@evenfoot}{\@FonteEntete\thepage \hspace*{\fill}}% \renewcommand{\@oddfoot}{\hspace*{\fill}\@FonteEntete \thepage}% \else \renewcommand{\@evenhead}{% \parbox{\textwidth}{% \@DrawPageFrame\@FonteEntete\thepage\hspace{\@ESPage}\VAR@EnTeteG}}% \renewcommand{\@oddhead}{% \parbox{\textwidth}{% \@DrawPageFrame\hspace*{\fill}\@FonteEntete\VAR@EnTeteD% \hspace{\@ESPage}\thepage}}% \renewcommand{\@evenfoot}{}% \renewcommand{\@oddfoot}{}% \fi }% otherpage style \pagestyle{otherpage}% doit tre plac aprs les dfinitions prcdentes %-------------------------------------------------------------------------------------------------------- % 2.1.2. En-tte %-------------------------------------------------------------------------------------------------------- \newcommand{\FonteEnTete}{\normalfont\fontsize{9}{12}\selectfont}% Police des en-ttes \newcommand{\VAR@EnTeteG}{% \FonteEnTete% Nom de la revue ou confrence ( dfinir par \texttt{\@BS submitted ou \@BS toappear})} \newcommand{\VAR@EnTeteD}{% \FonteEnTete% Titre abrg de l'article ( dfinir par \texttt{\@BS title[titre abrg]\{titre\}})} %-------------------------------------------------------------------------------------------------------- % % 2.2 Titres et sous-titres % %-------------------------------------------------------------------------------------------------------- %-------------------------------------------------------------------------------------------------------- % % 2.2.1 Premire page de l'article % %-------------------------------------------------------------------------------------------------------- \newcommand{\nofirstpagebreak}{\firstbreakfalse} \newcommand{\firstpagebreak}{\firstbreaktrue} \newcommand{\maketitlepage}{% % \@redefinitions% \setlength{\parskip}{0pt}% \setlength{\parindent}{0pt}% \thispagestyle{firstpage}% % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % Block 1\iere page { % Sous-bloc Titre-Auteurs, adressses { \par{\FonteRubrique\hfill \VAR@rubrique \hfill} \par\vspace*{6pt}\@filet%Filet de tte de premire page ;interlignage=paisseur du filet % \par\vspace*{12pt}% \par\vspace*{6pt}% Distance du titre au filet \@Titre{\VAR@title}% + vspace de 2 lignes de 12 pts \@SousTitre{\VAR@subtitle}% + vspace de 2 lignes de 12 pts \@Auteurs{\VAR@author}% % \par\vspace*{1\interligne}% espace avant Adresse \par\vspace*{.5\interligne}% espace avant Adresse \@Adresse{\VAR@address}% \par\vspace*{1\interligne}% espace entre adresse et filet \par\@filet% \par\vspace*{2pt}% espace entre filet et le bloc } % Fin du "sous-bloc premire page", c'est ce qui m'a permis de "dcoupler" la centration des auteurs et adresses des rsum et abstract \iffrenchlang \@Resume{\VAR@resume}% \par\vspace*{3pt}% \@Abstract{\VAR@abstract}% \par\vspace*{3pt}% \@MotsCles{\VAR@motscles}% \par\vspace*{3pt}% \@KeyWords{\VAR@keywords}% \else \@Abstract{\VAR@abstract}% \par\vspace*{3pt}% \@Resume{\VAR@resume}% \par\vspace*{3pt}% \@KeyWords{\VAR@keywords}% \par\vspace*{3pt}% \@MotsCles{\VAR@motscles}% \fi \FonteTexte% \par\vspace*{4pt}% \@filet% \setcounter{section}{0}% \setcounter{footnote}{0}% } % Terminaison du "Bloc de premire page" % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \iffirstbreak \par\vspace*{\stretch{3}}\newpage% \else \par\vspace*{1\interligne} \fi % Pour viter les interfrences avec d'autres packages, il vaut mieux dfinir % les constantes suivantes aprs \begin{document}, par exemple ici. \setlength{\parindent}{5mm} % renfoncement (ou retrait) \setlength{\parskip}{6pt} % }%\maketitlepage \renewcommand{\maketitle}{\maketitlepage} \newcommand{\FonteTitreEdito}{% 18 points interlign 21.6pt (120% du corps) \rmfamily\upshape\fontsize{18}{21.6}\selectfont} \newcommand{\@Coordonnateurs}{Les Coordonnateurs} \newenvironment{editorial}[5]% % #1 rev % #2 Volume % #3 Numero % #4 Anne % #5 Prnom \textsc{Nom} des rdacteurs de l'ditorial, spars par des \\. % Exemple % \begin{editorial}{L'Objet}{6}{1}{2000}{Pascal \textsc{ANDRE}\\Roger \textsc{ROUSSEAU}} % texte de l'edito si possible sur deux pages au plus % \end{editorial} {%BEGIN \journal{#1}{#2}{#3}{#4}{-}{-}% \renewcommand{\@Coordonnateurs}{#5}% \thispagestyle{firstpage}% \renewcommand{\VAR@SignatureArticle}{}% \@shorttitle{Editorial}% \setlength{\parindent}{5mm} % renfoncement (ou retrait) \setlength{\parskip}{6pt} % conforme la version du 8/9/99 des consignes \par\vspace*{2pt}\@filet %interlignage=paisseur du filet \par\vspace*{20pt}% \begin{center}\FonteTitreEdito Editorial \end{center}% \par\vspace*{1\interligne}% \FonteTexte\itshape% }{%END \FonteTexte\upshape% \begin{flushright} \@Coordonnateurs \end{flushright} \newpage% } %-------------------------------------------------------------------------------------------------------% % % % 2.2.1.1. Titre et sous-titre % % % %-------------------------------------------------------------------------------------------------------% \renewcommand{\title}[2][]{ %usage: \title[shorttitle]{title} \ifthenelse{\equal{#1}{}}{%Y \@shorttitle{#2}% }{% \@shorttitle{#1}% } \renewcommand{\VAR@title}{#2} } %-------------------------------------------------------------------------------------------------------% % % % Titre Courant (ou abrg) pour les en-ttes de pages impaires % % % %-------------------------------------------------------------------------------------------------------% \newcommand{\VAR@TitreAbrege}{Titre abrg : % dfinir par \texttt{\@backslashchar shorttitle\{...\}}} \newsavebox{\@shtitle} \newcommand{\@shorttitle}[1]{% % #1: Titre abrg de l'article (moins de 40 caractres, pour en-tte) % test de la largeur < 55mm \sbox{\@shtitle}{\@FonteEntete #1}% \ifthenelse{\lengthtest{\wd\@shtitle > 55mm}}{% \@latex@error{short title defined by \@backslashchar title[short]{long} too long: (55mm max)}\@eha }{} \renewcommand{\VAR@TitreAbrege}{#1} } \def\subtitle#1{\renewcommand{\VAR@subtitle}{#1}} \def\author#1{\renewcommand{\VAR@author}{#1}} \def\address#1{\renewcommand{\VAR@address}{#1}} \def\abstract#1{\renewcommand{\VAR@abstract}{#1}} \def\motscles#1{\renewcommand{\VAR@motscles}{#1}} \def\keywords#1{\renewcommand{\VAR@keywords}{#1}} \def\resume#1{\renewcommand{\VAR@resume}{#1}} %-- Primitives internes \def\@BS{\symbol{"5C}} \def\@ARGS{\{\ldots\}} \def\@ARG#1{\{\normalfont\textit{#1}\}} \newcommand{\@filet}{\rule{\linewidth}{0.20pt}} %--- Signature et en-ttes de l'article : % peuvent tre dfinis par \submitted, \journal ou \proceedings \newcommand{\FonteSignature}{\normalfont\fontsize{9pt}{10.8pt}\selectfont} \newcommand{\FonteRubrique}{% % \rmfamily\mdseries\scshape\fontsize{14pt}{16.8pt}\selectfont} \rmfamily\mdseries\fontsize{12pt}{14.4pt}\selectfont} \newcommand{\VAR@rubrique}{} \newcommand{\VAR@SignatureArticle}{} \newcommand{\VAR@NomRevue}{} \newcommand{\VAR@VolumeRevue}{} \newcommand{\VAR@NumeroRevue}{} \newcommand{\VAR@AnneeRevue}{} \newlength{\@ESPage}\setlength{\@ESPage}{4mm}% 5 espaces blancs \newcommand{\VAR@Pages}{} \newcommand{\VAR@NumeroSoumission}{} \newcommand{\VAR@NomActes}{} \newcommand{\VAR@TypeArticle}{revue} %Ancienne commande \iffalse \newcommand{\journal}[7][]{% pour article de revue % #1 [rubrique] % #2 {revue} % #3 {vol} % #4 {num} % #5 {annee} % #6 {1ere p.} % #7 {dern. page} \renewcommand{\VAR@TypeArticle}{revue}% \renewcommand{\VAR@rubrique}{\uppercase{#1}} \renewcommand{\VAR@NomRevue}{#2} \renewcommand{\VAR@VolumeRevue}{#3} \renewcommand{\VAR@NumeroRevue}{#4} \renewcommand{\VAR@AnneeRevue}{#5} % \renewcommand{\VAR@Pages}{#6} % \ifthenelse{\equal{\VAR@Pages}{-}}{%1re page inconnue % \setcounter{page}{1} % on augmente l'espace aprs numro page pour permettre l'diteur de % surcharger le bon numro % \setlength{\@ESPage}{6mm} % \renewcommand{\VAR@Pages}{} % } % {%1ere page donne % \setcounter{page}{#6} % \renewcommand{\VAR@Pages}{, pages #6\ \`a #7} % } \ifthenelse{\equal{\VAR@NumeroRevue}{\LMO}}{%signature spciale pour LMO \renewcommand{\VAR@SignatureArticle}{\FonteSignature % \VAR@NomRevue\ -- \VAR@VolumeRevue/\VAR@AnneeRevue. % \VAR@NumeroRevue'\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue\ -- % \VAR@VolumeRevue/\VAR@AnneeRevue. \VAR@NumeroRevue'\VAR@AnneeRevue} }{\ifthenelse{\equal{\VAR@NomRevue}{\LOBJET}}{% % spcial pour la revue L'objet : sans mot Volume, sans numro \renewcommand{\VAR@SignatureArticle}{\FonteSignature% \VAR@NomRevue\ -- \VAR@VolumeRevue/\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue\ -- % \VAR@VolumeRevue/\VAR@AnneeRevue.} }{% Autres revues \ifthenelse{\equal{\VAR@NumeroRevue}{}}{%pas de numro revue \renewcommand{\VAR@SignatureArticle}{\FonteSignature % \VAR@NomRevue -- \VAR@VolumeRevue/\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue. % Volume \VAR@VolumeRevue/\VAR@AnneeRevue} }{% numro de revue prsent, prsentation normale, style TSI : \renewcommand{\VAR@SignatureArticle}{\FonteSignature % \VAR@NomRevue. Volume \VAR@VolumeRevue\ -- n$^\circ$ \VAR@NumeroRevue/\VAR@AnneeRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue. % Volume \VAR@VolumeRevue\ -- n$^\circ$ \VAR@NumeroRevue/\VAR@AnneeRevue} }}} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} }%\journal #\fi \newcommand{\journal}[3]{% pour article de revue % #1 {revue. Volume 19 -- n 1/2005,} % #2 {1ere p.} % #3 {dern. page} \renewcommand{\VAR@TypeArticle}{revue}% % \renewcommand{\VAR@rubrique}{\uppercase{#1}} \renewcommand{\VAR@NomRevue}{#1} % \renewcommand{\VAR@VolumeRevue}{#3} % \renewcommand{\VAR@NumeroRevue}{#4} % \renewcommand{\VAR@AnneeRevue}{#5} \renewcommand{\VAR@Pages}{#2} \ifthenelse{\equal{\VAR@Pages}{-}}{%1re page inconnue \setcounter{page}{1} % on augmente l'espace aprs numro page pour permettre l'diteur de % surcharger le bon numro \setlength{\@ESPage}{6mm} \renewcommand{\VAR@Pages}{} }{%1ere page donne \setcounter{page}{#2} \renewcommand{\VAR@Pages}{, pages #2\ \`a #3} } \renewcommand{\VAR@SignatureArticle}{\FonteSignature\VAR@NomRevue\VAR@Pages} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomRevue} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} }%\journal \newcommand{\proceedings}[2]{% pour article d'actes de confrence % usage: {#1} = nom de la confrence % {#2} = numro de premire page \renewcommand{\VAR@TypeArticle}{conference}% \renewcommand{\VAR@NomActes}{#1}% \renewcommand{\VAR@Pages}{#2}% \ifthenelse{\equal{\VAR@Pages}{-}}{%1re page inconnue \setcounter{page}{1} % on augmente l'espace aprs numro page pour permettre l'diteur de % surcharger le bon numro \setlength{\@ESPage}{6mm} }{%1ere page donne \setcounter{page}{#2} } \renewcommand{\VAR@SignatureArticle}{} \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NomActes} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} } \newcommand{\submitted}[3][\today]{% Commun Actes ou Revue % usage: [#1] = date (par dfaut \today) % {#2} = nom revue ou confrence % {#3} = numro de soumission (le plus souvent de 1 3). \renewcommand{\VAR@NomRevue}{#2}% \renewcommand{\VAR@NumeroSoumission}{% \ifthenelse{\equal{#3}{1}}{1\iere~}{#3\ieme~}}% \renewcommand{\VAR@SignatureArticle}{% \FonteSignature\raggedright \VAR@NumeroSoumission soumission \`a \textit{\VAR@NomRevue}, le #1 } \renewcommand{\VAR@EnTeteG}{\FonteEnTete\VAR@NumeroSoumission soumission \`a \textit{\VAR@NomRevue}} \renewcommand{\VAR@EnTeteD}{\FonteEnTete\VAR@TitreAbrege} } %-------------------------------------------------------------------------------------------------------------------------------------- % % Noms prdfinis de revues studia Science Publications % %-------------------------------------------------------------------------------------------------------------------------------------- %--------------------------------------------------------------------------------------------------------------------------------------% \newcommand{\SCU}{Studia Complexica Universalis} \newcommand{\SIU}{Studia Informatica Universalis} %--------------------------------------------------------------------------------------------------------------------------------------% %--- Titre de l'article \newcommand{\VAR@title}{Titre de l'article% {\par\renewcommand{\baselinestretch}{0.66}\par\FonteTexte%@@ \textit{A dfinir par la commande \texttt{\upshape\@BS title[} titre abrg \texttt{\upshape]\{} titre complet \texttt{\upshape\}} sur une ou deux lignes coupes par \@BS\@BS.\\ Le sous-titre ventuel est dfini sur une ou deux lignes par la commande\\ \texttt{\upshape\@BS subtitle\{} sous-titre complet \texttt{\upshape\}}.}}} \newcommand{\FonteTitre}{% 18 points interlign 21.6pt (120% du corps) % \rmfamily\bfseries\upshape\fontsize{18}{21.6}\selectfont} \rmfamily\bfseries\upshape\fontsize{18}{22}\selectfont} \newcommand{\@Titre}[1]{{% % #1: Titre complet de l'article (peut incorporer des `\\') %\setlength{\parskip}{0pt}\flushleft% \setlength{\parskip}{0pt}\center% \FonteTitre #1% \par\vspace*{10pt}% }} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Modifi %%%%%%%%%%%%% %--- Sous-Titre de l'article \newcommand{\VAR@subtitle}{} \newcommand{\FonteSousTitre}{% 14pt interlign 16.8pt (120% du corps) % \rmfamily\bfseries\upshape\fontsize{14}{16.8}\selectfont} \rmfamily\bfseries\upshape\fontsize{14}{17}\selectfont} \newcommand{\@SousTitre}[1]{{% % #1: Sous-titre de l'article dans une police plus petite (peut incorporer des `\\') \setlength{\parskip}{0pt}% \FonteSousTitre #1% % \par\vspace*{21.2pt}% 2 lignes = 24 pts - (16.8-14) \par\vspace*{2pt}% }} %------------------------------------------------------------------------------------------------------------ % Auteurs %------------------------------------------------------------------------------------------------------------ \newcommand{\FonteAuteur}{% 12pt interlign 14.4pt (120% du corps) \rmfamily\bfseries\upshape\fontsize{12}{14.4}\selectfont} \newcommand{\VAR@author}{% Auteur(s)\\ {\FonteTexte\textit{A dfinir par la commande \texttt{\upshape\@BS author\@ARGS}. Dans le cas de plusieurs auteurs, sparer chaque auteur par \texttt{\upshape\@BS andauthor}. Dans le cas d'adresses diffrentes des auteurs, indexer chaque auteur avec des astrisques comme \fup{*} ou \fup{**} obtenues par \texttt{\upshape\@BS fup\{*\}} ou \texttt{\upshape\@BS fup\{**\}}. }}} \newcommand{\@Auteurs}[1]{\center{% L j'ai rajout \center pour centrer auteurs et adresses mais a \FonteAuteur #1% % } } \newcommand{\andauthor}{% % Tiret long maigre de sparation entre deux noms d'auteurs {\FonteTexte\mdseries --- }} %--- Adresse(s) de(s) auteur(s) \newcommand{\FonteAdresse}{\rmfamily\mdseries\itshape\fontsize{10}{12}\selectfont} \newcommand{\VAR@address}{Adresse :\\ {\FonteTexte\textit A dfinir sur plusieurs lignes par la commande \texttt{\upshape\@BS address\@ARGS}.\\ Email sur la dernire ligne.\\ Dans le cas d'adresses diffrentes des auteurs, indexer chaque auteur avec des astrisques comme \fup{*} ou \fup{**} obtenues par \texttt{\upshape\@BS fup\{*\}} ou \texttt{\upshape\@BS fup\{**\}}.\\ Voir aussi <<~Consignes aux auteurs~>> }} \newcommand{\@Adresse}[1]{\FonteAdresse #1} %--- Rsum et Abstract \newcommand{\FonteResume}{\rmfamily\mdseries\itshape\fontsize{9}{11}\selectfont} % Studia demande des petites capitales italiques postscript % Comme cette police n'existe pas sous Unix, % on utilise l'italique de Times en utilisant des capitales rduites de 2 points. % Si un utilisateur dispose d'une police en petites capitales italiques adapte % Times, il peut facilement faire l'adaptation. \newcommand{\FonteTitreResume}{% % \rmfamily\mdseries\itshape\fontsize{7}{11}\selectfont} \rmfamily\mdseries\itshape\fontsize{9}{10}\selectfont} \newcommand{\VAR@resume}{% {\FonteTexte\textit{A dfinir par la commande \texttt{\upshape\@BS resume\@ARGS}}}} \newcommand{\@TitreResume}[2]{\FonteTitreResume \noindent #1#2\FonteResume} \newcommand{\@Resume}[1]{{\french\@TitreResume{\bf R\'ESUM\'E}{.} #1}} %--- Abstract \newcommand{\VAR@abstract}{% {\FonteTexte\textit{A dfinir par la commande \texttt{\upshape\@BS abstract\@ARGS}}}} \newcommand{\@Abstract}[1]{{\english\@TitreResume{\bf ABSTRACT}{.} #1}} %--- Mots-cls \newcommand{\VAR@motscles}{% {\FonteTexte\textit{A dfinir par la commande \texttt{\upshape\@BS motscles\@ARGS}}}} \newcommand{\@MotsCles}[1]{{\french\@TitreResume{\bf MOTS-CL\'ES}{~:} #1}} %--- Keyswords \newcommand{\VAR@keywords}{% {\FonteTexte\textit{A dfinir par la commande \texttt{\upshape\@BS keywords\@ARGS}}}} \newcommand{\@KeyWords}[1]{{\english\@TitreResume{\bf KEYWORDS}{:} #1}} % <2.2.2 Titre des paragraphes ou titre d' inter (sections)>---------------- % cf \Latex Companion 2.3 pp 18-31 % Les dfinitions suivantes visent donner la police particulire % exige par studia uniquement dans les titres de section et non pas dans les % rfrences. Ainsi, 2.2. apparatra en gras droit dans le titre et en % police normale dans les rfrences par \label ... \ref. % Si l'on veut la mme prsentation dans les rfrences de sections, % il faut tout simplement incorporer la dfinition voulue dans celle % de \thesection ... \thesubsection % On numrote jusqu' la section de niveau 4 \setcounter{secnumdepth}{4} % Pour les titres de section sur plusieurs lignes, Hermann ne veut pas d'indentation \def\@hangfrom#1{% \setbox\@tempboxa\hbox{{#1}}% % \hangindent \wd\@tempboxa\noindent\box\@tempboxa %% ORIGINAL de latex.ltx \hangindent \wd 0 \noindent\box\@tempboxa %% MODIF } % Attention : les dimensions des interlignes before et after skip % doivent tenir compte du parskip qui est de 6pts et qui s'ajoute aux valeurs % indiques %--- Niveau 1: section : gras, beforeskip = 2 lignes, afterskip = 1 ligne \newcommand{\FonteSectionI}{\normalsize\normalfont\bfseries\raggedright}% \renewcommand{\thesection}{\arabic{section}}% % Il faut enlever le parskip de 6pts aux valeurs des skips (2 lignes=24-6=18pts...) \renewcommand{\section}{% \renewcommand{\@seccntformat}[1]{\thesection.\hspace{0.5em}}% \@startsection{section}% % nom de l'inter {1}% % niveau de l'inter {0pt}% % l'indentation du titre et du texte suivant {18pt plus 2pt minus 2pt}% beforeskip {6pt plus 1pt minus 1 pt}% afterskip {\FonteSectionI}% % style } %--- Niveau 2: sous-section : gras+ital, beforeskip = 2 lignes, afterskip = 1 ligne \newcommand{\FonteSectionII}{\normalsize\normalfont\bfseries\itshape\raggedright}% \renewcommand{\thesubsection}{\thesection.\arabic{subsection}}% \renewcommand{\subsection}{% \renewcommand{\@seccntformat}[1]% {{\normalsize\normalfont\bfseries\thesubsection.\hspace{0.5em}}}% \@startsection% {subsection}% % nom de l'inter {2}% % niveau de l'inter {0pt}% % l'indentation du titre et du texte suivant {18pt plus 2 pt minus 1pt}% beforeskip {6pt plus 1pt minus 1pt} %afterskip {\FonteSectionII}}% % style %--- Niveau 3: sous-sous-section : italique, beforeskip=1 lignes, afterskip=1 ligne \newcommand{\FonteSectionIII}{\normalsize\normalfont\itshape\raggedright}% \renewcommand{\thesubsubsection}{\thesubsection.\arabic{subsubsection}}% \renewcommand{\subsubsection}{% \renewcommand{\@seccntformat}[1]{% {\normalsize\normalfont\thesubsubsection.\hspace{0.5em}}}% \@startsection% {subsubsection}% % nom de l'inter {3}% % niveau de l'inter {0mm}% % l'indentation du titre et du texte suivant {6pt plus 1pt minus 1pt} % beforeskip {0.1pt}% % afterskip (0pt supprimerait le passage la ligne) {\FonteSectionIII}}% % style %--- Niveau 4: paragraphes: police normale, beforeskip=1 ligne, afterskip=1 ligne \newcommand{\FonteSectionIV}{\normalsize\normalfont\raggedright}% \renewcommand{\theparagraph}{\thesubsubsection.\arabic{paragraph}}% \renewcommand{\paragraph}{% \renewcommand{\@seccntformat}[1]{% {\normalsize\normalfont\theparagraph.\hspace{0.5em}}}% \@startsection% {paragraph}% % nom de l'inter {4}% % niveau de l'inter {0mm}% % l'indentation du titre et du texte suivant {6pt plus 1pt minus 1 pt}% beforeskip {0.1pt}% % afterskip (0pt supprimerait le passage la ligne) {\FonteSectionIV}}% % style % 2.3 Alinas % Disable single lines at the start of a paragraph \clubpenalty = 10000 % Disable single lines at the end of a paragraph \widowpenalty = 10000 \displaywidowpenalty = 10000 \sloppy \raggedbottom % 2.4 Notes de bas de page % corps 9pt/11pt, numrotation dcimale % spares du texte par 1 ligne blanche % filet maigre de 2.5 cm \newcommand{\FonteNoteBasPage}{\fontsize{9}{10.8}\selectfont\normalfont} \renewcommand{\footnotesize}{\FonteNoteBasPage} \addtolength{\skip\footins}{6pt} % = 12pt = 1 ligne avant le filet \renewcommand{\footnoterule}{% % Redfinition du filet de notes de bas de page. % Doit avoit une hauteur totale virtuelle nulle (cf Latex Companion p. 72) \par\vspace*{-12.3pt}% Hauteur totale => donnera une hauteur virtuelle nulle \noindent\rule{2.5cm}{0.25pt}\vspace*{6pt} % => hauteur totale 9.3pt % Hauteur espace sous filet = 6pt } \setlength{\footnotesep}{2pt} % Espace vertical avant chaque note (strut) \newcommand{\@Myfnmark}{% Redfinit la marque de footnote comme un indice % french.sty redfinit btement \@makefntext => donc j'utilise une autre macro. \mbox{$\arabic{footnote}$. }% } \renewcommand{\@makefntext}[1]{% \noindent\@Myfnmark#1% }% \def\@thefnmark{\normalsize\arabic{footnote}} % %%% 2.6 Formules %%% % %--------------------------------------------------------------------------------------------------------------------------------------% % En mode standard, les modes equation, eqnarray et eqnarray* % fournissent bien une ligne blanche au dessus et au dessous et la numerotation % colle sur la marge de droite. % La seule adaptation est la numrotation [n] au lieu de (n). %\renewcommand{\@eqnnum}{\reset@font\rmfamily [\theequation]} %\renewcommand{\tagform@}[1]{\reset@font\rmfamily [#1]} % pour align %%%%%% retour au mode standard %%%%%%%%%%%%%%%%%%%%%%% % Dfinition des espaces avec l'option fleqn : % L'option fleqn (\documentclass[fleqn]...) place les formules indentes % gauche. Par dfaut, les formules sont centres. \iffleqn %\setlength{\topsep}{1\baselineskip} % espace supplm. au dessus/dessous des formules. \setlength{\mathindent}{10mm} % indentation des formules \fi % Dfinition des espaces sans l'option fleqn : \setlength{\jot}{0.5\baselineskip} % espace entre les lignes de eqnarray \setlength{\abovedisplayskip}{0mm} % espace supplmentaire au dessus des longues formules \setlength{\abovedisplayshortskip}{0mm} % idem, formules courtes \setlength{\belowdisplayskip}{0mm} % espace supplmentaire au dessous des longues formules \setlength{\belowdisplayshortskip}{0mm} % idem, formules courtes %--- Utilitaires facultatifs % Utiliser la commande \eqncont pour terminer une ligne de formule % sur plusieurs lignes : supprime la numrotation + espace vertical plus serr. \newcommand{\eqncont}{\nonumber \\[0\baselineskip]} %%% Retardement du pagebreak % Pour retarder le passage automatique la page suivante de 1 ou 2 lignes, % utiliser le couple de commandes \delaynewpage{nb lignes} ... \forcenewpage % Attention! cette technique est du bricolage, mais cependant indispensable % pour une prsentation optimale d'un document. (indique par Lamport). % IL NE FAUT L'EMPLOYER QUE TOUT LA FIN, JUSTE AVANT L'IMPRESSION FINALE. % En principe ne pas retarder de plus de 2 lignes ! \newcommand{\delaynewpage}[1]{\enlargethispage{#1\baselineskip}} % utiliser sur la page allonger, un endroit bien visible % avant le premier paragraphe ou la figure faire tenir sur la page. % Provoque une descente des notes de bas de page s'il y en a ! \newcommand{\forcenewpage}{\pagebreak\noindent} % utiliser l'endroit prcis o la coupure doit tre force. % on peut placer cette commande en dbut de ligne, avec suite du texte % sur la ligne suivante pour faciliter son reprage % Listes -------------------------------------------------------------------------------------------------- % Espaces communs aux listes numrotes (enumerate) ou non (itemize) % Attention !!! Ces espacements ne peuvent tre effectifs que si Babel ne les redfinit % pas dans \@trivlist, comme il tente de l'imposer. Il faut ABSOLUMENT % excuter \bbl@nonfrenchlistspacing avant le dbut du document (\AtBeginDocument). \def\mkstudialist{% \gdef\itemize{\studiaitemize}\gdef\enditemize{\endstudiaitemize}% \gdef\enumerate{\studiaenumerate}\gdef\endenumerate{\endstudiaenumerate}% } \newcommand{\studiaItemizeSpacing}{% % espacements horizontaux \leftmargin=0pt \labelsep=1mm \ifnum \@itemdepth < 2 % niveau 0 ou 1 \setlength{\itemindent}{\itemindenti} \listparindent=5mm \else % niveau 2 \itemindent=\itemindentii \listparindent=10mm \fi \labelwidth=0pt \rightmargin=0pt % espacements verticaux des listes \itemsep=0pt \topsep=0pt \parskip=6pt \partopsep=0pt \parsep=3pt % pnalits \sloppy% \widowpenalty4000%ligne isole en dbut de page \clubpenalty4000%ligne isole la fin d'une page } \newcommand{\displaylistdimen}{ itemdepth: \the\@itemdepth ;\\ topsep: \the\topsep ;\\ itemsep: \the\itemsep ;\\ parskip: \the\parskip ;\\ partopsep: \the\partopsep ;\\ parsep: \the\parsep. } % Listes non numrotes (itemize) ------------------------------------------------------------------------- \newlength{\labelwidthi} % largeur de la bote contenant le retrait de 5mm + tiret moyen \settowidth{\labelwidthi}{--} % environ 2mm, tiret moyen \addtolength{\labelwidthi}{5mm} % retrait + largeur du tiret moyen, environ 7mm \newlength{\itemindenti} % dcalage du texte de 1re ligne depuis marge gauche \setlength{\itemindenti}{\labelwidthi} % = labelwidthi \addtolength{\itemindenti}{1mm} % + labelsep \newlength{\labelwidthii} % largeur de la bote contenant le retrait de 10mm + tiret court \settowidth{\labelwidthii}{-} % environ 1mm, tiret court \addtolength{\labelwidthii}{10mm} % retrait + largeur du tiret court, environ 11mm \newlength{\itemindentii} % dcalage du texte de 1re ligne depuis marge gauche \setlength{\itemindentii}{\labelwidthii} % = labelwidthii \addtolength{\itemindentii}{1mm} % + labelsep \newenvironment{studiaitemize}{% liste deux niveaux seulement \ifnum \@itemdepth > 1 \@toodeep % ici, \@itemdepth = niveau -1 \else% \renewcommand{\labelitemi}{{\makebox[\labelwidthi][r]{--}}}% \renewcommand{\labelitemii}{{\makebox[\labelwidthii][r]{-}}}% \advance\@itemdepth \@ne% \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% \begin{list}% {\csname\@itemitem\endcsname}% {\def\makelabel##1{\llap{##1}}% ##1 signifie arg 1 de list et non de studiaitemize % dfinir les espaces ici et nulle part ailleursn \studiaItemizeSpacing % }%\item \displaylistdimen \fi}{\end{list}}% % Listes numrotes --------------------------------------------------------------------------------------- \newlength{\enumwidthi} % largeur de la bote contenant le retrait de 5mm + n. \settowidth{\enumwidthi}{5)} % environ 2mm, chiffre le plus large \addtolength{\enumwidthi}{5mm} % retrait + largeur du tiret moyen, environ 7mm \newlength{\enumindenti} % dcalage du texte de 1re ligne depuis marge gauche \setlength{\enumindenti}{\enumwidthi} % = enumwidthi \addtolength{\enumindenti}{1mm} % + enumsep \newlength{\enumwidthii} % largeur de la bote contenant le retrait de 10mm + tiret court \settowidth{\enumwidthii}{b)} % environ 1mm, tiret court \addtolength{\enumwidthii}{10mm} % retrait + largeur du tiret court, environ 11mm \newlength{\enumindentii} % dcalage du texte de 1re ligne depuis marge gauche \setlength{\enumindentii}{\enumwidthii} % = enumwidthii \addtolength{\enumindentii}{1mm} % + enumsep \newenvironment{studiaenumerate}{% enumration un niveau \ifnum \@itemdepth >1 \@toodeep \else% \advance\@enumdepth \@ne% \advance\@itemdepth \@ne% \edef\@enumctr{enum\romannumeral\the\@enumdepth}% \begin{list}% {\csname label\@enumctr\endcsname}% {% \usecounter{\@enumctr}% \def\makelabel##1{\llap{##1}}% ##1 signifie arg 1 de list et non de studiaenumerate % dfinir les espaces horizontaux ici \studiaItemizeSpacing% \ifnum \@itemdepth =1 \setlength{\itemindent}{\enumindenti} \else \setlength{\itemindent}{\enumindentii} \fi \renewcommand{\labelenumi}{{\makebox[\labelwidthi][r]{\arabic{enumi})}}} \renewcommand{\labelenumii}{{\makebox[\labelwidthii][r]{\alph{enumii})}}}% } \fi}{\end{list}} %%%%%%%%%%%% OLD %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \def\ITEMIZE{% liste 3 niveaux: labelitemi=``---'' \ifnum \@itemdepth >3 \@toodeep% \else% \renewcommand{\labelitemi}{{---}}% \renewcommand{\labelitemii}{\@labelindent{--}}% \renewcommand{\labelitemiii}{\@labelindent\@labelindent{-}}% \advance\@itemdepth \@ne% \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% \list% {\csname\@itemitem\endcsname}% {% \renewcommand{\@curlabel}{\csname\@itemitem\endcsname}% \def\makelabel##1{\llap{##1}}% \mkstudialist% }% \fi% } \let\endITEMIZE =\endlist % Redfinition de quote pour rduire l'espace vertical 6 pts \let\quoteORI\quote \let\endquoteORI\endquote \renewenvironment{quote}{% \par\vspace{-6pt}% \begin{quoteORI}% }{% \end{quoteORI}% \par\vspace{-6pt}% } %<2.8 Remarques ou notes> ----------------------------------------------------- %\newcommand{\remark}[1]{{\setlength{\parskip}{0pt}% % \par\noindent\textsc{\remarkname}.\ ---\ #1\\}} \newcommand{\note}[1]{{\setlength{\parskip}{0pt}% \par\noindent\textsc{\notename}.\ ---\ #1\\}} %< 2.8 bis Remarques francise > -------------------------------------- \newcommand{\remarque}[1]{{\setlength{\parskip}{0pt}% \par\noindent\textsc{\remarkname}.\ ---\ #1\\}} %<2.9 Typographie> ------------------------------------------------------------ %<2.10 acknowledgements> --------------------------------------------------------- \newcommand{\acknowledgements}[1]{{ \setlength{\parskip}{0pt}% \par\vspace{2\interligne}\noindent% \FonteTexte \acknowledgementsname% \nopagebreak[4]% \par\vspace{1\interligne}#1% }} %< 2.11 Remerciements > -------------------------------------------------------- % J'ai francis le commande ci-dessus, acknowledgement tant un mot barbare manipuler pour des % frenchies --------------------------------------------------------------------------- \newcommand{\remerciements}[1]{{ \setlength{\parskip}{0pt}% \par\vspace{2\interligne}\noindent% \FonteTexte \acknowledgementsname% \nopagebreak[4]% \par\vspace{1\interligne}#1% }} %======================= Biblio la main ======================================= % Code import du package Harvard.sty pour obtenir des citations bibliographiques du style (Machin, 2001) %<2.13 Biographie> ---------------------------------------------------------------------- % Il faut 2 lignes au dessus de la premire biographie et 1 ligne % de sparation entre les biographies. \newcommand{\@fonteBiographie}{% \rmfamily\mdseries\itshape\fontsize{9}{11}\selectfont} \newcommand{\@firstbiography}{yes} \newcommand{\biography}[2]{ % #1 = Nom de l'auteur, % #2 = biographie enchane derrire le nom d'auteur, typiquement % est chercheur au laboratoire... \ifthenelse{\equal{\@firstbiography}{yes}}{% premire biographie \renewcommand{\@firstbiography}{no}% \par\vspace{18pt}\noindent% + 6pt de \parskip }{% biographies suivantes \par\vspace{6pt}\noindent% + 6pt de \parskip }% {\@fonteBiographie \textbf{#1} #2 }} % <3. Remise des articles> --------------------------------------------------- % <3.1 Journal de bord> ------------------------------------------------------ \newcommand{\andeditor}{% mot `et' en police normale {{\FonteTexte et\ }}} \newcommand{\logbook}[3]{{% pour revues seulement % #1: date rception % #2: date rvision % #3: rdacteur responsable \setlength{\parskip}{0pt}% \par\vspace{1\interligne}% \begin{flushright}% Article reu le #1.\\ Version rvise le #2.\\ Rdacteur responsable~: \textsc{#3} \end{flushright}% }} % <3.2 Annexe pour le service de fabrication> ------------------------------------ \newcommand{\adressestudia}{ \begin{flushright} {\setlength{\parsep}{0mm} \fbox{\parbox{70mm}{ \begin{flushright} \textsc{Service \'Editorial -- Studia Universalis}\\ 41 rue Gay Lussac, 75005 Paris\\ Tl : 01-44-10-84/83\\ mel : contact@complexica.net\\ Serveur web : http://studia.complexica.net \end{flushright} }}} \end{flushright}} \newcommand{\VAR@titletranslation}{} \newcommand{\VAR@Phone}{} \newcommand{\VAR@Fax}{} \newcommand{\VAR@Email}{} \newcommand{\publisher}[3]{ % Pour construire la page d'annexe pour le service de fabrication % usage: {#1} = traduction du titre % {#2} = numero de tlphone des auteurs % {#3} = fax des auteurs % {#4} = Email des auteurs %\renewcommand{\VAR@titletranslation}{#1} \renewcommand{\VAR@Phone}{#1} \renewcommand{\VAR@Fax}{#2} \renewcommand{\VAR@Email}{#3} \let\myenddocument\enddocument \def\enddocument{ \pagebreak \pagestyle{empty}\enlargethispage{80mm} %\renewcommand{\@enddocumenthook}{ \parbox{\textwidth}{ \fbox{\parbox{\textwidth}{\begin{center} \textbf{\large ANNEXE POUR LA FABRICATION}\\ A FOURNIR PAR LES AUTEURS AVEC UN EXEMPLAIRE PAPIER\\ DE LEUR ARTICLE \end{center}}}\\[10mm] %\setcounter{section}{0} \ifthenelse{\equal{\VAR@TypeArticle}{revue}}{ \textsc{1. Article pour la revue~:} \begin{quote}\textit{\VAR@NomRevue}\end{quote}\vspace*{3mm} }{ \textsc{1. Article pour les actes~:} \begin{quote}\textit{\VAR@NomActes}\end{quote}\vspace*{3mm} } \textsc{2. Auteurs~:} \begin{quote}\textit{\VAR@author}\end{quote}\vspace*{3mm} \textsc{3. Titre de l'article~:} \begin{quote}\textit{\VAR@title}\end{quote}\vspace*{3mm} \textsc{4. Titre \underline{abrg} pour le haut de page \underline{moins de 40 signes}~:} \begin{quote}\textit{\VAR@TitreAbrege}\end{quote}\vspace*{3mm} \textsc{5. Date de cette version~:} \begin{quote}\textit{\today}\end{quote}\vspace*{3mm} \textsc{6. Coordonnes des auteurs~:} \begin{itemize} \item adresse postale~: \begin{quote}\VAR@address\end{quote} \item tlphone~: \VAR@Phone \item tlcopie~: \VAR@Fax \item e-mail~: \VAR@Email \end{itemize}\vspace*{3mm} \textsc{7. Logiciel utilis pour la prparation de cet article~:} \begin{quote} \LaTeX, avec le fichier de style \texttt{\PackageName.cls}, \\ version~\PackageVersion\ du \filedate. \end{quote} %\vspace*{3mm} %\textsc{8. Formulaire de copyright~:} %\begin{quote} % Retourner le formulaire de copyright sign par les auteurs, tlcharg % sur~: % \texttt{http://www.revuesonline.com} % \end{quote}\vspace*{3mm} } \adressestudia \myenddocument}%\renewcommand{\@enddocumenthook} }%\publisher %%%-- Macros utilises pour le paramtrage sur le langage %-- Macros identiques en francais et english \def\pagename{p.~} \def\pagesname{p.~}%@@normalement {pp.~} \def\etalter{\ et al.} \def\Inname{} \def\inname{} \def\editornames{Eds.} \def\editorname{Ed.} \def\Volumename{Vol.~} \def\volumename{vol.~} \def\notename{Note} \def\degree{$^\circ$}%@@ % Quelques macros utiles dfinies dans french \def\fup#1{\raisebox{0.55ex}{\protect\small #1\kern+.17em}}% \def\fsc{\scshape}% \def\@umer#1{$^{\mathrm #1}$\kern.2em\ignorespaces}% \def\numero{n\@umer{o}}% \def\numero{n\@umer{o}}% \def\Numero{N\@umer{o}}% \def\numeros{n\@umer{o}}% \def\Numeros{N\@umer{o}}% \def\fups#1{\raisebox{0.55ex}{{\scriptsize #1}}~}% \def\ier{\fups{er}}% \def\iere{\fups{re}}% \def\ieme{\fups{e}}% \def\iers{\fups{ers}}% \def\ieres{\fups{res}}% \def\iemes{\fups{es}}% %-- Macros diffrentes en francais et english % Doivent tre redfinies aprs chaque slection de langage \def\initialisation{% \iffrenchlang % % \AutoSpaceBeforeFDP % \def\figurename{Figure}% \def\figname{\bf figure}% \def\tablename{Tableau}% \def\tabname{tableau}% \def\programname{Programme}% \def\progname{programme}% \def\studiaRefname{Bibliographie}% \def\andname{, } \def\acknowledgementsname{Remerciements} \def\remarkname{Remarque} \def\editionname{\'edition} \def\chaptername{chapitre} \def\technicalreportname{rapport}% valeur par dfaut du champ type \def\numbername{\numero}%{n~} \def\Numbername{\Numero}%{N~} \def\ofname{de} \def\guilo{~}% C. Queinnec \def\guilf{~}% C. Queinnec \def\Jan{janvier} \def\Feb{f\'evrier} \def\Mar{mars} \def\Apr{avril} \def\May{mai} \def\Jun{juin} \def\Jul{juillet} \def\Aug{ao\^ut} \def\Sep{septembre} \def\Oct{octobre} \def\Nov{novembre} \def\Dec{d\'ecembre} \else \def\figurename{Figure}% \def\figname{\bf figure}% \def\tablename{Table}% \def\tabname{table}% \def\programname{Program}% \def\progname{program}% \def\studiaRefname{References}% \def\andname{, } \def\acknowledgementsname{Acknowledgements} \def\remarkname{Remark} \def\editionname{edition} \def\chaptername{chapter} \def\technicalreportname{report }% valeur par dfaut du champ type \def\numbername{num.~} \def\Numbername{Num.~} \def\ofname{of} \def\guilo{``} \def\guilf{''} \def\Jan{Jan. } \def\Feb{Feb. } \def\Mar{March } \def\Apr{April } \def\May{May } \def\Jun{June } \def\Jul{Jul. } \def\Aug{Aug. } \def\Sep{Sep. } \def\Oct{Oct. } \def\Nov{Nov. } \def\Dec{Dec. } \fi }%\initialisation \def\@mkstudia{% \mkstudialist \initialisation % dpend du langage } \AtBeginDocument{% \iffrenchlang % % \selectlanguage{frenchb}% \selectlanguage{french}% \else % \selectlanguage{english}% \fi% } %EOF %%%%%%%%%%%%%%%%%% Doc %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % version commune pour les articles de revue et d'actes studia % Seule diffrence entre les deux types d'article : % en version finale, utiliser \journal pour un article de revue et % \proceedings pour un article de confrence. % % Documentation rsume %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Toutes les commandes LaTex2e s'utilisent normalement y compris \maketitle remplace % par \maketitlepage. Pour connatre les diffrentes commandes de dfinition de la % premire page, IL SUFFIT DE COMMENCER UN ARTICLE PAR \maketitlepage : % les commandes utiliser avant \maketitlepage s'afficheront par dfaut. %%% Utilisation des options: % Langue utilise pour l'article (franais ou anglais) %\documentclass{studia-Hermann} % article en franais avec le package babel %\documentclass[english]{studia-Hermann} % article en anglais (avec babel) % Numrotation des pages: par dfaut, les pages sont numrotes avec les en-ttes % construits partir des commandes \title, \submitted, \journal ou \proceedings % La signature de l'article apparait en bas de la 1ere page: elle est % construite par \submitted, \journal ou \proceedings % Option empty: ni signature, ni en-tte, ni pied de page... % Exemple: %\documentclass[empty]{studia-Hermann}\header{LMO'99} % remise finale art. franais % Option nofirstpagebreak: pas de saut de page sur la page de titre % (non standard, pour certaines revues seulement) % Option cropmarks: trac des contours de page et de corps du texte % (utile pour visualiser les problmes ventuels de dbordement de ligne ou page, % ne s'utilise qu'en mise au point finale). % Exemple: %\documentclass[cropmarks]{studia-Hermann} % article en franais avec contour de page % Option fleqn: formules mathmatiques cadres 2cm du bord gauche du corps du texte % (par dfaut les formules sont centres) Exemple: %\documentclass[fleqn]{studia-Hermann} % article en franais avec formules gauche % Mode d'emploi dtaill: % cf les fichiers doc-studia-Hermann.ltx et doc-studia-Hermann.ps %%% Liste des commandes utilisateur % Commandes spcifiques au style, avec nb d'arguments entre crochets % \title[1] % \subtitle[1] % \author[1] % \andauthor % \fup % \address[1] % \abstract[1] % \motscles[1] % \keywords[1] % \resume[1] % \maketitlepage % \nofirstpagebreak % \firstpagebreak %---- % \submitted[2] % \journal[8] % \proceedings[3] %---- % \acknowledgements[1] % \logbook[3] % \andeditor % \biography[2] %%% Utilitaires % \remark[1] % \note[1] % \bibliography % \CropMarksOn % \CropMarksOff % \eqncont % \delaynewpage[1] % \forcenewpage % \newenvironment{editorial}[5] % Commandes ou Environnements Latex redefinis % \rmdefault % \sfdefault % \ttdefault % \maketitle % alias \maketitlepage % \thesection % \section % \thesubsection % \subsection % \thesubsubsection % \subsubsection % \theparagraph % \paragraph % \footnotesize % \footnoterule % \newblock % \renewenvironment{thebibliography}[1] % \renewenvironment{itemize} % \renewenvironment{enumerate} % \newenvironment{ITEMIZE} % \renewenvironment{figure} % Compteurs entiers ou variables dcimales Latex redfinis % section: 0 % page: 1 % secnumdepth: 4 % topnumber: 2 % nb max de fig. en haut % bottomnumber: 1 % nb max de fig. en bas % totalnumber: 3 % nb max de fig. par page % \topfraction : 1 % fraction remplissage haut % \bottomfraction : 1 % fraction remplissage bas % \textfraction : 0 % fraction remplissage texte / page % \floatpagefraction: 0.8 % fraction remplissage floatpage % Fontes utilisables (utilisation rare) % \FonteTexte % \FonteEnTete % \FonteRubrique % \FonteSignature % \FonteTitre % \FonteSousTitre % \FonteAuteur % \FonteResume % \FonteTitreResume % \FonteSectionI % \FonteSectionII % \FonteSectionIII % \FonteSectionIV % \FonteNoteBasPage % \FonteTitreLegende % \FonteCaptionName % \FonteBibliographie % Paramtres de listes (Normalement, ne pas modifier) % \mkstudialist % Pour modifier les dimensions % \labelitemi % \labelitemii % \labelitemiii % \labelitemiv % Variables utilisables % \newlength{\interligne} mlpost-0.8.2/papers/jfla2009/whizzy-pp.sh000077500000000000000000000001471306046515300201050ustar00rootroot00000000000000#!/bin/sh # echo $* > whizzy-pp-command-line file=`basename $1 .tex` ocaml pp.ml $file.new > $file.tex mlpost-0.8.2/papers/jfla2009/whizzy.el000066400000000000000000000001101306046515300174410ustar00rootroot00000000000000 (whizzy-add-configuration ".*\.tex" '((whizzy . "frame -pdf .")) ) mlpost-0.8.2/papers/jfla2009/whizzy.sh000066400000000000000000000000301306046515300174540ustar00rootroot00000000000000MKSLICE=./whizzy-pp.sh mlpost-0.8.2/papers/jfla2009/yannick1.1000066400000000000000000000176441306046515300173760ustar00rootroot00000000000000%!PS %%BoundingBox: -1 -11 359 60 %%HiResBoundingBox: -0.25 -10.2126 358.904 59.38843 %%Creator: MetaPost 0.993 %%CreationDate: 2008.10.01:1434 %%Pages: 1 %*Font: cmmi10 9.96265 9.96265 3b:800000000202408 %*Font: cmr7 6.97385 6.97385 31:c %*Font: cmsy10 9.96265 9.96265 00:8 %*Font: cmr10 9.96265 9.96265 28:d04 %%BeginProlog %%EndProlog %%Page: 1 1 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 9.9626 moveto 358.654 9.9626 lineto stroke newpath 0 -9.9626 moveto 358.654 -9.9626 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth [3 3 ] 0 setdash newpath 338.728 9.9626 moveto 338.728 -9.9626 lineto stroke newpath 318.803 9.9626 moveto 318.803 -9.9626 lineto stroke newpath 298.878 9.9626 moveto 298.878 -9.9626 lineto stroke newpath 278.953 9.9626 moveto 278.953 -9.9626 lineto stroke newpath 259.028 9.9626 moveto 259.028 -9.9626 lineto stroke newpath 239.102 9.9626 moveto 239.102 -9.9626 lineto stroke newpath 219.177 9.9626 moveto 219.177 -9.9626 lineto stroke newpath 199.252 9.9626 moveto 199.252 -9.9626 lineto stroke newpath 179.327 9.9626 moveto 179.327 -9.9626 lineto stroke newpath 159.402 9.9626 moveto 159.402 -9.9626 lineto stroke newpath 139.476 9.9626 moveto 139.476 -9.9626 lineto stroke newpath 119.551 9.9626 moveto 119.551 -9.9626 lineto stroke newpath 99.626 9.9626 moveto 99.626 -9.9626 lineto stroke newpath 79.7008 9.9626 moveto 79.7008 -9.9626 lineto stroke newpath 59.7756 9.9626 moveto 59.7756 -9.9626 lineto stroke newpath 39.8504 9.9626 moveto 39.8504 -9.9626 lineto stroke newpath 19.9252 9.9626 moveto 19.9252 -9.9626 lineto stroke 1 1 1 setrgbcolor newpath 43.83539 19.9252 moveto 155.41663 19.9252 lineto 157.61754 19.9252 159.40161 18.14113 159.40161 15.94022 curveto 159.40161 3.98499 lineto 159.40161 1.78407 157.61754 0 155.41663 0 curveto 43.83539 0 lineto 41.63448 0 39.8504 1.78407 39.8504 3.98499 curveto 39.8504 15.94022 lineto 39.8504 18.14113 41.63448 19.9252 43.83539 19.9252 curveto closepath fill 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash newpath 43.83539 19.9252 moveto 155.41663 19.9252 lineto 157.61754 19.9252 159.40161 18.14113 159.40161 15.94022 curveto 159.40161 3.98499 lineto 159.40161 1.78407 157.61754 0 155.41663 0 curveto 43.83539 0 lineto 41.63448 0 39.8504 1.78407 39.8504 3.98499 curveto 39.8504 15.94022 lineto 39.8504 18.14113 41.63448 19.9252 43.83539 19.9252 curveto closepath stroke 15.44484 30.99492 moveto (a) cmmi10 9.96265 fshow 20.71094 29.50052 moveto (1) cmr7 6.97385 fshow 27.39424 30.99492 moveto (\000) cmsy10 9.96265 fshow 37.35684 30.99492 moveto (1) cmr10 9.96265 fshow newpath 21.91785 23.31245 moveto 21.91785 26.50055 lineto 35.86542 26.50055 lineto 35.86542 23.31245 lineto stroke 62.7756 46.90164 moveto (l) cmmi10 9.96265 fshow 65.7482 45.40724 moveto (1) cmr7 6.97385 fshow newpath 59.7756 49.61386 moveto 49.813 49.61386 lineto 49.813 39.65126 lineto stroke newpath 48.28223 43.3468 moveto 49.813 39.65126 lineto 51.34378 43.3468 lineto closepath gsave fill grestore stroke 43.94894 30.99492 moveto (a) cmmi10 9.96265 fshow 49.21504 29.50052 moveto (1) cmr7 6.97385 fshow newpath 41.84305 23.31245 moveto 41.84305 26.50055 lineto 55.79062 26.50055 lineto 55.79062 23.31245 lineto stroke 55.29524 30.99492 moveto (a) cmmi10 9.96265 fshow 60.56134 29.50052 moveto (1) cmr7 6.97385 fshow 67.24464 30.99492 moveto (+) cmr10 9.96265 fshow 77.20724 30.99492 moveto (1) cmr10 9.96265 fshow newpath 61.76825 23.31245 moveto 61.76825 26.50055 lineto 75.71582 26.50055 lineto 75.71582 23.31245 lineto stroke 124.3384 30.99492 moveto (a) cmmi10 9.96265 fshow 129.60449 29.50052 moveto (1) cmr7 6.97385 fshow 136.2878 30.99492 moveto (+) cmr10 9.96265 fshow 146.2504 30.99492 moveto (s) cmmi10 9.96265 fshow 150.9204 29.50052 moveto (1) cmr7 6.97385 fshow 157.60359 30.99492 moveto (\000) cmsy10 9.96265 fshow 167.5662 30.99492 moveto (1) cmr10 9.96265 fshow newpath 141.46906 23.31245 moveto 141.46906 26.50055 lineto 155.41663 26.50055 lineto 155.41663 23.31245 lineto stroke 90.98195 51.91643 moveto (\() cmr10 9.96265 fshow 94.85635 51.91643 moveto (l) cmmi10 9.96265 fshow 97.82895 50.42203 moveto (1) cmr7 6.97385 fshow 102.29836 51.91643 moveto (;) cmmi10 9.96265 fshow 106.72615 51.91643 moveto (a) cmmi10 9.96265 fshow 111.99225 50.42203 moveto (1) cmr7 6.97385 fshow 116.46165 51.91643 moveto (;) cmmi10 9.96265 fshow 120.88945 51.91643 moveto (i) cmmi10 9.96265 fshow 124.32175 51.91643 moveto (\)) cmr10 9.96265 fshow 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 109.58861 46.42575 moveto 109.58861 26.50055 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 108.05779 30.19618 moveto 109.58861 26.50055 lineto 111.11943 30.19618 lineto closepath gsave fill grestore stroke 1 1 1 setrgbcolor newpath 203.237 19.9252 moveto 314.81824 19.9252 lineto 317.01915 19.9252 318.80322 18.14113 318.80322 15.94022 curveto 318.80322 3.98499 lineto 318.80322 1.78407 317.01915 0 314.81824 0 curveto 203.237 0 lineto 201.03609 0 199.25201 1.78407 199.25201 3.98499 curveto 199.25201 15.94022 lineto 199.25201 18.14113 201.03609 19.9252 203.237 19.9252 curveto closepath fill 0 0 0 setrgbcolor newpath 203.237 19.9252 moveto 314.81824 19.9252 lineto 317.01915 19.9252 318.80322 18.14113 318.80322 15.94022 curveto 318.80322 3.98499 lineto 318.80322 1.78407 317.01915 0 314.81824 0 curveto 203.237 0 lineto 201.03609 0 199.25201 1.78407 199.25201 3.98499 curveto 199.25201 15.94022 lineto 199.25201 18.14113 201.03609 19.9252 203.237 19.9252 curveto closepath stroke 174.84634 30.99492 moveto (a) cmmi10 9.96265 fshow 180.11244 29.50052 moveto (2) cmr7 6.97385 fshow 186.79575 30.99492 moveto (\000) cmsy10 9.96265 fshow 196.75835 30.99492 moveto (1) cmr10 9.96265 fshow newpath 181.31946 23.31245 moveto 181.31946 26.50055 lineto 195.26703 26.50055 lineto 195.26703 23.31245 lineto stroke 222.177 46.90164 moveto (l) cmmi10 9.96265 fshow 225.1496 45.40724 moveto (2) cmr7 6.97385 fshow newpath 219.17722 49.61386 moveto 209.21461 49.61386 lineto 209.21461 39.65126 lineto stroke newpath 207.68384 43.3468 moveto 209.21461 39.65126 lineto 210.74539 43.3468 lineto closepath gsave fill grestore stroke 203.35025 30.99492 moveto (a) cmmi10 9.96265 fshow 208.61635 29.50052 moveto (2) cmr7 6.97385 fshow newpath 201.24466 23.31245 moveto 201.24466 26.50055 lineto 215.19223 26.50055 lineto 215.19223 23.31245 lineto stroke 214.69734 30.99492 moveto (a) cmmi10 9.96265 fshow 219.96344 29.50052 moveto (2) cmr7 6.97385 fshow 226.64674 30.99492 moveto (+) cmr10 9.96265 fshow 236.60934 30.99492 moveto (1) cmr10 9.96265 fshow newpath 221.16986 23.31245 moveto 221.16986 26.50055 lineto 235.11743 26.50055 lineto 235.11743 23.31245 lineto stroke 283.7394 30.99492 moveto (a) cmmi10 9.96265 fshow 289.0055 29.50052 moveto (2) cmr7 6.97385 fshow 295.6888 30.99492 moveto (+) cmr10 9.96265 fshow 305.6514 30.99492 moveto (s) cmmi10 9.96265 fshow 310.3214 29.50052 moveto (2) cmr7 6.97385 fshow 317.0046 30.99492 moveto (\000) cmsy10 9.96265 fshow 326.9672 30.99492 moveto (1) cmr10 9.96265 fshow newpath 300.87067 23.31245 moveto 300.87067 26.50055 lineto 314.81824 26.50055 lineto 314.81824 23.31245 lineto stroke 250.38295 51.91643 moveto (\() cmr10 9.96265 fshow 254.25735 51.91643 moveto (l) cmmi10 9.96265 fshow 257.22995 50.42203 moveto (2) cmr7 6.97385 fshow 261.69936 51.91643 moveto (;) cmmi10 9.96265 fshow 266.12715 51.91643 moveto (a) cmmi10 9.96265 fshow 271.39325 50.42203 moveto (2) cmr7 6.97385 fshow 275.86266 51.91643 moveto (;) cmmi10 9.96265 fshow 280.29045 51.91643 moveto (i) cmmi10 9.96265 fshow 283.72275 51.91643 moveto (\)) cmr10 9.96265 fshow 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 268.99022 46.42575 moveto 268.99022 26.50055 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 267.4594 30.19618 moveto 268.99022 26.50055 lineto 270.52104 30.19618 lineto closepath gsave fill grestore stroke showpage %%EOF mlpost-0.8.2/papers/jfla2009/yannick2.1000066400000000000000000000123561306046515300173720ustar00rootroot00000000000000%!PS %%BoundingBox: -1 -60 220 60 %%HiResBoundingBox: -0.25 -59.38841 219.427 59.38843 %%Creator: MetaPost 0.993 %%CreationDate: 2008.10.01:1434 %%Pages: 1 %*Font: cmmi10 9.96265 9.96265 3b:800000000202008 %*Font: cmsy10 9.96265 9.96265 00:8 %*Font: cmr10 9.96265 9.96265 28:d04 %%BeginProlog %%EndProlog %%Page: 1 1 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash 1 setlinecap 1 setlinejoin 10 setmiterlimit newpath 0 9.9626 moveto 219.177 9.9626 lineto stroke newpath 0 -9.9626 moveto 219.177 -9.9626 lineto stroke 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth [3 3 ] 0 setdash newpath 199.252 9.9626 moveto 199.252 -9.9626 lineto stroke newpath 179.327 9.9626 moveto 179.327 -9.9626 lineto stroke newpath 159.402 9.9626 moveto 159.402 -9.9626 lineto stroke newpath 139.476 9.9626 moveto 139.476 -9.9626 lineto stroke newpath 119.551 9.9626 moveto 119.551 -9.9626 lineto stroke newpath 99.626 9.9626 moveto 99.626 -9.9626 lineto stroke newpath 79.7008 9.9626 moveto 79.7008 -9.9626 lineto stroke newpath 59.7756 9.9626 moveto 59.7756 -9.9626 lineto stroke newpath 39.8504 9.9626 moveto 39.8504 -9.9626 lineto stroke newpath 19.9252 9.9626 moveto 19.9252 -9.9626 lineto stroke 1 1 1 setrgbcolor newpath 43.83539 19.9252 moveto 175.34183 19.9252 lineto 177.54274 19.9252 179.32681 18.14113 179.32681 15.94022 curveto 179.32681 3.98499 lineto 179.32681 1.78407 177.54274 0 175.34183 0 curveto 43.83539 0 lineto 41.63448 0 39.8504 1.78407 39.8504 3.98499 curveto 39.8504 15.94022 lineto 39.8504 18.14113 41.63448 19.9252 43.83539 19.9252 curveto closepath fill 0 0 0 setrgbcolor 0 0.5 dtransform truncate idtransform setlinewidth pop [] 0 setdash newpath 43.83539 19.9252 moveto 175.34183 19.9252 lineto 177.54274 19.9252 179.32681 18.14113 179.32681 15.94022 curveto 179.32681 3.98499 lineto 179.32681 1.78407 177.54274 0 175.34183 0 curveto 43.83539 0 lineto 41.63448 0 39.8504 1.78407 39.8504 3.98499 curveto 39.8504 15.94022 lineto 39.8504 18.14113 41.63448 19.9252 43.83539 19.9252 curveto closepath stroke 17.67949 30.3307 moveto (a) cmmi10 9.96265 fshow 25.15948 30.3307 moveto (\000) cmsy10 9.96265 fshow 35.12209 30.3307 moveto (1) cmr10 9.96265 fshow newpath 21.91785 23.31245 moveto 21.91785 26.50055 lineto 35.86542 26.50055 lineto 35.86542 23.31245 lineto stroke 46.18364 29.5005 moveto (a) cmmi10 9.96265 fshow newpath 41.84305 23.31245 moveto 41.84305 26.50055 lineto 55.79062 26.50055 lineto 55.79062 23.31245 lineto stroke 57.52989 30.3307 moveto (a) cmmi10 9.96265 fshow 65.00989 30.3307 moveto (+) cmr10 9.96265 fshow 74.97249 30.3307 moveto (1) cmr10 9.96265 fshow newpath 61.76825 23.31245 moveto 61.76825 26.50055 lineto 75.71582 26.50055 lineto 75.71582 23.31245 lineto stroke 148.73279 30.3307 moveto (a) cmmi10 9.96265 fshow 156.21278 30.3307 moveto (+) cmr10 9.96265 fshow 166.17538 30.3307 moveto (s) cmmi10 9.96265 fshow 173.0593 30.3307 moveto (\000) cmsy10 9.96265 fshow 183.02188 30.3307 moveto (1) cmr10 9.96265 fshow newpath 161.39426 23.31245 moveto 161.39426 26.50055 lineto 175.34183 26.50055 lineto 175.34183 23.31245 lineto stroke 99.1515 51.91643 moveto (\() cmr10 9.96265 fshow 103.02591 51.91643 moveto (a;) cmmi10 9.96265 fshow 112.7198 51.91643 moveto (i) cmmi10 9.96265 fshow 116.1521 51.91643 moveto (\)) cmr10 9.96265 fshow 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 109.58861 46.42575 moveto 109.58861 26.50055 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 108.05779 30.19618 moveto 109.58861 26.50055 lineto 111.11943 30.19618 lineto closepath gsave fill grestore stroke newpath 43.83539 0 moveto 135.49142 0 lineto 137.69234 0 139.47641 -1.78407 139.47641 -3.98499 curveto 139.47641 -15.94022 lineto 139.47641 -18.14113 137.69234 -19.9252 135.49142 -19.9252 curveto 43.83539 -19.9252 lineto 41.63448 -19.9252 39.8504 -18.14113 39.8504 -15.94022 curveto 39.8504 -3.98499 lineto 39.8504 -1.78407 41.63448 0 43.83539 0 curveto closepath fill newpath 43.83539 0 moveto 135.49142 0 lineto 137.69234 0 139.47641 -1.78407 139.47641 -3.98499 curveto 139.47641 -15.94022 lineto 139.47641 -18.14113 137.69234 -19.9252 135.49142 -19.9252 curveto 43.83539 -19.9252 lineto 41.63448 -19.9252 39.8504 -18.14113 39.8504 -15.94022 curveto 39.8504 -3.98499 lineto 39.8504 -1.78407 41.63448 0 43.83539 0 curveto closepath stroke 46.18364 -33.79001 moveto (a) cmmi10 9.96265 fshow newpath 41.84305 -23.31245 moveto 41.84305 -26.50055 lineto 55.79062 -26.50055 lineto 55.79062 -23.31245 lineto stroke 57.52989 -35.9209 moveto (a) cmmi10 9.96265 fshow 65.00989 -35.9209 moveto (+) cmr10 9.96265 fshow 74.97249 -35.9209 moveto (1) cmr10 9.96265 fshow newpath 61.76825 -23.31245 moveto 61.76825 -26.50055 lineto 75.71582 -26.50055 lineto 75.71582 -23.31245 lineto stroke 99.1515 -56.8977 moveto (\() cmr10 9.96265 fshow 103.02591 -56.8977 moveto (a;) cmmi10 9.96265 fshow 112.7198 -56.8977 moveto (i) cmmi10 9.96265 fshow 116.1521 -56.8977 moveto (\)) cmr10 9.96265 fshow 0.5 0 dtransform exch truncate exch idtransform pop setlinewidth newpath 109.58861 -46.42575 moveto 109.58861 -26.50055 lineto stroke 0 0.5 dtransform truncate idtransform setlinewidth pop newpath 111.11943 -30.19618 moveto 109.58861 -26.50055 lineto 108.05779 -30.19618 lineto closepath gsave fill grestore stroke showpage %%EOF mlpost-0.8.2/papers/ter-stage/000077500000000000000000000000001306046515300162275ustar00rootroot00000000000000mlpost-0.8.2/papers/ter-stage/Makefile000066400000000000000000000010051306046515300176630ustar00rootroot00000000000000 all: slides.pdf PDFLATEX:=pdflatex -interaction="errorstopmode" rapport.pdf: rapport.tex figrapport.mp pdflatex $< pdflatex $< slides.pdf: slides.tex figrapport.mp pdflatex $< wc: grep -iw frametitle slides.tex | wc -l %.mp: %.ml ../../tool.opt -ccopt "-I ../../" -pdf -latex rapport.tex $^ test: ../../tool.opt -ccopt "-I ../../" -xpdf -latex slides.tex figrapport.ml clean: rm -f *~ *.aux *.log *.bbl *.blg *.mps rm -f rapport.dvi rapport.ps figrapport.mp rm -f mpxerr.dvi mpxerr.tex rapport.pdf mlpost-0.8.2/papers/ter-stage/figrapport.ml000066400000000000000000000340101306046515300207340ustar00rootroot00000000000000open Mlpost open Num open Color open Box open Path open Tree open Command (***************** Simple Block ******************) let simple_block = let b = Box.hblock ~pos:`Bot [Box.tex "a"; Box.tex "A"; Box.tex "1"; Box.tex "$\\pi$"] in Box.draw b (***************** Traffic Lights ******************) let traffic = let two = Num.bp 2. in let b = vbox ~fill:black ~padding:(Num.bp 3.) ~dx:two ~dy:two [ tex ~style:Circle ~fill:red "R"; tex ~style:Circle ~fill:yellow "Y"; tex ~style:Circle ~fill:green "G"; ] in Box.draw b (***************** Rubik's Cube ******************) let alpha = atan 1. let beta = atan 1. /. 2. let mag = 10. let proj x y z = mag *. float (x - y) *. cos alpha, mag *. (float (x + y) *. sin alpha *. sin beta +. float z *. cos beta) let pen = Pen.scale (bp 2.5) Pen.default let square color p i j = let pt i j = let x,y = p i j in Point.pt (bp x, bp y) in let points = [pt i j; pt (i+1) j; pt (i+1) (j+1); pt i (j+1)] in let path = pathp ~style:jLine ~cycle:jLine points in seq [fill ~color path; Command.draw ~pen path] let right = square Color.orange (fun i j -> proj i 0 j) let up = square Color.yellow (fun i j -> proj i j 3) let left = square Color.green (fun i j -> proj 0 (3 - i) j) let rubik = seq [iter 0 2 (fun i -> iter 0 2 (right i)); iter 0 2 (fun i -> iter 0 2 (up i)); iter 0 2 (fun i -> iter 0 2 (left i));] (***************** Histograms ******************) let hist1 = Hist.simple [3.;1.;6.] let hist2 = Hist.compare [[1.;5.;6.;5.;3.]; [1.;2.;3.;6.;1.]] let hist3 = let vlabel _ _ = None in Hist.stack ~vlabel ~fill:[lightred;lightblue;lightyellow;lightgreen] [[4.;5.;5.;]; [8.;3.;1.]; [2.;8.;1.;4.];[1.5;3.5];[2.;2.;7.;1.]] let hist5 = let vlabel _ _ = None in let rot s = Picture.rotate 25. (Picture.tex s) in Hist.stack ~vlabel ~perspective:true ~padding:(bp 15.) ~fill:[lightred;lightblue;lightyellow;lightgreen] ~histlabel:(`Center, Hist.Values) ~vcaption:(Picture.tex "Dollars") ~hlabel:[rot "2007";rot "2008";rot "2009"] [[4.;5.;5.;]; [8.;3.;1.]; [2.;8.;1.;4.]] let hist4 = let pics = List.map Picture.tex ["2000";"2001";"2002";"2003";"2004";"2005"] in Hist.simple ~width:(bp 150.) ~height:(bp 270.) ~histlabel:(`Top, Hist.User pics) ~hcaption:(Picture.tex "Year") [4.5;5.0;6.2;8.;7.2;6.1] (***************** Radars ******************) let radar1 = let pic = Radar.stack ~pen:(Pen.scale (bp 3.) Pen.circle) ~color:[blue;red;green] ~label:["weight";"acceleration";"speed";"maniability";"stickiness"] [[3.;4.;5.;6.;4.]; [6.;5.;2.;1.;1.]; [1.;7.;2.;4.;5.]] in Command.draw_pic pic let radar2 = let pics = Radar.compare ~pen:(Pen.scale (bp 1.5) Pen.circle) ~color:[lightblue;lightred;lightgreen] ~fill:true [[3.;4.;5.;6.;4.]; [6.;5.;2.;1.;1.]; [1.;7.;2.;4.;5.]] in Box.draw (Box.hbox ~padding:(bp 10.) (List.map (Box.pic ~stroke:None) pics)) (***************** Paths ******************) let path1 = let p = Path.smart_path [Right;Up;Right] ~style:jLine (Point.pt (bp 0.,bp 0.)) (Point.pt (bp 50.,bp 50.)) in Command.draw p let path2 = let p = Path.smart_path [Right;Down;Left;Down] ~style:jLine (Point.pt (bp 0.,bp 0.)) (Point.pt (bp 0.,bp (-30.))) in Command.draw_arrow p let path3 = let p = Path.smart_path [Left;Down;Left;Down;Left] (Point.pt (bp 0.,bp 0.)) (Point.pt (bp (-50.),bp (-50.))) in Command.draw_arrow p let path4 = let p = Path.smart_path [Down;Right;Upn (bp 10.);Right;Downn (bp 10.);Right;Upn (bp 10.);Right;Downn (bp 10.);Right;Upn (bp 10.);Right;Down] (Point.pt (bp 0.,bp 100.)) (Point.pt (bp 100.,bp 0.)) in Command.draw p let path5 = let p = Path.smart_path ~style:jLine [Rightn(bp 30.);Upn (bp 25.);Rightn(bp 80.);Down;Rightn( bp 30.)] (Point.pt (bp (-50.),bp 0.)) (Point.pt (bp 90.,bp 0.)) in (Command.draw_arrow p)++(Box.draw (Box.set_stroke Color.black (Box.tex "Obstacle"))) (***************** Trees ******************) let tree1 = let node s = Tree.node ~edge_style:Curve (Box.tex s) in let leaf s = Tree.leaf (Box.tex s) in Tree.draw (node "1" [node "2" [leaf "4"; leaf "5"]; node "3" [leaf "6"; leaf "7"]]) let tree2 = let node s = Tree.node ~ls:(bp 30.) ~arrow_style:Undirected ~edge_style:HalfSquare (Box.tex s) in let leaf s = Tree.leaf (Box.tex s) in Tree.draw (node "1" [node "2" [node "4" [node "8" [leaf "13"; leaf "14"]]; leaf "5"]; node "3" [node "6" [leaf "9";leaf "10";leaf "11";leaf "12"]; leaf "7" ]]) let tree2simple = let node s = Tree.Simple.node ~ls:(bp 18.) ~arrow_style:Undirected ~edge_style:HalfSquare (Box.tex s) in let leaf s = Tree.Simple.leaf (Box.tex s) in Tree.Simple.draw (node "1" [node "2" [node "4" [node "8" [leaf "13"; leaf "14"]]; leaf "5"]; node "3" [node "6" [leaf "9";leaf "10";leaf "11";leaf "12"]; leaf "7" ]]) let leaf s = Tree.leaf (Box.set_stroke Color.black (Box.tex s)) let node s l = Tree.node ~arrow_style:Undirected ~edge_style:Straight ~ls:(bp 30.) (Box.set_stroke Color.black (Box.tex s)) l let subtree = node "subroot" [leaf "son1"; leaf "son2"; leaf "son3"] let treebox = Box.rect (to_box subtree) let maintree = node "root" [subtree; leaf "son"; Tree.node treebox [subtree]] let tree3 = Tree.draw maintree let node s l = Tree.node ~ls:(bp 20.) ~cs:(bp 20.) ~arrow_style:Directed ~edge_style:Curve (Box.set_stroke Color.black (Box.tex s)) l let tree4 = Tree.draw (node "A" [leaf "$\\int_H\\dots$";node "B" [leaf "texte"; leaf "a"]]) let leaf s = Tree.leaf (Box.tex s) let node s l = Tree.node ~sep:(bp 5.) ~arrow_style:Undirected ~edge_style:Straight (Box.tex s) l let tree5 = Tree.draw (node "$\\alpha$" [leaf "$\\gamma$";leaf "$\\beta$"]) let leaf s = Tree.leaf (Box.set_stroke Color.black (Box.tex s)) let node s l = Tree.node ~arrow_style:Directed ~edge_style:HalfSquare ~ls:(bp 30.) ~cs:(bp 30.) (Box.set_stroke Color.black (Box.tex s)) l let tree6 = Tree.draw (node "Combined A B C" [node "Combined A B" [leaf "A";leaf "B"];leaf "C"]) (***************** GMlpost ******************) let init = let dx = bp 5. and dy = bp 5. in let tex' = tex ~style:RoundRect ~dx ~dy in let tex = tex' ~stroke:(Some Color.black) in let box name = box ~stroke:None ~dx:(mm 2.) ~name in let fml = box "fml" (tex ".ml") in let gmlpost = box "gmlpost" (tex "GMLPost") in let mlpost = box "mlpost" (tex "MLPost") in let glexer = box "glexer" (tex "Glexer") in let edit = box "edit" (tex "Edit") in let png = box "png"(tex ".png") in let fedit = box "fedit" (tex ".edit") in fml,gmlpost,mlpost,glexer,edit,png,fedit let interface = let fml,gmlpost,mlpost,glexer,edit,png,fedit = init in let boxarray = Array.make_matrix 4 3 (Box.empty ()) in boxarray.(0).(0) <- fml ; boxarray.(1).(0) <- gmlpost ; boxarray.(1).(1) <- mlpost ; boxarray.(1).(2) <- edit ; boxarray.(3).(2) <- glexer ; boxarray.(2).(1) <- png ; boxarray.(3).(1) <- fedit ; tabular ~hpadding:(bp 20.) ~vpadding:(bp 20.) boxarray let interface1 = let mbox = interface in let a1 = Command.draw_arrow ~color:Color.blue (pathp [(Box.south (Box.get "fml" mbox));(Box.north (Box.get "gmlpost" mbox))]) in let a2 = Command.draw_arrow ~color:Color.blue (pathp [(Box.east (Box.get "gmlpost" mbox));(Box.west (Box.get "mlpost" mbox))]) in let a3 = Command.draw_arrow ~color:Color.blue (pathp [(Box.south (Box.get "mlpost" mbox));(Box.north (Box.get "png" mbox))]) in let a4 = Command.draw_arrow ~color:Color.blue (pathp [(Box.east (Box.get "mlpost" mbox));(Box.west (Box.get "edit" mbox))]) in let a5 = Command.draw_arrow ~color:Color.blue (pathp [(Box.south (Box.get "edit" mbox));(Box.north (Box.get "glexer" mbox))]) in let a6 = Command.draw_arrow ~color:Color.blue (pathp [(Box.west (Box.get "glexer" mbox));(Box.east (Box.get "fedit" mbox))]) in let a7 = Command.draw_arrow ~color:Color.blue (smart_path ~style:jLine [Left;Up] (Box.west (Box.get "fedit" mbox)) (Box.south (Box.get "gmlpost" mbox))) in let a8 = Command.draw_arrow ~color:Color.blue (smart_path ~style:jLine [Left;Up] (Box.west (Box.get "png" mbox)) (Box.south (Box.get "gmlpost" mbox))) in (Box.draw mbox)++a1++a2++a3++a4++a5++a6++a7++a8 let interface2 = let mbox = interface in let a1 = Command.draw_arrow ~color:Color.red (smart_path ~style:jLine [Down;Right] (Box.south (Box.get "gmlpost" mbox)) (Box.west (Box.get "fedit" mbox))) in let a2 = Command.draw_arrow ~color:Color.red (pathp [(Box.south (Box.get "mlpost" mbox));(Box.north (Box.get "png" mbox))]) in let a3 = Command.draw_arrow ~color:Color.red (smart_path ~style:jLine [Left;Up;Left] (Box.west (Box.get "png" mbox)) (Box.east (Box.get "gmlpost" mbox))) in let a4 = Command.draw_arrow ~color:Color.red (smart_path ~style:jLine [Rightn (bp 20.);Up;Leftn (bp 5.)] (Box.east (Box.get "fedit" mbox)) (Box.east (Box.get "mlpost" mbox))) in (Box.draw mbox)++a1++a2++a3++a4 (***************** Legend ******************) let legend1 = let l = Legend.legend ~ensstroke:Color.black ~colstroke:Color.black [(Color.lightred,"january");(Color.lightblue,"february");(Color.lightyellow,"march");(Color.lightgreen,"extra")] in Command.draw_pic l (***************** ******************) let figford = let ford n = let u x = Num.bp (200.0 *. x) in let circle x y r = Command.draw ~color:Color.black (Path.shift (Point.pt (u x, u y)) (Path.scale (u (2.*.r)) fullcircle)) in let rec aux acc p1 q1 p2 q2 = let p = p1 + p2 in let q = q1 + q2 in if q>n then acc else let fq = float q in let fr = 0.5 /. fq /. fq in let acc = circle (float p /. fq) fr fr :: acc in let acc = aux acc p1 q1 p q in aux acc p q p2 q2 in let l = aux [] 0 1 1 1 in let pic = Picture.make (Command.seq l) in Picture.scale (Num.bp 1.5) pic in (Command.draw_pic (ford 17)) let graph_sqrt = let u = cm 1. in let sk = Plot.mk_skeleton 4 3 u u in let label = Picture.tex "$y=\\sqrt{x+\\frac{1}{2}}$", `Upleft, 3 in let graph = Plot.draw_func ~label (fun x -> sqrt (float x +. 0.5)) sk in seq [graph; Plot.draw_simple_axes "$x$" "$y$" sk] open Num.Infix let architecture = let mk_box fill name m = let m = "{\\tt " ^ m ^ "}" in Box.tex ~stroke:(Some Color.black) ~style:RoundRect ~dx:(bp 5.) ~dy:(bp 5.) ~name ~fill m in let mk_unbox name m = Box.tex ~style:RoundRect ~stroke:None ~dx:(bp 5.) ~dy:(bp 5.) ~name m in (* les types de base *) let fill = Color.color "salmon" in let num = mk_box fill "num" "Num" in let point = mk_box fill "point" "Point" in let path = mk_box (Color.lightblue) "path" "Path" in let dots = mk_unbox "dots" "$\\ldots$" in let cmd = mk_box fill "cmd" "Command" in let basictypes = Box.hbox ~padding:(mm 2.) [num; point; path; dots; cmd] in (* compile *) let compile = mk_unbox "compile" "\\tt Compile" in let compile_ext = let dx = (Box.width basictypes -/ Box.width compile) /./ 2. in Box.hbox ~style:RoundRect ~dx ~fill ~stroke:(Some Color.black) [compile] in (* metapost *) let metapost = mk_unbox "metapost" "\\metapost" in let metapost_ext = let dx = (Box.width basictypes -/ Box.width metapost) /./ 2. in Box.hbox ~name:"mpost_ext" ~style:Rect ~dx ~stroke:(Some Color.black) [metapost] in (* composants avancés *) let fill = Color.color "pink" in let box_ = mk_box fill "box" "\\phantom{p}Box\\phantom{p}" in let shapes = mk_box fill "shapes" "\\phantom{p}Shapes\\phantom{p}" in let arrows = mk_box fill "arrow" "\\phantom{p}Arrow\\phantom{p}" in let advanced = Box.hbox ~pos:`Bot ~padding:(mm 2.) [box_; shapes; arrows] in (* extensions *) let fill = Color.color "blanched almond" in let fill2 = Color.lightgreen in let hist = mk_box fill2 "hist" "\\phantom{g}Hist\\phantom{g}" in let radar = mk_box fill2 "radar" "\\phantom{g}Radar\\phantom{g}" in let tree = mk_box fill2 "tree" "\\phantom{g}Tree\\phantom{g}" in let legend = mk_box fill2 "legend" "\\phantom{g}Legend\\phantom{g}" in let plot = mk_box fill "plot" "\\phantom{g}Plot\\phantom{g}" in let extensions = Box.hbox ~pos:`Bot ~padding:(mm 2.) [hist; radar; tree; legend; plot] in (* wrapping *) let pyramid = let pen = Pen.scale (Num.bp 1.0) Pen.square in Box.vbox ~padding:(mm 2.) ~pen ~dx:(bp 5.) ~dy:(bp 5.) ~style:RoundRect ~stroke:(Some Color.black) [extensions; advanced; basictypes; compile_ext; metapost_ext] in let mlpost = mk_unbox "mlpost" "\\tt Mlpost" in let mlpost_ext = let dx = (Box.width pyramid -/ Box.width mlpost) /./ 2. in Box.hbox ~dx [mlpost] in let full = Box.vbox ~padding:(mm (-1.)) [mlpost_ext; pyramid] in let _ = Box.set_stroke Color.black (Box.nth 1 full) in (* arrows *) let arrows = let mp = Box.get "mpost_ext" full in List.map (fun n -> Helpers.box_label_arrow ~outd:(Path.vec Point.down) ~pos:`Bot (Picture.make Command.nop) (Box.get n full) mp) (* une variante *) (* let mp = Box.get "metapost" full in *) (* List.map *) (* (fun n -> Helpers.box_arrow *) (* (Box.get n full) mp) *) ["num"; "point"; "path"; "dots"; "cmd"] in seq [seq arrows; Box.draw full] let _ = List.iter (fun (name,fig) -> Metapost.emit name fig) [ "hist1", hist1; "hist2", hist2; "hist3", hist3; "hist4", hist4; "hist5", hist5; "radar1",radar1; "radar2",radar2; "simple_block",simple_block; "interface1",interface1; "interface2",interface2; "path1",path1; "path2",path2; "path3",path3; "path4",path4; "path5",path5; "tree1",tree1; "tree2",tree2; "tree2simple",tree2simple; "tree3",tree3; "tree4",tree4; "tree5",tree5; "tree6",tree6; "traffic",traffic; "rubik",rubik; "legend1",legend1; "ford",figford; "graph", graph_sqrt; "architecture",architecture; ] mlpost-0.8.2/papers/ter-stage/ocamldoc.png000066400000000000000000001675061306046515300205350ustar00rootroot00000000000000PNG  IHDR&CssRGBbKGD pHYs  tIME 72w IDATxy\UA@f2̴2LrLɆSֵ}WSZכ Zi)jֵ̮0 PE\8z8Z{xy0 Cr `S#VXX= rh2,۶^RX^~aaaa2`('rTYPɑA'X(k`9,e2Jҙ3g4n85kLnnn ȑ#cr%˛L&/߿_õ28p@񑟟ziW~BB"""Pu֩sΪ_4vXۼCcǎRXXuC;vѣG/0sXÇEڻwΟ?oFvZa{'IW~+11QFp[Α`9.))I0az2m+~ꩧ4}t:uJ_~Ux=ZgϞաCd&Mdz|r讻ҨQ4k,XBgΜw߭ɓ'W_`VX)]ZVJJJ%?Pͭ+o QF{O>^Ǐ$RE+VQФ|[i7oVztw~j۶駟ZozT~}3Fo$UV/l2+88X}6lؠ믿Re˖ڰa>#+$$D.]jhoŊJIIQvAwv]L! ճgO;v; pr+b2`@رcOr.cu&~z[NM6 =eXB˟ ]gF N,85Xpj`S#F N,85Xpj`S#F N,85Xpj=F VdaVWﴪ^;[=}L&S/aWu^곺to.ƵVe#Pl8qB<|}}秈%''[c2LO}l-UmgBB"""P֭SΝU~}iرJOO$m۶r|2՟iIsuum۶)y}_jw:x`v^8PEaء$}5nj\pHJJ2z!cᕞgϞƫjyyyƾ}{װiQF FVV3ƈ#,iSL1oU...θ꫍+VFzz'͛77,\sL#&&ܹf{3BBB%KiiiFffj*7N8Qa?T}5vm\p/d;FVVb<ѣ-w6|KҥKMͳo4v]Yy3vZn{QBMX_UѣGJU~}ٳVi'N;sNӧˤ%%% 4*7rHceηh"cԨQQF<.::#Gof>cҤICu$==hذehܸU?oN:Yƍߵ׎>3k׮{QBMEmM;0ɤlyzzZ Z\sw}p^z%uMv3LQFfZ:w^5n|IIIj߾+<.--M^[EӂWVǝ;wN:u377WnnnUyGԪU+M>]'OO?Gztjܹ_tR~ʻ5}fS+&.-^2 Iճʕ+վ}{7N 6T׮]5w\]pE_^ZI)))jԨQF)%%4hL&tر VL5j(ť5-[H/_zH*::Z_(<<ܡR=g5}fk^P~bp<*$زe,X`T]v4rqqؒi!!!:zh=A׮])S($$r-˜={V͛7Wrr:w/R:szM6I&JLLoG?g5r/jVr`2t)I,ÇW_}ٳ֮][&}ڵٳeW^Zn]F'NX6޽{kewءo²UmgE~͜9SM6LrssvVƍ-S6l`͝;Wwygեߎ̦Mj^\n?̞d"Ƣ 09b)))+bw}j=iG15kf|'FFFa,_(e[h߾zjDFFN2rssm۶v~3ڵkg_2Ο?o|WF&M ~v?~o.\0{fYf'|b'nnnƬYl,((ؽ{glܸhܸqLc͚5FXXXދ/XpTi?lJyfcUW]eԫWhҤ1n8̙3UniaѧO6c/eٿѷo_1ze8p9>>>1`vȑ# nnnmf,_ܮio;Km랞S?1|||,LسgO;~sGM65\\\kj7 r^{Q߂B p)ٵWϞ=+]Be2`@رcO9T,֯_u֩iӦҰag}B,85Xpj`S#F N,85Xpj`S#F N,85Xpj`Ss/d2Y èR_P,qcv.0.j bP0Nlȫ7  C nQ$OOۥ7JO>)H~~RVVУ^׫s>QJjZ;رcի<<<Խ{w;v*_:v?ӒyzzC:~]mܸQm۶Zh%KTP6eOyK))ѣҁRr4p9v|SڳGz9sڌ?)͛'}G /e_,n`hpC;gϞz畖Wjj=WtmM 9sF:u]EFF***Jy*J0-T4tvlԣ|t4q]wIM5_uԨ9ռҹs%K|2W_ɢ999jذ-'&&*88XIIIj۶N>-I ?&M(--M-[TjQ?TPW_'_~jժn-ꚪSyD:yRڹS:qzaa\zO~*ڍ߻/AWmQҩTikVo#_jԩ:r ޢcL& ⢂կ__$WWW˱2L*,um駟ki׮]:{̙cdOqwsz~Aھ]zo+<{^RRjgM/w^)WzrtXRT)J۷M&IgΘYS-ҎH_}eG3fHIo!3ya=e~%lM{urs]0UwA~}VEA꽅j3#u63E]tgtiq/G`M mRE5HcҐ!i`άrunaGLLѩg0Wc $׋UQLk…ٳҜ9رd@Ð mkڴ&&GW%%ݗ嫶(T ZI닯M?)+;G ]D:ǡ,)/Ors3$V11M,`Gfyz:17 =kVKpGn^zb*7BC..ղE&,Iw7xa8 *)wmYi9M3nRX$"B>]0/>z3r{EIzZȼ|z)?@k7|Wבv:q tEx{yedv^n2UɓE%{wUMJ+WPnI7O|\fܚ5RÆ̙#T.\&OV0!TjUtL P],zSOᧃzٗɵwujH#-7:Wnn ˖CXpf}KXpj`S#F N,85Xpj`S#F N,85Xpj `L39&Er1U9br\0̟Zb8܆a8|5s=?c^X/VNGO^lZmuKϕ.vU TӐ@;E}o\^љ#ǥ?NK͂lzunZ*?`KMJHQ#6nܨm]-ZВ%K,yM3Ljܸ{9uE/Uދ/(///}JLL-銈:tǏMxjl7 I*,4K?/Г}SiYev\5۬JU~{4yڳ7k|lzQR%O"K|.M/}O*>O횘D;vS^^>p2X}JGHR\9[ٶMTBddXm߾ݒWt3g7Pdd>c|k׮zj˴i3g(""BSNҵTw]-Fa=t{VԬI#5ֲ/;}0zn\?l#95Mo>Q#)zֲ:I?RӪvݏKn mɾ2 ̟51h@vUOO{[1JN9_V>7JI#% IDATX7`߹Ff͚iҥv|ySw7/Tn+J׻9Nݥg[vݽ:]B[/=./O>f/8nݤ3<c⒓ոqcaÆeM& T^=KZppYtIP=VC^ުV5STzFy+=# ñ_)6i..R^*t|U ݗ;(IuFM@Bʏ0+XUXh ˖+ZnСCo>*==]y)''GW^hB}UZDDO ?~\GR]ֈRZzsvM[onw)//__oeoO{CYҰf҅O/*^K:r1?uv7hޫOjĐp"̟_-\(G_mVR˖R.v:t &ooo͜9S˖-|ayo#,a ֭[믗ɏҀdK.V4uh{KKxmTۋ YM]c̕K9{j+ HUU@֖c]' Y ʱ34ecB8s VnnUɘ.f2^Ņ.3#VgXLvEj潪w$u:s=?c^Xsy-~mj$ʦնQ@IuvU TӐ@;E}oԝ̑fA<FX32UXXohm2V9xzݟfM5y`]O(ңҳ4t)ꨵ:Jh^HSGXw$.}+K:ԮX*9hd1#jzvSInnMu~ -Fa=,ɩizMѫZW&?_/k3p{k-l%o .}V5Ӣ(L~yQ"KnҹLiUY=ػ/A[wQѓܱCz6ֆWٚ?>ͭEJnKO+7zUI+Tf\倛$5 nmY?~u𗥐?{HST*S[@*d2 à++;GS/ҢyO5,Zjr.jێ#P}r _/=5uhҸt0N)pjj7ʫtu:s=?c^XYŋROI+M8Z^}_5q@5 ZZƕe9r\,\t멱파l׫};i]ycM?X |$I)izٗ:|nx]@t\+FORwYUQ^ɩGaEcjm2V,*?qJ:j5^)z4uuzIR'IRﻤIZI#KQ3g;Λ25s,-^^#jgԺUs}z%չտzwTK^-jݪFVTlS5~xrc SOÒozZSQ^e(ww7umS\էԨxK϶Vzu(NItݭ C^B~/+P^~2~^$_/efe[KU[t*2HfyK9?_o*a̶j-슸GzUid/R߽;OE+LPVyAl5VFf=-~^v^=1i%R.=#|UҳGU.+&}8E˗\soèZw_أ'չc=7ypS[#ͻw֛[ZU[on+]vUmmZj[~]Z[",Pڼ[W酒zIGN8ŬVwA^}R# xJp04v\w=8%=5U[jgUt5v\؝9&h*]჻+I2Wn5itkq|Nc]' Y ʱ}:4eAA.{͜: @&0+#DUv3鋴h<B8(Bnj} 8rr>^zj5 ФqpŹ"B8+z ohg5J/nkoJ^m(帨>xhu5T^]捫tފ. 썗_/9!zIJ;Wn}"NڽWM3PMCu8Qf/8:?W*.N[#|=wӳ_v9e{3R4nsО޵}kQ? 8:&TXhT<[ni)U~{<_/\9u6]Rr5aUT_Zq%Ij[{K{:wl&PP?!pu~ ujU:y2s)1UrsU[&!4˜3WfXy5i7s<8)agBS#F NVV-[=c,pessN>ࠆKآN]c(-[ͼ/Em'tk_5q@5 ZZ$:eNaVa!X{ մgF߭T_|ĤTzqIgY-~*mk67ԾI~9pT|m)}Ew W+:&֒-ju]3_uݵMb}yaЀ0󫞞cbr\|k•ruuܨ ƒP}eQKO9ޡ9#U i<$Irws՟):uj̣TvS䃽+Oѭq8[oiYk/Ow:f  UWz0Dqyyz+4{yTq .%IRfV%=#3[S^X(Ð ÐTM7X_|omIY9zhhOuھFKT`#-7;KPVv⎞S"t*y}YY-Y-y~ʶ/&*BYֵTX03[7Y^5Zq%I `U~>JI= 6 2uu }{]ݬ<=K_%Ò%o/OLRa!S} ںc⏞Tm NO!,oͦ7R^^6nޥ[o.Fl6*LY],|gN<?"թK6ZΥe*''Wn/S~=J}fnz˵V\=ٶMu]kuM-+*?g!fݷ 1+..WS௿kK t2257|[_c&eZ;{qWh+j Q^52o%,/]--_`Hɵ;e9nV׃zbl%Ԉ!=+2lнrgU1s Ԗ7p1a\i9&ifu>ą.3#vEN!XpjWdom>puv:שgP#z[\T6‹’)/uSCcT-[,m5SXciHע>7^T9!}UDZ4pNu:vFF ׫\M&xJTPPX}~jP..IRJj_9k'FW5d]5o'mܼKW7o˿%HvшyGa=cj"D Rcڼ{JJK*=z)@ZNfTP(=GҭlGB7PZ]J˒ us>v q)(k-5#jzvSInn"k`eehY7ZtFaIONMӛOn^ՒoY/?=,Kޫs z VujgԺUs}Zh Nܶ_϶uΛu6ՊUV]C:!}t]S~=~%?%EJ/9YZ9S9/_n\5m-i_s"9 WEs&ShKzΡmt*Ւ}|}Q_#kxrc SOêU} /ָ3W*kLIOL]yMKz~ݣKJ^Ҝ{ͣIt{z0Dqyyz+4{"?\&KT`#ڻ/AWmQҩT2E|$I>^ʮq3[뭬v]CFvUgTRjBԨAٴsa?&S?+M,r1VUG)Xvw?\GFQ[W~~4*?=#[ -ooOJ0r,y{y^~l+%4"KnTU[yVuU5U޳w_أ'չc=7yERVTi]:Ѳot.-S99Zv%///_~^/ ߕ)]ͻt-x{nKo~-7k}wIoŘGbe_>X__/ f҅<vzs]Ϛt/{/ՖYhwF A WqWXiB=Я%=5U2 Cw-S0 2WW7 լ+77[K5zbllD k ~KZ+=-˖C@[\n;K`[2@R2] ڵjKu͜(? .!aPsc<]s `1NXpjDɷ^j%Fp);w 3 jtˍ-.Y{M%S^R뤧H!W9ܱ ;S[@͸۽WM3PMCu8 鳭%ҢsFX32UXhl3OU&:g澽Jsf$*:&wqQ? KVZjxM14R13WҴ٭oݺy3]~*f5ܷ42ДŤA`u112̙̆HK9s<` պmK",XUzkڲH32)+oF\aʽ3QjX GG,{E УkMKDnu9y .M1{Znc#<2;9"dX?=iuS/\341Veh uG΍۲;dg" ֔?4Ԯ5i+t> ;~F{0I_!8ipui|KW~ɳQiC] o9n]cƝPrxiG мΜ@l!ܸ{:+@ 겫%}z(ݠ..Dۉ$c.KJ]hޥ44 "(+R """""""} ~Kj"¥3ڵi_@6piwТK?߅'wŌyK EbHǜ7&}rG W~@prNJ淵w`Y܉/cVgeHwk'Es/=H:Pݻvā#)ѭ^cs)PI_UThtFsI_}cϽOB}OG׎\ue޵n{|n]ۤ*A{'Vq.8JWR~XBCzvi󺙯]н!&^()UK%$K`¸"""""""cWۓL4}zZJnxu< } !0ehצGl K@yy[k!XcV;s]kiKo!<0}P@Yt3n_#O<܀CͫTY,ͩFDDDDDDDDs`Q} ,""""""""!k?V7Yǜ~l]N[W3$+%gI[.֪V?!E[Y=xrNJEW'pfZ Ah{Yi-}>ŵ-DŽ="vALz&P4qnG:gⶶcub[Qdw&:͖Rbjٳ>ϪI[sV}ĵ г8+,ǐy5sR&:?"""""V_0whkbͧ;ҹ ^5iPZVc'bD,zWcƝ\(y L`=}[}"OEoڅq/B10Yi&OmGE5X'"""""=ҬߋQYy9#NckQ(Yw-u!R3%0K1a4A\.ͻqU<ܩ f<fM=u۷&žжM ̏o/w@Ii7™hӪ9G7"߷ l?l87ƐA}%vRNVE'"utl3KiU[Cuh&|/D:k֯~<}L7"U ŸР~긬oG Ю/Gne7o1%&j> sj޽ D'Nw+炁qOF%yh`@ <3(.>8u; sX*'(8t6 hso;@V@i:pXzC)@p}$"""""XRl;M0{n`"bS~D9N, Ƨ+pүL%bW_*0Jd}·n? +~yn;dV՘H9 ^yc5VSii9۵n;Ν`S궶K鿡{j#9cfWXK8s>s[|Y]"=@χW|vBe@ܻڴU3cΤ[ߧiNI/k"U@`ׇ=o[ $}꬝xbil^Ҷ}$"""""G+uׅ;a`ȹq[־;9\ܸo%fqU[nc#<m2Υe"F#~iص{x8s\]?lҕ_Zߪg[ CӲRեȒ1(ߧN Fpsm7LwmV[Vggڵ,;Ƅqډ b[Qiȼ54O/UbzWNJ[rWBma/=v}6ȾTVJ?;PXl}ޝE@`@yiM=Jn ծO`0v8\ZVG'JN`R(J{ O FA),*TpwsՅ{zc(46T~:s.GFzؿ;^?-{٬m4iaɝ"~_wӲ/] Ԭ-yַǼw0G] U3h^2/ok^C{іʇ1ڻw5@B4wTI5f^{v M'{ȸk=rvd~]I.悬_Ko ҳ**4PB1H)TTh)Qģ(--B۸SV~KB1{tؠGÞV%h*.>eG \qضiL*o<+a6kbŬRepӟ]潆i@Q.A*w?>ک K6ykj0'Uqf>Z5i ؄_3ڊrݶx!0Ae2F* Ʀp9\.V*?K-zs]ۻqc'tl<>1cRtl sg1J00lKf߀[ GH}^^vmZ7M &Ӗh-<0}P@Yt3n.n>݌> {S{WE,rL N;T.j4VwcxuͫT~,~ o }k N!l]C_Cۃ.֔["""""?3ށE8@DDDDDDT8 φl""""""zB""""""""xk\o!4*K4?S͜7u~CYV_ zT$}u7ne Ln7jĒ=Y_I&@NK&u1wL Y:?"""""""V_0whkbͧ; g֣j"'vXX*55, zYcuR^X0g ͚zoM<}Om5^2Do܅33ЦUs̏ GS[ L 7@;uWQ@?P߭}D/'(8t6 hso;@V@Us|tޝ=.vWoh5%o]y#}ɉOյ z.Lzf({׎88];גe +֯xy?Jo{ee%|>q u[k?Y<b2=^_|Ժ}MN$M{Vƫ '{~HY;TeN܎^$y- L v/IcF /xՈK8[wx """"""C ~룕[e￈zt퀳sѭ}-BGѱ N2u?tC?WlR!?׀Ԟ_ON3C/ڷxxa1oSUqje9~x.XmԓO˯kMHлCxqxd g"""""":szaݺǺ;..챲u\b!my(]JwW%"U1^~}%P(̫ZrTa&vJߧiʾTVn*lUwGAv; =$1ȁy#}GDDDDDDDkXR.MѮM ڵKg8 PY)pob`41o^¢bxzHU w7W];.Bc'Ig->j)]CJ _(]Ӛ3id*cW"݀r P?MUY Ԁ۽p%mXH;$ߛO`:s.GFzؿ;^?-{ADDDDDDTG#֏޵#IAn_5kKzax(]EW{**4wzvX_{ nNYVڴe=v `aG )]KE[]N~]潆ix˽^]@qp3_L8..`6!0>^2 QӾRg؞| =J̘hV̙8>c$nua Ʀp9\.V*?kM N; TQM@kڻޞj.b( ܼ PtO<xw#Oޙ%V*Ѿe[KoEoN噂>R!+6g""""""""zXDDDDDDDDTq?['|&|_9o4YCҷ}U9v[+9 ß@DDDDD CTh<^'ԚfsE w'5oDZBuȼumOow[M֫=Ǯu3Ùt`'@߁v}Ρ\@DDDDDn ӿ`h/_ŚOw`YU~h#U?B!_|: |!"""""=ҬߋQY)t;GpP`s#ЧWZ{6KWp6|5mߚxB6-0?j%e޸ ggM>6~~Dͻ4wd)n%\00)tUW٣_j`j(T{xw»:*L=v.5[ZN.A{;y#}Ѣ:S;EX+ѱo/euo4#mGq(N&_xx{*XRßRޝFԾ-'(8t6 hs/݂gOw `Dݵnl2~o{DDDDDDhK97¤go.Eا}-YbWxWVVb' pXuQx(]c v!/%''Z߻4v `@ܻڴU3cΤ[ߧiNI/k"cmk>K1ʅxc$\d:[=7fdRNWXø{:SmйSt[{Cs@GMN21槆_8m&> 7V?]mwj;e! \8'>ZXЯ.|h uG΍8 mGFx*3~2;9"dX?KԅE @c'G 8d%GX׀Ԟf)p!MJ(]jÎz9N;9\ܸo%fNizx8s\]?lҕ_- Wt34ΧeCE%? ~=/-틷)V>@Pv+ֽ ڲ?xDDDDDjo!snM HBSΜ@l!ܸ-C PB.w*˯ yu0v%wE.ڧyQוyñsK1q| c~弍.D.эO%5Pn wv:yWmߧiʾTVJz#5BDDDDDjX>fPj O FA_ Eb==ܱtqXcG*?{QjitM@F{ym~[{,2=;siYX(9qbnY32pigТMXnMt㳰H 7W`[G `c۔c[ 䫴]0F{cn@[(/~Y#"""""amGӬ.gUThtFsI_}cfS`Sٽ./=mGQZZyXqaOwb풾T(mS  lإfvAx1TY,?SVێoB2\uCB1c$nua Ʀp9\.V*?KzPӖhB8ya+{f> ,L7cY#O>n|yu*g-vO<%|k  K@yy}ͩu:v Uщ1o):o3זֽC _i'z 0 X { x-֊ ݜch(OڵeGDDDDDdk !`3Q}& """""""XDDDDDDDDTq5N`Q ,""""""""8EDDDDDDDD'^k"R@@8~qS(P(l;Yee?cpvvnXcNIŭ>7}PY[57V'`#عN8FBdd$.\JՃ>~?NEDDDD(ğW`ߦy6WOBzf-ܽ{Oqׅ-ܜ}eIyd_m IDATY֊"nߦy6(d ;<==1f\zU@P ##cǎcɺG}ZhYfpQGT*J%] stt;z( //gF6m???L4 ǏU~5jJ%<<<0vXܺuKv{I/UގӧOm?iii岶k… ߿?\]]t_~hҤ LP(xeWNٺrɜ u{[O䶯Toθ5^R}`9Dqhj !88pwwLj#pŚ:3ǩ:I1֎ϟ?#F(88ؠ;DDDDD 3==]-["RDBB8pf"$$D2{nxĺuZbƌbʔ))))Ch4]ئMD֭ף>*RRRtŒ%KDnnΝrcmY#G2#&N("""d9k[nˢ]v,,,111m۶&<))I.}^=^ddjZ,X@OL0A/0mm+U^9$?8۾rkk;n9sCcS$&& JʲYXs^3FшN:1־ֶSps򷴝mu184ZŚ).]?^XΝŏ?h2g\~ ^~~ҥ55;9ky4vǫӇN8QݿUzƒscG)7)4;bО8m:YfឞF899I_~h޼nuFBBBp!@ll,&Nxgعs'BCCmݺ}ٳAaٲe(++3YGQFf-_m}٬Y3n}^`0k+6uym'KX;~y>1־+{s9aujUקEX{^ҹsgٳcǎ=X;pm7\R3""""2OzP\}sՑ:7v[CSBU rgcBU\j:Qf+""~~~矡h w ©SPRR-[`„ pl߾˗/GFF2331g$$$&-fij˚ح mdkuN֎}Ϳ>[sêISj1\4o޼)SNņ 6l3l~TVVYf(..6hk!qFDDDDiXw/@̲K#Y NQDU[ }O7$ލ/aߦyػѼ7ISJPP «2w}Euppr ޽{cE˖-uA˖-l2^^^57tسgcro֯J`` “Xk߿n}^_m#[vv|røqo>V/?;v[w^ k w0K1p ?]qFDDDDvDfvЈc.g*k-VoDYFlzB|vA^(\M/lbm1Q\R&nJe>ddd KVdѧO74hYYYL\|Y i/^,DLL^xLLprr/{ȑҥKBш\K 6d)dbZ=RarעE "***ľ}n=6mڈQTT$DlljJ" }+׬E_m#[לv_kھ9a9{g@@-UB{{cᖌS 1m4cƏ/&O,nܸ!ѣGEhhAܬ,ѻwok.VEIIسghժ38݉/iORz SU?'FM_%-R+2wQ+.)YO<=I|&O3.R4"$$D www$RSS W}6ǏIt]|嗒'nJ?x=zhڴhԨhժ={k--xRRarOnZ888m6ݶgϊ`&Dpp8{>W*",,Lddde嶁%mmF.9džqeck67sX{S&crCSm%„Rnnn"$$Duܛ d|;vL999b]#GWJƽtիW/k!N`?Q-?6cCP@ SLDDDDdP(b ݻpf͚9sqx5"zڵ hݺ5\]]3`رXp!8 ޿DDDDDd3!$"""""""w`Q ,""""""""8EDDDDDDDD'^k""""""""zXT/?DDDDDDD8U)Z,ݯ-eOVXU~g 8ε{kn>rch45kVoC{!ko1m4t77pA9990a<== &ƍǫq֬Yh4<0LV='H}_e'Nإ,unXp!T*8Poڒ|I{T'c~Ձ⧟~¦Mp\v 1c ╕aذa޽;\,tAAA(//7;^]qذaxy`s&> 483s >[_[b*_]wޕuF}(o]S(ݻN͜qXǢ}/x¿kHMM]| x3fpHH֭[v Ե͟N8 ~Eϟ?P(J(J_UVL>]=99YQ-0k,UGJ>RT*q5].ѣGVSjj*BCCOOO3W^4UGƨQT*ၱc֭['pppB0yw-{y1BW`"'ٳѦM899&MeSN>|8 U9##cǎA9*ͅ п" HMME~ФIqLL Ə/Mצơ9ur'fkr΃5'+._}vL2 s=rU3pwwLj#p6JKKCpp0<<<p[ 2"hrTw]|YkNlٲEB#ڶm+._,{?ĺuZbƌbʔ)fE!RRRh4M6֭[?X/>*RRRL?==]RDBB8pdYjcHH8r(++999bĉ""">U;ۣ/_~~~bƍ@T*/z!- rۥfyŒ%KDnnΝ6grUj$%%^z!!!"%%Eݻw3gGFF Vł D~Ą ta/ ӧ 6X{Lvvԩs˖-ENNAׯ ???:N(JҍUegϞ"11ָ?>|8.*?>W~ Јg^yj4e|K1rjٶzq>hrՑsbܜubhqtf0`8p&&M$ ׬Y#"##-,,,>>>f_VVV ___qI]СCŁĀ.}}}EeeGFFJ/..΢ {eff ooZ^lN4I,_n8cbbļydAn,7`;%]$ox>o޼i#<==kͣm۶֭[qsZ84X%*K,?uDyyArѸqc:N$j @bǎ޼yS[  BɧN.~&5d^߈Ҳ nql QZV!K\k97c$ѻ ZliĊ%UL"{=!۷B!CL$G}$csEXzaFVζ(~A|ѥKYe.Rw` )]STF)5Yax/--}4V&MHɜ1nN_[;9eyP!Ν;':t7iZXc\ZL[  n ;LJJpEε)*ƎǬ|LJ<ƎG[N~O-ey055Ç oڴ) iӦf3CrJK*+ㅈϨM`uk7 pP(,O}ִRxyh/<\FވQM(???h4;,.SPPN:lٲ&L]xw} VvgيuVخy{{{c@ff&̙ݤXl.34Ucھ6uV 2oFG8{AgϢgϞf3EsssѼysÿ+/h&DH_j}{csxW{|[tOKi=ܛNQ N@!_d@Yh"nڡQ^^nդF޽zje˖l˖-C߾}0&((Uwx=Hl/Ç_m~qtծy+ ܸqC7={`Ϟ=6mWc`f]͛KN3ƭksl|Rii)fϞ~CTTA1c`7oFxxLꓤ$}Ɋ[PP-Z[ 1 #",ߟASGđZꃵ{ņ'DYF^+uVB[/~%ѦM#DQQ|;^-DJJB! $DVV(++/_/Uo[xpss111z111I,^XV]322ЦVErrӧdY5}igs/[7++K[ڵKjQRR"#Zj%-: F).]$4׿İadSn*J$&&ǩ[T̩ɓō7Dyy8z ]Sc[y0--MCL2ET*ݻ_|={2:N#v!jn{ a@@--DDDDD|o*RsEee7g((*ћ\26[yEbޢ/EUo!ebo!4wŋ~9{nnnMg'Zn-ضmB]?^xzz '''ѽ{w_+,/ 2VTUBϟ?/BBBpwwAAA"55U2:۷9u'g*KDxx{%bcc-_RRaGM65Zgyyyi>J >f [lذAr9c\N_kuBvѣG www&F)^*\yՠ~CFDDDDd;6!$"""""""w`Q ,""""""""8EDDDDDDDD'^k""""""""zXԠDDDDDDpP(jt(♫e~g 8v2eciE]fͲKܯll߶Ν;h۶Ѽcsrr0axzz &L7p֬Yh4<0AL|dx:qnH,\* c>cMk!((N@] ,ѣeoγeee6lw+W ++ ݻwGPPK _5 q?g;d+oӼ:Kom~uBwSgKk3/{-wBXW_DZTײ{Ix*-|޽3gΞ= wwwZv-|zᑑ3fܗ1u֡]vCDDDD4ށ%Qß_avSs R RP?ߪӧ'''jѢf͚BꑝQFATcǎŭ[ ?#FЕ?88XRө ;<<<0|p/LS( "B@FFƎ ooZ;SF[,U<̞=mڴ0i$?~\v=崯9DN_9V\p+TM4AYk`۪cƌիW%=֌gs.5f>lgJaa!f͚O?nnn˶oߎ)S?sHHHWb̘1􄻻;F .HQZZa4.#66؉')]~.|h׮زe(**"&&FmV\|Y~u Z-rssŌ3Ĕ)S*Kx!!!ȑ#L䈉'7RD||x衇DvvɼӅ96 IDAT*J$%%^zISn̩MHHHIIeeebݵu[TyŒ%KDnnΝ6grqb/9V"##EFFPb_~b„ _~Y΁RuKHH45ǚϘ3fٳgך׬Ypqq ЋӲeKcOq2p@/T*n,={駟уN`}u7g?7Z<ۦ..%¦sE-KWSS"ljyI8Ocib64i6_fPX5w^LmP -&&F̛7dޑuOJJ2z*L2o[ {5HYegg˞۾sԱrI7oOOZh۶uA͚cV [L`=8p@BU*bÆ "//OJiF߿0`&*|}}вeKOʘ3U\\h ׯ]t1T*eS&[}#ul鸰G[TyE@@ؿ0rגqb JKKu+++զI&e2V;wXyXrΡEEE}b߾}+99Y<䓺϶*((5 jeeeŅv`8;bG[N.1iT?87vȡ=q:-[~8{CGv~8yMƖf͚7k quDFFyuolxFĹ}6 ^a+WXTwSk)'''oMn݊>}`Al2ٴ}-'cYo}#ca)++6y_kXn|yo ZE%\بP_AQ)<=J&C]J~gh4۳Œ/.. os[˗/GFF2331g$$$`ĉ6m_[u8;;CnZm6^֮] 6Lwp'G8{AgϢgϞ$ƹh޼A 4j4 Q""""՟->nHZ_¾Mw7z*N⢠Ģ} DRRAxRReâEкukE[yyy ?]Ld׋ho-B7nNDDD`Ϟ=سgMז~+͛7p3VCټͩ +us gO<uY".]mڴ111HX7ݵhB o>+bРA"**Jdee2qe /X,ѻwok.VEIIسghժ5fdd-11QX.2%2ڣg0bȑ{PQbe>GHy fb>%:G;I==Z'z4 ގwK"/rGP'A`\X{f>W^k=׮]jVTpB>|yVc1e-MpRRtI=qIΝ;\UU'Nర07׷-CA???>{,WTTصkWNNN֥ŋy3peePw^h4j-K@KTk˯QKgꍁE5<<2fosGLmO<*fܥ>ĝtLIKK㐐,9$$ m޼tܣG޹s'33߾}Ǎnnn۷+RsLmv;VW>BǦshh(rV(G:3c#hGKXWݸ 2DҘV)-gj{m6.++RnݺqVVʕ|A]JȫW+++'Nȑb@DvZh4R8&&L"9AAAdVTjοu OpG^nXs>#cV; \X]|_}s-:NWt_sGƬov-s@@ֆ֭3gm3g,^<5kO0>-77-Z|UZZ;v(ggg...ۖg޽{ų7a޹s޶lrxr~dzgG YJ9bZSSJSRRt^z%o_o1ETrMM䲥QkQtXӎ.ZHFFٓϝ;g֣.`O8Zް4nߔw6\=G/?>ڭ۷daް4WTjySz J-ضw&sE6qZhOîH+J.,,4HWPP^^^VUUYTv||[I~*:t`n+y{{<ݝnܸ!t~ 儆ұcLj(>>&NHDDǏ""ڷoYtRhm?9J#5sHBj4c Zç+tLA1R/hT*+SWિ`n_C\DD؆jj~}|IY^=¦>JhhرSiEFF7]x~i唓Coݻuu{J\r:uDo]uyW^^.t~կ- ҥ 98<UUU'Ν;t!:tAZcodKLL[СCz222w޺GA'O48ԩSԯ_?Ɛ:ۢwwwzhժUT*ˋ:vH^^^l28p|D˶Ee9b5sH5a8p mݺ"""(++1DK]daiv$Gk~|m.PeњՎdn m?k 7ECܥvwڕ⸬8>>fOg զEƶ{zzrjj*kZ>r+Jff~x֬Y|u䬬,6m""5j_vYR… yuo!=o_ZZWַL4h/[LsYСCܹsg6vnw^h4&,S̼h"wL\\;99E (Z:JgkњA??!!}||%:h XO+y^ ?t2Ǿ#XÉ^[4WTƳ#g4XP2[뿍V}͆[Smw2qHHrbz{2&CSy;;;7&Del߼y3w҅G7ݾ}Ǎnnn۷Pk}w+pNM6ܹsg墢"z^~G r9rff^:139sٙ===yzo];v.g}=322888]\\LYJ9څb{Z۷ .h"3cEƈh }^[l4CK2b :ivZSI \:Bd2j 9 MkBKO3OvE@qDK;فKB>s541a a a l&00Ah1G!N!hZ24̬t~ͩ#LbٜT\?ԹQ[s5uacܩo7scc\\=0~e~rcј~EtZpThȦzFL]at[-)g`mI`|EDtM3f ӕ+Wl6ƻ.y2D":/?"cVs_K_ET-vcͻRZ׍7Pvv6jm7n4<:܂ܢェ,h-4$Dġsee%ĉ922R/]VV{{{ƍj5ڵ}||8//lW^姟~xذazuݻm۸KKK9..uYYYfI걡ʕ|A]~AAAdVTjw322gϞ|9?2Z*}EDkmϻ󷱼}}}<Æ 4` Yr_}~~~zmU^^8RSO=e R*4 9I=h800=Z&q6  XRb*zzkzO2?Cffu8 ƹ̼tR dnjh_wcP$9sv0@o[>}Ik,))1m2Ļ6\ի?~XJ~47Z*}̉kmZ2;?Yf Ւ,j,펎LDFklmڴy4Z͚c***ٳgs^XPp`` /]+**laA X XRb*~x稨(`LO33'l2ff^n/^۷oVcѾ(ZkƠ%$Rk100/]'O4Xв&jH$޵?Z*}oMλcܽ{;usrrf,%['<==X"ݻ Bqj*C4֦λrE2U/su ~oݺ_c\r9+8m۶?/j,kƌh_w"cP$%$2:kϽ&Ok֬i쉈5oo`Ļ6x駟XTٳgm:w=6Ji_)howx~W^ghx(԰}dĈtb1u IDATIN~=vСtq;[wPP%&&HAAAfoTsyxxPdd$:t::tҥ 98<^ ҹs=GV"RI^^^DDԱcGe˖Cb̈E~'2E҈Hoƍ{ҽ{4qD\MLL`xך0a 8nJe][*}W4f̻֘2e ZK'Oƍ"4 |7+$﫯.sYСCܹsg;+--{kRff&4H3/ϵڵ+qYYq||[9QFk׸U*/\`ǍǓ&M;wpUU8qŒ>X2Dc,FIII+m OOONMMeVGaR)9I Bu9s 3{zz y!!!,Y.sHHMMbw+:u6mpΝ966^o+s˖-±0xV낹B$86ԾМ(:NEcf,yۧjgϞ;gh2ߴ>}:ݛϟ`@۱c߿6oތ`@qDGzz:З_~`@dtiݺu4 72999ѬYh4)| {=5,`]5,`]5,`]V+̴zj0`oߞڵkG>,Ϸ8d2dMvj999Qn(::l^w XOG[Rii)T*/4`VfnMTSSCEEED}CѣGl{'ixtdlRI mΦ>}LfZ{h~}˚m]oƆo`Ј+L2ruu5cNP(HPPHH+ڟ]r}HٔAmے-7,,LWnXXr322(,,\\\͍ƌC7o4YX sիBe7s3f`]V+Jͣb鲳)88ƍGoߦB1cЭ[$3vlO* DѴh"ڶm?Os1_xx8M< (??),,urrrt )??&MD'N4YLcǎQ߾},[$uXoÆ `ZOLFw!LFD~UVC_HB5PA1—Jԯ7}z)=\uy9u"ApAW_7-,Uy^K}ÓJ. )$&Өj;w.mݺiȑ4j(֭^h4h͞_x:w-_\R:P&#"{޶;wP߾}z{)&&F/5kPrr2mٲ&MD/A۷ LlE%FCٴw^Zb%$$͖-s`Zi˃kyZ86Jw^mmh?9SQ':Ӂ)|}n.qIchk9**)wbk꧂-Y}B7SDCscC<SyrppcTRRBҁhذa~zСyyyŋK?effJJgdTQQADAF^^^t%R*z/MWRRB:t-bQёJ%3<`"0wp\r~̑^K wgQ/ onh'Sȷ_7rrlCaCSfN^cC@Ώ9R_J|:j|ƏO ,,X@~!ǓZ&ZM۶mŋoѢE@ji߾}pB>{={.iZ:y$}BujXH'T]]MG5xfiu X Ξn4(_Kߟ@Z|?E}#=Iax0}c ]rWWC@o/٭SWb"|2 !V[MMMNII^zQdd$M:ӥٳ'ر6nH;w&WWW;w.})91϶+m}Җ-[ˋhtѥի8p6oL^^^T*iʕuV< *++޽{;-]֬Y#T'[BJZx}4zhrvv_V\Z| ac0Ah<3,`]OX`װv X`װv X`װv X`װ03^ @۷vѳ>K&2d2Yo*NNNԭ[749V+ѣGi֭TZZJ*K:}4 0āxS13PQQ%%%Q>}hСtF+SWБMJ~rww۞M}iU#2̪xO&5eۺ SWgWDDeeej`Q#==IPBJOO78V4]}?r Q)00)##Lm۶%???5ZnXXܰ0fddPXX3n޼i>ۍ4իWn(Q3fV&44͛GfeggSpp07n߾MCcƌ[nINgLŋ)>>T* 4iѢEm6***̙cPpEGGSXXeggR~~>M4&Nh>-Tǎ}6XH|ާLmܕB97[D>FD|CsOtߧS"z4.4imM6*//{VRrlLS4ɼkjj֯SSBJ<վcԫ['Ozu&;R-M<[%5_RH!ok4)Rȝuy/-'yڒL&|=޷FA'O4Hw)ׯtD)((Hwpp0%%%;v|;t@yyy"b!%Q} =(X^;IE56NVi?#J9r _""-eݸ#\Gߧ}f9А!CL7yd:|ƏO ,,X@~!ǓZ&ZM۶mŋoѢE@ji߾}pB>{={.iZ:y$}BujXH'T]]MG5xfi XI[ xZiӍfwEkri^H o;) 3eoKWn 0j%<8b u7QLd]OcbWSfV9Īsi)))ԫW/$WWWrssSRXX{t={;vƍsJsΥO?"##%3Vuq%O>tAڲe yyym޼8@>>>tz͛ˋJ%\nj'_|AeeeԻworwwKҚ5kdXHI+"O?FMʕ+1]ko!l 0!{,k !5| a a a L Da zuЁ^|Ed2d6Ok)khIOK`mO5VhQŋ@z4Z~'if)5\{K>vn @ ,`Qvӵk(++Kұ(i-eMQGqs>(QMjouۓ1!~ hץfjmi}9Ga 4s2n3͈+ȦVR^-)yZZK˓bС4gJII6mВ%Ku,L"&%݊2~y>eokI}͖TO[ac~"eε\ZĘ{n[eq=(ZV ,K;Fţy=ʎegg/B#GiӦ7|CFfddPXX3n޼iuZct_Q3gRii)%7oҘ1c͍\\\(<<\b.==IPBJOOS3f++,,LWVXXpYѥK(88r9Rhh(9r ]^^= RDDݻwO8&`E%z.|||t3dYjo(H&ܹsT?L& wwwtEEEK]v%'''(:uꔤs]Dڸ+Woߞ);;222hԶm[\fffRHH68ǖm,%O{h kPfe|}cszeWDo9ϼՔsٍ7eggZV7f.iڶsĮ^o 9OY$yK-z6yΝ;~mw^tܣG޶mZݻws@@ZRҚBDvZh4R8&&L"|]XVsii)q=tYYY7n䒒Vռk.Ἴ#ZڲwﮋgmuYYYfZφbtU~9998++ fPw"Pﹲ yĉ) v07xI9ZܳgONKKx̙qҮR`j섆rjj*WVVu邂xɒ%RX˗yСfcv2&9''5 o tz-9rsgxϞ= Rc62ޚ-lQOs}Rj}!Z2>a|Xך59GcͅJ3GƬogUZOS^#g?/wTV-`s@@@骫s|ݶ7/l6::׭[g=!!`VTii)wꛕ#"NHH0ؾzj(^ܰMx6]2իWstt)>g{"՚hw-0>ka/Q+2Tsϼe/sbyذa㳡DSyyd*zg^sVs|WTKgIeff2Ye\Q'3xƼ-B?^e]TҢ}S3nrh^ R>)}|1} IDAT}?+Z KJJ2XRzەJ%q} JJZIʅ %%% [Ljz)T< lR)R'R*JrS)iSus^zǭs"7"qu64& @>z(kZǤhHDkjjLn3VoF#4HXxk궰E=I?\Dkai_k{jN\yE4u~-{>s5kﰰ0޿me|gs5K>J-vJ/o`U}?`f_ҭ1>K>O+*<͜>eLpj9B(_|㖊j,TYU#cV/p?9{YJZD_l%KmkӦ WWW MPRQQQ2Hϒ SJ~jQ/ڵkg,S_'cD)#smktYr.O<{zz}.b˔"={6Ջ ҥKn"1!zN6U{6E[XROshnnZmy l!7\1"hM5'[{_[2ݽ{;usrr⚚FK.`Zct?ӭZKcn=/^}s-橌MͿRv=gZO}ܙ_關Bt/}sFvboi_ШUTU0t7vhGe )/(bRW4z 4m4d2Z~=}z=<=g;-_rrr(77|Mڽ{7M8>))2TswoJHHիWٳP+,]G(SW:z@ؐ?7t-_fjBhK8-FpzWt2,-M<[%58K[nrJ\3o 4o-T5z׌vf&'''t郃))) cǎl֘g|@]t!ݶsz&&&Rpp#Fɓ' ҝ:ugӾDFdXzhСtqmԻwoQv&^Re„ 4p@ںu+EDDPVVV_#Ν;H:t:t7f|}TSSd^Ϳdkq]>Tsٔ)ShժUw^twᥢTj|V*|5ڵ+qYYN"o!hҸo߾7dffAxٲe6 H;S4^KBB=/ U,%nR_cxԨQ|5fJ .Ç s}""eL?5 ԽT?>ֶ5amf}\#>9]sEjNZ8i;vϷf|'~Poucy~0#+ ̭MWQ]=kїtk N/Vpuo`}Lټy3w҅GzolIKK㐐,9$$҄ƈH=̙3 ,ݺsv0h:777o߾W-/<`0R&Ү c6cw+:u6mpΝ9661 h~:9 XR󴧶 Ik#ڟq\K\'E}W!Ys/{jN\yE4ui7nG9]@ٳ'[uMf|[+0`n\xy䌕o!4P7Q1Ż823_Ky?wpش/{¹s ?ߝlhԻwo?>тd2e_p̓N|8͝;u+~4x *5 -0ף8ki:[}Dqpp~Iќr͡`_c9 )cs.6v,4k,:|0b }vZ޽;&T\إK(88r9Rhh(9rD/Mzz:B BAaaan0d2ˣѣGB WWW{{L&3fmɡrww7H})**Xڵ+9997EEEѩSo-{xx!!!Bu7%))IzOOO9s&M{M3f ӕ+Wƾo.mdikoNH& ?'N0ZM uuN8!iXE1#FRGc79s1LFW\!???j߾=Rvv6eddm۶Gskƀ9Q$uqBBy2su\t~ҸHk2duq k\c9)l رc)>>ަOQ?7+(33BBBX!D51Fq tU~9998++ uO7++w۶m㲲2.--常8֭geeGD=WVVraa!O8### 6|RSSu%KXRV˗/СCYyEygee7oܸKJJXV]LJ,ڵkYѰJ☘2etk.Vպу_nQEz#F᜚ʮ\]]۶i&ҥ gzi|INMMRi+KLcQc7ss ι999ho<'L[oȑ#-֌9ќjݻ7m;ZIbM_ƀȵTLE"ս^ٓ< p2ǚ|Xo[nn.K):s}RS3m˳yGEE ٳg[UZܱcG&$$[)ul,6.`԰R䔔ݶ^z[׻S*\SSc!2V!Vlo{sMſn?{Bvssk[:̉ 7o\Roے%K866fe5}Śfs"6S19##{Νcn޽{V-`Yxci{j{.Cm?"s&qof5w޽uc X>4Xh XJU*Ui ]^^ڢUUU6O]AAAGeVkӛ8V*\PP`p|qq1?S6Y2w1-))17oooXj5_2e |-8p 336sssyҥ&\KLJXZH[Y:fcs}Nv5BwMMmsKǀsP]׮]mӧ6+S]+\7H\̿ܫW/>~p۶mkr,ql>Jn׮PHRE_^Q\s5c]t jbM6z?FղU%kSTTijg^zB@^tއƼ9::2'rT?|bdzֱ~ܤԱ1D:ZӟO>XTU8  W1{\W%\EQaE\?R=v'LLJVɊnPrɯ|0&Ǚ;̀~=r{{ ;"11Q!ĺuĪUBL0AZܹj1ki1j֖sk$J,)f2&oܸqԩSB! Z#k?ls@JߤŜ^^^bϞ=( 5w<,=sRZĝ;wC?k[:%fbg*!qFu<==j ʵZ-<==;͖III8{,Ν;_|;vY:)!S[[kー<466echZѣh.)c ۨRpqa۶m9sa;wבk{>s=I?R怹k=6lذabcc~L)bIlm}猔6Kb/ ,c$mF]:mRZDcc#s?ufN/e[35C&Dd25a8p@ 4mm=2 7h#==C>i$dgg:t6{Xb|}}p7YFvom41zmtwwñvZx{{gϞݻgϞHLLĈ#sAGG06ŋyX#e&J]vʕ+ػwAcJKbkk>gYsߙ3gbĈزe "##q̙VߣGܼyn׻j:qMxyyVklc+͌}󧔹nPz}>ŠAtQTT$F-JݻغuUUU"%%Ŭo/2V% 222Ko-i.Eccj"!!AL8X?^ >\|FՉtѫW/mmǏ/ϟogΜ?˙Ů]DMM.n{9m1Bԟ+W \.nݪWuV(V\iϥs1֖%ׄʣĜ9sDeeƪZ3m殉R=sBRf1%5myHyo3vlqi}vgG2[a1sq~9iΜmR柹}1Fͤƍ} 9s]ni-}| "nkǎ9"bjZr!˅Z6jhTMppp}};T-CtIK,Zkҍ^)...ӦMJR8::aÆIoﯬLDEE5djPBR"$$DZ!9 掿1jkM_.\0x)'O...ݺu39物UsE)mdXru|<,kBK"""B7EiiϜ1o0wM:׿*g1%J[7V怔6Sǖ)RYY17olņ ̞mYsM`:'e>IOs !śo柹}1F^`3Ο?/„B0{K{n{YI%iQ"";;˗/g0Ü;wK.W_}`}`ȑ?vJJ ;$O^1O@,igk^'|>G3>[A~p{Eojjj515kܹsÇ#**J/AӧlhiviP兛7omɓ'+""YY??33h=Zmdppp;P\\^rIDATZ/yeRADDDDDD(VO KN`m|{cNLzOS? .9_ %=etFۢѣ8|J3fMPZZ !/^{ի{VL&;.\`v899&cejd׽<==j[T*~X#W`544ҥKغu+vRADDDDDD(l05QTR? p{.U\GSPJW*QUfUb~pXz5q]'Ν;ggZښ3z'rLի1簾&888Hk 0'DDDDDDDsご1OtsbPG&A*q}6{-AZ"mnV.]uݕr%/ޏ!cc~'xd(//7(ҥUI&MBvvACaf׳`!88XJݻ ߿~pEHbaN<%v-Cb|z{X?T wuqmvf|;<##~OW0wEݏjacǶZoܹ8y$n߾cܹXpNBB/_/w^̘1f׳x/AJJ Q]]m۶aժU[r%oߎjbϞ=HHH0߉'_?dggwߕԦ s}؉'؈}gϞ\ш> ;uPKK.}Ĕ ռ$]Yzv$Ye齦$#/HWW^ CL~=1 "P(ƌbGX't"xwESS^b1m4T*6lHII1اz1L!Zr\rVE~~q DHHET*QXXht"""B\.Eii6Y3֕M6 ___ +>SADDDDDDdd?!MDDDDDDDDd""""""""eL`MclXDDDDDDDDdӘ"""""""""4&Ȧ1EDDDDDDDD6 ,""""""""iL`Mc!%t?g{Z''vi-mGl11""""""CJ5ꫨFff]mGlcޑ'"""""GL_]q&_kflmOdVO>pҘ}{yG#wV8'lx޽[w띗.\[n[ZZSBT8}ABP@P@Vն\v -B޽̞=jqDd2^{5h4][4A[og;{,"##.7SNARA.!!!0wEL2 ĕ+W$q4iN_b>vXDDDDDD$ o!|DL2qi!g<6k,Ġ/_ٳ .ꔔ@R!** eee@ll,NK.ؖhNB]]233Q^^ǷݽM ![os(//GLL 4 JJJ _l?_}U4Rb\\\ٳg#!!7nɓ'Q__Zmp _իWq8;;cٲe\8곔xӗfׯ󑓓ÉIDDDDDD-/= >d2~;?ǠWFUjoᝏ?ߕa@2?ޞ3F`< P[WĿ/_o4^VgJPPd2Y[rkVUU뇫Ws툎+ONNFnn.6nFiIIIcǐd]vEEEte.]B>}Z폱>੧BllA>͛7m=ZR駔Ϛ5 o~+;{,%ɰw^L4IWvyڵkOlh,RiN_(**Bhh(RSS1rHDDDDDD$^U-c~T6|rX6sL ɋ0Hܐ;Ml /֧\#psugk"(nʒvfB0 1(}tgeea4MW7n&OL466z>geeaFۜeP>b~O 0h"%]8ZOsry㣏>b򊈈f 8u_K<Ν0Eg+^~N]:#r?NsN`Qpo.ZGV˗=zs\]] <==tU-j| h"tǏGbb"n߾ݦiZxzzmV5(wttocVwYK~ԩYq2ӜjTWW.vEt;Iڕ=/9Tq6J׻ U5?oV!AY/ȋƨQ88[Jb֢[nzeZ=zs$YpwwGRRj~^Ǝ;_sb۠1[J?7n܀Gq$%!!DXXvڅQFq%""""""هd0HR%³FcϺ%HK^dͪVեR2dlޏ$}s$77+V.R__orAR~4i :tnm&K6588iiiFlQSj'LbV?%4/3gĈ#eDFF̙3\}HΏjǽ=]QP\OT8:nΌo1'"ga/ʃ`㎣;ujn;sjVgԇK5zh+~^zoB 88MMMسgz-KEZfkyIb'9"lҊTqzںz2_ 2I:)b̘1-O2%JpttC /,,*J\.BBBDQaŴit6lHII1fYYY"""BxxxN:^zEk׮{ Z-rBV|۷DJ?X!9"񢩩ŘTn*NRђxJRYY17o,Z#X"""""""""-clXDDDDDDDDdӘ"""""""""4&Ȧ1EDDDDDDDD6 ,""""""""ix+'H]IENDB`mlpost-0.8.2/papers/ter-stage/proval.png000066400000000000000000000021621306046515300202410ustar00rootroot00000000000000PNG  IHDRY DC pHYsHHFk>IDAThY1*5g ̱.^\f?%p X&3]4U]̍,\{As 'ss1b,Qf=-1\p@9:uT;}':KDXg5L\"!J)16˲,c+8v]g 4˲(!A2r&ޠccr&)%|!!cREPJMdYvmBkv8`h  .Z{. !m>Ȃv}^5JctmZۿ.vם>8U'6twsQ0@zOYWn}& @}u'bދb*f_Tg_丷7w9/TUUR9BoGĂ;G Ad:$p۶UJ5MC)%4M+wZ+|}m!,ZQ3`\ R,ڹz~Pߢ~3; x&4o J/RZEAv~V G^!Wc,5cBt ð*wtQtlK~8JiqEQH)%]1[1}F&D~q{Dkp4e4M]וer:<;/BzʷƘEYϸ=Q proj i 0 j) let up = square Color.yellow (fun i j -> proj i j 3) let left = square Color.green (fun i j -> proj 0 (3 - i) j) let rubik = seq [iter 0 2 (fun i -> iter 0 2 (right i)); iter 0 2 (fun i -> iter 0 2 (up i)); iter 0 2 (fun i -> iter 0 2 (left i));] \end{alltt} \end{minipage} \begin{minipage}{0.3\linewidth} \begin{center} \includegraphics[scale=3]{rubik.mps} \end{center} \end{minipage} \subsection{Notre TER} Le sujet du stage était à l'origine \textit{Implémentation d'une bibliothèque de diagrammes pour \mlpost}. Il s'agissait de réaliser une extension de \mlpost, sans bien sûr avoir à modifier ce qui était déjà présent. Nous avons donc dû d'abord maîtriser très vite l'API. Pour ce stage, il fallait bien sûr que notre API soit claire, dans les choix de types, de noms de fonctions et d'arguments (surtout optionnels), et qu'elle soit accompagnée d'une documentation (conçue avec \textsc{OCamldoc}). Dans la deuxième partie du stage, notre encadrant nous a proposé de modifier le module Tree et d'implémenter une interface graphique pour \mlpost. \subsubsection{Modules au dessus de \mlpost} Nous avons travaillé sur cinq modules. Sur ces cinq modules, nous en avons créé trois (Histogram,Radar,Legend), enrichi un (Path), et modifié un autre (Tree). Nos trois modules sont des modules \og haut niveau\fg\ qui n'ont nécessité aucune modification du noyau de \mlpost. \subsubsection{Interface Graphique} \gmlpost\ est une interface graphique de \mlpost\ permettant l'édition de figures \mlpost\ avec un gain de temps de praticité. Sa conception nous a permis de devenir familier avec \textsc{lablgtk2} (et donc \textsc{gkt2} par extension) et d'utiliser à nouveau l'outil \textsc{OCamllex}. \section{Modules \mlpost} \subsection{Histogram} Il existe trois types d'histogrammes: \begin{itemize} \item simple, \item comparatif, \item cumulatif. \end{itemize} \bigskip Le c\oe ur du module est la fonction \texttt{hist}. Cette fonction est nécessaire car elle permet de factoriser une grande quantité de code commun à chaque type d'histogramme. Elle permet la création d'un ensemble de boîtes avec leurs labels. La fonction \texttt{hist} renvoie une Command, qui est utilisée par les fonctions -- simple, compare, stack -- couplée au dessin d'un repère grâce au module Plot. Concrètement, un histogramme est une \texttt{hbox}, un alignement horizontal de boîtes. Chaque boîte contient une \texttt{vbox}, un alignement vertical de boîtes. Ceci forme une sorte de matrice, où chaque élément est un morceau d'histogramme. \subsubsection{Simple:} Un histogramme classique construit à partir d'une liste de nombres flottants. \begin{alltt} val simple : ?width:Num.t -> ?height:Num.t -> ?padding:Num.t -> ?fill:Color.t list -> ?perspective: bool -> ?hcaption:Picture.t -> ?vcaption:Picture.t -> ?histlabel:[> `Bot | `Center | `Top ] * Picture.t labels -> ?vlabel:Plot.labels -> ?hlabel:Picture.t list -> float list -> Command.t \end{alltt} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let hist1 = Hist.simple [3.;1.;6.] \end{alltt} Utilisation très simple de \texttt{simple} pour trois valeurs. La construction de cet histogramme nécessite un appel à la fonction \texttt{hist} et l'ajout d'un repère. Un histogramme simple est une matrice où chaque colonne est un seul élément, c'est-à-dire une \texttt{hbox} dont chaque sous boîte contient une \texttt{vbox} qui contient un seul élément. \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.]{hist1.mps} \end{center} \end{minipage} \subsubsection{Comparatif :} Un histogramme comparatif construit à partir d'une liste. Cette liste contient des listes de nombres flottants, chacune étant un histogramme. \begin{alltt} val compare : ?width:Num.t -> ?height:Num.t -> ?padding:Num.t -> ?fill:Color.t list -> ?perspective: bool -> ?hcaption:Picture.t -> ?vcaption:Picture.t -> ?histlabel:[> `Bot | `Center | `Top ] * Picture.t list labels -> ?vlabel:Plot.labels -> ?hlabel:Picture.t list -> float list list -> Command.t \end{alltt} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let hist2 = Hist.compare [[1.;5.;6.;5.;3.]; [1.;2.;3.;6.;-1.]] \end{alltt} L'histogramme comparatif se construit ici après deux appels à \texttt{hist}. Ceci génère deux histogrammes \og simples \fg\, avec un padding entre les barres calculé pour mettre ces histogrammes côtes à côtes, et une légère translation pour le deuxième, puis le repère est calculé. \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.]{hist2.mps} \end{center} \end{minipage} \subsubsection{Cumulatif :} Un histogramme cumulatif est construit avec la même signature que les histogrammes comparatifs. Cependant, chaque sous liste correspond cette fois à une barre cumulée. \begin{alltt} val stack : ?width:Num.t -> ?height:Num.t -> ?padding:Num.t -> ?fill:Color.t list -> ?perspective: bool -> ?hcaption:Picture.t -> ?vcaption:Picture.t -> ?histlabel:[> `Bot | `Center | `Top ] * Picture.t list labels -> ?vlabel:Plot.labels -> ?hlabel:Picture.t list -> float list list -> Command.t \end{alltt} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let hist3 = let vlabel _ _ = None in Hist.stack ~vlabel ~fill:[lightred;lightblue; lightyellow;lightgreen] [[4.;5.;5.;]; [8.;3.;1.]; [2.;8.;1.;4.]; [1.5;3.5];[2.;2.;7.;1.]] \end{alltt} Cette figure est construite à partir d'un seul appel de la fonction \texttt{hist}. Contrairement à l'histogramme \og simple \fg, chaque colonne est désormais constituée de plusieurs boîtes, c'est à dire chaque \texttt{vbox} contient désormais plusieurs boîtes. L'histogramme \og simple \fg\ est donc un cas particulier de l'histogramme \og cumulatif \fg. \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.]{hist3.mps} \end{center} \end{minipage} \subsubsection{Pour aller plus loin:} Il est possible de faire des histogrammes plus personnalisés, mais toujours de façon très simple grâce aux arguments optionnels. \begin{minipage}{0.5\linewidth} \begin{alltt} let hist4 = let pics = List.map Picture.tex ["2000";"2001"; "2002";"2003";"2004";"2005"] in Hist.simple ~width:(bp 150.) ~height:(bp 270.) ~histlabel:(`Top, Hist.User pics) ~hcaption:(Picture.tex "Year") [4.5;5.0;6.2;8.;7.2;6.1] \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=.7]{hist4.mps} \end{center} \end{minipage} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let hist5 = let vlabel _ _ = None in let rot s = Picture.rotate 25. (Picture.tex s) in Hist.stack ~vlabel ~perspective:true ~padding:(bp 15.) ~fill:[lightred;lightblue; lightyellow;lightgreen] ~histlabel:(`Center, Hist.Values) ~vcaption:(Picture.tex "Dollars") ~hlabel:[rot "2007";rot "2008";rot "2009"] [[4.;5.;5.;]; [8.;3.;1.]; [2.;8.;1.;4.]] \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.]{hist5.mps} \end{center} \end{minipage} \subsection{Radar} Ce module permet la création de diagrammes radar. Nous donnons la possibilité d'en créer deux sortes. Lorsqu'un radar est créé, l'objet \mlpost\ renvoyé est une Picture, une image de \mlpost. Nous en verrons l'utilité plus tard. \bigskip Contrairement au module Hist, il existe deux fonctions charnières, \texttt{empty\_radar\_coords}, et \texttt{radar}. La première permet de calculer le repère, c'est-à-dire les coordonnées des axes et leur longueur. Elle renvoie une liste de couples de nombres flottants. La seconde utilise \texttt{empty\_radar\_coords} pour calculer les coordonnées d'un radar. Elle renvoie une Command. \bigskip Un radar est constitué de N (=cardinal des listes) Path, correspondant aux axes. Chaque axe est décalé du précédent par le même angle (360 / N). La longueur du ième axe correspond au maximum entre les ième valeurs de chaque liste. L'origine du diagramme étant (0,0), pour placer un point sur axe, une simple règle de trois suffit: multiplier les coordonnées de l'extrêmité de l'axe par la valeur, et diviser le tout par la valeur maximum sur cet axe. Enfin il ne reste plus qu'à relier les points grâce à des Path. \subsubsection{Cumulatif:} C'est le diagramme radar classique. Toutes les données sont regroupées sur la même figure, de façon à les comparer instantanément. \begin{alltt} val stack : ?radius:Num.t -> ?color:Color.t list -> ?pen:Pen.t -> ?style:Dash.t list -> ?ticks:float -> ?label:string list -> ?scale:float list -> float list list -> Picture.t \end{alltt} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let radar = let pic = Radar.stack ~pen:(Pen.scale (bp 3.) Pen.circle) ~color:[blue;red;green] ~label:["weight";"acceleration"; "speed";"maniability";"stickiness"] [[3.;4.;5.;6.;4.]; [6.;5.;2.;1.;1.]; [1.;7.;2.;4.;5.]] in Command.draw_pic pic \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=0.8]{radar1.mps} \end{center} \end{minipage} \subsubsection{Comparatif} Contrairement au diagramme précédent, celui-ci ne fabrique pas qu'une seule Picture, mais autant qu'il existe d'objets à comparer, ce qui permet de positionner chaque diagramme. \begin{alltt} val compare : ?radius:Num.t -> ?color:Color.t list -> ?fill:bool -> ?pen:Pen.t -> ?style:Dash.t list -> ?ticks:float -> ?label:string list -> ?scale:float list -> float list list -> Picture.t list \end{alltt} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let radar = let pics = Radar.compare ~pen:(Pen.scale (bp 1.5) Pen.circle) ~color:[lightblue;lightred;lightgreen] ~fill:true [[3.;4.;5.;6.;4.]; [6.;5.;2.;1.;1.]; [1.;7.;2.;4.;5.]] in Box.draw (Box.vbox ~padding:(bp 10.) (List.map (Box.pic ~stroke:None) pics)) \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=0.5]{radar2.mps} \end{center} \end{minipage} \subsection{Path} Dans \mlpost, le module Path permet à l'utilisateur de tracer toutes sortes de lignes, plus précisément des courbes de Bézier, et ce par le biais de nombreuses fonctions auxquelles on doit préciser tous les points de contrôle. Nous n'avons rien modifié de ce qui était déjà en place. Nous avons seulement ajouter une manière \og haut niveau \fg\ de tracer un Path, appelée \texttt{smart\_path}. \bigskip Cette fonction prend en paramètre deux points: le point de départ du Path, et le point d'arrivée. \begin{alltt} val smart_path : ?style:joint -> orientation list -> Point.t -> Point.t -> t \end{alltt} \bigskip La particularité de \texttt{smart\_path} est que la fonction prend un troisième paramètre, qui est une liste d'orientations. Le type orientation se définit comme ceci: \begin{alltt} type orientation = Up | Down | Left | Right | Upn of Num.t | Downn of Num.t | Leftn of Num.t | Rightn of Num.t \end{alltt} Ceci permet à l'utilisateur de choisir la façon dont il veut relier les deux points. Les instructions de l'utilisateur sont respectées si possibles, et sinon un segment est ajouté du dernier point calculé vers le point destination spécifié par l'utilisateur. L'utilisateur peut donner une liste d'orientations avec la possibilité de spécifier une taille pour les segments. L'objectif était de s'approcher le plus possible de ce que l'utilisateur voudrait si il n'indiquait pas la taille des segments, du moins pour une liste d'orientation courte. Celui-ci observe le résultat et si cela ne lui convient pas, il peut ajouter des dimensions aux segments souhaités. \bigskip Nous avons d'abord simplifié le problème en le réduisant en deux étapes similaires. D'un coté, nous avons une abscisse de départ et une distance à parcourir sur cet axe avec les orientations \texttt{Left} et \texttt{Right} et de l'autre côté la même chose en ordonnée. Dans les deux parties, nous soustrayons les tailles données aux segments à la distance à parcourir, puis nous attribuons aux segments restant la taille \texttt{t} qui est égale à la distance à parcourir divisée par la difference entre éléments positifs et négatifs. Les éléments positifs sont en abscisse \texttt{Right} et en ordonnée \texttt{Up}. Si cette différence est nulle, une taille est definie par défaut. On obtient donc des deux cotés une liste de distances, et on n'a plus qu'à combiner ces deux listes en fonction de la liste d'orientations pour pouvoir créer le \texttt{Path} résultat. \bigskip Exemples d'utilisations de \texttt{smart\_path} : \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let path1 = let p1 = Path.smart_path ~style:jLine [Right;Up;Right] (Point.pt (bp 0.,bp 0.)) (Point.pt (bp 50.,bp 50.)) in Command.draw p1 \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics{path1.mps} \end{center} \end{minipage} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let path2 = let p = Path.smart_path [Right;Down;Left;Down] ~style:jLine (Point.pt (bp 0.,bp 0.)) (Point.pt (bp 0.,bp (-30.))) in Command.draw_arrow p \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.5]{path2.mps} \end{center} \end{minipage} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let path3 = let p3 = Path.smart_path [Left;Down;Left;Down;Left] (Point.pt (bp 0.,bp 0.)) (Point.pt (bp (-50.),bp (-50.))) in Command.draw_arrow p3 \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics{path3.mps} \end{center} \end{minipage} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let path4 = let p4 = Path.smart_path [Down;Right;Upn (bp 10.); Right;Downn (bp 10.); Right;Upn (bp 10.); Right;Downn (bp 10.); Right;Upn (bp 10.); Right;Down] (Point.pt (bp 0.,bp 100.)) (Point.pt (bp 100.,bp 0.)) in Command.draw p4 \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics{path4.mps} \end{center} \end{minipage} \subsection{Tree} Ce module permet la création d'arbres \mlpost\ de façon esthétique. Il remplace l'ancien module Tree de \mlpost. L'algorithme utilisé est issu de l'article d'un chercheur américain\cite{tree}. La particularité de ces arbres est qu'ils sont dessinés en optimisant l'espace sur chaque ligne pour n'importe quelle taille d'arbre. \bigskip Nous avons dû adapter cet algorithme à OCaml, et procéder à certains changements. Tout d'abord, l'algorithme a été conçu pour des n\oe uds et des feuilles de taille unitaire en largeur, et sans notion de hauteur. Hors, dans \mlpost\ on veut manipuler des objets de taille variable comme des Box, et les utiliser dans l'arbre. La première étape a donc été d'ajouter la taille des éléments à la largeur. Puis la seconde fut d'adapter ceci pour la profondeur. Nous parcourons l'arbre en accumulant la valeur de l'objet le plus grand (en hauteur) pour chaque niveau. Puis nous parcourons à nouveau l'arbre pour calculer et appliquer l'écart entre chaque niveau, grâce au résultat précédent. \bigskip Le module contient deux fonctions principales: \begin{itemize} \item node pour construire un n\oe ud \begin{alltt} val node : ?ls:Num.t -> ?cs:Num.t -> ?arrow_style:arrow_style -> ?edge_style:edge_style -> ?stroke:Color.t -> ?pen:Pen.t -> Box.t -> t list -> t \end{alltt} La liste contient les éventuels sous arbres. \bigskip \item leaf pour construire une feuille \begin{alltt} val leaf : Box.t -> t \end{alltt} \end{itemize} Quelques exemples d'arbres: \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let tree1 = let node s = Tree.node ~edge_style:Curve (Box.tex s) in let leaf s = Tree.leaf (Box.tex s) in Tree.draw (node "1" [node "2" [leaf "4"; leaf "5"]; node "3" [leaf "6"; leaf "7"]]) \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.75]{tree1.mps} \end{center} \end{minipage} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let tree2 = let node s = Tree.node ~arrow_style:Undirected ~edge_style:HalfSquare (Box.tex s) in let leaf s = Tree.leaf (Box.tex s) in Tree.draw (node "1" [ node "2" [node "4" [leaf "8"]; leaf "5"]; node "3" [node "6" [leaf "9"; node "10" [leaf "12"; leaf "13"]];node "7" [leaf "11"]]]) \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.75]{tree2.mps} \end{center} \end{minipage} \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let leaf s = Tree.leaf (Box.set_stroke Color.black (Box.tex s)) let node s l = Tree.node ~arrow_style:Undirected ~edge_style:Straight ~ls:(bp 30.) (Box.set_stroke Color.black (Box.tex s)) l \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.1]{tree3.mps} \end{center} \end{minipage} \bigskip \begin{alltt} let subtree = node "subroot" [leaf "son1"; leaf "son2"; leaf "son3"] let treebox = Box.rect (to_box subtree) let maintree = node "root" [subtree; leaf "son"; Tree.node treebox [subtree]] let tree3 = Tree.draw maintree \end{alltt} \subsection{Legend} Un petit module, très pratique, servant à représenter la légende d'une figure \mlpost\ quelconque. La signature du module est définie comme ceci: \begin{alltt} val legend : ?ensstroke:Color.t -> ?colstroke:Color.t -> ?fill:Color.t -> (Color.t * string) list -> Picture.t \end{alltt} Cette fonction prend en argument une liste de couples couleur/chaine, et renvoie une Picture. Celle ci peut ainsi être dessinée n'importe où sur ou à côté de la figure à laquelle elle se rapporte. \bigskip \begin{minipage}{0.5\linewidth} \begin{alltt} let legend1 = let l = Legend.legend [(Color.lightgreen,"2009"); (Color.lightyellow,"2010"); (Color.lightred,"2011")] in Command.draw_pic l \end{alltt} \end{minipage} \begin{minipage}{0.5\linewidth} \begin{center} \includegraphics[scale=1.5]{legend1.mps} \end{center} \end{minipage} \section{Interface graphique} \gmlpost\ est une interface graphique pour \mlpost\ permettant d'éditer des figures à partir d'un fichier \texttt{.ml}. \subsection{Motivations} Le processus de création ou d'édition d'une figure peut être ennuyeux lorsque l'on essaie de régler certaines valeurs à tatons. Il faut avoir un editeur de texte lancé, éventuellement un terminal, et il faut recompiler à chaque fois et lancer le fichier postscript ou le pdf obtenu avec un viewer. Les actions de l'utilisateur se limitent désormais à éditer des valeurs et rafraichir l'image, ce qui devient quasi-instantané. \subsection{Structure} Schéma de l'exécution au démarrage: \begin{center} \includegraphics{interface1.mps} \end{center} \bigskip Schéma de l'exécution du rafraîchissement: \begin{center} \includegraphics{interface2.mps} \end{center} \bigskip \gmlpost\ n'a nécessité aucune modification de \mlpost, nous y avons seulement dû ajouter un module Edit par dessus le module Num. L'interface de ce module comporte ces deux fonctions: \begin{alltt} val num: string -> float -> Glexer.dimension -> Num.t val point: string -> float -> Glexer.dimension -> float -> Glexer.dimension -> Point.t \end{alltt} Lors de la compilation d'un fichier par \gmlpost, les Num et les Point éditables sont interprété par le fichier \texttt{glexer.mll}. Puis le programme crée un fichier \texttt{fig.edit} contenant des éléments définis par le type: \begin{alltt} type elt = | Num of string * value | Point of string * value * value \end{alltt} avec value le type: \begin{alltt} type value = float * dimension \end{alltt} et dimension le type: \begin{alltt} type dimension = Pt | Cm | Mm | Bp | Inch \end{alltt} \gmlpost\ peut enfin utiliser le fichier généré pour créer l'image de la figure \mlpost\ et afficher celle-ci ainsi que ses valeurs éditables, et ses points déplaçables sur le canvas. Lors d'un rafraîchissement, le programme va écraser le fichier \texttt{fig.edit} avec les nouvelles valeurs, et compiler la nouvelle image fraichement obtenue. \newpage \subsection{Screenshots} \bigskip \includegraphics[scale=0.45]{screen1.png} \begin{center} \texttt{Exemple d'utilisation de \gmlpost\ avec 5 points éditables formant un polygone jaune} \end{center} \includegraphics[scale=0.45]{screen2.png} \begin{center} \texttt{Exemple d'utilisation de \gmlpost\ avec un histogramme dont le padding est éditable et une légende dont la position est un point éditable } \end{center} \section{Conclusion} Les modules de ce TER ont tous été élaborés dans le but d'être ajoutés à \mlpost\ comme des modules \og haut niveau \fg\ à part entière. Nous avons respecté l'homogénéité de la bibliothèque au niveau des arguments optionnels (ex: dans tous les modules, \texttt{?fill} est l'argument remplissant l'élément de la couleur spécifiée), et au niveau de la documentation, rendant nos modules simples d'utilisation. Nous avons effectué de nombreux tests pour nous assurer qu'après notre TER, les utilisateurs et les développeurs n'auraient pas à débugger. Le code est écrit assez proprement, et les fonctions récurcives sont terminales si possible. Les modules sont opérationnels, mais peuvent ainsi être modifiés et complétés si nécessaire. Nos modules sont intégrés à \mlpost, et ils seront disponibles avec la prochaine version de \mlpost. L'interface graphique n'a pu être terminée par faute de temps, et il demeure encore de nombreux aspects à travailler au niveau du canvas, du zoom, et de l'importation de figure. Ce TER nous a permis de participer à l'élaboration à un stade avancé d'une bibliothèque de diagrammes, avec tout ce que cela implique de rigueur. Nous avons pu nous rendre compte en utilisant \texttt{lablgtk2} qu'une interface compliquée et pas claire rendait le travail beaucoup plus dur, ce qui rebutera à coup sûr les utilisateurs. Nous avons appris à utiliser les arguments optionnels fournis par \textsc{OCaml} et leurs subtilités, et nous sommes frottés à l'aspect object d'\textsc{OCaml}. \begin{thebibliography}{99} \bibitem{mlpost} \mlpost, une bibliothèque OCaml développée au sein du projet Proval de l’INRIA Saclay – Île-de-France, permettant la réalisation de dessins scientifiques destinés à être inclus dans des documents \LaTeX. Auteurs: \begin{itemize} \item Romain Bardou \item Johannes Kanig \item Stéphane Lescuyer \item Jean-Christophe Filliâtre \end{itemize} \bibitem{tree} Andrew Kennedy. \emph{Drawing Trees.} Journal of Functional Programming, 6(3): 527--534, Cambridge University Press, May 1996. \end{thebibliography} \end{document} %%% Local Variables: %%% mode: latex %%% mode: whizzytex %%% mode: flyspell %%% ispell-local-dictionary: "francais-latin1" %%% End: mlpost-0.8.2/papers/ter-stage/screen1.png000066400000000000000000001171251306046515300203040ustar00rootroot00000000000000PNG  IHDR`1ULsRGB pHYs  tIME 8>d IDATxy`EnzAK rʥ"r*#x/"* ʭ(" rG-R(wkw?iI%IGtlfg'2!eĮKbza ߰LU/U !.Zsb4aI"׳J Gg"O}Xp>5eYuJbғ]ロ݃:'5B ;{N>H82EL0cB0[D1!lR0fKE f *#?4iĦe49Dd4S&Z5|: b.Gkb3J%ǧ1Rږ*l+ϘmRQ#JB&Y3Q]~^Rٗ4ȇmĉY56Rǖy&(!3 "F&"::~Ϋc{jt%\8_~*rC fIj~=D]|:(u8:]*VN(&R{ψ ֥t:`0 "۱t, 5 ZkK$I\})PUaXEȃRϵf~rВ)b[voܱB*yf`סmvcLkX[%0T!/ߤ4a l{#,:mz`RoaX]ۃOsrtJDb mH=FD|O0Ɩ,Yb0tF>!`eV:Z]IwFxdI#KKDUUU%n6[Qb)gXaos^l*F6j1>\IvO'b7 =\t/_~7W|28ߥ֗IH|j¨;ąr2\YDD'{h̆Rڴkm9m۶תM.aqtnbؽ{Gzŋkc#c.)Z &HL0Q<#%P ~1ѡՉ]#Tt$| !aŇ9~:FȲ$IgLUUEUf3 R ieaL|ԥ )xq3|ލ=ݲxǴ;oP|lz~%݋b:^J{"Ѽ 7 {z'k5mޓb }{˶k?NH>}5^ "WΦ* مfHQb'/m5`5ml'>x5’KbDԼyGkӞaB~7nx%¢(B؎ڮJ&}{ķm7r(??߿1AkBFvY⌈ 9~ZVe,KFQQ ?600vM%h#GOՅt|ǏXSq׿|Tt8%Y]2hDt}`^tw߀]{u˖W[L?O'2SY<<2vS햾fhX.{c!!YtxRL6vW>gD\p|6 :x,-_tҤ2}tq}l^^_\xΚv^~; UQmKE%" E(h:w6U??9;hm(]2a4p!&g/eIȌ‚%IZ GA\L?wDШ oL 3sjέ]~/)L?zj 6DDl-]hu2Hnpg["_ۑ;7.;:xѢ$Ni%t )3}ȑZ=㦍 _\fS'| /222͛;tcq k+cM*x_5n8//qFƍ mĒED2 pb&A(3YloFku:C Ծ6Zhp輱CV \ÔvEc{תugCDǾ.Ԙ%?h;WqIvۀKbiOS0xPoӢKL.͕O~^tz.t8̍8v7߬ycشic[R~yݰ= 7oqԩұvq[/d& FْSIj}#_bYaLH$XNRUh2r$IM YYyY)Ic5$9oA!ZtꇕQ`O=zb6KR}Jnґ jNM'rFD?Ҕ2v,Ϗ_(wk뷎`ϩJĹ_ԝTJ_vKh SE*DDok/`޿o_y+HXC:bhMmhOH'ٺvxD*$T&XIz.vJQF9$9FԬY3;;;v LC8]f߹Cjv ^ƍ9Y$t8KiL+gC-;W'W}wഎgn%]t?~or-{+9=OhFKDiG `/]Qt{߭?}o {;DWJ⿝/F^_U;dv#b?ߨYl۾vcEP_bɌqs{ ,rhԳ,pjK=w5#" (}X~gcߝ]Z4oWO"9g035&zMiS?/\2[T|5 :9\-UJb&^{يSEY fQ!]T|V2Lu->2t^:ڶ* A3#bW}vy.oO%'8\ɢUEQcq.q3"Ae? /-FJdFbE.RbV_T(Wgsz P-"%Y bQg42IT|; BP Xs٫RJ]RGTr2a^n{]Jܷ2K2-q"b\ՖX:i,횅qOWT:pIJe=`@, %w+9\v|T{伿R(ŢPQ(az gm&N[9C5㏨ DdE`FB%]UJ=bBYOg X .ENDzc#ScLDqip-YzHW̏TtȷDatLPۅ>/.S-{eiLUI9y &YuP3$8eX([GzlY&VAf\U]*U2wYم;;6[^;BUqzgu mkb9U͇pw93y7U(˼ؖVyLxĎʺQۢ 5^5U*W&M+}3^+; 2cLsG^LxȢ-Ed;OE!ݮY ߅psM:W»wԁ[X1YQ27T{gW\=vw7/|z%/'ɻp<=ȡ q DxVacLftG*/)cnltϲ;yˮ^TmQQ]T2wN5,̝͔uU[ױUtWox*T7eȍ{Pu:႕$drp;cţ;r`v,sCBkY1sUȷ@D׷f.n;ve-‡?t#ƙ,POɷ)& Sǵ'h Lg{wdg.VnrGu_kj:JA0A fQR .'/OvI)*E5К?`5T~H.(4u.5xѡm¸/)tp@fϞu+Tt)/9ɯ&nZJ#z&XO'T7ָj'|ɜ1 G*oQ1 h3frxYdU6i;?9ՍMDCڌ;}}Ǟo~ュ'UA$EwƵs~P?jȿhv%ϷM (Hf\iZ>5c{DQtݳ m~_yѕ-k~&ATfMX/UtިZhd$M˶6{r<}"A_+}=^lXt.l5cP`w՗{7RM/w{u![~|hA$cQ "&3F""aʼRp{µzjeW"RFvR~m5bjK;ӧit~F)g.IZmPS2)Y rA*u P(drF5d"E8)-DSSz{_Fmtw~L*eWnL뽤wl]?' 9dkxr!;X|tѦa!w Wߠ v]4?|5 k$Z{𸁈иA) Le׫TrP%?,^# 䁤&7"ځRs0d"FB8 m+a7ytӾ>㇏z6=˂#٘k5#:vOmubn+~ sNƅ̿&/~qh苻Ut5:ǽ[`q>0?l !P I?O s>8^DԿl*P$mC·'Yjz/s\s6aAyhҔ\9fDَw |K@lJLb|wY/P sB-w4Apη<^f_^¾XEPj&;bx}+6\lDUTkDo綷\YU7y_t7rO3pu*˙cj`(jDޢJ/nQUO4([i"toxZoHs8[ܚoU~VU#-*dq+KLnauʚĪۋN[ÛGϼ׳{[wϦ˞*x)U 74Vx&|9r.L75@]xH) lPnDc ""ٚ׭ 288wBpb31n@"9 =`DB"b!'&,'q=ۧG| !'"(N"T8Yo.D݂bAY@1NQ07 1-!Z||$p3f&DD3بdbT07# z1Ƙ/j0\|!?7֭ [cLR~lOfTUW`itazΥ쫷nnT˖_L&B!Dqa}`q F{K"T_qebT6S [K%?J -őD21;j=9iD텪VhKODɌ1 , q1PǏ?sL:u5kMA&! (n(dT+w9j$YfsF$㌱#Gڵ111; PUa$l-*ի߽|z #ޠZ9knNZ,^YfI$I9'pфYsssZWU(U-5dbD }hػo-x 'ݰ ?0iJfgpz-yH19ct:u=:9o׮PUUQ,f3*Z \-U=c֭ҸBPA~N93pIMeKqkB8|XXX6m4hh}VzקJJ:U<]xEc-a-% ֿ;ɢ"h 493:dꯗ2͙$'U\raݔqS]QLިT(i)DMDoU[/RL5/z]%w4\c ^Y;;xo-OfA[ϋZlgO[PnҨ G7oMͼB$gT^h׫FzonD:?WMm4 RwX*j)Zb@m>$an֘WG6YE$NX=(۞XZ{x@!<= i9o֫byO("i$q^|J]v+L}KBb4EGT*h&D1\-MՀ~ٗm>kZh!uvhoᄎ{sjY6ƚ!(2iV, z5NlzPm4ZrDS60^ɺxPRͺG+m()ƊI q8vtX}).isްL5~Oh_S.wG2Pd;@B9zA%5SdW-5uwbi۩4e_{$'G*mkBJ M";kxKw6մo/Ǐ{8Y-SXXTQ R$nZuorm^EP0cfrqˬ9m޿Z\To؀$Y'پRJ~Y~dM"?b6&6r䋀yKN7ii!c9iSaO}0&Z+gJ4M3ι%.Ӌ9Kq`1fVjp07A6 $l3K;5ڬgSrYlM+{vw9iʊ}ÕvFǗDHG[˺3|x  J#-4I6ӄ02 *Ɣ݇7Eo)W;HĵZf,,,A5I_㌆z IDATA8m#JqiݳQ>\ܱimy'j9%*T z1FbA(.S7 7% GvsubÆ# _|i=G+ݡ"ոg//٥m?yxV2㌉[ܞk@*'"f=}%xcfwˆV=0=JϰwԀ]˟g.\޴vJ fDUM3 [[Qf`Ȓb$Bh4j4:: Vyψdb.@x::F/q}!BTfE&"˥ y ,S`>̞82Hk:9y=K,WOQ dDd&"?2)&'8e@X QܕۭGEKZuybDS2B넳Y =_Os6忏eK^ݿx\v=7_3*6Eώe<}Lʕg4hR;V{ I8yH$ax~wpr:zW@,: QQ2Oq*.ّtJפlGL*BŒyuʤ +W,I:7WP[V}tʤ W-d0m֪gD2IsQBc~I+z}~`] k?ߔe"C{{)E5 f8-'[4я tLN>q%,7ٿu:٠[5uŠk̳'$NXԠ&MuDJnmܓZpt͞Z@# \㪙VfDʙt/K7O;ڹu;0es._!9},̮[UW]"vTDZ ?h2fegrc#"U^cTE)4" TOm1eٕ!}c4gȝc,)YFhۧXlqLDun?k7r{-Ygʜ>^T;}U_wlg? gz2SM7m8M{p|j4:w{o2yxW-W2Y(cG֭ / d4MFb4#"#="([3ʋTnyB$1u&8dŪS&=W7m.UQ윜2l6QUd2/P9 {TR,6Gzyؘ B.q$HnI$L&b@_6" =rûL{1ߞ ܳB-aRRGBE"|Uq1!d=fn&!5lk#*G3"T;K2 At+%IQDUCHpνJ[dF"Zҹ }H۽b4n+TTq<hիx%ϴ@"Z~db.k۶&Uяxk/]ep##:wa4alǬPfН$I :t8$ƭ*dPY PNBdL&FHŽ,łS#uDD@SebrFP}UP Q;\QTI3"WUt1N*J/INRg{1)( PQ>dp,xG>B?II^>+=g%%*.|@@MhALN>wC ~s;ɧ]݃hnʸۮTÌɸM6rl1\ʥƽ}{3ͩ똧2|(jj{˿^CL|d2ᣯl>s[(S^Xxu[5wkbWܿ2T^\"i$q^|J]v+PE j@SK6v5Hqqu5c77~k#DD"ȇzgb/Ӝm­0ױQ]t̶HL[iWv>wt? 攍-з?Q/xpފcX<+~'D"⌕sPsްL5~Oh_S.wG^h|Lմ̥ Z?p }8*ЂyΚ#9v~2==\߮[;mGKEG2cԤ+׼:P{NbK?9"Fy?_-_2Peư 2zҴMi`RV #Ty*\o·D\YntS̙1 lG.HE?&Am<wiFBsxyꓝB}7냭i?.y}Y'6l8ŷ~ّsd=]Z nٻe' ,ܕۭG暧juIaszԽrZ'LRHj}㵑kՐ.}<-377XD=g?;4unּ-ΜܻbǢhHd:16+q\E'!*RC)\%s%;.\I?qch.Yw/&Rzu5dj|SHUG(8-j7ɩ'dژA=N\07@yNXq07œyD cIѕo5rh9O5'"%?VFHr6>movhߵsG]w0a\sցUx"O4.}LxYjm`@IՍTcT4WgH Cp~yZ/OS] TӀ(2w٤/V2"1ߞ ܳB!*-TTU }*= .CHF!}#pIRQ+Qs@8(w8ٷ{bAi\B*Τ"q1\N?ݽ={m۶u҄.7,V_Ve{M@9db8N$ :KJVSd2( ,~wX@qf(ƈCPD*8L@hk}pC( N :z qHO|8q܎7 S; <$Er"t! l2Wf"S_'3K >GL:q{5!#ؓ! o }X-(b͈ߑ GwH)L\C5IٙuQJ2N{C#;h CD $£p)2 ,8|xI2Wf:,Cm(7(p=R8p'Ba)Jvy ͦ!(F2q Wh "^pybS$n@dBA9רO '@ayhQQ`wS,ɨH근sεZ?Ii6|a1I2cLDٖ_&nMrw9*Ȉ7(VxpZww[ө@#CRn_&3RQ nd6߸i#Cݠ ?0iJfgpz-?+bR)Q HI[[BRQkc=%P$%z} Otx%Y_@ݺʉ&xGu &'~s;C ^ҡC9ӮA\X7emW/5qX'n[hX <Q3a#<^yڸ\oo˫lfϘw6y*W>}ZMz>t׫psqa(I&l)gt!WXA]',Ju LS>-VGD«Z>~S_{N"y*j^2핗$΋/XѽK׮~I2 Vfa. j@SK6v5wP.^Ma uھ,oᄎ{sjY6ƚ!(2iV, z5NlzPmϴiWv>wt?OmCb7mh?ɜqyB6'}[qx+'bϭ 8cez =9kgoWR׈G)#C·Go ‰Fii pTԡ֝5Y2t>QH_$}tgŜo/?]qcԤ+׼:P{NbK?9"Fy?_-_2Peư 2xD15>>]Ǧ.M;y M^?fQnsoN4rtӔW/+F-Sn-Fkn|- $+?laOr֙&,GnK1?S&R2EPDHQ!Q!{!|Jg+D4D&沄(x`)yNzKLd./&3zҶ]ׅ(TK0tBUI9#>}sRwT҅);u gG2"%DR^a-GOQz3\DD+rrC) $\d9풟O^~xòi=cbZԩ/1}t<2~bҊ,5^gXWSk><;qZ"mO~i[Mxڍ}GKYoܳuߣA4j s#̙gO$ >vwi׾l$‚IhH~ݏxk FAo}2?)G'2DyM іfiv];wN}L|;WLjX8i]Eayh"w]"i+]skS/f* ŝ%%m0Ζ<Σo[.ϔ9}沈Wm8:^㮧?鲅f΄ q>ZC =h4t߸e([.l*|;G$xclB$ ޓnL/>Yjm`@IՍxVxQVu\y 'xםb1_8>"v8աPUtH4|IurûL5JؘoxsY|[8Z#%7'cLfBEA$2]BLa$x;4N@tL璤( *avsTDaoH ! ؘ}wY,VL*8˚8ɤH!xߛ(&scp۳׶m['Mrk/]ep##:wa4Pb.e2M0dbɗ{^K!!Cro9UQL&Z[޲yD J& snb1;>RA{aMd >ScblڀDyqh:h6DoHF>0h6xp( IDAT% O 'Zǡ =ȇp4ڂQppqh/4,fSP91D,N^}D"aB/ 3T>"14,a@ĠMb::,Cd Kz!B& ʥH<뙈(2AgqXymAhX n^q&[@Yd 'G@H$ ^>(0h6x\%qx0h6xK@d *`l 3$ɤHJ2" ;YRe!ã`* 47dB>Ud >rEQA "A]qx`l-@͆"1̍)dT1b-8Z$ڃOO 'VàP$T;ӡ\z{ΧF pι^_Nwkt:bAh "^FQ͆[7nb舧8t'&M)?+)Tt"G$M矅p/(fH%!zO9Cz!ߜNriW Z.2n+.\fꈓ;Y{0lؙ]uxi^r>̃_{=wTuSzy>˿^5r~j5=r_!fdBǡrzeϊUq[aQ<3+(맼0k׮;L+* 2:=Vp(nZՌʶ\X7mVe_j/GiZ{7}'kkԌoOُ#NR띉-swLsڶ y2@<^cGu1:"y/3m/rD69eA'mO ;w;VQGvi;Z*r<89]&}8^Ɇuث}p>_1rcjUI-3]$4m{[GG2T\D%p,g7m̘Ku~Qw#h@aNDNp7A6 $l3K;5K֩}7Y' Ocg H~¯mF,Sn-Fkn|- $+JIlaOr~<W2"͆j]8PP- UDdq%,7ٿu:ѿ٠[5uŠk̳'n5O~ݏxk FAo}2?)G'2DyMl?C;Z'mテ S&>cWI*fwM5Ia$DCa)ٙuQј*s-W<-,^Jmw.SyG<ȁhuq}0E q}ti3cgB8 u!ΧFsw-'wrqesP+\\ly""p@e=L&GAJa^v[pGNւr"Ս3'+V 2鹺1up=q0h6TqW /N}}uv B>'NlL'15" h G$"z% eb.E.sxzMra// RSp=+B%#qgrrC)ELS/Jn ptYQGuY( _Ȉ4<+b)K((ȇ\"3wqQs̰C;[Hj.b4LԴD/C2%Qq4jr\6ʢ 3Y~Hyx+әs|94]>DQ-bhU&q ˲m/ R]yg5C tIk_[և?NF@g?E8]b#aG?Cȼ`Fehvw0dTΤRkiaTv%"#E0Fs9TatYsXRR4E! U,:Yo8B4t@p+M!T4t%" @#Tp: JVA$;@ h : 3@ԣwn3Lԙ4t L/!BaJQбȡQ6@28 Clɀ4'@~:1K B8+k:|R(4.T^K 2"ʚfp=fʈܯxf ៲N=AG"M0@g2": M03MA(ÇMAG e M` :4O! 4-4-  "vN*DZli9Q4MK$F=4; KNl.5E)@v!egg^4CFl${;.CӴTj׷__1ϲ(~F|:V`(E*7=<;ΠіFnZ2y9ČSh1'-IP 4B8OIM8%ͭ52׳0]طg70(農ٙP x@h" q;l:^,[y@o!"h1 x * D(T:AlVBJ>*K?OKK_BXu[33NB,ALHxlJI~GlʄAdӏZt> %khk}*I*B6z8&䞞"VМ/{6;s~ C؉Ho8]mWy$OVn6jǹ=53- R}, 2B?l`BȘ#$E/YMRquMTEDWeMfo~gu7wDXN'6&tշCwr1ʊ9zۜyna֮CeϺl7_{*%`[hW?j\%?S;"1- *.:dA\k el"@S|)Dl4t"~!Ϟ`жCyEҾ[д^6ww[ & ^L&DBMQ5N%?fckN[83 ͨQhB6Rœǯ0&ܰ~i#riNwl:R//d[wbWpHVqp Vz~w^M ]:r:-dk'Hk.h羯~NGr3-HP m(b_)~?5>Ղ|MpIOTK]%?+VBB6G;Sh3svլj1TO|<'Id>&sӏWLkҽ{Qo 1…'_bx ӥcڵ5/HP |[3ƈV*sD(cV2[B\ۺ?_owUcP~r)!BXYǎ gG}&\R:e2Ag~tHת=9v6l˜kޣu29-Iz7o^S{} Dz_&7.u(kR@!O)zъ"[QhqQeyy@_~'mOԎK]F\(v-(BB4M,( 9o3_7ߎ\0kKNG"2w_vſZ9wgCJiۘInv.">Ch%EH(4oW7`Gu2"hMh͝efs~zVZܩ}R8xR콿|pўC=S%BaWߘVvrbiijʞJrDP=_ cbgdSPP~%&}3*|D͟-M:w:?wx\.U݆9\UPgKwϝv:#Uۿt+Nܯ6/XDFKڹ3s۶,ڔ+q\>ɗsIwzdCdFu(@lJdcް3@.ozćȸ3JL={\2u՗$~wI-ض]B;־NxqO(s7ɏ L^0æEٚn-jlum`hĒbfF%"ȃ$DBէ^ՖLMCCZ s(惦TF@6*\e. v[8E[}fC̟8 ZsXLӴnBlʚf'"4k@"VB(IXX>FYѸQ)fPȇ|?<4+k:@sDhCӮ2ٍkWXE5^.!/`"a#U@i64 D&R4u 4%  -4͆f Bh Pi64'?M!!賲٨4I@Y,34% 414Aͳ| 2 R0 i"nڀД3Clh2"A@lh2Mi``i64F>0h MZ0@i64} fˣ) )hf1]h / ÇM%p=XTmnM#`ʚfg>D)9.;;_2b#ٿpRyEYX>F@F1mjg47-BB_ /ؘ#}JB [Y7Q8OIM8%ͭ52uavonaZfNF@l/P8jh9&#˲5y Z4͆S)܋ '! U(?"!QuM1(&8daCXB4+UQ(hQ4wL3n`[sbBƒeWO;rh$eW&$<"~hՀ,B/`hZ:dA@K"Bi$'Ö_23y*#!3{ي1 nc[g3~X1gk&BP!W\puSJB[fATk6Ss&ĬOFxLQNID=8nBLńf<*%UC:X Q|:tq/xU׌/z$DBMQ5F D3|5N-یVTЌ4!JUG?4 i4;6OQW;d?;vzރܺ\~T({OfTXi贐V]p# gdܢ@H6勃#HܓswQj?6 IDATR)îw_1_< '#ۛT HoJ:o[(cۥS_Jdๆ @|ʙ3f]:B ;@+k:@њ̈^u0ȶO/]L) }%qN K^;&/֯P޼"]ۨǠS>|nR[>ϷOcSbk٫Mԝ>^^ߚqޖ^f̽n'{x/Ws+,+ɒs xA$DA"{ o(u2v$ٓ XY'p" DF־|6kfZQ_+(R~k;}>EFYt翋=:ĝow鮒}blrAIbض6*mkzD/+&&$;u欒E/oYpyY)[Zfʅ]okՀ|^㟫W /1g&}{ tƪ][ ^ώЌc4&fERyVco2-UPƶdu7~8oҫ,c½|W!׳N!`M4>uʊe(у{ЦNm;ѱџF9}Z4%!]%~qW]ފ*|_iђɽeֿLnS]u& ngS6.oEqQeyRy@6#z/9 ,oENS kJɼZ-/NH"RJuWO٪ՄzdL3}5@r2)f>CbS$Tn @4"BlhA& 0ݞ ӳN;0tHӗb(烛Z>*ޖϦ9 m/wV쩴y.G_L0&v6L_9EQkN&joTݨ;Ow+߭_ o7+ں+k~tŽnDJwϝv:#D6&Ы?o:w>|7Y5m"Dj\wXM$؞K&"3kGgaAlYh <4x/flw-Z#_71Q9}F !gϙK&%] v:Ru;{¦GK=M~X`ڄ6E/w67:'oXcӜkQ"B( >KvcOn]7OZAġ˘w7%(8yO8jcVĊϦU6'|eVGRs lc.ko5h@rFLl9A"٘v"CU:v0|IP x1LwR-;xjE> y2WY,ym6INV ݷ/p]buji>>xC$m_; is1Ǥ{g9s㉙ |aCR({o~nJЯW<}5([T8h42 ٠G~0ѵԝnHq٫r ih7Y+d fCC4*~'89!Ա1W*sY8]e.4rPiDQӻk!"x`v?Wˊ4MV(F ::9/ uz XEQڽ n*k:@=49jE q 3QAi@lT CӮ2ٍkWXu_2!/ e*K?OKK_BXuhwl1(`>&$;&jpo///>X{.YUd\\4aפ)lÿ\2=` CSnj)nj95te-;mډ9pbW87XN_lN؊TŬ7obp/)Y4cT7K(f iKKQۡ;e\m:>>bk䵁ދ))wJ]fh-&D6,Q)ŭ~ǑThtw/ۉ|B.=Aϧ+U Uc~֜:u'l3"pf`/[Q];>@O%R9bhя7vDnZ?MSjTjAlniTm #~@[3Xuez7+tXi贐V]p# gdܢ@H6勃#HܓswQ[NOU`;UŸD64ٸ,%\8!tޤU W~@ )gΤwv]D*7: U @hhnk¸4v?饋)/wG_FGat`ۑ[eI׷Nу;9Jm]<tRyogk1E1ug"Jl-{J V 0ep<{~j?DnmA"{ o(u2v$ٓ @1Z G OD&0ҶtY+7ӂ ЦlPPٰg ڙ|16|[1OMal[K%/~M_~؂5zh{O2Vښ$g(wwVq[q0LimAznca G~O.%}^ Q=رLքz8KJ>ZXμWķE\ջٿ}%Lբ, !Z/yӔ'^7~tHת=L !p,;/erBkGCbDh)DAsyϐhE(4ޘ"ѹ _F Zxl{ړPx`fcg'jǥ.a#]uSs;uN!|~rj!_WuNMT)YeG).L3V+lH[ᲊ#ϚSJu1B⛐s|=us ]zE|QGK.OPhޘsG/&6REvf; њ<0p?=+-ԾcCȌO.lZ?;݌&?x )-F jƜ |7[LS׽NSVTZ<#Oj;&Ԝ"Un|ͨ5'}I̥m \̹mVb#:Y]lBj ;Vzdo)=wz4B”xރR$="'I>N5}/J~"q5;&_Z~l%EzVZGյ#5nlD"٘7o 9[Gnb JBV.{Iۯ[.q"^vKxIw7 eb.f7Z&MaSyks#sRVuwݺ/6nC1KnJHIQq.*\>eoe&d7.o#?{\:=:!4B$Yנ}1hMmw+2d߳o$}0jý'_G) 0 mT}Ȣg>:}Ǟg1sg!uӀU*)G|}TQn>>:^t9>zLG\rWcx@eOz/mU}:e*7g]-^NqUR\@$NB$Z}_m9}44dnLԇ}PC ǃA*\e. v[8E[}ZSL+$PD*qzWW I*sYi hIN'A) MaH )!VAQv-XR"@ 0jki`PQ@B2fPȇ|?<4ZAsD4ʆFoPsT]e׮,j\B|^x8P!&hx2/Fz!vw0dT0G Y|g>Ev1 cia@3 x+-UrhRyqU# j˪YV:K O1%7D(B,)FtxDD8A4,7h}"@8--U%5u 7֨R\_4tcߞ4à\0j<- M q;l:^,[yož:1uf0(THHp'D: @w: wRCɇ³B"qiiiK?W(#P$F@t2 b $! &$_~lͩSwrx6#gյ# Z6_؎M9ޱxJ--&Z=]eN({OfTXi贐V]p# gdܢ@H6勃#HܓswQj-QVI3>>'}jK_< '#ۛ|nR[>Ϸ1%Th _)tm{=3o֮2^uG=pҊGc\5ΩFg{/6ƿrkH,%& ſ>Ml۲ X@$bON]N${R׿#LR9fMbmhVnIJMpL9a϶"&3(#_cwwG璸n\:Us_M.(@t+&0 CmzM襍C¦_ 8y~V}9o> 6xKKl\p~ϴeܥk#~t/^ۮbB y.=Q}kۗK@7aڵ5/HP -è ANH#*V*sDU깍kG-Vq2Eop/6}fScdž3>Xh.)hbft%n\%3V+lH[aOHnvN}ʐ?*hI) Su@qpl M4nυYiqKu:Df~raf4äIiyޖϦ9 m/wV쩴y.G_L0&v6L_9EQkN&j,m?l0Uk-1 [Gyk|{#:Y]lBj ;Vzdo)=wz4VmlIDATҭ;qڼcY}f.mWhbPfm۶d kcq\>ɗsIwzdCdFuZ*15˴|:h_ "AsH"٘7o 9[Gnb JBV.{ۥőb>}k6gZIw7 eb.f7Zckvhށ꜔b-Σ.jI>뗾^Buy_lYH^]̑έev vh"4&(@`A:hHCTD5NBvE6:"\e.+"4[-@XX>3s+.ZAcD *!VAQv/9EZ@D 8)!_s4m@?%6Rꀀ14*ݸveYTäggq@OXKAVc##aG?Cȼ`F_haR%*F-u("EYZK KaPs\i`-N*slMD QXVͲjVRyrAp "4c\+$@D lZfܿ *pCKDt4kEha`jiauZ C* XR* 8 RQ*ĒbԡY?i Z|"4' 4pxYIffCAD0Y@0oĒbEl΀0[".A}0juhrE3++$Vi!D[Y"J$'/ɣS?B8yRE^k;Ͼe߹t@D "B(*p3jylDF|ـ;hDz*PfF4-1"j͑˘#DdėV!egg^4CFl${;.CӴTj׷__1uDb.JyMN3hsioy!/S{lLLL̈>%l!P+ԉSZ/5 (hڽǾ=iA߹]j`O4# j9&#˲5y ȄcD# &!VOH|fƅ mY 'I % ĥ៧/ \H:B4 r  $$@۝M5hH.d^K094pJ,[4ؖ!l>m;kepo:֩N= ?g( mѺϛS寡ۄN )[;p>:[N:?bB<&.{iܦqzx'{ %ޯD)_F:䞜R!TImM]z9{ZiCߪ=נ4ؔ3gһX."tm|#wDA&`Nmݟ^ҰKhiAIٽ,iA^t}딸=ţ@@'ﱏ*Rogk1E1u)vNf #J"K'KR5`Uk QбHĞ~A;J6Iro!"h,1ҶtY+7ӂ ƨ! 4=W$> bIտNwc ʳ[1OMal[K% 6Gg /1g&}{mUJvDpVeŏ'>M/䈅u p&kB=%QSV,CьN߳1 忳iђi2F xXv_`f?Յ ;&Єϐm\ߊBsW{ㆍwFj6vҿq鑺urI#;9[HhON-}MSD:'S{*w5l1w3nN,Ӏ0A 9Yh3!Tq)*7 \6=gŝw,a!|qFäYALP#{9oun`''{V쩴y.G_L0&v6L_9E7לLۘ@|݇|]'.f;=tW2u>eĊ9qaG4c{.)ҳN?l_׵#,lw-Z#_71!E-qnsĴW~6Xȏ;2w !nAu[mw}4~7~㞰Q&Rov56alMыx͍I[.BRDD=χ/4͘G?4 i4;6OQ7Y{p[~ w/I>ÌsK9 ~ʵ}~y$A5\[s{^(ɦ|qpd{r.br;J ?oJ:okB!˩JzO4ؔ3gһX."tm|v~(F1 >͞`609MDOtzbJC.y_塼ya !DȏQAMY}.:)}TzL|;[)Ȉ;Sbk٫Muf7W';XV4,,IAzǹ&z^%DA"{ o(u2v$ٓ q;BGRiط>"6"iHڗfL 2B(#_cwwG璸n\:Us_M.(:n|YKƶmzM腭Nⅳ'_bx ӥl0Vښ$g( I5J"FA, V0G2Eop/6}fScdž3>Xh.)hbf#cnoE>ɯ GK:gzc~/TlcwF>6'&!O)*;r+ ]8jbfDO;?4SHbBBS|~rjaSWi"92o߳U齫 eiusx=WʨG 3OPĎР]XLQ!T ! 6'F\wj߱TCdFI>gUVj򃇏2%{[ʿ?4uZbT=x2WØ0ŧ_xgߌ _s2Q5”xރR$="'b1^|ӹ_?N]|;=tGs3 V\q\>ɗsIwzd I04CQ04u|hfa(262g+^kO~MbƼa{gȁ\ޢ?uBJ[~6EWE_=]1cnS?{ˡӛj׾i#;n{x7~7(uc/_r.|pok˄J9|ov紐=tIDzΛ_yL=L]~].!L~h=}㚜ҪVDG "IJ *{䓕K68\O7wH^2?ٹy=mE9+goe*U|uwq>_Ѿԇ|oiFs=D&3y?x?y㺫=" lWKmD='fTY?'^,fQP&'u)\asG291wu>o7oXל;Mn |yהؿ:uj k۱zwUc8 ??Ԧ;7;}˷k?%Â)Ѹe㺝z`=Ms~׍mӧu1(yhlDS bJXy\;ͨûDuӓ&x(Q)"rmu1ϋyq[[_P0 s91/ff?xJ$%( =E`B ,t~꘱XZ+( U 㝛volHm7+ kVDʸ""hA`u(Z$()IiJ$^?J.ǩ`gx%=Ɔ|qƯ(%=ue "EheAJug_|qkCGfϚ' ͙=ӟdz?21Q-J[њHU4Sqk|]jL0|#~m>#DlFh/*ZRbEhOx7Ϝ93Eٳg57CHBk,rő|JG/\AOOO*ZJDBb"PM555t:ZkϜ9 E D|uGD֋-RJ>|xuuu\#:Ŋ?5'&bhҁTUUuttHWWב#G-[x0:U5p"E0)(ƸJ)(*++=Kmmm!"as/ؐC@ĄR Rd2L&?u\ $ZY@^ыĐs22<7?wT0d'D Ѯd[9* a \{X8}T("`M9Ća&3{̅&cP?9W#kÐPo1(C Z EbC Ze`V3 161L|B bjf֍+E9xR[kX8K99~{݋oJ'lL+n,8c ڕR$=`7IENDB`mlpost-0.8.2/papers/ter-stage/screen2.png000066400000000000000000000656211306046515300203100ustar00rootroot00000000000000PNG  IHDR`4ݦsRGB pHYs  tIME7#G IDATxy`e3IOJW9DQ{ v_\Eu]uUVTZoYb7܄g?4a UqrÖ4 UHdjB-1EgYKjq"nvnzCj5Y8ٶ#&zÁmm;ߎ9J8#69rAط܅hs<a00$Qhlfw*pLV h-e,ׄjI6nhXn$Y4mlth؇|qC^NYڔjj9^zCAMXI=TE"3NF )~xD CfѸw_F5/͠ '[]pޡ&"i 8H=']5υܠO w13+j:]Nr9SQ5#Daq+tǾ:G}*0ƆQF`={zZAjZ$QgZCB6iSBkXŢ'f/W:QT =Z7>)*:Qt_4zEc^ {V߻']? i[44ԄN/BWyJGL<}uE-B|)N x8&oFp]&D#]\{>5o4|?-*Tm=D׹/H!H$+Ea|  BW os Y#7d}qK163M0D'̞5yt8kku5W]rn+2R -٠4v3{ ])|: ߘº]?W~H0{"Q@lB? #8@ !¡P$u> }9! "*N5(vB'< 6Jп@΁p`Ws -~nֵ[Œ>UYw<$!NA_5F_5c6n!6[fg't;Մḿ/C;w $doA! vXboK\ 3&X?3kت̺L,LȢf砆] s~@"xڰ{Rvb҅$ I,˥h[;i6 ǾC>a)MkG}y"Dn_~ti~-d&-HgJu(("]nYWSWUᬮpV˭e9T"!jx!įzj hSxB-%ZWOhib&!qE6J)  -RX3&5hMxfL'28/P} "*LU]A;'kY&T 8!X"bh ]K K|9 1YK ]z7瀪JxЃD@(ʳWp@YOؠMD*C#}e+9L)_s=۲"a"AmRhf>CE_HR1{#`e @$"w ~+4Ѡ )}|4xC5~=>HHk=&RK̒vY!ƧpAV*EfO, ,8R}$8( ;y*/A7oim',597:iZG@os}|^v{6MJ&aAOZ;f`!<3 )$TԌDXgCwpP]ݡ<i7A]>_y[Zw!].''_3mAtV;+j+ W]TdחeFqIAK >{-O1~:%vD9Š"k Y3||\ uԪ Auu&:"Wif.vj"_@t\g2L&$IKVvݲ,ߐ{聓z ]|K<ҁUg/;]2clϪ0xXk+kuUN%6JoU|WܾdX[v5i;PqVV(,g 2)D y1ߢ yǻ((ɴ\;4曅/r]]mllY7Prrr.i\kv9DmlLl2$ɤ Wc1$MdӯG HMx,ocibg k9ZqY&O>Ncѕ?,g!W_];8;g_}.,߷vDk3zq90GD$Qqn(=AnXk=WH9ۣgϏ?oѹ~xeO>cM/-{c&'dGř䢭EL[V3n0p{6{. bi.[7$)&6:e6L&$(\.bRX i0yuÈ5?syQ]TL\IoUd6IZg\1)^k5Gez~LN|͋vрkY~yqD|G_#y.~^GB8\?[Ɍ[bb̒&Lѱq&4 )޽{Yfs޼??#fυyLܩS[om޴9OΘq!Ck_(MiZظ?ÇWU>|ؼybsyS<&*d|D験ݲdtң{X}Vwp!:?Ŏ|xN1\W4x$.6z\A!1f{ $ո޽疚8oic.Nsh[:v"=b۷c[6oUVa-aѣlܸזo_=zn- idYOMH!΁t.w /<[Xm׎3>+5W^'B0s47o ȇ'(鐄0L$78QvV}~=ѹv241S{֜mZ_6'c`H.cLj]. v>rGhL/ |xO""wɷer>]}_ O^m9X_q"IB@@@/>>cf]Sp mܴ!x{Bd3ulڤ$nKњOR.D}vw8(f'6eYI0$I$Q9{[ӽu搫pYʽޕs]'yCib8QIwqi7_†wCzѾמnv+RJVz16~;/wD3)?Y]WqOnY޺i}:S7gΔq{Qݯ%60E5rme1cD@r7*=v;na2o^{~qמZ5RϺxsb{=nyg?:&))ْr+"5 ZC6wI.DGiЧ ,q|voplf/ ZhoGHm:$&omrDg5rKmܬ/%KOj`rWm-It:mfzlznۚ?GZ|h]8)۰( ʛ,ދ IDATp86qn+lk$&φlh'x;մKۏQsץv݊"L=Zx<, u1ͅ"6"@Do2xї|( @(C#D\@H\M A1"@B@@4$H Dd@Pq= P̄kDl@7OND8 b0A^L ! v=0HbfAkɆ|^JK(B! f:eE9{27 }˞[ j\4j>)ºB%$*ˏSBk~T󡐄0 h33VG7JBOnрb%"@jE?vThUL1q(1Hƫ$Ђ.EQO@!ߕ4 *PE0| k~ÀČ MD$ LLD;wܳgπF( IjBߌjB ! !jkk/buuuguV||(DE6I@8p&d2KEEEfjVVV1g(,nYQh\ 3"@xG\$$ Q\\u & 8[lٺu$I{.+"n 5_ n@>0+HJJ;vСCbbblRVVz9Vf9ADRȊbbEaF׫W("2`VVXA3@D!03  #VyСB2BDEEOGvF "@fPKHaTMZbfEaI P=^ b!HH0J | ό̾+/ !WaR{5H] .{ "E_5ZL]_[!1"@UޣDft$2(^\qUK  O @n9 a&&1?DDdC0r9$$I2I&dT$I2IBr8.DDr/C!3сzމhEQXq:"旌d^Մžsnr OM¬@Dr/B! bFJ& CP"7w""ƒ,+n[rhΟ(#"[ɮ?Μ}v\n(5ѥ@@è)  \a jFDb!FD$0P "D|@CQ{2@3@D=!$hB@@""/ 4~""F/J{ 7jD!IgKGfBBldt(haBٌnҡ,?8xPW^'$I=z`Q[@il͏&v۰qcf̼M$H,}λ3Oeۢ-[lxŤZw lQ(ee74hJT0SMuE=wLƞeɄ0B z:(f(GR-+&%EQPV?&B;) EHBdv?{9ԂYc*%2ڵ‡<‡wiYP@T[;J bݎ'GO>o  KJv?У3M]3M}GKJvW+=w2e9D<$6}RL?'9WοxgO?Z;pRѩ;(@яgwշ;󺑶7+w 즹3n&WYkHI6m%cq/wv.X5 .}O_&wh3{>)~6ve4g|3R;9ïAOpl{ʺ}DL:c'9s~xq[~7k ϝ8 G6AJ^:7mv%2qܙu7 ڀD~gU7{':M?'%nyREg߽GwWrb?8r=uD7cgyc}!w7tk˙?α3#OgL^tCZζzi -X4{{=ݫ z䮦˝=$Zsk/Cg߶E_>n6 PxZQuG$Hd>G~Z)W]zƠ>=~M7h~-R/ҳqj| 󮪄]{݃bLђP*U)DD{Яyj{;[ޠmPwC?pyn3w@U#p0wSmⴗC,Mǎպ]ʑޭ|WIU^x/E!Ihڭo\u؄_fYӓ8o\WWFԃLξz;W/_zF²O&Y1vO}}_~?ν{ʫ~ɹG>}Edzow5[ xݘwJ$% |@D<\:xIp.tjnr 3 bPE5m`8@7phB^U!NZ~yAQvΧ^z OwH:OY{Ӝ}W^P%ċ~?Wk 葝۶(ZV0,)c=ayZ2*R]|߲ɺhw<|ʂG~qucx+YU@=2b2Ip(SK'𞽥SÑڹvl+**/,,$T5Qm$"ŒKDEEEjRSS(###--- JƠnPTLoS&4&ճ^IIIss BY,öP`GáF BxZ"Qin0HKi~ύ2~ #﵎YL J"1 \j%K_XB$eu К:wΝQ 5 zR"!X0@Aj2"7 ꉐL"HAYDin3 =Qmd):h?@@㹞 " D @I&]KD4"Dz@%B!HB@Dfe|ei5'SnHUR:Zk@[4 z'AffflD-(,,OJJlYYYMfʲZIMm6[^^M81==rssv{NN :4--b̼<Œ!))IM*!_ QjjڎĤ$H͂B5 fyQFFFLp "T" n+**h5_[) jAQvajj0??0Q6D:dĂS\C> 2o"fUG4y%juD&Ct1D*Ɓ"DR:LOOɱZZ`@RZnlÀ_2b0o;T3~ yGXVmhs@^ 5~ DhApݭ[7!"==]]QTTd v{ZZ a)Q A&0%'''77p֭իdfffdd8LIIhwܨT/(fXŰPmM f T"S色 akoDềintΝ3ʡCF%ZU0H1轐|@DOfD}Nj4\PPHBDB0&@@T1{G Q!)̌KD"s"! p"4_̚F|[6 )Eͪh]ˬyb LȌs"9Јa.33fl6"JIIіkRo'%%l,Ţݹfjwм-NL1|͖u֤tuynnnRCDv=333##C͑ڝ-KAAAIIn h  b EEEDA5%%%- VCm2;aPw1{N>d|B@XKMM%"fG{0ժS0(o@ n.<֬Vs %##0333))Ibbu1пgꉆMjáڔN|IQB` D͖״ƿiӦ ,~sD@dժ5$Em`J',Zּ<NB"2"=}ۡ:Y |Fxݙ+xM:llveQ6 jᐉXaE&EF@8yYwR5XHEE% bCYY)͵‰_]8DD7ӧNV'^+SAbA9D8Q,H\+lnj^yl N!#[O  {l}3abbb. 9GA2CوVmP IDAT)(D&ADL#   &fHPJ*ҡ " Dp""zC,a*Z8}}gB"TD"@$2Xtdt(haBٌ' "#u:z*22b$GL *6VqQhf۰qcf̼M0iy-}λ3Oeۢ-[lxŤZw ""1YQJRo3hƩ`z Lg=g$ " bs6,ʑfɲb2IQR\:\E#"IBdv?{9Ԃو~՟QH`8 @@Y|e{`z`ûvٴDt{y6ϙ;o񒥉G9zȏΙ;o򴙥ekjFDCFN\R1m.1m=ZRZɸ1/ƥK5W̿Cz;(FFhl@dOLlfؖ?@i7zpV<~|{Wmgß.k=jN{T7b_jG?-h^Zg·ߘuӌk"::ꚫuӌWFkDhtHD ߡ_<[gQEE Vhۄn>SΈoǕgV`WsΔy&$كe%켿OZAosێ}߷.:/[ ̨ wޝ}G~KПo؄RA*Cк3i|rGn;f2pDNۯoyO_[`M.0o{4#!*+x5ww#צ;dp<'))|V7Ni'猈iTԀ^"okW:O~I>𗵿Ӳߩy%D"h) ^:7mv%2qܙu7***(޾8y@ѣFj˓ON_Z]5H5?i9O/wkgoq }W7*^'Eg߽GwWÆg?dsz7HՋnHVnO/ˢG\84N-g׷fǷ7v|H К|:O,ʘh9mo]7hk .uѵ67DŽYsF}˞yعX=8KԧG/1us^FRbbL_JJ>>f\uz'z[̉}P#rC%DngFN2Ogn RZWTTW$3Lmũ/L=I {-1 Inιaݽ/}=7(_`GeZғuϮQԐl>Gt"inYt6 ?~{L5zIVM]NPH>hQ߰Y=++SPJ OVk}~+nm:V7FkI>zJz/=+G\پu{ӯ R*U)=*I:"aظKj/:3H> /o@#)GW_'QJNS7@/,[~f"Z0u,s`oٌ+'n{}ƙ(*rr\ vſ]ߨm 6qEQmu|ymgu:yz]579TTT.[v|QbtfYہ߯b@~yAQDT}E_{~߲o *' &>{έg/xnGgf\xvΧ^z Ow Cpܨɿw4 ?rմŬyUo{չYO[?gIΘg捎#"Sr/>ӡL=%Ϟƫj-Ewwk9 rGfQZm***:Ct.%YR,͵UDZ )D}o%R]|N+H<떜}r^"""wuFhNEstE+3AM'-|cRۼU}ȰԻsԎB/^wְzTh.j\@H{"EbnTimwRW-zjkh@$ ,33d&0$yO$=͜II0@T ۗp!*Q"HL* @CFDft&!A*D+Em͊e:H2"XC$9b\O 8]@4? c2H EQF"uK"X/ C1xΩ9@C" @ *2*Jjlq(#bİ@D@y쒡"Ę:Q0)gāC#NԚJs*DFDg c ю\Sb @ '2oфJ)Q)td%@X#1(ՁEو1bإ́XGp5VdcO-YqTx案 -Yluѣ 8@4 ش3׭ "Æ))-c@1&í "t6oάVϞ;߉Ebt%Q :A#J*N"*R B1aDWb]:ihBpu 6A65'ir ۱9wSx1 ,4 DCH P٣CNjg+,|E" h#*@v]w͓t۷ŐH:͆]D _C+=G1z @pĺv9Hq8D@()-+))2476%Kxz8f%8uޜYƩCysfpdL8G6X?9@!e@ S 4>YDXK c" ʀN ĘtT"1b3QJ8 cшa3?@7vlDW:*JT *|Ea" ED§1"@ FwD4p3h|IFp{ _odDbJԌ1Mٹa33}XZ{lbpA(")@4CB  $DGgep-=D#bgDn(+D F8F@ g\L.D#H#<%ib *pu ۈ 1:b$aD1lc ;D 1b*J&H&*:F q@ :i>6blFRM"VlDA&OG~i%e>B"w1G3,иDUZ"tⱧƌ$Xp+tۢM@p'"%K͛3kŸ#"z{?*2{|##9"s/3~ܘ r1 ֮[!ѹΞE H:,)-$">r׺w6ȰCӤ'Ⱥ#WqVD*$'gM1_@@*BDkF@:Z~C*{] $pV kjm;PeJk-a D֬P諯|u!ti>ZnݺhoV 2hxסp-VV[]w 9~i6'jܛOߴqƍ(xAo_yET%b>-ٹ˽Yt6׾OOvvGLuI}銪Kxv_pAc1m^~մ2߄1Ry0e4┧xL[Å{ﺭ|׮f|o>{VVVعtNnݺvKΛli/ݡ}xc=XYٌ_}ߙ:RD1bX;lq/ ٖQ#EuVV5_&F?~N&1).~;wݺ W,G姲5ziN r)fdN!WmLg+.}=۶}+]/4O~5WO肱> ^sM̙j|Ir=GOx!>M&X9sҥ'oj`j\:sw;lK7Hi+ye֪Cܞc7 6;3=̋gSr=WM: ^|Tf'J}Ov;?WkccөEL Z; Nђ|͇?GB@R8u.X;{|gqe?~ysf1>Xfo"+oŃ;jtqxTvy:qܠw_qHDLW>rqyN߀1}BݺtW_H? '|˫o%OnV}g6e>t`~ӱGvdɓ+[*vjǦU!6rٴ1k^;d/4bޜYkW۷m6}f PĊX0D5 Ŷ1Yݾ^o_ٞ*sɯ:0vh7?t¡|qY=ՏM;+­;v":/(rڵ83FUnc_Ғrqowع 8۷1vT؇q8<[=x.~m9MG~A=;j>>끪}Vǜ@䠋m IDAT`< zfn5cH()gW_=ͽѰZF{OQAah:J[hw =sz.,±,=U˙Ulyksqhzr/_ۛiz&f{OQYs7x!pt|l)Ov-/O=_sr"vv|@T-鎲/~[g.Ui9w7 |^*MXwܼ늊;__kJmto9kۖ-Ż*mhJ^ w>p'럹sYa SwHzl}k\lzbd'P(To[Z[-zWw-3OBy{х9ﭘ>u6hO.z1a:{Z93 Nscj.5ΚwW?ΝGtݑ׾Ewq͟t&ډhx-bY4-pݿ#O;Qow6n[}*>@[Vʞ63é?]t 7&i1-;pqc•[VlڔpOS݈Em:Ǧgq΃}ť:#|kK/׵)=?^r MЁeov7ZhEnߟι_ꙕwhEhHUbU9o}v)S.ޑ>D>/M7^#M7^/Ok6.fQ lDOͻ#kG7s"Q_nݢn[Q-Ų!p$cJ` =1.Bi B DsaGc֌] M\&XZ}7 )YI>mrIhDЇ:ok̝=p9b9s|&$i#[]Sň$#ǩY){䫵e1G TX i  kZd;泂@ F@cb.QD1R@ '"@ c3PM#\,B'@P""ĘF8\h@C @l؈ft:, 1mhDX@p{ O<nĘT4b Kq3RT\&\&ј^pu 2b8Q6ӇinD1DOob]*A*b C1#; "@ D(C161""iH$ n#1f晿A*&ڊ2RJRQD2f晿 bd,>c\=wbȰO g$bVJ)*ȜJIj#x g~쾆M@FT)YAwڋ<$7@Fa) "{׌ iBA)%ur cXRJY-˶oPҖeYR*g3@!I#,|1So%9FkmY#3'32@fZ;G(ٯWNٝjjjjkXY*G6Zk-.A7 &,˲,s[om/VRrVm^W\xe"zohDC'>RknֲnUu|ummjkkP7p>~=СÆ;>m5>T{jvoD2s",\m=ەD4R$yHCkt ;c"'RJk9C*zo*Z-9ӄWJ;o/1TJk%E gD+$K.9^J9o%RZiQF+E gG1 G1>ҙ'^mgs.0"6dHJ;>+//w޾}N"{Ox óڼyseeI'4p@ 6mڤ8pVb3gfpL&մչs⚚cL^{ >UřP4pI ^ײ,(u'_PPХK}#F9my=^ <{A 9ӁֺcǎyyyZ_wgu)ҡCU g ")<h"ҡC#F><:Ghm[iAwIQȤiE"?????Eu .([d d&%4c9C`O|=%8 Aw:cl;e3'a"3Vy[Yop>mСb3DR҅:|Z}HmWW՞m|ObJs!}nj; _'CVf0@eJ@5D7h5IENDB`mlpost-0.8.2/papers/ter-stage/slides.tex000066400000000000000000000207341306046515300202420ustar00rootroot00000000000000\documentclass{beamer} \usepackage[utf8]{inputenc} \usepackage[french]{babel} \usepackage{url,graphicx,alltt} \newcommand{\mlpost}{\textsc{Mlpost}} \newcommand{\gmlpost}{\textsc{GMlpost}} \newcommand{\meta}{\textsc{Metapost}} \newcommand{\metapost}{\textsc{Metapost}} \usetheme{Madrid} \title{Extension de la bibliothèque Mlpost} \author{J. Robert - G. Von Tokarski} \date{15 mai 2009} \begin{document} \begin{frame} \maketitle \begin{center} TER Stage - Equipe \includegraphics[scale=0.4]{proval.png} \end{center} \end{frame} \begin{frame}{Problématique} Pour l'utilisateur de \LaTeX, comment réaliser des figures \begin{itemize} \item nécessitant des calculs ? \begin{center} \includegraphics[scale=0.6]{ford.mps} \end{center} \bigskip \item incluant des éléments \LaTeX\ arbitraires ? \bigskip \begin{center} \includegraphics[scale=0.8]{graph.mps} \end{center} \end{itemize} \end{frame} \begin{frame}[fragile]\frametitle{Metapost et MLpost} \meta\ est un langage (de programmation) pour construire des dessins incluant des éléments \LaTeX. \bigskip \mlpost\ est une interface Objective Caml de \meta. \mlpost\ est développé dans l'équipe ProVal, et est disponible en téléchargement. \bigskip Avantages d'une interface Objective Caml par rapport à \meta: \begin{itemize} \item langage fonctionnel \item typage fort \item messages d'erreurs plus clairs \end{itemize} \end{frame} \begin{frame}[fragile]{Exemple de MLpost} \begin{columns} \column{0.7\textwidth}\small \begin{verbatim} Tree.draw (node "$\\alpha$" [leaf "$\\gamma$";leaf "$\\beta$"]) \end{verbatim} \column{0.3\textwidth} \includegraphics[scale=2.]{tree5.mps} \end{columns} \end{frame} \begin{frame}{Objectifs du TER} Se familiariser avec \mlpost\ et son API. Ajouter/Améliorer des modules haut niveau de \mlpost. Documenter et tester ces modules. \vfill \begin{center} \includegraphics{architecture.mps} \end{center} \end{frame} \begin{frame}{TER Stage} \begin{center} \Huge{Nos modules} \end{center} \end{frame} \begin{frame}[fragile]{Histogramme Simple} \begin{columns} \column{0.5\linewidth} \begin{verbatim} let hist = Hist.simple [3.;1.;6.] \end{verbatim} \column{0.5\linewidth} \begin{center} \includegraphics[scale=0.7]{hist1.mps} \end{center} \end{columns} \end{frame} \begin{frame}{Histogrammes comparatifs et cumulatifs} \begin{columns} \column{0.5\linewidth} \begin{center} \includegraphics% [scale=0.8] {hist2.mps} \end{center} \column{0.5\linewidth} \begin{center} \includegraphics% [scale=0.4] {hist3.mps} \end{center} \end{columns} \end{frame} \begin{frame}{API} \begin{itemize} \item Utilisation des arguments optionnels et étiquettés d'Ocaml \item Documentation générée automatiquement avec Ocamldoc \end{itemize} % \includegraphics[scale=0.5]{ocamldoc.png} \end{frame} \begin{frame}[fragile]{Exemple d'utilisation} \begin{columns} \column{0.5\linewidth} \begin{center}\footnotesize{ \begin{verbatim} let hist = let vlabel _ _ = None in let rot s = Picture.rotate 25. (Picture.tex s) in Hist.stack ~vlabel ~perspective:true ~padding:(bp 15.) ~fill:[lightred;lightblue; lightyellow;lightgreen] ~histlabel:(`Center, Hist.Values) ~vcaption:(Picture.tex "Dollars") ~hlabel:[rot "2007";rot "2008";rot "2009"] [[4.;5.;5.;]; [8.;3.;1.]; [2.;8.;1.;4.]] \end{verbatim}} \end{center} \column{0.5\linewidth} \begin{center} \includegraphics[scale=0.7]{hist5.mps} \end{center} \end{columns} \end{frame} \begin{frame}{Structure du code} \begin{itemize} \item Code factorisé: les 3 types d'histogrammes sont principalement construits à partir de la même fonction. \bigskip \item Cette fonction générale prend en paramètre une liste de listes et construit un histogramme cumulatif. \bigskip \item Les histogrammes simples et comparatifs sont des cas particuliers. \end{itemize} \end{frame} \begin{frame}{Legend} \begin{columns} \column{0.8 \linewidth} \begin{center} \includegraphics {hist3.mps} \end{center} \column{0.2 \linewidth} \includegraphics [scale=0.8]{legend1.mps} \end{columns} \end{frame} \begin{frame}{Radar} \begin{center} \includegraphics [scale=0.6] {radar2.mps} \end{center} \end{frame} \begin{frame}[fragile]{Radar cumulatif} \begin{columns} \column{0.5 \linewidth} \begin{verbatim} val stack : ?radius:Num.t -> ?color:Color.t list -> ?pen:Pen.t -> ?style:Dash.t list -> ?ticks:float -> ?label:string list -> ?scale:float list -> float list list -> Picture.t \end{verbatim} \column{0.5 \linewidth}\includegraphics [scale=0.6]{radar1.mps} \end{columns} \end{frame} \begin{frame}[fragile]{Radar comparatif} \begin{alltt} val compare : ?radius:Num.t -> ?color:Color.t list -> ?pen:Pen.t -> \color{red}?fill:bool -> \color{black} ?style:Dash.t list -> ?ticks:float -> ?label:string list -> ?scale:float list -> float list list -> Picture.t \color{red}list \end{alltt} \end{frame} \begin{frame}[fragile]{Path.smart\_path} \begin{columns} % \column{0.4 \linewidth} \bigskip \bigskip \column{0.8 \linewidth} \begin{center} \includegraphics {path5.mps} \bigskip \includegraphics {path4.mps} \end{center} \column{0.2 \linewidth} \includegraphics {path1.mps} \end{columns} \end{frame} \begin{frame}[fragile]{API} \begin{verbatim} type orientation = | Up | Down | Left | Right | Upn of Num.t | Downn of Num.t | Leftn of Num.t | Rightn of Num.t val smart_path : ?style:joint -> orientation list -> Point.t -> Point.t -> t \end{verbatim} \end{frame} \begin{frame}[fragile]{Path.smart\_path} \begin{columns} \column{0.7 \linewidth} \begin{verbatim} let path = smart_path ~style:jLine [Right;Down;Left;Down] (Point.pt (bp 0.,bp 0.)) (Point.pt (bp 0.,bp (-30.))) \end{verbatim} \column{0.3 \linewidth} \includegraphics [scale=1.2] {path2.mps} \end{columns} \end{frame} \begin{frame}{Tree} \begin{columns} \column{0.5\textwidth} \begin{center} \includegraphics [scale=1.2] {tree2simple.mps} \end{center} \column{0.5\textwidth} \begin{center} \includegraphics [scale=1.2] {tree2.mps} \end{center} \end{columns} \end{frame} \begin{frame}[fragile]{API} \begin{columns} \column{0.7 \linewidth} \begin{itemize} \item Point de départ : l'article Andrew J. Kennedy, \textit{Drawing Trees}, Journal of Functional Programming \item Adaptation de l'algorithme pour prendre en compte la taille des n\oe uds \end{itemize} \column{0.3 \linewidth} % \includegraphics[scale=1.5]{tree5.mps} \includegraphics[scale=1.2]{tree4.mps} \end{columns} \end{frame} \begin{frame}{TER Stage} \begin{center} \Huge{GMlpost} \end{center} \end{frame} \begin{frame}{GMlpost - Motivations} \begin{itemize} \item<1-> \mlpost\ permet de fabriquer des figures jolies et personnalisées. \bigskip Or il est souvent nécessaire de recompiler plusieurs fois la figure en changeant certaines valeurs pour se rapprocher du rendu souhaité. \bigskip \item<2-> \gmlpost\ est une interface graphique de \mlpost. \bigskip \gmlpost\ permet d'éditer interactivement des valeurs et des points choisis par l'utilisateur. \end{itemize} \end{frame} \begin{frame}{Démo} \end{frame} \begin{frame}{Solution technique} \begin{columns} \column{0.5 \linewidth} \begin{center} \includegraphics [scale=0.7]{interface1.mps} \end{center} \column{0.5 \linewidth} \begin{center} \includegraphics[scale=0.7]{interface2.mps} \end{center} \end{columns} \end{frame} \begin{frame}{Conclusion} \begin{itemize} \item contribution significative à \mlpost \begin{itemize} \item<1-> utilisée dès à présent dans l'équipe ProVal \item<2-> sera distribuée avec la prochaine version de \mlpost \end{itemize} \bigskip \item<3-> sur un plan personnel \begin{itemize} \item<3-> utilisation différente d'Objective Caml (arguments optionnels, OCamldoc) \item<4-> découverte de lablgtk2 \end{itemize} \end{itemize} \end{frame} \end{document} %%% Local Variables: %%% mode: latex %%% mode: whizzytex %%% mode: flyspell %%% ispell-local-dictionary: "francais" %%% End: mlpost-0.8.2/papers/ter-stage/whizzy.el000066400000000000000000000002271306046515300201160ustar00rootroot00000000000000(whizzy-add-configuration "rapport\.tex" '((whizzy . "frame -pdf .")) ) (whizzy-add-configuration "slides\.tex" '((whizzy . "frame -pdf .")) ) mlpost-0.8.2/path.ml000066400000000000000000000151341306046515300143340ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open MetaPath open Types include MetaPath.BaseDefs let transform tr p = mkPATransformed p tr let start x = of_metapath (start x) let append ?style x y = of_metapath (append ?style (of_path x) (of_path y)) type t = Types.path type metapath = Types.metapath let knotp ?(l=defaultdir) ?(r=defaultdir) p = Types.mkKnot l p r let knot ?(l) ?(r) ?(scale) p = knotp ?l (S.p ?scale p) ?r let knotn ?(l) ?(r) p = knotp ?l (S.pt p) ?r let knotlist = List.map (fun (x,y,z) -> Types.mkKnot x y z) let cycle_tmp ?(dir=defaultdir) ?(style=defaultjoint) p = mkPACycle dir style p let cycle = cycle_tmp let concat ?style x y = of_metapath (concat ?style (of_path x) y) (* construct a path with a given style from a knot list *) let pathk ?(style) ?(cycle) l = let p = MetaPath.pathk ?style l in match cycle with | None -> of_metapath p | Some style -> metacycle defaultdir style p let pathp ?(style) ?(cycle) l = pathk ?style ?cycle (List.map (knotp) l) let pathn ?(style) ?(cycle) l = pathp ?style ?cycle (List.map (Point.pt) l) let path ?(style) ?(cycle) ?(scale) l = let sc = S.ptlist ?scale in pathp ?style ?cycle (sc l) (* construct a path with knot list and joint list *) let jointpathk lp lj = of_metapath (MetaPath.jointpathk lp lj) let jointpathp lp lj = jointpathk (List.map (knotp) lp) lj let jointpathn lp lj = jointpathk (List.map knotn lp) lj let jointpath ?(scale) lp lj = jointpathk (List.map (knot ?scale) lp) lj let scale f p = mkPATransformed p [Transform.scaled f] let rotate f p = mkPATransformed p [Transform.rotated f] let shift pt p = mkPATransformed p [Transform.shifted pt] let yscale n p = mkPATransformed p [Transform.yscaled n] let xscale n p = mkPATransformed p [Transform.xscaled n] let point (f: float) p = let p = Compute.path p in Spline_lib.abscissa_to_point p f let direction (f: float) p = let p = Compute.path p in Spline_lib.direction_of_abscissa p f let pointn = point let directionn = direction let strip n p = let p0 = point 0. p in let p1 = point (length p) p in let c = scale n fullcircle in cut_after (shift p1 c) (cut_before (shift p0 c) p) (* directed paths *) type orientation = | Up | Down | Left | Right | Upn of Num.t | Downn of Num.t | Leftn of Num.t | Rightn of Num.t let divise_dir l = let rec fct left_down right_up listn =function |[] -> left_down,right_up,listn |((Leftn _|Rightn _|Downn _|Upn _) as x) ::res -> fct left_down right_up (x::listn) res |((Left|Down) as x) ::res -> fct (x::left_down) right_up listn res |((Right|Up) as x) ::res -> fct left_down (x::right_up) listn res in fct [] [] [] l open Num open Num.Infix open Point let dist_horizontal dirlist abs distance = let left,right,listn = divise_dir dirlist in let diff = (List.length right) - (List.length left) in let distance = gmean distance zero in let d = List.fold_left (fun a x -> match x with |Leftn n -> (-/) a n |Rightn n -> (+/) a n |_ -> failwith "impossible") distance listn in let dist,b = if diff = 0 then (bp 10.),false else (gmean ((/./) d (float diff)) zero),true in let rec fct acc abs = function |[] -> List.rev acc |Left::res -> let abs = (-/) abs dist in fct (abs::acc) abs res |Leftn n::res -> let abs = (-/) abs n in fct (abs::acc) abs res |Right::res -> let abs = (+/) abs dist in fct (abs::acc) abs res |Rightn n::res -> let abs = (+/) abs n in fct (abs::acc) abs res |_ -> failwith "impossible" in fct [] abs dirlist let dist_vertical dirlist ordo distance = let down,up,listn = divise_dir dirlist in let diff = (List.length up) - (List.length down) in let d = List.fold_left (fun a x -> match x with |Downn n -> (-/) a n |Upn n -> (+/) a n |_ -> failwith "impossible") distance listn in let dist,b = if diff = 0 then (bp 10.),false else (gmean ((/./) d (float diff)) zero),true in let rec fct acc ordo = function |[] -> List.rev acc |Down::res -> let ordo = (-/) ordo dist in fct (ordo::acc) ordo res |Downn n::res -> let ordo = (-/) ordo n in fct (ordo::acc) ordo res |Up::res -> let ordo = (+/) ordo dist in fct (ordo::acc) ordo res |Upn n::res -> let ordo = (+/) ordo n in fct (ordo::acc) ordo res |_ -> failwith "impossible" in fct [] ordo dirlist let smart_path ?style dirlist p1 p2 = let width = (-/) (xpart p2) (xpart p1) in let height = (-/) (ypart p2) (ypart p1) in let dirhorizontal, dirvertical = List.partition (fun x -> match x with |(Left|Right|Leftn _|Rightn _) -> true |_->false) dirlist in let lesdisth = dist_horizontal dirhorizontal (xpart p1) width in let lesdistv = dist_vertical dirvertical (ypart p1) height in let rec fct pc acc dirl dv dh = match dirl,dv,dh with |(Up|Upn _|Down|Downn _)::dres, dv::dvres, dhlist -> let ps = pt (xpart pc, dv) in fct ps (ps::acc) dres dvres dhlist |(Left|Leftn _|Right|Rightn _)::dres, dvlist, dh::dhres -> let ps = pt (dh, (ypart pc)) in fct ps (ps::acc) dres dvlist dhres |[],_, _ -> List.rev (p2::acc) |_ -> assert false in let points = fct p1 [p1] dirlist lesdistv lesdisth in pathp ?style points let draw ?brush ?color ?pen ?dashed t = (* We don't use a default to avoid the output of ... withcolor (0.00red+0.00green+0.00blue) withpen .... for each command in the output file *) mkCommand (mkCDraw t (mkBrushOpt brush color pen dashed)) let fill ?color t = mkCommand (mkCFill t color) mlpost-0.8.2/pen.ml000066400000000000000000000032261306046515300141610ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types open Transform type t = Types.pen let transform tr p = mkPenTransformed p tr let default = mkPenTransformed mkPenCircle [scaled 0.5] let circle = mkPenCircle let square = mkPenSquare let from_path p = mkPenFromPath p let scale f p = mkPenTransformed p [Transform.scaled f] let rotate f p = mkPenTransformed p [Transform.rotated f] let shift pt path = mkPenTransformed path [Transform.shifted pt] let yscale n p = mkPenTransformed p [Transform.yscaled n] let xscale n p = mkPenTransformed p [Transform.xscaled n] mlpost-0.8.2/picture.ml000066400000000000000000000101631306046515300150500ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types open Point_lib type t = commandpic let tex s = mkPicture (mkPITex s) let make l = l let empty = mkSeq [] let bbox pic = mkPABBox pic let ulcorner pic = let pic = Compute.commandpic pic in let ll, ur = Picture_lib.bounding_box pic in { x = ll.x ; y = ur.y } let llcorner pic = let pic = Compute.commandpic pic in let ll, _ = Picture_lib.bounding_box pic in ll let urcorner pic = let pic = Compute.commandpic pic in let _, ur = Picture_lib.bounding_box pic in ur let lrcorner pic = let pic = Compute.commandpic pic in let ll, ur = Picture_lib.bounding_box pic in { Point_lib.x = ur.x ; y = ll.y } let north_west = ulcorner let south_west = llcorner let north_east = urcorner let south_east = lrcorner let corner_bbox ?(dx=Num.zero) ?(dy=Num.zero) pic = let pdx = Point.pt (dx, Num.zero) in let pdy = Point.pt (Num.zero, dy) in Path.pathp ~style:Path.jLine ~cycle:Path.jLine [Point.add (Point.sub (ulcorner pic) pdx) pdy; Point.sub (Point.sub (llcorner pic) pdx) pdy; Point.sub (Point.add (lrcorner pic) pdx) pdy; Point.add (Point.add (urcorner pic) pdx) pdy] let ctr pic = Point.segment 0.5 (llcorner pic) (urcorner pic) let transform tr p = mkPicture (mkPITransformed p tr) let scale f p = transform [Transform.scaled f] p let rotate f p = transform [Transform.rotated f] p let shift pt p = transform [Transform.shifted pt] p let yscale n p = transform [Transform.yscaled n] p let xscale n p = transform [Transform.xscaled n] p let spin f p = transform [Transform.rotate_around (ctr p) f] p let place f pic p = shift (Point.sub p (f pic)) pic let center p pic = place ctr pic p let place_up_left p pic = place ulcorner pic p let place_up_right p pic = place urcorner pic p let place_bot_left p pic = place llcorner pic p let place_bot_right p pic = place lrcorner pic p let beside p1 p2 = mkSeq [p1; place_up_left (urcorner p1) p2] let below p1 p2 = mkSeq [p1; place_up_left (llcorner p1) p2] let clip pic pth = mkPicture (mkPIClip pic pth) let width p = Point.xpart (Point.sub (urcorner p) (ulcorner p)) let height p = Point.ypart (Point.sub (urcorner p) (lrcorner p)) let north p = Point.segment 0.5 (north_east p) (north_west p) let south p = Point.segment 0.5 (south_east p) (south_west p) let west p = Point.segment 0.5 (south_west p) (north_west p) let east p = Point.segment 0.5 (north_east p) (south_east p) let corner pos x = match pos_reduce pos with | `Northwest -> north_west x | `Northeast -> north_east x | `Southwest -> south_west x | `Southeast -> south_east x | `West -> west x | `East -> east x | `Center -> ctr x | `North -> north x | `South -> south x type escaped = [`Backslash |`Underscore] let rec escaped_to_list acc = function | [] -> acc | `Underscore::l -> escaped_to_list (('_',"\\_")::acc) l | `Backslash::l -> escaped_to_list (('\\',"\\backslash")::acc) l let escape_latex l = Misc.generic_quote_list (escaped_to_list [] l) let escape_all = escape_latex [`Backslash;`Underscore] let set_pos = center mlpost-0.8.2/plot.ml000066400000000000000000000156521306046515300143630ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Command open Helpers open Path open Num open Num.Infix type skeleton = { width : int; height : int; stepx : Num.t; stepy : Num.t; } let mk_skeleton width height stepx stepy = {width = width; height = height; stepx = stepx; stepy = stepy} type labels = int -> Num.t -> Picture.t option type ticks = (Num.t * Pen.t) option let get_style = function | None -> fun i -> Dash.evenly, Pen.default | Some f -> f let off_pattern = fun i -> Dash.pattern [Dash.on (bp 5.)] let defpen = fun i -> Pen.default let get_borders sx sy h w = zero, sx */ (num_of_int w), sy */ (num_of_int h), zero let draw_grid ?(hdash=off_pattern) ?(vdash=off_pattern) ?(hpen=defpen) ?(vpen=defpen) ?color {width=w; height=h; stepx=sx; stepy=sy} = let maxl, maxr, maxu, maxd = get_borders sx sy h w in let drawline dashed pen p = Command.draw ~pen ~dashed ?color p in let horizontal i = let y = num_of_int i */ sy in let pi = pathn [maxl, y; maxr, y] in drawline (hdash i) (hpen i) pi in let vertical i = let x = num_of_int i */ sx in let pi = pathn [x, maxd; x, maxu] in drawline (vdash i) (vpen i) pi in seq (Misc.fold_from_to (fun acc i -> (horizontal i) :: acc) (Misc.fold_from_to (fun acc i -> (vertical i) :: acc) [] 0 w) 0 h) (* This is a hack, we need the maximal size a label can take *) let label_scale stepx = let max_width = Picture.width ( Picture.tex "$55$") in ( 4. /. 5.) *./ stepx // max_width (* The default label function, it is quite generic as the labels are resized * when they do not fit into a cell *) let deflabel x w = Some (Picture.transform [Transform.scaled (label_scale w)] (Picture.tex (Printf.sprintf "$%d$" x))) let defticks = Some ((bp 0.25), Pen.default) let get_corners maxu maxr = (bp 0., maxu), (maxr, maxu), (bp 0., bp 0.), (maxr, bp 0.) let draw_axes ?(hpen=Pen.default) ?(vpen=Pen.default) ?(hlabel= deflabel) ?(vlabel=deflabel) ?(ticks=defticks) ?(closed=false) ?hcaption ?vcaption {width=w; height=h; stepx=sx; stepy=sy} = let maxl, maxr, maxu, maxd = get_borders sx sy h w in let ul, ur, ll, lr = get_corners maxu maxr in let hcaptcmd = match hcaption with | None -> Command.nop | Some labl -> let hlabels_height = match (hlabel w sx) with | None -> Num.zero | Some pic -> Picture.height pic in let h_caption_height = Picture.height labl in Command.label ~pos:`Southwest labl (Point.pt (num_of_int w */ sx, Num.zero -/ hlabels_height -/ (bp 0.5) */ h_caption_height )) in let vcaptcmd = match vcaption with | None -> Command.nop | Some labl -> let rot_labl = (Picture.transform [Transform.rotated 90.] labl) in let vlabels_width = match (vlabel h sy) with | None -> Num.zero | Some pic -> Picture.width pic in let v_caption_width = Picture.width rot_labl in Command.label ~pos:`Southwest rot_labl (Point.pt ( Num.zero -/ vlabels_width -/ (bp 0.5) */ v_caption_width, num_of_int h */ sy)) in let labelcmd pos p i f = match f i sx with | None -> Command.nop | Some x -> Command.label ~pos x p in let ticks_cmd pathf = match ticks with | None -> Command.nop | Some (f,pen) -> Command.draw ~pen (pathf f) in let horizontal i = let x = num_of_int i */ sx in seq [ labelcmd `South (Point.pt (x,maxd)) i hlabel; ticks_cmd (fun f -> pathn [x,maxd; x, maxd +/ (sy */ f)]); if closed then ticks_cmd (fun f -> pathn [x,maxu; x, maxu -/ sy */f]) else Command.nop ] in let vertical i = let y = num_of_int i */ sy in seq [labelcmd `Left (Point.pt (maxl, y)) i vlabel; ticks_cmd (fun f -> pathn [maxl,y; maxl +/ sx */ f,y]); if closed then ticks_cmd (fun f -> pathn [maxr,y; maxr -/ sy */ f, y]) else Command.nop ] in seq [Command.draw ~pen:hpen (pathn [ll; lr]); Command.draw ~pen:vpen (pathn [ll; ul]); if closed then seq [Command.draw ~pen:hpen (pathn [ul; ur]); Command.draw ~pen:vpen (pathn [lr; ur])] else Command.nop; hcaptcmd; vcaptcmd; seq (Misc.fold_from_to (fun acc i -> (horizontal i) :: acc) (Misc.fold_from_to (fun acc i -> (vertical i) :: acc) [] 0 h) 0 w) ] let draw_simple_axes ?hpen ?vpen hcaption vcaption sk = draw_axes ?hpen ?vpen ~hlabel:(fun _ _ -> None) ~vlabel:(fun _ _ -> None) ~ticks:None ~hcaption:(Picture.tex hcaption) ~vcaption:(Picture.rotate (-90.) (Picture.tex vcaption)) sk type drawing = | Stepwise | Normal let draw_func ?(pen) ?(drawing=Normal) ?style ?dashed ?color ?label ?(from_x=0) ?to_x f {width=w; height=h; stepx=sx; stepy=sy} = let to_x = match to_x with None -> w | Some x -> x in let maxl, maxr, maxu, maxd = get_borders sx sy h w in let ul, ur, ll, lr = get_corners maxu maxr in let box = pathn ~style:jLine ~cycle:jLine [ul;ll;lr;ur] in let normal acc i = let x, y = (num_of_int i) */ sx, (Num.bp (f i)) */ sy in (x,y)::acc in let stepwise (acc,x,y) i = let nx, ny = (num_of_int i) */ sx, (Num.bp (f i)) */ sy in (nx,ny) :: (nx,y) :: acc, nx, ny in let graph = match drawing with | Normal -> Misc.fold_from_to normal [] from_x to_x | Stepwise -> let p, _,_ = Misc.fold_from_to stepwise ([],Num.bp 0.,Num.bp 0.) from_x to_x in p in let pic = Picture.clip (Picture.make (Command.draw ?pen ?dashed ?color (pathn ?style graph))) box in match label with | None -> draw_pic pic | Some (lab, pos, i) -> let pt = Point.pt (num_of_int i */ sx, (Num.bp (f i)) */ sy) in seq [Command.label ~pos lab pt; draw_pic pic] mlpost-0.8.2/point.ml000066400000000000000000000056151306046515300145340ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types open Point_lib type corner = Types.corner type t = Ctypes.point (* angle in degrees *) let dir f = let angle = Num.deg2rad f in { x = cos angle ; y = sin angle } let up = { x = 0. ; y = 1. } let down = { x = 0. ; y = -1. } let left = { x = -1. ; y = 0. } let right = { x = 1. ; y = 0. } let xpart p = p.x let ypart p = p.y let add = add let mult = mult let sub = sub let shift = add let scale = mult let segment = segment let rotate angle p = rotated (Num.deg2rad angle) p (* rotate p2 around p1 *) let rotate_around p1 f p2 = add p1 (rotate f (sub p2 p1)) let xscale f p = { p with x = f *. p.x } let yscale f p = { p with y = f *. p.y } let transform (tr : Transform.t) (p : t) : t = let t = Compute.transform tr in Point_lib.transform t p let pt (a,b) = { x = a ; y = b } let p ?(scale=Num.bp) (x,y) = { x = scale x ; y = scale y } let length p = Num.gmean (xpart p) (ypart p) let origin = p (0.,0.) let ptlist ?scale l = List.map (p ?scale) l (* construct a point with the right measure *) let bpp, inp, cmp, mmp, ptp = p ~scale:Num.bp, p ~scale:Num.inch, p ~scale:Num.cm, p ~scale:Num.mm, p ~scale:Num.pt (* construct a list of points with the right measure *) let map_bp, map_in, map_cm, map_mm, map_pt = ptlist ~scale:Num.bp, ptlist ~scale:Num.inch, ptlist ~scale:Num.cm, ptlist ~scale:Num.mm, ptlist ~scale:Num.pt let draw ?brush ?color ?pen t = (* We don't use a default to avoid the output of ... withcolor (0.00red+0.00green+0.00blue) withpen .... for each command in the output file *) mkCommand (mkCDraw (mkPAofMPA (mkMPAKnot (mkKnot mkNoDir t mkNoDir))) (mkBrushOpt brush color pen None)) let normalize p = let l = length p in scale (if Num.is_zero l then 0. else 1. /. l) p mlpost-0.8.2/presentations/000077500000000000000000000000001306046515300157405ustar00rootroot00000000000000mlpost-0.8.2/presentations/proval/000077500000000000000000000000001306046515300172435ustar00rootroot00000000000000mlpost-0.8.2/presentations/proval/Makefile000066400000000000000000000010171306046515300207020ustar00rootroot00000000000000MPSFILES := cfg proval mpex colortriangle path cheno pictures tree2 \ tree6 florence MPSFILES := $(patsubst %,%.mps, $(MPSFILES)) GENERATED := cfg proval colortriangle path cheno pictures tree2 tree6 GENERATED := $(patsubst %,%.mp, $(GENERATED)) pdf: slides.pdf slides.pdf: $(MPSFILES) slides.tex pdflatex slides.tex pdflatex slides.tex %.mps: %.ml mlpost -pdf -latex slides.tex $^ clean: rm -f *.toc *.aux *.pdf *.log *~ *.mp[sx] *.snm *.nav *.out rm -f $(GENERATED) %.mps: %.1 mv $^ $@ %.1: %.mp mpost $^ end mlpost-0.8.2/presentations/proval/cfg.ml000066400000000000000000000015101306046515300203310ustar00rootroot00000000000000open Mlpost open Command open Diag let fig = let pen = Pen.circle () in let empty_node x y = node x y "\\phantom{M}" in let a = empty_node 0. 4. in let b = empty_node 0. 3. in let inv = node 0. 2. "inv" in let c = empty_node 0. 1. in let d = empty_node 0. 0. in let do_ = node (-2.) 2. "do" in let diag = create [a;b;c;d;inv;do_] in let arrow = arrow diag in arrow a b ~lab:"$i\\leftarrow0$" ~pos:Pright; arrow b inv ~lab:"$m\\leftarrow t[i]$" ~pos:Pright; arrow c d ~lab:"$i\\ge n$" ~pos:Pright; arrow c do_ ~outd:Left ~ind:Down ~lab:"$i draw ~pen ~color (path ~style:JLine ~scale:N.cm [a;b])) [(a, b); (b, c); (c, a)] [red;blue;green] in let pic = Picture.make (seq triangle) in let pic2 = Picture.transform [Transform.scaled 0.3; Transform.rotated 30.; Transform.shifted (Point.p ~scale:N.cm (0.2,0.2))] pic in [draw_pic pic; draw_pic pic2] let _ = Metapost.emit "colortriangle" d12 mlpost-0.8.2/presentations/proval/florence.ml000066400000000000000000000041761306046515300214020ustar00rootroot00000000000000open Mlpost open Command open Path open Point open Plot module T = Transform let f1 i = let aux = function | 0 -> 1 | 1 | 2 -> 2 | 3 | 4 -> 3 | 5 -> 4 | 6 | 7 -> 5 | 8 |9 -> 6 | 10 -> 7 | 11 | 12 -> 8 | 13 | 14 -> 9 | 15 -> 10 | 16 | 17 -> 11 | 18 | 19 -> 12 | 20 -> 13 | _ -> 0 in float_of_int (aux i) let f2 i = let aux = function | 0 | 1 | 2 -> 0 | 3 -> 1 | 4 -> 2 | 5 | 6 | 7 -> 3 | 8 -> 4 | 9 -> 5 | 10 | 11 | 12 -> 6 | 13 -> 7 | 14 -> 8 | 15 | 16 | 17 -> 9 | 18 -> 10 | 19 -> 11 | 20 -> 12 | _ -> 0 in float_of_int (aux i) let f3 i = float_of_int ((i+3)/5) let flab i = (Picture.transform [Transform.scaled 1.7] (Picture.tex (Printf.sprintf "$f_{\\omega_%d}$" i)), Command.Ptop, 19) let instants = let pen = Pen.default ~tr:[Transform.scaled 2.5] () in let base = Command.draw ~pen (Path.path ~style:JLine [(0.,-65.); (280.,-65.)]) in let tick i = let xi = float_of_int i *. 14. in let yi = if f1 i = f1 (i-1) then -60. else -45. in let p = Path.path ~style:JLine [(xi,-65.); (xi, yi)] in Command.draw ~pen p in Command.seq [base; Command.iter 0 20 tick; Command.label (Picture.transform [Transform.scaled 2.] (Picture.tex "$\\omega_1$")) (pt (-20.,-55.))] let florence = let sk = mk_skeleton 20 14 14. 20. in let pen = Pen.default ~tr:[Transform.scaled 4.] () in let pen2 = Pen.default ~tr:[Transform.scaled 3.] () in let dash _ = Dash.scaled 0.5 Dash.withdots in let dash2 = Dash.scaled 0.66 Dash.withdots in let dash3 = Dash.scaled 0.9 Dash.evenly in let vcaption, hcaption = let tr = [Transform.scaled 1.5] in Picture.transform tr (Picture.tex "\\textsf{Number of ones}"), Picture.transform tr (Picture.tex "\\textsf{Instants}") in let plot = draw_func ~drawing:Stepwise ~style:JLine in [ draw_grid ~hdash:dash ~vdash:dash sk; draw_axes ~closed:true ~hcaption ~vcaption sk; plot ~pen ~label:(flab 1) f1 sk; plot ~pen:pen2 ~dashed:dash2 ~label:(flab 2) f2 sk; plot ~pen ~dashed:dash3 ~label:(flab 3) f3 sk; instants ] let _ = Metapost.emit "florence" florence mlpost-0.8.2/presentations/proval/mpex.mp000066400000000000000000000004221306046515300205500ustar00rootroot00000000000000beginfig(1); numeric u; u = 1cm; draw (0,2u)--(0,0)--(4u,0); pickup pencircle scaled 1pt; draw (0,0){up} for i=1 upto 8: ..(i/2,sqrt(i/2))*u endfor; label.lrt(btex $\sqrt x$ etex, (3,sqrt 3)*u); label.bot(btex $x$ etex, (2u,0)); label.lft(btex $y$ etex, (0,u)); endfig; mlpost-0.8.2/presentations/proval/path.ml000066400000000000000000000016571306046515300205420ustar00rootroot00000000000000open Mlpost open Path open Point open Command open Picture module H = Helpers let z0 = 0.,0. let z1 = 60.,40. let z2 = 40.,90. let z3 = 10.,70. let z4 = 30.,50. let l1 = z0::z1::z2::z3::z4::[] let labels1 = (H.dotlabels ~pos:Ptop ["0";"2";"4"] (map_bp [z0;z2;z4])) @ [dotlabel ~pos:Pleft (tex "3") (bpp z3); dotlabel ~pos:Pright (tex "1") (bpp z1) ] let lcontrols = [(26.8, -1.8), (51.4,14.6); (67.1, 61.), (59.8,84.6); (25.4, 94.), (10.5,84.5); (9.6, 58.8), (18.8,49.6)] let lcontrolsbp = List.map (fun (a,b) -> JControls (bpp a, bpp b)) lcontrols let draw5 = [ draw (jointpath l1 lcontrolsbp) ; let hull = List.fold_left2 (fun acc (c1, c2) f -> f::c2::c1::acc) [0.,0.] lcontrols (List.tl l1) in (* As long as we dont have the dashed lines : gray *) draw ~dashed:(Dash.scaled 0.5 Dash.evenly) (path ~style:JLine (List.rev hull)) ] @ labels1 let _ = Metapost.emit "path" draw5 mlpost-0.8.2/presentations/proval/pictures.ml000066400000000000000000000006311306046515300214330ustar00rootroot00000000000000open Mlpost let half pic = Picture.transform [Transform.scaled 0.5] pic let rec right_split n pic = if n <= 0 then pic else let smaller = right_split (n-1) (half pic) in Picture.beside pic (Picture.below smaller smaller) let d11 = let p1 = Picture.transform [Transform.rotated 90.] (Picture.tex "Proval") in [Command.draw_pic (right_split 2 p1)] let _ = Metapost.emit "pictures" d11 mlpost-0.8.2/presentations/proval/proval.ml000066400000000000000000000010211306046515300210720ustar00rootroot00000000000000open Mlpost open Command open Path module T = Transform let fig = let f = 7. in let pen = Pen.square ~tr:[T.yscaled 0.5; T.rotated 40.] () in let check = jointpath [-1.2,1.2; 0., -2. ; 2., 2. ; 5., 5.] [JLine ; JCurve; JCurve] in [fill ~color:Color.black (transform [T.scaled f] Path.fullcircle) ; label ~pos:Pleft (Picture.tex "Pr") (Point.p (f /. (-4.),0.)) ; label ~pos:Pright (Picture.tex "al") (Point.p (f /. 4.,0.)) ; draw ~color:Color.green ~pen check;] let _ = Metapost.emit "proval" fig mlpost-0.8.2/presentations/proval/slides.tex000066400000000000000000000212671306046515300212600ustar00rootroot00000000000000\documentclass[nodefaultblocks]{beamer} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{beamerthemesplit} \usepackage{stmaryrd} \usepackage{amsfonts} \usepackage{latexsym} \usepackage{amssymb} \usepackage{amsmath} \usepackage{mathrsfs} \usepackage{pifont} \usepackage{shadow} \usepackage{alltt} \usepackage{tikz} \usepackage[dvips]{epsfig} \usetheme{Madrid} \beamertemplatenavigationsymbolsempty \definecolor{yel}{rgb}{.9,.8,.4} \definecolor{mygray}{rgb}{0.85,0.85,0.85} \def \ebox #1{\colorbox{yel}{\mbox {\strut #1}}} \def \gbox #1{\colorbox{mygray}{\mbox {\strut #1}}} \title{MlPost} \author{The MlPost team} \institute{Proval} \date{Réunion Proval} \begin{document} \begin{frame} \begin{center} {\huge{MlPost - un outil de dessin scientifique}}\\[2em] {\large \alert{Jean-Christophe Filli\^atre, Johannes Kanig, St\'ephane Lescuyer}} \medskip \hfill\includegraphics[height=5cm]{cfg.mps} \end{center} \hfill\includegraphics{proval.mps} % \hfill\includegraphics[width=0.15\textwidth]{lrilogo.jpg}ρ \end{frame} \begin{frame}\frametitle{Motivation} \begin{block}{Problème} Un outil capable de combiner \begin{itemize} \item des éléments de dessin souvent simples \item du Latex, et prise en compte de sa taille \item Automatisation commode (dessin de grille, placement d'arbre) \end{itemize} \end{block} \begin{block}{Solutions existantes} \begin{itemize} \item outils graphiques gratuits style {\tt dia} : Pas de support Latex, pas d'automatisation \item outils ``langages de programmation'': Metapost, Tikz \end{itemize} \end{block} \end{frame} \begin{frame}\frametitle{Metapost} \begin{minipage}{0.3\linewidth} \includegraphics{mpex.mps} \end{minipage} \hfill \begin{minipage}{0.6\linewidth} \small \begin{alltt} beginfig(1);\\ \hspace*{0pt}~ numeric u;\\ \hspace*{0pt}~ u = 1cm;\\ \hspace*{0pt}~ draw (0,2u)---(0,0)---(4u,0);\\ \hspace*{0pt}~ pickup pencircle scaled 1pt;\\ \hspace*{0pt}~ draw (0,0)\{up\}\\ \hspace*{0pt}~ for i=1 upto 8: \\ \hspace*{0pt}~~~ ..(i/2,sqrt(i/2))*u \\ \hspace*{0pt}~ endfor;\\ \hspace*{0pt}~ label.lrt(btex $\sqrt x$ etex, \hspace*{0pt}~ ~ ~ ~ ~ ~ (3,sqrt 3)*u);\\ \hspace*{0pt}~ label.bot(btex $x$ etex, (2u,0));\\ \hspace*{0pt}~ label.lft(btex $y$ etex, (0,u));\\ endfig;\\ \end{alltt} \end{minipage} \end{frame} \begin{frame}[fragile]\frametitle{Tikz} \begin{minipage}[]{0.45\textwidth} \footnotesize \begin{verbatim} \shade[top color=blue, bottom color=gray!50] (0,0) parabola (1.5,2.25) |- (0,0); \draw[style=help lines] (0,0) grid (3.9,3.9) [step=0.25cm] (1,2) grid +(1,1); \draw[->] (-0.2,0) -- (4,0) node[right] {$x$}; \draw[->] (0,-0.2) -- (0,4) node[above] {$f(x)$}; \draw (-.5,.25) parabola bend (0,0) (2,4) node[below right] {$x^2$}; \end{verbatim} \end{minipage} \begin{minipage}[]{0.4\textwidth} \begin{tikzpicture}[scale=1.4] \shade[top color=blue,bottom color=gray!50] (0,0) parabola (1.5,2.25) |- (0,0); \draw[style=help lines] (0,0) grid (3.9,3.9) [step=0.25cm] (1,2) grid +(1,1); \draw[->] (-0.2,0) -- (4,0) node[right] {$x$}; \draw[->] (0,-0.2) -- (0,4) node[above] {$f(x)$}; \draw (-.5,.25) parabola bend (0,0) (2,4) node[below right] {$x^2$}; \end{tikzpicture} \end{minipage} \end{frame} \begin{frame}\frametitle{Pourquoi pas MetaPost ou Tikz ?} \begin{block}{MetaPost} \begin{itemize} \item Pas de structures de données \item Pas de fonctions (seulement macros textuelles) \item précédences des opérateurs très bizarres \end{itemize} \end{block} \begin{block}{Tikz} \begin{itemize} \item langage très complet, similaire dans l'esprit à MetaPost \item les dessins se font directement en \LaTeX \item compliqué à prendre en main \end{itemize} \end{block} \medskip les deux : Encore un langage à apprendre, messages d'erreur incompréhensibles, \dots \end{frame} \begin{frame}\frametitle{MlPost} \begin{block}{A commencé comme un ``pretty-printeur'' de Metapost} \begin{itemize} \item pour profiter des capacités de Metapost \item typage et expressivité de Caml \item developpement facilité d'extensions \end{itemize} \end{block} \begin{block}{Aujourd'hui : bibliothèque OCaml} \begin{itemize} \item un ``cross-compiler'' vers Metapost \item interface fonctionnelle \item memoization des différents motifs d'un dessin \item utiliser le côté impératif de MetaPost pour du partage \end{itemize} \end{block} \end{frame} \begin{frame}\frametitle{Brique de base : les chemins} \begin{block}{Les chemins} \begin{itemize} \item Une liste de points, connectés par des lignes droites, des courbes de Bézier, \dots \item on peut les fermer, les combiner, les intersecter, remplir la surface délimitée, s'en servir pour faire du {\em clipping}, \dots \end{itemize} \end{block} \begin{center} \includegraphics{path.mps} \end{center} \end{frame} \begin{frame}\frametitle{Types de base} \begin{block}{Types différents} \begin{itemize} \item longueurs : {\tt Num} \item points : {\tt Point} \item chemins : {\tt Path} \item transformations affines : {\tt Transform} \item plumes : {\tt Pen} \item couleurs : {\tt Color} \end{itemize} \end{block} \begin{center} \includegraphics[width=0.3\textheight]{colortriangle.mps} \end{center} \end{frame} \begin{frame}\frametitle{Objets avancés} \begin{block}{On peut se servir de \dots} \begin{itemize} \item Boîtes rondes ou rectangulaires qui contiennent du MlPost arbitraire \item des chemins avec des flèches \item \LaTeX\ arbitraire \item \dots \end{itemize} \end{block} \bigskip \begin{center} \includegraphics[width=0.5\textheight]{cheno.mps} \end{center} \end{frame} \begin{frame}\frametitle{Pictures} \begin{block}{Une figure est \dots} \begin{itemize} \item Un objet \LaTeX \item Une liste de commandes \item tout ce qui peut être dessiné avec MlPost ! \end{itemize} \end{block} \begin{minipage}[]{0.5\textwidth} \begin{block}{Manipulation des figures} \begin{itemize} \item Rotation, Translation \item Placement à côté, en dessous \item Scaling \item \dots \end{itemize} \end{block} \end{minipage} \begin{minipage}[]{0.4\textwidth} \begin{center} \includegraphics[height=0.5\textheight]{pictures.mps} \end{center} \end{minipage} \end{frame} \begin{frame}\frametitle{Première Extension : les arbres} \begin{block}{dessiner un arbre \dots} \begin{itemize} \item c'est facile ! \item il suffit de donner la structure de l'arbre et les options de dessin \end{itemize} \end{block} \begin{minipage}[]{0.45\textwidth} \begin{center} \includegraphics[height=0.3\textheight]{tree2.mps} \end{center} \end{minipage} \begin{minipage}[]{0.45\textwidth} \begin{center} \includegraphics[height=0.3\textheight]{tree6.mps} \end{center} \end{minipage} \end{frame} \begin{frame}\frametitle{Deuxième Extension : les diagrammes} \begin{block}{Pour dessiner un graphe} \begin{itemize} \item Donner les noeuds avec le contenu \item Donner les arrêtes avec les labels, la courbure, \ldots \item Jouer ! \end{itemize} \end{block} \begin{center} \includegraphics[height=5cm]{cfg.mps} \end{center} \end{frame} \begin{frame}{Dernière Extension : Plot} \begin{block}{Plotter une fonction} \begin{itemize} \item Dessiner des axes \item Ajouter une grille \item Plotter des fonctions \end{itemize} \end{block} \begin{center} \includegraphics[height=5cm]{florence.mps} \end{center} \end{frame} \begin{frame}\frametitle{Conclusion} \begin{block}{Points forts de MlPost} \begin{itemize} \item les mêmes que MetaPost ! \item Bibliothèque Caml - dans votre langage de programmation favori \item The sky is the limit : on attend vos extensions \end{itemize} \end{block} \begin{block}{Inconvénients} \begin{itemize} \item Syntaxe un peu lourde (inévitable, sans réinventer un langage), camlp4~? \item Toutes les erreurs ne peuvent pas être détectées par typage \end{itemize} Pour l'instant : \begin{itemize} \item Pas toutes les fonctionnalités de MetaPost, peu d'extensions comparé à Tikz \item ``lock-in'' de certaines extensions \end{itemize} \end{block} \end{frame} \end{document} mlpost-0.8.2/presentations/proval/tree2.ml000066400000000000000000000003101306046515300206100ustar00rootroot00000000000000open Mlpost open Tree let fig = [draw ~node_style:Rect ~arrow_style:Undirected (node "1" [node "2" [leaf "4"; leaf "5"]; node "3" [leaf "6"; leaf "7"]])] let _ = Metapost.emit "tree2" fig mlpost-0.8.2/presentations/proval/tree6.ml000066400000000000000000000002661306046515300206260ustar00rootroot00000000000000open Mlpost open Tree let fig = [draw ~edge_style:HalfSquare (node "1" [node "2" [leaf "4"; leaf "5"]; node "3" [leaf "6"; leaf "7"]])] let _ = Metapost.emit "tree6" fig mlpost-0.8.2/presentations/workshop-ml-2009/000077500000000000000000000000001306046515300206125ustar00rootroot00000000000000mlpost-0.8.2/presentations/workshop-ml-2009/Makefile000066400000000000000000000003351306046515300222530ustar00rootroot00000000000000all: slides.pdf FIGURES:= fibtree.pdf $(FIGURES): figures.ml mlpost -cairo $< make -C ../../papers/jfla2009/ figures.mp view: slides.pdf xpdf slides.pdf slides.pdf: $(FIGURES) slides.tex %.pdf: %.tex pdflatex $< mlpost-0.8.2/presentations/workshop-ml-2009/figures.ml000066400000000000000000000130021306046515300226040ustar00rootroot00000000000000open Mlpost open Box open Tree open Color let sprintf = Format.sprintf let stern_brocot h = let frac (a,b) = tex (sprintf "$\\frac{%d}{%d}$" a b) in let rec make ((a,b) as lo) ((c,d) as hi) h = let r = a+c, b+d in if h = 1 then leaf (frac r) else node ~arrow_style:Undirected (frac r) [make lo r (h-1); make r hi (h-1)] in make (0,1) (1,0) h let tree8 = draw (stern_brocot 5) let texint n = tex (sprintf "$F_{%d}$" n) let rec fib = function | 0 | 1 as n -> leaf (texint n) | n -> node ~arrow_style:Undirected (texint n) [fib (n-1); fib (n-2)] let fibtree = draw (fib 6) type t = | Node of int * t list let rec bin = function | 0 -> Node (0, []) | n -> let (Node (_,l) as t) = bin (n-1) in Node (n, t :: l) let rec trans (Node (n,l)) = node ~arrow_style:Undirected (tex (sprintf "${2^{%d}}$" n)) (List.map trans l) let tree10 = draw (trans (bin 4)) open Num open Color let hist = Hist.stack ~fill:[lightred;lightblue;lightyellow;lightgreen] [[4.;5.;5.;]; [8.;3.;1.]; [2.;8.;1.;4.]] open Helpers open Command open Box let hbox = hbox ~padding:(bp 30.) let vbox = vbox ~padding:(bp 30.) let diag = let rt s = rect (tex s) in let a = rt "A" and b = rt "B" and c = rt "C" in let ab = round_rect ~dx:(bp 10.) ~dy:(bp 10.) (hbox [a;b]) in let v = vbox [ab;c] in let arrow x y = box_arrow ~sep:(bp 5.) (sub x v) (sub y v) in draw v ++ arrow a b ++ arrow ab c let (|>) x f = f x let archi_backend = let sep = bp 5. and dx = bp 5. and dy = bp 10. in let rt ?fill s = round_rect ?fill (tex s) in let sigma = tex "$\\Sigma$" in let metapost = rt ~fill:lightred "Metapost" and cairo = rt ~fill:lightred "Cairo" and concrete = rt ~fill:lightblue "Concrete" and mp = rt ~fill:lightred ".mp" in let left = vbox [mp;metapost] in let lsigma = sub sigma (Box.hbox [sub metapost left;sigma]) in let left = round_rect ~dy ~dx ~fill:lightgreen (group [left;lsigma]) in let right = vbox [concrete;cairo] in let rsigma = sub sigma (Box.hbox [sub concrete right;sigma]) in let right = group [right;rsigma] in let center = hbox [left;right] in let mlpost = tex "Mlpost" in let mlpost = List.hd (same_width [mlpost;center]) in let mlpost = round_rect ~fill:lightblue mlpost in let output = rt ~fill:lightgray "output" in let img = Box.scale (bp 0.5) (round_rect ~fill:lightyellow ~dy ~dx (Tree.to_box (fib 3))) in let all = vbox [mlpost;center;output] in let img = Box.place `East ~padding:(bp 30.) (sub output all) img in let arrow (x,y) = box_arrow ~sep (sub x all) (sub y all) in let arrows = [(mp,metapost); (concrete,cairo); (mlpost,concrete); (concrete,mlpost); (mlpost,mp); (metapost,output);(cairo,output)] |> List.map arrow |> seq in draw all ++ arrows ++ draw img ++ box_arrow ~sep (sub output all) img (* Koda-Ruskey *) open Command open Num open Path open Box open Tree type tree = Node of int * forest and forest = tree list type color = White | Black let bits = Array.create 100 White let rec enum_forest k = function | [] -> k () | Node (i, f') :: f -> let k () = enum_forest k f in if bits.(i) = White then begin k (); bits.(i) <- Black; enum_forest k f' end else begin enum_forest k f'; bits.(i) <- White; k () end let leaf i = Node (i, []) let t1 = Node (0, [leaf 1]) let t2 = Node (2, [leaf 3; leaf 4]) let f0 = [t1; t2] let draw1 f0 = let white = circle (empty ()) in let black = circle ~fill:Color.black (empty ()) in let node = node ~arrow_style:Undirected ~ls:(bp 10.) ~sep:(bp 2.) in let rec make_tree = function | [] -> [] | Node (i, sons) :: f -> (node (if bits.(i) = White then white else black) (make_tree sons)) :: make_tree f in hbox ~padding:(bp 5.) (List.map to_box (make_tree f0)) (* let () = Metapost.emit "f0" (Box.draw(draw1 f0)) *) let gray f = Array.fill bits 0 100 White; let boxes = ref [] in let k () = boxes := draw1 f :: !boxes in enum_forest k f; hbox ~padding:(bp 10.) (List.rev !boxes) let box_arrow = Helpers.box_arrow ~sep:(bp 10.) let smart_box_arrow ol a b = let p = smart_path ~style:jLine ol (ctr a) (ctr b) in let p = cut_after (bpath b) (cut_before (bpath a) p) in let p = strip (bp 10.) p in Arrow.simple p let gray_grid w f = Array.fill bits 0 100 White; let boxes = ref [[]] in let k () = let b = draw1 f in match !boxes with | l :: _ when List.length l = w -> boxes := [b] :: !boxes | l :: r -> boxes := (b :: l) :: r | [] -> assert false in enum_forest k f; let rec reverse = function | [] -> [] | [x] -> [List.rev x] | x :: y :: l -> List.rev x :: y :: reverse l in let boxes = reverse (List.rev !boxes) in let h = List.length boxes in let b = gridl ~hpadding:(bp 20.) ~vpadding:(bp 10.) ~stroke:None boxes in let sub i j = nth j (nth i b) in Box.draw b ++ iter 0 (h-1) (fun i -> iter 0 (w-2) (fun j -> if i mod 2 = 0 then box_arrow (sub i j) (sub i (j+1)) else box_arrow (sub i (j+1)) (sub i j) )) ++ iter 0 (h-2) (fun i -> if i mod 2 = 0 then smart_box_arrow [Rightn (bp 25.); Down; Left] (sub i (w-1)) (sub (i+1) (w-1)) else smart_box_arrow [Leftn (bp 25.); Down; Right] (sub i 0) (sub (i+1) 0) ) let _ = List.iter (fun (name,fig) -> Metapost.emit name fig) [ "archi_backend", archi_backend; "fibtree", fibtree; "hist", hist; "diag", diag; "gray_f0", gray_grid 5 f0; (* "tree10", tree10; *) ] mlpost-0.8.2/presentations/workshop-ml-2009/mlpost-wml.tex000066400000000000000000000037721306046515300234600ustar00rootroot00000000000000\documentclass{article} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{graphicx} \usepackage{url} \newcommand{\mlpost}{Mlpost} \newcommand{\ocaml}{Ocaml} \newcommand{\metapost}{Metapost} \newcommand{\tikz}{TikZ} \title{Mlpost - A scientific drawing library} \date{} \author{Romain Bardou ~\hfill~ François Bobot \\ Jean-Christophe Filliâtre ~\hfill~ Johannes Kanig \\ Stéphane Lescuyer} \begin{document} \maketitle We present \mlpost, an \ocaml\ library for drawing diagrams. Because of the possibility to include arbitrary \LaTeX\ text in figures and the resulting figure in \LaTeX\ documents, we believe it is particularly suited for the scientific community and ML programmers. Unlike other tools with similar features and scope, like \metapost\ or \tikz, \mlpost\ is {\em not} a stand-alone language, but a library for the modern \ocaml\ programming language. This greatly eases the construction of figures resulting from a computation or figures which are intended to illustrate the run of an algorithm. Initially based on the \metapost\ tool to do the actual computations, treatment of \LaTeX\ snippets and drawing, \mlpost\ has grown into a full-blown implementation of Bézier curves and interprets results of \LaTeX\ runs by itself, using the {\tt Cairo} library to draw objects. It supports output in PDF, Postscript, SVG, and even to X11 windows. Mlpost is freely distributed at \url{http://mlpost.lri.fr}. %TODO decide what we want to show The demo, if accepted, will show many examples from lectures, PhD theses, articles, talks, etc. In particular, it will focus on figures which illustrate the run of an algorithm. It will also show the basic principles of the \mlpost\ library. %TODO references \subsection*{Contact Information} %TODO more contact information? someone else? Johannes Kanig\\ INRIA Saclay Île de France - ProVal\\ Parc Club Orsay Université, bâtiment N\\ 4 rue Jacques Monod\\ F-91893 Orsay cedex France\\ Tel.: (+33) (0)1 72 92 59 79\\ johannes.kanig@lri.fr \end{document} mlpost-0.8.2/presentations/workshop-ml-2009/slides.tex000066400000000000000000000127141306046515300226240ustar00rootroot00000000000000% -*- coding : utf8 -*- %; whizzy -pdf \documentclass[nodefaultblocks]{beamer} \usepackage{beamerthemesplit} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{lmodern} \usepackage{graphicx} \usepackage{pgf,pgfarrows,pgfnodes} \usepackage{tikz} \usepackage{alltt} %\usetikzlibrary{shapes} %\usetikzlibrary{arrows,snakes,backgrounds} %\usepackage{xy} %\xyoption{all} \newcommand{\ocaml}{OCaml} \newcommand{\metapost}{Metapost} \def \ybox #1{{\mbox { \strut #1}}} \usetheme{Madrid} \beamertemplatenavigationsymbolsempty \date{August 30, 2009} \definecolor{yel}{rgb}{.9,.8,.4} \definecolor{mygray}{rgb}{0.85,0.85,0.85} \def \ebox #1{\colorbox{yel}{\mbox {\strut #1}}} \def \gbox #1{\colorbox{mygray}{\mbox {\strut #1}}} \def \goldbox #1{\colorbox{mygold}{\mbox {\strut #1}}} \def \magbox #1{\colorbox{mymagenta}{\mbox {\strut #1}}} \definecolor{mymagenta}{rgb}{1,0,1} \definecolor{mygold}{rgb}{1,.7,0.1} \definecolor{darkgray}{gray}{0.5} \definecolor{mygreen}{rgb}{0,0.5,0} \definecolor{myblue}{rgb}{0.1,0.1,0.8} \definecolor{royalblue}{rgb}{0.282,0.463,1.0} \def \blue #1{{\color{myblue} #1}} \def \green #1{{\color{mygreen} #1}} \def \red #1{{\color{red} #1}} \def \gray #1{{\color{darkgray} #1}} \def \toto{\only<-2>{white}\only<3->{black}} \newcommand{\colornodeboxstroke}[4]{% {\color{#1}\pgfnodebox{#2}[fill]{#3}{#4}{3pt}{3pt}}% \pgfnodebox{#2}[stroke]{#3}{#4}{3pt}{3pt}} \newcommand{\colornodebox}[4]{% {\color{#1}\pgfnodebox{#2}[fill]{#3}{#4}{2pt}{2pt}}% \pgfnodebox{#2}[virtual]{#3}{#4}{2pt}{2pt}} \newcommand{\fleche}[3]{% \begin{pgfscope}\pgfsetlinewidth{1.2pt}% \pgfsetendarrow{\pgfarrowtriangle{3pt}}% {\color{#1}\pgfnodeconnline{#2}{#3}}\end{pgfscope}} \definecolor{lred}{rgb}{1,0.8,0.6} \definecolor{lightgray}{rgb}{0.7,0.7,0.7} \definecolor{lightgreen}{rgb}{0.6,1,0.8} \definecolor{darkgreen}{rgb}{0,0.6,0} \definecolor{royalblue}{rgb}{0.25,0.41,0.88} \title{Mlpost - A scientific drawing library} \author[Bardou,\hspace{0.05em} Bobot, \hspace{0.05em} Filliâtre, \hspace{0.05em} Kanig, \hspace{0.05em} Lescuyer]{ Romain Bardou, François Bobot, Jean-Christophe Filliâtre \\ \alert{Johannes Kanig}, Stéphane Lescuyer} \institute[]{LRI, Proval INRIA Saclay - Île-de-France} \begin{document} \begin{frame} \maketitle \end{frame} \begin{frame}[fragile]\frametitle{Motivation} how to make nice pictures \begin{itemize} \item with embedded \LaTeX\ snippets \item scripted in a nice language \item possibly resulting from computations \end{itemize} \begin{overprint} \onslide<+> \begin{center} \bigskip \includegraphics{fibtree.pdf} \end{center} \onslide<+> \medskip \begin{center} \medskip \begin{alltt} open \alert{Mlpost} let texint n = tex (sprintf "$F_\{%d\}$" n) let rec fib = function | 0 | 1 as n -> leaf (texint n) | n -> node (texint n) [fib (n-1); fib (n-2)] let fibtree = draw (fib 6) \end{alltt} \end{center} \onslide<+> \medskip Alternatives: \begin{itemize} \item dia, xfig \item PGF/Tikz \item Metapost \item functional metapost \end{itemize} \end{overprint} \end{frame} \begin{frame}{Our contribution : Mlpost = \ocaml\ + \metapost} \begin{columns} \column{0.5\textwidth} A stub of basic \metapost\ features \begin{itemize} \item embedded \LaTeX\ snippets \item Bézier paths \end{itemize} \column{0.5\textwidth} \includegraphics[width=\textwidth]{../../papers/jfla2009/architecture.mps} \end{columns} \bigskip Additional features \begin{itemize} \item High-level libraries: boxes, trees, diagrams, radars, function plots \item persistence (allows sharing) \item uses optional/labeled arguments massively \end{itemize} \end{frame} \begin{frame} \frametitle{Two backends} \begin{center} \includegraphics{archi_backend} \end{center} \end{frame} \begin{frame} \frametitle{Example 1: for a math lecture} \begin{center} \includegraphics[width=0.6\textwidth]{../../papers/jfla2009/ford.mps} \end{center} \end{frame} \begin{frame}[fragile] \frametitle{Example 2: The histogram library} \begin{columns} \column{0.6\textwidth} \begin{verbatim} Hist.stack ~fill:[lightred;lightblue; lightyellow;lightgreen] [[4.;5.;5.;]; [8.;3.;1.]; [2.;8.;1.;4.]] \end{verbatim} \column{0.4\textwidth} \begin{center} \includegraphics{hist} \end{center} \end{columns} \end{frame} \begin{frame}[fragile] \frametitle{Example 3: Easy diagrams using boxes} \begin{columns} \column{0.75\textwidth} \small \begin{verbatim} let diag = let rt s = rect (tex s) in let a = rt "A" and b = rt "B" and c = rt "C" in let ab = round_rect (hbox [a;b]) in let v = vbox [ab;c] in let arrow x y = box_arrow (sub x v) (sub y v) in draw v ++ arrow a b ++ arrow ab c \end{verbatim} \column{0.25\textwidth} \includegraphics{diag} \end{columns} \end{frame} \begin{frame} \frametitle{Example 4: From a previous talk} \begin{center} \includegraphics[width=\textwidth]{gray_f0} \end{center} \end{frame} \begin{frame} \frametitle{Example 5: from a PhD thesis} \includegraphics[width=0.6\textwidth]{../../papers/jfla2009/figures_flo/chrono2_1.mps} \includegraphics[width=0.4\textwidth]{../../papers/jfla2009/figures_flo/automate_jfla.mps} \end{frame} \begin{frame}\frametitle{Conclusion} Mlpost is freely distributed at \begin{center} \url{http://mlpost.lri.fr} \end{center} There is a debian package (currently in \tt{testing}) \end{frame} \end{document} mlpost-0.8.2/print.ml000066400000000000000000000127311306046515300145340ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* print an mlpost AST for debugging *) open Concrete_types open Types open Format let option_print pr fmt = function | None -> () | Some x -> pr fmt x let position fmt p = match pos_reduce p with | `Center -> fprintf fmt "" | `West -> fprintf fmt ".lft" | `East -> fprintf fmt ".rt" | `North -> fprintf fmt ".top" | `South -> fprintf fmt ".bot" | `Northwest -> fprintf fmt ".ulft" | `Northeast -> fprintf fmt ".urt" | `Southwest -> fprintf fmt ".llft" | `Southeast -> fprintf fmt ".lrt" let rec num fmt f = pp_print_float fmt f and point fmt { Point_lib.x = x ; y = y } = fprintf fmt "(%a,%a)" num x num y and picture fmt p = match p.Hashcons.node with | PITex s -> fprintf fmt "tex(%s)" s | PITransformed (p,tr) -> fprintf fmt "%a transformed %a" commandpic p transform tr | PIClip _ -> () and transform fmt t = Misc.print_list Misc.comma Matrix.print fmt t and knot fmt k = match k.Hashcons.node with | { knot_in = d1 ; knot_p = p ; knot_out = d2 } -> fprintf fmt "%a%a%a" direction d1 point p direction d2 and direction fmt d = match d.Hashcons.node with | Vec p -> fprintf fmt "{%a}" point p | Curl f -> fprintf fmt "{curl %f}" f | NoDir -> () and metapath fmt p = match p.Hashcons.node with | MPAConcat (k,j,p) -> fprintf fmt "%a%a%a" metapath p joint j knot k | MPAAppend (p1,j,p2) -> fprintf fmt "%a%a%a" metapath p1 joint j metapath p2 | MPAKnot k -> knot fmt k | MPAofPA p -> fprintf fmt "(%a)" path p and path fmt p = match p.Hashcons.node with | PAofMPA p -> fprintf fmt "(from_metapath %a)" metapath p | MPACycle (d,j,p) -> fprintf fmt "(cycle of %a with %a)" metapath p joint j | PATransformed (p,tr) -> fprintf fmt "(tr %a by %a)" path p transform tr | PACutAfter (p1,p2) -> fprintf fmt "(cutafter %a by %a)" path p1 path p2 | PACutBefore (p1,p2) -> fprintf fmt "(cutbefore %a by %a)" path p1 path p2 | PABuildCycle pl -> fprintf fmt "(buildcycle %a)" (Misc.print_list Misc.semicolon path) pl | PASub (f1, f2, p) -> fprintf fmt "(sub %a from %a to %a)" path p num f1 num f2 | PABBox p -> fprintf fmt "(bbox %a)" commandpic p | PAUnitSquare -> fprintf fmt "unitsquare" | PAQuarterCircle -> fprintf fmt "quartercircle" | PAHalfCircle -> fprintf fmt "halfcircle" | PAFullCircle -> fprintf fmt "fullcircle" and joint fmt j = match j.Hashcons.node with | JLine -> fprintf fmt "--" | JCurve -> fprintf fmt ".." | JCurveNoInflex -> fprintf fmt "..." | JTension (a,b) -> fprintf fmt "..tension(%f,%f).." a b | JControls (p1,p2) -> fprintf fmt "..%a..%a.." point p1 point p2 and command fmt c = match c.Hashcons.node with | CDraw (p,b) -> let {color = c; pen = pe; dash = d} = b.Hashcons.node in fprintf fmt "draw (%a,%a,%a,%a);" path p option_color c option_pen pe option_dash d | CFill (p,c) -> fprintf fmt "fill (%a,%a);" path p option_color c | CLabel (pic,pos,pt) -> fprintf fmt "label%a(%a,%a)" position pos commandpic pic point pt | CDotLabel (pic,pos,pt) -> fprintf fmt "dotlabel%a(%a,%a)" position pos commandpic pic point pt | CExternalImage (f,spec) -> fprintf fmt "externalimage %s@ " f and color fmt (c:Types.color) = let mode,color = match c with | OPAQUE c -> (None, c) | TRANSPARENT (f,c) -> (Some f, c) in let pmode fmt = function | None -> fprintf fmt "O" | Some f -> fprintf fmt "%f" f in match color with | RGB (r,g,b) -> fprintf fmt "(%f, %f , %f, %a)" r g b pmode mode | CMYK (c,m,y,k) -> fprintf fmt "(%f, %f, %f, %f, %a)" c m y k pmode mode | Gray f -> fprintf fmt "(%f * white, %a)" f pmode mode and commandpic fmt c = match c.Hashcons.node with | Picture p -> picture fmt p | Command c -> command fmt c | Seq l -> Misc.print_list Misc.space commandpic fmt l and pen fmt x = match x.Hashcons.node with | PenCircle -> fprintf fmt "PenCircle" | PenSquare -> assert false | PenFromPath p -> assert false | PenTransformed (p,trl) -> fprintf fmt "(%a,%a)" pen p transform trl and dash fmt x = match x.Hashcons.node with | DEvenly -> fprintf fmt "evenly" | DWithdots -> assert false | DScaled (f,d) -> fprintf fmt "%a scaled %a" dash d num f | DShifted (p,d) -> assert false | DPattern l -> assert false and option_pen fmt = option_print pen fmt and option_color fmt = option_print color fmt and option_dash fmt = option_print dash fmt mlpost-0.8.2/radar.ml000066400000000000000000000203501306046515300144650ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Command open Path open Num open Color open Types open Infix (* Module implmentant une file avec deux listes *) module Q = Misc.Q let scale_radius r l= List.map (fun (x,y) -> (multf x r,multf y r)) l let scale_radius_2 r l = List.map (scale_radius r) l (* Calcule la liste des max des ime lments de chaque liste *) let maxlist =function |ml::ll-> List.fold_left (List.map2 max) ml ll |[]-> failwith "Empty list" type direction = Horizontal | Vertical | Other (* Calcule les 2 points distance d de la droite de coefficient directeur a2_equ perpendiculaire l'axe de tc *) let rec make_paths a2_equ tc d sens acc radius = match tc with |(absc,ordo)::res -> let (absc,ordo) = (multf absc radius,multf ordo radius) in begin match sens with | Vertical -> (* Le long de l'axe des ordonnes *) let absc2 = (+/) absc d in let absc3 = (-/) absc d in make_paths a2_equ res d sens ([(absc2,ordo);(absc3,ordo)]::acc) radius | Horizontal -> (* Le long de l'axe des abscisses *) let ordo2 = (+/) ordo d in let ordo3 = (-/) ordo d in make_paths a2_equ res d sens ([(absc,ordo2);(absc,ordo3)]::acc) radius | Other -> let b2_equ = (-/) ordo (( *./) a2_equ absc) in let co = 1. /. (sqrt (1.+.a2_equ*.a2_equ)) in let angle = if a2_equ>0. then 360 - (int_of_float ((acos co)*.180./.pi)) else int_of_float (acos(co)*.180./.pi) in let absc2 = (+/) absc (( *./) (cos ((float angle)*.2.*.pi/.360.)) d) in let ordo2 = (+/) (( *./) a2_equ absc2) b2_equ in let angle2 = (angle+180) mod 360 in let absc3 = (+/) absc (( *./) (cos ((float angle2)*.2.*.pi/.360.)) d) in let ordo3 = (+/) (( *./) a2_equ absc3) b2_equ in make_paths a2_equ res d sens ([(absc2,ordo2);(absc3,ordo3)]::acc) radius end |[]-> acc (* Dessine les ticks le long de l'axe pass en paramtre *) let draw_ticks ticks coords m d radius= let (x,y) = List.hd (List.rev coords) in let rec ticks_coords acc ticks i x y m = if i<=m then ticks_coords ((x*.i/.m,y*.i/.m)::acc) ticks (i+.ticks) x y m else acc in let tc = ticks_coords [] ticks ticks x y m in let x = if (abs_float x < 10e-4) then 0. else x in let y = if (abs_float y < 10e-4) then 0. else y in let a2_equ,sens = if x=0. then 0.,Vertical else if y=0. then 0.,Horizontal else ((-.x)/.y),Other in let p = make_paths a2_equ tc d sens [] radius in iterl (fun x -> draw (pathn x)) p (* *) let draw_label pt lab radius = let (x,y) = List.hd (List.rev pt) in let angl = (acos (x /. (sqrt (x*.x +. y*.y))))*.180./.pi in let angle = if y<0. then 360.-.angl else angl in let placement = if ((angle>315. && angle<360.) || (angle>=0. && angle<=45.)) then `East else if (angle>45. && angle<=135.) then `North else if (angle>135. && angle<=225.) then `West else `South in Command.label ~pos:placement (Picture.tex lab) (Point.pt (multf x radius, multf y radius)) (* Dessine le radar vide *) let rec draw_skeleton acc ?label ticks lmax skltn d radius= let label = match label with |None -> [] |Some i -> i in match skltn,lmax,label with |x::res,m::lm,lab::labl -> let x2= scale_radius radius x in draw_skeleton ((draw (pathn x2)) ++(draw_ticks ticks x m d radius) ++(draw_label x lab radius)++acc) ~label:labl ticks lm res d radius |x::res,m::lm,[] -> let x2= scale_radius radius x in draw_skeleton ((draw (pathn x2)) ++(draw_ticks ticks x m d radius)++acc) ~label:[] ticks lm res d radius |[],[],[] -> acc |_,_,_-> failwith "Different list sizes" (* Fabrique une liste contenant les coordonnes des axes du radar *) let empty_radar_coords nbr = let delta = 360. /. (float nbr) in let rec empty_radar acc nb diff angle = if nb>0 then empty_radar ([(0.,0.);(cos (angle*.2.*.pi/.360.), sin (angle*.2.*.pi/.360.) )]::acc) (nb-1) diff (angle+.diff) else List.rev acc in empty_radar [] nbr delta 0. (* Fabrique la liste des coordonnes correspondant chaque valeur *) let list_coord lmax l skeleton = let rec fct lmax l skeleton acc = match lmax,l,skeleton with |x::res,y::res2,z::res3 -> let (z1,z2) = List.hd (List.rev z) in let x_coord = z1*.y/.x in let y_coord = z2*.y/.x in fct res res2 res3 ((x_coord,y_coord)::acc) |[],[],[] -> List.rev acc |_,_,_ -> failwith "Different list sizes" in fct lmax l skeleton [] (* Fabrique un radar associ au squelette de radar pass en paramtre *) let radar color lmax l skeleton pen fill stl radius = let coords = scale_radius radius (list_coord lmax l skeleton) in let rec dots acc f c = match c with |x::res -> let col = if f then Color.black else color in let cmd = draw ~pen:(Pen.scale (bp 3.) pen) ~color:col (pathn [x]) in dots (cmd++acc) f res |[]->acc in let dots_cmd = dots nop fill coords in let clr = if fill then Color.black else color in let path_cmd = draw (pathn ~style:jLine ~cycle:jLine coords) ~pen ~color:clr ~dashed:stl in let path_filled = if fill then (Command.fill ~color:color (pathn ~style:jLine ~cycle:jLine coords)) else nop in path_filled++path_cmd++dots_cmd let default_radius = bp (100.) let default_style = [(Dash.pattern [Dash.on (bp 1.);Dash.off (bp 0.)])] let default_pen = Pen.scale (bp 0.5) Pen.circle let init radius ?scale l= let ticks_size = divf (multf 3. radius) 100. in let lesmax = match scale with |None -> maxlist l |Some l -> l in let skeleton = match l with |x::_ -> empty_radar_coords (List.length x) |[] -> failwith "No data" in ticks_size,lesmax,skeleton (* Fabrique des radars empils *) let stack ?(radius=default_radius) ?(color=[black]) ?(pen=default_pen) ?(style=default_style) ?(ticks=1.) ?label ?scale l = let ticks_size,lesmax,skeleton = init radius ?scale l in let rec radar_list col stl maxi li skltn acc = match li,col,stl with |x::res,cq,sq -> let c,cres = Q.pop cq in let s,sres = Q.pop sq in radar_list (Q.push c cres) (Q.push s sres) maxi res skltn ((radar c maxi x skltn pen false s radius)++acc) |[],cq,sq-> acc in Picture.make ((draw_skeleton nop ?label ticks lesmax skeleton ticks_size radius) ++(radar_list (Q.of_list color) (Q.of_list style) lesmax l skeleton nop)) (* Fabrique des radars comparatifs, renvoie la liste de Pictures reprsentant chaque radar *) let compare ?(radius=default_radius) ?(color=[black]) ?(fill=false) ?(pen=default_pen) ?(style=default_style) ?(ticks=1.) ?label ?scale l = let ticks_size,lesmax,skeleton = init radius ?scale l in let rec build_pictures skltn col stl maxi li tcks acc = match li,col,stl with |x::res,cq,sq -> let c,cres = Q.pop cq in let s,sres = Q.pop sq in let r = radar c maxi x skltn pen fill s radius in let sk = draw_skeleton nop ?label tcks maxi skltn ticks_size radius in let pic = Picture.make (r++sk) in build_pictures skltn (Q.push c cres) (Q.push s sres) maxi res tcks (pic::acc) |[],cq,sq-> List.rev acc in build_pictures skeleton (Q.of_list color) (Q.of_list style) lesmax l ticks [] mlpost-0.8.2/real_plot.ml000066400000000000000000000201521306046515300153550ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module C = Command module P = Picture type ('a,'b) node = { values : 'b; node : 'a} type 'a curve = ('a,(float -> float option) list) node type 'a graph = 'a curve list let curve_l fl node = { values = fl; node = node} let curve_opt f node = curve_l [f] node let curve f node = curve_opt (fun x -> Some (f x)) node let graph x = x let rec calc_one_value nb_f ((which_f,acc) as w_acc) x = function | [] -> (nb_f,None::acc) | f::lf -> match f x with | None -> calc_one_value (nb_f+1) w_acc x lf | Some y -> if which_f = nb_f then (nb_f,Some (x,y)::acc) else (nb_f,Some (x,y)::None::acc) let calc xmin xmax pitch {values=cf;node=node} = let rec aux acc = function | x when x<=xmin -> calc_one_value 0 acc xmin cf | x -> aux (calc_one_value 0 acc x cf) (x-.pitch) in {values=snd (aux (0,[]) xmax);node=node} open MetaPath let cons_opt x l = match x with None -> l | Some x -> (to_path x)::l let rec pathn_opt acc current = function | [] -> cons_opt current acc | v::l -> match v,current with | None, _ -> pathn_opt (cons_opt current acc) None l | Some v, None -> pathn_opt acc (Some (start (knotn v))) l | Some v, Some c -> pathn_opt acc (Some (concat ~style:jLine c (knotn v))) l let draw_aux ?label values = C.seq ( List.map (fun (values,brush) -> let line = pathn_opt [] None values in C.seq (List.map (Path.draw ~brush) line)) values) open Num let ysep = 10 let rec tick pitch xmax nb = let rec aux acc x = function | n when n <= 0 -> acc | n -> aux (x::acc) (x-.pitch) (n-1) in aux [] xmax nb let rec tick_log xmax = let rec aux acc = function | x when x > xmax -> acc | x -> aux (x::acc) (x*.10.) in aux [] 1. let rec tick_logneg xmin = let rec aux acc = function | x when x < xmin -> acc | x -> aux (x::acc) (x*.10.) in aux [] (-.1.) let vtick = let t = Point.bpp (2.5,0.) in fun v -> (Point.sub v t, Point.add v t) let draw_axes ~logarithmic ~ytick ~xmin ~xmax ~ymin ~ymax ~yzero ~xzero ~pitch = let ytick = C.seq ytick in let vert = Arrow.simple (Path.pathn ~style:Path.jLine [xzero,ymin;xzero,ymax]) in let hori = Arrow.simple (Path.pathn ~style:Path.jLine [xmin,yzero;xmax,yzero]) in C.seq [ytick;vert;hori] let count_max iter = let y = ref neg_infinity in iter (fun x -> y := max !y x); !y let count_min iter = let y = ref infinity in iter (fun x -> y := min !y x); !y let filter_opt f l = {l with values = List.map (function | Some (x,y) as p when f y -> p | _ -> None) l.values} let draw ?(logarithmic=false) ?curve_brush ?label ?ymin ?ymax ~xmin ~xmax ~pitch ~width ~height graph = let values = List.map (calc xmin xmax pitch) graph in (* ymin, ymax calculation *) let values = match ymin,ymax with | None,None -> values | _ -> let f = match ymin,ymax with | None,None -> assert false | Some ymin, None -> (fun f -> f >= ymin) | Some ymin, Some ymax -> (fun f -> f >= ymin && f <= ymax) | None, Some ymax -> (fun f -> f <= ymax) in List.map (filter_opt f) values in let yvalues = (fun f -> List.iter (fun x -> List.iter (function Some (_,y) -> f y| None -> ()) x.values) values) in let ymax = match ymax with None -> count_max yvalues | Some ymax -> ymax in (*let ymax = if ymax = 0. then 1. else ymax in *) let ymin = match ymin with None -> count_min yvalues | Some ymin -> ymin in (*let ymin = if ymin = 0. then -.1. else ymin in *) let ymax = if ymin=ymax then ymin +. 1. else ymax in (* scale *) let conv = if logarithmic then fun v -> if abs_float v < 1. then v else ((log10 (abs_float v)) +. 1.) *. (v/.(abs_float v)) else fun v -> v in let scaley = Num.divn height (Num.bp ((conv ymax)-. (conv ymin))) in let scalex = Num.divn width (Num.bp (xmax-.xmin)) in let scalex x = Num.multn (Num.bp (x-.xmin)) scalex in let scaley y = Num.multn (Num.bp ((conv y)-.(conv ymin))) scaley in let scale (x,y) = scalex x,scaley y in let scale_opt = function | Some (x,y) -> Some (scale (x,y)) | None -> None in let xzero,yzero = scale (0.,0.) in (* tick vertical *) let ymm = ymax -. ymin in (*let xmm = xmax -. xmin in*) let ypitchl = if logarithmic then let l1 = tick_log ymax in let l2 = tick_logneg ymin in l1@l2 else let ypitch = 10.**(floor (log10 (ymm/.(float ysep)))) in let ymax2 = ypitch *. (floor (ymax/.ypitch)) in let ysep = int_of_float (ymm/.ypitch) in tick ypitch ymax2 ysep in let ypitchl = ymin::ypitchl@[ymax] in (* Remove the tick which are too close but we need concrete for that... Currently only for ex, but we can be more precise *) let ypitchl = if not Concrete.supported then List.map (fun y -> (y,scaley y)) ypitchl else let ex2 = 2. *. Num.ex_factor () in let _, ypitchl = List.fold_left (fun (last,acc) y -> let yn = scaley y in let f = Concrete.float_of_num yn in if abs_float (last -. f) > ex2 then (f,(y,yn)::acc) else (last,acc)) (infinity,[]) ypitchl in ypitchl in let zero = scalex 0. in let ytick = List.map (fun (y,yn) -> let p = Point.pt (zero,yn) in let (p1,p2) = (vtick p) in let label = Format.sprintf "{%2.1f}" y in C.seq [ C.label ~pos:`West (Picture.tex label) p1; Path.draw (Path.pathp ~style:Path.jLine [p1;p2])]) ypitchl in (* values *) let values = List.map (fun x -> {x with values = List.map scale_opt x.values} ) values in (* Brush and legend *) let color = Color.color_gen 1. 1. in let curve_brush _ = Brush.t () in let colors = List.map (fun x -> let b = curve_brush x.node in let b,c = match Brush.color b with | Some c -> b,c | None -> let c = color () in Brush.t ~color:c ~brush:b (),c in (b,c,x)) values in let legend = match label with | None -> C.nop | Some label -> let legend = Legend.legend (List.map (fun (_,c,x) -> (c,label x.node)) colors) in C.label ~pos:`East legend (Point.pt (scale (xmax,(ymax+.ymin)/.2.))) in let values = List.map (fun (b,_,x) -> (x.values,b)) colors in let xmin,ymin = scale (xmin,ymin) in let xmax,ymax = scale (xmax,ymax) in let axes = draw_axes ~logarithmic ~ytick ~xmin ~xmax ~ymin ~ymax ~yzero ~xzero ~pitch in C.seq [axes; draw_aux ?label values; legend] mlpost-0.8.2/scan_prelude.mll000066400000000000000000000030531306046515300162150ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) { open Lexing let buffer = Buffer.create 1024 } (* scan the main LaTeX file to extract its prelude *) rule scan = parse | "\\%" as s { Buffer.add_string buffer s; scan lexbuf } | "%" [^'\n']* '\n' { Buffer.add_char buffer '\n'; scan lexbuf } | _ as c { Buffer.add_char buffer c; scan lexbuf } | "\\begin{document}" { Buffer.contents buffer } | eof { Buffer.contents buffer } mlpost-0.8.2/shapes.ml000066400000000000000000000126251306046515300146650ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Command open Num open Point open Path open Num.Infix open Types let pi = Num.pi let kappa = 4. *. (sqrt 2. -. 1.) /. 3. let mkappa = 1. -. (4. *. (sqrt 2. -. 1.) /. 3.) type t = Path.t (** Rectangles *) let round_rect width height rx ry = let hw,hh = width/./ 2.,height/./ 2. in let rx = maxn zero (minn rx hw) in let ry = maxn zero (minn ry hh) in (* let ul, ur, br, bl = *) (* pt (-.hw, hh), pt (hw, hh), *) (* pt (hw, -.hh), pt (-.hw, -.hh) in *) let ul1, ul2 = pt (neg hw, hh-/(mkappa*/ry)), pt (mkappa*/rx-/hw, hh) in let ur1, ur2 = pt (hw-/mkappa*/rx, hh), pt (hw, hh-/mkappa*/ry) in let br1, br2 = pt (hw, mkappa*/ry-/hh), pt (hw-/mkappa*/rx, neg hh) in let bl1, bl2 = pt (mkappa*/rx-/hw, neg hh), pt (neg hw, mkappa*/ry-/hh) in let knots = knotlist [(noDir, pt (rx-/hw, hh), mkVec right); (noDir, pt (hw-/rx, hh), mkVec right); (noDir, pt (hw, hh-/ry), mkVec down); (noDir, pt (hw, ry-/hh), mkVec down); (noDir, pt (hw-/rx, neg hh), mkVec left); (noDir, pt (rx-/hw, neg hh), mkVec left); (noDir, pt (neg hw, ry-/hh), mkVec up); (noDir, pt (neg hw, hh-/ry), mkVec up)] in let joints = [jLine; mkJControls ur1 ur2; jLine; mkJControls br1 br2; jLine; mkJControls bl1 bl2; jLine] in cycle ~dir:(mkVec right) ~style:(mkJControls ul1 ul2) (jointpathk knots joints) (** Ellipses and Arcs *) let ellipse rx ry = let m theta = pt (rx */ (cos theta), ry */ (sin theta)) in let knots = knotlist [(noDir, m 0., mkVec up); (noDir, m (pi /. 2.), mkVec left); (noDir, m pi, mkVec down); (noDir, m (-. pi /. 2.), mkVec right)] in let r1, r2 = pt (rx, neg (ry*/kappa)), pt (rx, ry*/kappa) in let t1, t2 = pt (rx*/kappa , ry), pt (neg (rx*/kappa), ry) in let l1, l2 = pt (neg rx, ry*/kappa), pt (neg rx, neg (ry*/kappa)) in let b1, b2 = pt (neg (rx*/kappa), neg ry), pt (rx*/kappa, neg ry) in let joints = [mkJControls r2 t1; mkJControls t2 l1; mkJControls l2 b1] in cycle ~dir:(mkVec up) ~style:(mkJControls b2 r1) (jointpathk knots joints) let round_box width height = let w = width /./ 2. and h = height /./ 2. in let mw = neg w and mh = neg h in let dx = h /./ 5. and dy = h /./ 5. in let style = jCurveNoInflex in Path.pathn ~cycle:style ~style [ mw -/ dx, zero; zero, mh -/ dy; w +/ dx, zero; zero, h +/ dy;] (* let arc_ellipse_path ?(close=false) rx ry theta1 theta2 = let curvabs theta = (2. *. theta) /. pi in let path = subpath (curvabs theta1) (curvabs theta2) (full_ellipse_path rx ry) in if close then cycle ~style:JLine (concat ~style:JLine path (NoDir,origin,NoDir)) else path *) let rectangle width height = let w = width /./ 2. in let h = height /./ 2. in let mw = neg w in let mh = neg h in Path.pathn ~cycle:jLine ~style:jLine [ w, mh; w, h; mw, h; mw, mh] let patatoid width height = let wmin,wmax = -0.5 *./ width, 0.5 *./ width in let hmin,hmax = -0.5 *./ height, 0.5 *./ height in let ll = pt (wmin,hmin) in let lr = pt (wmax,hmin) in let ur = pt (wmax,hmax) in let ul = pt (wmin, hmax) in let a = segment (Random.float 1.) ll lr in let b = segment (Random.float 1.) lr ur in let c = segment (Random.float 1.) ur ul in let d = segment (Random.float 1.) ul ll in pathp ~cycle:jCurve [a;b;c;d] let patatoid2 width height = let wmin,wmax = -0.5 *./ width, 0.5 *./ width in let hmin,hmax = -0.5 *./ height, 0.5 *./ height in let ll = pt (wmin,hmin) in let lr = pt (wmax,hmin) in let ur = pt (wmax,hmax) in let ul = pt (wmin, hmax) in let f cl cr x y p = let d = pt (bp x, bp y) in let r = Point.rotate (Random.float 60. -. 30.) d in let l = Point.sub Point.origin r in let r = Point.scale ((Random.float 1. +. 0.5) *./ cl) r in let l = Point.scale ((Random.float 1. +. 0.5) *./ cr) l in (Point.shift p l, Point.shift p r) in let c = 0.25 in let ch = c *./ width in let cv = c *./ height in let l1, r1 = f ch cv 1. 1. ul in let l2, r2 = f cv ch 1. (-1.) ur in let l3, r3 = f ch cv (-1.) (-1.) lr in let l4, r4 = f cv ch (-1.) 1. ll in let path = jointpathp [ ul; ur; lr; ll; ] [ jControls r1 l2; jControls r2 l3; jControls r3 l4; ] in cycle ~style: (jControls r4 l1) path let circle d = Path.scale d Path.fullcircle mlpost-0.8.2/signature.ml000066400000000000000000000024301306046515300153740ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type point = Types.point module type Boxlike = sig type t val width : t -> float val height : t -> float val set_pos : point -> t -> t end mlpost-0.8.2/test/000077500000000000000000000000001306046515300140215ustar00rootroot00000000000000mlpost-0.8.2/test/.gitignore000066400000000000000000000000611306046515300160060ustar00rootroot00000000000000*.mps *.log *.mpx *.[0-9]* *.aux *.tex *.mp *.ps mlpost-0.8.2/test/Makefile000066400000000000000000000012071306046515300154610ustar00rootroot00000000000000manual: testmanual.pdf testmanual.pdf: testmanual.tex #mpost testmanual.mp end make -C manual mps pdflatex testmanual.tex #dvips testmanual.dvi -o testmanual.ps other: othergraphs.tex #mpost othergraphs.mp end make -C othergraphs mps pdflatex othergraphs.tex #dvips othergraphs.dvi -o othergraphs.ps tests: tests.dvi dvips tests.dvi -o tests.ps testbox: testbox.dvi dvips testbox.dvi -o testbox.ps %.dvi: %.mp mpost $*.mp end latex $* tests.pdf: tests.dvi dvipdf tests.dvi clean: make -C manual clean make -C othergraphs clean rm -f testmanual.* rm -f testmanual_cairo-*.* rm -f tests.* *.mps *.pdf rm -f othergraphs.* mlpost-0.8.2/test/color.ml000066400000000000000000000006141306046515300154720ustar00rootroot00000000000000open Mlpost open Color open Path open Point open Picture let square c = shift (cmp (0.25,0.)) (Path.fill ~color:c (Path.scale (Num.cm 1.) Path.fullcircle)) let () = Metapost.emit "alpha" (Command.seq [rotate 90. (square (rgba 1. 0. 0. 0.5)); rotate 210. (square (rgba 0. 1. 0. 0.5)); rotate 330. (square (rgba 0. 0. 1. 0.5)); ]) mlpost-0.8.2/test/empty.ml000066400000000000000000000001101306046515300155010ustar00rootroot00000000000000let fig = Mlpost.Command.nop let () = Mlpost.Metapost.emit "empty" fig mlpost-0.8.2/test/externalimage/000077500000000000000000000000001306046515300166465ustar00rootroot00000000000000mlpost-0.8.2/test/externalimage/Makefile000066400000000000000000000005401306046515300203050ustar00rootroot00000000000000all : latex beamer latex: powered-by-caml.png images externalimage.tex pdflatex externalimage.tex beamer: powered-by-caml.png images externalimage_beamer.tex pdflatex externalimage_beamer.tex images : externalimage.ml ../../tool.opt -ccopt "-I ../../" -pdf externalimage.ml clean: rm -f *.pdf *.aux *.log *.mp *.mps *.1 *.nav *.out *.toc *.snm mlpost-0.8.2/test/externalimage/beamer_mlpost.sty000077700000000000000000000000001306046515300262532../../beamer_mlpost.styustar00rootroot00000000000000mlpost-0.8.2/test/externalimage/externalimage.ml000066400000000000000000000015751306046515300220350ustar00rootroot00000000000000open Mlpost let debug = false let filename = "powered-by-caml.png" let height = Num.cm 2. let width = Num.cm 1. let square = let rect = Shapes.rectangle width height in Command.draw (Path.shift (Point.scale (Num.bp 0.5) (Point.pt (width,height))) rect) let extim x = if debug then Command.nop else (Command.externalimage filename x) let image1 = Command.seq [square;extim (`Exact (height,width))] let image2 = Command.seq [square;extim (`Inside (height,width))] let image3 = Command.seq [square;extim (`Height height)] let image4 = Command.seq [square;extim (`Width width)] let _ = List.iter (fun (id,name,fig) -> Metapost.emit (name^id) fig; Metapost.emit (name^"_ro"^id) (Command.draw_pic (Picture.rotate 128. (Picture.make fig)))) [ "1","image", image1; "2","image", image2; "3","image", image3; "4","image", image4; ] mlpost-0.8.2/test/externalimage/externalimage.tex000066400000000000000000000016021306046515300222140ustar00rootroot00000000000000% -*- coding : utf8 -*- \documentclass{article} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage[french]{babel} \usepackage{lmodern} \usepackage{graphicx} %%%% % For externalimage : % specials.sty and supp-mpe_mod.tex % must be in the path \usepackage{specials} \LoadMetaPostSpecialExtensions %%%% \begin{document} \includegraphics[width=3cm]{image1} \includegraphics[width=3cm]{image2} \includegraphics[width=3cm]{image3} \includegraphics[width=3cm]{image4}\\ \includegraphics{image1} \includegraphics{image2} \includegraphics{image3} \includegraphics{image4}\\ \includegraphics[width=3cm]{image_ro1} \includegraphics[width=3cm]{image_ro2} \includegraphics[width=3cm]{image_ro3} \includegraphics[width=3cm]{image_ro4}\\ \includegraphics{image_ro1} \includegraphics{image_ro2} \includegraphics{image_ro3} \includegraphics{image_ro4}\\ \end{document} mlpost-0.8.2/test/externalimage/externalimage_beamer.tex000066400000000000000000000013411306046515300235270ustar00rootroot00000000000000% -*- coding : utf8 -*- \documentclass{beamer} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage[french]{babel} \usepackage{lmodern} \usepackage{graphicx} %%%% % For externalimage : % specials.sty and supp-mpe_mod.tex % must be in the path \usepackage{specials} \LoadMetaPostSpecialExtensions %%%% %%%% % For \includesomegraphics< > : % beamer_mlpost.sty must be in the path \usepackage{beamer_mlpost} %%%% \begin{document} \begin{frame} \includesomegraphics<1-4>[width=3cm]{image} \end{frame} \begin{frame} \includesomegraphics<1-4>{image} \end{frame} \begin{frame} \includesomegraphics<1-4>[width=3cm]{image_ro} \end{frame} \begin{frame} \includesomegraphics<1-4>{image_ro} \end{frame} \end{document} mlpost-0.8.2/test/externalimage/powered-by-caml.png000066400000000000000000000057631306046515300223560ustar00rootroot00000000000000PNG  IHDR:OPLTEffffggjjnnppssuuwwxxzz}}dd^^\\NNffeeddccbbaa``^^]]\\[[ZZYYWWVVUUTTSSRRNNKKJJIIHHFFFFDDDDCCAA4hhggbbPPe33KKy>>g55kkjjY..``a33mmZZWWeeooppUUrr@##tto>>mmhhvvMMwwyy||RR||ppՀ}KKփՂׇׅ҃׈؉ss؋kkٍَ·W::bb[[۔֑__ܗttݙN66ޛݚaaޝ̑ߟߠٜᤤhh㪪ڣ֠tt㬬Ĕ䯯ssrXX沲ff絵ګ緷ɠxxeRR龾ɨťxffʆssָèĻӭî˨՚⧛ȼcftRNSfYbKGD pHYsHHFk> vpAg:.wlIDATXř \U߬,88% ;+ ǒx殚E&%ᅊiVZfZixT~ӴPS)\;3gofނ؀\h`4k#-f,bQnX|mKt@w$D5<55 j&8D 'w 6Qjc+1E`dokިε;έp&zqv{/H! 9X [Ih֠8jBhrptik @GОcMYhSǚvLl9@bF΄c.V!΢yUg|5£>|#8l-M6 1&1a}XU;cG-9(2,Ssua|x+XG1RD~2CC1hpB$D` SPI!@& y0+`C .@=߫@ B\>H d<~PѷLc"`O!ۊhDH' r)A'$p O`Q(`Ml~2^ _%~2c6ޗ~} ?5jnF,{ L/J[hֲ$LH>c BBMt~x`> ;gNGNܪ WNBik}(gt.ӥӹRiյI ()f"t( /ɜ9 B)7svඒI:\nI \rx1{r&-/ՙ7iRK6gNvy0zÐpaB :rsҖUTe(NzYLBG2Ӵ#ƉEjY h=J{DZ' x;rS+h.ǿ1 gd(C+{[q;_pB^h8{.á3R@9{\>׌@`IIQXjʣ/2zLtkV8Q'۸82C'j 4JQ$MR[:g.߹5+55gޣv(~pE1~>V4(LS%}ef>1h`ênE}(""j,Zz;<,qֻ; =jɑM"%L1k ξ4pzpu~wĴ£% 8Yeb+3nc~\{:Htd,l9 7~5!aqy8b$a9m O` ?'q6>./T K7m١SdTNƟ/e3߅@wġW+|ebVޑM%ޢ nw/ՊlGSH`S[I) j T.LY_Djr=[8+/)E{=)ߡbYx؈"~00V|VYEuA%K-y7 ,esi +-M;y$x|9L9uqJC{Эu*zѭ1@GBIENDB`mlpost-0.8.2/test/externalimage/specials.sty000077700000000000000000000000001306046515300241772../../specials.styustar00rootroot00000000000000mlpost-0.8.2/test/externalimage/supp-mpe_mod.tex000077700000000000000000000000001306046515300255452../../supp-mpe_mod.texustar00rootroot00000000000000mlpost-0.8.2/test/manual/000077500000000000000000000000001306046515300152765ustar00rootroot00000000000000mlpost-0.8.2/test/manual/Makefile000066400000000000000000000002041306046515300167320ustar00rootroot00000000000000mpost: mpost manual.mp end mps : mpost ./convert_to_mps.sh clean: rm -f manual.[0-9]* manual.[0-9] *.mps manual.log manual.mpx mlpost-0.8.2/test/manual/convert_to_mps.sh000077500000000000000000000001361306046515300206760ustar00rootroot00000000000000#! /bin/sh for i in manual.[0-9]*; do bn=${i%.*} v=${i#*.} cp $i $bn-$v.mps done mlpost-0.8.2/test/manual/manual.mp000066400000000000000000000104271306046515300171150ustar00rootroot00000000000000beginfig(1); draw (20,20)--(0,0)--(0,30)--(30,0)--(0,0); endfig; beginfig(3); z0 = (0,0); z1 = (60,40); z2 = (40,90); z3 = (10,70); z4 = (30,50); draw z0..z1..z2..z3..z4; dotlabels.top(0,2,4); dotlabels.lft(3); dotlabels.lrt(1); endfig; beginfig(104); z0 = (0,0); z1 = (60,40); z2 = (40,90); z3 = (10,70); z4 = (30,50); draw z0..z1..z2..z3..z4..cycle; dotlabels.top(2,4); dotlabels.lft(0,3); dotlabels.lrt(1); endfig; beginfig(204); z0 = (0,0); z1 = (60,40); z2 = (40,90); z3 = (10,70); z4 = (30,50); draw z0..z1..z2..z3--z4--cycle; dotlabels.top(2,4); dotlabels.lft(0,3); dotlabels.lrt(1); endfig; beginfig(5); z0 = (0,0); z1 = (60,40); z2 = (40,90); z3 = (10,70); z4 = (30,50); path p; p = z0..z1..z2..z3..z4; draw p; for t=0 upto 3: draw point t of p--postcontrol t of p --precontrol t+1 of p--point t+1 of p %withcolor 0.5white dashed (evenly scaled .5) ; endfor dotlabels.top(0,2,4); dotlabels.lft(3); dotlabels.lrt(1); endfig; beginfig(6); z0 = (0,0); z1 = (60,40); z2 = (40,90); z3 = (10,70); z4 = (30,50); draw z0..z1{up}..z2{left}..z3..z4; dotlabels.top(0,2,4); dotlabels.lft(3); dotlabels.lrt(1); endfig; beginfig(7) for a=0 upto 9: draw (0,0){dir 45}..{dir -10a}(6cm,0); endfor endfig; beginfig(8) for a=0 upto 7: draw (0,0){dir 45}..{dir 10a}(6cm,0); endfor endfig; beginfig(109); z2=-z0=(1in,0); z1=(0,.2in); draw z0{up}..z1{right}..z2{down}; dotlabels.bot(0,1,2); endfig; beginfig(209); z2=-z0=(1in,0); z1=(0,.2in); draw z0{up}...z1{right}...z2{down}; dotlabels.bot(0,1,2); endfig; beginfig(110); numeric u; 10u=1.5in; -z0=z3=(5u,0); (-x1,y1)=z2=(3u,2u); draw z0..z1..z2..z3; dotlabels.bot(0,1,2,3); endfig; beginfig(210); numeric u; 10u=1.5in; -z0=z3=(5u,0); (-x1,y1)=z2=(3u,2u); draw z0..z1..tension 1.3..z2..z3; dotlabels.bot(0,1,2,3); endfig; beginfig(310); numeric u; 10u=1.5in; -z0=z3=(5u,0); (-x1,y1)=z2=(3u,2u); draw z0..z1..tension 1.5 and 1..z2..z3; dotlabels.bot(0,1,2,3); endfig; beginfig(111); numeric u, c; 10u=1.4in; c=0; z1=(0,0); (x0,-y0)=z2=(2u,5u); draw z0{curl c}..z1..{curl c}z2; dotlabels.rt(0,1,2); endfig; beginfig(211); numeric u, c; 10u=1.4in; c=1; z1=(0,0); (x0,-y0)=z2=(2u,5u); draw z0{curl c}..z1..{curl c}z2; dotlabels.rt(0,1,2); endfig; beginfig(311); numeric u, c; 10u=1.4in; c=2; z1=(0,0); (x0,-y0)=z2=(2u,5u); draw z0{curl c}..z1..{curl c}z2; dotlabels.rt(0,1,2); endfig; beginfig(411); numeric u, c; 10u=1.4in; c=infinity; z1=(0,0); (x0,-y0)=z2=(2u,5u); draw z0{curl c}..z1..{curl c}z2; dotlabels.rt(0,1,2); endfig; beginfig(17) ; a=.7in ; b=.5in ; z0=(0,0) ; z1=-z3=(a,0) ; z2=-z4=(0,b) ; draw z1..z2..z3..z4..cycle ; draw z1 -- z0 -- z2 ; label.top("a",.5[z0,z1]) ; label.lft("b",.5[z0,z2]) ; dotlabel.bot("(0,0)",z0) ; endfig ; beginfig(18) ; numeric u; u = 1cm; draw (0,2u) -- (0,0) -- (4u,0) ; pickup pencircle scaled 1pt ; draw (0,0){up} for i=1 upto 8 : ..(i/2,sqrt(i/2))*u endfor ; label.lrt(btex $ \sqrt x$ etex, (3,sqrt 3)*u) ; label.bot(btex $x$ etex, (2u,0)) ; label.lft(btex $y$ etex, (0,u)) ; endfig ; beginfig(19) ; numeric ux, uy ; 120ux=1.2in; 4uy=2.4in ; draw (0,4uy) -- (0,0) -- (120ux,0) ; pickup pencircle scaled 1pt ; draw (0,uy){right} for ix=1 upto 8 : ..(15ix*ux, uy*2/(1+cosd 15ix)) endfor ; label.bot (btex axe $x$ etex, (60ux,0)) ; label.lft (btex axe $y$ etex rotated 90, (0,2uy)) ; label.lft (btex $\displaystyle y={2\over1+\cos x}$ etex, (120ux, 4uy)) ; endfig ; beginfig(21) ; path p ; p = (-1cm,0)..(0,-1cm)..(1cm,0) ; fill p{up} .. (0,0){-1,-2} .. {up}cycle ; draw p .. (0,1cm) .. cycle ; endfig ; beginfig(22) ; path a, b, aa, ab ; a = fullcircle scaled 2cm ; b = a shifted (0,1cm) ; aa = halfcircle scaled 2cm ; ab = buildcycle(aa, b) ; picture pa, pb ; pa = thelabel(btex $A$ etex, (0,- .5cm)) ; pb = thelabel(btex $B$ etex, (0,1.5cm)) ; fill a withcolor .7white ; fill b withcolor .7white ; fill ab withcolor .4white ; unfill bbox pa ; draw pa ; unfill bbox pb ; draw pb ; label.lft(btex $U$ etex, (- 1cm,.5cm)) ; draw bbox currentpicture ; endfig ; beginfig(40); path p[]; p1 = (0,0){curl 0}..(5,-3)..{curl 0}(10,0); p2 = p1..(p1 yscaled-1 shifted(10,0)); p0 = p2; for i=1 upto 3: p0:=p0.. p2 shifted (i*20pt,0); endfor for j=0 upto 8: draw p0 shifted (0,j*10pt); endfor p3 = fullcircle shifted (.5,.5) scaled 72pt; clip currentpicture to p3; draw p3; endfig; mlpost-0.8.2/test/othergraphs/000077500000000000000000000000001306046515300163475ustar00rootroot00000000000000mlpost-0.8.2/test/othergraphs/Makefile000066400000000000000000000002031306046515300200020ustar00rootroot00000000000000mpost: mpost mpost.mp end mps : mpost ./convert_to_mps.sh clean: rm -f manual.[0-9]* manual.[0-9] *.mps manual.log manual.mpx mlpost-0.8.2/test/othergraphs/convert_to_mps.sh000077500000000000000000000001361306046515300217470ustar00rootroot00000000000000#! /bin/sh for i in mpost.[0-9]*; do bn=${i%.*} v=${i#*.} cp $i $bn-$v.mps done mlpost-0.8.2/test/othergraphs/mpost.mp000066400000000000000000000105401306046515300200470ustar00rootroot00000000000000input boxes; beginfig(1) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); draw A--B--C; endfig; beginfig(2) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); draw A--B--C--cycle; endfig; beginfig(4) pair A; A:=(0,0); B:=(1cm,0); C:=(0,1cm); draw A withpen pencircle scaled 4bp; endfig; beginfig(5) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); draw A--B--C--cycle; draw A withpen pencircle scaled 4bp; draw B withpen pencircle scaled 4bp; draw C withpen pencircle scaled 4bp; endfig; beginfig(7) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); draw A--B--C--cycle; draw 1/2[A,B] -- C; draw 1/2[B,C] -- A; draw 1/2[C,A] -- B; endfig; beginfig(12) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); draw A--B withpen pencircle scaled 2bp withcolor .8white; draw B--C withpen pencircle scaled 2bp withcolor .6white; draw C--A withpen pencircle scaled 2bp withcolor .4white; endfig; beginfig(20) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); fill A--B--C--cycle withcolor .8 white; endfig; beginfig(21) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); fill A--B--C--cycle withcolor .8 white; draw A--B--C--cycle; endfig; beginfig(22) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); fill A--B--C--cycle withcolor .8 white; draw A--B--C--cycle withpen pencircle scaled 2bp; endfig; beginfig(23) pair A, B, C; A:=(0,0); B:=(1cm,0); C:=(0,1cm); draw A--B--C--cycle withpen pencircle scaled 2bp; fill A--B--C--cycle withcolor .8 white; endfig; beginfig(60) u:=.5cm; pair A,B,C,D; A:=(0,0); B:=(-u,2u); C:=(4u,3u); D:=(3u,0); draw A.. controls B and C .. D withpen pencircle scaled 2pt; % draw B--C dashed evenly; draw B--C withcolor .8 white; drawarrow A--B; drawarrow D--C; endfig; beginfig(111) path a,b,c; a = fullcircle scaled 2cm shifted (.5cm,0); b = a rotated (360/3); c = b rotated (360/3); fill a withcolor red; fill b withcolor green; fill c withcolor blue; fill buildcycle(a,b) withcolor red + green; fill buildcycle(b,c) withcolor green + blue; fill buildcycle(c,a) withcolor blue + red; fill buildcycle(a,b,c) withcolor white; draw a; draw b; draw c; endfig; beginfig(130) transform T; u:=1cm; z0=(0,0); z1=(2u,0); z3 = z1 rotated 90; z2 = z1+z3; z0 transformed T = .1[z0,z1]; z1 transformed T = .1[z1,z2]; z2 transformed T = .1[z2,z3]; path p; p = z0--z1--z2--z3--cycle; for i=0 upto 50: fill p withcolor .8*white; p := p transformed T; fill p withcolor white; p := p transformed T; endfor; endfig; beginfig(140) for i=1 step -.01 until 0: fill fullcircle scaled (i*2cm) withcolor i*white; endfor; draw fullcircle scaled 2cm withpen pencircle scaled 2bp; endfig; % beginfig(141) % u:=5mm; % path p; % p = (0,0) .. (-1,1) .. (2,0) .. (0,-3) .. cycle; % p := p shifted (-1,0); % for i=1 step -.01 until 0: % fill p scaled (i*u) withcolor i*white; % endfor; % draw p scaled u withpen pencircle scaled 2bp; % endfig; beginfig(149) def couleur(expr x) = if x>.5: (2*(1-x)) [red, blue]; else: (1-2x) [blue, red] fi enddef; for i=0 step .5 until 360: draw 2cm* (sind(2*i), cosd(3*i)) withpen pencircle scaled 2bp withcolor couleur(i/360); endfor; endfig; beginfig(195) n:=8; u:=5mm; for i=0 upto n-1: for j=0 upto n-1: if odd(i+j): for k=0 step u/5 until 4/5 u: if odd(k*5/u): fill ( (k,0)--(u,u-k)--(u,u-k-u/5)-- (k+u/5,0)--cycle ) shifted (i*u,j*u) withcolor .8white; else: fill ( (0,k)--(u-k,u)--(u-k-u/5,u)-- (0,k+u/5)--cycle ) shifted (i*u,j*u) withcolor .8white; fi; endfor; fi; endfor; endfor; for i=0 upto n: draw (0,i*u)--(n*u,i*u); draw (i*u,0)--(i*u,n*u); endfor; endfig; beginfig(267) def drawredboxed(text t) = forsuffixes a=t: fill bpath a withcolor .5[red,white]; endfor; drawboxed(t); enddef; circleit.a(btex D\'ebut etex); a.c = (0,0); a.dx = a.dy; circleit.b(btex Fin etex); b.c = (2cm,0); b.dx = b.dy; drawredboxed(a,b); drawarrow a.c {dir 45} .. b.c {dir -45} cutbefore bpath.a cutafter bpath.b; drawarrow b.c {dir -135} .. a.c {dir 135} cutbefore bpath.b cutafter bpath.a; endfig; mlpost-0.8.2/test/palatino.ml000066400000000000000000000004431306046515300161630ustar00rootroot00000000000000open Mlpost open Picture open Command let hello = tex "Hello" let () = Metapost.emit "palatino" (seq [hello; shift (Point.cmp (-1.,-1.)) hello; shift (Point.cmp (1.,1.)) hello; shift (Point.cmp (-1.,1.)) hello; shift (Point.cmp (1.,-1.)) hello; ]) mlpost-0.8.2/test/palatino.tex000066400000000000000000000003251306046515300163520ustar00rootroot00000000000000%% -*- coding : utf8 -*- \documentclass[10pt,a4paper]{article} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage[sc]{mathpazo} \usepackage[frenchb]{babel} \begin{document} HelloHello \end{document} mlpost-0.8.2/test/transformations.ml000066400000000000000000000015551306046515300176120ustar00rootroot00000000000000open Mlpost let () = if not Concrete.supported then (Format.eprintf "Concrete is needed for this test@."; exit 1) let unitsquare = Path.scale (Num.cm 2.) Path.unitsquare let fig1 = let t = [Transform.slanted (Num.bp 3.);Transform.slanted (Num.bp 3.)] in let square = Path.transform t unitsquare in Path.fill square let fig2 = let t = [Transform.slanted (Num.bp 3.);Transform.slanted (Num.bp 3.)] in let t = Concrete.ctransform_of_transform t in let t = Concrete.transform_of_ctransform t in let square = Path.transform t unitsquare in Path.fill square open Transform open Num let fig3 = let t = [explicit {x0=bp 1.;y0=bp 0.;xx=bp 1.;xy=bp 3.;yx=bp 0.;yy=bp 1.}] in let square = Path.transform t unitsquare in Path.fill square let () = List.iter (fun (s,l) -> Metapost.emit s l) [ "fig1", fig1; "fig2", fig2; "fig3", fig3] mlpost-0.8.2/test_freetype.ml000066400000000000000000000006231306046515300162570ustar00rootroot00000000000000open Cairo_ft open Mlpost_ft open Format let () = let filename = Sys.argv.(1) in let ft = Cairo_ft.init_freetype () in let face = Cairo_ft.new_face ft filename in printf "charmap %i\n%!" (ft_num_charmaps face); ft_set_charmap face (int_of_string Sys.argv.(3)); let char_index = int_of_string (Sys.argv.(2)) in printf "Index of %i : %i\n%!" char_index (ft_get_char_index face char_index) mlpost-0.8.2/test_vf.ml000066400000000000000000000001361306046515300150460ustar00rootroot00000000000000open Dvi let () = let vf = read_vf_file Sys.argv.(1) in Format.printf "%a@." print_vf vf mlpost-0.8.2/tests.ml000066400000000000000000000470421306046515300145450ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Mlpost open Num open Command open Format open Helpers open Point open Path module T = Transform let (++) x y = pt (cm x, cm y) let shift x y = transform [Transform.shifted (x ++ y)] let () = Random.init 1234 open Tree_adv let rec bin = function | 0 -> Node (0, []) | n -> let (Node (_,l) as t) = bin (n-1) in Node (n, t :: l) let to_box n = Box.tex (sprintf "${2^{%d}}$" n), n let t = map to_box (bin 4) module Pl = struct type t = Box.t * int let width (z,_) = Box.width z let height (z,_) = Box.height z let set_pos p (z,n) = Box.center p z, n end module P = Tree_adv.Place(Pl) let t = P.place t let adv_fig = let (++) = Command.(++) in draw fst t ++ (fold (++) Command.nop (gen_draw_arrows Command.nop ~style:(fun a b -> Helpers.draw_simple_arrow a b) ~corner:(fun d (z,_) -> Box.corner d z) t)) open Tree open Box (* Bresenham (JCF) *) (* the data to plot are computed here *) let x2 = 9 let y2 = 6 let bresenham_data = let a = Array.create (x2+1) 0 in let y = ref 0 in let e = ref (2 * y2 - x2) in for x = 0 to x2 do a.(x) <- !y; if !e < 0 then e := !e + 2 * y2 else begin y := !y + 1; e := !e + 2 * (y2 - x2) end done; a (* drawing *) let bresenham0 = let width = bp 6. and height = bp 6. in let g = Box.gridi (x2+1) (y2+1) (fun i j -> let fill = if bresenham_data.(i) = y2-j then Some Color.red else None in Box.empty ~width ~height ?fill ~stroke:(Some Color.black) ()) in Box.draw g let block1 = let b1 = hblock ~min_width:(width (tex "c")) [empty (); tex "A"; tex "B"; tex "c"; tex "toto"] in let b2 = hblock ~same_width:true [tex "A"; tex "B"; tex ~fill:Color.red "c"; tex "toto"] in draw (vbox [b1;b2]) let block2 = draw (hblock [tex "A"; tex "B"; tex "c"; tex "toto"]) let vblock1 = draw (vblock [tex "A"; tex "B"; tex "c"; tex "toto"]) let hbox1 = draw (hbox ~pos:`North [tex "."; tex "B"; tex "c"; tex "toto"]) let hbox2 = let s b = Box.shift (Point.p (100.,100.)) b in let stroke = Some Color.red in let b = vbox ~stroke ~pos:`West [tex "A"; s (tex "Bx") ; tex "c"; tex "toto"] in let t = hbox ~stroke [b;b;b] in draw (vbox [t;s t;t]) let simple_box = Box.draw (Box.rect ~stroke:(Some Color.black) (Box.empty ~width:(bp 50.) ~height:(bp 50.) ())) let hvbox = let row = vbox [tex "A"; tex "B"; tex "C" ] in let col = hbox [nth 0 row ; tex "D" ; tex "E"] in seq [ draw row; draw col ] let d1 = let a = circle (tex "$\\sqrt2$") in let b = shift (2. ++ 0.) (rect ~fill:Color.purple (tex "$\\pi$")) in let pen = Pen.scale (bp 3.) Pen.default in seq [ draw a; draw b; Command.draw ~color:Color.red (Path.shift (1. ++ 1.) (bpath a)); draw_label_arrow ~color:Color.orange ~pen ~pos:`Northeast (Picture.tex "foo") (west a) (south_east b); box_arrow ~color:Color.blue a b; ] open Box let d2 = let tex = tex ~stroke:(Some Color.black) in let b = hbox ~padding:(bp 10.) ~pos:`North ~stroke:(Some Color.red) ~dx:(bp 2.) ~dy:(bp 2.) [vbox ~padding:(bp 4.) ~pos:`East [tex "A"; tex "BC"; tex "D"]; vbox ~padding:(bp 4.) ~pos:`West [tex "E"; tex "FGH"]] in seq [draw ~debug:false b; box_arrow (nth 1 (nth 0 b)) (nth 0 (nth 1 b))] let proval = let f = 7. in let pen = Pen.rotate 40. (Pen.yscale (bp 0.5) Pen.square) in let check = jointpath [-1.2,1.2; 0., -2. ; 2., 2. ; 5., 5.] [jLine ; jCurve; jCurve] in seq [ fill ~color:(Color.gray 0.2) (Path.scale (Num.bp f) fullcircle) ; label ~pos:`West (Picture.tex "Pr") (Point.p (f /. (-4.),0.)) ; label ~pos:`East (Picture.tex "al") (Point.p (f /. 4.,0.)) ; Command.draw ~color:Color.green ~pen check;] open Tree let yannick style = let tt s = Box.tex ~style ~fill:Color.orange ("\\texttt{" ^ s ^ "}") in let node s = node ~ls:(bp 20.) ~cs:(bp 10.) ~edge_style:Square (tt s) in let leaf s = leaf (tt s) in let tree = node "ComposerPage" [ leaf "MemSet"; node "ComposerMessages" [ node "ComposerMsg" [ leaf "StrCpy"; leaf "DeclarerPanneRobustesse" ] ] ] in draw tree let rec random_tree ?arrow_style ?edge_style ?stroke ?pen ?sep n = let random_tree = random_tree ?arrow_style ?edge_style ?stroke ?pen ?sep in let tex s = shadow (tex ~fill:Color.yellow ~stroke:(Some Color.black) s) in match n with | 1 -> leaf (tex "1") | 2 -> node ?arrow_style ?edge_style ?stroke ?pen ?sep (Box.tex ~style:Box.Rect ~fill:(Color.rgb 0.5 0.3 0.2) "2") [leaf (tex "1")] | n -> let k = 1 + Random.int (n - 2) in node ?arrow_style ?edge_style ?stroke ?pen ?sep (tex (string_of_int n)) [random_tree k; random_tree (n - 1 - k)] let d2c, d2s, d2sq, d2hsq = (* let ls = bp (-1.0) in *) let stroke = Color.blue and pen = Pen.circle and arrow_style = Directed in draw (random_tree ~edge_style:Curve ~arrow_style ~stroke ~pen ~sep:(bp 5.) 17), draw (random_tree ~edge_style:Straight ~arrow_style ~stroke ~pen ~sep:(bp 3.) 17), draw (random_tree ~edge_style:Square ~arrow_style ~stroke ~pen 17), draw (random_tree ~edge_style:HalfSquare ~arrow_style ~stroke ~pen 17) let d5 = let rand_tree name i = set_name name (set_stroke Color.black (to_box (random_tree i))) in let t1 = rand_tree "1" 5 in let t2 = rand_tree "2" 6 in let bl = Box.hbox ~padding:(Num.cm 2.) [ box t1; box t2] in let b1 = nth 0 (sub t1 bl) in let b2 = nth 0 (nth 0 (nth 1 (sub t2 bl))) in seq [ Box.draw bl; box_arrow ~sep:(bp 5.) b1 b2; ] let tree1 () = pic (draw (random_tree (1 + Random.int 5))) let rec random_tree2 = function | 1 -> leaf (tree1 ()) | 2 -> node ~cs:(mm 0.2) (tree1 ()) [leaf (tree1 ())] | n -> let k = 1 + Random.int (n - 2) in node ~cs:(mm 0.2) (tree1 ()) [random_tree2 k; random_tree2 (n - 1 - k)] let d6 = draw (random_tree2 10) let cheno011 = let p = Path.path ~cycle:jCurve [(0.,0.); (30.,40.); (40.,-20.); (10.,20.)] in let pen = Pen.scale (bp 1.5) Pen.circle in seq [Command.draw p; seq (List.map (fun (pos, l, i) -> Command.dotlabel ~pos (Picture.tex l) (point i p)) [`South, "0", 0.; `Northeast, "1", 1. ; `Southwest, "2", 2. ; `North, "3", 3. ; `West, "4", 4. ]); Command.draw ~pen (subpath 1.3 3.2 p)] open Dash let d3 = let p = pathp [cmp (0., 0.); cmp (5., 0.)] in let pat = pattern [on (bp 6.); off (bp 12.); on (bp 6.)] in Command.draw p ~dashed:pat let d4 = seq [cheno011; iter 1 5 (fun i -> Picture.transform [T.rotated (10. *. float i)] cheno011) ] let d7 = let pic = Picture.transform [T.scaled (bp 4.)] (Picture.tex "bound this!") in let pbox = pathp ~style:jLine ~cycle:jLine [Picture.ulcorner pic; Picture.urcorner pic; Picture.lrcorner pic; Picture.llcorner pic] in seq [pic; Command.draw (Picture.bbox pic); Command.draw pbox; Command.dotlabel ~pos:`West (Picture.tex "ulcorner") (Picture.ulcorner pic); Command.dotlabel ~pos:`West (Picture.tex "llcorner") (Picture.llcorner pic); Command.dotlabel ~pos:`East (Picture.tex "urcorner") (Picture.urcorner pic); Command.dotlabel ~pos:`East (Picture.tex "lrcorner") (Picture.lrcorner pic); ] let half = Picture.scale (bp 0.5) let rec right_split n pic = if n <= 0 then pic else let smaller = right_split (n-1) (half pic) in Picture.beside pic (Picture.below smaller smaller) let d11 = let p1 = Picture.transform [Transform.rotated 90.] (Picture.tex "recursion") in right_split 3 p1 let rec sierpinski p n = if n = 0 then p else let p = sierpinski p (n-1) in (* let p = half sp in *) let p1 = Picture.beside p p in Picture.below p p1 let d12 = let p1 = Picture.tex "A" in sierpinski p1 5 (** plots *) open Plot let sk = mk_skeleton 20 14 (Num.bp 20.) (Num.bp 20.) let d13 = draw_grid sk let squaref x = x *. x let f2 i = sqrt (float_of_int i) let f3 i = squaref (float_of_int i) let d14 = let hdash _ = Dash.scaled 0.5 Dash.withdots in let vdash _ = Dash.scaled 2. Dash.evenly in let hvpen i = if i mod 5 = 0 then Pen.scale (bp 2.5) Pen.default else Pen.default in let pen = Pen.scale (bp 4.) Pen.default in seq [draw_grid ~hdash ~vdash ~hpen:hvpen ~vpen:hvpen sk; draw_func ~pen f2 sk; draw_func ~pen f3 sk ] let f1 i = let aux = function | 0 -> 1 | 1 | 2 -> 2 | 3 | 4 -> 3 | 5 -> 4 | 6 | 7 -> 5 | 8 |9 -> 6 | 10 -> 7 | 11 | 12 -> 8 | 13 | 14 -> 9 | 15 -> 10 | 16 | 17 -> 11 | 18 | 19 -> 12 | 20 -> 13 | _ -> 0 in float_of_int (aux i) let f2 i = let aux = function | 0 | 1 | 2 -> 0 | 3 -> 1 | 4 -> 2 | 5 | 6 | 7 -> 3 | 8 -> 4 | 9 -> 5 | 10 | 11 | 12 -> 6 | 13 -> 7 | 14 -> 8 | 15 | 16 | 17 -> 9 | 18 -> 10 | 19 -> 11 | 20 -> 12 | _ -> 0 in float_of_int (aux i) let f3 i = float_of_int ((i+3)/5) let flab i = (Picture.transform [Transform.scaled (bp 1.7)] (Picture.tex (Printf.sprintf "$f_{\\omega_%d}$" i)), `North, 19) let instants = let pen = Pen.scale (bp 2.5) Pen.default in let base = Command.draw ~pen (Path.path ~style:jLine [(0.,-65.); (280.,-65.)]) in let tick i = let xi = float_of_int i *. 14. in let yi = if f1 i = f1 (i-1) then -60. else -45. in let p = Path.path ~style:jLine [(xi,-65.); (xi, yi)] in Command.draw ~pen p in Command.seq [base; Command.iter 0 20 tick; Command.label (Picture.transform [Transform.scaled two] (Picture.tex "$\\omega_1$")) (p (-20., -55.))] let florence = let sk = mk_skeleton 20 14 (bp 14.) (bp 20.) in let pen = Pen.scale (bp 4.) Pen.default in let pen2 = Pen.scale (bp 3.) Pen.default in let dash _ = Dash.scaled 0.5 Dash.withdots in let dash2 = Dash.scaled 0.66 Dash.withdots in let dash3 = Dash.scaled 0.9 Dash.evenly in let vcaption, hcaption = let tr = [Transform.scaled (bp 1.5)] in Picture.transform tr (Picture.tex "\\textsf{Number of ones}"), Picture.transform tr (Picture.tex "\\textsf{Instants}") in let plot = draw_func ~drawing:Stepwise ~style:jLine in seq [ draw_grid ~hdash:dash ~vdash:dash ~color:(Color.gray 0.5) sk; draw_axes ~closed:true ~hcaption ~vcaption sk; plot ~pen ~label:(flab 1) f1 sk; plot ~pen:pen2 ~dashed:dash2 ~label:(flab 2) f2 sk; plot ~pen ~dashed:dash3 ~label:(flab 3) f3 sk; instants ] let shapes1 = Box.vbox [Box.path (Shapes.rectangle (bp 10.) (bp 20.)); Box.path (Shapes.rectangle (bp 35.) (bp 15.)); Box.path (Shapes.rectangle (bp 15.) (bp 35.)); Box.path (Shapes.round_rect (bp 55.) (bp 25.) (bp 10.) (bp 10.)); Box.path (Shapes.round_rect (bp 55.) (bp 25.) (bp 20.) (bp 5.)); Box.path (Shapes.round_rect (bp 70.) (bp 25.) (bp 14.) (bp 14.)); ] let shapes2 = Box.vbox [ (* Shapes.arc_ellipse (f 10.) (f 10.) 0. 1.7; Shapes.arc_ellipse ~stroke:Color.red (f 30.) (f 10.) 0. 1.7; Shapes.arc_ellipse ~stroke:Color.red ~close:true (f 30.) (f 10.) 0. 1.7; Shapes.arc_ellipse ~fill:Color.black ~stroke:Color.red (f 30.) (f 10.) 0. 1.7; *) Box.path (Shapes.ellipse (bp 10.) (bp 10.)); Box.path (Shapes.ellipse (bp 30.) (bp 10.)); Box.path (Shapes.ellipse (bp 30.) (bp 10.)); ] let farey n = let u x = Num.bp (200.0 *. x) in let circle x y r = Command.fill ~color:Color.lightgray (Path.shift (Point.pt (u y, u x)) (Path.scale (u (2.*.r)) fullcircle)) in let quartercircle x y r theta = Command.draw (Path.shift (Point.pt (u y, u x)) (Path.scale (u (2.*.r)) (Path.rotate theta quartercircle))) in let rec aux acc p1 q1 p2 q2 = let p = p1 + p2 in let q = q1 + q2 in if q>n then acc else let fq = float q in let fr = 0.5 /. fq /. fq in let acc = circle (float p /. fq) fr fr :: acc in let acc = aux acc p1 q1 p q in aux acc p q p2 q2 in let l = aux [ quartercircle 0.0 0.5 0.5 90.0; quartercircle 1.0 0.5 0.5 180.0] 0 1 1 1 in Picture.scale (Num.bp 30.0) (Command.seq l) let why_platform = let tabular l = "{\\begin{tabular}{l}" ^ String.concat " \\\\ " l ^ "\\end{tabular}}" in let dx = bp 5. and dy = bp 5. in let space ~name b = rect ~stroke:None ~name ~dx ~dy b in let green s = space ~name:s (round_rect ~dx ~dy ~stroke:None ~fill:Color.lightgreen (tex s)) in let pink s = space ~name:s (shadow (rect ~dx ~dy ~fill:(Color.color "light pink") (tex ("\\large\\sf " ^ s)))) in let interactive = tex ~name:"interactive" (tabular ["Interactive provers"; "(Coq, PVS,"; "Isabelle/HOL, etc.)"]) in let automatic = tex ~name:"automatic" (tabular ["Automatic provers"; "(Alt-Ergo, Simplify,"; "Yices, Z3, CVC3, etc.)"]) in let b = tabularl ~hpadding:(bp 20.) ~vpadding:(bp 30.) [[green "Annotated C programs"; empty (); green "JML-annotated Java programs"]; [pink "Caduceus"; green "Why program"; pink "Krakatoa";]; [empty (); pink "Why"; empty ()]; [interactive; green "verification conditions"; automatic]] in let arrow x y = let p = Box.cpath (get x b) (get y b) in Arrow.draw_thick ~line_color:Color.red ~width:(bp 4.) ~head_width:(bp 10.) ~fill_color:Color.red (Path.point 0. p) (Path.point 1. p) in seq [Box.draw b; arrow "Annotated C programs" "Caduceus"; arrow "Caduceus" "Why program"; arrow "JML-annotated Java programs" "Krakatoa"; arrow "Krakatoa" "Why program"; arrow "Why program" "Why"; arrow "Why" "verification conditions"; arrow "verification conditions" "interactive"; arrow "verification conditions" "automatic"; ] (*** let alt_ergo = let b = tabularl ~hpadding:(bp 20.) ~vpadding:(bp 30.) [[green "Annotated C programs"; empty (); green "JML-annotated Java programs"]; [pink "Caduceus"; green "Why program"; pink "Krakatoa";]; [empty (); pink "Why"; empty ()]; [interactive; green "verification conditions"; automatic]] in [Box.draw b] ***) let rotatedbox = let t = tex "$A^{-1}$" in let b1 = Box.rotate 90. t in Box.draw (Box.hblock [b1;t]) let style = RoundRect let stroke = Some Color.black let pen = Pen.scale (bp 2.) Pen.circle let dx = bp 5. let dy = dx let tex = Box.tex ~style ~pen ~dx ~dy let tex' = Box.tex ~style ~pen ~dx ~dy:(bp 10.) let assia_schema = let tabular l = "{\\begin{tabular}{l}" ^ String.concat " \\\\ " l ^ "\\end{tabular}}" in let lang = tex ~stroke:(Some Color.red) "langage de developpement de preuves" in let genie = Box.tex "Genie logiciel formel" in let moteur = tex' ~stroke:(Some Color.purple) (tabular ["moteur de"; "dev de preuves"]) in let verif = tex' ~stroke:(Some Color.purple) (tabular ["verificateur";" de preuves"]) in let langf = Box.round_rect ~stroke:(Some Color.blue) ~pen ~dx:(bp 50.) ~dy:(bp 10.) (Box.tex "langage formel") in let h = Box.hbox ~padding:(bp 20.) [moteur;verif] in let v = Box.vbox ~dx ~dy:(bp 10.) ~pen ~padding:(bp 5.) ~style ~stroke:(Some Color.orange) [lang; genie] in Box.draw (Box.vbox ~padding:(bp (-5.)) [langf; h;v]) let grid_with_padding = let red s = rect ~stroke:None ~fill:Color.lightred (tex s) in let blue s = rect ~stroke:None ~fill:Color.lightblue (tex s) in let b = gridl ~stroke:None ~hpadding:(bp 5.) ~vpadding:(bp 5.) [[empty (); red "abc"; red "def"]; [blue "titre 1"; red ""; red ""]; [blue "titre 2"; red ""; red ""]] in Box.draw b let grid_with_padding_2 = let red s = rect ~stroke:None ~fill:Color.lightred (tex s) in let blue s = rect ~stroke:None ~fill:Color.lightblue (tex s) in let pen = Pen.scale (Num.pt 1.5) Pen.circle in let b = gridl ~stroke:(Some Color.white) ~pen ~hpadding:(bp 5.) ~vpadding:(bp 5.) [[empty (); red "abc"; red "def"]; [blue "titre 1"; red ""; red ""]; [blue "titre 2"; red ""; red ""]] in seq [Box.draw b; Box.draw (shift (Point.pt (bp 5., bp 5.)) b)] module Tr = Triangle open Color open Command let t40 = Tr.create ~left:0.5 ~depth:(bp 40.) () let x = let t = Tr.create ~fill:white ~depth:(bp 13.) () in Tr.tex_root_label "$x$" t let anchor1 = let t1 = Tr.tex_label ~depth:0.5 "$\\sigma$" t40 in let t2 = Tr.anchor ~depth:1.0 ~x:0.3 t1 x in let t3 = Tr.anchor ~depth:1.0 ~x:0.7 t1 x in Tr.draw t1 ++ Tr.draw t2 ++ Tr.draw t3 let pose = let t1 = Tr.pose_left ~x:0.2 t40 x in let t2 = Tr.pose_right ~x:0.8 t40 x in let t3 = Tr.pose_right ~x:0.95 ~depth:1.2 t40 (Tr.create ~fill:lightred ~depth:13. ()) in Tr.draw t40 ++ Tr.draw t1 ++ Tr.draw t2 ++ Tr.draw t3 let redex1 = let t1 = Tr.create ~left:0.5 ~depth:(bp 40.) () in let t1 = Tr.tex_root_label "$t$" t1 in let t = Tr.tex ~dx:2. ~dy:2. ~fill:lightred "$r$" in let t = Tr.tex_root_label "\\footnotesize$p$" t in let t = Tr.anchor ~depth:0.8 ~x:0.3 t1 t in Tr.draw t1 ++ Tr.draw t let label1 = let t = Tr.create ~left:0.5 ~depth:(bp 40.) () in let t = Tr.tex_label "$\\sigma t$" t in Tr.draw t let pic1 = let t = Tr.tex ~pen ~fill:lightred "TOT" in Tr.draw t let x_depth = let t = Tr.create ~left:20. ~right:60. ~depth:70. () in let r = Tr.root t in let depth = 0.7 in let x0 = Tr.x_depth ~depth ~x:0. t in let x1 = Tr.x_depth ~depth ~x:1. t in let x = Tr.x_depth ~depth ~x:0.7 t in let p01 = Path.pathp [Tr.x_depth ~depth ~x:(-0.5) t; Tr.x_depth ~depth ~x:(1.5) t] in let p = Point.add r (Point.mult 1.8 (Point.sub x r)) in let pd = Path.pathp [r; p] in let b = Tr.x_depth ~depth:1. ~x:0.7 t in Tr.draw t ++ Command.dotlabel ~pos:`Topleft (Picture.tex "0") x0 ++ Command.dotlabel ~pos:`Topright (Picture.tex "1") x1 ++ Command.dotlabel ~pos:`Bottomleft (Picture.tex "x") x ++ Command.dotlabel ~pos:`Topleft (Picture.tex "0") r ++ Command.dotlabel ~pos:`Bottomleft (Picture.tex "1") b ++ Command.draw ~color:purple p01 ++ Command.draw ~color:red pd ++ nop let figs = [ (* grid_with_padding; adv_fig; grid_with_padding_2; rotatedbox; assia_schema; hbox1; hbox2; bresenham0; simple_box; block1; hvbox; why_platform;d2; block2; vblock1; yannick Box.Rect; yannick Box.Patatoid; yannick Box.Patatoid2; d1; d2sq; d2hsq; d2s; d2c; cheno011; d3; d4; d7; proval; *) d11; d12 ; d14; d13; d5; florence; Box.draw shapes1; Box.draw shapes2; farey 17; (* other *) d6; Box.draw t40; anchor1; pose; redex1; label1; pic1; x_depth; ] let figs = let r = ref 0 in List.map (fun f -> incr r; !r, f) figs (* CM fonts do not scale well *) (* let theprelude = "\\documentclass[a4paper]{article} \\usepackage[T1]{fontenc} \\usepackage{times} " *) let () = List.iter (fun (i,r) -> Metapost.emit (string_of_int i) r) figs mlpost-0.8.2/testspace/000077500000000000000000000000001306046515300150355ustar00rootroot00000000000000mlpost-0.8.2/testspace/hello-ref.png000066400000000000000000000010731306046515300174210ustar00rootroot00000000000000PNG  IHDR9a=bKGD#2 pHYsXXƾ vpAg9hўIDAT8An P,Juk tG%&Qf*ِlA22D}9.;w3˜睽m p%ݸUjIV8ۥ+_᢫rr9: /H~` : use_unix mlpost-0.8.2/testsuite/frameWork.ml000066400000000000000000000036261306046515300173710ustar00rootroot00000000000000module Assert = struct exception Assert of string option let assert_failure s = raise (Assert s) let bool ?s cond = if cond then () else assert_failure s let eq ?s a b = if a = b then () else assert_failure s module F = File module File = struct let exists ?s f = bool ?s (File.exists f) let eq ?s ?ignore a b = let ignore = match ignore with | None -> "" | Some s -> "-I " ^ s in let a = File.to_string a and b = File.to_string b in let r = Misc.call_cmd ~outv:true (Misc.sprintf "diff %s %s %s" ignore a b) in eq ?s r 0 end module List = struct let non_empty l = bool (l <> []) end end module Test = struct let _ = Printexc.record_backtrace true let id_unit () = () type t = { prepare : unit -> unit; run : unit -> unit; clean_up : unit -> unit; name : string } let mk ?(prepare=id_unit) ?(clean_up=id_unit) ~name run = { prepare = prepare ; clean_up = clean_up; run = run; name = name } let run_one queue t = t.prepare (); begin try t.run (); Format.printf ".@?" with | Assert.Assert s -> Format.printf "!@?"; queue := (t,s)::!queue | e -> Format.printf "?@?"; Format.eprintf "Error during test %s...@." t.name; Format.eprintf "%s@." (Printexc.to_string e); Printexc.print_backtrace Pervasives.stderr end; try t.clean_up () with e -> Format.eprintf "Error during cleanup of test %s...@." t.name; Format.eprintf "%s@." (Printexc.to_string e); Printexc.print_backtrace Pervasives.stderr; exit 1 let run_many l = let queue = ref [] in List.iter (run_one queue) l; Format.printf "@."; let l = List.rev !queue in List.iter (fun (t,ass) -> Format.printf "failed test %s:@." t.name; match ass with | None -> () | Some s -> Format.printf "assertion failed: %s@." s) l end mlpost-0.8.2/testsuite/run_tests.ml000066400000000000000000000001721306046515300174530ustar00rootroot00000000000000let _ = Sys.chdir "testspace"; FrameWork.Test.run_many Test_file.tests; FrameWork.Test.run_many Test_metapost.tests mlpost-0.8.2/testsuite/test_file.ml000066400000000000000000000010471306046515300174050ustar00rootroot00000000000000open FrameWork let test_from_string = Test.mk ~name:"from_string" (fun () -> let s = "toto.mps" in let f = File.from_string s in Assert.eq ~s:"toto.mps" (File.to_string f) "toto.mps"; let p = File.set_ext f "pdf" in Assert.eq ~s:"toto.pdf" (File.to_string p) "toto.pdf") let test_dir_from_string = Test.mk ~name:"dir_from_string" (fun () -> let s = "/toto/blop/blip" in let f = File.Dir.from_string s in Assert.eq ~s (File.Dir.to_string f) s;) let tests = [ test_from_string; test_dir_from_string; ] mlpost-0.8.2/testsuite/test_metapost.ml000066400000000000000000000025401306046515300203210ustar00rootroot00000000000000open FrameWork let s = "hello" let fig = Picture.tex s module FM = File.Map let test_mp = let out = "hello" in let ref_file = File.from_string "hello.reference" in let cleanup = ref (File.from_string "") in Test.mk ~name:"mp" ~clean_up:(fun () -> File.rm !cleanup ) (fun () -> let f,m = Metapost.mp out [File.from_string "hello.mps",fig] in cleanup := f; Assert.File.exists f; Assert.File.eq ref_file f; ) let test_mps = let out = File.from_string "hello.mps" in let ref = File.from_string "hello.mps.reference" in Test.mk ~name:"mps" ~clean_up:(fun () -> File.rm out) (fun () -> let l = Metapost.temp_mps "hello" [out,fig] in Assert.List.non_empty l; let f = List.hd l in Assert.bool (File.compare f out = 0); Assert.File.exists f; Assert.File.eq ~ignore:"%%CreationDate:" ref f) let test_png = let bn = File.from_string "hello.mps" in let out = File.set_ext bn "png" in Test.mk ~name:"png" ~clean_up:(fun () -> File.rm out) ~prepare:(fun () -> Compile.reset ()) (fun () -> let l = Metapost.temp_png "hello" [bn,fig] in Assert.List.non_empty l; let f = List.hd l in Assert.bool (File.compare f out = 0); Assert.File.exists f) let tests = [ test_mp ; test_mps; test_png ] mlpost-0.8.2/tool.ml000066400000000000000000000220521306046515300143520ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format open Arg let use_ocamlbuild = ref false let ccopt = ref " " let execopt = ref " " let verbose = Mlpost_desc_options.verbose let native = ref false let libraries = ref (Version.libraries Version.libdir) let compile_name = ref None let dont_execute = ref false let dont_clean = ref false let add_nothing = ref false let files = Queue.create () let not_cairo = Version.not_cairo let not_bitstring = Version.not_bitstring let used_libs = (* put libraries in correct order here *) let acc = ["unix"] in let acc = if not_cairo then acc else "cairo"::acc in let acc = if not_bitstring then acc else "bitstring"::acc in let acc = "mlpost"::acc in (* mlpost_options is activated by default *) let acc = "mlpost_options"::acc in ref acc let add_contrib x = if List.mem_assoc x !libraries then used_libs := x::!used_libs else begin Format.eprintf "contrib %s unknown" x; exit 1 end let remove_mlpost_options () = used_libs := List.filter (fun s -> s <> "mlpost_options") !used_libs let add_file f = if not (Filename.check_suffix f ".ml") then begin eprintf "mlpost: don't know what to do with %s@." f; exit 1 end; if not (Sys.file_exists f) then begin eprintf "mlpost: %s: no such file@." f; exit 1 end; Queue.add f files let version () = (* The first line of the output should be the version number, and only the * version number! *) Format.printf "%s@." Version.version; Format.printf "mlpost %s compiled at %s@." Version.version Version.date; Format.printf "searching for mlpost.cm(a|xa) in %s@." Version.libdir; if not not_cairo || not not_bitstring then Format.printf "additional directories are %s@." Version.include_string; exit 0 let add_ccopt x = ccopt := !ccopt ^ x ^ " " let add_execopt x = execopt := !execopt ^ x ^ " " let add_libdir libdir = libraries := Version.libraries libdir let give_lib () = List.fold_left (fun (acc1,acc2) x -> let includes_,libs = List.assoc x !libraries in List.rev_append includes_ acc1, List.rev_append libs acc2) ([],[]) !used_libs let get_include_compile s = (* TODO revoir *) let aux = function (* | "cmxa" -> List.map (fun (x,y) -> Filename.concat x (y^".cmxa")) (give_lib ()) | "cma" -> List.map (fun (x,y) -> Filename.concat x (y^".cma")) (give_lib ()) *) | "dir" -> fst (give_lib ()) | "file" -> snd (give_lib ()) | _ -> assert false in print_string (String.concat "\n" (aux s)) let nocairo () = print_string "Mlpost has not been compiled with cairo\n"; exit 1 let options_for_compiled_prog = Queue.create () let aotofcp ?arg s = Queue.add s options_for_compiled_prog; match arg with | None -> () | Some s -> Queue.add s options_for_compiled_prog let execopt cmd = let b = Buffer.create 30 in bprintf b "%s %a -- %s@?" cmd (fun fmt -> Queue.iter (fprintf fmt "\"%s\" ")) options_for_compiled_prog !execopt; Buffer.contents b let build_args ?ext () = (* ext = None => ocamlbuild *) let lib_ext lib acc = match ext with | None -> "-lib"::lib::acc | Some ext -> (lib^ext)::acc in let include_ acc libdir = match ext with | None -> (sprintf "-cflags -I,%s -lflags -I,%s " libdir libdir)::acc | Some ext -> "-I"::libdir::acc in List.fold_left (fun acc c -> let llibdir,llib = List.assoc c !libraries in let acc = List.fold_right lib_ext llib acc in let acc = List.fold_left include_ acc llibdir in acc) [] !used_libs (* The option have the same behavior but add itself to option_for_compiled_prog in addition *) let wrap_option (opt,desc,help) = let desc = match desc with | Unit f -> Unit (fun () -> f ();aotofcp opt) | Set s -> Unit (fun () -> s:=true; aotofcp opt) | Clear s -> Unit (fun () -> s:=false; aotofcp opt) | String f -> String (fun s -> f s;aotofcp ~arg:s opt) | Int f -> Int (fun s -> f s;aotofcp ~arg:(string_of_int s) opt) | Float f -> Float (fun s -> f s;aotofcp ~arg:(string_of_float s) opt) | Bool f -> Bool (fun s -> f s;aotofcp ~arg:(string_of_bool s) opt) | Set_int s -> Int (fun x -> s:=x; aotofcp ~arg:(string_of_int x) opt) | Set_float s -> Float (fun x -> s:=x; aotofcp ~arg:(string_of_float x) opt) | Set_string s -> String (fun x -> s:=x; aotofcp ~arg:x opt) | Symbol (l, f) -> Symbol (l,fun x -> f x; aotofcp ~arg:x opt) | Rest _ | Tuple _ -> assert false (*Not implemented... *) in (opt,desc,help) let spec = Arg.align (["-ocamlbuild", Set use_ocamlbuild, " Use ocamlbuild to compile"; "-native", Set native, " Compile to native code"; "-ccopt", String add_ccopt, "\"\" Pass to the Ocaml compiler"; "-execopt", String add_execopt, "\"\" Pass to the compiled program"; "-version", Unit version, " Print Mlpost version and exit"; "-libdir", String add_libdir, " change assumed libdir of mlpost"; "-get-include-compile", Symbol (["cmxa";"cma";"dir";"file"],get_include_compile), " Output the libraries which are needed by the library Mlpost"; "-compile-name", String (fun s -> compile_name := Some s), " Keep the compiled version of the .ml file"; "-dont-execute", Set dont_execute, " Don't execute the compiled file"; "-no-magic", Unit remove_mlpost_options, " Do not parse mlpost options, do not call Metapost.dump"; "-contrib", String add_contrib, " Compile with the specified contrib" ]@(if not_cairo then ["-cairo" , Unit nocairo, " Mlpost has not been compiled with the cairo backend"; "-t1disasm" , Unit nocairo, " Mlpost has not been compiled with the cairo backend"; ] else []) @(List.map wrap_option Mlpost_desc_options.spec)) let () = Arg.parse spec add_file "Usage: mlpost [options] files..." exception Command_failed of int let command' ?inv ?outv s = let s = Misc.call_cmd ?inv ?outv ~verbose:!verbose s in if s <> 0 then raise (Command_failed s) let command ?inv ?outv s = try command' ?inv ?outv s with Command_failed s -> exit s let execute ?outv cmd = let cmd = execopt cmd in if !dont_execute then (if !verbose then printf "You can execute the program with :@.%s" cmd) else command ?outv cmd let normalize_filename s = if Filename.is_relative s then "./"^s else s let get_exec_name compile_name = match compile_name with | None -> Filename.temp_file "mlpost" "" | Some s -> normalize_filename s let try_remove s = try Sys.remove s with _ -> () let ocaml_generic compiler args = let s = get_exec_name !compile_name in let cmd = compiler ^ " -w -58 -o " ^ s ^ " " ^ String.concat " " args in command ~outv:true cmd; execute ~outv:true s; match !compile_name with | None -> if !dont_clean then () else Sys.remove s | Some s -> () let ocaml = ocaml_generic Version.ocamlc let ocamlopt = ocaml_generic Version.ocamlopt let ocamlbuild args exec_name = let args = if !verbose then "-classic-display" :: args else " -quiet"::args in command ~outv:true ("ocamlbuild " ^ String.concat " " args ^ exec_name); execute ~outv:true ("_build/"^exec_name); (match !compile_name with | None -> () | Some s -> command ("cp _build/" ^ exec_name ^ " " ^ s)) (* I think we should never call ocamlbuild -clean, maybe only remove the * symlink -- Johannes *) (* if !dont_clean then () else command "ocamlbuild -clean" *) let compile f = let bn = Filename.chop_extension f in if !use_ocamlbuild then let ext = if !native then ".native" else ".byte" in let exec_name = bn ^ ext in try ocamlbuild (build_args () @ ["-no-links";!ccopt]) exec_name with Command_failed out -> exit out else let ext = if !native then ".cmxa" else ".cma" in let args = build_args ~ext () @ [!ccopt; f] in if !native then ocamlopt args else ocaml args; if not !dont_clean then List.iter (fun suf -> try_remove (bn^suf)) [".cmi";".cmo";".cmx";".o"] let () = Queue.iter compile files mlpost-0.8.2/transform.ml000066400000000000000000000031341306046515300154100ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Types type t' = matrix type matrix = t' type t = t' list let scaled = Matrix.scale let rotated f = Matrix.rotation (Num.deg2rad f) let shifted = Matrix.translation let slanted = Matrix.slanted let xscaled = Matrix.xscaled let yscaled = Matrix.yscaled let zscaled = Matrix.zscaled let reflect = Matrix.reflect let rotate_around p f = Matrix.rotate_around p (Num.deg2rad f) let explicit t = t (* applied the transformations in the order of the list *) let id = [] mlpost-0.8.2/tree.ml000066400000000000000000000214061306046515300143360ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Command open Helpers open Path open Num open Num.Infix type arrow_style = Directed | Undirected type edge_style = Straight | Curve | Square | HalfSquare type 'a tree = Node of 'a * ('a tree list) type extend = (Num.t * Num.t) list type 'a positionedtree = ('a * Num.t * Num.t) tree let movetree (Node((label,x,y),subtrees)) dx = Node((label,((+/) x dx),y),subtrees) let moveextend (e:extend) (x:Num.t) : extend = List.map (fun (p,q) -> (((+/) p x),((+/) q x))) e let rec merge a1 a2 = match a1,a2 with |[],rt -> rt |lt,[] -> lt |(l,_)::t1,(_,r)::t2 -> (l,r)::(merge t1 t2) let mergelist l = List.fold_right merge l [] let rec fit cs (a1:extend) (a2: extend) : Num.t = match a1,a2 with |(_,r)::t1,(l,_)::t2 -> maxn (fit cs t1 t2) ((+/) ((-/) r l) cs) |_ -> bp 0. let fitlistl cs (l: extend list) :(Num.t list) = let rec fitlistaux acc li = match li with |[] -> [] |e::res -> let x = fit cs acc e in x::(fitlistaux (merge acc (moveextend e x)) res) in fitlistaux [] l let fitlistr cs (l: extend list) :(Num.t list) = let rec fitlistaux acc li = match li with |[] -> [] |e::res -> let x = neg (fit cs e acc) in x::(fitlistaux (merge (moveextend e x) acc) res) in List.rev (fitlistaux [] (List.rev l)) let mean x y = ((//) ((+/) x y) (bp 2.)) let fitlist cs (l: extend list) :(Num.t list) = List.map2 mean (fitlistl cs l) (fitlistr cs l) let bfs t = let rec bfs_aux lesmax m current next = match current with |[] -> if next=[] then List.rev (m :: lesmax) else bfs_aux (m::lesmax) (bp 0.) next [] |Node(x,tl)::cl -> let ((b,_),_,_) = x in let m = maxn m (Box.height b) in bfs_aux lesmax m cl (tl@next) in bfs_aux [] (bp 0.) [t] [] let rec dfs lesmax t = match t,lesmax with |Node((b,x,_),tl),m::mres -> Node((b,x,m),List.map (dfs mres) tl) |_,[]-> failwith "impossible" type node_info = { ls:Num.t; cs:Num.t; arrow_style:arrow_style; edge_style:edge_style; stroke:Color.t option; pen: Pen.t option; sep: Num.t option; lab: (Command.position * Picture.t) list option; } let dummy_info = { ls = zero; cs = zero; arrow_style = Directed; edge_style = Straight; stroke = None; pen = None; sep = None; lab = None } let design tree = let rec designaux (Node((b,ni) as label, subtrees)) = let trees,extends = List.split (List.map designaux subtrees) in let positions = fitlist ni.cs extends in let ptrees = List.map2 movetree trees positions in let pextends = List.map2 moveextend extends positions in let w = divf (Box.width b) 2. in let resultextend = (neg w, w) :: mergelist pextends in let resulttree = Node((label,bp 0.,bp 0.),ptrees) in resulttree,resultextend in let thetree = fst (designaux tree) in let maxlistheight = bfs thetree in dfs maxlistheight thetree (* drawing *) let strip ?sep p = match sep with | None -> p | Some n -> Path.strip n p let cpath ?style ?outd ?ind ?sep a b = let r,l = outd, ind in let p = pathk ?style [knotp ?r (Box.ctr a); knotp ?l (Box.north b)] in strip ?sep (cut_before (Box.bpath a) p) let box_arrow ?color ?brush ?pen ?dashed ?style ?outd ?ind ?sep a b = Arrow.simple ?color ?brush ?pen ?dashed (cpath ?style ?outd ?ind ?sep a b) let box_line ?color ?brush ?pen ?dashed ?style ?outd ?ind ?sep a b = draw ?color ?brush ?pen ?dashed (cpath ?style ?outd ?ind ?sep a b) let arc astyle estyle ?stroke ?brush ?pen ?sep ?lab b1 b2 = let x1,y1 = let p = Box.ctr b1 in Point.xpart p, Point.ypart p and x2,y2 = let p = Box.north b2 in Point.xpart p, Point.ypart p in let boxdraw, linedraw = match astyle with | Directed -> box_arrow ?color:stroke ?brush ?pen ?sep, Arrow.simple ?color:stroke ?brush ?pen | Undirected -> box_line ?color:stroke ?brush ?pen ?sep, draw ?color:stroke ?brush ?pen in let drawlab b1 b2 = function | None -> nop | Some (pos, lab) -> let p = Box.cpath b1 b2 in label ~pos lab (Path.point 0.5 p) in match estyle with | Straight -> boxdraw ~style:jLine b1 b2 ++ drawlab b1 b2 lab | Curve -> let p1, p2 = Box.ctr b1, Box.ctr b2 in let corner = Point.pt (x2-/(x2-/x1) /./ 4.,(y1+/y2) /./ 2.) in let p = pathk ~style:jCurve (knotlist [noDir, p1, vec (Point.sub corner p1); noDir, corner, noDir; vec (Point.sub p2 corner), p2, noDir]) in let parrow = cut_after (Box.bpath b2) (cut_before (Box.bpath b1) p) in linedraw (strip ?sep parrow) | Square -> let corner = Point.pt (x2,y1) in let p = pathp ~style:jLine [Box.ctr b1; corner; Box.ctr b2] in let parrow = cut_after (Box.bpath b2) (cut_before (Box.bpath b1) p) in linedraw (strip ?sep parrow) | HalfSquare -> let m = (y1+/y2) /./ 2. in let corner1, corner2 = Point.pt (x1,m), Point.pt (x2,m) in let p = pathp ~style:jLine [Box.ctr b1; corner1; corner2; Box.ctr b2] in let parrow = cut_after (Box.bpath b2) (cut_before (Box.bpath b1) p) in linedraw (strip ?sep parrow) let is_leaf x = Array.length (Box.elts x ) = 1 let root x = (* if this access is invalid, the box has not been created using * [leaf], [node] or [bin] *) Box.nth 0 x let children x = if is_leaf x then [] else Box.elts_list (Box.nth 1 x) type t = (Box.t * node_info) tree let leaf b = Node ((b, dummy_info), []) let node ?(ls=bp 20.) ?(cs=bp 3.) ?(arrow_style=Directed) ?(edge_style=Straight) ?stroke ?brush ?pen ?sep b l = Node ((b, {ls = ls; cs = cs; arrow_style = arrow_style; edge_style = edge_style; stroke = stroke; pen = pen; sep = sep; lab = None}), l) let nodel ?(ls=bp 20.) ?(cs=bp 3.) ?(arrow_style=Directed) ?(edge_style=Straight) ?stroke ?brush ?pen ?sep b l = Node ((b, { ls = ls; cs = cs; arrow_style = arrow_style; edge_style = edge_style; stroke = stroke; pen = pen; sep = sep; lab = Some (List.map snd l)}), List.map fst l) let bin ?ls ?cs ?arrow_style ?edge_style ?stroke ?brush ?pen ?sep s x y = node ?ls ?cs ?arrow_style ?edge_style ?stroke ?brush ?pen ?sep s [x;y] let to_box t : Box.t = let rec draw x y (Node (((b, ni), dx, dy), tl)) = let {stroke=stroke; pen=pen; sep=sep} = ni in let x' = addn x dx in let y' = subn y (divf (Box.height b) 2.)in let y2 = subn y (maxn dy ni.ls) in let b = Box.group [Box.center (Point.pt (x', y')) b; Box.group (List.map (draw x' y2) tl)] in let draw_arcs tree = match ni.lab with | None -> Command.iterl (fun child -> arc ~brush:(Types.mkBrush stroke pen None) ?sep ni.arrow_style ni.edge_style (root tree) (root child)) (children tree) | Some lab -> Command.iterl (fun (child, lab) -> arc ~brush:(Types.mkBrush stroke pen None) ?sep ~lab ni.arrow_style ni.edge_style (root tree) (root child)) (List.combine (children tree) lab) in Box.set_post_draw draw_arcs b in draw zero zero (design t) let draw ?debug t = Box.draw ?debug (to_box t) module Simple = struct type t = Box.t let leaf s = Box.group [s] let node ?(ls=Num.bp 12.) ?(cs=Num.bp 5.) ?(arrow_style=Directed) ?(edge_style=Straight) ?stroke ?brush ?pen ?sep ?(valign=`Center) ?(halign=`North) s l = let l = Box.hbox ~padding:cs ~pos:halign l in let tree = Box.vbox ~padding:ls ~pos:valign [s;l] in Box.set_post_draw (fun tree -> (Command.iterl (fun child -> arc ?stroke ?brush ?pen ?sep arrow_style edge_style (root tree) (root child)) (children tree))) tree let bin ?ls ?cs ?arrow_style ?edge_style ?stroke ?brush ?pen ?sep s x y = node ?ls ?cs ?arrow_style ?edge_style ?stroke ?brush ?pen ?sep s [x;y] let to_box b = b let draw = Box.draw end mlpost-0.8.2/tree_adv.ml000066400000000000000000000122611306046515300151670ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type 'a t = Node of 'a * 'a t list let rec map f (Node (x,l)) = Node (f x, List.map (map f) l) let rec map2 f (Node (x,l1)) (Node (y,l2)) = Node (f x y, List.map2 (map2 f) l1 l2) let rec combine (Node (x,l1)) (Node (y,l2)) = Node ((x,y), List.map2 combine l1 l2) let rec split (Node ((x,y),l)) = let l1,l2 = List.split (List.map split l) in Node (x,l1), Node (y,l2) let rec fold f acc (Node (x,l)) = let acc = List.fold_left (fold f) acc l in f acc x let rec fold_child f acc (Node (x,l)) = List.fold_left (fun acc (Node(y,_) as n) -> fold_child f (f acc x y) n) acc l let filter_option f t = let rec aux (Node (x,l)) = match f x with | None -> None | Some x -> let l = List.map aux l in let l = List.filter (function None -> false | Some _ -> true) l in let l = List.map (function None -> assert false | Some x -> x) l in Some (Node (x,l)) in match aux t with | None -> invalid_arg "Tree_adv.filter" | Some x -> x let filter f t = filter_option (fun a -> if f a then None else Some a) t let root_map f t = let rec aux r (Node (x,l)) = Node (f r x, List.map (aux (Some x)) l) in aux None t let map_children f t = let rec aux (Node (x,l)) = let child = List.map (function Node (x,_) -> x) l in Node (f x child, List.map aux l) in aux t module Place (X : Signature.Boxlike) = struct let gen_place ~place t = let box_from_a z = Box.empty ~width:(X.width z) ~height:(X.height z) () in let box_tree = map box_from_a t in let b = place box_tree in map2 (fun z e -> X.set_pos (Box.ctr (Box.sub e b)) z) t box_tree let place ?(cs=Num.bp 5.) ?(ls=Num.bp 12.) ?(valign=`Center) ?(halign=`North) t = let rec aux (Node (x,l)) = let l = Box.hbox ~padding:cs ~pos:halign (List.map aux l) in Box.vbox ~padding:ls ~pos:valign [x;l] in aux t let place ?ls ?cs ?valign ?halign t = gen_place ~place:(place ?ls ?cs ?valign ?halign) t end open Command let draw to_box t = fold (fun acc x -> acc ++ Box.draw (to_box x)) Command.nop t let gen_draw_arrows default ~style ~corner t = root_map (fun a b -> match a with | None -> default | Some a -> style (corner `South a) (corner `North b)) t let wrap_whs_box give_box mod_box f = let width a = Box.width (give_box a) in let height a = Box.height (give_box a) in let set_pos p a = mod_box a (Box.center p (give_box a)) in f ~width ~height ~set_pos let wrap_corner_box give_box f = let corner p a = Box.corner p (give_box a) in f ~corner module Overlays = struct type interval = | Bet of int * int (** [|a,b|] *) | Bef of int (** ]|-oo,a|] *) | Aft of int (** [|a,+oo|[ *) | Nev (** emptyset *) | Alw (** N *) let in_interval i = function | Bet (x,y) when x<=i && i<=y -> true | Bef x when i<=x -> true | Aft x when x<=i -> true | Alw -> true | _ -> false let min_interval n = function | Bet (a,_) -> min a n | Bef a -> min a n | Aft a -> min a n | _ -> n let max_interval n = function | Bet (_,b) -> max b n | Bef b -> max b n | Aft b -> max b n | _ -> n let min_tree to_interval t = let f n a = min_interval n (to_interval a) in fold f max_int t let max_tree to_interval t = let f n a = max_interval n (to_interval a) in fold f min_int t type 'a spec = (interval * 'a) list let rec assoq n = function | [] -> raise Not_found | (i,a)::l when in_interval n i -> a | _::l -> assoq n l let max to_num = function | [] -> invalid_arg "Tree_adv.Overlays.width" | (_,a)::l -> List.fold_left (fun w (_,p) -> Num.maxn w (to_num p)) (to_num a) l let set_pos sp pos = List.map (fun (i,b) -> i,sp pos b) end module Overlays_Boxlike (X : Signature.Boxlike) : Signature.Boxlike with type t = X.t Overlays.spec = struct open Overlays type t = X.t spec let width = max X.width let height = max X.height let set_pos = set_pos X.set_pos end mlpost-0.8.2/triangle.ml000066400000000000000000000076621306046515300152140ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Num open Command open Color type t = Box.t let draw = Box.draw (** width defaults to depth *) let create ?brush ?(stroke=Some black) ?pen ?dash ?fill ?left ?right ?width ~depth () = let width = match width with None -> depth | Some w -> w in let xl, xr = match left, right with | None, None -> -.0.5, 0.5 | Some l, None -> -. l, 1. -. l | None, Some r -> r -. 1., r | Some l, Some r -> let s = l +. r in -. l /. s, r /. s in let xl = xl *. width in let xr = xr *. width in let xmin = min 0. xl in let width = max 0. xr -. xmin in let dx = width /. 2. +. xmin in let height = depth in let p0 = Point.pt ( -. dx, height /. 2.) in let p1 = Point.pt (xl -. dx, -. height /. 2.) in let p2 = Point.pt (xr -. dx, -. height /. 2.) in let p = Path.pathp ~style:Path.jLine ~cycle:Path.jLine [p0; p1; p2] in let f _ _ = width, depth, p in let style = Box.Custom f in let b = Box.empty ?brush ~stroke ?pen ?dash ?fill ~style () in let b = Box.setp "root" p0 b in let b = Box.setp "bottom_left" p1 b in let b = Box.setp "bottom_right" p2 b in b let root = Box.getp "root" let bottom_left = Box.getp "bottom_left" let bottom_right = Box.getp "bottom_right" let root_label ?(pos=`Top) label t = Box.add_post_draw (fun b -> Command.label ~pos label (root b)) t let tex_root_label ?pos s t = root_label ?pos (Picture.tex s) t (** point (x,depth) in a term *) let x_depth ?(x=0.5) ?(depth=1.) t2 = let bl2 = bottom_left t2 in let br2 = bottom_right t2 in let x = Point.xpart bl2 +. x *. (Point.xpart br2 -. Point.xpart bl2) in let y = Point.ypart bl2 in let p = Point.pt (x, y) in let r2 = root t2 in Point.add r2 (Point.mult depth (Point.sub p r2)) let label ?x ?(depth=0.7) ?pos label t = Box.add_post_draw (fun t -> let p = x_depth ?x ~depth t in Command.label ?pos label p) t let tex_label ?x ?depth ?pos s t = label ?x ?depth ?pos (Picture.tex s) t (** move root of t1 to point (depth,x) in t2 *) let anchor ?x ?depth t2 t1 = let p = x_depth ?x ?depth t2 in Box.shift (Point.sub p (root t1)) t1 let pose ?x ?depth t2 t1 = let p = x_depth ?x ?depth t2 in Box.shift (Point.sub p (Box.south t1)) t1 (* FIXME: rather middle of bl and br? *) let pose_left ?x ?depth t2 t1 = let p = x_depth ?x ?depth t2 in Box.shift (Point.sub p (bottom_left t1)) t1 let pose_right ?x ?depth t2 t1 = let p = x_depth ?x ?depth t2 in Box.shift (Point.sub p (bottom_right t1)) t1 let pic ?brush ?stroke ?pen ?dash ?fill ?(dx=bp 1.) ?(dy=bp 1.) pic = let width = 2. *. (Picture.width pic +. 2. *. dx) in let depth = 2. *. (Picture.height pic +. 2. *. dy) in let t = create ?brush ?stroke ?pen ?dash ?fill ~width ~depth () in label ~depth:0.75 pic t let tex ?brush ?stroke ?pen ?dash ?fill ?dx ?dy s = pic ?brush ?stroke ?pen ?dash ?fill ?dx ?dy (Picture.tex s) mlpost-0.8.2/types.ml000066400000000000000000000463451306046515300145540ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type name = string include Concrete_types type corner = [ | `Northwest | `Northeast | `Southwest | `Southeast | `Upleft | `Upright | `Lowleft | `Lowright | `Upperleft | `Upperright | `Lowerleft | `Lowerright | `Topleft | `Topright | `Bottomleft | `Bottomright ] type corner_red = [ | `Northwest | `Northeast | `Southwest | `Southeast ] type hposition = [ `Center | `West | `East | `Left | `Right ] type vposition = [ `Center | `North | `South | `Top | `Bot (** deprecated *) | `Bottom ] type hposition_red = [ `Center | `West | `East ] type vposition_red = [ `Center | `North | `South ] type position = [ | hposition | vposition | corner ] type position_red = [ | hposition_red | vposition_red | corner_red ] open Hashcons type num = float type point = Point_lib.t and on_off_node = | On of num | Off of num and on_off = on_off_node hash_consed and direction_node = | Vec of point | Curl of float | NoDir and direction = direction_node hash_consed and joint_node = | JLine | JCurve | JCurveNoInflex | JTension of float * float | JControls of point * point and joint = joint_node hash_consed and knot_node = { knot_in : direction ; knot_p : point ; knot_out : direction } and knot = knot_node hash_consed and metapath_node = | MPAConcat of knot * joint * metapath | MPAKnot of knot | MPAAppend of metapath * joint * metapath | MPAofPA of path (*| MPATransformed of metapath * transform*) and metapath = metapath_node hash_consed and path_node = | PAofMPA of metapath | MPACycle of direction * joint * metapath | PAFullCircle | PAHalfCircle | PAQuarterCircle | PAUnitSquare | PATransformed of path * transform | PACutAfter of path * path | PACutBefore of path * path | PABuildCycle of path list | PASub of num * num * path | PABBox of commandpic and path = path_node hash_consed and matrix = Matrix.t and transform = Matrix.t list and dash_node = | DEvenly | DWithdots | DScaled of num * dash | DShifted of point * dash | DPattern of on_off list and dash = dash_node hash_consed and pen_node = | PenCircle | PenSquare | PenFromPath of path | PenTransformed of pen * transform and pen = pen_node hash_consed and picture_node = | PITex of string | PITransformed of commandpic * transform | PIClip of commandpic * path and picture = picture_node hash_consed and command_node = | CDraw of path * brush | CFill of path * color option | CLabel of commandpic * position * point | CDotLabel of commandpic * position * point | CExternalImage of string * spec_image and spec_image = [ `None | `Width of num (* keep the proportion of the image *) | `Height of num | `Inside of num * num (* must be inside a box of this height and width *) | `Exact of num * num] and command = command_node hash_consed and commandpic_node = | Picture of picture | Command of command | Seq of commandpic list and commandpic = commandpic_node hash_consed and brush_node = {pen : pen option; dash : dash option; color : color option} and brush = brush_node hash_consed let hash_float : float -> int = Hashtbl.hash let hash_piccorner : corner -> int = Hashtbl.hash let hash_string : string -> int = Hashtbl.hash let combine n acc = acc * 65599 + n let combine2 n acc1 acc2 = combine n (combine acc1 acc2) let combine3 n acc1 acc2 acc3 = combine n (combine acc1 (combine acc2 acc3)) let combine4 n acc1 acc2 acc3 acc4 = combine n (combine3 acc1 acc2 acc3 acc4) let num = hash_float let point { Point_lib.x = x ; y = y } = combine2 12 (num x) (num y) let transform' { Matrix.xx = xx; yx = yx; xy = xy; yy = yy; x0 = x0; y0 = y0} = combine4 52 (hash_float xx) (hash_float yx) (hash_float xy) (combine3 53 (hash_float yy) (hash_float x0) (hash_float y0)) let rec hash_list h l = match l with | [] -> 54 | x::xs -> combine2 55 (h x) (hash_list h xs) let transform = hash_list transform' let on_off = function | On n -> combine 65 (num n) | Off n -> combine 66 (num n) let direction = function | Vec p -> combine 61 (point p) | Curl f -> combine 62 (hash_float f) | NoDir -> 63 let joint = function | JLine -> 67 | JCurve -> 68 | JCurveNoInflex -> 69 | JTension(f1,f2) -> combine2 70 (hash_float f1) (hash_float f2) | JControls(p1,p2) -> combine2 71 (point p1) (point p2) let knot k = combine3 64 k.knot_in.hkey (point k.knot_p) k.knot_out.hkey let metapath = function | MPAConcat(k,j,p) -> combine3 85 k.hkey j.hkey p.hkey | MPAAppend(p1,j,p2) -> combine3 86 p1.hkey j.hkey p2.hkey | MPAofPA p -> combine 87 p.hkey | MPAKnot k -> combine 88 k.hkey let path = function | PAofMPA p -> combine 89 p.hkey | MPACycle(d,j,p) -> combine3 90 d.hkey j.hkey p.hkey | PAFullCircle -> 24 | PAHalfCircle -> 25 | PAQuarterCircle -> 26 | PAUnitSquare -> 27 | PATransformed(p,tr) -> combine2 28 p.hkey (transform tr) | PACutAfter(p,q) -> combine2 32 p.hkey q.hkey | PACutBefore(p,q) -> combine2 33 p.hkey q.hkey | PABuildCycle l -> List.fold_left (fun acc p -> combine2 35 acc p.hkey) 34 l | PASub(f1,f2,p) -> combine3 36 (hash_float f1) (hash_float f2) p.hkey | PABBox p -> combine 37 p.hkey let picture = function | PITex s -> combine 38 (hash_string s) | PITransformed(p,tr) -> combine2 40 p.hkey (transform tr) | PIClip(p,q) -> combine2 42 p.hkey q.hkey let commandpic = function | Picture pic -> combine 91 pic.hkey | Command c -> combine 92 c.hkey | Seq l -> List.fold_left (fun acc t -> combine2 93 acc t.hkey) 94 l let dash = function | DEvenly -> 72 | DWithdots -> 73 | DScaled(f,d) -> combine2 74 (num f) d.hkey | DShifted(p,d) -> combine2 75 (point p) d.hkey | DPattern l -> List.fold_left (fun acc o -> combine2 76 acc o.hkey) 77 l let pen = function | PenCircle -> 78 | PenSquare -> 79 | PenFromPath p -> combine 80 p.hkey | PenTransformed(p,tr) -> combine2 81 p.hkey (transform tr) let hash_opt f = function | None -> 83 | Some o -> combine 84 (f o) let hash_key x = x.hkey let hash_color = Hashtbl.hash let hash_position = Hashtbl.hash let hash_spec_image = Hashtbl.hash let command = function | CDraw(pa,b) -> combine2 43 pa.hkey b.hkey | CFill(p,c) -> combine2 46 p.hkey (hash_color c) | CLabel(pic,pos,poi) -> combine3 47 pic.hkey (hash_position pos) (point poi) | CDotLabel(pic,pos,poi) -> combine3 48 pic.hkey (hash_position pos) (point poi) | CExternalImage (filename,spec) -> combine2 52 (hash_string filename) (hash_spec_image spec) let brush b = combine3 85 (hash_opt hash_color b.color) (hash_opt hash_key b.pen) (hash_opt hash_key b.dash) (** equality *) (* equality of floats with correct handling of nan *) let eq_float (f1:float) (f2:float) = Pervasives.compare f1 f2 == 0 let eq_num = eq_float let eq_point (a : point) (b : point) = Pervasives.compare a b == 0 let eq_matrix (a : matrix) (b : matrix) = Pervasives.compare a b == 0 (* we enforce to use physical equality only on hash-consed data of the same type *) let eq_hashcons (x:'a hash_consed) (y:'a hash_consed) = x == y let rec eq_hashcons_list (x:'a hash_consed list) (y:'a hash_consed list) = match x,y with | [], [] -> true | h1::t1,h2::t2 -> h1 == h2 && eq_hashcons_list t1 t2 | _ -> false let rec eq_list eq x y = match x, y with | [], [] -> true | x::xs, y::ys -> eq x y && eq_list eq xs ys | _, _ -> false let eq_transform = eq_list eq_matrix let eq_opt f o1 o2 = match o1,o2 with | None,None -> true | Some x1, Some x2 -> f x1 x2 | _ -> false let eq_color c1 c2 = Pervasives.compare c1 c2 = 0 let eq_pen_node p1 p2 = match p1, p2 with | PenCircle, PenCircle | PenSquare, PenSquare -> true | PenFromPath p1, PenFromPath p2 -> eq_hashcons p1 p2 | PenTransformed(p1,tr1), PenTransformed(p2,tr2) -> eq_hashcons p1 p2 && eq_transform tr1 tr2 | _ -> false let eq_dash_node d1 d2 = match d1, d2 with | DEvenly, DEvenly | DWithdots, DWithdots -> true | DScaled(f1,d1), DScaled(f2,d2) -> eq_num f1 f2 && eq_hashcons d1 d2 | DShifted(p1,d1), DShifted(p2,d2) -> eq_point p1 p2 && eq_hashcons d1 d2 | DPattern l1, DPattern l2 -> eq_hashcons_list l1 l2 | _ -> false let eq_brush_node b1 b2 = eq_opt eq_color b1.color b2.color && eq_opt eq_hashcons b1.pen b2.pen && eq_opt eq_hashcons b1.dash b2.dash let eq_on_off o1 o2 = match o1,o2 with | Off n1, Off n2 | On n1, On n2 -> eq_num n1 n2 | _ -> false let eq_position (p1:position) (p2:position) = p1 == p2 (* correct because this type contains only constants *) let eq_metapath_node p1 p2 = match p1,p2 with | MPAConcat(k1,j1,p1),MPAConcat(k2,j2,p2) -> eq_hashcons k1 k2 && eq_hashcons j1 j2 && eq_hashcons p1 p2 | MPAKnot(k1), MPAKnot(k2) -> eq_hashcons k1 k2 | MPAAppend(p11,j1,p12),MPAAppend(p21,j2,p22) -> eq_hashcons p11 p21 && eq_hashcons j1 j2 && eq_hashcons p12 p22 | MPAofPA p1, MPAofPA p2 -> eq_hashcons p1 p2 | _ -> false let eq_path_node p1 p2 = match p1,p2 with | PAofMPA p1, PAofMPA p2 -> eq_hashcons p1 p2 | MPACycle(d1,j1,p1),MPACycle(d2,j2,p2) -> eq_hashcons d1 d2 && eq_hashcons j1 j2 && eq_hashcons p1 p2 | PAFullCircle, PAFullCircle | PAHalfCircle, PAHalfCircle | PAQuarterCircle, PAQuarterCircle | PAUnitSquare, PAUnitSquare -> true | PATransformed(p1,tr1),PATransformed(p2,tr2) -> eq_hashcons p1 p2 && eq_transform tr1 tr2 | PACutAfter(p11,p12),PACutAfter(p21,p22) | PACutBefore(p11,p12),PACutBefore(p21,p22) -> eq_hashcons p11 p21 && eq_hashcons p12 p22 | PABuildCycle(l1),PABuildCycle(l2) -> eq_hashcons_list l1 l2 | PASub(f11,f12,p1), PASub(f21,f22,p2) -> eq_num f11 f21 && eq_num f12 f22 && eq_hashcons p1 p2 | PABBox(p1), PABBox(p2) -> eq_hashcons p1 p2 | _ -> false let eq_picture_node p1 p2 = match p1,p2 with | PITex s1, PITex s2 -> (* it actually happens that the same text appears twice *) s1<>"" && s1=s2 | PITransformed(p1,tr1), PITransformed(p2,tr2) -> eq_hashcons p1 p2 && eq_transform tr1 tr2 | PIClip(pi1,pa1), PIClip(pi2,pa2) -> eq_hashcons pi1 pi2 && eq_hashcons pa1 pa2 | _ -> false let eq_knot_node k1 k2 = eq_hashcons k1.knot_in k2.knot_in && eq_point k1.knot_p k2.knot_p && eq_hashcons k1.knot_out k2.knot_out let eq_joint_node j1 j2 = match j1,j2 with | JLine, JLine | JCurve, JCurve | JCurveNoInflex, JCurveNoInflex -> true | JTension(f11,f12), JTension(f21,f22) -> eq_float f11 f21 && eq_float f12 f22 | JControls(p11,p12), JControls(p21,p22) -> eq_point p11 p21 && eq_point p12 p22 | _ -> false let eq_direction_node d1 d2 = match d1,d2 with | Vec p1, Vec p2 -> eq_point p1 p2 | Curl f1, Curl f2 -> eq_float f1 f2 | NoDir, NoDir -> true | _ -> false let eq_command_node c1 c2 = match c1,c2 with | CDraw(p1,b1), CDraw(p2,b2) -> eq_hashcons p1 p2 && eq_hashcons b1 b2 | CFill(p1,c1), CFill(p2,c2) -> eq_hashcons p1 p2 && eq_opt eq_color c1 c2 | CLabel(pic1,pos1,poi1), CLabel(pic2,pos2,poi2) | CDotLabel(pic1,pos1,poi1), CDotLabel(pic2,pos2,poi2) -> eq_hashcons pic1 pic2 && eq_position pos1 pos2 && eq_point poi1 poi2 | _ -> false let eq_commandpic_node p1 p2 = match p1, p2 with | Picture p1, Picture p2 -> eq_hashcons p1 p2 | Command p1, Command p2 -> eq_hashcons p1 p2 | Seq l1, Seq l2 -> eq_hashcons_list l1 l2 | _ -> false (* smart constructors *) (* num *) let unsigned f x = (f x) land 0x3FFFFFFF (* knot *) module HashKnot = Hashcons.Make(struct type t = knot_node let equal = eq_knot_node let hash = unsigned knot end) let hashknot_table = HashKnot.create 257;; let hashknot = HashKnot.hashcons hashknot_table let mkKnot d1 p d2 = hashknot { knot_in = d1; knot_p = p; knot_out = d2 } (* metapath *) module HashMetaPath = Hashcons.Make(struct type t = metapath_node let equal = eq_metapath_node let hash = unsigned metapath end) let hashmetapath_table = HashMetaPath.create 257;; let hashmetapath = HashMetaPath.hashcons hashmetapath_table let mkMPAKnot k = hashmetapath (MPAKnot k) let mkMPAConcat k j p2 = hashmetapath (MPAConcat(k,j,p2)) let mkMPAAppend x y z = hashmetapath (MPAAppend (x,y,z)) let mkMPAofPA p = hashmetapath (MPAofPA p) (*val mkMPATransformed : path -> transform -> path*) (* path *) module HashPath = Hashcons.Make(struct type t = path_node let equal = eq_path_node let hash = unsigned path end) let hashpath_table = HashPath.create 257;; let hashpath = HashPath.hashcons hashpath_table let mkPAofMPA p = hashpath (PAofMPA p) let mkPAKnot k = mkPAofMPA (mkMPAKnot k) let mkPAConcat k j p2 = mkPAofMPA (mkMPAConcat k j (mkMPAofPA p2)) let mkMPACycle d j p1 = hashpath (MPACycle (d,j,p1)) let mkPACycle d j p1 = (mkMPACycle d j (mkMPAofPA p1)) let mkPAAppend x y z = mkPAofMPA (mkMPAAppend (mkMPAofPA x) y (mkMPAofPA z)) let mkPAFullCircle = hashpath (PAFullCircle) let mkPAHalfCircle = hashpath (PAHalfCircle) let mkPAQuarterCircle = hashpath (PAQuarterCircle) let mkPAUnitSquare = hashpath (PAUnitSquare) let mkPATransformed x y = hashpath (PATransformed (x,y)) let mkPACutAfter x y = hashpath (PACutAfter (x,y)) let mkPACutBefore x y = hashpath (PACutBefore (x,y)) let mkPABuildCycle l = hashpath (PABuildCycle l) let mkPASub x y z = hashpath (PASub (x,y,z)) let mkPABBox pic = hashpath (PABBox pic) (* joint *) module HashJoint = Hashcons.Make(struct type t = joint_node let equal = eq_joint_node let hash = unsigned joint end) let hashjoint_table = HashJoint.create 257;; let hashjoint = HashJoint.hashcons hashjoint_table let mkJCurve = hashjoint JCurve let mkJLine = hashjoint JLine let mkJCurveNoInflex = hashjoint JCurveNoInflex let mkJTension x y = hashjoint (JTension(x,y)) let mkJControls x y = hashjoint (JControls(x,y)) (* direction *) module HashDir = Hashcons.Make(struct type t = direction_node let equal = eq_direction_node let hash = unsigned direction end) let hashdir_table = HashDir.create 257;; let hashdir = HashDir.hashcons hashdir_table let mkNoDir = hashdir NoDir let mkVec p = hashdir (Vec p) let mkCurl f = hashdir (Curl f) (* picture *) module HashPicture = Hashcons.Make(struct type t = picture_node let equal = eq_picture_node let hash = unsigned picture end) let hashpicture_table = HashPicture.create 257;; let hashpicture = HashPicture.hashcons hashpicture_table let mkPITex s = hashpicture (PITex s) let mkPITransformed x y = hashpicture (PITransformed (x,y)) let mkPIClip p pic = hashpicture (PIClip(p,pic)) (* command *) module HashCommand = Hashcons.Make(struct type t = command_node let equal = eq_command_node let hash = unsigned command end) let hashcommand_table = HashCommand.create 257;; let hashcommand = HashCommand.hashcons hashcommand_table let mkCDraw x y = hashcommand (CDraw(x,y)) let mkCFill x y = hashcommand (CFill(x,y)) let mkCLabel x y z = hashcommand (CLabel(x,y,z)) let mkCDotLabel x y z = hashcommand (CDotLabel(x,y,z)) let mkCExternalImage f s = hashcommand (CExternalImage (f,s)) (* commandPic *) module HashCommandPic = Hashcons.Make (struct type t = commandpic_node let equal = eq_commandpic_node let hash = unsigned commandpic end) let hashcommandpic_table = HashCommandPic.create 257;; let hashcommandpic = HashCommandPic.hashcons hashcommandpic_table let mkPicture p = hashcommandpic (Picture p) let mkCommand p = hashcommandpic (Command p) let mkSeq l = hashcommandpic (Seq l) (* dash *) module HashDash = Hashcons.Make(struct type t = dash_node let equal = eq_dash_node let hash = unsigned dash end) let hashdash_table = HashDash.create 257;; let hashdash = HashDash.hashcons hashdash_table let mkDEvenly = hashdash DEvenly let mkDWithdots = hashdash DWithdots let mkDScaled x y = hashdash (DScaled(x,y)) let mkDShifted x y = hashdash (DShifted(x,y)) let mkDPattern l = hashdash (DPattern l) (* pen *) module HashPen = Hashcons.Make(struct type t = pen_node let equal = eq_pen_node let hash = unsigned pen end) let hashpen_table = HashPen.create 257;; let hashpen = HashPen.hashcons hashpen_table let mkPenCircle = hashpen PenCircle let mkPenSquare = hashpen PenSquare let mkPenFromPath p = hashpen (PenFromPath p) let mkPenTransformed x y = hashpen (PenTransformed(x,y)) (* brush *) module HashBrush = Hashcons.Make(struct type t = brush_node let equal = eq_brush_node let hash = unsigned brush end) let hashbrush_table = HashBrush.create 257;; let hashbrush = HashBrush.hashcons hashbrush_table let mkBrush c p d = hashbrush {pen = p;color=c;dash=d} let opt_def_node def = function | None -> def | Some s -> s.node let opt_def_map f def = function | None -> def | Some s -> f s let mkBrushOpt b c p d = let b = opt_def_node {color = None; pen = None; dash = None} b in let b = opt_def_map (fun x -> {b with color = Some x}) b c in let b = opt_def_map (fun x -> {b with pen = Some x}) b p in let b = opt_def_map (fun x -> {b with dash = Some x}) b d in hashbrush b (* on_off *) module HashOnOff = Hashcons.Make(struct type t = on_off_node let equal = eq_on_off let hash = unsigned on_off end) let hashon_off_table = HashOnOff.create 257;; let hashon_off = HashOnOff.hashcons hashon_off_table let mkOn n = hashon_off (On n) let mkOff n = hashon_off (Off n) let hreduce = function | `Center -> `Center | `Left | `West -> `West | `Right | `East -> `East let vreduce = function | `Center -> `Center | `Top | `North -> `North | `Bot | `Bottom | `South -> `South let corner_reduce = function | `Upleft | `Upperleft | `Topleft | `Northwest -> `Northwest | `Upright | `Upperright | `Topright | `Northeast -> `Northeast | `Lowleft | `Lowerleft | `Bottomleft | `Southwest -> `Southwest | `Lowright | `Lowerright | `Bottomright | `Southeast -> `Southeast let pos_reduce = function | #hposition as p -> hreduce p | #vposition as p -> vreduce p | #corner as p -> corner_reduce p let opposite_position (x: position): position_red = match pos_reduce x with | `Center -> `Center | `West -> `East | `East -> `West | `North -> `South | `South -> `North | `Northwest -> `Southeast | `Northeast -> `Southwest | `Southwest -> `Northeast | `Southeast -> `Northwest mlpost-0.8.2/types.mli000066400000000000000000000154241306046515300147170ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) type color = Concrete_types.color type name = string type corner = [ | `Northwest | `Northeast | `Southwest | `Southeast | `Upleft | `Upright | `Lowleft | `Lowright | `Upperleft | `Upperright | `Lowerleft | `Lowerright | `Topleft | `Topright | `Bottomleft | `Bottomright ] type corner_red = [ | `Northwest | `Northeast | `Southwest | `Southeast ] type hposition = [ `Center | `West | `East | `Left | `Right ] type vposition = [ `Center | `North | `South | `Top | `Bot (** deprecated *) | `Bottom ] type hposition_red = [ `Center | `West | `East ] type vposition_red = [ `Center | `North | `South ] type position = [ | hposition | vposition | corner ] type position_red = [ | hposition_red | vposition_red | corner_red ] open Hashcons type num = float type point = Point_lib.t and on_off_node = private | On of num | Off of num and on_off = on_off_node hash_consed and direction_node = private | Vec of point | Curl of float | NoDir and direction = direction_node hash_consed and joint_node = private | JLine | JCurve | JCurveNoInflex | JTension of float * float | JControls of point * point and joint = joint_node hash_consed and knot_node = private { knot_in : direction ; knot_p : point ; knot_out : direction } and knot = knot_node hash_consed and metapath_node = private | MPAConcat of knot * joint * metapath | MPAKnot of knot | MPAAppend of metapath * joint * metapath | MPAofPA of path (*| MPATransformed of metapath * transform*) and metapath = metapath_node hash_consed and path_node = private | PAofMPA of metapath | MPACycle of direction * joint * metapath | PAFullCircle | PAHalfCircle | PAQuarterCircle | PAUnitSquare | PATransformed of path * transform | PACutAfter of path * path | PACutBefore of path * path | PABuildCycle of path list | PASub of num * num * path | PABBox of commandpic and path = path_node hash_consed and matrix = Matrix.t and transform = Matrix.t list and dash_node = private | DEvenly | DWithdots | DScaled of num * dash | DShifted of point * dash | DPattern of on_off list and dash = dash_node hash_consed and pen_node = private | PenCircle | PenSquare | PenFromPath of path | PenTransformed of pen * transform and pen = pen_node hash_consed and picture_node = private | PITex of string | PITransformed of commandpic * transform | PIClip of commandpic * path and picture = picture_node hash_consed and command_node = private | CDraw of path * brush | CFill of path * color option | CLabel of commandpic * position * point | CDotLabel of commandpic * position * point | CExternalImage of string * spec_image and commandpic_node = private | Picture of picture | Command of command | Seq of commandpic list and commandpic = commandpic_node hash_consed and spec_image = [ `None | `Width of num (* keep the proportion of the image *) | `Height of num | `Inside of num * num (* must be inside a box of this height and width *) | `Exact of num * num] and command = command_node hash_consed and brush_node = {pen : pen option; dash : dash option; color : color option} and brush = brush_node hash_consed (* smart constructors *) (* knot *) val mkKnot : direction -> point -> direction -> knot (* metapath *) val mkMPAKnot : knot -> metapath val mkMPAConcat : knot -> joint -> metapath -> metapath val mkMPAAppend : metapath -> joint -> metapath -> metapath val mkMPAofPA : path -> metapath (*val mkMPATransformed : path -> transform -> path*) (* path *) val mkPAofMPA : metapath -> path val mkPAKnot : knot -> path val mkPAConcat : knot -> joint -> path -> path val mkPACycle : direction -> joint -> path -> path val mkMPACycle : direction -> joint -> metapath -> path val mkPAAppend : path -> joint -> path -> path val mkPAFullCircle : path val mkPAHalfCircle : path val mkPAQuarterCircle : path val mkPAUnitSquare : path val mkPATransformed : path -> transform -> path val mkPACutAfter : path -> path -> path val mkPACutBefore : path -> path -> path val mkPABuildCycle : path list -> path val mkPASub : num -> num -> path -> path val mkPABBox : commandpic -> path (* joint *) val mkJCurve : joint val mkJLine : joint val mkJCurveNoInflex : joint val mkJTension: float -> float -> joint val mkJControls: point -> point -> joint (* direction *) val mkNoDir : direction val mkVec : point -> direction val mkCurl : float -> direction (* picture *) val mkPITex : string -> picture val mkPITransformed : commandpic -> transform -> picture val mkPIClip : commandpic -> path -> picture (* command *) val mkCDraw: path -> brush -> command val mkCFill: path -> color option -> command val mkCLabel: commandpic -> position -> point -> command val mkCDotLabel: commandpic -> position -> point -> command val mkCExternalImage : string -> spec_image -> command (* commandpic *) val mkPicture : picture -> commandpic val mkCommand : command -> commandpic val mkSeq : commandpic list -> commandpic (* dash *) val mkDEvenly: dash val mkDWithdots: dash val mkDScaled: num -> dash -> dash val mkDShifted: point -> dash -> dash val mkDPattern: on_off list -> dash (* pen *) val mkPenCircle: pen val mkPenSquare: pen val mkPenFromPath: path -> pen val mkPenTransformed: pen -> transform -> pen (* brush *) val mkBrush: color option -> pen option -> dash option -> brush val mkBrushOpt : brush option -> color option -> pen option -> dash option -> brush (* on_off *) val mkOn : num -> on_off val mkOff : num -> on_off val pos_reduce : position -> position_red val corner_reduce : corner -> corner_red val vreduce : vposition -> vposition_red val hreduce : hposition -> hposition_red val opposite_position : position -> position_red mlpost-0.8.2/version.ml.in000066400000000000000000000042231306046515300154670ustar00rootroot00000000000000(**************************************************************************) (* *) (* Copyright (C) Johannes Kanig, Stephane Lescuyer *) (* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) # 16 "version.ml.in" let version = "@PACKAGE_VERSION@" let date = "@TODAY@" let ocamlopt = "@OCAMLOPT@" let ocamlc = "@OCAMLC@" let libdir = "@LIBDIR@" let include_string = "@INCLUDELIBS@" let cairolib = "@CAIROLIB@" let bitstringlib = "@BITSTRINGLIB@" let cairolablgtk2lib = "@CAIROLABLGTK2LIB@" let lablgtk2lib = "@LABLGTK2LIB@" let not_cairo = cairolib = "" let not_bitstring = bitstringlib = "" (* (contrib_name, (include_list,lib_list)) *) (* The second second composante is linked in reversed order (cma,cmxa) *) let append_dir = Metapost_tool.append_dir let libraries libdir = [ "dot", ([append_dir libdir "_dot"],["mlpost_dot"]); "lablgtk", ([append_dir libdir "_lablgtk";lablgtk2lib;cairolablgtk2lib], ["lablgtk"; "cairo_lablgtk"; "mlpost_lablgtk"; ]); "cairo", ([cairolib], ["bigarray";"cairo";]); "bitstring", ([bitstringlib], ["bitstring"]); "mlpost", ([libdir], ["mlpost"]); "mlpost_options", ([libdir], [ "mlpost_desc_options";"mlpost_options"]); "unix" , ([],["unix"]); ] mlpost-0.8.2/www/000077500000000000000000000000001306046515300136665ustar00rootroot00000000000000mlpost-0.8.2/www/Makefile000066400000000000000000000012221306046515300153230ustar00rootroot00000000000000 WWW = /users/www-perso/projets/mlpost/ GENERATED := index.fr.html index.en.html index.de.html \ manual.fr.html manual.en.html manual.de.html ALL:= $(GENERATED) slides-jfla.pdf mlpost-jfla.pdf install: all cp -f --parents $(ALL) $(WWW) export: all scp $(ALL) filliatr@pl-ssh2.lri.fr:/users/www-perso/projets/mlpost/ all: $(ALL) $(GENERATED): macros.prehtml version.prehtml # RULES YAMLPP=yamlpp macros.prehtml version.prehtml .SUFFIXES: .html .prehtml .fr.html .en.html %.fr.html: %.prehtml $(YAMLPP) -l fr $< -o $@ %.en.html: %.prehtml $(YAMLPP) -l en $< -o $@ %.de.html: %.prehtml $(YAMLPP) -l de $< -o $@ clean: rm -f $(GENERATED) mlpost-0.8.2/www/index.prehtml000066400000000000000000000076161306046515300164040ustar00rootroot00000000000000 <#iso> Mlpost

Mlpost

<#fr> Mlpost est une interface <#ocaml> pour <#metapost>. <#en> Mlpost is an <#ocaml> interface to <#metapost>. <#de> Mlpost ist ein <#ocaml> Interface fr <#metapost>.

no image

<#fr>Exemples<#en>Examples<#de>Beispiele

<#fr>Ne manquez pas notre galerie d'exemples. <#en>Have a look at our examples. <#de>Beispiele von Mlpost-Programmen.

Documentation

<#fr>Il existe un petit manuel. <#en>There is a small manual. <#de>Es gibt ein kleines Handbuch. <#fr>Il y a galement une FAQ. <#en>There also is a FAQ. <#de>Es gibt ebenfalls eine FAQ.

<#fr>Parcourir l'API. Note : Tous les modules sont regroups l'intrieur d'un unique module Mlpost. <#en>Browse the API. Note that all modules are packaged into a single module Mlpost. <#de>Werfen Sie einen Blick auf die API. Alle Module befinden sich in einem Hauptmodul Mlpost.

<#fr>Notre article et nos slides des JFLA sont disponibles.

Download

<#fr> La version courante est <#version>. <#en> Current version is <#version>. <#de> Die aktuelle Version ist <#version>.

CHANGES

<#fr>Contributions<#en>Contributions<#de>nderungsvorschlge

<#fr> Si vous voulez contribuer, le projet Mlpost utilise github pour son dveloppement. <#en> If you want to contribute, the Mlpost project uses github for its development. <#de> Falls Sie zum Mlpost-Projekt beitragen wollen, knnen Sie mit diesem Befehl einen Anonymen Zugang zum github-Repository bekommen:

<#fr>Auteurs<#en>Authors<#de>Autoren

<#fr>Mlpost est dvelopp par <#en>Mlpost is developed by <#de>Mlpost wird entwickelt von
Franais / English / Deutsch mlpost-0.8.2/www/macros.prehtml000066400000000000000000000005151306046515300165500ustar00rootroot00000000000000<#def iso> <#def metapost>Metapost <#def ocaml>Objective Caml mlpost-0.8.2/www/manual.prehtml000066400000000000000000000121501306046515300165370ustar00rootroot00000000000000 <#iso> Mlpost manual

<#en>Mlpost manual <#fr>Manuel Mlpost <#de>Mlpost Handbuch

<#en>There are really two ways of using Mlpost. The first one uses the command line tool mlpost and is more convenient. The second one uses only the API of Mlpost and can be used in situations where the mlpost command does not apply.

<#en>Using the Mlpost Tool <#fr>Utilisation <#de>Mlpost Schnittstelle

  1. <#en>Define your figures in an Ocaml file fig.ml. The Mlpost modules are packed in the top module Mlpost, so you probably want to open it right away. <#fr>Dfinir ses figures dans un fichier Ocaml fig.ml <#de>Definieren Sie Ihre Zeichnungen in einem Ocaml Programm fig.ml
             open Mlpost
             ...
    	 let fig_a = ...
    	 let fig_b = ...
    
    <#en>Each figure has type <#fr>Chaque figure a le type <#de>Jede Abbildung hat den Typ Command.t.
  2. <#en>Add some code to emit Metapost code, as follows <#fr>Ajouter du code pour la production du Metapost <#de>Fgen Sie den folgenden Code hinzu, der das Metapost Programm erzeugt
      
    	let () = Metapost.emit "file_a" fig_a
    	let () = Metapost.emit "file_b" fig_b
    
  3. <#en>Then run the mlpost program on this file <#fr>Lancer le programme mlpost sur ce fichier <#de>Fhren Sie das mlpost Programm auf dieser Datei aus, mit dem Kommando
           mlpost fig.ml
    
    <#en>It will create PostScript figures in files file_a.1, file_b.1, etc. <#fr>Les figures PostScript sont alors cres dans les fichiers file_a.1, file_b.1, etc. <#de>Die PostScript-Abbildungen werden in den Dateien file_a.1 file_b.1, usw abgespeichert.

Options

<#en>mlpost supports the following options: <#fr>mlpost accepte les options suivantes : <#de>mlpost akzeptiert die folgenden Optionen:
-pdf
<#en>creates .mps files instead of .1, for inclusion in LaTeX files compiled with pdflatex (the PostScript file is actually the same, but the suffix is used by pdflatex to identify PostScript produced by Metapost) <#fr>produit des fichiers .mps au lieu de .1, pour inclure dans du LaTeX compil avec pdflatex <#de>produziert .mps Dateien anstatt .1, zum Einfgen in LaTeX Dateien, die mit pdflatex kompiliert werden.

-latex main.tex
<#en>indicates the main LaTeX file, from which the prelude is extracted to be passed to Metapost (this way you can use macros, fonts and packages from your LaTeX document in your figures). main.tex has to contain at least a documentclass and the line "\begin{document}". The contents of this file are taken into account up to the "\begin{document}" part. <#fr>spcifie le fichier LaTeX principal, dont le prlude est extrait et pass Metapost (on peut ainsi utiliser les macros, polices et paquets du document LaTeX en question). main.tex doit contenir au moins une commande documentclass et la commande "\begin{document}". <#de>spezifiziert die LaTeX-Hauptdatei, deren LaTeX-Prambel an Metapost weitergegeben wird. Auf diese Weise knnen die gleichen Makros, Fonts und LaTeX-Pakete wie im LaTeX-Dokument in den Abbildungen verwendet werden. Die Datei main.tex muss mindestens den documentclass Befehl und die Zeile "\begin{document}" enthalten.

<#en>Using only the API

<#en> The mlpost tool works on a modified version of your file, and this can be a problem sometimes. The following method is a way out, but you need to do a bit more things by hand.
  1. <#en> Follow steps 1 and 2 above.
  2. <#en> Instead of running mlpost on your file, add the following additional lines to your program:
    let () = Metapost.dump 
               ~prelude:(Metapost.read_prelude_from_tex_file "document.tex") "somefile"
    
    <#en> Now you can compile your program using the ocaml compiler. The obtained executable will compute your figure, dump the metapost code in somefile.mp and produce the postscript figures, using the specified file document.tex to extract a prelude. The Metapost.dump function has the additional optional arguments pdf and eps, with the same meaning as the options on the command line.

Franais / English / Deutsch mlpost-0.8.2/www/mlpost-jfla.pdf000066400000000000000000021566641306046515300166350ustar00rootroot00000000000000%PDF-1.4 % 3 0 obj << /pgfprgb [/Pattern /DeviceRGB] >> endobj 6 0 obj << /Length 4239 /Filter /FlateDecode >> stream x[s6_UAE}9k_$*uJf™QH׮H#*xe+h œ'~wϵNrV\$WLB3clrIޤ3Y=[ITr^P-Y[ xϬMr|<U.V"AOnnz]UWO˗'.O~;`'b$ZV,YoO޼s/Ta;me*7O'<⮧0HFRsVmU YeVg+mN]+}}f3πQ;` fΡL%F)2C\\&B'm\KυM(\(&9yPkL/3nO䑉i! <ևu"kdXMKc^# 6!(tgAO&z؟'َH-+ekPbi^mC,c,Z6 2׃|\9 |bf[Y[W͡>SvLdxnsH+X̠S 9aA"ŏ>aiD9VL\E@Bp؝vú}}AEk\LWXy wO\ v_ca$Cy1ȅbwnti;5N7ø?a%|fanz?vޅt+ 6Ԗ;DP &aϫ=AEĠQvHAʠdᙝ,l ,#PdJRFg@>QF|sDOq~0xM,oIpDHZ25 2eG5Vs/U\fS^St(OȡؑC>2}$<p!'`Nyqyxf.3q|q~.R2Bq"oRH3^M^%?y'0~9<+plOp v7 ̮nMnm/_lG@Y"p`6V3ܺ^R̐0CR\FH0Cy1}Y!S2Zi̐@i3$Щq`:LDH#L8w"s#Q Dy-4f6P0q@EɊ#Qz `CeTtUtx` `Fä0X"( bNL'DM,>IIӇA a(f $ lݒ}aR|/*+9J1ntqZE8!(c1}}r,!{#2p0ý%+rN%fX9* -cIA.ÆwPNd&Dy '-{BFT4mO0φ# 0 meҢ's N/Fhh|"0e6jSG0pxM7rНz+#Oб'+DAʙ(&vEf2|D#8 r VAG?,/?LX8 /JL(x̠6{_&RC>~+J)/l.M1;$B3&_DB?d|ar:=@I\H0-t#\oXPHg0VJ>t=V+Jhf+uT(pES gc@S2j%Bjq}!T QƸ2Jp:Q3B%šj8> P⥥#npY>}rB\D`TA=iv$,}tfH| ʷjڥ .+c!lNÅdxI6(pq)tw[!,7I"n(=A2ڊ1Z.qP.ܦփ/=:ϮdaI7BGT [ޫ̣n[-@G?DC̪׿vKtqƧ鍝vvTX(t|TVzRQv^/VFd~a S̩\L.w|3b%auMwlhfEij9O?.UgSRuđ,C5~ʸDB@ 9$ׇ$ЍB j X!d,Yn/(s+Q\S |w{HL*D?] pb U xoqC GF 3&L"]/ lv[Pũo2ҡV[>!6 e` 1D~sD%u1ڡ0ڵfg]v#߷cGeEljxuzkII~ߓs l^}SL,YYMGy ljEiQ@?(7y;ޔ*u bq4T9uukgr'zNK惵Va{7DߺIu9ٹum"DZs-9ZP`-<ꉾoCj`]wz*j DՇE! A#z#‚)j|`,CYTQ[whg34SӔqKL_fn endstream endobj 5 0 obj << /Type /Page /Contents 6 0 R /Resources 4 0 R /MediaBox [0 0 612 792] /Parent 28 0 R >> endobj 4 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F44 7 0 R /F16 8 0 R /F17 9 0 R /F18 10 0 R /F20 11 0 R /F28 12 0 R /F29 13 0 R /F31 14 0 R /F30 15 0 R /F32 16 0 R /F33 17 0 R /F37 18 0 R /F39 19 0 R /F15 20 0 R /F40 21 0 R /F11 22 0 R /F41 23 0 R /F14 24 0 R /F8 25 0 R /F42 26 0 R /F43 27 0 R >> /ProcSet [ /PDF /Text ] >> endobj 31 0 obj << /Length 25749 /Filter /FlateDecode >> stream xĽXq'|x47-Rٛ8ެ*U@Y5>'9vSu/g8@h4LJ?_ByO?)PGzc!~o?ǔ~ˇ/rYۏ/?/?y_~~~~TtoOwo~{<_~8)CN)~߽:8S84Jz(>T.`9S(]WfxJ5@To뛿^Wx/:‒K#@uA4FZ)՜DoX2 OG8B S 1F0qRMTh iB0%DiC=mu8 Nin8Q)W{f j+fO-UオjzVpᅴU5`"Ū[ƢUmVU^U SD i&IudzBsVojt lD .n(֎*`cÎVذXYA[XKY,_ch؈Xc8Wk:YXZPP,b/ѐd ,=tEIWXR͌rTog>_7nYJ}(pnj]K~36 v回ւ; NIb4LW؅ʜ5H?.Trs8~)q>.{xM4Ghae`oyje~F{ mZ*DlcZPehÔ.+UT",e).汜|D$U#a!Yvҕ6OTӪD9jw5uVqX䪈Q4+Hn$i)I6B1`I ́+QYQd]rCZpVqB5Iwhmͷsݘ4 mɊ^ 5X K!-l5"!(t'@ulH22*Aq$'(b5Dqu6+""JYù(DjY6oN#r[piKd v4V_/M2(Yx dDcFBQ7HG(71֠KSI<~eiֶh2tccH4 IKnp*mFu,fV%30a^pK}%I^]<_iS0g#KaJ򅆈&LmS&W-|oip:U6̰WpT 8ZsNokVZ C8'TW/j iZSR[Lv7 嬥mm]1cNPѱi5+:[}׀ϔa|"ak0 BN8K:Щ n% m4BQ#N$DUAz' 4޺P|[M҄UNleMu$4e3&W=tm2_T`Ef 8Yuc:gՅ-#~VҦ`nV]XX|ݬܬJzMᛥoXa%ubwjX#,qELlK9h!kQ<*ǔFث:IA긒NLUÊQM[IBCQǀYtxV[ӌ9Y KVd] ؑk+6l`TҲoݕ6*- 6Rk'l6nҦ6Ь٥tqcÈNwk}KWnehqS[ӱU78Z^HsC`bbL]4z,-1QL#lT8݆:@i֒1Z(͢Skn™`GϙI Eԅ V#zk,me>Q>DM~z ;mc'J1LWCǞY/QΠ|2je{[B؏˭`o#4U\p]um d&{ 954 a׎35t$ C]q!) ^B]rRL3-%?T9fz N Sl/^RcQ͒@2.VcMꁥN%] z BAҵkY m: dz]2Z?<,M6NpJd6 :n%'՜A瞡bgm#[~4yNv꤆6MݢFɒ3vJ MǷ:<̲sZJ%9F3pQdTS sMBkr5ع]im-M\c ,:QD877E[X -gEP-B2"2a[d֩\.T)Un4fڹmuj,G*ZBI`w'ofIzѲ/r\`{MZYsTQMBE&pDDoKpۋR-l%J5b)~*_oWKu2Mq14u)5+ ]JUs7[LcKɾm_hSMdtec (+e-53tߎ튃GOkBؾ&ɮ>2CŭMAAٮU)1lV򸑴I[*O+jksXdEPvM3rWt5M8;U伻Ptڃ6i %.\Opjڔ 6k5A].4;=p$ؒUkaiݺ՚EYk8BԧRj  nuaYV62m(kTe^p4}W[% j +[G؆)0`a]S24qĭ;=oOܚ9YXQM+e)V3ZTq)$ (%'ƭ6OnXmҕ`HbHQT4pYx֔qC6a[] J;b{ WވSpn5.25S)/.&9umoHs&I#vi/5[{1 .?KETr &5Y7$]6p_6(:uAfY{eT$+c+UMq4NeӍ5vAƕ6 Twt8]mA`hG[L@v+A]=6 A%:塐, ^Ц ”&HY +9YTת?N,s5X`<Iw4i0󅀅;@uw$1i Z؀( Zm dac*)G o8KEjiNba#h*tĨyq m *^o|EYmq5RdHwQF,*%j3h,, R+@h2kBX7L)ihncBeU-ffɘ+mZvP=NBG< nl,,Nq.kşMߒEZ0.9;,$!K# tmIsU.,m _gl0m6Wn_[/蔯yl!Kk2C. s8۲DwU\/k@$mՁ=CN4Q]M<ŭ;\"4ّZQG0~, 874ӧGkW>Ђ !RB uԈC3\q!8|!M m ̧z5,Yc{$2">WtVV+Mu+"E\)GBt\iS:M̺lB4Ck"$KCI#@4E*tE( = 14-﹀UrN49%+(Υq:;]i=f["w!1ڸH)l;+=j`ңt}c)HHI2v9rrdVX9$oWLYQKa6EV #͓'N']j2Yrdh(kdhE/XLWEaVW]^+:_a(boq}d j A\iNHg#ΨY9v曰Ƴa14iOp֠K1OC`PY [\ ~F} 6V} I?QAL5 &Nr ޶!F7s_i(* b?'I~t-#LlIw@_bY`]Jւx9/ҦQ/ɐi#sf ĺM!q)&Jj:IfNKVDR喒Jc5s&h,.Bt~ y\`3R"g)xlx  zZ'n)r!L{9R2!p@A ěg Tu.@%ոh@+eNnz!Mǂ:XCMwJŦ(Kg)4%CV]e8ƉBl[U‎H363h=vAH"f Gvu`/_uk p5]23Ӣ h,Œ&sZrmG!A}r¾ H=rty]]:^퉻ΐ;#Mؗ]p]h{a1c?HpvG|*IXWd]5b ;A6"FLRi"DV--/$VMhyҖR5: 6jbBbmUE Se dYTLže0PWad'vD0L`[nhI&f4H(+UY& "dShBX+&`QoZ`QxosT2͠Kx̆9_`q?}%=n dLʒS*!Mx? ̛F06PIOlIYQG-Cčh5n@򻲍a!=BPHM)3/$VT,ҳ* ( Ѕ0Uh:PPR$ˆ$TC T @c*.K#!Q|pd^WdM&d0Ƀ;s!Mf| oC`W^APN]Hx"&E)j(),cs~YJ6@.YÅ4hgmZ o% ELv.U-CIO:#.WtA׀|>b[೎-Dw J,l[ǖz8a(Mw@+˂XT֜XEt l45vWJo!42KOr|Ե1Gh(kOd$Xө*&.qFlOWtX $J-#{|&;U>^n+m 6lE)vtdnʄX1|Xh+ЊaYbv5nngpTO.CIk`}j٥ʅ47D()jͲ4jNSPƚ bqՋ+E%,'WA$] X&9 ֢d7 m: Cn0!ئ 9 Y~Цዋ8k(YTF,\UeX :׼#X-$-lqXLSzW!ںzjtkz?කfTނbT\9\#'->öb#C: uhz&nj#M35_+m ΨGXѬ@BձBjl^i?8h-[.[w MFZb-(gWJ!. vt3ĉJ Jax~J_W~IJ=JܮdP2w/ە684m8梟/F:Snzj}ѷ"z.crmBmafFi/m6Ǘh;򾎄+*i:f`ˮ(8v!$$))7½۽ATPsۘMmE]t7xqy!Me[In*ݺ ]>6emJ6ODpP41@A%}T Ccc]S;dT.f1Eݰ}\ ({sC$yL}pn@>um+ p=F#U!Xplw>w.ĩ`pfڼD*ЪA'R )e øC6Cltװ@ a_yF|d3l~ge Yv<.V yGKT=";ei4l~ ʼU5rnPA6AVco ! -v[#k=$SSI֟WdPn}F-ڢTT*"'!4ib)e5`7H0~DsMQ9߿3g_SA?gS iΦ99J[Β^%e7`q6[aO 籢|E%2Ec[]i`&_qv(UHVC lgyiphV*J<#;.4 qZ M]JP ^uOsV)`9 {[QC>~O jf1$.ؑ؝ fӃk9ΜJ&!K Aw q(a1`j!j٩Ɔ̠3%bN8Rd*11&8 N< b)A1o!ЎaSI7}gWx5K]EogŢ\Bj,fǸ%SEtxF@> /?!N(x6!)LMRtM C)i=^鿧@A8G}h}yϜUE"f]84&uuj0$NB!qt-Q\ o%KF nAxYr(="mKRhFWsl:u tgNVE2X Tt(3S$lT;-tp+%%^@\{8j_h8e^lrxUR퉚@l;Q[xDO9e[:̦(nxXM[9 7Ʊmba q*uԐ,ێo$N!;x+T%9sdnG1 qe/kp抍m1iAٖ,quqDNYYmpCwu9 YvI4Dq "g - m mG>Bwp,ty7ڴ[rB+aݍnnh?_erF[>:gc-i7?KvWպ)味fqB3MRun'{1-OawI( Xoc6MD&M9~'s7vzۡ{Ʉ6-g\na%v(q8Vz"8w8轌b!jmR QbΕ=Ҭ1&zY$-q.)טLoxiOӠ{jQ$GY:ulLxkD۱q86Rש߶6ZvNc!n0x1Ez'{weΆh/umP?o”wFK -oDmZ;Q;8=P6N]\WZ=NFO3YFrNxzf+MWw>խÑwFC$?J3x7Teݹݍ̢̠qK3)2%Zo(2ΙqɛV™~ǘ)YJg 4mJJw0gqb=aMrT7m~5^89q[ qztS,g!5mlq{iLah7k^<;]A_2ȕ&.3>N Pc f' _z!OB* xMagk֔-EJĩ3Fٱ:ۑQ9{gv4\ĦYl_qJY;CMRV7nf¾A <댍، /4% $xZSIR`[6'+q*Fde6i6(<{pW8!8N/p)W.1-cIsT4GTڶƀߵϴXq|sa@㍸MY fJk<5,ɩ+$efJbRKZ s?s8 M1rS&"U%Ne`U'|H&'KC+kD,>feZF[ C)!xG+qxSaI.cbehS5gуc5rJ Ƣn=bp٠ڛ}n#fv㜴k?p_ktu\3R V`;y-M:p~-{ή@56"5VRNtk?@ܷGA[vP^Qpyҝ 3MU^G7|l/.؆2@}M2⍠M)/-t`vȤ֜TQ\vNty>MS$K=pD5<;UQozXְC4(]LӨ{kvjj2qn>"hD/au:mV2!8tXW<_iV DAHn\"X Xs"XpKk :X;%)3e b4 m*&*P6lmt`Β4iz&HT,p) [Wi?@-yrݥK ?ku`Ɩ`ϒ\0,?f`kfa mnO5R:aV_G3[S /5E}k\efsSP0vNVBE(Gpt0`3z6k}JHZd8CV߃}M{?k0K e|sx4 Hɕ2$72ĭ4^~ OI9\3r@k.3iruõPߴjf$]3MZeϹӴ^bPM"i^%C6NM2jg9rLX[yX#BȴNoe X5cn'e>Ls@ `0\n+K2 H45S ٛ=(klSҘ;%$ZMf mٓP1b,QD^fL͜ oVz6X\;Bʚ? mhJkۆI@j|d :ɟc%]Qnw!nCZSݥ5k=vczGo{+,ee:Di1ĠEi[A2d־It2ĽG4W`!2k2B_Y`_+O I6GXN0Xk>¢7G .Ѭgj}pm\khh\|lm2 }8ӡYoL,QU @odMh 8S8T>;2v,s`/tu@Y~M/%˜-n}hc[)DY$cC\#]*s#:!:ᜂaa4÷!ZB=Jz~NP$?rCU46L ^ `|\ABV*&}?2dN6 B/9Ǘǵ"<ig+]䬕`v\j&Ͱ.gXA*;_eZ{DaMA)ԇMltoѫUXԲu;8|2F%EZ*tDKiI`.UьAo' vN7P'o#CV [h-?߆zO3:y"Xۙ}'mLGӞUٛEVCmU*+PG^O¸Iܵyk -^Mh-RNᑪVS4S%hJ=2WA?1Nԩ4Ork}ndbc8Nً;cq={960G4f̞:渑Ce7E`2u`&xs|Qbv[=) 6'S|+ ArdC9}WT\G9Y=Uz ~ğ%NǜNSy;NJ2UJ"W)LԄ)KSIok:t?)h;'IyTG;l㤶Q8,kу}Aj_}F0h@Sy|c C٥=(52t9`E`qǣ|F@JA;kdGQ)wɳ9Χb!N;%5!SJ5ݏtߞD i<ت=6Dsjݴ lm*,fK|FO7DTi$} Fwpʉ*b߹rQHWWHi> sV'tuFt>= ##Tk>-cw8<O {߽QOSâZ,=6wç(738L ;퍝TggRhV q­~ۓ4UBq6`oʣSMrpgq52wxz|fOz5GU`K{qjxS"xt7w.o`ВdWk;|Xi/mAwIoFvj$̙+ݞԌ%it2:\8w#]Dž;l&9xb蒻hDMa ^-{3W*Hśs-q1t;`F70摽#[9SIz T:! _ mlXGiuv "- @?Zço+XxfTjprN+Bf.A|!Tnҥ9vOnnuTuuCd6zO, ƊM8|<Y\QNPN{Q50t{!/xmG6pӦunSѻX).|w 6\^zŲKոt-=Dw>P~9@PP7Y_6stu# ~i$5#xևyE&*gͺ\7CTЮBvOZ%i 7VK KBþ ?^0ΊGNXq#QuRc֢IK=zçya[ osƪ_ӵwVGvN2֤Z֦5`ZVKU6Rlդٚu"Օ.И  fݡ]r|E޹>-uPdƅ}A>!NktN•pŗ^ op[~x+Z4LZt׃ <6WK8-yutDDwZ\f]Tuj֜u7AZϠ=Gz[aGot]oҺ[#pٺ[ 5Gn5]'ǵ)< |-G'turbwswyŒ4F@zZ Qxϻ[->O<}[]>Z@tGjӡY9oDicu~;Gv,Ly-Ӽ׻=)orAhRqQX <}ԩh= GPZ)m*RTKfO@M(0Z+ k&C"GմɠE P9XۏgٮWJ't+t^@RIjmayrٵ F8|]t[|" eԋ[}tsFPֈkviJ'TOA;7#C5B'υL2B?Xe4+y>F kK>t0EÝb-u:3 O6ߑ*TFI,œ6w `{ڰf˛;xOvف$GcoڱQ:v佑@[vQl=hBT Ȏ(]gٗR+SkVUʾV `p (OUvbEsD$h.;N_wM1݈ *eM{cp'_jڨ[Y6Ih{&IYxW+Q;nunXTyHl%iFtD%Km^w7:H&[Gr0W[v5Ct 秀iKm^ⴠюLkwZ7˜RQ9z5}s`Ck͎/"=-,hfh)# 3څ8^^\ ^fH)}}]SxZ_sC9bs0cb/S85sgtABZRAؙ  M*f]#ƵX&j (Vlk1hTxaB @[ƪ|ƅ0o@`5aE0;Aȋ°R TIb[sݑR;oKv%N5.ᲧWi)oNL"Ҧ0MyUG0n0p(㈗b >Njj3]9Am`&v4] Edp_mS>6>!84ֈ2ֽM&Uq~Z jZA>4V=|s+XO XCY^nzL,:{SQ3et%dE K\D[`ВsM 咔.wኬn&*;+Ӧ UǗ 'ۭ(MÖZɊ-(KؚcJj΢[iүhy]2o,tQ# hj|ŭ4BQ_,ɒ&3Ut4;-bIuaЖձWt{α).^El;7~Dcg UxBnIDmtXEfnw2ӻWt|{NvtWܷ8Snpg :0E:^[u%t.^Ugi`[6Jű4Qފj[]=1 m ˣutWvYf#hD؄Nh; q otOfT[[^KZ-Wy8uǵ;n6 v+:_s3 aw0سnYC#-Gź36kmT&1\䁗fi( n.# (so\(%F)PBx/I/FT O;Z7`PyA(0Us(--GP'saTivujj5& b7;p۴/Rc !"u'x,Nt.W=:1,؆- B :#}t Y$ kaoeAiԐhwFѣSZ m 71kN9t#8(oSx7 A(EVc/w+Ac3 0yQ6YAk #,.NJSX59.J0N0-@Z).^ ]J r QV㔶9{ìwt98=g+Rm[YDF O=L}3;iQ[C\B> x=pCDy К`s1cx؀N#\ Q.2vM@G5p]G;[3¶)|+5¶L=)ltM=9 Ӝ{;ݯiwǾtZ]C4wegJ <ZUWo O~6{ir?vn!Nu+f%nl7rS8Wx{jH^dꚮ <{=Y'S!c5.9'oLGa&:5۝}u!wMp;]D4F5l$E%A 8nQ%a;_H10P9Y7{8sj!k8+ qʴAb؅O{]Fn F6exnZڜſYdK %sDQ$C?kڊ,Qf]%/PλP亯AJjwQ f 7tUC;_kԸGq؎(®F~ AmhtCݓv_@Jvªl ۵,z5F޸.!CG DC 8ٓJ4`m!"wȖ4J)ҘaF1+cvo~dmo7gnҽ6w ' zEP`vxy(e1 V{ zWGn]Q%; [u78p`HKoS@U :IY';yp6 -)i(zJ8<}65w辫}#A $/ Ϥ)n㒖.:d*m?8bؠĦ?\Yw2蚲)䊩^?4MCf3vOaP$gt%\2)F AW>iK IԘ| 2lFT5\kEI#ё΅(yyq fF/Ix[A$I6T Kg.NZȕ8 *ޜxtXQAp`t爓Y ci#1)]` @x$Vn) (#t_zI1cUq `&jFu)\9 ,7bM. m7,qr'm%IJE3(n)K8b~c91CH \Ժ%s"桼ݳo]M7^HKW㥹q[E57fդ[88MV L}'^LSs/dZ.z\hiƶoc^}'_ۼ}Hscrs9w3VtN:'O#Im}5|u<5MF)^ Q̞}7 h SR4NcbXd}-Ԡzi:viOG{Oq {-A`Qu[cHz$NyYc{PTtM&j1I<]9"xl)"ǔ* C`rf]g!'@H I=Y Oyagpͺ x%2? cKlCxДw5UdG#?|EE"x]P~WA)C0+ 4qֻ rY 8] A2 &.(zI*|p+7y$EգjbŵyE4zwd][S_4e3G~qԵ_GW۬<3 ҄qgy- :pQgǔQ1-> nO5yE}5$sͳ?YRxP=z)`(L`цNRowgVd`)h2ި#?q9=X7D9{us/nsJ};x34}Ф'~)A}1w3.ֲ<youMr6gR㙱ԯwވ"{ Px~}(W{, xd*fiehӬ@}6H}Ձu$Y_S{܏߻U"gvKo9Pva}`ּYS^ fh^c;Az䇉Va̻&ޯWv4}7_h|R5UetE Yz!sR ]h<g!cus֧hG]J/d7u&[r;'sG?honH.AkqJ\o} 7U=7)2yަ-(5|#PK =GGvu Xpby hy5$TWfޫRwWhƖs6WouiȮz "$5(#hPm #)8^Z=I)UUw%Na| X+᜺]\䡔n[`_ćI6y0jJ͵XwyCʖq\6OCz٦lUg%J99rRv̺88(]dbPPMx.t({NMxsC nq! WpS&Zq2.r%M7D3fA̠#O0J},`lHB?i_hGkizj1 +Bx2I5Y6cRDNvWs>7IFڙ!@BA4ٵ'cWv{~\;`pyH\`AtlOzŖ&8T[ ;l9烔;l*bzCEuy gHp]m9j!krsG 8YǐDu JgckX^7%iMe e`%y$K-l3$+&1$"xۏ+:Mv_Wj$%ȸuE;Mq.4UDUY)K:a&k= B륥(4v59ȌzסQmv(t 6U ^VKx(`g%,1a8WtWw]JJjxƊjG`pP50pu[on X`+KN2P\Qh%$gd`n%$ez2k`͸Ux7_A-|xO?ן ?᷿e"6= 3)ɯ ȊJxg׷_߿}|9HYsJ9O(r_84oɧI~xa(e݂>> L$9NL16'7yZ{?K/G*_?w\ ᚍ6I_kB`L?LNNQ¼d_DbeSuUF>/ k=Q ^~|~W1DK)k\b?<$)3\f9 $!񷫹ͯ]w \#+pEVe1߽˧T&p^'Xb\mu7JȘG sP0Vl)_/O4o6zz?|wOn6k$~峪.}~C쯿R^?\ P?8˧-7 s?Z*2Xz ]#]5QɁZTK]-=/?ϟ~K :?_zAO߽||LԞ'| g2#?>Rc@O<հͅƒeW7ܹL_({~WffyNS>~;ޤgr`kM78KW??lN|G*B?}ϱ&~N ah_>D*)O/sͻ^HfB)ۥƗ׷|#"k+K?MpI%̀k5Ta3%;8<8X/B{G?˻e@>z/1I _O tOeIe5wqtVol f))`W8#*zG6m_NmoN3/~ HFӇO?eyc~ ?iLV5W{Z/?~o'vo__Ve1qjz;9خcpjeY˴T_S d'aGՃ"{ Ut:!ĈIap甇UF.'v>}y+fk,N.i$Ӹ *̟~ "з2ٚ9І ?g1ʝțV.UUcdWs "Ѱ6Ǘ}_;WpzvI$pO5RiXj_鈘d,)XXHĆ咖˻jffLmD44 ͵JZcsm?H>3gz*<\ɰ/?|ޕ{W`B%Þ9+߿3&s4P#X2|4LO3aTԚj8L.#2O߼s䧣%0>~|(H=E_x6=d-x)NkAE'xMlE7P7 b{AL';ؼjf2 /_ U:4ECĿ>]; yiH Yr8O/뇟Qn>-/ [DU^DUӑߙj0/_;Mj(W4M l!k bw_ 3m;|V"#'3" t2J ^>B% kZlzPaN Vߊ m=}DCϯׂ9g[ epD\7/u_|SӥB]P@O ",igZg4s~zȼ? ~CWrW'\שGUp7 ~o=?- V$Sk/Sa}G- 6acIooᗵ]cMK!=6ݹ6 .`O./dv}L2cmZz!7R w tn'_h0sy^~N@i l?-y|}[eq#6@ L-_EF 8-˗e2~3\FöAcpO;c Q_dGF_eɕ&T-dk`JQϭfDwvf;fM'+}7/THˆ߈ F+4J@: endstream endobj 30 0 obj << /Type /Page /Contents 31 0 R /Resources 29 0 R /MediaBox [0 0 612 792] /Parent 28 0 R >> endobj 29 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F45 32 0 R /F46 33 0 R /F43 27 0 R /F40 21 0 R /F42 26 0 R /F28 12 0 R /F29 13 0 R /F37 18 0 R /F44 7 0 R >> /ProcSet [ /PDF /Text ] >> endobj 36 0 obj << /Length 4334 /Filter /FlateDecode >> stream x;]不+ yjK>,d6`M&@r8q5~{HQe{7{D$EQI.滷7Zۇ4%Bt.tڽ}QAJ?D'R=Nmq'`T݇JG x[ҿk.0"7n8Hv|%kәaܤ|C;&l<̘4 7?$dIiWyu[DxhF|}:rM -qDSK?fZiO["s$NZSnc?{/S=V#)Ŕ^?*iO*,*@f#gXL$ڣ ];Hd!e,4Rcڠ/N}Mj==J7kvtڲ SS'G1|4gĭ#y=ضLyΕ3OT C6TrZNcӻOSMw5{G%ri=Y c_(}9m2jGkG,Krlv훂+#s} d ; 9MY`,723t,I3-d203[;R"+E< kP KF^}mP6gMSugMgKL֢,i)%aXw-)*Ey/UB/'I y)M.H 2k yiITY>)G0zWM]xcwiaҽq4HmdiK;X8tmi x/V[{("X0>b* #990%DD<5upHo%[{甼sOzgtͻ~w#ps'@BC 0:͆37!DCqx!+*F< "x"!|5isZ.3'5X" °rRS_D xnc` :~B: a2ϿW GW$a}.m-HM;5OTB _Kd޻,5IDaNlhT):2G"un4/8/}i-CLvʡnXub` ]4"$/bDs'h}.v?Ma56cS@3qIJOhd*pSSNtv&nSY\fWcsm\RcEM9b A$dRS4w髳 }(Mʔe<‘1 LR<\)xHڴ˥/0Býpt.-Ba"f f]eLu7t.a2u,( ,RT.~δ"W[j pzAy٦gsV_~,NJ[փC(]Fe%53sr%E"`,h5[+8z=Ki KPɞ8 q5g<N|V88]>@v -RDlسX¥OM4P-H zc7Q 7h<6@ `R]Um`į]Fy;lgB~.,%SJ$}>yrD@MZE|Y¯8SzvUo\I\EբD.0ۨP>Bwʊf#`FjxlmL8UNly8>lZŝ)S>n[|*elDڐJKMsm5\|h|i.h,sju`R$5+ &$3?xEr0Jj@75oְLAu_A}:2wVa? +"hQT*HԇgQSWS+w4IT#ko~HS--P -\[dRF/? 6xۉMj|>D(8qitZ(W:"/ &=c@5۳Eh,#^n K<\IݱgFWR::ɟ^ى*%j2CUbz Un!*+#N0G`,'gCx f1ǚ*:Ԟz{8;ڟH3wl-RjKPy8_,/ ĦӋB5#p +KGZ_شmN,L+ۡ<پ6u 3;`w{ˇz8¬!j= icuJHzt1'ZC R+)=U{Ɨa|Ghz'/]UZ'y1\=Ji=AwHl4K_C]ȁqݓ#۸/1gܨ-3]KBOhT z3ŪaP yfW'zvlNx]#Z`F@R\הklp/#u()- !n䴡̆ ^~{ao^.M}}^JQw[$39<^oxsV ?T>!@e\ve\ve(7U\K|QVR ]t#^@hT]2^q‹'W6 (F{D>BS!Sݤ登?hNJ:'c_^AŸQЅ%|M UPlᙻbEIG/l ,bW>tْ N(Y %8S endstream endobj 35 0 obj << /Type /Page /Contents 36 0 R /Resources 34 0 R /MediaBox [0 0 612 792] /Parent 28 0 R >> endobj 34 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F46 33 0 R /F39 19 0 R /F48 37 0 R /F49 38 0 R /F28 12 0 R /F40 21 0 R /F29 13 0 R /F45 32 0 R /F36 39 0 R /F11 22 0 R >> /ProcSet [ /PDF /Text ] >> endobj 42 0 obj << /Length 3452 /Filter /FlateDecode >> stream xڭks;*j""=db4Mt:c{y91v6ŽIt_Db],MG,].>Z(y:b!$Jr-TMfh6Jk=|]+ڨ9'sn&+C]~9Wٲl]~xqi!8Y*djͻ8ܷQ,tE]dt&tj`\G13NE(I!Böç!E=T( y5`D43qp{sf3sHN+aM.d}DŸ%QJ4]^"y^H%2șm 4bWQ34QH)Al>U XG+ pk2,s_x2f̷IMTd,2Fl9x7`2v!526A3H t/qX2EZ$DHHqq(2ptK'eD7뱦<٫zVG1 <}/j+]p]Eߵ43]vEuٶEՔ!SKl4yUW@uk6gmISXvPwtv1YbqMjœ/qZ JSU[2vj4q*g~wuW *)^p+b̻$!Dı?* 8e^@L 7կ~HWԥ? /t0 S=mv[%tP(܂K:wwwHu]Sye=&>@ ;@պoLeJHPT''$:@㔀qH xhwX)x\OD>>bIX pS~dVV>F {_qRL|8*irbC9cz6WJil`LɣO%e1kYVY'q? w$hfz ;Uޏrb@j3.V GjV1nϊj㜾6ѧ9Qe@Gy|]3j%qO5}L<A L2d"Wý e7bPҢ..hCbVn,3*+ [B&.kC~DԦ+ow fy6w9f TqAugeKRy/% 3<FwL. wJZxyKo  }v]n_qVJ%PNJ@FMx*lZRڙC'E ^6[*D}8w̨ rq;H1XN=Nm-!x^4t&5Dq3NZ`Cφ~vqփ#tVʚֻla[(KcAE\1vrr){s1Cܔ@57}PO\@g'5b̻Ye97zg2wŏ%-ׇ4xsyv;u_.XL NDlZ߳F O'l4!w]psAxӧ[18;G܀1mX>3?z|e2 fFFs jo{t(5lRyMsAu rR~uWǀRz^8Okvk ;R{f5H\p$VE< ?q A }d ܯ| 1=Xd*zfw@ 5g!Y:KJ8\V҆|"oW+9#4޳Ԁ7G;.UEjQ{f:dŋnl endstream endobj 41 0 obj << /Type /Page /Contents 42 0 R /Resources 40 0 R /MediaBox [0 0 612 792] /Parent 28 0 R >> endobj 40 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F14 24 0 R /F29 13 0 R /F45 32 0 R /F40 21 0 R /F43 27 0 R >> /ProcSet [ /PDF /Text ] >> endobj 45 0 obj << /Length 3648 /Filter /FlateDecode >> stream xڵksܶ~qǧBОL'kIڸv?NJQ2ޝ̇6bQ'Ş~@\'ig}u<Y*ưT$%9tmo.\US^ˋ~ۯR0Z\zw>FeǦwWq +[(Ѿm_6p^^'|^)L"ɩ]V˪©Ah:|ppZJpex4@8%C/M@#l:>ۯd:X,yU Ņ:y20}34GL²flϞY4cJ^")"㿁2I "%gۻ P Bku/̠?1`:3ⓘIfČ70@>izG`W0w}$b&՟ .Ps53S)ӤB$')FCMV'>V&|Sdb!ȅ\& JROHEbsB134&^e t L!/t884eR0bܖh$|Rd B;AaQ@C62 @/ Pez29ϼg["\%/hУ]#fKФ5 nR l9fyv=Uq4W~UM۹̈ wSm[l!"`)7!2btNY`.Żea?-Gr,X/iC}Cu5R2 @bU&m9r\)f'S"JV|@Ex50&7Tkb~]vԸ*6U'l_6CD?gzPUb/$ŧÞybh_!ޏmH~[z1m1g!۝فR+#ܑig0t 'zDD&Me~Yc$ŪTI @@*Q%րuƾtq|v݆&OA1b7yi pmq iG Aʠv dhL#pu"D+]NϖdtgabpmJ6e]oP9Xz&\tî8SNՒ2b[viˤ\ ]Wc7v 3v?їtU0v8,D7C>fja;Ze7<ܽngwՃi.}(bUv%l:sGPgБ:9}y`gj1ͺ?La&U0V]=)4W/=4gO~s@= )u#7rԈ Zl[?PanDr$;*"e9ϦzM)2f8hD`G"W%*v]`Tt8ɟTp`t\;brz{xWDžg5}|ݒ!; T/ qObgsSlvDDID|mZ쪮)i0v͘C #] w {1!,xm#F^"דxR!noemSx7M4e VdϢN,S|b݃Z Ηb70}X@-wUO|2U'j4/gܙ3!~<r$wTJrE8beq‰0㰎8sEJTHQ_(y91}2 Sa$^;0FDikE]7ӐC]礋q5̂š$M&;"Ppfdfń)shAX(v(`%8!'%S+U iK[7T2mT .5} ])$X*Nc,M9aJSo ?F “ @ ٲL7 k~q[Wu仳 WxVDN+JZ&e鹕JFӪ=*6@oQhA4BX>VGónщ sS` aݯr'D$k^Sĝ {t'I૱RWG=Ht{a!Bmu:vYLq9]{j,xjYZcACOWXyy'+ϳܧep&Q@FK'sivx쨓IDQ}LE.urٽy=cdC^z+·Q3McB;YHs*ﱲ ۇ>;4[S!2iY/M_NaOw;QNisrC_ PA4͌11 1.R_t)3/u)!҃K'+ƯbVo ۻ~l1upY{GonJvB>65gz|:7cQ1D!S3rH}VLQa'0w.Mc*]HJ4v7uF0WyE齗ʁ3& _E]KrUQV˦>mxcJq;hA䝳9['9g/0Hb >s ޵`x_vƮ>wsCQs3v(hk ddpi6u2O_|akܱ#l$S+($"MbNͮ W0Te@e9$߾F1N)~V1vn+O0kW^ᙼkN endstream endobj 44 0 obj << /Type /Page /Contents 45 0 R /Resources 43 0 R /MediaBox [0 0 612 792] /Parent 28 0 R >> endobj 43 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F46 33 0 R /F29 13 0 R /F14 24 0 R /F8 25 0 R /F49 38 0 R /F40 21 0 R /F45 32 0 R /F37 18 0 R /F44 7 0 R /F51 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 49 0 obj << /Length 4364 /Filter /FlateDecode >> stream xڵ[ُܶ߿bY`G%ERE6E$Ml?hghGnQH$/lsa?]}ojS$Efnr,dH#ͫ7ewhǛbkm_  V4!_S}?o4V͛rǟ_q6U}-4w]'mЕP1٥O~W{@ܛe,Ѳ9wne('zwퟛf쇮=N-!MMz,b/X"Y܂Kv4Re}7+&v fB6[=퇚VS&Z-HÍʶ% )9A_Z 'ܗN_TV4V,wHd3o۱H;roFc`?4him9_T6_Alo 4XIOb%IlOTէzW"P4V`gBy'S|+22k]iL?"s?n$SЮTq څ]uq ҆u*3`] M۞tV&ȞI:?Mhzw|zo$ >';U64Zύ:7b85zp(s~Βe`}1'&en~k$ȞmXܟw'ʁl')% \;i!e/s_Ft۔4}~JCCuK}}k8yۏMYwխCj\=+MR|n}D憺j4[Eztvw)bV8 *'1[ f^5M2z)c{t/ۦ풻 Ef."24#ZK%F.RDRiXbB%,sm^5Ø۾ p.Q,8Evo} ]T 0e>ЛBhotЉ U߷cSh* #2lb }}Gi31>h`Kd^SgF$i޵fwhCL86"5M_xgxL6. @}{˚ JmnǡZ}eŻ~ nxrvn(XDJlY1KN6v`Ɓ^ٲLê~z6|pF*N{OvjEZjOr4ω}oz#&$|M W\OujTZPTDĿFj.!ෛ5EEiOր$3Xa3" )8Q+'-!gVrUU!. i&&ꪽ&T4vw0՗Ҫmcf1ui)JAmMO}U^ %gU:/W5?R]XXwSXsmυ/E!s4),QW6'8*G \JmU$c3"7 2(r<ʇLTF%_HR i(1o?߱D;pSA=4G8dJ5Д"`1niz&S ɡH9zx_y'>, {Lg_ K0TТTmOkC`LDzCx R-P7DRt]Y^)KrTr) 3lR0o$# ƟhPZ\0սNt( 3opx!iO2qƔ=;7|#GpX92Al {/$_)(li 9xbf6Dk C,rb#`" D3:"e:H8Yhe榻WxuI&S^Cw+*1vB1Q<3;uKܬpD MNjNxGXXGĘ4* 4<j|j>]5 G<>*/:Hr_#Cͤ|>z38ڟP͑{A8tG'XûoVgAM8SS齯`;6թT5n*hwS{$a-5b:IM|̱y:" ]+[+j l.rh81KMEk#kscGs5 yf:oQbs0Sp%xжF)bK r,j4)z,/L_5Mj Z(Jy:7ۯ,^yy`p|$@?8X3I8s queP)Ǿ k)n@"yE[tM6jݹ2JH@7kpmpkj~)N+0ggs4UBy'k5G< 6ey@8|?Vh'tCŪeXp:MvnΚ]e1 VUF7p.GR搢AXg]S7oOV96mv5G'poj,NуgttكQYڻhζ~[|{kz`Gɀ>~LKt cZ7`;@ztօAJV9m,\pOqH\bJi)Uo^ C;-zN?UG:Fփwܻ=ɊׁڏQBG_@9~}[Woj'a=P@nпW;^ǑoE <5n*ܠxa2= ;$Up/:輑S"֗ DN?2 vnD/̶9:j] L]SY*^=d ~2jKG1Fs ;/R'OOWm#;"Ac,ڃ?tXR䦗UZy]IHd&|kQ1l5EN{4fn]qq{41 U[LȮ hW>J܍h>/ݜMVjՉJ'w1S./,.2XIE9w,/̷M4Rw i6LSy4F0'y:Mx0_^g7bŽD]v-sbDyv/k\DMZh:ڦDtbnrp&gdhMpN9QEȹGb {ath=8山/Vx >Yf3C~g~x(=) 2XydZk˩7v)9|Qf+I[䭝-d]q*Ysj d?i))Oeb,9+Be&&>NH؛''TlsM(OYO2Ro=v3% ]HQ M{/CbQX+8QZ6Q_ sEBq1o(ָҹlz;dV"KaJ,4̗O,Wt]$=\] endstream endobj 48 0 obj << /Type /Page /Contents 49 0 R /Resources 47 0 R /MediaBox [0 0 612 792] /Parent 28 0 R >> endobj 47 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F49 38 0 R /F46 33 0 R /F29 13 0 R /F11 22 0 R /F14 24 0 R /F40 21 0 R /F37 18 0 R /F44 7 0 R /F51 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 52 0 obj << /Length 4570 /Filter /FlateDecode >> stream xڵ[k6_m i3`L`d~ʥDHW#=/Q]XH'/Ͻd]UW}ӯao+i-L#htSu]r~}nlTwvzt˫ӯ)Z1!$?l7ٛLJ╫722nu\^XW7uU3ٸ﹮tLZnzYESQ-+c J~pBv_V }=>7Mh|iӮx E0]\ꏩϷ.-&+j7wwxx'xJ"y|ޮp\`,R$edox3onP-v 4X׿i sEݢӿ֬;eW8XtYa0g%Q¢ԓ2pznڷqyy}ˇ6irSiͼd,8ګj~,J?]+v01ЬV@vZ6 RC.JҔE0:"u0]S_-8\2lWe/} oM`rI[6?$SRmܮc[̿Ö cnƪйWЯOD'Roch:Ѩmumh;:`tjQ ;vՅiD|93/!nMld!h֌ Qch`ê_ _~u;|߾]vd(o4\x9n|Ć:YcؓX7onG?}pX@m`J0 v4 L%Q*5safbH[wwUxo`h ׌g{? _/xZbI hUI+&nl Ǭ3|ZJHfe;rsX,R:;L"Y#6ՂRf"s 쳜gBzoQL.2|/e 3eUF 3QwƋA…B7 duxTgY`N`)ϛzp< GȗD,xVmhAKZ`A( j!}7:ֶh^i,FC:P4ig \c- 5k,ܢ0A3a;oA!)@I\YL4=qg@ΉڐP}{j.D@@BH) F0C-@5՞FsDϲc^ȾChJ`ZIEn!,y%uCp$-!fDnH-- Ji=&J>fMl~n(,,ANV,fUR#:q+XWľZM4F r[y"VLvOIP ni9D.sf$M[niBb-cg+azGA뙮)k* Ue@T%Úآbf BdT$d,#4.@ZB WҒG=0~փ]~/To %; 0dqKEA ]ϥÜ{vƑ#gia kkxiTߠTPt&* 3LmhI4tzkC*;~j(76^b!<ib)I873< HQnx(fEe)w(sq^eRHu~zanr eE{Mڀ}d-4Do $7־Q>cP)R6~;>w⟤PZ̝CMry c}Õ+=Uߦ:y}~mߥJo3~}q׮% PLI=]Sy5Q+)5+ńD&ΥH:F|ǣtDlzFC5I!]_x쏶#0G2a_7{O X5\.5R縇Pq(Xzvܐ,d6 NQ#ߴWxfdGT&ʤ#=?Ӆm1z9daQ\M:vȭ=x㪍kY8yp,{G} bDӀxpźJGM gFTxj~npƓiEC#l,Ii6-K"3W-].(1""mq5+:KRCC;dEk_%]9Ђr6-)!e%cNLԬVZuR'ݕ_ꪼEc1)[#$џ5r]Nk'N!H<#8u2@"N)j~z8J :g:2M; []UGT"{a儓pu,_sxѻѤ)(9ܦċ#4L ['Sѭuywoet*ٓl>PЏwtU&r[HV I0vW&wn SNqL;ݎ=cz W&>ǏR&KoO48MN&ԞULh&T endstream endobj 51 0 obj << /Type /Page /Contents 52 0 R /Resources 50 0 R /MediaBox [0 0 612 792] /Parent 54 0 R >> endobj 50 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F46 33 0 R /F29 13 0 R /F14 24 0 R /F11 22 0 R /F8 25 0 R /F45 32 0 R /F48 37 0 R /F49 38 0 R /F1 53 0 R /F41 23 0 R /F36 39 0 R >> /ProcSet [ /PDF /Text ] >> endobj 57 0 obj << /Length 4627 /Filter /FlateDecode >> stream xڽ\_ܶO1OC%XEOu0=vg2X7[TaanpܦmO`i 2*W욎`s踏?oFz{uxv#nڊwG3ynO[&!Imm: UXlsȰ5YRXu g.A<22ز by#/qq>}٬1&*@ymQĉx(wRrZ>J?F̡ng3~t Qe]8uMh>2wiXA"_ޣamx*cH+xm<B "yGuO6t}rǑnC# CC,kA V)P3C,M5=ZEy[t( >ACPg=˿tj7XHsxQVɚ oV-]_w|̴Xjt"1gsUCrBh@ivM\{Yn ~TWK~0C""7I_Ĕ+ 2nا?*E +JQ CQB: j%rMneY귫&+L.V`S] :_AGX'c]PB 56Pcߡ^x*%[SdTרb9]_ X'?SjpsBU6 1Q^ l&4'eu"U1̪Q X$`gUc:G(X4ZR1ׅ'=C;\싕$Q,hڿN $,J%In/,\. Y%*WbI$Dk$"Y#.` >"䂑R4\@8G,,44d`\L63]Kd,&Y2X0/KاL*u6tbɸph--YM\.Y".G]qe,. 3p3$ $d9YIr9Ȅ$A2Q i:ÓZ 43IF21}XaiIL'fHI&"/I@rEa}$? r, ϱ$lք͉217R xdI\'*+UHc}a%SdvhdL2$_$Hd2dSD<ʔD&<2E2D$7H@EDt@9@z'!\ѓBwBѲ^<<×<υqY5 p/ _oW2M.>a1]}b@L!y6"aX*Ar@EBFT6Tn/F&iP ͣ`AW\/:F>7*(Մ)S'&G ёGf3eitam\k%|("t5 t,z^M7$3.ax<fraJY^%RFơm0GqzBEHX&dgY4c+LZi~2k #XȤ%%W!m^b2\j`V)X|)qЍGqzxC#0iO&Fne7?[XN5`LQPl 1Dľc}e`E=j24H:w&^Zq/oeȿS_REpEbEν0;L0?Ƿt/K0uW?Tsw,x5-?/u[b ^= |J!ۚ%T}O }3]kZUM>I}kl^/뮾Kw62V!C"^}c6U264~hǂZg>W}vhiĖztHt3|o=a[w9ף{]]UւƒMHYaVUs H5sZgoAnN吙@$3!q//K$G|hH| }5+3zmuw I {lښ29HCpG )Hic%}u`p 3Y9cJ*+R|oz HO=_ K%KN{R㜶"pW_%ݞ/%J;oH4ç욹 m@YC7> endobj 55 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F29 13 0 R /F49 38 0 R /F11 22 0 R /F41 23 0 R /F10 58 0 R /F6 59 0 R /F28 12 0 R /F8 25 0 R /F14 24 0 R /F57 60 0 R /F46 33 0 R >> /ProcSet [ /PDF /Text ] >> endobj 63 0 obj << /Length 4509 /Filter /FlateDecode >> stream x\ݏ7_ g 68H $A-hԊ/ۯOg<;0vEX*6YEM5̫_g5F۹UBM#h?v7K)RԋnڜCm{#V7/) +ń0oaoهjuŸ1sS[ƭ~k~^1s;Wf*(7gՃs5Z΍1+AxOluڱuێ/'di&u  V&t W[1y1,tɹ #7s*_gXq Zj7o X8fof"pxdT)#RGсGScJK&>OxjxPeMi^%R&>B S5{5QZDQ "GOxZ#("ى v" 9 |mdn'2؉(C|:EU^`'0]caCˈ a,֒VDas&E| leV6%|2ǔ**`+ Hy'_DHcT|X2bzӄ3i-imRNda&_Dۉ v" 󨋹V ۉvrd':؉*̃|2EE^cBˈ a,֒Dr>"B:/[U&_Dc.tW%Ct Sx Ex^0cSc2b&#c>%M&؉.C|:EU^0`'06yvb">*/Y5:糁/c͑YSjs&Et` dmD6ǩ`:g`ZS2;@q0ȚUUMڡoZ~=Q+|ŻFv]oGyQzY`=uOT0܋?sO)]#yǧ@pAYP,aR{s!m? -;vnwn]cP>+z| Ae&\[/g4u~:oێf?y(Q]W~9%حT#E9ae=$~O/N,+k)XpZ2tYrU347zyݝn}2`iCr#c뎞)Jxn|V?KF荿#emCYBd0.%5t~Ruv?mQMtHHSZҎW#ةnj Aɐt_{w8fx`jQͫ/p9z[Ξ904eh:"=˴=ŴQ]JUJɸԹ*Ow8I+ԭ{4o#,&q# p&u=AV#qf nj35y0bVaO5R.0xICl8L sB9PyN<'T* sB9PPYS2;V^_+f1fZ(:N{jTU'._F. aꀩ%&ܕdFp]*wVq41buG8a+:OȏҧD60R铘%W.01HXF7%Tȡ! '\/*r-ߧ*uq'aƋ؅Ekq^Qx>vlPea)@ф0#|QfW{o _T_^(^+2(ľj_W ܋D@)>v)(ѧRp^lsXLI\``Ս䋻~7v17XB_hnno0ݜ`[ #nE~Az=쭀UT__L1_>>|\XFj11tcp'H ºTʱʼn=ؐ-ϔNh7*0 $Y*ǛBk͸-O4uc8;8{?iɪ&)cehO؝~QYd_{>1 ~slNfxp]!f6)~I㻣 rqD6lYA%%$8+*M7}GV !s͢nw'*9C:,V&:02 U4yP:<˵4;RRI:: 7ur p>`] M̹awu94i|wl]BD &jJ]L\wZ~V(KkF+-iND %Tt皲sȠK؝n _'̸u:W~myF' xSmSz̵rv~~ W![P zt$)MƥrJ^wPibҵ}E4ɵ30:+ ;MwfŤc~S:%LٷqC)c>y c.K/,-0Dɧo0 GۡMLK_ m=bq:{^lw"c#'#2l!k/H4,Րr}wzJףLuA"},,/2f̎ jH gd6dʌ_ p/ޖ')DXf2\/pmsĦ3DsQqDw]vf)Eml 3nIbƧ$b tM3_eH;|By;VI@fK0]f?e6 4N =\kbUY5:<)؂3#q.(ֺjrTD%a0XB"MTY0DI$ZMF5'!5w`LvfG  8Q5eT'@#9Tj-e⮳DÜGH/-, hLD.se*Jcm^0#-H=08@R8uAOh&T*t " Ȫ`khkp I&Yʸ0y!q ‡$ ƂKk@d0Yr> endobj 61 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F46 33 0 R /F8 25 0 R /F11 22 0 R /F29 13 0 R /F14 24 0 R /F41 23 0 R /F45 32 0 R /F39 19 0 R /F43 27 0 R /F40 21 0 R /F42 26 0 R /F37 18 0 R /F44 7 0 R /F51 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 66 0 obj << /Length 5499 /Filter /FlateDecode >> stream x\KsFWiٌ`cPl1^ڳa#9 t7n~3+A= U*"^ݭ\|}soY5Uc]|X֮l*rqv=Wm_mĺ~RZ+ns{&-i7~%yś/RDڻJ8/~gg߭J5~kxsWiW.qQ?:FVВ7 ]9MQ= u߶t=@oydO;l9[ kon\FnɄfc*SH "Anm ~KrݕxX"ϴj%VUc u LDz@8}&|N"VF8vOw7>BZ]zwvgZ~;w<ݙ@vx?i*Vlr۝oDSWR4SlkcwB_Pp w裣&iHn˲#e҆B,JIt~{*[W]1p+mp FO>JO@+!5x=$w+o 2_/~\aF]zSUV{@C^h[ 5FJ;їժljwZ@FE]IWPŖU-sЉ!Zhݺ~00Ug!( Hm*%/ }hxZh$M+']4! lY6ҥXԕIP-%+ ЏquRKl#k6:U0UxwJ}mpQ@WBW*"2iBkjh(eҊiѼZhXPAܩ0-o,lm 0]czԾ9/ #K [$`wg5, (t+}J`f0K٠Q;2XRTc&+@+@*%/w o$XL ,fc ^+uhiX&8}q` 7F}#uv R[M-%0I V(%AYW5,'Xk$3>ځiBVpa› 'c-pTWvg/7 ;(kͼ*œHI IAjޡmtj!8= 6hZp'n P JSy!O'(4rj5y+]IvBvHf2JEzτ& fIxG\M0_& m=xD@Y , 1Fo 3Bɽ'f"J $jK@0h'0~Ke孛Ͽwۻϫ>Ch1 )̙ ScVѨVkdpeg`qF62!#!VL?tJz'%z4Bk/e*!C|J*ȗ$$WVl>S0o()ɪ{j 5 ,A3J1X` \33CFa녇X_"=rUc0x%lWRP9JtIt y%τ& Xqz1 rl\_{R*)?m-eqYMD)ȣKJPG qd0q)I)e.e7Y6βX)($('b b`!C$,SƾO_b}wQF'ZE-]m`@sOTT6H,&vb|g IV1SVaN}Oq;^+ziIЮ$;# չf*)HHy?yÿ>T@ݬ誩/5^E6,\K)X/J S8Uj^L Ds E$JR*R*Z%z^㟣b+B*gɌX-UÊfbs?S6E^eV'HȹU㧮PzRzU FčO I `dV!4SR$\JDxQ.<2T#4JFȲxȽ۩,m{ګH_\ @H *VM]Ւ?8XX|ZcVVFx7UQcFϔ-úA0bXhAF$Qi/7Q*g:id5HXւ 8RvmMe7%U_HNTuGSNy}1E(a%+!jd'kv˩(9D 'D1C,R)n"2MB6:ϰ~ˊ:] FPY}"5P&!NR? ghtAVG&_%fU 1 Js9-DgGojf̜KT,s Ц(GTS}aFFj}yrph-w t^&GJ!=Zcrz}aPܲ=w' wLXV] Sv$ ㉐[9F?ǑrN(~?)&Tڬ;z>lw=q96h s_r~ݹ?oJs$ˍϪ͙פaߴt=Kxz}|1vĄIDX8PS wbqT4r;/ ˸ c= RT@-R 9

Pu#t8֥w{ CSv _O @K!ygAz[³CuD(w9}U2&Hi)ܪ 9 c{o28r+娊COGR#.=u9\LY'1 @MߋE(@czl%Sf(%yW䰖GoNF8"ܺnYza[N, =8 /oG⑆֎8\8L'i$ Zz^F >j5Uн2 OUFȾ;%[eHBcעuzc`7hYՎ uda }?p2Ȁ߸rP_}Ɓ(I$ˆEr nzwgNJΠt_=ɱj&T}[2HJZѪ% w(hF<ݠC5* Q䶴Jѥ '3rYav[InmFbbb*\(`>#H)ZvP"}ڕRI/JNb N!P1x8ATp5|,H.TV0ͳw0՝RGD,WXQHuuO6PQd$V1r{P(N+ءDRWajFZ2)k&دAZccv6~!lFZjhQP+z{MЏ׈}K0ۃ"_^c_,(1/xZwB5*Oz}<h;bB֌=mU2:$T?lz:I% D&ko">B> r=*hkl(IusuMU.Rh,7z,qGt\IBKkr[G D$0sf-VwB];{k¢Usodvɞ@(25dsC'ڽ6󖲺_ Ɛ<ϔ16gh|ё]' RIk&8i.ؚ!R!se-TEF7a(>Q~,2ߎfR >[[Jŧx68lA.Z7s"x-Sl#kh^Iqwl3j{,XEKOC|XS)cA\xe\4|>:Ңq=guvg~ "c赉ʿ#h. \X(d%resqdHX59dg#(Q9E'RqׂۛP*-UCbI@5AgFi=ߒ~mp1@nr V Ey_}߽u>iTg#I|ᮼ%C4gJ\7lJw5ʪzMgN]šp= K_JIr.8Ey./VķZ{Hqݠzmzɛ{˵GNMxDƳroP_k2Frs-9=9oH ,n/뮺Rm ~󨗪"JX|XƬ\,.풬 .D2| Q3vhA.YV PQK2zB_2b~XtuꌜλtC.-pyዻ)}ElUI\v8h/#:Ʒrf: 1g=Ssiiu-TRzɤfn3|X(S#AX[72L C~%@0w@#1P>"W$圎>Hqo&a>S9&Azaxp=nIJ ' (a zk6!0o :w@AEݘD[9$SBɉ ě_wG10PVs&-E#TL<^Z˩rPM@% 5qú )5F*ǶXh@: ^wr)]%12vw*뉏5f ÷Lay0X[۴4Uikofn ͉Qz98'k9o F"d\2^E7Qq2QU|8ggre=k6\ў$01 !O=R;Ԧhr }7()%DF}W9K.Y8IKhxUىܖ6QvRT'+WrBټ{ݶY]b+)I~AI)y[$L4u"9gbz )C3-FC_`r rx8vvG+pzW{)=·hae[W-b1K7D\Ȥ3MM7],"CRl5i.z6ʂ*QeTE3H2m <O͵xH1TMZ{ۮ1Ӊ-divna'^)UzIQP!^ ҙ@qq~)+uPj/P߳ޒ-HR@/(XdqL9;Qc K-Mjme;s 7h]ZZN1cd)':zzU7DB}**R`~v+>bzaYq%i5.U⻎pjݕO## dݳc-:¿z B;9*)}ӳdǺH LOk_ VYӷX;-:m_ x7996נ*ݭ YC65ZcF,9:SF3 u1!˦M M8.?$֓h^,AH՛v;*&9,ʥ^Fَc߇#TD=zJO˗"~HTYtdNzzSla@j+aB2WאβjC{I--ܣiMPvZ pY+_Fcӿ rKvG-;yK0J8i.l ; l"< ՟s1xHք\C&FR܇0Ax&zӈnA5UPnŔl M -tɣѶ Ec*lE%0@ANa""`:V_uϮ2`،}&V_4Ñ2p-\3:2;/UK&8lFAFMD\{g(:/dp>x }KF#q"Q$40;k1s?nb``{J^)vi)s lfG+О PBH;șQx %Tמj\숧MR5rWrLïy C5M^"(;.޼ 3 &ZGjD|[El6Y{-ݧ~nIcOniqc8ֺC)Ov$LP5hTX@]<[ M*s%%*CCɊOźBO&2]}k0&H{w7S"D-X8E߹1Q (Q"ʽ\FEg&*5ܭZ?>Bf5΢Qk1خ8u[%Eй{~Q7vl /-xk&!ـ<* $ʫ" Ew+ endstream endobj 173 0 obj << /Type /FontDescriptor /FontName /XDDNOG+SFRM0800 /Flags 4 /FontBBox [-203 -320 1554 938] /Ascent 689 /CapHeight 689 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/A/Agrave/C/E/F/J/L/N/O/P/T/X/a/agrave/b/c/comma/d/e/eacute/ecircumflex/egrave/endash/f/ffi/fi/g/h/hyphen/i/icircumflex/j/l/m/n/nine/o/p/period/q/quoteright/r/s/t/two/u/v/x/y/z/zero) /FontFile 172 0 R >> endobj 174 0 obj << /Length1 721 /Length2 21489 /Length3 0 /Length 22076 /Filter /FlateDecode >> stream xlspf_.8yc۶ƶm[wc۶ӱm3nWz:{:uȉ%\< L<U y&n&&+9NTf 39@@eBo#@ aocfibsssrsvepr`'IXf6@$JRA :\m,Mr&@;g 5 ``bogj/L `tr-@^\MXBQA .ʨ& 03InO4_\'O2?$8ff hni/ޤ1: ` 4'Fupu:MNv{[#FZxix39,%,=J.PmfdEk/@SKW5?KSƿdS֒_-ngbojigPuK#'V2O uy#'Kÿڃ_%%"bMgea03Y9}&NN@;O-H@nmބ7*9Ol$ yKŸޅ.DP&];j(;[IK<[cHS撚y' _+t&%rNR2`G7Yه\)O1dS}RĜG 9Vy9ɞW:w^߽ݹVc(5yTĜRSb/4C(T_[/@GW%Ѷ.A {zh" ĩkՓb"ga 80 s%A-ni:?吷 q`(̪)6.p|SF} xj@A/EKKL\<1wGھ&F9Ww)x? gq<,7Za%-Rpr̊K`yF8&q+Aaa'Ra>W/a~"VCNsX$Cʡrڲ+͢%T,.tNN}^1N4ڄ#<UǎOFLؐR&%9ѩ"P{*Pn}#&uC7AmS#ZʅR"CtԮQMޯ_oey_ơ h(헜a4Q̀Nr~-[lSݧ<]_aq`zfx1@k"*{ǔ%rȃt q%-D^LB +?UIqm28XjsČ%` RX<3*g6P4M gGz?qXټ,{XxLYhXrhl0!:G~9QjZ,,ܨtV1 @, aXK74v#.>z߷5w:<."#A>M^\C"trb|w|b4~(ixѵot;RUgG/8Z5/C ƵT!եm Yׯ;@ܞ|Ax9XUucz7iH3L{i&s~4VtO׶0 rUX0â`<P=ų_u,a* -OK- ?T)/g`鏔x`sr@v~#waZbnSF)l|-+\ k8_&`Wv>Un6Ɔұeb{W"ÚBh TpqP^@H\p$O(ZH@ '.?ķr۲b3YYQv4"p{aFwFNÌwH%^DެI|}"uY-4S7jL\&d1l%A.P*gq@]/hؔFX{tTC F\4^pvZ`hFq~M ;@ \\.1(Slkf~Q(54p4u=C|m?(asuƺ,q*q}oMû~ 7wsAasˢ VaڹssK{"U(> TlkhT``%֟Ē΋f$gZҙ?BX19 m7aRhLq)-a3$t3 g6bzbV)4Ą{2zqv'?l]lIB \AS4[O,z;coj1Rsֵe 1 S5qZ(K9feSIѧ (z@0FJk*prlIe3)1fXWW,[^?q@ /O݅hᅩoTUL=ૠRfJZd@)%͞o4o΅e!ZͩK7zC&G~CTSFw傆 jvkحXvhcl9Ⱆsw&Ym6L?3j I 2/78P@HΤvb9N$kr ;46nfN^߱KŝκDbCijF4x8Il})6$9? ̒qО7H%HU+usC3)"ꂅ{ 3QO !ĂJr3r_n)7 ~Wj,rjwTanODaG>/ gg?^2>5Nr/K=?Ӝg[nvx Z+AxYxkpv˭*P\iw[-7cDъuﭨn,mEuΠHPcn2vIc@zQ~~s4 %m)ӕ HPl@â>?Fz 6$98ʁg27.Fqnܻ ڿb":PM<>QmwטfT/)\V.$;pC ᯱU0{4KOuE26 =ӆ($ ʕ 88w"i_d3`0l(mk`Փ.j?s;c(4tF{ka|m~$8\TU#gZDv~ReD17{c4az xCܔq Eb?=7z(3N1fþ@beg}M6x롢seU` 9a|x~IZ M|T(76Sdh ʫuY_ml( -§j;Ιd9жS/' O[g>t[X $z3 (sdz;i81r8>@I,NLiyȾܧ%sxIRNGsۃG=9y*zƦes)!ӦwܒZA) B'U߬VdVn?w>*jWm%$pl 'MA/lOO15*Nj3ٞˉ_T>Ø?ed 4&aBD[yxѷ/;_ ̣ϵY5Q$& {rcosߤu%Y5+GY 6LGl;e((_ēݭoݻ7^īRRt\&K4F'n"V:CwP`cIOnN[t *UP3.6/2ʔRZxrs*͑kYs<Ƃ+{}*1baz0ui!M\,-;1qeӭ;v#l;oSz=.,A>2QĮ4K{RPFBKȨ9 SOea b)>L vrQZ#DOhr`9/Fϡ;Ze47b:C S8&k-; A Ø4{_Ni Q^rcoG},݋=bd_ib?3UL?SviøVX^Éll1'2F%6 Ñ\ UjF uI{HrpEAFoeYdHf1X0ժPLxQA}Wp6 ok :aPi4G¡u(_f6_r]cs8d)0ERJ\FcDAԈ]C VKp/ub<1.RWc1p+Яbeŝbf2#d`4RdY#yyg)jv]ce gHL7x[p|K;XrCȉ+ɂա-óҒ,a}j2-r{btF>H",MM$/ IUuyl 5bܖYEg-nHpJmxhvƒz!;TmwsUsNrioo1I,!=M !0i\X52eqÍE4.R [ ŭ51gRr8)Vz 7 t2p~yKGD[c¡.OXHkIc=w'*"Te@dpA3z027>F4vu4NAJF@INf$vNb"O#bO@Å?*'V$]F1ɚ,FG=%jIt)oˣ =MzJ^x됄d_`lPά]H1=YI\6xc%V *[~dԚk:Fzs,7#=;wy #vy]@KO13՚"ia:Y>p876x _K_"&yC? &kTqZj.#FMDO*{c .@:7Q!ߺi`2mxM5Ɩ%j27#2"1POعe |8Kehw({ !lTfR(q|y)zJ% ;FX-P[פ^5JzrUX`;R`Zi#DP(_;-|Ә# 6&Յ'io+ ;t2.M{#"Clf^Aم"Xr?C~hodg.{E^}Ă=FG e |w+5gxݽB VLb<_n{~ck͕6䴯K 9Q4Y3ᆶ{7Wm-Ngu9d+g^L"9@UB}VkɣIRc9C"12yKEf9j';Hs'ɖ$zng3"fh-H`҄A]|3TYpU"WdhGd\ƠRB;T(t[TܡnH.8@k(b .-"etER ņi~$ARF[#CTr5 nPN&)G+ژ #{$pj\+|ъ&q "Ng߀]{ A4] ?͘LOR[ Q/6-,G&I|mʯ^:f<m!:r,?ӂҳK⽸ԿwޖDžzD%-Z+""eib-Tp i~Q8N,Q2K;n,.dg|?;HSlg9g[#:E|$xPUPى~?bl dPP?*֠I|@ϙ0lDBp<,(odGr}D.*ߥ]u3o;,k1+I>3/-{g]}QVeýp6VoTQc;thϙ;v\i+3C8'أ܌rڱ7Pu%;f#6aCn|$P *[(tدՂuc(c.$xkWrGv_-]ˑ_ه 0=yYdg-ނKTƫG#[,\i*<1*ګy(Qu z*YВ<]qyGnw~;Tھy*q<;s5 ! _NnW>iv # Ay=xH1،FD+^{ Țn !"6@T'\k#G8>FQxhv.WYEPQtላ;΍+,6 `Ѣ|Ste@Se~j$RoDýc$F8+K-h.p6c4e g+ ]XpEʳqv/GL4@ ~rUH4^ȩ{ %9bk{\ 3w(vE?-*ShXYDBՆ吔A 0Xysv@+Y!iK/Sr Fvj RղThq4+Kw:^PL&5Ǵ^ zߒ,C9;=ֱJF'8룅hڿ6>|WZhVȷRd0 X_ֳu|#%-ዾ6]óĘ*D6dd;k?~D Aܥz/̿pTLv U;>4[w&H8M:͌"Ȣٺ6uwG8I$r)f56@缰 )$`+jo5qa2cnK{ZHcH/<&5{'8Ki6|188 ao+U6te2j,T ϗ(/\8 CK{x b87L|?Mf, LYB=X/3E|"#pfᷲVT,TV^mC h˒ T؄áK mq׍ iT=3߮{`w(B $[لynP_[s!d? M̞ %61UNγ~^6SnO# &݂cܯZ٩eG 5&|9 4ۿGܹ[)S/L)/Odnp ܙǃT%TqEm5^-M7=V9錥K7p?%m]vغ(kUu'{(1Yb}/,/؁<"5]"sU$If8ȜU>A-~mM{prţpB>YsĮ Õa1'i1U$E2|YUl4ި@,8&,}dfh4e=hD[PMLXuWśL_5wp'Et(WW"%ͭ@kdrKyps69td^~7.oCcŧ[;{@Z|<[7'<n^bHZޮ1L+rym,Q^?7T%tKR1n\&CF 7HzjmDTL(*_9XDbk7 ^-;iAU a. ?(pfIAhniTMdH9eׇY$y'd(Ft@[~6|ū6kp63ߞ̉ /- PhCCg.TL@"G;1Y*xRd՘ޔVY -XYw2@/gY|QrluzHK0F ?$D} υdxxP)3L8;%gNu9uݣ&R8uxA玎@F)ȯ1o +(p7WL(?N'?{ %<@Tlur> "郷M| %hL''@@2_ҵ"x1V"{8"?Uufk̪# YP]bv{>dD|Dox! u7ZIQ$(IxpԆ쟽j0AxӦS ;!]1aNã")ۓva~ê;?X,0+FߋDB0M7Z73\ѫۂG+|z (b2dѧ#rӡ>0RG/v@V{DS K,@6gMlw[KE0JLE`Yr`yo=p| cW>"LjV xd7nxc+{Dxf+AX@ G.}u[)p]X.ůg0,1 iR 43$U!f:H4h]QA"==m-āV/QC":yAStBٕfS+e<uCkH PtRǫ!tube$,幓v~uؙD7΁=ĭ25P 0Gccd{r0pT$BggkȖZe_ f Epb?ۚ6wpZ'JGDz(2YjKpAsƘ%Kl9:@(~ɥFh+&,}!c*YYnʌAYtbeL3%Y1J Sqxs`q sFi:O=G"bJ2}A 4aEž~hb8˜ [Ylt^V&jۊgPe땑P"`t[ct/[wQPJYwqr.x惷o i|VKąxg/0DO>)&NE6jxD@#C֖}k]j-=W xHS`P=C`O4wgVd**,&67 CU^ʇ%{'@UkE<-|ca 8gp}^->yg?IA ndΐ$&:H3Yl0ʋlSH˫, NWZK/maF"."t7mÄ̵TU,MǼ R Pޜ'5qPzR7[P6ن6{i毱^ց@Bx,$Lsɕ!lNkwIҩ0v(SBà Ծ Qcq)KRdž{A!7p5}'٩g|hOm8R-Jvy/:sס,IahoPfI/]ƿUp>R,FIud @듑dY^ 7t<]B"6Dm*&B| ~Bm=9塎9g'LXXxw˼ֿ-{nd*`m@V=WZ z"3 TdcpD{q2]"m`64fhWP++t'B,o?ZqlM>5RʅS=uT .>1d &F&ʈf.%/لRAj$-3\37*x0QNj|5:(?_ˍG|sֺ+k}]v0J1t 7s]{e]D!@g?D46]žU߱HxZ?˭."N;^n9jew1qKKL8R$yPk,_<|xv1+]`z֣^1燭7.l V6S!%EY _E!z`ԥFC1D:$Yz <hGOPV$H66d;zoLBOB %[0~g,V77"aVbJ d(2uA 9Dx ;BcDZ͡m?rjg,t*3cR;48)UuI_.+ɯ6֒h=gV6Ԣw&etvPV#3D i'hHe¿Vv^-0ZL5i0^;߈q^jʗpZn';owBX.ٶm4gs!-9u^V[yԐ6+QHu;@}mդ1\=c+ &4Jcib g?W-D -Atmҁxc`kr0s@2/҉C%Bu`dl b f!D~*AXlm!ok D %]#֨K5>.{I8/ &Ϗq.] 4}rU%`Dc_a4JIZP]*nzOI:Ѕ+]pʹT&J6tb=fR`-bweXa"B@OP3eH9 {A-ϸ~6>CѫiN:fh)j4x k}vl6F*yM{ fS\a,cJ#gBĠ|7EGw€UϡQ0J!Jl9 )h&l.o(*e%]v<@{oHoY| iVM_%ە!:oM|شgkE?.A] ##3¸ؾo sI3[>(UHu9VIZ>" u~#'!糺dj'IjmJjf}s#gD֌m_%'n[CDizI&$$U:Lȷq?_ ƆK:Izbq>޶eTUkK 0J 'Kڰ hZgz3^蓂O@H>KRufxƚPQ (QvR9Wl2ckjsymI%lH(B_:做@ ' <{l Wmg> (M:51x$=Y^f\ fxy L dt* =iX9pouO}]r5-) 1H C"l=+NcT*YWAޘ˩RyJ{ֽ5w᝖ͽX)O}Ӏ6>?C=؁Oyf#O4tYeu)'/IRGpG1㧖N$g'7ϡ˝1Q?t藬qq?>&ۍy4OWA6ܱ)R0@t%3`is ǼE=zЖh[C^$g_f+ae,0GGX#m[0&w- 6!sθh] M e7oVVѥJ,cLjx Wjeh!D]ooKx^FlUM-xC4qG嶱ޣKCfNZr=DM P2%#Sݗ WVoȀOmDz$g'tlܡ^䌼.Hc E#k~GqELa2ga 5H$ە{e?rĂ2]h\#12{aq9~w٘s#>;e%=bsFYհq"0(!YP:BXPb3ݟ &l)jQ|l &P>Np 0 `p~^|oCXANWcE``f &(|R8 ]=9/NG{!,tL΂ \f U ^5f=2Fp RJ,R@FB<(\f RxqHa(f8{E_rܙH,e]-1$?~(h ?y~ح %"N{ ѽEc#s?p5nOG֦bR]UGJ|,@C@)qౌ8{R5jfoKݐz>D]V00 u5Dfܨيh .!c 2r <r?qD d&P[I2d-] >;`ɇa\m>jolꠎ1mc۶EaaËSR@{V񈓔P&~@.Tz%5K{ PW7($[\hj'L2 # ϋ`;9,ҕ_^n-! ‰6+TBlEL\hrT9_`ݶ.%?2D }C8l"l D`WӖgg%\5D"[ }ۼ~&J6k&#򣼑10-M[VBI,˪ՄJ4U=o)vp{1]h5CB@fhiGw `Bن._g1h) /5e*c`J]o]YdMPߵ)eQhf+Buƺ(/S4oy{ug|*[/^S2;bUѳYwTj.X!+mEޣ\ڙMZFέeR7ǑSu n2ɜ>өSlxx=]y<=t% XZ0 Ekګ.[P6wi;UAw@gp {ӝB)OG[\IcMݥl_@VbNnK5yOΫHdu[ 57T]7|`n$5Zd Y;A2(ce:N &e<%9zN/ys&R/UJ@E'ii7R;;OQ#$A.[TބbAxa~2Q%)_8`i<}’0_:+Ps2<'==0֖Q O{uAKfBW 9MDukIY>!kq<'- D!nTa \8~;^:O{Z:Hӱ`;f Ϳ˓ΑG50uj[p&>\HYZy>Gd}J# 54$'y46VtCz2u4Wb&n)Ji?Sqb"(tC9#ݒMGV=csӅ-BKp ٨ < q#(!TH쳟P-e&#CbǕXuh@i;~;멩 H iDj85i 'I{ 3۔lpB2/M!H)3KNak6]%3Uy >7Q~1Ú9?.O2πu/وXcV`$fnnܷo{/['/*>0spq%R(e_JAHW2sNxtn$nRp߄Z@ٍmV'69'1М pcnN63<#VWQWu0sJD6)ӥ=":Cy6AeޮB\{zMNW(oa8Zy+,>` ?;aFT}&?$ʑS)+8T4 x +4Zieq$|'L0=up Ցҙt5eu"ai}B ݗ_2~ghhG`OX@p228"S>aQUX /d`#=0wJAZ3`!|?%$AHG2260'zSH1ULҁj'Ɵ l {!yUΑ0!!=AHH-t3cFXtoAB{A?'^?lbܹxeHvY3>7qu:) .o]%X~_96mGu_=OO\U e+<;~eSd+&00>۹ ҁq7_pڑ`Yt5y0=6׺1:|C_/.j|;j $Ʈ_՝?3ODKgu_I1qYɝIG⛙'2'u^@iQ)k^Ѣ*ne_8Ph!gFV@=:Ԑ/=cD]z<eywq~Z)b> M`u8?i_een1}@ϫSVU, :`j7bВ< Y(]uws !\u?)G/hZv?9 li/쇗i0D@u`V[?slXT)ݒ\}!"?x K;#}xeҴWMx<9V9>,qC5HQsk4U;$"n1_Ł?mQj XԒT;0lՠC!;9y-ztcS^^ВQ W FƄ̗ɘ`4m(#XVB)D!\V<*u(nW%+9mgx֬e 3T}7k>q;*d׻~x[ endstream endobj 175 0 obj << /Type /FontDescriptor /FontName /LNIYJG+SFRM0900 /Flags 4 /FontBBox [-196 -322 1502 937] /Ascent 689 /CapHeight 689 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/C/E/L/O/T/X/a/b/c/comma/d/e/eacute/ecircumflex/egrave/f/ff/fi/g/h/i/l/m/n/o/p/period/q/quoteright/r/s/t/u/v/x/y) /FontFile 174 0 R >> endobj 176 0 obj << /Length1 721 /Length2 27586 /Length3 0 /Length 28177 /Filter /FlateDecode >> stream xlcf]-\ŧl۶m۶e۶meۮ.{gܸ_?3W^v}HJ(fo`HHPSed``01Ð ;XۉrMMʦF&# )@@aLo'@ focfilqsspsvsr'Iba 01+hJʉ(TvN6W#Kc)% `_MbfNYQA1y900 #O3?hSc'UGpec?N`&.#SsK;&igf`ῡ9@񏆔SЮ66r a{[WS'@(C[K_AH?1e,faj`f6HoE?ϊx))+ J(P373(+Z{K`cYC'K6ݿڃ_-e231YX]cW''S; O-LM=LaW썹CZ*D+{`mJ[tk2S"eM'f܃ }WhތKe$@ةOϻ2+8YIg$/ vO!sI^Vv>9עչD 'RcI1ZjSKD!EkCMQ! 2F@"~ZzfD)9UQwpZЭ r^,J?>e j79䝊xRpd&v‡WM9S[<ƟR b45au+RKp76i/&sz#2 Xw 70K ="ɦȇu[m͈L_U(\=X!cJX4RJ2z\X,ݷJ8,PY@{ W]e恥[cٙ'FQ\ucI'ʗ>#L2𼉽`|uqȥzU'r4MX'T 豢nbj Z b\ 17D ԯ#chոOMzwJN@R4 tSQW]׸A"}N 'zukK9P=?-\@'8gW5c**Ln2QО;f.q}“&Pٸ@RjO^J@z<"‡'ngCtuwFN x3lC$EA4|E_9}G}{:tK%/5-86"4iU +\9Wqx04q^J }0Tf%=[yʒǗ{]2ezh;UtV/IĻ1I| pvjGnY1qr%hx5xzC[) (}|b~34_r;%w锈7aa4f4jҟŀj4~cu`%U8DW.?4f ݇[4CcZf*?NfdI;zn>jF n.q i!~o#+2zrFO Jc?'drDѠb}̷c!ڋGp!,W` c݊uk^XeEW{*͞~(w (";abZg̘Vt`zH\oӧB9H8|*Za rw"he7'*#NcgS_4 3SMK+@EKF~0nŌ3JMu&mpWDfc&0ӿF߁wMxA@@f$FQ%HބW ̿N\t މݎFpikyG4L'Wt1v >g hn g21 w]}M^ܼ}n2 EN)"HKϓ؃JֆkT%ud \6-8'@@bHn #0VJ[>F}na9C2eRoVnvO(\[W0pAӁ(bIF A @(FejuZ]:~eO 5 9n *p\\ mXr-Zg/Ta{$]nq[DFӽ[]7T ("kOzJ {VVv&0" 7x6m(Wln_9 ^ 6W@$5 1bLJ27llqz`.+&%3|Yږn.Fq*׮XhV@o[2b, 9KDq@PpQjCټ YÙzH4!ŚZ\NJmcȾK-ŵ0}"D&yڶ9 }ItKr%ji4DW9(G.pm熂a oY`s%SwuChu ur7򟛆|Ơ #G/3\ uj5N?I RRdS+}ZqK/YtdCy*[;1-ULtNi,f꽚 uor;)2%b$;Ñ]ěp4zO=w mPt0h%w!¤F6P?E jsxRO-դG|"8nޓXWS@"7֛ěq_v p1(HU) ­QLIL7N:lF~XHNl.W& W ԴEϻBls DSc]d k({|v:!PfvCWPNfDEFd { g㼃 6q~Rx)qƗX֗!e:C%T;xWIGgPN=^v<#P=ϹJwe߿QBas!˃/!eQx@dƹxy+Pp9 `:1X=,NDiIO׫}e,8hh'~Yy37!IS09F ]zzS'xBSzb)5:9]syngeAGVtnyde#eȇO67zlR'd{7-p`5{BҽnŘY::CE{,3rJblОw>/W|}M,|4\zi&Mg#rS)uF9b"'S=)]RKl]SȳL[ |y˵Q sөwRE(z(eH0Tzȋsf[7#q>`*A Ĉ-%\D.|96x1.sOL"Uj1-cJ/F0CDK_sx,7ziѹevƒ$T=3b&j_z%с z.F%~J[:a3#;q/*E+mf,Z&Xa1 §yhHR@|չa;Si:989|5( +~{{#^ C:i>1s-wP7M04D,e(w~E3W l3"6^UxH9W>oxJP}~}.dMVsA'o#Vr!3!wJtB늃gyҍMQU3XNt瓡'M2T>0Dt6Nji6\㵴NhAq0Kam2JĶƇ~ Tg^J^`IKcs>3r3ŵ@ 4fyd@X< g3R4VtxtA o1VNM̳M_W@tVO'tCgnWlQ|7Ι!n;>^L?YyL$)cGaxM}.2Aca?m=3/؆w{cSeNs"R?fo3+[MQn&> k)Wn &5ey??gCj6Szukj+JF/!"3FA׋E)ؽo`խ8R#(ѥL-߷Q`LX0GWˀd 5}Ӱ!gWB*:х8~G*bb2͚Js#|J;$DS\ -˝KL)҅B93#3F'dheun(ۑ/aXjTp Ff1jhܵROg4\5j|ͺ~]┿4SQO#r>z/{% 3rj93֫/.? &6Ajމ.f "L*v\rtS딾UJbjy\ld]~z,"E|hz1DQCSYv HY71YD.0xC'S\B۫PTXKT,FfjCSv>d)my{>+`0ehWVcsu \)f+Z94uN)$ ABĪOZW{'wĠ~|nˉ4M?䎣򑻃V+ EϏ7+k(H lj Οe+r_# 6~tr̍Qݚ(.c>;_0I$1=|L]W%')m[pǡ Og$.|H#Аs5Zhs$ZA(%n,_,xI= Sn졕V*y7a?jSZφ"jdqӏN~Ֆ%S9,`?tQE5O8MJ$>8ş^qshl'0~,t8I+8 zS,Ǭ[z7]N~"2pY"[ MщWЬ vmKhuaQA_;KaA,m{vVjF}O4G֬} y{ MgUtAoM &t:DK.މ ?]Z>\xunBTc)'OxIZ62c-?ojƫ>>Ŵ.*Bb{ kx TcTPiZB~òs1)ݭNq46 z 7DEÐo]sB^Ws_JUU_^ek?y/!OE(>@uqg,_(Օ(x&ӹF^亲,N奟PB ZC}L9B1r1j-bNܣc{Cg=٫UAmh+ maв@C*Ӕzb6S+jq:$uSA,6_琜;o%q3{miam M" ߻wo7mTmt<5$`9(.*(e02"[]c6YY4buMXTlxEUWL.Z6~8C"P?dIHn*/&&rWrS>O1J&RShsM0Gyײ6%ZYkU_Xgbo+K9r8}BirWA]4ӈ7(~m-֨xRZ1~'#>zn}L _,ůk>mD IkVLi.:KGo˟zv;*ZUΰoR҉+G$aB9RM 5BM(@>'eU@Zgw6\5)2D0ER> .nvvCU׿c0HPc/K>3}ؕFY|HjIFM59a qKa9 ;{_pԈ*?sVq u-~I?QT'\e8ǥ@cP:T<(> S7Y ]u,&t8 j)ZmV*vڀqjﮚf4IZ@GRh wT*㫖lɩ3,&;;a/σQ#z"(*apfP;~ Pvw(/JƷh^;p8{g/׹X3dY\l-19C ѰM"0~^A>v*hѣH{:TEo#Ċpؓ$oR4 # e/<8U\ _+\3(D IV #JP5ΩҼQ.z@͙JiLj'`'_EWÿrPfcaJXFBJ|-\a~;kP5*rٍs›=AgF?63I kp`6=m~yjYk<Ůd˞T9%"65t_a.wMPaHpSu@m/sW XDdsDtSt jcۑ3"lO/r]=Q(n-ngq4[I.eI1H}Mx1-PU)Y+eGUH EٓD 5hb'& {SBf2}Ia&Qb8*S1j&B~ՏWrn$K㱞 !#E\dnFV&:(.r-&_%=D'g,)C`\Gذ`&Td/ s0)v3'!Sk߫i&Fk@ﯚ}vU 3:]{Pp :4 ҆GciXBy[W2LY7*4_=K;H@_(EV"$jǟ3(Ym.~/T>cv *CJ LXnx>n4M\*j4+0Y}V/eB2cة8v2\ZϬCCquOdD%`ߔ}H0 iz6bt^̭ Uq:t3cIr6D xkzA"mN9,CD#J/~"Y1F -r݉0h^}q{1p:/d\XdPhQm_Յ |ifiDM4*Ri;w* - ll2+)>!hA;c$c}rh>lU aAnqI:WJP?- +yeH|~Hp71#}Ê޼I&- kwI<8_n{^ȗ&Q]ufz4C]! 6;aMa5ՔZEL-PTla=`( +J>g#W,mZѼLmt\Qmu+PèICNH! _V;ƱwO;#"-:SoNtH ]w F9Qw"R5EF%|ʼlRb0KZ/iA"qV4Bsg_Y+4,M2Es6@s̊'@H{/\fO7R>:4YF` ^$zzcLnj.fڙ7^q=lq>=D/?x7gr-8EmL24\/WN1 *zrE uc+g~i~}{iëx#ݏ`ͳTaڬrͩCM"0ÕU=\VshE0WS\j \S#owNÃo&ݖKӁ7U֞Qrm E9x WYG* o-6 UU1 7Jlb^uM)CQG!3Ra w5׋aZ.tpk|,\Z%/Kk-E*7؜,AxXkpb;RKU`-]vMz{ ўZ+l8g/{<=q,nB% pMHEe፳EBD55_h 26[(c-H;/Es7VPJ=1d[^^|\)Ѳ9?h7 :n BGJ0Hj39ѱ-_X"봍cVJ,oYDm"[G2L-^GZo f.7ؾke.Tf4h! ψ\|RGbq{ {A<uw{V a|r zu KWO5 34'49%tg @ٔqY2'ļA?Z(\"ɷS\j{j8 dr.~N꩜*U#\9t=HZZ/.ՋOdYt38S; D(\eyP;3n\Q_j.ŃJ":Hw۔dkJͰVX3/mQ. +B0;n\lLn^[_ŨIIuuZhPX@N,%h謁iaMb|Zo-ER? < @ҵ*ߘu1)9I6*Q %I_ lr @ڽv9GԛPϡD7G^NdOzKuffҶcQ2WQ$C;'I~ zja#X흩?"(6&? -#o2X*G|857\ˌxCld,܍ $MkѷY> 7 5q5mLwvY=׏Vnȶ$&5Ԓ5yR"+u5R':seEm*O":TP-p0aVք(+KK-_[͒XX vuB+%)JZ\v4? VD qDtQ\6/]l8L}"YJKß 4w c(lIƶSX~C6~BVRe}l^OLE%bNO3{FJ TtS WN`ߣuݰԝtku8~PJ*fZjN%O|H[TiogcjmZ;uFxHD% P nu ǹ_`GQO?/;HWKh$/9&9&:[/?WޗQ_Yڣ8)VB=mtWh]5YHx-*>j]أ] 4A +X ފؘ#U5W`<>z:pUDӓ®~z~KLIx*pa RtR&ݡ7A:,|p M4V%y,Ty/|Q)6,bztq r<" ԏGTGJAФutbI*>]wwgЎKj*cZ`#ޛ0>>lHyp8f.V[DY+j&%Fbz!?;eptbvͿ[ >xbps/沲6 +?-]5Z'Tb`9uzP\m*eR' J.T̡)Ҿj4=!q'@;_KwT!QjMs/z'8T朖Ԭbi5䚹^H,+2/V_ƀT=ZleZ\DQԷܷu "8m(Eҫ+R$ QCa_Ce3âd8ތi`!1~vW+4}A_mi~ R!#6z*>4G]rO9z_xur-LIi@sSl4D\h ƚ(]N_ (`sXEVtW`OSLJH򱃱2teG,z91FPx[X)a)E}O╤aФ냽ڨ'z33f2?ľA0)YuŒLA  j|; mI7szm[Z#N,t0:D5aVn(тcP A#ճC^~N.|~: bn"o Ĥ eY>D*<_ag[zcDfڃ56 /{a,$$9'(iB+Dy4ݻfSN䞿u8ec !&ai=kB.1 | )B#9ՙ䠶2-Ndw3ʬ).-+nA+ܨ:2V{;H$b  B%Q´W=;%.j;ocb0MSJ7/H2)Bd?90V^ӄ /&}'o*|I.};Pzd %5Rq M;b JԫV uX+I YfouD-3~!ޓ^t',@p|8TƄ,\BPFN5PILYhl9u 7J>G;Qx>Uvd%۩MpKk6q3c/Lwj(W1?RMo-؁2*p~zK'gqZ£MvqBڷ#cҁHa+g`apT [)N%pZRc9Pv5I#7 4*_ܢ+xT},lۇK)Go$1'ɗ e".uk]gwHɉ) ]Q8v 2^ N Ŏj1"'F'N^ >;f~~R. 5gi\Aف_ACvQ̛[ء#^bP ]W~҈\Oɦ\XuRsnã<2|W (wGЍH;/!?CZLfg7ҙMcXXNLr-,B"E;ep\+ L u/?U堌_lr[O/炁,p\)q+܉b5$[yxN\,jE"ȼpYqc}Rdk(o=Q3F1 y#gu:S~hUH=bߟU+`ESFV¥ohd f_jbh5ʚv3~to%M(G''Md#Un֏ z4nC E2XS.o=<;lNm[k͈D!PyU`\?s8l2.Wj+W֠iEW,ũE_jૡEHlZHtLC`W`.\sq$MT z@ `I] . O?S5zO G68@}B[0ѫRU{#{>eiN t؃(}|}R(@myz%#pE|'8腨4[/WEǠ8-mr[]iW#F>;ȋL˕q0z.ɢ(i&ϾFxpO(QK8݈y M UJd}dvcpuC!=ϴA/Lڇ;) -" & \rG*vV{k ial8d2sr(E6KR5{wTF,f7Ө8O8}a#į"#P[<֤쁛 Q.sy44Y*>Ly В ݉|EdҼ4&ge7Cr2Z@+&qMV {$P10GܗRD((F~M)(sl3+j6we&*\u#zWgIm%!ℳMgwMFDYwV/!߱^+mm 峻1??4+^sd-*23W;uTݼ)\ b8n蠦uI{#vRi0_I bm\V,Qܿ{> .1ݖ"HŞe}b-qL n @-9OR%GihkX5!Qhpƽ?|fڄuM.R;1ߏ"{ Dyk @7 F $_0%hpq)d/Mmֽ*LkٙQ>A練ي#6֚p4x6/cw )mh22 Z>P?zo봻"l^kGjTϩGkIًFdKI D69CQ tGH(ڋ蛦3bx(*E|pfyԸ+%v,O:3@Ѧo|brRZEU}'&ٵWOjIQYm o QD2j>'&~hՒG@L>:ۜvyD͙4\ZCd)i.߲4G$ ץк9A%{_,Q%e9 ׁ gߏGr 0jt҉:=oE44Q^pȑ#ep Nk C+oN{ OQ4J 2S۽KJ,[N*sJW 54]'Tq?J5 aowl닺BAl4°4(5(ܕ:ڴ f^fV{QeS-y{E|˥=xE$n.'}m=ř'FyX2k/hN_\1p'K#FwZ*l+Ib.Ish b1urO#Pu2k:U+6z8ȠK>D(Bgvz+T2䫨ڂCfx OQqftP|{xkfH+$ h,S 37SAtRE\z}|ۘ5>]cpW hTXVN aN#~#+(&>3SۧpJ)m=az+U>B(%sJiMg kc)U oRO;el9n e6|_0CUal<(^.VdDhX+!f`"6uĴr/no8lvxYvʑx]mlI/W+1@gTwr@64YO =ETH`dž%19}إmT! :3b)2c DgpxBD,NɌ]I㪣c8pp 'A!sนa&_MHgp}Ok}*vfy|{OZ]ٮY@HG8uG]'cm"c:1EJJ&jdM|MiQ:a+8͹ҭ>-,V8 By(F!q^^s"&6wV]ĀYøх ?`PǓǀ(ߤ'M)wxK7A~فA thͅ4x-M<;k!O]AW Ln 3/1pG$p57/JR$!cO3MaqGd[vOZ#j@S&%K!1!ʰ!+|= =pǝ%uTp.8Ld&@#^K mrjZ+zt}/-'?OP}̝J18P`b?C֊ug]*NYMXlVoק=khRs#@FM͞}Uz: + 8"{EIpuG#qAZntʿj\@Tz[CV++X@v=xߵ §<u BC^x߯ kkndmy֪Y+ۃW7ƲC#''k]ԝ8A( _JxwCm,%Duh~Y]'ZG2nm" Vͱh4~o&D'&S*}㻗AJR/ J3QDq'~3JQE1c1jK%9wI7.)8E!?deڊxUsB\΢?=/e!enaoZ FԲ+A<kmI[2&c,5EpUhK: &soGNsd@iP\6h4&z$$}YR]+n dyҩ̺l7JV'Xq*iRwʣe'or(/c/`+8X%jǀzX"`ב w{(>qOؠLKB 0nY ,S mOF6}Upb5jr=B[;U͑xgȮW+\XּkV?cWzSo&ٜJBt(¡pԺQ}Ks{xMx?忺qb0:+8/'I/EPtK_H!QU8yd=/ZZ4B~#^r:;Z%dC F1u~(:U*8lT8H -D UDz7<ː&g=zGk4H6L WxǠc!'!XxfbUu'Ź}@ tڄ>l­s}l\%/.WQ,ǿ0' 4;d|B!Ʈ/Z:s Jp"$HBץw/ ~*^mqw ˼jJQBӕ]ǠTo7[ qeQn ^ɸM#WQncBib%PXߎҿ•G tFaWbdCjǴP9g6}Fsa³пg&= Z"a Yی>9(ve]c2m@ATƣ׺{3Ff6D Y FC{appF-|P96j5ꕈ¡!ռa٧1sa2M7O-57N"~Ni]L<>>ҥFs*['!M ĥhiYw!7#=jf/.'gRR93A&{Sbm3xIAJ0',B`Ɨ䟖"gfsj1:csOק u/&"x2l-"g] Ƣ6it* 0(A!Բ0/۳bޠ0I%.#֊!CI;U]Sz/…aIq9iH$Wi|֗R+n/nܺŠw$焐m52jWzMHEdbNG~Ht.7#ʑLIᡒ^bb6H ynO%__@ bXZl@Ct׉bdCXLM菀=Cftﴭ-1DUC_)}}aEhDl dH^m/^ڽnY1OMSHgبs1C˴.5E {:D Gd**CL$ Wћ{B٩4ΦX^ueկ&u~AΜyM R.g'n!6Rڜ12&&0dG{ݥnNog"S1?XL0Β0MDEE5 IG]o3*==o׽Ѱn-֜q&L+w>D6"65 PIss>sr|Vhp 0`o7W/R*[SDZ3g˲Y5zLJ"(݁/Ǚ 2K -\˷H_ a$s[-QFjeͪO ?7+n.QS5aWO<ch;߮uPbb&%劤!lAkEZd8V{M\`Խ'.[iP9H}tR ==-r%b>z{Q 0tLP=bvi٢1)OMd$ck`P%5j|tKFr:?:œ>MI^)LXٜn3rA=)n@m ,oH\`ORFuf޼@S/{]19]0`-&TWZ>-ۯ:]5Kx]fg._ #LQ¯D#XNq) b27ȁ#o60b'8W׍ƾyL-DFѬZnǚj-"H!Ffs-HS;1ҭi_9$_m'wri{@j%(#L@eɰ$ohQ=mx08w1^8fSHs5SE/N8$p9p _J%_! t QK~BMUȀAV;$[^W"^@Qw R0-;껗'T>Gx%R!ЍRM*>fBQ+}.V#_`O`7+JJYpK_gV]lJB,U#h.9%nMl$H13Kr\縡*!Zv NHAW``W1yŋ`Mi-bP_}Max[ 6͜cWV+MpFޠ>$ɥfنqE_>UO.|3Lyۮo@axSu䄮y"SjE>z4ĺ u0R:dKOn؏֘jo'oK\v7{}ڿ]:T%O[;j?$kK3۱.~MQ>JV_R=PD Eq'<:oo16m9c~7[_ Z ?!.f),VF Kf26)-wXa0G[[e9%tQsf |)zrǺ8#3l=5k|\\qLxHM$)}6BA|ӌHy/Z?[|2YK J1AOb]y&́C&s=1IJ9 69f(we>CIhn%-ܦIG(vj2WhHwk~#H/_LK]Y;FrKVׄS_JA9+f4z3{z+wi#J> endobj 178 0 obj << /Length1 721 /Length2 17486 /Length3 0 /Length 18050 /Filter /FlateDecode >> stream xlwspfelyc۶m;ol۶1Nضm۞;75SSk^ګ9DM PTU`a03QPMܬM܀-9@ `a23Q]-f4.4Ḽ]vfV~aWwFwA7+ SR֑QPK)j@;@ X8̭ɕ<.npq(HH*)$Ę&y;k:zDv&O?]Dp,,sk37)_8X88S6wwoBP! hNswrẃ.UG{Lq3GcOU hl&vH?4vz?zsv{LRʒ:"tc%ͭ,jnhib?M,'W0qs13z/ 77ag蚹-?7@/꒣_MfsįJHZPQ˖$ņNЕdP&}MEQIPK)-ん$eCWr@DY0.ӎ_iOqJҷ[$\Gy6;|\"}ۯ゙?W⨴x]G/)!k.M2l{C硣-kNÁRhP 9ݴC.M4<5R g`0mb%Anh#o-PZPs\U{S -o!YVfG@8? )Q|+ao+ոr&M=(?v}O7J[َ fypk!bW%LڈA`',INYI"+{kr:G7ȗ#}=/c\>N4Z=` 9Av.'yZ?7p si>ֱC$bq攕0wuCٮ0`ك׌i3".)P4+w{;hI$g?'/4-(I_ vMPd#Ƅ1?| +I2m*+4V]JlWoU9YA65V~hn_X1+;apWP0+fPHqdjAXۃZ4 KO!@S?spq9y4XDK(=A DC 5fg-Ph]`% ]6? ➀{nsP2#QY:Ju MuLiNCc)j&ޫ#cM.QiU0IVy@rE8\EFvn}_UmYiۗ(Cc}lKk-iG$ mχ֝uڑS<78ى$GyIa6VG7.k1<,k޹\ebMYgR? TۃQ"K4>b^oedf4ࣳcF ɯv ߃9.=)gxŢzYo3ԁ= b"BCtBwt@nb"C'о"Pi F/ j #S%hvbƎU+"LHH-z gIn{|j0 |URj`O\ҬSJn~͙ÂBM*Zc1"Յ؝GM@BCHO RT3Mk9~h,?$Oro91+ɹfؽUap0N|m؋#kx˻0@^J巯&M}_e0#cc+ SZCM|:a7qj"l6K 5M8zah,qT3B#W=b҄z?t9ʌDžcf7=gL'[GWl*nb7aTWUE:+ ӎ1[F7w^x&F/ X ÿZĚ}|$ |VWbwEe*=JŽ4$ 3sOB%]WF/.^Le\+1-Lơz С\N1uصCԐ DEg,ʯ&{s6CvRy='dp1&w>[tAFUBHƨsbuqU\U+(Ԋv72X뫨ۊQ)dٶd,74tI5U &pK_&-'c31iUzDeUv: DiݧgmپO0(2|Є<+&JxdĆ(^̙&:< ? +Kw_ƺ'^-Xu;93 Y 6˒ )dU]U*gքi14 VaiFjae۾$ 8ǰ\Z4{\'k|.Sq̓HmW@QNf|r븟m'&AJihd5q$u$Q4œl CV9"ps]׻[ӖZ3_['~$ֵިg fO ]͕9u0K{iגG%A-{CVC+iB7aob8zЪYH:>P-yx&gһִ&2m}UG i w̫֞݉㑘x,|5,=@ F CTE* "/n S  ʼ=ցAZ C?'3Y =v4=z?5C>J"CvF=^츺j~"B3h8ydಋ*W< D3SAZ>]?28\-g,̔eZ?z6Z~6Jd. ]WMe f}_ .uN>b-'u;ol[IpgO$eg=aLE p[EwE>܃^nu25y]F0c^3)P])5[D'g~>%: iNpxm-M0q扁lDz(w~IkX.8k\l6c i6j)0P,l7 Cd^-EKǤa]41o5dȊlX'ܝQ]e EG4;^p+eSP7S0q~ũIV&XF*`b;֡y0:F~lRCӨ/;$ #tN6ſ\ko ǦS"&^Wz:Qo46z 0rW|}E[!j x]tPvȅBD<üÉS7̔]B[ж4Mlªvrw,)V!yA7F2>ƪ/g@_-{¾;;rC}ytWROAY""qNK4\X{}V58uWi.|>mZ L7)cCt,XpahIA"VQK9Q{#cj&k_ ?V ,D8e`Gq5Ʈ vAyaEFdmߚ vBO#5\ɕΗխ;A4ٟ 剪C}nRt"7o+8zs6_ȹYco,!q46 aNbKuߤd 9Q;;8̍ nXaOvŒc3Fp D 'љ߶cCFg=p'\Nr!CTDZ3p s H&.fu:qBH7.c8A?>MvNcލ5wDjd@=,b:1Hܐg;]>(xQCuFk7_i% ,`qHT]?1UCx]8WcufO7g "]<C,|en\BExG#/Yw>ۘà`4k#SnFrvp{ITCU-S] c>abA@@},'GGLbd;R4e!wҒj!T b)&J3&% Tх܂4э,EEv5xh_IbGWn 8عЊ9nNmViJ-('t؈bՓ xSA&Dr&%:Kŷ脞SaE< M)>8MS@DmX1,ܚ"g JhoP_l\Sbtx/?zH"93$Hlg ֝3^o]r{ iVZV)jJUW.'x65=Mq=PsWRHCQB%OCd\lI ]w?:m$C?QV('SHkC!b`poAjg]`b}vHcu9;Ҵ۩ʋ ծa?2"yC7Z6*7Legd%C**piõF'ۈŐLϴs?%ik߿G&.^G3T՜vZn k |̗s*U%)#^/_ jg7rcPd;ϻrA8:C mMZ[$Eڲl*,lS/YNֹ^`Y~ mjù5}4<Ta$Qũ77omu 9}j7MٳO$DYC[e(ZjwRbJiG'@Y ^["i*XeIY $ւ4JA4W}J~r۞}n@d]H>j9G8t*=aSNeO3CwL MV1;֮D z/DY=Ήyz%ʉ^+Mwnw/C7;,[ԤP&dž}M%1j{ȹ"Jأє*8d7H`4A%{o!|i! d1/偟g 'o2µV}?!(9}"&yQ׸Bc̈́nlMfEg3lHd^ߐ-0pgI]aOHfj&Sn@*:,d_j6'ڏ9o(_n9ģ*F$h-y {N>^Je-ؤXW^^Wj (N" S慧(TXX#Ї݅83W{ w!#Y*Ph>,=L!=5,IDV FIyO4C~/2)[2 :?ȡ=)l{WiyGwYJqc-_ġt)NL G 3Z&\ߟ<ݴbe{\$7{v0Fj!Il j4ƯHT42v~ *m l:A]ߙ9c>z`~M)+s vaagoYDpt]T5lsL¬ ㈮¼ztܴKÇC 0 3h5bțyĕq K=4c!7Z"X(n ^nbeAH48Qʈ][{QlC'yZKr,a3w-•Cxn8dpTZ;iI@}5R`!xX?d KkqdkwP]g; -zu S J_Ea(ƭHMxKY5F /е}ܱq[k5nG:C,@v׼7u;umqK,]fuzM׭koe͸@uRC~n"y[V+D9 >βeeY1jbYeW 8;Abc3˖fVZgEY4c@i;^?r(.!*{¿n)k!"1E%Y RGq[od*ŰldQXb(( WEo\4#r Z@m6 k|V M$yFq-Rr֧'x=rF6o <. Ƞ1 Y|˺]%?@ҥB>aaϝD: {q˓:@ 0 &+VP=߫ r="˝`rfs$}.Lְg?Ԍ;/ 18j=z%yB;;f4=|ӎQ$A00̔84袀X޲'Gp\5pDnk9F&q=JU'u :5dwFƱ!+>^-@N˨M=88z3_$ÉJ;L7sk$DӁos\tSd7g.H a 7K".[?~w(mt4&H4<p)6\nrU?6xZrHKcl -y QlZCyQƾ](U\ܣIT vSʴ>+lRKI 6F$NZ(GM}SSCmh͵k7O|z/A]C_ȶ#dFgrY xU g&L_*8Z~EFв ?=>y?ujq"r%bAMd#dÿG-nR - 7vu%?YtO!`Ռ;lQo%B_d-/s=@;4 T iP%Y_6:ceS.tŅ|# (UԐ|wZӠ LtƖq=2Kqaѱ48frl9?0',MZI>2OS{yUnXH}j` ^:KTgG,m ( ү>!(?Y゠li &p@R ,>^/<}/$gykZ/d=n>ϗb2D<gyQ0۞3JNZTWfQ> [)_6z,`X_{u)j塗7Ar+>LjN; lT ݡ'%{uB|uv`3hM~TbnQ\6u*OI/0=<(ˡZy,;I59d"ϩw~0q\46~HYDS b Ȍ#%P19VؽMX E{wۇ_z&\z!g[Щވ폀zk"^xij3;F.Z}̜r=R$0[c_[L ezSuS%Q{*񍻄 f0 3 xWP.Q |ѽ.w-]Oo5g =vMO(<"̪BisZNFpI@t0SQ[5'hEw͙1 &,sk;x՗deLFi Ȥ.Ӻc[ ^W&5@lD,G>2$v2aU Z֛m^nL'!wQh2Lَ]MgkzK{fUx:~o%Ĥr6v(yy : ,r{dh2!g}.Ӆe=,؉iw㫍m6?. cԎctJiY0~J@N %,nrdTgwir9|rY&P׀:V$`*.8ϝ;F'm|嚓i/@34'm9"1̘xI>'K]k i{[UX 0z!—w.A:ʹ":8"|\m=]I7_w0(ZyJ1+װs|LzcxGX{Ȼ `m#,f 5AS\NUߌ;P~-f>Xi #}0f~<$VڙZۥxvwc兾Yy;^`؊NaN@P`DxbWc#j- 'uԐM<2ANtc4O(+ +*ihO tc׬~FY{[^}$u#'ӕOa,.-2U#+T Kk\gb[BB\0!·[O&nuR+?#Ҿ:hvc!E(,"poB}W$d?`pTptxU.O??wLjaA=a,fuƈ==Ԡ\3!S9\pIl~9LBʯ4jgv|C(6OZgD|Թ םDU =>d"gg67'IۜP†7:x$eK:2bQ>W2p>^0 07%Q z>4bBU]|lH0a>OI)hGC[ɿaa<ɃϨ '00-qd,5I i[}?EHwG_  '"KHMqua'j)7y AMx%6jx6>ԌEM-BOگEtuB/Ls6\1Eew.)&9e ЗEj[lf">1>U#y+"G`X nB-?|IFdr> wUێSdY%_/(^ x|ϧ0]?ʏ^P8oHڨBGB۠c|trqQ|B*gPGz}Ur= y9?'ع⠊Qwi7|r QpпR=t?\Cp /zȝ>~aTna~l~orRg &>O:v!!7WkyE{ H厂W\lJ8DFUN69fS{6*.5"{za&jp-NX3O1l39r?+>;2#uVUؔ06deU/HdD?E^|S &CNД~#qgઍ-L__[c@sm2 &!ـF$Kɧ:vϟ'~< :al "{v2HS#N }\oh9W~W)MΟrrjDmb 1ҒFHJ(Vlc&{,~)#v>+Z)6?-*7_wSmyNYc2'FVϋW#[TWҎȤ C6-ƃ9$GyǀQ<'' EGd*~\HvXV$J]QxIې砬qxP牁͜fu/*U:[B`}^ Ѥb?bf3[\Nit'[Oxj/hJ[ EF 8⎺cwsK#jy;;SyhSK"D?W[_(4)Ϡy=ҌNqx3y3ߋZ2(j 8-q$dc]B/jw08 jequ :&F"^BsjDU$}U+%_IW8:cgGZԇg$ bvV&S_ie R5,L`0J_kyeX+7 "<^jkCI3ق`Ǧ5 J)j܊:tQ!@$7+a7=J*khUc+.|S-eMx2nWcڢU y03 p6%hIVS?-kݐ'1(9W͇f? YvbxƍPRu ivDd囱I~*LY%^|Ej]T<+$4jCY5$ic gRv$ʘWq!,yњ̃&"&8N.I|k-\Uw"Ң6YB&b]M 'Q]-aOA0"GH(+ ,h:> חjݳY 86"@ 3n9% [1y>Jrh+l~_Ape,>"Zri(~A6 Ld]>+v 9:滰@/6%8fqbg4tR(L\AZiXuHiԟq_WᩆJk} ]QH=ޞ)Kl);޴jhr\G-f=>'*9]!пNE>\q TRJ"6/ joʖDΊ_ ǃ2fxn׈v g&nH%zvpw(l, A| ӕć+ͱ*w@G'`- j*SͮLGW&Q/0*yuύ+>1,,彰df`F< 7"0ۇD-o-fDFgu9RN tky jpgplu@!xW=2!4+~n"7AӦ W:|sc4u 5'zY ŬbCV3VŵwæLZJGn-cd=k]EIUiՀ/%A@h\LVFeW㏻?$&w<#:@_ T3ޝ1/ұVO70(ݟmN= ֟ ? +yմ^Yy^{ӱGjzj-qZ'.K`Xpkc ~FI'COaffc3%D6lyī3;ڶ2}u'_F$NIfBCEFf5)3^5;x%p~ǩE_%d DYL1_ȀW [7tsƛJJ_DޤhnGb@3"ϷW.dg(=f-[ŔDP,@+> g Aûrq+ض[ч#IC@,$w!]"2tc7'keJgӊԓP;YnV*XWP9#6rgVewad.R{JVWH!_}D__de1gz"ɦrWHO8Q%QǴ]:?u 1qN"5lzGA2 ޓriuwǪ ي5Yf;hSbdPQҝmSГn^[JuC/@DžypbtAB|{!/#o/jTn[/ËnVTWRrBM0OC};5 lN?c49hmW:E䴜M ~3 ʥ}{8N%SniQW](6+oyva:rXW.7sQXgV;Z*aiW`J:e-Q_)w.&Ԃv/gt 8\"BS./3r$Xf{˭T)5)wۓAQ`VdVnq8Kг%69qH-1[r&rKCMW4gC.S68aO?F^2H=ЎM~& 8XDxU"wxZ6ǫ .*[>Iq0X_"|#;لE8}gxq=(>aPw.<[.ux"Ϩ: חN\T7E&?mЭ)a-~:Fy9)a Zj4߭@$UAnBneF<9oNWK@A?9.2D%p9ԔDS K"m#e70nc+VoWy@9$S"_S8Ό̓"sڑI'BMz>W[ĕ@݉NɄJڥ)MA޿%|}9qrWoi!wӴa,'q P=?MKM>|C2U^XQ姜 XM_RmOS}t5b(=ސ3~`dXiDԶo%z}:p~GQZ"‘ҳ TV. i -XL[29KdӧoӬɽiy< 1É权+8 FY1kL7A"Oǩʃ- \Ds<}?Tk_ʬ0Y`ѡtAWONxoMdDqjbPY8W/$ntzed`J%nJ|v?P)LMJmbG~ 8But;?Moʎ(Rͨu!bXx&ׅ^_AȐ˵w+y3ַ4`4M:[ =WC;v,.eʊ/y<΍J<t);[۝t:%Z+bC!YGSr 78Y9" lo^<ݾk׫J^51F@^C zO^$u /L5_rht.B@,AtNDefbg_>ߎE  endstream endobj 179 0 obj << /Type /FontDescriptor /FontName /GFPFYA+SFRM1095 /Flags 4 /FontBBox [-188 -320 1445 942] /Ascent 689 /CapHeight 689 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/B/C/F/J/K/L/R/S/a/acircumflex/ampersand/c/d/e/g/hyphen/i/l/n/o/period/r/s/t/u/y) /FontFile 178 0 R >> endobj 180 0 obj << /Length1 721 /Length2 9735 /Length3 0 /Length 10310 /Filter /FlateDecode >> stream xmvUT],nYY,N%wwKf}ƽ]]=~2.ZN vfv62/Z 2svt2s tAMƎD tt[[}q:vf`5 @Mٕ*I|,@IU5}yY6@\%k Dt70K=@YZK\FUE -ɪ% 0s(mwpq 쿑VX@9_;X:x [:W_},@ٮvv*f  Pvfa[yyÐw1냸_ Y;X{,Ԭ]Zmifעp]п vw?7j`?OYĵU${VM^- SV3G ``YlfNv>;' tA.w"-/8mRB a %Tv -C79Vy'G:Pl+[$ 59x_ ,V*@2_g%=pGQt]ngl R=.zl>x.E hHEϩ`T~vK‡KYU d!ar̡05 Q,៧7Lj{xqmf8B<~*b򺫮KjJ8@cYEgs'Pʓ@~HUbPzfjUPyhѽ2~+)%j47vp.ZEdne ͊>]e@ۼ A7qyFAxP!6h^YfZqSs5` d r) x%0S5%jydrqy|@CE;[v?fqCqIviTc~5Zf+сVG1ysૡa h,t4 M~^{ tL!G J>谜,`JAF=W6Kҡ~Sٻw@͎~u.Oa7ӓ9]H#P=YEsEPc=؅?gK[DhZoqT_"kbFMC V$E5 HO*`g4kGbh*t?v_mqN6Бij令tHU _l ߼GD,E0Ns\zer[9Aa3 ~#˶ainPqWyp2.&WP<{*O2 }iS&+$+$dU) }۾N@!);GZИ\_ hz G9-]fmQM J ZAsD#*][7K,O% |5؜5y:X.SUḣvdFZ ɀN?YN7gw.fSQ|G€ukbs\^M8՟OMգ3DfJ,Mj\ژ/x(QD HrH]Z |+ҟAn>Le٬UH&}ZgsP@{a(oϤQߒ|*!pm *YJڐzQ9BU 7Ҏθ6|oqZtѭѧ ig 5Ah#erpNa[wE *:^T|>ThBB['_[Feߍ멈ubWiyp"YBOf:Ūn 87PG~| 1x2!G[ ߺϏrE> wR2cO,ur0I弫Yz$u%Ȇ|ܒjjHOf17V0KsS<כD|@лY1cT㡉%Oмs 8h!>ek9G;筧,2^yA|Jrr|ZŖ˸ò.kb#Ϫ?鳳Pss)`hwI4˃u\ MBǢ#=_}I6Ңqg>~Jh=A3C ޞ.%kv_ѐފtEqLX[Ǣ<0,-Abn; k ag$NIxA2C_qu]VD>$pVV)=`\*◌f~]B[5Q=ݜ ̠ ; yFݣo %BKǡ~4s ۼ>AoBWw&0o1+>qE# ݥȌӚiD̅^cwveVN"hxދvI{?|~{YK4<3IGHM-"d(IM٣>0^AtC' j^YQ=M`!A_H9[zfI!xMkԳ2"D]ß.!'魝雷k FPF_rbu or(l KC "锰ӑD%[1)"m?Nfz׽wTOWz9憥|;-`[۹+u9|TiO/|L MYI:bʥ3{NV^Mld\!+:7IRaTod&?GlY+m~ae)L+m)8 Y\.Cd~-C#lRU_;m$5GRP{>qac M؇=Hm6wP2~nzhdid~l'^@.ڭL&DQY{]6tP+tۛzZ’ WKӴܳ'S2sקD7I3R e~$4qT7#E/6$:TfB漾Ƀ54<=GM5!Uzz.h3| Z_܅V[ݖYcul=|D?M+h8뿠πT93_֪~$#wOJL5";@ eM Y+\[Uk.YA`]e7EdG]HP/^y'/ R_*ci?עώ.'Z:c|9E$`qVg34[LŽS1D,;1q*c{SUjNRQ&#. ]fw- f;(ŵGM:*kV+1JPR$j6oWD[`STRԵ>E1t=Kƅ9;OR"`+-˴CKDC/OclSzy&ʎ?)깣)E¾Pb@+x>D} fTQ$~5La`z^I!7#Pxի&-ɯ4p M+о%X5JrtoM2|0H#{x ~Cm#},-W3 $J?A[ OjSשgҲOS %0>:0VNFfʿE^W/&M$ʓlj6Ԡc{O :e4V2V$+0Ţ_oUp<ϋ|(G~W`܏ j[ L|z|ai`NW~N ۃX+9>'RF/Ӌ&;]%ʈ!m!bW S?%RRoeaםPO} ;en* HL |chs[ B۾n jf$%]Wʩy qro*Д/PKx/*=b<2Zu 5T?-7`.(цuGaoKҡi ߅@i7;O~c\rZg_2>\Wg Mn{%H0Y:2ɘ̸zrQQGBCȕ]8e)#WjlxTײ(\񰙍3w@KaFjʛ"\z% &g9:.P&Em~bQٿZSu{7kx{3%nFhN68'-apmi'alFGMò02S*9J kΎpbUէ$hYEG|\hQu;+NQwNԞ?@$JK?3V}2I.e bDx{w%ޙDOM|dGUZy'6~H^TG a%LB(xp|bGmJT%̺{E7zɬqVa1"uG sEn>:=vfv?{ n띱1ƺXhWU^vAǟмy(Z-΢ "Dycҏ:y[6 vPzw>e/Ktf" ٱvK #Y6`}6ĥۿc'/dliZf4L!dlKY2AjOn\䀚Z^/.ͪpp3zNe>-5lC\4ojOxͳ x_a4*iv? \`gOWBi|Ml``TYFzm:NWvDKLl?{(a7lqv8U-WEE8#ۑ&/zQP'n FY%;G5 -1៻[CwG"MW(OW;ғ>䮚 MmK<nVfϑ"GNwOӼqD=b>8!1Emo)~zMZw0_I;>-NnV y~ OƏT]?R6>d1;C !ALDʈ'o(eT)Dk[T(dV+gw[CbxyvAtGT*{fC ZT#:ܥ) oL̅WzysVA_m|GG3 TPHEʡfwֈ=J*[DeKS̥6x;jN>g_2J-[mol씢WZY?qz7tYYmL?vs 2MtU;e=t^!>E O1ҹXB(2>Ȍ-<3]~p 0Bqj(Lzin9{Q҈Ȉ"Bbu/J.2Bm0Zu<,ą)C}OyrRcn:?w)8z OV5Li=YX3}Ȑl4ܧ=2L&A5gB(J ߅|_tOFPYzN-l%}8"L2edf/Tly/?p,“|bP?r=O#2חU 3P?fG+@Cj9k!F&Sȉk~е PR$ih$@ #E#^= !B=Xg2c!XHi-PG?Ka>TeM풻zl,#&d#-&&7ѪgZ#*OREP)wǗj [eu{eXLWDjCw G;xCgKb&j{owm̨ |W#*FDPF6l jZe}ȵ)y9Mg2wEPF 4lSC !ZDێAqw[4HuY34\ʴkK!n 8Ҧ`9jkGy/&2`1g-nUluDgM}omOݶwaKVQ7ʯA(Gw4AsJus-,/h C/Y¼Wtτ~X;(YawP]Y^Yi^ɸܨ|M>cO,e5*PBX~96gf,1z *B,:cJy_zE7(pZ*jJ[ο[EA 9{2$%ZrwDv̱JEppU͠Բne9"6xN1WOQNu{]`Z9)8_k;iB0(40t9/}9* vDiS}oF7q"8?ܝ?!{%~&+C\GN+b^60AFn=ou![y Ɇ~ |cJF:i,k ӉW',@bۼ9 r]J|m\$f%P%-cڽA>Ѷ~8r@+?ytdҏ1:|NPRSEL{` cʾ>-/ܖ}{efXzFani궖a g` cԊ*kr0vy0ƻ{g') 1qWBǡ$m}H*rNr'( %$>"0êsR?Ey6 ̴5~}zς?Y/O"BQ.A݂z4(3@U:c1n6)L^˚ؖ ˁчUW$bZT mw䋕9cp䝠sEmǀ_~s.b)}bICLkM[ѢJ7ĩԏVV_ĩC8NP6Es*={p<~r| T7lՔdx1%Q;X*?*7h Yu 8zgE1<d;jZQR=ЧFD)L"-yYO% JD#J7f /&gB Q)JwGΆ8fl =*&!n\ؿl;!sf,K1~ 2Y[gSzMJAXyӽBxvU[G/e%tj3xEW[93+&a PYg_b9k.1~m6,S={@Ŵ8ʎs?qC}5& xՄl"w= zIGDă KFrݼ\!j؎MΒNjqWU! OfQwV ;lݣa6׶^YeLt%,. cpf:Ss 0ZP1 T>@ ȯ˒b-)d#.鶦kQ j埄9\V'>wDE ۱3/TmXl "eIe5n-rkj&jwB*-k&:ՇFND[+ڲIAa;[⦿&N$jؐ1`xkɍR De7!p¹Ut飩yTKd . sT֤8aI_aL%ewZ9ֺQU{8 Il}yt oq&I*affqK+|h=Iw#JƫPR<^’ 8uRT49`$V>;bg&n[}'ۧS>4'/WcuSP&UZuj']-JNh ~vj!6Z!A!w0d{t`xCA8[i3:?dƷ()ښ_.EqJH^Gk_ܿs9jJ endstream endobj 181 0 obj << /Type /FontDescriptor /FontName /JAUNCH+SFRM2074 /Flags 4 /FontBBox [-170 -318 1322 952] /Ascent 689 /CapHeight 689 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/F/a/b/c/e/fi/g/i/n/o/r/u/v) /FontFile 180 0 R >> endobj 182 0 obj << /Length1 726 /Length2 8203 /Length3 0 /Length 8796 /Filter /FlateDecode >> stream xmVeP۲%xР n00CAΠAC [p{;֫z^굻v}tTrGWM/'0;0@CNC΃FG' @e\0vpq99'/+т/moq!w k;MO p,mjz @#PU ;f57s{ @' #?\f 8Td5%ޫjd94f vGW?lcٛqq@6s#|SpAnNrC&lfoj0JC\P :4]8j`cj IG?q ٸxAj64_Ql1ϵ ^{Y:CWWG[W-,h8Z4\j UV3{JBm<|DFeIIA<}ظl<\.^A'k]r,m @X Mm /?^Jʪ)^k=d.}Q#;=9ڑz {YyZxyk#D cɞջXa PrR1a#jűy_J]L$JU~X| DԙoziEe h}c4BjR)@`c->-dnxTW^ޤ0%F_9 ,'ٕb q;:[n[$jk?fUHiH-镸 Q ݓ{S\.Ds~A7%Y* u+B*^8? _&l.Xg:2_pF j!c[DmfJpTڌI=$JXl J_G@[mRMLzծzsFVH뗳P=?¢)DýV$^ 爭}7Y/n~"m]C׌0D:wm]Eb=4$&"e rWP-"ñX($OY*NF{WAˠX#3|z舲*dfͽIHAVFC}![td6Nj&qtW8B4 vET qZe٥L-9 V`Bc0=m,= >Uȳ`'LC1\;%{2+27{a\;'񚵟ܛzqָIg,*ifmH뮒_\u l)]IRN-W|'HA3#BVWes-%o(av<:{8lSrijQ:)bTE|gZ AA%N<s5p*B7gCA b:TѸF&Y쾓ǧ^Ј&;Yض$e {'8?^KLF+|aE䓖90Lp0cq-(R -}hlLz:b!r倽 IC$CUy)a2T{QcCOu=Y!Ьδ_w-Fͷ5{(6bl ھAE!<\,9 f@Weq)L1FM?9QrKdÝZRZGN9h#GN,[ {qLcF\ {q@gR~pFub:u=0WekMT |vJ4mOwsFj]A$,M}YO2s}mJp[fnMTժ*%7N &1げsFeE;}z?F8T~{rR56)<^8>B$WI0_EmP6 ~FL''Zu5^p 1i/pv]EjIS L  07 \w.jb=38ggGȯɝP253v'jq$]B_9&éPT6+sYT}UԌ'o:e[{yNNY^2mFӌ%XTHZA)TbTF'HUuT7ڛ9`D>ۉ7_lҽH-wEW sx0A;NYsRN(I8D{J=# i)LαBaD>rW-=aiޠDAZ݉$ΚATIYP%TW'>$ RhG2ck"^)ӯq-(^-2Dq:  'PXqsqB*%qB_>.-/*H8&_@ͷTgh>?4.$HO)\uS xY3N`k7 K<6U?Im"c388d[Hw<.cP+\zgcHvZx;oOPW yEGEϐ!lr\,| n&i&| r0KW9XhZOAċR53[{Å*X}d1E8"XW+髋,v"!TvͱÂb(BQIcruMzN rP1jCG@_hB#nj]TO(L'o [=ݠ?s;PE_tyM*(KW;)E~~`-Wq|>\5f9DlM=~Li`LXej ,sL/!É h2ml^ i;tJM:"JX%?gQ}ozzH" +.{?`yZ ۦ7X(G9'IsII^_٠DF׺?DI'o8-IHdÍ#Y(o Bdz0X.bo"&̕ASe='Ȗ&A0?R̮+%`8)ˊ:Ӭ\YZ8ݕw3C>OKFHi#2kY8١ =M0m>BԊ>~@ 3 DOo]QBowwГ[3[hL𲸷}-r$ӭK9MB|>JA1:? ̄"5Eͮ!KLJj ?^j$#8+{p7to3پJ8Zj+d;8)pDhbIurT$7kFAp'|^39JEi37ib~Sp$RG1i@kq3DH 2@LQpPZخ nlnh&[ޝF1};e5^@[֟Fk&<} ;Zbζn.#Fr1~ExL gq71{ɾ~MeM1Ɇv6oTϸhӜsa|8ﰵ->T]4.x†IO|u A3V8}Uloe wsڟ6.zPy  υkHsSPl@B!,U\KTcpAxɤG+uЅX-'JGzÜI1OBQ&HRAQJ{IկHxT៾,><Op9/ } w8JE, ߽ó/[2v0_x+o|Rn bY Q&sdJ6 Bz6D5.[\:XŢ"$ 7l[3'qp (A@hG6xp1kfhs<1!Bt̒wxՠ Heˑn+,,Wl)كD3cdHyER0&Jx11}.N3>PcceI?ͣ_L$ܶan|Is<@V26]i;LkS|DX2!vD4[M]vs-ŋP0$5_Ĺ+U^+Luc"0t~z$ly|n{,'i+y}W\]lUZ$e(B|blS#xz_?:F&\q6 Yj۹ x1y;_L.* OzY c{+K(=hA Z_})pu!Nr)7f fw ɁZ*)ȑ@= j^A]mdFg1J hRNr>~ B QMFЫ`bɚ)c('iuDr5V=tW9 zp˸3:+җZVu-,fҏ)qji-8*{>>k^:Vr[{h]H%㖌uCgDXBfhkLCmGpzl nj5>wFr5ɤfgGv ! )ZV;NQȰEfS^Òw8"H:4`t_i?P4|>˲C#K |vޖm$&XUHq.E]|79{$^/&k'+W0OEr?TSfTY| }%J!dWE\YF84έ&5 &I Z9$sS}7 F끙5vC#W0p~q2 g ΓĤ-:c#~I+tn3iE$f&쵺"" ~/jC ʥװe3"h஌s[&I+^!w,н1i|/ܱThKnZЛ}hhvY/8W\Ɩ~ؔVM ZкA!!ʍ+׶%~̊ˑIKRm4p \bءډ h*I{d,Ƅ3W yjwSS3]D5cQ.,'?az4WKrx\ȵ1eVSiV A=c/hKHYȋ1R JH+N0 6ѿ q2@Hk܇b9="{S5^}`UqMZj1,G?A:F%1 m'I~abWѫ;|r ^pYGxq ;÷r?t':'mѽE J}%s{*UuXT']e)xKg䲾Smx"Dm: {:4;%MY䂰0}50eQj"oڕĂR>S gg(}K;NCr(J!k)a!T3GlϱCV}5 ?{~@@pBR3|o,vL4/T(mw3Ҋ?JV̦ԺZ2gkƁɄ MQ,)"C7 Q L%ĪiA\|#IF`P һ59mwWswωRAz\5Ʒ݋£ZN2+.!×-ݨ7mmہ $H?D )gԎAI̥ Tn67){wCmѸ SkM]F 1Z8 +OmQSOkӲf؛0;gXDRec Ky{냎L3O<% ЇSZ7o93*yҧOEݶBy`nk2!GA$B|vQxc+Ij,MNmo=/i _2P\S%0 B3iQo)1bu~ɕl'|BPw RߗL⾐E @4;-Q@PDO9Z嶥ћP5.љݹ 5-P7dY"s?^Vm9SԨ] Hד`ʶ.:h'"y^k^򜈐 !dU3 do_) =ĕŦ C-fx'}OxᛳVp]&=ݣmjewRq5UbvSF:ح~O5Z(nQY=HDOCֶ+Xq o4BZ0% j҄-L5$QF>?>;s?8'Ly D Wc#N(s)cDpzH!c[̏D;HXŊGvd)t n,|3hcޠߘ{Sdl r\ҿ왜oG=x`)lbAC@FgDz5qu7@meLb:Y|;@Sj #tsI8̫O+J.'Gt4C fs9 ӌ tж#" [ԑqs]SI:Y=EKH3S`~Q{]:֓גs3&]- bF*Af=ls1D_TX_ovZEp0u9uكgm^#"v!w ~}PW)9Ʉg<&X' UQ,RIzMe Y&\ =ײS ΎeɕM3k5ˮw͠5,_ΗwxJt;ig~HkqW1Xssy7 +b?͔]>(:XQ\u '  yYў5GK;gd&{ѿJS[ܝzuAg%rV_N]-/9||<|0gOtr_l:j#DZ8JsFf@> endobj 184 0 obj << /Length1 726 /Length2 26862 /Length3 0 /Length 27414 /Filter /FlateDecode >> stream xlchM-Zv.۶m۶m۶m۶mv.7֟̈kEB jgao@@Kω$,@OOOOEB"hblag+ll‰fbdbHOE/dghafOnDo##9>+ /?LLMM-M5$ddULlM ] --LlL(M[+&'`jO`v62"r"BtB uvmbl+YW2_$Z(|c #g|C3 [(&akj  >#-? ؚC 3-=N&nj`QgwdL-\l3?vwt jBT-El-la ,SCo O1pvpעWIܽh8XiX9}WF.&fTGw5Amq[VWR 6/@'ZhۊxfDّ1N\ܙq 7S;Yӥ~7*sb: >`O~a&{KvcFU5,0^MƩt( >sC "[sc8Zb5 .lVsb)v ڗG9j3"BPgD;W?Hׂb+jj~_Bu gWsԴtc*ڿ;L؃0$`;3fs6,2m* [[_NjOa 'j<'UϺCt2Qq5Ǘ^ $JZc3ys{S,Aaґ~Mh_$"Ƶ=E=TN:*GY׈/&MsSrG$NS{xjVO-:#& HEKiw󋑷 HX85!z+I.[84/RM]M/&roQQ0²r" nUJk|E:(lKK$˳O=a^Q?΋Z킀m=1G:)8u;\-yX(iUɩX&P:)@!IX,\夸' $^z{AGe.[^o m}QM à o8!+^Q`P+Q96qC"ٱNm7Sݰ,)/F)Nd*'-TNRoZ" 5}h hg H; ddCN3 ".MZMكBi%Q 0ԘP|*/-5޹`Ίǯa t-3~Xn yMVhnbg/[Y`Ba(xqswET@F<8k ^*t: )}%Sw``L#o^IpcMX;y,Apz+B_B5F>-,߇w@7`fВ/Jy 6OW W*Гhn/-1.7n;a9;h{ Vg wHy etkYKx0`F J N˚qijۭR#K2~Sl.^ BջXh#I͟{8iKeÑ ^dё:!ۋoGS*θ"X~ܶzƾCIj*sdKr:6|oWH5#(IA LG"yv  N dx>4k(;dx&$}քD#BAY)hR7ڞhzF%@LEmb JS:+C ²$苛@4N4g)*5H$m%JjhBlnD{OG5#ps33i~c/^R{  npJ**@qTh,Nn?}G$F蔳zAj(x+3MiBd? 5߇Uj"|>v!+45b$yQ5+}o~@S9 k_\ybD S:'_*:YQ @L!\4SIJ\BgM9ݚv^Yhp\%UL 8yuUBHثX^cIT낏Iqzi7 붛)hJY:z$:kS2V~*4AB_bn>W @Jf3b]_Uw8?%=+ *Nc;0 Rbfpǁ\[FjDX!pA\7s>RGXGA=QWݟ5pτD'uX夢{Vy n+ӄVp*rA>CH<yi!I݌*^^oơ&=y1ߴOV@% +B8"v=iYIs;*ݓSɸ׎] _뎉~܄n\ !oZITXrm&TI~ٿ2_لl=VMe7۴]%S] @h"yuA+i0cŃ00E^: ~Q.HaURCꡙ =/*,o~rF?J?xȘGB|oMH| sgaS0h~azf:5zztP0t&~$lx`Ɓ=K+֛Շ5է֕y9.L n2[r1JΡ$K_z" ڟJVOu+F`I̖@"1.g?tzAmyޠnYQ 9uLya45p:]έDXq*f n{g&5&[ ȽτeeZ3閈%eNSPaVrJB?kV 1]M.iRg6\5q6c<"S#z+Py S5#{>Jw}ҝÉ|R->HћW?/LuVwp Л1@ɱ fB`O.#`g!2N O@]\{`2Iif3ۯ߶$DžJ 87JaR6>,v%Kp-I>"M( ,=--9UM "?elIw]ҬȷtO[wJ -l R}.LZ2J@n uH ]FGiM;g!Y4$덑VYjmR.?HAN(Jrz~e RB {VT!iMx+̐G(G ݝ|" pPtƷ-?_}}9[z77jf5*\k hWHuJ, M輊/Hťq[ukwJjStG=:n1>@h J sc Olb\P?Y1Zvdcؗ  PHM1-˹[!&@ m|q\cB%q "+MTgǩԫ\gFg#*Q('N}8\ Uj$Uj[hg(Ķz}h`13hdxzlmr∎FjwlͿ/{z}f+Spj*l_@Q5Oa-dyҒlZ4TP0;6()P)5J5h`gx6XxsCsѾ|n\U"Noe-ad7T˻FV(ejIĕ *z˱D.yTa+MrjOv &x3(Ո YT J3$hDCJߜmz*qg4ϥ9YHP?(c!փD=.+Gh7 ݢFU7_CXR6+U'>U>!J% rFbpY+%k#ú!:hW)V-#%,Hq5ɱ)^כUE2nl.j:9'̋ %ZkV\#f<-߰)ςh-x8rٳbEiinOGc[$E@;}ģu!}J%*yNS ˳7?wqף-Yqk5(O`5!0XLGf3.Pp)(GrZ!u䦆T oy?&_ `|ghb]lI r'BM~hRDg6bc@0ohd;SX>2y}5Yx֙#K̘Wb#!=j>ꟉK?.ay*m)Qْa< ́zYw&yNü:j&{5Xv܇Ĭ{}>` [qt¨ mBOb|/6Y$[|z赏F K;'%GFEfVpR6D4c{qR")$_e.}Th8yF{Ƣ"۲h2 KON%6iGӀ aOLU=6xZ柑ţO 榷pGߒw}^鮮krxw RM /LwQF* 5zY B,UȎ?W=Fi kşO!*^Y>? 9 OpL7Btq[{dF gg#LS,3v{12`"[Fvs:q]Q/tfL2g͌hF6U|0U=kۘʼI(.Z; @ʠb]]\@bS{8:cKL﴿R*HӍ{ec}xLFbS ڨOLVgC.:vFJ9rIIq_[ȱ:ZԿ,%fD:Ew;R-zf$3]]XYiM*ظXâ\bECZ@ެe:8&%3]U&("y^bZ򙍨h\>LIJmHL(L27~% |eH).5wNw՟GٕnSMt$l1_Q[h#`$ ɤ'xPo߬FD9v#\̇{hGY3'Oibj-鰵uov]ҐhhX\1')xt9Ӹ~ B^O$Ci 6`k1lgKi5@lAHהuhG 1u{uO_#^#oo^Z.?bNѼu_36<Ϭ;[ss?ui+10A2,'Z6O`"Jj5d}LC]=VXDKw C6Q#acb))^5\Zp ^3m^GC#k>2n^650zN4Ft#) t^Rq{Tң~GyHrgcr`ƾɹQ*zрLyp)SޞPYg L#,HJN)ߣ{W=Đj,z?N0nhYq;yTҰGL=kKCs>c⌆{)+iݘ7|B!eYir:gM('v)#ً.KۦSQe#U_=rpQWӇ dkov߽wT0DIZBQK?1~Zc@k8]M(0E_x!AhW'na0Єa5צ.vuuFzSW9VDO]3+`I/tb4Փ珠At%qRrɹGjB,9Nn=S l#;Je:?|E|Xq~|nL_SrZ'N]Cl|!!_Wf2{Y.Y^zHSr1j=7z~UX|4rD4ܕ'}%gbƽ2j䪭0^cg9Brya"q/AZ!T>NX?VzT;F p;s='gH<ĕcf+Ҿ^)rיjQ=ІXhh䚜KXBKfn REB] uJa@7Y5[D25Ղ7ك@r}+a;Kb g|#lJ1`9_OP HĢhQ`Y ~pI֞-4PKBꀡ ȉH"8l\ T`Vݟ| 3h9⎅VOBu:*1r˨TM3疿Yo 94=%էZxKb㷰ٔIvCs>&zBBIzdfǒWč'/JKA8oK! 5IW j̔9Ϟɚ &CAtiUwVyd`C`/,G'c*c)faH,ɪ]L+R.]xџ8UԋSVxL8 [cwI `TIVWN]d6om~&]/J28QTUշͼx+c!299W43j.J}7*vG Sf-4M%@%=3,@ %0ftު+Q `bR+9ˈ(3u,$|Hdfwz*=C9X*8yEAaɨ` ldU7{y$lK~f$ndgĒ/Յk(Z W]H)8vNpE2bi݇U^cg}^5/I;S(`|Z/DMpv,ZA,NlWFlw%HlN~Y?6[ħZynv&Ǘ 6@ {yh  }}<2viI Đ }Km/fO$2qD/,bSmwo0+yPAP ufY9d]v2ً ,+<\aN}{ 0H_Svޒգ"!wv~ :g;pVSw!\/oe|6p]5$^Wpu:5w8q-I񳄕Gnkѝ{}`ҵ|;(4MWB`Mzrn4\7[wQodOLGX4J;Z2z6' uyH$F {_ò \FMX@(jbgY[90/Lj2Xmxz& Te;DŽtR:|#S6Gl.kY7d*_jh_oNeE;,lU_d4XTl!&ys!Uk2k9*+ՄKn"ctz %jtEC{7ߢubŸzǿ{ٗoxϸV\ 緲!0{U(#u#P1~X2OhBqv|TGMڭ[(d [=7Ž2!P2b(Öycx@mQ$P&^r>E uݝ|NFͫH0ƹ(z]0APz϶ެ,W:JR)݃&JE7/0_gq(hVbAD~(cɔpGlㄴOaf*[0@!2: Ȭ@z] fOG t&""Lۣ } Et]>{8kh9<]097xK*3(dzr3!󩰹?~f 'g #`v$2;{pgni*o qV,M/e;)hs+|l GKg#xݜT|XVYUhd} IVFHSOR@ 72E B!grFp_ۣi@@='0(^ W{lEdQttX3mI all,~X?q 66ĕ"4$lfuVV[SI"z'(glT3>UK0^CDqК3XzUak-M[W12 0v⑴owcRV=+q^_2<#Gϳ U2ͺ̅$J6A -mW ɘYNMH:2xG\ƽ ݯ!ظ.>rDS#]dy2rNW{4#i1}l8fUj/33/vlߛr? >஛LQ)$ tN=!3AE>F+?6N_B6ц4JsY~;Q8θMgܪ̇"FBP==2ȝp"(_C}EјM`O#G2CC@=Dw"ʬ}[[9_{oN,-)l"?k۳!f+6j ޖ;#/Ҭ'y@n(# wYNnOsj~yw]~aIxwh"s$_`XZB3wWCTrh0a{sJl m%>rS7S F3L=('1?5vE]b;tPP9<h@}#cAרi(.l_E^Pj!1|!NZSG8隝5#?Sq a/rR҇,bS쳜~ =cwW}jxwM< h35],TS<d4p{LW=tM`?ig0ι+8  ~i)p'?=|awqUl ƴ.ҩyc8;re~=]yȯkoA>`Ӧdyk$e3L A~Xs׍&4Y<)Z 1=YQdݬ' 끰c`ذQ+pQ[{*N 撃x‹^Ft].HШ~fSg'R'=]ܜS'Rû;ƺ_ݳRJX\q' maZ>;8Tsu:i4N>7NXʭ8^ҍHlϡhZ ~^oc>ndz!(\j[0PH^_hQc%Qf^# (~;ؖfj8'V8F[@ xӆ B,ɡ^|ke X=_J݌ܭ=).& XHzCٖU㩁RiSx;X`x0E%/߷bIl#GtSbT^ iJP"/\H'3mҺeINouYlpb.RyFXT͸ڍk-Ua"QtYد[mjf6,S/nf]\}e ]xIOFY7Q@ؚݥ%>@Bgzpfp`6w2.JS9BHlQ6>PeMb oۇ(À.Xy2P ҡ(ܝpf ,29oT4޵HʼC=T!婦ѻv2nW@qG;ߌ{O~+{txI cgqԎyƋ*NGHMZ@(LrAԥU~=rrONL^-Eksmx~QNUDf"TiD|p?Q0Iq`IZ*{qbiԯW!"RfXo'yT N;")&zX/"m^h˘WCW쎿 w.(<0[:$;ߕv<pEb;-=A yCFvë@P=Laal t=4N}  .6:$#kCO6A` v@CE9SX$CGEBqo J{MOwkmGév!ma)SXr[s(X_ I!jd%W͜([7$ƥJ=w.0.|>- ݯUǷ\)'.%Tٹlj_%qQ~?Nt:~tLƃ%":a*1 ͮ o??v<2cc64=RkOYϭDV{ &j݂.r#O5T*=U!B;Q{CIE)3w!L8[}C$!o /|0NSy ?OY8 x]8RQZK!f Iö4Okdߦq2PB0,mf]6ae`z5aq*Au4u !ͪFh=aH{AU9ڧ+c]u&"- /SxP]ӫ ֊AGѪW\b aTlcH 1d7#YwKo 8솚,R#m-4(vaLQ J9+vAƜC}_vreZcw#.gmO[¹J=%Ա]⌼wꋹa )>{:[Q*5u?\Yy0̹qlSy1븯RJOaIY2tӛz5PSW1)խ@zOTZR*!*}} ! Ot2<Ձܬr$!`^쏎>ܑt/OP+Z wz'- 8fI o4Ɋ 2BP4a(%wฃ+A-± (1]vs.Q<.϶oS=g$*3 @)sYW Nbk`bf^D+CXV "Q A-R'3GȑQaOz9i$ 6(4Ta` 4!þ%2;I%'mbdͶ* M(JM\p,!^a 5+?gSudicFN/WTRZGW.ԑ 1zWY כ{!c[cAyW 4םcz` WQSkhvd!ᎲimUFt$f;5k2%Ц2O?fdUF S! !}mp+ ΆBkt S0a4-M"ǏZL3Ps&^csyCR|ǹӽĐ{HE]rAc_BHYܜ*Z+ǵnJ/M Mh4+Ob^#HF ДCP{\v}&<;@Q5AE瞟`9xQ#3Q1,q!{+F|+WIJxʊ_tP]SXa'^y3Q>Fπ)=cMqTlb'(k*_K/>U[ Ou8%:,iϰO/2FO_Gp$!O\v r؟^GǸ9!3ocw#$`c7jL;Rl> /y-Jš|D)\;8#6kJuBt*jD0&(͘ dج֧]&q w 2meK*cGg򘫸P1cl]^J1[x컷lu_(Y]RFnc%Zw1,!'uGJB׭3T8B]'$85M|' TTe!uu*)࿹z0eʁuB?V;`s5t[I]E=-Q U}.m_P# {hS>ICZc8KU 7tfJxs`E\u 0:F҆!7mVzUgw]PP wPc@3SG(TnHc駋xvjGGϩ$f B c~LDQB"(Ds!ma.[z8i:p|ˆefcm`^cos/S&nvnM1=Ns>MrrkCK. D " %ekT{k Nh\M8}=OS!Y R HEͩaIی9ݸ^ZֆХ$շ ZQT̋IcbXW| ~==#08 ^nόa4.3?I,t{/|R -[wp^&F'=䊜g#_w;-t bi׾$/q]t[ 81K j YX}Fе?ʦ<掕?eh Zx-7["~C W^.Z{ʈaR8*{`//}ߞw&YEbi72#KVo KyRQdwm.i!X cSzҎfP~ed|,ӫ`!vhT.H.p#–8)7%\t}$B9q].;$ҽ sl}04=/7c]l'cf6Mh~rtś?q~~o a̝a3;HO՜l)u#1vN5c!Ij:U ܨ{8SuAzh |)o5|?%`:n4}=,s _[' .˘B!DV-fVOM(&:5]PS3e!Θ;2&ce8]66}n9Z]̻4oORt|7Ѳ_Eґea6{13b>~-%l乚%bn>&1~1[>+*DģƻClFDE]B#on[u뒤IVV.˜AmI0\U:i(\w., CL ˏ"?32nj=r}JZ/H} W3Gy6C53beC }l138pA{ )3oK?T;b|[E7" K\~yY's)2tu {D-]nRLcYrHpZT-T ]CXD9%ܠB|Eg%LJg,~CBFk tْ҃"GסtWWQ:޴55/*j;M$͊ @b߾3{g4" xwcC^=1\ޭ5A#sx̶D`&zɔdۯ}q0OV~SX(P괝eDvW5%g{ŵQʾ ǀjqt_ +, 4 7 b }"혚ޜb;M?~!ĸ5GEÊ q%ch!㞅v,Ur/J2:")vaQ8=6l1TtlZ6O,^ݗ 'GI=~KA0uG$Fn1`4ja7H|QP!h6m_*<ˠs6{m@ږ#םtwe֪;K* %yX¤ˆ]%xii38H;c-X<}>k(~@VRb;LTa^;݊@|>ȓ)}؏4@:Ҥ3֔\$T2 m #2v zw^ TQȢxؠxHAc*79 '25u.ȑBz7_F;w )WT?GydQξZ?_}:TPV$η s; /˝`x!l#砺hBvZS楤(NǤXIj]j/g< &Jzp{ie5fcYxԬ 1}6KApY|Kc/,R,co5M$I $sBJ\>N"9VO˼h_]j7`(Nb ~iǠDչKv"xO ֿc+5w*Ղ[)6v(ʆ:"RHEPe(>(F,ȶ'| bM[ M6{" 8o7^5tDJjF^?&Սif}'NKBж%mzZ 73M3idM["7G *.imh'K6qj:Nj n.Z1pw1VA `s;]b1x$4m>NO饩 "t"F Ңyau)&42w5UGg!6=bv wC8,[waZ?҂s溮…x+oگJLFu\9^A(2 8['rZI^h.j_3?r<89EDh ֑XLOr%C閤G^,n=+?~F:۪tuGkrˌ>3\au(uJF:;gR~43xt2]?6)#Vu2o"L.pJz-Q:d.Rd oP})dڂZncYMC+~'2z%r@ {oÍP r%}Gl_@gFv#Ersc >,ˮF4|$||Vn»Qv5CoMBoԅi<栽#%+d֞+ϖmr_bM*Tp{kXCN/p"^6Pf$N`:tK 1 <.YiE?S3wi~l>\k[wLKFvC`mXVҒ,W987{b3:ۨ8A)BI\Ϥj-=8~T#d\Fڄ$HϕBxQ){.{;װdJ# hEk M--(ݺxmP`+t^f-3z'i#6#cH^X Coo=}Hcf[;ɞeC!5P;i4qiqcgeN~ H2Y`@c^#~о*!5ըKE|s "kՑt@a.?Fr0G< !E98Ջ'鏉Qm+m#GYQMSrϝY_T8dq3*1\|8MbT{>-yM!/8n9?[o û?}/M(!jƴE= -`V׾炊,Y^`H1!*rXd%$nͤp,2pj_+y+[}G41WΪK- W.ybk+p/o Y>^CU͐-'"9(l?W;1Bj=bq2=Im#k6uoH0gzݹ'`hl5T\Yߕ).o@FJ@0BG(V6kS* zNѲwcIDmab[Rh\!$G"2LK?gvA>G~!qfjVw67qR:}*;:SQ1 1¾2.ƖK?,ZЎ ƈmv:qPҌE(BV籐H\߇ *ZN R}cWU6?V<!͓b g˃pC3ʼ]`LlOLs:ɂ' p|^(gYq1ΎOhI! xkBp= a:Q3z+!y(8Ѯ]"7R̥^oۿ,S Dд-*OwnrB1&Ŀ-enɪ}En3cO|jlOT$݌`TJA-Jy.z> a>b8QOTĮQam]O*I:&MQ~L3nFQ=cvxW[+*'2SQcs[]%l7/dٜ)&gw 4uP =7eyUv(TE2638;P1}zl26qӷ2`A%{^#P<(Cy  *|ħ&GA^1@IB)R\ܜ TKֻ^)A<}ir<5-p`;.FVdz?=ϘxoA@ed['gU\muuY ŭח 8r\7є|j淼5Z\g{ Gg"E݄lr_,^BR ;Y"N<"? ^Gp;oMTG0OJ+}ɣB~*)܎L"X FG5{i`74| .ӊ}{/,E endstream endobj 185 0 obj << /Type /FontDescriptor /FontName /FQZWDC+SFTI1000 /Flags 4 /FontBBox [-95 -321 1415 932] /Ascent 689 /CapHeight 689 /Descent -194 /ItalicAngle -14 /StemV 50 /XHeight 430 /CharSet (/A/B/C/D/F/G/I/Icircumflex/J/L/M/N/O/P/R/S/T/U/V/W/a/b/c/colon/comma/d/e/eacute/eight/endash/f/fi/five/four/g/h/hyphen/i/icircumflex/k/l/m/n/nine/o/one/p/parenleft/parenright/r/s/slash/t/three/u/v/x/y/zero) /FontFile 184 0 R >> endobj 186 0 obj << /Length1 725 /Length2 28561 /Length3 0 /Length 29048 /Filter /FlateDecode >> stream xlSt-vNfl۶m6fl۶m6fouiPW"%uV7aec(*+3f`01Ð 98[ 8pLJ&F&# )@@aD @jgmjadvuuwurstg `jamאPɪLlM .Fi #['J#?_ `v6eQ9Ye -r[g'M -k ߬,:FF3_Iؚ6v?CJ?.ֲ6& !;{gG-_ܻ9ZR kS!lf🐅?|;;'f򟳑11pr8Tl=ώE%$eWN[ؚNXGA`;@_a?sebd2r9XY} I-&w#;#`?-"sTf}ݰAk %ڶb՞)e9݂Ds}~WuiތJ$AةO;2'e&!b?Y̶b'yY,}r]MƩt 9sM&[}m8Zl/.lV}b) q @ޛK5b= &BPkJ;W7Ќn#jb~WLy }H EfZM*ʿ ;T؃o $.;#fc>,d+=3 V;闾>1 \<+~<Ǒ gY6[ LߺpvY;F*%Ү?<0A*y7|z23]f]V;S1 H͠:߸tVib1e΂ ЭR_Bd1[+i~(쓲0QuL&KâP)S 8,a@,$'/?W:Nm504R8iϢ]+g+&ܠJeMAӿv$v~)_18 L=?CIq554$`{\=c1pL)G"w11$ɚR4X/8m<>禶!;wWy8[\ȸ9툿n3ڲq޹*E-=*ܮߠߋA&"?vC}gJݣA.'FsOk[MIrHmg[aw՘{ X3 ؾ&JegQ/l69 `"r55ye# eܧvRt9yK"o{gߗIׅxxT\w4 ,6ƪ !T/g]kĄy o7/V-E-qMFT*h9cMrL!Y]Ηؒ E4S搝ˆL2O~Qk< elAi5m:2GCYm(aQ=!3Q[ H}Y#<4#|RbP2-k,rſ%.Sƿl)3%x~$_Gra;~[M߽lF3ȭMǼt>gF7}r洠* S:m;aIl9SE?OB.Pb+`UFM+D{w#f]㕧C35E$A23P 1s^ `e#H3v.uw}>NǵќH\Q*A|:@~b6cřVspZ͹R jܞNV͛"GEJ(FSxr3W*jA5QPm,FXs0W5Fުapi~]T~{ ?ҨCP]h b yC,Ji!wִI1 Sn~2eOC iH5΃ ߗ~iA q#lHc-5"CM5n _ gDs?XF2PaE$\ ?H`6xU`8]^oڐ۞,sswyD b/ˁG;$S9=^!v \]RuX-E{MRcBU8g$bdYΒ-l,[*~SK嚜(II$tγzmf^1VZiUtJ\F/! ޴z.ol [HgZ6NOF|B1,5* @xՄ 'C9qzMq@ 1 j`nO`v$^&wGFkkِ{KܼI(f H S`+FhsQ$ dVf4Ws'-2-U-F6`”!O*4JB|P^>O"WqSH&4Fo,+G )Epeu1pe[,s3i,W!=bEF 7ˎP/M+ϛoY` O̱/6XpWT0J!2FuYH:G$Ew$:ȞBg"<Ő7N Ǻ64Ē sAn GDUiИԵ`U, ;g͡ f[#M Z}Nz ?Rߒ*)~NʬYZ̏W%GqefXo^:54}? n#;3|.%}"HyW+r3i tVP@ oa8BTm ?{`(hhx [L&cݷΰۀQz6j3Is{8~@l5rTL!8&X*``Ym)\{Z)#'gfL{4E,2@F] yj$L)Kñɰ:T0Z$.|>"Br%vNg:52;6qi2Jqzysr͡}v:WL+}:sP*z[S?(Pbt/w_<'fq9]qUL%x aGJl@)Ie9ʿʫ\ Ut S2HWJB޼3\gM]4h<)Fv&m>lo{]mcȹb]KkÐI碶m,9'ku!Pо iA%]ݺt~hG}$GGxozN,XOULٱ=VF-iY<$Xuì Q&gv`]/Yijtz(%~eXpR\ Fp]lq_${+ta~)c`p'^;xE^ކȅ+U`DUz؞ϒGAvLLXƺ@+hϟ_PџZiP4 gįHņhK衛⤺,l7=5;h ^8I L~ВmŽسɂp!8[q r/Js]REqH:sfX @I -Hµ4omɆkjYJ?/:1kcwD䰂0/I8ALֱYW,]@䠂'dV~2!O~Oxפֿ'ƅͫΛ&r2v Ob\a'~SVƵ]t^ŕ8άĸ@' PAz:PɗArAG8[z@%r'z:3mMXF3r-O65Ɵ )Po>[Q͖KDza2{2PzJm!y`cNz/ny2omVkmf6 (?d=̙G!7f`-q_nlzif3]ViW^3ǚ/{J?UVSXd{}2q)'6? `3%AqKee1_||OG]TY*},c*J42 Y5vzO[~,N!3?ɧqSfIh)S+ܱJSڊәyTIo <]?^$k}Rj ieכMˆi ˏs1iht"73+;c_^$i~dD6ج"iE_|AwfGuh qY|mQng#"6%B | )hI ]gkoZ8M[x=/RQ#.V \ְ%VXX;X/'p xR,=3*:~`+yLj>\c,P1ps .mu/L&ﲉ ya`ūqf' rڨ/-+uœ%|ag7q7CsKlK;V}A 'fƸđC`ugz|wZ#d ,KorI!{?u&ՈNBq:1gԥf0 gS`[3E h+sAA7:7C#iR-Rtjq_J P ʏ㽓laa0Kn0D -ua͍ [nK| @Үyx԰[U8=)V^q͉xhwZh11Ov0Ngh2pz dwV@FP}.` OaJ3&PCO.@1V''YIoqt)l9ؑӪe-Olαgs+|޶颎_T:aLFn2w+{a҈IhF0uZ)qkBd~{-߁{r`V>FG3œa)Dko24JH]~\.>p@o 3Cl)FsI luJ<862):@kg5&P{T9cRxtдz绉W=x/5#=a2v8COqxZd]>sZɤo]4 /.HE qrWiE;VvՁ d[}8bc^4r^yqiQxΐc+Bj%қTz-t*OBݱA㙼=EL#UgX %+N}]{V!D2Ŗi~|zdo* E$<>jqՑyE+7ف e.DbM|?s;37-~5iΩrS_䟪g6M\>Eyy`d@͍*ԜFAQ7㲵:jD£rAn {:!%#ب*"x)fD_+55#_bˮj~ 9Юj׺af%!:F`.übrO}Ί8;U6X!zN@ X?Je}~CLMHkn(yĬd,Epqi!g$-ojOܵapٲPZr B`\je8 M8z".ËFkJLƥ &U-{c_V(QK pF׽hdi"z|m7Su&pa?}m*Z,3{.O 2l[L ?7H$L')љ0x5[LiQ"bMA*CMߞXKDI E`2Q8 6C BM-`4=NBTq)J$5M+X(ϓx]M_0ވh?4Qy{fNp+1s#߯'&?bQb^WoYQTAV{aNud4L1.[ۑLrDwG~UIb8ψT7cA0&=ـH$2~,^V\[m+J2\N qHtz)dAB6p=,L}RR**det]Hm]C4^QvӓM9^j>3tV .dM kF#|gTI*7bA| S%ֺkn@ Gg~S@%F'|jk5vo\7[;}TÉ0,91m&(Î=<([N0,փ/b"̋dD53 "/=u"kxh4"ŧ_yL&DUn ˳ݕz;ZϩfqIۨ7q"d-R$y8W\L9i`|6a{TM bDQ`SSD頑<ٝj]$/cY깞YTuLD "4|dF<."^`fP# |nN܏bBX^6lZD[P8l|{]'NGb7_<5%+|"lyi1Jn~r1 ?B D4ybh\[Fnjij, H BAx"~]IpKdQn?IvH3YkC""x@HItbj\,êA4rߟqguNg%JCdIC =߯!>T3j5@!n )ut$K {U쑋/a b7LYy <$=^xB_`ȰJ(Q~N1.^4ΜE""l!T,i/;&#ԙV7"dS |MLLKCJ&qx<`Bg^\"BFbcL8<z&HBa{ !\}֠of .>˕RoE󑿴LK&e jc!is8}Ѷ TWd/{Y}2-;XDubQ]>X-0 8{'~ܩDĽ..T^tSJvDAXZȏqw /7RBGhtU |1@V;P܊{3 oήJS#.?5lxzCSZ*Ԡz@ɔyeUt&4My!j(__[ ݆Ul̈́9M; uW;,CSyn/yLIl{j|^f_%1Y )W=0=biL}C_Q.:]KhDY! >)Ns4˖@ks{dvo=6'8d~Eޮͺ>Cm7z7T}ѯfW/r+䥗4ծqm@Yjp "kn6 Z qܻH}o/(7BC&-.U)BpNLzFj~ՑoBlE :}TKnMm`*;u|L{noYXk'IuTi- 6^ zJ U_-Rr2p!(@J2p2@cwHxo;Y4o:ls4^L |9"f%[$yn 7dIA5ب[K̟Pzի|a05Z<1G9xCF LU9\tZPT8-l]X@v9s X j@RC[C=LQJ}e/@@ӥ`\o* !ZL`>0D( F0@I| p{Hm_W0/y̮Up^wNGy mhTYJPhFF%qU֗96ܣQp-}ݮw]Ն_X%qf9:"A!E e`W5#9)2cZR>'xkWu1 ^ש)lZᦵk$+`9/Ij&SwWNM!vuibN@e)ka_L'ڿ(;?M ޣ‹bwSgs勀VpզI* 1[K~46@Iʧ rqQ=sZŐ,\tKBCz>ϟar7IX5|^ ө :݆DOumxA`j=\D=&*! lHk3b,$a$2M -Iv[y ?]FA(-t>1 i#p$ )gqt5aN+j)ioϖB&%vQ;h3w=>-JmҴi8WdѿGe"Ѣ =GPvHӌfd2LXU )% kj@ODp@A eZ[U|JGfo1QQDį["]HaLRgV#;B#D޼Z ҚL;;a+Siv4LUD!d"+ϕR[E}D0PuiՊf^ZaA*aΜGGkmP,~2A@]~t&ƾbcmm`wmao D,C(=M#?;SwdǼs|e{ 仇.7"5uy5|s_`Pᴿ]ؘ嗍Mɂml%Q-9(% yݧpPUVlmNs`RPxkgVak ]UG^ޯWn#;G6j"aXo< ܻs'adu%)8a@1mAf>c,M8#Ə( )2~⪑Yip-Ǩ=2*5vMEVH|iTFؑï2bheSrVi|]+;֨MQWɪ`EomeuwIkE=ɢjxg^ℌXڀ> k|5j [=]_Gr9TBe`9sodF?B36?)E&:j~La팭AsPX?/8'kՋpڰ Zn ySt(^D ٗ~TP>Kº2<x ]  ﻗ::З83  ֨TǶr(K:3}~k2FB4796bUHM(a,)vAZ1Eeq]@PG1v+2!֦B4ؖ:5TɃrRВ8i>/`$ k/ÏHrv vu^ R2HSRX_.$aMYQſ|]&wjFb;nّrj,WF(Ow _=k0Ovk6PvྌRp;:aKfY*fU[5־ OI<TW:f@z|\o)c#Pw TxT%s *@~^t6QNqR7eo Ҕ&\|0ofpu,H䜔^N8ԓݍ \wɶ˲gG|+T$ȴ~#-S~XSpRTz^*#6ΣILٯU"['Jā[ߍÓyd4Rnu?wDfhd WpB?Sh\ RthLƈ-8ѡόuu6a a(rTjtl{(aq}'omUO:PM]ʂrU^O.}rOVry)%6(yu?~i]{e}33ϢD:=M6trdH`%$,$m\ƻ<%ܡ_95 ж~3jIӯ&Ot/0XN&8H5MI mVJS.ZtUV% bƻ $%yU1R:kU =%7St06e|FG߈gus(jsIBO JSkooy*@1_ً"5oG*B`_=--ڔfGHevYO=*Q@[LfsG("B?z*tIY_  Sc( ղql sm=_ 7cnILtJwˇK[$pkwx ʫc{?|gD9nF,h;0臱-6Uk8de yQVN&7ʊ@Hax%O r=Z i]cFdDM94ׇS'/ $_uUg,WpG6F|Ki926!:[*G(d_Jjb^z(h"W4 JY3A=);GjÒĝC8RZLqLǬ,\g}3?wJ 3ak*e}r65irڝDaXK0;l]n >bkp]iI)5fP1!Sߩ ) R̚S"ω*!C";^eU>V{o)ec{ĉ]L4YOV!De 9o%`3WNsIuE ի~]3W,gwe m ZgN(qjz1M\h3wߣ?[5B_V2z)#}TUWDPeRhc6Rf),[ qmLTCDL@5]46uTEXK/ [oUԒ1K h5us5aVS9􁁘U!Mő0?6 ^ϳȊ6.M`bt@* yAŹuşmن=C#U0pbHIwb(Or{3Q }\ mAǁZzd=?5նmyY&^)ץB /m,f#"չv?է2B+nΈ;F5ŶD#2?T>^Jc?D Udg9$C%X)'sEސ/Ll5^R7cL|]Wy<F\]PWUSmPaH8yl hChwyNJ_uE@JЬ8\2W&Ghy}5d 4`߾,8 V+KDffƧUTUi:nT]G1qOE$AH>)}<u1\t][tr뻆Qx):NsѰ8vjD #11 rbpgƹR!61|nS˵'~Ih%ˎm)Ȩ"db^andPL< Q \ۭ# (=sVim{eڎjV.)=Z쭟Lw&CUQ_S ~|l0QP #OrĘD%ȶ{Ԑ{;-oNڷy!td砂/0h#~ }cP*`ìz`xe6$i:5xm4 촻s澠Cɔ~:MvW"&n莭J%N;=_M!)kwH,m `WȰ% ̌X65){$Qç SGrB*a,!VP$)yM6}N u&.1D%W"2d ; yk5(53^j-ǁl<`G~nE'}%4ޖ/UQ qCϪ^1֓Nn¬2̇yMRF G?b_0Ā>\lH#y ͕'Q [엙?A7A09/}#y4̂J1+J[_,kE '&aˇؚхU2*QpJҷ kDgjc **% E[WT)" V951Y~%em_]KYnR.rQ/QP}\:\Im$vv&lzb4Luh` Z?٦au? Ac FI<_{Y6/\5j&ZE}3cJФh6%ie c!asXW^ ӛ^Q(d^yaR(`9ҩދ-Š κpv5Yj>Z.M#\Bgij_"b?Im^ tVaOĠis]BfC+ ! ^z˔\@+tF\  M"':/+Go۹6&`ץ9Kv$iISTY啍K{GګU$ ej[?Zk?eBۗ<1 Z$4ѷ;OV>[ۛ!Db7] !49SfĴs#5x1 l50@f{-Uo*]ă4 uBvGup>>nVQ S>MYw';b^ F&4)K\ҖNv0m[pv=RntdWCA eF?kT~K ^T[ 5]La0GL[],K*53 Ж*0e'%S:&j,ݞuF',eg}IdԳz}wO~BO;<7e޳b*@9Z>vL;4H/3݆̏4]xH2Fqd D WBR! L[]ػ6Gu=jM|TȝlX,& N,yCt?$3F@'N;ͨTC XͪFV!ҶL)P&D0y[;uwMhel~룴+}E{+Mnӳr:zo"p"?6L]esy.D,V.yj RNNHoߪ\yW& zvz(.\ BjA+9ZU1adhbg@32]#}5J]RYpdC3ʮP>^%Y|ii#|p4󫅘1? _1Tia2q%!41,&HAI#˝MsE(8.*Z%W(#>m/boϵ>v*/[ "ݤBvMnh>ct|;κ jFx^fM{wz-^ L{ú\q$IxGHh23gW=OQ,p 8иc{l/p70f5ILպji'N_Dq W/ ʸS8TݼRW !҂b}&?aycvIY0KRfI j l~B紷p!sW '%GZT='`(dR]MqcƿcgwA=LFsJ䀹E_So񓎏;C?bv"/X7ket7,(YQ Yn%=iL[ iyDoL5>0R?E|GBx-p<_3qJ}~-˓B-K׫ōf[,!p /ьuYD-$'0ɯ'L,t呙BphF3t 'A2py[\k{0@Wr>̹2'qEZ Q@]-c, [Zy摎s`BuUI*}.$-\MA[=5U?&e%gp Ki̦.I$CzrDƲ~uֲhaL_}v{Ǒ dL|;0}*Ȭi ,-}%Mu^LL${r3&!Ts6U}Qf NFDi1.W, a=ΫL/??yJP- \ٮ/RL:E~fAp*T)N HDBG$8JI~u8hà\$#6YS`(*4F~c;f$RS΄1+.~`fpco/ЧCf#ŪnN/a.zjAaۀH.OrzŬxLP. e/5HTx 4G$^Ő:lLy+| FÁ|lgL?v Va0j#$"ƄTGcADiՂf2l.h#ŁinIU"=rHO< j>G/AEJOg42 GmXdYxCb)@ies /W5;R;e;BueVz f7 A+So[岚OmĄĒm.[njr I7wyu U\ie;8 4*Mŵ!ɦdJo Uп6RB*3 vU;mOl>OkQQ72]ŝnCrsU@L 큾qJgjV4& ŕIۮS螲9kP1d:9U8ZҀZŹ|Q4<.R vZJ"0[>x\1B9>1kHL-X^!O'?}:֮bvrp[ +Be6?Y(No.yfHM(eJ~b:|^6lPwK .@bو OF#jE0`I# X3V{^ =-7K8-z;P s#.%8517򧇂{x9N=ӣ=\f|–c.~1=4`epdhwLi 8H>^AB^}} S!#R9YZe7ťfԳ^kzs->N9!}uWg75 7J}qdzk*݀4(^%1Pf8xTŞa61@[lSBҔbGqV)[6`){R˷qp ~Lp83nCl(hyGL g+!q,5f>2d9M _2+x=%NbLbY 1g^OGdoNvYaANp/, ge"%( o=g؈aLA;f.VČפ"9T/»FC*] w+N[8 Wmġ$GQjM JP;LP6c24}i: ˤמmpaw|izKبOd'3H3fE|R"i(wW)m dCѳX[. =:軎,ڦ U\L M ԠYAc(1mkU;1Kմo=~}Q_t䞧jw[&ʗvdUH,ZEb)`̤*JMOwAs'HlCh!7 ::%\ \.Ak KH7 ߲~$FFX)Bo5/*k|ϰ`Ķ}I $ن\IV_]2;=,xKeϣF Dy5$Skjσq:N+؈i.Ѕ]޳UzBk+[9bQcH$61kYo_u+NdZ;cBZ&"#^ŷBX_u]Ҧms?8A/sg5B(6G+;_C9g8s |U)s!Ʋcq*ٴ ?Wqqk*P '-X4bBޫMvid7909?(ބxV3o9M##O+? @[n{]![s0<ā-E+z1RBbN{'e6KhA$f0u+X'OmkDSwS X t"HY:B>o+6HVqd&_x…VjВUt0T94cаim] ׊ͣ_f2o߁.@l d׆.q fBl]j~YZ+6۩lWlb+L4XݒOl JqVXP~F_M:y: Ƴ>u,va+)pg,8\}0+Eȣ7:Z^N|Jߟ)#$lRm|a725tfiyH-භup5%xU;+"]lE8w<͋t7#! hZֶDnsm!ԪM~q" 6Nǟ; ח"[ŨnR#GDp= E'M/L% 'j;$ŋ$U_9U˧0Bsm Ѿ?>znq,WV+J7j-XJZW (C.y>7V/ iPdͥQc%1=IĚ=yDW{9HضigKTqЈ Kq}ȽTT.Fb'G.HL./Y?\qK@<x* bZ#m1[>[%aoc̼ќ)XS}HY|[@6U~5XSrZqɎ ?$ Gerz7،Jڹ8CxX,-%$H*N bQ(YtLbѝ)|# quC?7j/>TPR*93AwZABP . :^Rpe``j&f{6ړ5G+t`!X i1U9w&r Qe=NMzK,䅌:]#MhF1V8Ĝe 9oH-U#e 1U5y-تxe2n$w+oܲ!Cl2 k72Țs9hPF`>eu= 7id焯(f/o4P?$&Y FC" 9r?ٿ V ʻJkpp-^J#Q_N[(CrpG|ͱ8]){l4D7|&02Y٨L ʹ&=F m̽kҭmpr5j襁a~;WqHH =nYZ] \ _+*}}{M 3S4xD񏚚:RiR{DFo!GnIiQrZvO;Z6˒P|>i$yBhM-%Źcb7 eMU{GJ ( VMsz]7'薲 S{_%#lgoY:hJיYqhK%ɴ7ڍs/Gjrd6%)ͶK[R 'nY|\f^'Zd1.ѺDhڒk f7\6T L~RnL*:2VihC3qh9\cjؽl +uBkLP7ƲX|/=$ gxNLb_MTP&vqIsp}@C]hl`.Y }KDTQaY v6y92O$fPiB-S<oSʼnOdJ+?%d"'բ Dz֛98zw-權~~CjQ2?E8Zfx.7s*ThV[g߳&xJ|huY0۾o%0P#WZC$4*|͑3R%@~SS8}!Jpu/^(N6&P _%0~Gd¢-_=nF FZg Vsx{%Zy-݃1P#穥0Z&S~jpg*ӦFs^E%dyӲ7B*dixS>v^#{yŨ1[xj.OH'n'ZF?c10eegllTgtfHae ء˖ uk+'|Ȅ&wUV|dڜ+7 `kyʆm4DUrOcEAPVTJXA舘5Kh/t2G-y+F6kڠeߛ0AR5ؽ([<&r=Qmj^5ݽOx8 teydmXSsU"Ǧup0'bTBg"gRSYaБfef@2Y){ipCgZOQG/L㜅x"#Ep-"{ ÄKÝk?lj2u9!NK0xxY()2*FbbAr >ҘIu-FS$ h/ͶvJ|XoV_KY ,j*GyX}Gfp% 7^ G]\t B+,ipz5j[ZmqM .P_懌L;}ee"UܧRՃtb)A UEg ; b6!9ThKk3wnn +qǃF'l-nn9V >T[  68?'N"Pl+ jB_z @秒E&C(VMK3 nXK5ADnZrmIi<U>SrSv΢A)$uu䇋~dRsK׍)M҂Lo!yyͰC£"7,=Xs36m#6fl-O6lqﻜ8{E9̂TK?X(~lr_ђDҘ)$]: hN N2֍%Ļ ZטCZW9J Md`k3/QPOxh+w9U85nxh֮"k2;0,@gC_Gn.x*t22[6}tkV~-u G&AޭACS7A52i B;KAF)ζL$u9U]^LF?S#KF*k@2Š<ݼD(8H w\g#x ]:-H펶~Rc]O'<}HQPSf N6󏖈m@hB_B6~Vspc'Hg؁ۅ v8fzZPhQ9h$w tKZۨEm֓#mn$ސW hpڃ,֝y endstream endobj 187 0 obj << /Type /FontDescriptor /FontName /EBLIJN+SFTT0800 /Flags 4 /FontBBox [-213 -359 1395 851] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/a/b/c/d/f/h/i/k/l/n/o/p/period/question/r/s/t/u/v/x/y) /FontFile 186 0 R >> endobj 188 0 obj << /Length1 725 /Length2 35036 /Length3 0 /Length 35585 /Filter /FlateDecode >> stream xlcfݲ-\zʶm۶m۶mewٶD|$F9fF̈dD^fLtLqUUF.FF#= 7@b`b0322D,,]&TmL쬜V&^wwwAw7zg7~Tfs+[3RB^ afold Pt32ZٻQq&VBofή3wvȉ +ȫDTEFY]]A;ZXFc?YgX0LLS+W= ÿt7w'l?\GC*?h7[[y#;33@/=jdge )WG>\ĭUmn!6TBRPP.gM+OG$ ߇< B3#>TOpHJ 1u( 3Z0Ϗ~AR%,ZjO(}Y"BGP}zssmc7A1)5۱H ,ib/ia ^?i#مh`瑡:`Df8̱mPmc> ^$7u5#+N2Jd{60 1xw{QgV$uʥ%'0A<Ԃ_׼$eقr8)p^Dƌ ]>{Go4 άbW%i(IS%JZ^>{Ey:_90oTyӆANk|DdwS zKO{(-Tx$ :?fVt v;uJD~N< 7Ҏh*:!{ʿc04.˦ioG<*#"D !Z砱X =%>)N i@F/)_݌[h7 (Jpuy /ŝ6Gp74UWn32?mY5޳z.ĤX9}Ix2XɭejFP'ADo6F85h/g5L;NOpk$a!#hdi|{]$xՕw:=nNe8 ~]sRv{U89jh`q!w6>A勳2_&+;{I(]ri+BR'hwi~Yg|y3@ـ<*ЊaÚ|Q\7F%(Dz)@yL| KS|>>NNƫp$@UBTT-hC~/0}^gSJ$oW r h42?աzj#ZbQ;JYK Si7L1Q_zK aqwH]aBF(ʹ}\R'vzIQGFfEQ |[ǒ]mkYim9-f\-x)£l' |嘤2`KR#)gjJX0꣨\MsDK3rfrMPp‰WqTNb5uxc$\5a&[Ku9͇wSwH> xnO?6} hL{ N$>^L >h xHH8ޜ94 .؄' <ɵ?%u2-\m{|y42u}lhȐLT+O@혏[C/ieF _(aҗOj do϶ƌ[x1j[Ix ׉i񱯮A(o 94R)-Pޤ JPD)וKNR˻pˍ#j{Qr>K6?t(K̷|p"u"}&d4d0rL/^kFX@eOk݉ 72 oEnӓn@XR'_bb;3A{V_3CpK.e @@A,jr 푋߼&S`B)"'?'+k: X[sg:Gǩy]ݲ>GIZ}$~\z~D_ܼI1!-- sqVfI$U4m]cjXͶ b?r[PY6+*5Բa'b~+wZqy "3VHj* Q2؋`L:]NJ},Mr|ro4I1QbYHW<~W8e^vkqd)$2p #ahgW\BԬn6_[ȗ~y[b<8ه)G~Gm]u4Df`Q4ER1l97KIxLZ Rz=< l1趕Sˬ~~\@N&ZɕyT - XPN.m4C*$a!BUk9=}N-z3WPѐjw>Y?>aw!Thhd*rJp}| )ם"Py9!8{Ax,Qڝݰ5v 5dS\Ԭ17n/RCJm  iR 䓄CgQ\|kLKm;Q)h7m`>]}O$y[:A_RH&0>fOZ݈A,sc߀m S?f%J\7*ɕB~rn?F7jw_ewKrOi@"^s@+R>+D$m-4CBoqe_d:%3-m뾃 f}{%E^hY| DyB#:g܅YfKSY1n;@KxYUlG}uVȨ K.EM'N/OD~VUOPh թ?taQ~/'pIG# OERa0O5RH#M71-evi~{>KeSOLA^K󃺰{YfPRPaXLLMC3]UhU.KK7YohëHs:)7VU{^梈_S1 $%ΧsƴP*鮩'aSbq,G xYnX gO5)zk7.+2%^!%\]}"~.+źYcMh;SѣU*ë94ZgW]:$c $|bk;Kۖ3-oGZUybd){3O-進'|Fs1)hNnX@4 7 Bz"A#IxӅ1!LYQkKBm'Rhir@Q;G"7{)ـ_9΋~0[aSH>Ҹ ?[mp ND$좋ƕ :QĦ\4^kjpߘXo[۬s-o@aMԁiRßrgDҸ jK+!疍axrAjo>M4T_BeM bdGVţSg9KTnLj'SIeTg.'Lx'o*omW4k~S8FU5GT;ءZ5"% b^lߴwfg2/gizDžC5W^G v{R~y@WpA䐏vY`]2EYՍtk;|IMcs'sJaٻ ; /ĿtxxsH]jvDT"jrͬeaX,qخzC8o¦Qlo$ J3`E|Q$A<(;X m5,|UzBAS7KE]wg1Cʥ>7} ϋa9(NQߧ7qhġfm!m<5.Y3@GՍ&7tg|W'rۅBHF׌/']%`HW;|WJigK;:탻P'xK"j~ 2-E_aW|0k^6d_MO%ޠU+QqƉYW;M+}+F/"](7L/M*N2?ۢ!wӭ!]LzKִ۵}_{kQţ !ܹ' g`^ 2p`,NHiJ *t~~D̽97HJC3cŞ67y)@Gj!`[Q8׸v@ R7jNL?3Zaф7 U{"Ghs֍p|VJ ;$bi/G c03yI̱$"J`P3D"ۘbN%j/Y5Wr99f4ժ#3Q)닸F]-re&Ҍ"~9{r|tgvBɓE !m!ƨA ~𜶤oူMd An-R>bL Q;+ bÞC6)rQ+"l :F jGwwl'R_1*eksէL{ِ@CqЌ J_Xˏg._TQN I4[ಓxa-Z>tY6^""ZrP5 Βdߑ1BA5MܐLƿ_fDudCA<D3+`G5Gz]P¤աf* a?cIJ(RfPIp4f\0 qJաv8%m T_.GDPa;BR g6N zEqU誱t*Vj<jǣccef5T vC'}.*;FěiFؿYK},Rs53`)hVဩt!r=>B$=|pCc1ӦLf,CVH+[Vc"6+z~rƟ]3zX|<.(OrW?ƗdՕrUK"l d =Lcbv d׺0F0Gj"b3I4o*C[kCr״=KI,.f ,mSAҟϖ[%e哙%`f80ZL ś3dŮ)n4;4)?vFbto| sot)7M"o0R\b"ykV^Կ|JYѬMLN0Fe7F#1NӐ|1C fBZ5 ]20ڢ5vz*B>Uj$plMws0uNT4 ӋC5n|72؝DSvv`0w$@וccQ}ΰw_VIȲTn%*(ܯhI;̾RvyR3.L.UDxF^^"ī꾧Iɪl'ֽ@\9-e4‘a(?RÝa_ )C7=,&mB!ѩ\ KB%(zK*>@^-)s  Xݜ[9O2Tdg"xÍ%UpD+1EO| ~DƲAe8Cc2P?MQwuwh$jXp?iRוym0؛3J~gm:)'#1El*_g5句54 z5*ynxZmT"#|%|dNShhVpHżoJXxG ~gGE ; NUfx4wӎBW=Vvf[<;l|udunErӵTs?ǘ=i#x7NF?o^ڄg$k`'XCsmr`l޽EMSv"20 Q8 w|jf09uD+.³~4bvsUIt> l;a9UVOs!›8@ >'l(Yc$YV)~XJG0 lm2<\ 10}k= {ZGqn1^؇(!Tvm9i BbwA U &\LgZviKm~P|M{\T2;՚[.`P֧ 0sf݆lF6a NI[?Od!kptn %q f +ӢuwRtP2^eT ̝b C EL/퍦lY!Db,5jҊ25M{:H{Ć/HDwyM4"kGihGEoXTx8[wvSZ&Oe3"jI||fwXe,֒680'Fj- ;*UWGXᒌ?Wfsه"rJHrQZ5oCQ]%u؝i,jÚeJ*z@S*PCxb~ 4 ר^O:&5vyWhU9|XB2ei "HHX; |hu;+xLۘ#0_՘GިM;e'p]:J&n:@ťz# sVuO-`^AɰuShe`3uXcAzT\(OCZ/ȗfLҁ$#G: J xggfZ% oH"*a)&*ϸ2[JgN:G?YbBA|z[qED"?nݟj:O<- څzK1G]FwP}:бX<1;%O=+q|vҞaAHah!(.Ńlc%j,l kXt&Xי@+OvEAhwC&B:5疒|={-SqԏpDY,Xc;2LͶf(+ ,ƈԳ˓}R=1d@SkhA i{?jןj2B^GO٦׬ N#kr[RcǁWMXDMTm"jBk<⳺>u~/bZ'َr6jTVƌA[MKH1aIhR/iSJG+gvpusZ=ET"PyZ ^s\.WAtmDӯ 0xDZ+1By%Yrڛwj_*wZlHri*ĝ]Dbh-$ZNAǫDu. nPB1˞ʸSke W1T/>("/1~jm^@w'q߭SC`ȎľVYPb+>)x4P=RE+.rrsGPj`آrnmz ANE OunBiS)H y/ ~JOR V׍b]/V7SjB*>lN]*oGLqM`:2 JMl$x @ȪCRO29wb 28c>?6yq{-32S zQ$xt\=ֵ~TyѬrP񼆵ﳕŚn'/%4oX&"|3]lPua=%aSp_r3VȈjvAHfe~8+cW)ތ(*!=-0%2JBKZٽauTY0r )CG< [@ 1;Ҫ$f8e5M1o{8RDփD)^qnХ- x760*WLU{lp,w=|}S{h{N'AwOܙZȖE@gW0SȝƑց!ˊWR>oMN;.Qvs;|jނKޜ4P&pz5Sȃt"پmvNA%J#V-${3om4lя/:J v1[}A]߯5mx#t~H`SZH"=n].!TܙMh>bgav_5R+|C̓G!ZA 8n)'rciA[n4 Ь"`j,0c5Jw[d߁bY^ݝ`wQa,W5PzjP"BTFq *Gk5M^lwl8s&T?œH0~ a\ 2,۠Ud+Y,D A[6}^uN9V8|1vPV`KW ylˋ"ܷ bC✿Zm Lc&'" =J@DJA%?㊺H#F|QLJw+'b L 8xN`;<0ATe#:9EԀ/MԐkUQ fe8q%ㇻ Z>f >9D*#%Ze6K9ѱi KccxVTq 'd0Fҝ3tt8;!]_Rt*uhFF8(7<9h8_H4]6URzNLYV=93}J [APVF h>iKiو{*+(Լu vdQt042dpP>YE=WjWb!7F-N'iúuy%&,Mu\`V "vT-1[%O8Fa,yz)\Yt&Ty*)OŜi$#遡]:uH͓TWd"m[4NoQTh ɕ]~~ :rzEZy}GsC`b^2,&l _ L\RZJlN bfAhZ7Ua "1ٞz~`x"da ܀),ckNQUg s&-a ~w< 5A!2T?DNB?[eLd\d\YL/  F4PP &!7F'4Rc# 1DO$IǍ_%b./~_G$a\@ |6KpM~?eqѥC`ČlS]+`.\Eu:/E3]3 g@&@ml[XV` -O2 4~fr}c)^?ƃYQٟ8/[CQb5D)⢚jH;[}ZFM`CR^6 Dn !U`όpA) A'"ww 9Ǟ.2t;kAbȄ7jPq6X@jF|DCnҐ۳oXz٧ }m=<`lCju:n')zZ X5M4Ag%bH _mԩKDY+pCԓ?3%<:>$?U^hOt8{pN'/۟D{.0 ӿʢA %;&aۨp%TJNZ As-Īz+"[$OkB{#3FZ=&sS!^HAܲq|ױEڧ[jues>79a8=/}G pj26Ӟsʁ&Ge4fNsᲜQ<ͬj&B-܂!xxtCڥ㤋PsTVZw›'>%QOu]07eB^E-& lh%mN DtqVRzqslN>d;PtcqݩRa'Ь2(RSKVI#|zna@ ,ÀZ Y6080nO+N0_ǀ ^E.g{cE ؛V;&^2qW9Ayٕ&,mu8C8jRSBnԭ/V#v%?Z"(2ǖ"Ͷ0TaRK>LoK}dRN #!/ȁ#&+"rpugnD*0j? QHe [Nuͽ#:ṺokA˱{ݘ <>3 Y^8zI5X! pc_fM>SݡQBg4Q.ʚmR#%dUCqdST_J%0ZQ4;>O!Xrj&%nsADЭG0:~'  }+'HovW,Ԕ=W\B[  VCtPKY~gׇlb%{:K6W`WaMX.?t|x[:( t K_/=pŇ1]m3$#h*M2s jFZc箶+-p &J8_ 5[[ l /џU?W}Q#Alۍ}Ì> GZͶ qƮeނz 6eCl 2 ,AxB0XrUE1loQ&ﴶVW7o^@S|泋s})bG@!['7n"SsU W8Se+M0l7I"7|y=Vx8^-B/`/_V>,3>ÕԥflNm2v΍(uʡ6_ߗ:k|i" y<^=_rp>/U8YxOC7ZH Xo>miBE9Y9CK,_ AzcJ O=mXo>:AL]Ty@5Amy2k5^+Ҷ:|>LzS퓔;[~huWF_55쎶pa $G="L #?[wK8@y'T4018_둮7V'}tJ>V=&sݰ]ײ*b 2d>ֿ׀^̖3V9oN`A# fKXɰPrɵ4tzSiڋJ2dS i+Z7F%z$`$;AXK.&D9luoԎ\f-i^/p h~ x:= I&1rsj#;:*T-0vw5iq7,<Dt/SLmޣvaB:.pA#yF`6t!^ꨰ($LC Gn>'l u@J2v ɳZ52 'r k`x3: Z{d"O*> Dz&B4M5 Es 9L7̭I]j\ s1.~ǟ7buWTkIHO`6yN[U)kB1rOPAM4SῸ@{][E9}w4Vr(6<$s>iq%TSCNa%B* &x8로^@XU~G ~NBB JmsNa /Yt2'=ے t:2~Y1"1)4 $/@J 8!LP>E <~PN6h&:3R[m#A{QZ CϚCU<ٸꠑ68iw5N;_&go'36ꜚk%';vVlkǶvl۶m۶m۶mN9ꪞ&JhU:ϠѱH02;yR/M>Ŗ&S S*Ȏi/MqnLz[ *$`冢UYZ}dAlDU:l}0ߺva%ᎄqզ#ȂwOF/FAc{tz`2z1WeAF bbߚƜBg6]Wc^H-_$9Yژ6KiӴ$D?~3Z=NHʶȣ]5c>.<+9:"%cCs )Kvf/QOg@~FUyi@aQy56?d%KK+r@<΋NKi$Fi?| 2sω^I39x +-IDmq}Xu^sc=O֎y;À` 6rrAZ& 0Jқ(Bl'+tऒ |KГ77[D{UO$Y6|eh}@+>輵D*fW˳c7/a-zI] >hlK~,DɑDx,K$ݮUuNYM>~0aL꒩Q]9Yh7F:Z/oPtULKnƪ͔yvi=ʫv?0wc%-nÄHQ3ꑷIDRxeYe% @ĂS3,U&r@j!:s7^EY}RepKͺɗe-,}!Ak˼\[v)TG[I 1kQ03.dְH ݀ XhIx$|bsnQ+F!)XB+0$Cвӹڅ$lƲ"j,SRkljۇՌ: Y11f{o M+M`*7/'GPFF[VfK,;c[>DeH?IN1v]_Yg@4'N1 JA,9AhD+%T\Wx\#,o^]}o#o/E wNDŽNgCӌ_҉.NC;?McTbE^]]mƘsQRn><lrڭyI0=y؋Î}:7`x|Gha0 U$?j]QHTb$LjG! E rS Xa*{ d鿊xCimU+s0_Cp=LZ0G8t+ˉl<$L|" ?֯]jÎ= ^.i5dA +p#}D"5 ׇly!f̑kxrP' V]cyiBڃH` -M_ QQFzCDx`;KBġ,Y/T^u[sVsn sg2tG15(Ql{9`AM] LMP!_Kq, Ӆ\2]B#uz؄VPdYKoh-#ߛ]X7w5M J#,%\m VcI+c̃lV@|xD )J7ᬇ8~~܌5q' @}L¢[Je 1iک8 #37ݒ<. 0725\D]w@HOIϔsB[ KE25eJ6, 2y$.|8Ol-XOϳ͢UlHQ|`fr+@&M)<:nA9haZWSᔫ?ϞZh7o{nPps,0~jWtTY5 E%b_+5w˧Z׽/:zNHE2Nyp ˂+~:U405ڸyQ )0*K.9o}x\>y1|qױ6l=v; ?QpJ{`J-ИUo{23z+m}좥?{`KrX T{2ԛ!/ )7TBW{G 29v1}- 6l9Te:OF0o=v<@3*E#s]<YG$l^|>}3oǓUwst%硏ۧ꠩K^&) 0v6C2Hf  426+FZ\],Uz(ȥhSm>לIf#; u/W/Tk H*|qQhE>Ou=Ul, ّV>[d-ޑ%iP rOBf1x)6[ {a}=U|m J#Fj54]VPt,|;',B%.* %ͦAQYl+: 2SxireVJ4830ଗmrY4ZD j5 uUǐR}ט w]-YSh xm[,2O!R yGQ֕<4gmqz|[o3#wo3 .}]o-qܗK{h:w~@z3;Vٌ'P]3oH Tg`l=Tx9(N,Cc}mק!ș 2+a~$=d{3sU_h^QN/9Ros+qa9%p<'% a}~/y)pnևFC% z-h¯x 5a<.!qSuLEn~y>i&tL=%7U[>ghe3r b Uj~ lA֦c Nϯ!eC*amtl 1G||nun::T0]bV/y[+\VpѸu'"#.Z0zgcZ]`rnbnӋ(Zzv0$ 4^$NU$nxv/'kNw/NwA^_`9."t|y}D-P r$@ѝXd]K zÒSe ݁-puiI`A=3Xnr[6on]L2Z_(28ݞ/ӭ߀%[1Q Ƌ_v2DK uQo!Sng =T{/mGĨd.<hptQ+; Hl\>\G1 kY jnZf9n7ɷ)XT\ŦQ{*C,( j@ MO8m\+TP"Y ʂcQ΢!tJIYMh5IRd|`Y^$-KYRDb 'R/p8+i76~v/gwV Kf00y8NI` jD`gki3ޅ34ءS:kRB34BؚGaXk|/U*(2*_O阋q2jѴ+:(-mMFZo;+k -Iҁ6Yk;rU]³79=,͟>[hOk¦4Rӏ4bf&(LzFa}r*w3! qapZ/g|E߃&  +21s!046N.eX$" e*?#ӞojjS"$fE!LK Ů Z5㔾Qrh٦@i 'F13+c"ѥUҢ#D0m\L0JL灄lE?Bh%Z^r͕ \s[ rW m(A^ gT #:R“1(wyh(eY$ $b֟cʣ#5d'Cҡ֡'?B?:WBizjhoϪ5h1*F֧?,>kuhj7dN@>T.x\)NĀZn"w^x_-s<3p{eܩcTd*<γ ?޷uGnj,d'secfVoxl NQ񭜍J9׾1E05IdLuSUP!(ϡ+ƙa&9q߽pwxc\f )" b`:Z*JP9e%bڣC[kθ3OeO.z #5GvLpJW5Js,dLzK~̪E3΃[^W@C\BC lꟕYp|I&]]swQAWW<]EH }:" fW2&?~+l媠^="%lH)4(?'OXazAIetUz2=fPDb]̟gWړ"'|zp0-@-숾U2;"עޮl`G"Zʔk^s3\o>H[ԏuҍ|~b?Mkj!] V5\|uLwA`mLDSv gH80EB8xDegz/\ƿNug"N'ŧ ԢQK>*1/j#M"bEmՓ_΄k3eĻ;M<ÉHeOb(bOj_06s(w(W\vٝ%躂Ɇz:VMQL(wd0Dc:9U>*Z#d2>0łɱekFus^]F'/N[:$mZ -pۖjv+u'Rgup|?<d`je%U)l̹&voZ5Qp}zS-0 ۟ie,oK{u-WkC9e 4 @kkrZpĵYm˫!ZC1S Xr*muvdiD \kѲ?"#]_sf'J7=*̄%]X:78{t5{M"}E Q*{|پ*roE4Ŗ2vL]V,;Kl♾\E(z!-un$\U ɚ_aIOwӻ9nqzB]@(܌|!26Ok_Yyųq>'0-D-9=sB1ρC{ ۙN>~lt޽G:09ue:pX8[gG4+*-OQ@)X խ؈uިKB'&4>;;2OAz=&Y5ȷ/ˑ]%-BJB3]yXxԍ{]rH$J'XܪBA̤TP"ë҂@nWh/|'#}縲r @Ţk(n\Q"kX?4pr] `S)8h ~.[lQ ` 'waf "(R\v!;≌ѱIXrrPف/̽^-tjKanC\FRrJehdwߖb/vr ,Yz뼈-Ls㲓d1EtUxͿyT <:V@m0YDM=g`S~Xj<)OL=_$춉$%g/p< tpo5aOrT.5~!݂M+E%!QWm}{9?PR KGhm0Sxvk >~9[7tKHTXlSPcb1 Ӽrɡ67+[餮ŪZ!ߗ sbW)Q!ڦpWFXT2, uc4 UҐ(Fd2& kPV=VaJ{eZrxEBpS6w3U8f[R}$7'NiPCU@+.HDkIs#[iW=aIJ>yŎ`@1:v2Ьi.# Jkɏ/BdE¾3@,TĮBH³ \T=萺AQq`MYjam}H8O9(aL9sLKW |@AuR};Ћ<~> ջL)7sKpW4qy}` Y(.ϦJ:vah ώow}bZЭ l<f5#Uȯo %'D/7c[U `tӵfH6Bc;X}8*JA@j6"pBs{5x|1aG wI߼T97-~L9vi45s1:B%ɳƶո()EV"qCB!^ Fܴ' v +&EnD"~MSd]4فA#!qi#/5Z(#9V C@'`pЁ_]ɤF滮y>/h*#*K-iP0䨛~ QR@v7 KRsD> W7 Zטt&NbA ʨ2>Sj*i3T8s慊RPnLg1tLnPs_nr@ ~2 w/(#EXj^@[h0D$P̒))#byK7āgɑ[]ͱa}k BYIhIN;WpK+|U."YYN_ղ f`kiA+GqYF}:ȝv`VC|)!\jq> c{3Q֚{|lRű` /^.iy҈ƹ6- #ef2z봥'm֋!&9XC~O y*; UmwPyT.8@t7^8z瀺kv7kb 8qҧ!su£~RTA>0$V9j>Or Rv忿 cVk=Dy0vj-*ț iT̥8ِ~y566+K"sD|~:(i_}H|g2 ]HjQgM17dn gTh ^.hMWt2-yE͒N+M^az&MBW'hEiu6EE H-#'v;!xlZ9pZWy~Dѯ}2!*q ؟e,a/roa*Fl urYvjUTw7f N`V#MQႬQ+ (o$j5߳t E'2>c:ŬU!]Y+*4B;cV>ĊaMqm։o}'IC-f,S^ n@,y ^]BYZ)P]q .2 AAm$1R_Yr5Z M!0nsCU][e ] .oUDc[N -niqs? -}K р# c,6|VeT.rdc/>`=-~|3= ߋ-3X8=q8ad hmϟBԐNgdQnDwZYbi l`sАd62ۇkC.o99qګݍ˘~cH)|2Gv ttπ9TOV'QϔjbV=pl ̀ Te>Hesl)~$ŷg~HK>_9#ALW> IRC@1r7Hſ/y,[?qxw ?:x9[H#HUg{ˈ&C1Gp qzٺn{>֊0j+}8)1 \Pz-UhDb!CԟS#-C>"lވmv=tWFld%* 2+N|WK ~‘i rvl-@+ hwb`*n P&RzF?(Ec 2#_o`_-0QYp|CP ,megWu:7>W-EC')uH@!ӂ&RRәC m1G3-&t4V'3w,FjqYUJ235J8%/~a{qc a_;D ^@6|MaDc$KI,_-U7aYE]mV\i U' v5&#kRZIL 51u\c 48@sydR}$W X'Lm?)R*<37x4Y^bg'^s A~)ԟCyD[!Z"W7:e6cR*$dh.#}kUհ.ȢngR_V)|,ߟi&%IrAo 6oƁE'OqoMLe3e;\n%2xVI3<SS>JSI(,< vLI$O{Zć^? phUdЯ˅{5SeHDw0{RUxj/6V.|kk}1>ӹK8 x4 kwj)e>^9$S&̭-c-`۫4*~(k:̭!cc:(8oLz5?>/aK "`6&>~SHw?iVcF& (@X9VUCuR4JYጏ.WZI$[*-beQ1}M o*>cJE4n i@$HҺ[:g%|bfB Pd@q ޷ /n Cf5fXҀ,Èjak?dL4C(j *+pDtPJa"||di)"z]iTk>@MՄ;R`}_ eBKn>Wx<0N6 {usʾZ~a4<~0eKh X%?"+a;[0n]N 7Xfꍟh40p]^ 2h#!L4 aNL'U}ݷ>QJ̝пuK2%͐Y eoIyhwbN-{:^س"lnkO:&$Xp%4dGL1ȓG{U}BG+ E/i@odFdǀ1-l<18sy폯Bi;b2̬MBaphRQqyy oFD{׋YpH?ï\C9,x?Mk[61 (ԡ " h7͵:+[(GTȎfh͈0px;su}Фl]L$i9sOLZ3TyyY<ԇ'r;i&Ћ BVj:He_|I3z[ LaHME[[o ݫk?t9G{o=k.wK5Wi'AWePd.cr>K@ُ*-1 b,7FW ?נAqSfsBŲqE3ڧ\2Ԅx &܀zkGm`f% 7{q+̚:]ke#4 ,DEl]UPEYKJ1T;}Ja#ByT7LNZ)f؂pQ7s|木呞}ʺ +/kTddzE''}TQ3;Q؞ՅW2uz&JύkDZ_:"g]v%4H-~ ДCv@Do},~ԅwg0ډϿD2+ D@Y6Xho4ZcVNc {erLՊqv\uQk5ۘV(Bi<8dmJ@cD ihlnX J5 KɁ|%=20E@Ul^_x?uj0v^f D !܁)剃c'oԅD{ߨz۸|젊ٸBgcZ)c2Bo<)ʓ]K^naR,Y 8(gA9x/:bgGaWRDi4C WPZ-LH=[L9$2`8`mjkēג{ SXz![e$T^N$j@%;3)>l)վvgWvH l+yҥ-X?OcT""[B7';%j;r^o?xݟ QbH7"o z緲g6^WlXI SpwbMoM ]TU50v{ofƩSS)kfD#V*4eOR4+CԘҽnx\"l+ #|jswmn}ed/"HU',w"?WqeT=(Vj=;CQe 3c37o@|\w}zdN:z@i;2\b1Cqc %ݰByɱMڈ6lpSH$s#$.f:UbU{ʿRΖMl|-yI0GRVeWP+J˘=;0fؚ*I/5ރ([ ȧ/\2+PǼVzt%I6|G0&Cti#_ qes\LDgL*$4f1ƇA{(a"F@17 g^ylݦ\O9h ŭ$8sOGq2UM¤VZD<}IBd4~+@ήGI4sߊkPN7կJcq:uE5/wu\.,9U73㨬ZS-xz6v x 66{Vm MtЏK' N/QM^?I_I3)Y#!3l `tߢQj^H  ;k.T+ la4dCI&F_v歙A9^̐Q uvݦN-A׹Q񣞄P|{,007!硡kMp4,:=.j~D݇nW.FᩞKNŶ߀k0*>u#HH:~k F"}hl@!>U ޏ7,ZJ};䆎*_d*,0?$/,1g(-Ɖ-PJ2,g%ʸFY.Y?GW!nV MEz0v m"6={j +yE!bHO y8ߐ6\huM/&- ׆kMbm {h*IEʞ '4f~RWiI qeJ*{E,B̮>ͬ X|9DF*[ I~ Kx z%zK h SٹiMnEJ:^P`zաׅA5i1}*~_CL;|NۧyĀJTȇ6c;jx?\y**F0 d䛆7e0Et#sӫw^EzB(v /B+|T宽6w~räӥv,{cP}7ZC榹;}{lWz>v3}7+vpŘ7;QnVsK?mzGmT%~eDantܺ"mSF WKڼlVy2\yA.ۥb6*h4̠u4CeVe F[UNa[ @4QkyR?*Z_EGG%[‹C\AMVpJ Sꞧ+K|1[SCmZ8$X4ՍNeOKc5͊jkI%}^!_fX:kFCSP3Oj9*TJN 4B1Lχ00H[fc=u졤yx7Gǐw4mJ U>êA\{}Aa/s^0yI=Q\;8 &Td"!D R 9ANPq[>wbSH:yA) +z)iXmǒg\ USuXJrU)#)bdIHSkMھa@[ie{w] KC"TyWʜO GPq*C-ËKc ͹q6״׊7nNS8*Ym08q\DЄ r?#'+LˊŸZ bOR4$R)2_V+3c l~i'GR<g&ZMxIptBXS+ Po:(c-8XwۆKS:>3E$)*2:d.HZ.)l2#(w7{7#Nzч%^* ԑTG&,;e!j/(gS6ٹ;##EiIŲڀ }JKZY!ݲ.<L4:Z{XĬR >f Xn"iT]I\ Ó%wAny]Em3fNn,BgݧZ^|<>G~,ע[$زMnd޾!6-dH/ԾXzEf6! v%/}x»=y~~bBp&ﵴy7e(B=BZ筋Ͱ;-}3]s߱#ilC[LR`Lې>WEW'p3](k̴]=̃Pb,c{hL `?UDօ,+>+*nN]8xhqf>>``"'̛>e|zG)^1]E`/+տDž!пti@as[W [qOB<SA*R5C6sͯYu!Z?̵ӨpKPՆ:\H[sy#Vdfx%l˟ ;:yFyt(:u}-Nz]8^#=Pu +ILAH͉^+d}_8w!r&j?rډ( VQ "ڻ!?_J0n U߇*p-\x&E9mZ*Iņx)<B f$RH`H_%gx"t&;둊{?X'{Ns34:f(ZK-))9̸WIŽI.2aB%Iϒvp9DNKhڥYۺC؛EkaF3Jp4;@?gjp1zsq䰭sxSmأaW* O/4-lsUf1'cS ]3/S>r欩C 8ίiRh,dO &17՚ f5ْ$ftKHI<&`b~ :Dd);rr endstream endobj 189 0 obj << /Type /FontDescriptor /FontName /JXZMOM+SFTT0900 /Flags 4 /FontBBox [-210 -359 1376 844] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/A/B/C/D/L/P/S/T/U/X/a/asciitilde/b/braceleft/braceright/bracketleft/bracketright/c/colon/comma/d/dollar/e/equal/f/five/four/g/greater/h/hyphen/i/j/k/l/m/n/o/one/p/parenleft/parenright/period/plus/q/quotedbl/quoteleft/r/s/semicolon/six/slash/t/three/two/u/underscore/v/w/x/y/z/zero) /FontFile 188 0 R >> endobj 190 0 obj << /Length1 725 /Length2 35998 /Length3 0 /Length 36532 /Filter /FlateDecode >> stream xlzspfnlycۜضm1m۶͉m['d;unZꍮ$@W5/GsFf^ 333 B(fj 47;XX,pQG/gkK+W)Ϳ ;c3k{kg]ōMEW+s9@TQI[ZA@-4;LMr֦@s3? hf/L.t7wv=@^\MXBQA .ʤ& 0Ytu'_\W3_:{GbcaYL-pLMh\rifD)ۛE\͝f@p?v^!j@cEL]c4țYg?sf@;?{?&uII1a -Łf@K?|;n%cT`?]a?qa`e0q2Xظl~o)ƪ)_Mz[Xx|$-e{BR/|z"]YP;+5 H#o»34,1`)if@fZ&Y*^4.+礒;G Ġ. t>Zwψキw*M^C1gAԔk 6kRA%1ڋPsIk@,~1@qzty]|Æ!f.VLh< Rڞ#e9#"#JZʍ-n5gb^cEnwk|'YI{]c!USa?|q:)>0k]8p f8*a 蟈ץ<,n1POY8ݐAE\*̷^,&XߠUƤnp)cUii"l4%2mV1,= D!D^Jԑ|{ЍqKK?*1NUR#iS[bB_ɰ1~:(|'Ou!jMuFt98n4oppkdLK:~Wv%nd=@Uŭ%*1k+?mw`WOa߉dhfGm/?E I9)QPf35s kc_Y'q;XFEAݿTS%\.IYQKQ{!ssכ\ \+@>+rs:Hpid=+x?[ed{9զbpaV'2`n{hEbd_a#Z=qayN"jcVLIh0 u>KOs@mXrXr<' dՅܜ|Hv 8o~F} oP}8QLn '%|۫QV^ߺE/9^6%>/~9u0lrLh4̲},Sr'㟘SzO w>J61go d\_^9~8 TOA4vE"+0e.№!^+w%C| 6"4nX!|c1NwM>m%M:%GzXl" #(@/aQ9w4w!F5 ]>-{!+'eyuTcOu {v 1Z&MlN>G=t8"6g\}|9\M^g{@uAPxD%q)llJWf~%{8s!FodؗeE_ݓY@} =U\O͔?NpX4NՆ g35 +鹣W9O:x6LQ$q-l6=$h9L5?š+|\CL~5{{}knyڕw#Hn[{*;{lh@2&d>s^- 'MCFx>fRVhDPxM޸NBKȝ7I+ri[7Qs c3Un"'[ڵ9gioIɢuq(ݬY Jl;COaPtA5h' i]nnÎZ٪_~Yi)0[[̈́Z_x]RэE@9nw;?(܁"ˡ yI$GCc*onН:PUT <^q*IJpkWd0?_χ(E ls[;j! D}  P[ql|$>. 2)ͧS%ڿaIY *ö_wQS^m=FNCZ;f$| {-HYcFޙkplîG1:ĒTQJ|-WŻ^G \,\bVvYTd"FӷC `R•W3poqg,Eu_}gQ$`4gPY#Yx(}~%NpVhi9FMdM oQof/DnBpGENWA #+1$Fph4~l) QP[/&Ė2!.xWڭVGbu{?AnZ})Үnz)A*1Y&{Ԏڈ .5gbj:A kBbr-~dS?aNQJ|屘Sf1bC&5)KmE_9F;W: J"L/촙zN(8xX쾑Z)dc^*p]&|(݈.lEvZ7KGγ2/quEa.]+9TlHyr.3UY(]d"$$ҧdD[;}ZBJ8pF}Е`*;sOCЉ|#Zwnl&-!zcb`ii~Q_[gZZ@W͂AQwIi f)>RӾA Ns-:k(tGwhϣ 䏞{㫷OfޮDu ?. sxH2pLkd( csNBFLAoB+ӥY*mz:1hӧ,uCQTO+r*l;a^w.vibH6KӞg]:jY޾[qΧ$>I_a zX)v(}@W٪[ 2)&iTz+p,BKB{2̃ot~i_&/t5 +X'%ž/\qӘz48~412~V`@j!ρY۔Kme Awrj>Uo/^ijLGH3^IKsG%.77+cĐ1"eӭfmt d cLI*v9.u)hqӶ"ƦO ug qRV 9x$P1⨙d]tOևOMA_"iz 32ZM.DaZ2K$U/"ſF| RuH@Qsᩄ |T󀇢䱵uto$ !wcG" }Wb@.E?vaTB)"jNϰ{:U!'D}~]CFK n XZBZaӰ$(kttg,t/ؼA2|Z~l35c`A0r/2,Ъm'ֽv+[*4XC]xQoϟ9s"֔!{ZLtie ,_Oa["٬#eM׋F)7Nc:/)\B%kZ Qӗה4ީը@&,R4G&>쏐Fpw_G:r6s)+Ti'9f~YحKi hv+0σXn,Vh!^jY!- KMn`Ocdf׭ۚW銊 jIAM2e!)GX@"yU8,U rbY)c4аo_-u8o!BnszbTQ th̥wTvA ؑYn3N}/5C~Y&|t&c}J~ɪks+S"V bybtNwqͅ{ẍL!"rM D >UB>|e`{uVvuo;ZOqmU K>1;0"Fۨ2-%ްqm^ItiRxc3 `.|g%7CpK=m'Q[ Jd>}4b&}%.QkT>Sw&҄Sx{Z̅I*-Ep{g4G٣5IƻoRP3xw}3ڙY{k_Eps L+\o֦*s/~sDIfNtR,t 2@htfQG߭U[^Qb+ߖ3m|- B.A\Ǧ_o`H&IR*ۂjzL\@ȣP1 %[r\JA^ -6 G&l8kBOA4[)1nQ`%qk B OXS\E7xCQP " $H#i,< Џ{TmeEcI; lASnb?lG,Ohc>4@@w VDz',Ę?!zc~rgQpBzvZjL Ґv=wv& :k vgq'?i?ߜG[.9W BҤ+Wrhý1,S;{60@Y S 5?^ڨQ>S8X'=:A n԰g,hb F :ב$LV%)(5&H^v^v2^lUUY`wͨ[~D3k C*Y1ڊDz *`!H3z.ƀ{i?[b KUVvR9]<yJ!j <-tQ/9"`|ةg;d(?5e{Px8"(-E Ѕ!wˌm~cXDC;J*f7$ѩ.k Ҝ9{1Vp@(&F%؞*\w8U9 %5um;~xb}T>j;epSddx|Fp.[!=tQ ^$qńPHոI)EU{%(mDw>Xf^G_F)Ckc㫯2㞩En3>;x|#}J5S{{6\cĆ(Y`rD]EyЌwԁy5^;Cz[y"'RRHFDUa.[ GaкBj &(H+^h] gdiqShIt vYw/Bq˃<0ok/l&Rz.dYQ 2 s\BQc~+~5ZYRo+[RsFK~ȏrSzFJ|rH` Q uXK6u;Y0Zڤ"Vh.Jɥ2'6T,; a4j f蟏*R8sx%+o8p௫J>wg.JJw7&zA7HnJmZw3ZX:ސvXTklGɯX3T|[chBgJ$>yr5fį@U}6۴\C4qŏHNxc>9mĥmP/aϘӥg=>m+nUۢ<$IeRd Dte;`*W!TLvRR6uIcbs'9q}[8&@NpЪ2{Snɡ@"@O=Ηx&تgWq<ҹ#h /wQh* Am_~8itFss l=y4P"~bdTs=NZT/E=`b`go W@mT4x.=)ĶgvPYVʠ> $6k暵EVb$R+9D͗IG(/|S6Ŷ*GLqM^O䵺@Dxl(ڂcq,{ 2N򔋩zd"H`kWQlV˦S˹wj|@{>3É2k1UIx”ևon?2Zj65=" c~n2!XW6d4h*+߉j^vzT:8gQqq6xt&"vڂ"S70SBxGcE_|IهNyc˜Gi {x'6ke;%(4%́ϵf=5})Uf c@1`f K ΁u#Jr qrg{ݸ=n71oƲ->CY>T$+m4T48ȹnMR4< KÂw'*-wX J D؄'O "G5ɡPJEL41{7=,TL=2f(w҇YX{M*BN[#xFW ́^Vʼ9֭p'~֤C9\~^ =)*/'պ1Y(GVW5ފtoe#RZ,` q[^B?Z=IT{mm9 H,.ka٪ /j}Ӏ#N#{tذ>![MBG|w|K#a1z] +lW^^2kkIjAE-9<,.1əݥ,5lǸL ;ִ۾-"E ʛګ@Ԣ'ҕ|g1sOp鋻FGT:Ғs)97VpE:d.{CzC#A8@_@{DY7Ifp:":H,~-v#OdR >W%M/I8:BuI=pȾ{nWxdžg$X2%5^-˜?c#N^Jkr_.R5Ez`.< (5Z3&3 $ kW+Eo_=fAY\ ?xm HOҪ^~@ rˈ{g0ppv5Fu.)10c XYಛ: mf/[ﮏ^t}֓hr؁kR=$MZOmYi6jhc|T d5D L;!}2 Ҽgd {Q(zSY$w#- f, 0W2lf3V>eO2{0;=~`G1YVpI:#l/ ̢`ͺ^=~atcKKǜ2?Xy2~Nj;5**D[}6:2/>^fb?@fnYW<_o3cUEKvxʑ!<܌E߭g+R5a4\ټ=߷#qQ{!ub ș݂Kasx.l Cu >ӿٽ0G`W<#͛)I#@pC4иTȃѓDaj5wy)=a5p|Ixci>z jJKm^NԎ\˽a~og`?%Gj$d,E)m;o"=mC{;̜\WA\RL╂N5{LxsR=ƫ}VJZ4+qk}$&bG!~xm * DMoP[=cgU`0f4q88wn7K K N S(!M#,M6fum+dKS> "9}Oc3pd3VTKVġ )~y-0P}UhqEF۷DtA/H&-/qab3;~ L fڛ1^Z1kd?D"K#b?Xxrf>pZ%s'38jRhzN2ݺ?*s]u$KɥRglX^ـkRShy6+1 Q[OMcن|D$5Pg,YA'f]ϙte5 h/D1"ޢM8-h/E(xf\"k)4s7,?!*W_%mR4qth$/Lj8H8ELM{7*m!6$i?8q/N[9բIaZFG0*'FNHI:.pa¦ׄ/cwgn~D<&ꎺ^z\,#oy,g{ 'hYf o@Jeo&c%ErlEDw( R'h{H7 )B.tÎSt@i֖FAfSc 6!0"dʧtny<[HBm(jgzFr'ĿyQ԰0TXKxy2|V\A"x\{1xDB2pAa*jfG/eG?OdDqF:ė߽+OҢUY9Ƶ9[n`6qh\aB\:9Ђ(AָݡX$@X^7-ѩ9T¨GL2ۼOִ(n3zU&gGߧ%~= U$:d:&^f^- e rfڱylR!mx4fnӬP2ϷPI++:h'Ua06gL;|,m #*{Xg!xSErԦx1&moZ5 5):Cx&KG?]]I:2^]WRf x%#õ^~K.ߩSc++wRHM4jWYn̥ ?r3<˰7?i֑.` %S:7߂R٥uKg{gmvsDϧ~b)xiκ#[ƶI:TtϾ."03$1%]1h ?Lsߣts/б[yӦp ndOf[A)T2t&"3Հ]dt1YUf6FXVpM'abNv!d0ՅC2{V9_$ZXI}r4i!ZE*ILJ{i v*0GvN,-A0~X!Y('An,Clu-}oͿ-Mв e v06Fq GYiXGtQlAo*O8߱P4Y^-jL4. B ήzPSb} wz .h:dZ8)&VvgohiX4DZr2#rqfhm)5,|ƀUoRc7l򳝡4㲄}#siI/>3iFR%pUM8{8W)(2V]YGut˺L*4ڥ~^ӣ4Q,w6rBV\*rIaoހ<q3"Ǒx}FD^1OXY>Y1v uLyCWnyq@!BDúr= 5b<0RطhV%vF?Цy\¤0~ֱ%oM,6}]S% `"\&  &A0蛻rUY!@G5 ɭO{C :F-\pQ|֧&Fiq@L=!bKJ9k!-Zɉl@VpA1*>? NOʭ+L0aX\ӲUL$7C:h/uO.!?1hb<XUawlzӳ/LoPS}ĎȏdVsP0*:˴i3 /5Eeva EXlN:|!Ǹȶwyw)tq ]Bhv%Em u;9wU;՗EQ@} 뎰 oN(9K]>q;O.ʯ 4&hYXCv1ҪMq_F9=ʀV^+Qoě_G~d%T-̤g{(\A_ǫAs_5~u|c46GDRs r.w );\Ḥ.zE'3=q8V-p^s9=u`#r֊Yjӫr'q:mכpu<,Ϲ=Z>z߃\2+LNJ(U,w%u˸?79 p-l7D]Odp0LtNv ^]q|R2S3ՠhPoB=!x=; 覿f/S/-Eplܛej)1X_C1 Prʒe,g`nb 8 l)BdFQk|zڎf`J'K:b3]9z`/hOŬ)9(M?1f5A 'Ahj%z!?7?lfO Ĉj;*ý|y݆<-#Bw\AH DIt=k i:B``V{‘,{>]W2?8Q.)(&ׂLE"vDa(k}K +0-|7h\RN'p@rgr1R%C8D76 t`tax=/ -Ƒ9uiiAb@AU&Bo؟ۜkV̨?0ūOL܈VAuͬ r)k_Yot@ʳi HW81g z}@[DJ*eW!X%x*Rv<@` $vo9qJ0N-)&#;wR1?*?3!o*;H' k ؿ ,Ͳz;_M;l%K< P qvsw^ .n Y$&K9=rCn2&?6ֹVoDղZ(=wpG֥<C%#`ȸQD/ˊn\Ze.Ҳ|X<{"I|x=4R%@$Dk@':Nϊ`,HY岖5ߥ1aq Z^^ 'yQ Ni;|L13#ٳ:^uYĔbw}RczbeY=&L +5467VOffk5>JnYex=rayav#-H\2XeHE]?2Et_TR$WV5o z#GSfF%G7HiQ~6\"370ru z67t.2BG"i+@eS!l8Qm:(=H+0Ubݦmre=&fA+u lBVھFXa ݝ|p^2S:*']m/pf09XA8*Sd RD>~@#tFMFC *NSġY qRVmxkOM3%'bcGnn"KΈܳ7WƷlSԤBue\mMiD'h'Q[N30]d R[{X@!ڨ,1X/I9, ?Ӎgvz]Xq:B9z$Ws^RwilpНX1Tӕ@1oux|Zԭg'8@-"z?%,b Psuh -5+_Je1jg^\~^ף-IvhOL̸ vxK1_B άz{h)9Dz:OigVjqC'=ѝ6{X<׭H(eGsyl㧁2 FSL4#sFߋtmEr}a IBOȐæ0{RnƒAaNNi|R/sJ./ګhvh87ÊTmkZlBs5,{Z7aDZjD;ʘ*6&+Fp8W0tu21FKC H^僲ja$)Yyu=WAE{9ư띌'|:P\?8ד6z\ qCb(vx.ft9xc^O/gtPy%0o021&o#-BZt1Ӌwo0*I[ff{;Ը"Lp"[:%#t%MO/f_DGQ_sg#D-fw}TK0ezhk~-F |s.UZen>lϚlZ#oMn̋1nOzݮP. [x\M&evro|ZjQ;he++ AwsiijѹFbObRWBLkHZ>ZAKR4b o7?3A'ULT=wf]y~o/IO$ybo$~ UM7iL*&';g*Sj{ I<"W W-Y8)h\o&crVd<(p{/!a~ijr6kvO9ѮC:p:mFXyRO֓}{=k.??C3]r ١\Bx8^yj|v{nPc'K^~/r}kr=͟77ciT3֙k*SyĨGAy$&<W]AݷC=daAF`sa{Y ]s iaGJw>z.c@̉znG7=+|i슼bL=zt-` qkSߖI7Uַc)V 7x7>~ h) ! Ml3##Mn#Lp~0aR`f,5"N)49%V،C<\hk%fQDG?{#]H)άͩ7s\r?Mv B ge^oZn#x-շՃ~cv$@BMl<`Z<"*o]h$fDihߞx99!zTG-גQϾ 6I#۸Cp=CA=P8Qc,z$9i:dq\<%US;yYApN*ȥj;u:8sz(aV}%jxLzF=^Hs+QL@H%+vpg+\ه) 퓚/) tG|.~7: x&J6 H*T);cVWu'o  !VӺ5X>ج~i.ו5RƯqwJqj "<:RHːoC]Gw[Lbld /p6{nN#m)kS1S~I;X i:6fQvf*~pz\@0Ed(ڪ6^ᗮvDNb/H31Y1oBs#^q9TxNi:jNJ&INAY@}WO7NR7i@MGM )IȯT f [W1sr K[Yh5.M'~R .Px繟j2"+̘,7de'qs{dɷ^ s^tH9!҆_ [8W^V^Rfe˻M+fFH0 =œx䴴6?D.=gRDd djx۶<=$ʗÚrꍾ x{Xz ߏM^nJGcqu{${/@3rbgr8&׃( >V4 4%4\R&Y HhVP9靲0V+䔊\e:e$c'm-z9nKoԟLm'٪/RW@,7e1]N޹ I9My/): 7Sv!'+yOVNP$ST{>yL_:I6 t/1J.&efj#m :/&ͯF3-ʹu:Ä&>Vt6ŠsmB8W/R_JT|3719(s,EtA;mם`lgs<i ub?Y@vJep)Gi*pI`/v)**:␍m~*䍸6O(/ 1;!HJUՎc&ԁ+'xzJ6Y($;صnOsb6|_`DkxL-)+jKCqa%H*' Rw  J/`f~`[Qz\sاSV HwO< 19,sZ<I=|xL+턻\976{nS+M`:{>ԛXޛt'ҽ j,5}BQ cK47{3xl: Rxx)/t; Q[5IYHDLzc d4W0 *%/6#%ꞹ2,9n'E_θ>FMZ"˝k#$IEEJ|cz/|qR+_@l@]iRq#`j:{R3FlM\v,AP$XFd2A<e , BB ]aQczI/?\K!豹~sFNARg6Txei ІG$)q뜧rM]RCX[˩I.bTFֿ<=ådmSvկm,~8obf>hk?&u0,2'6\ߗϢϴۉe7u y/E?L@lj thvy4_-P֨:zÌ Q' *),=Չ>ZA8 َk ?S9^4LkWvvr7Kd6U7Dd9bpEMn;6jTEkH´҅J EGlm:RU⛸y'mc.u9 Cu(n`ºSJ1җ\@©T.@PT ǹWJ\|^*.39fP/L)Oή$/IǤqEr91H6ȕmFUϴT6<Ǽi8MzhF^7/)A{)p:H5fs=[4{*6 (1@Dhv4 Z0 E>U(&$WC'E("K~xexQۙQ??:D 1*R ¨+mpPAqzg=&lҗqz.xPiH;!!/ȸumCG =I `)X7T;Z$!A[t}9F]ڰA5L{lwG5{A|o>5Xa؊M$Q3 3KiOLV9ZfR'2\3'&\eWx/`Dd,V \͞W~¡{|F wZ 432iM4zC4iHqrTU)VI7VKvťdrt@9.9vees~5V`!WX/?_]󗐆mi!?ۖ2ߗ 4 q.t]|syfmK-bj䎀{"*س"J1}kC^B[$Q%_Eu^XBCXؚf~/Ip+MYVԝ>,gkhk+L?!?{ox 틧f3!#-8uٓd2J zռIrzXH4f BgηA7\Q'W){0I>/ *>8W[QO'@Y%wxfZn%\C[6C!4 b,r bd:j0e&*EĿ*C ӝ:X}nQ%0&XmN Jõg5Qŷ\bl,7P>d83EZ֢`Hs]'#C$su,U8h}l-`s,0E˅dxJ/XΦ7_|XyX: yv#H]ۃ vS}7_kŦhMAcrcVʡA ,nk9 ihMUužP{^%`o6=qԜ Y #]/^szHJ֩pdX\Oc~/OVe f_²T;_ TR 7?ډ `FuDW6HgSz)UӞ}HR* LSR\z.!տD;Ql~gA:+IfZb|~XQ=9- f6Y$aeZ7jGI{<$,Hbdruhc )! Dt9ߕ\=~wFS%NxYV  }q;uAĿ]ΔP;ſ<$]Qm)@S'w֯z P';+.ptc=vLb|ćދa ɕ^6c ]O4U ZD,_yT+Jtώ-< .`YOI<> W gg`MuL_::5փ+ψfzo;3Θ({ṴeϘ2]IF,M*BTTg./˭~ⱥ_L;텩Uv4zFRR1.)HvkA6)HVC!xnBuZ{I¯  >5o\JA櫎xv\{ 0ܥ,lBչÔwFXJ;a5+Yk#M>}_[up CН2#W(h]L|m;)l@e0_SwʄSin"}&I-$% sxygy5y؋&la̖KV0hnl>^vmD8rt,dJ`hY$_ėⴂɛ6ʽkib/l)`y j|gc"g?v xPwɠ;Sdk|'$$B| {mux 09,[ɜQ1u d0anCe,dz;?Y[%LܚW,Z^=*jMD\;ɞ]~._{g_CT"Y}vQB^OiDk#%|Jo^=x<_VUu Lw'/Gv;+rT ,a9͵#Y_˅%s:)生UrLtߤ./ k$94t\f{IErN9uB<>HV,evP( _+p,"%{#̐#{P/ zXaK* N YX#Ceu:XGt 9׾sDt*!nkr45vYyMŧ|q# OJDe"S&Sӧ^>\-Vhh/j]2u;03nc:֍X:pDi< z!WROlW̃9K4Q"ôC;R#\f~u.f,vn<+ݰY t̥hH_r:hԥ*jDT"6[qHW1=`QdTj9T4 iOrG=(jr˅QTMaUJg?m#:*ZcbI䕈I7- :!ę!"05* 3On)$ &w:Azrd ( ;1 Jª0Pe8cJvrAja*Јt&ӚĴonKK sXH~`nz^ io iS#ω4EC>a{z(ryHEv6jN-ECՃe]U60!Фv{G8W͒7a8Dkc, ZHVC?ӝzGY^À+:jV,kk'#I^=[Vxo D DISuòCYUG"^s-kA3s$-cF6v IkRya?Q OxRCf|t/23#+EL\$^>ܷPWAy:$SoET${C* ⫈bL`|7;\rrͩfd0j)#j7Sp9 ja P;+c(}2J 37| CAGoX@Eh 1"_O2ES-ZGe^Ɨ׭E~bޡei Qm* 47}9Y #~sZ(&>򛍿Mp1,Q(ͱJ]?.4dPN0wR+hii*EyOfU ?|5T2!u-?%S2G5_:+$%8E]vdcW+B*Z=hKoY 2ΟSVyiQ+ ph .@^/y'9VCuG/f}Ӎ-i}&r^ԋ00%I>lPy/Evq=;tEtxZWzފ62##k/.jQ*> 0999A4>>tN`dd}n-Ei2{$H\_;v޶QT@_:OkP}(Hkzb *&WF^寅XA9s4_8U.e Mhױ˞D{%d)13< N>6=_ Q4HHEφ#q!H2t| gx;FLΫ%EsHAbLS 7M/SqFMjeiF?1jSI#or㢖T݂ľLXgz5 d.V\4(O6#0b^*Iɓ1{)V *u,~5DV:h#cZXkIf_I~spf1 >.]~^yHAĉPi n6Xon5ssfsLT(N7+{ư /]$1|r%֒rGG sF f״,~BO6;k$!=\ ?]e9}hJac0|[JIիW8:A%}_& ɴO pdⅿ.yvԁk 2.T4/ `A5[CFdV}H2^iT)iie~%b0`f#c&\u*|x^wɮv؝D1 L^ 1cyUa^i ԧַWhs~U"wRf\!_QL@I.\n9#$ ǵ o筎h)="y"gϝ8uM5= |=nyb3+S@:H-`,96V˨7pd%#0 9 V \xlK8&EcTR7ߞDܠ$3#ڢ |{NȺGU8T3#GiUJEMcuD(nĸAא`ܵE|5Gu/(=)b~\x2qZ)Qlkgp2ٯI3h囁C6 u؜ғ<>ᯑЁoW J>w! B@-,2N\Bgpk)] .>Py{29Y_=zu6α +V;G{:•2܉f͔V (qRU3v.7[1sFiOޑc7^i fS&\;e o4O is5Şىϩ:q<cz_] WO|V}{vM͒E$cRj!xqj{Kd[p 6$ ՓA'Öd"`[S>iF#*^l TZ{TvpǮ#jG ©bӤ*e @73xgV0]P`RU! i|@lCx3g"u܌2$Cx^ͮ޹]>C:'8!`k6'0믔35aqKXnIpؐ4O<}?7i"if~|o"ER RGCe˯e$~ӄ<5!'nLY|fx(;9C$ wc ;͖V4h'zGxmZn8ޭ]d2RN^sy; \%L&p LbY[Xxlk6@d71A 2'"7ۡt՘GNi [n*W֗Ow=(ٿdݝFN[ߏ,^yW̔ O/.Fj9(8^2.*mn;@âWxY_ǔu:xVKl@ f\1@_x6^Weoa\O\g9g gT#4HzAƇHVNaxGGDs Ϊ6jeS4WFՄ\;i}lnZ̝ZO4"FGM.II5`1e㉣$Fѭ=k:Lg,Gzޅ|;PPO)c/2Xggned2", q(#+VԏY"/#)"7&-HعSN joD:OZ,Lj7P)$*\.LIR-g%RQ!Xj[ PB{V9 2d"nTTk$+ q@&RsI>iT[uG~7tApg”Wr?to#(!y[f@E8=IKWZjh 7d?|KtC^l ᎜E۠iX=3.[jiq[ я-q!:{E '+Yz-Yj5HSmBxJp2IWu@Q]M3إ?6,%j kYX:5x|LocwOje]xPzgb ->fɥ77s~!t,>) ׎mʶK'3 /0=ٍj~*&.l3M ~ܶN蘊C?ո E#?kWnDq]>tA /*6( mLzΊ­R/X92Dz1O?5t'q!J7B+ 0Wof)}8oD VȨS# 'S|x8?oyaQpcBRmf-,|GAiahW3dax, 򂄰K\kƩ2ܹ2pR8 ב]-VL R]'߭|FP:N:qX&nw޸:xMl|:N6QƗKm2Uo, 2EL&`\P&aIt|" G :$n > endobj 92 0 obj << /Type /Encoding /Differences [3/tilde 6/ring 21/endash 27/ff/fi/fl/ffi 34/quotedbl 36/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon 61/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P 82/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 192/Agrave 201/Eacute 206/Icircumflex 224/agrave/aacute/acircumflex 231/ccedilla/egrave/eacute/ecircumflex 238/icircumflex 244/ocircumflex 247/oe 249/ugrave 251/ucircumflex] >> endobj 53 0 obj << /Type /Font /Subtype /Type1 /BaseFont /CZNUER+CMEX10 /FontDescriptor 125 0 R /FirstChar 113 /LastChar 113 /Widths 96 0 R >> endobj 22 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RAKFSC+CMMI10 /FontDescriptor 127 0 R /FirstChar 11 /LastChar 121 /Widths 108 0 R >> endobj 58 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VNHVYB+CMMI7 /FontDescriptor 129 0 R /FirstChar 119 /LastChar 119 /Widths 95 0 R >> endobj 25 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZAECCM+CMR10 /FontDescriptor 131 0 R /FirstChar 40 /LastChar 117 /Widths 105 0 R >> endobj 59 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RHUHOI+CMR5 /FontDescriptor 133 0 R /FirstChar 49 /LastChar 50 /Widths 94 0 R >> endobj 23 0 obj << /Type /Font /Subtype /Type1 /BaseFont /WYSOUE+CMR7 /FontDescriptor 135 0 R /FirstChar 49 /LastChar 57 /Widths 107 0 R >> endobj 11 0 obj << /Type /Font /Subtype /Type1 /BaseFont /TNKJCO+CMR8 /FontDescriptor 137 0 R /FirstChar 49 /LastChar 49 /Widths 119 0 R >> endobj 24 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VUDZWF+CMSY10 /FontDescriptor 139 0 R /FirstChar 0 /LastChar 112 /Widths 106 0 R >> endobj 39 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PDOZGQ+CMSY9 /FontDescriptor 141 0 R /FirstChar 110 /LastChar 110 /Widths 98 0 R >> endobj 14 0 obj << /Type /Font /Subtype /Type1 /BaseFont /HJQQTQ+SFBX0900 /FontDescriptor 153 0 R /FirstChar 82 /LastChar 233 /Widths 116 0 R /Encoding 92 0 R >> endobj 38 0 obj << /Type /Font /Subtype /Type1 /BaseFont /SRSTGQ+SFBX1000 /FontDescriptor 155 0 R /FirstChar 28 /LastChar 238 /Widths 99 0 R /Encoding 92 0 R >> endobj 37 0 obj << /Type /Font /Subtype /Type1 /BaseFont /COSKSQ+SFBX1200 /FontDescriptor 157 0 R /FirstChar 46 /LastChar 238 /Widths 100 0 R /Encoding 92 0 R >> endobj 19 0 obj << /Type /Font /Subtype /Type1 /BaseFont /DNOUWO+SFBX1440 /FontDescriptor 159 0 R /FirstChar 46 /LastChar 233 /Widths 111 0 R /Encoding 92 0 R >> endobj 16 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IOBQJQ+SFCC0900 /FontDescriptor 161 0 R /FirstChar 77 /LastChar 116 /Widths 114 0 R /Encoding 92 0 R >> endobj 33 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PCTAQA+SFCC1000 /FontDescriptor 163 0 R /FirstChar 46 /LastChar 116 /Widths 101 0 R /Encoding 92 0 R >> endobj 9 0 obj << /Type /Font /Subtype /Type1 /BaseFont /YTTLYK+SFCC2074 /FontDescriptor 165 0 R /FirstChar 77 /LastChar 116 /Widths 121 0 R /Encoding 92 0 R >> endobj 60 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LSPZPF+SFIT1000 /FontDescriptor 167 0 R /FirstChar 39 /LastChar 118 /Widths 93 0 R /Encoding 92 0 R >> endobj 18 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NKWQEC+SFRM0600 /FontDescriptor 169 0 R /FirstChar 49 /LastChar 65 /Widths 112 0 R /Encoding 92 0 R >> endobj 21 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PZMVCQ+SFRM0700 /FontDescriptor 171 0 R /FirstChar 49 /LastChar 65 /Widths 109 0 R /Encoding 92 0 R >> endobj 7 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XDDNOG+SFRM0800 /FontDescriptor 173 0 R /FirstChar 21 /LastChar 238 /Widths 123 0 R /Encoding 92 0 R >> endobj 15 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LNIYJG+SFRM0900 /FontDescriptor 175 0 R /FirstChar 27 /LastChar 234 /Widths 115 0 R /Encoding 92 0 R >> endobj 20 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RAHSGT+SFRM1000 /FontDescriptor 177 0 R /FirstChar 6 /LastChar 251 /Widths 110 0 R /Encoding 92 0 R >> endobj 10 0 obj << /Type /Font /Subtype /Type1 /BaseFont /GFPFYA+SFRM1095 /FontDescriptor 179 0 R /FirstChar 38 /LastChar 226 /Widths 120 0 R /Encoding 92 0 R >> endobj 8 0 obj << /Type /Font /Subtype /Type1 /BaseFont /JAUNCH+SFRM2074 /FontDescriptor 181 0 R /FirstChar 28 /LastChar 118 /Widths 122 0 R /Encoding 92 0 R >> endobj 26 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XXWVXV+SFSS1000 /FontDescriptor 183 0 R /FirstChar 28 /LastChar 120 /Widths 104 0 R /Encoding 92 0 R >> endobj 12 0 obj << /Type /Font /Subtype /Type1 /BaseFont /FQZWDC+SFTI1000 /FontDescriptor 185 0 R /FirstChar 21 /LastChar 238 /Widths 118 0 R /Encoding 92 0 R >> endobj 46 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EBLIJN+SFTT0800 /FontDescriptor 187 0 R /FirstChar 46 /LastChar 121 /Widths 97 0 R /Encoding 92 0 R >> endobj 32 0 obj << /Type /Font /Subtype /Type1 /BaseFont /JXZMOM+SFTT0900 /FontDescriptor 189 0 R /FirstChar 34 /LastChar 126 /Widths 102 0 R /Encoding 92 0 R >> endobj 13 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UGGDAF+SFTT1000 /FontDescriptor 191 0 R /FirstChar 3 /LastChar 126 /Widths 117 0 R /Encoding 92 0 R >> endobj 27 0 obj << /Type /Font /Subtype /Type1 /BaseFont /WNCMKK+LOGO10 /FontDescriptor 143 0 R /FirstChar 65 /LastChar 84 /Widths 103 0 R >> endobj 74 0 obj << /Type /Font /Subtype /Type1 /BaseFont /GGPPKB+LOGO8 /FontDescriptor 145 0 R /FirstChar 65 /LastChar 84 /Widths 90 0 R >> endobj 17 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZVJSAR+LOGO9 /FontDescriptor 147 0 R /FirstChar 65 /LastChar 84 /Widths 113 0 R >> endobj 67 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ALSLCH+LOGOD10 /FontDescriptor 149 0 R /FirstChar 65 /LastChar 84 /Widths 91 0 R >> endobj 85 0 obj << /Type /Font /Subtype /Type1 /BaseFont /STESQB+LOGOSL10 /FontDescriptor 151 0 R /FirstChar 65 /LastChar 84 /Widths 89 0 R >> endobj 28 0 obj << /Type /Pages /Count 6 /Parent 192 0 R /Kids [5 0 R 30 0 R 35 0 R 41 0 R 44 0 R 48 0 R] >> endobj 54 0 obj << /Type /Pages /Count 6 /Parent 192 0 R /Kids [51 0 R 56 0 R 62 0 R 65 0 R 69 0 R 72 0 R] >> endobj 78 0 obj << /Type /Pages /Count 4 /Parent 192 0 R /Kids [76 0 R 80 0 R 83 0 R 87 0 R] >> endobj 192 0 obj << /Type /Pages /Count 16 /Kids [28 0 R 54 0 R 78 0 R] >> endobj 193 0 obj << /Type /Catalog /Pages 192 0 R >> endobj 194 0 obj << /Producer (pdfTeX-1.40.3) /Creator (TeX) /CreationDate (D:20090204144403+01'00') /ModDate (D:20090204144403+01'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX using libpoppler, Version 3.141592-1.40.3-2.2 (Web2C 7.5.6) kpathsea version 3.5.6) >> endobj xref 0 195 0000000000 65535 f 0000115065 00000 n 0000115085 00000 n 0000000015 00000 n 0000004490 00000 n 0000004385 00000 n 0000000067 00000 n 0000573944 00000 n 0000574590 00000 n 0000573300 00000 n 0000574428 00000 n 0000571905 00000 n 0000574913 00000 n 0000575398 00000 n 0000572329 00000 n 0000574105 00000 n 0000572976 00000 n 0000575841 00000 n 0000573622 00000 n 0000572814 00000 n 0000574267 00000 n 0000573783 00000 n 0000571199 00000 n 0000571765 00000 n 0000572045 00000 n 0000571484 00000 n 0000574751 00000 n 0000575559 00000 n 0000576267 00000 n 0000030784 00000 n 0000030676 00000 n 0000004847 00000 n 0000575236 00000 n 0000573138 00000 n 0000035534 00000 n 0000035426 00000 n 0000031013 00000 n 0000572652 00000 n 0000572491 00000 n 0000572187 00000 n 0000039416 00000 n 0000039308 00000 n 0000035776 00000 n 0000043434 00000 n 0000043326 00000 n 0000039598 00000 n 0000575075 00000 n 0000048226 00000 n 0000048118 00000 n 0000043674 00000 n 0000053213 00000 n 0000053105 00000 n 0000048455 00000 n 0000571056 00000 n 0000576376 00000 n 0000058280 00000 n 0000058172 00000 n 0000053465 00000 n 0000571342 00000 n 0000571626 00000 n 0000573461 00000 n 0000063229 00000 n 0000063121 00000 n 0000058532 00000 n 0000069204 00000 n 0000069096 00000 n 0000063517 00000 n 0000575982 00000 n 0000073542 00000 n 0000073434 00000 n 0000069434 00000 n 0000078196 00000 n 0000078088 00000 n 0000073748 00000 n 0000575701 00000 n 0000081905 00000 n 0000081797 00000 n 0000078449 00000 n 0000576486 00000 n 0000086144 00000 n 0000086036 00000 n 0000082111 00000 n 0000114285 00000 n 0000114177 00000 n 0000086350 00000 n 0000576124 00000 n 0000114932 00000 n 0000114824 00000 n 0000114515 00000 n 0000115105 00000 n 0000115197 00000 n 0000115289 00000 n 0000570373 00000 n 0000115375 00000 n 0000115873 00000 n 0000115903 00000 n 0000115927 00000 n 0000115950 00000 n 0000116424 00000 n 0000116448 00000 n 0000117690 00000 n 0000118864 00000 n 0000119300 00000 n 0000119877 00000 n 0000119970 00000 n 0000120531 00000 n 0000120969 00000 n 0000121617 00000 n 0000121690 00000 n 0000122325 00000 n 0000122446 00000 n 0000123896 00000 n 0000124979 00000 n 0000125074 00000 n 0000125167 00000 n 0000125424 00000 n 0000126686 00000 n 0000127602 00000 n 0000128361 00000 n 0000129610 00000 n 0000129635 00000 n 0000130739 00000 n 0000130994 00000 n 0000131543 00000 n 0000132850 00000 n 0000134519 00000 n 0000134746 00000 n 0000140258 00000 n 0000140538 00000 n 0000142353 00000 n 0000142572 00000 n 0000149661 00000 n 0000150012 00000 n 0000151880 00000 n 0000152105 00000 n 0000154588 00000 n 0000154828 00000 n 0000156511 00000 n 0000156731 00000 n 0000159043 00000 n 0000159342 00000 n 0000160585 00000 n 0000160814 00000 n 0000163794 00000 n 0000164017 00000 n 0000166751 00000 n 0000166969 00000 n 0000169707 00000 n 0000169925 00000 n 0000172603 00000 n 0000172822 00000 n 0000175621 00000 n 0000175845 00000 n 0000188093 00000 n 0000188329 00000 n 0000209965 00000 n 0000210326 00000 n 0000227609 00000 n 0000227920 00000 n 0000241965 00000 n 0000242263 00000 n 0000251725 00000 n 0000251953 00000 n 0000259788 00000 n 0000260028 00000 n 0000267581 00000 n 0000267809 00000 n 0000284018 00000 n 0000284319 00000 n 0000301692 00000 n 0000301939 00000 n 0000316658 00000 n 0000316905 00000 n 0000349374 00000 n 0000349776 00000 n 0000371972 00000 n 0000372305 00000 n 0000400602 00000 n 0000401236 00000 n 0000419406 00000 n 0000419707 00000 n 0000430136 00000 n 0000430384 00000 n 0000439298 00000 n 0000439554 00000 n 0000467088 00000 n 0000467515 00000 n 0000496683 00000 n 0000496958 00000 n 0000532663 00000 n 0000533165 00000 n 0000569817 00000 n 0000576582 00000 n 0000576657 00000 n 0000576710 00000 n trailer << /Size 195 /Root 193 0 R /Info 194 0 R /ID [<20B3058E808A852E3BB9BC1E171AE40F> <20B3058E808A852E3BB9BC1E171AE40F>] >> startxref 576982 %%EOF mlpost-0.8.2/www/slides-jfla.pdf000066400000000000000000015131661306046515300165730ustar00rootroot00000000000000%PDF-1.4 % 3 0 obj << /pgfprgb [/Pattern /DeviceRGB] >> endobj 12 0 obj << /S /GoTo /D [13 0 R /Fit ] >> endobj 20 0 obj << /Length 13882 /Filter /FlateDecode >> stream x}˲-q_GW6eE4uf֕( v-YCd||!_?#wGH-=cWF1~蟟u~g'A!G"yҞ5W}^c ޷ǿ=3[|wD GV~(5fo `7`._+yt1G7؏&>?>l}n}XopOxwҀ>?`B}j4%?7Œ0x̂G_V9{|nVdGi'G[y|Gw~/k~]}r?xӎ#>?il G뎽-"ώ>{bˏS{7?8o_V}cݏ+Xfd/2>DUdo˯Woy)_]Kb~n_f |7"o@s8~op")s*8ŧ+CN& -o7߿ܕ5i26(.3qOɭŖmbX{nˡ}Oߠ(խ=K-=w' t,X}\+>Z GyB-Cuz1/#fBmt-X"a "J;08;ylhBP,sE=Ga٣b'I2[[.:0lbO)a Jk/vcu br/ѯ'uXPǏN쉚/``V3uD`d0EίRfSUr`+,}`U&ƴkGe!kV"qDv2a_.UP4U0I5 5x+cHXӫdA7ԇ` X0hCs,B[ ;E o+|Bś&v4U2Ԧ/\e`hYZqO~m^O#oؓut* #E@xA1CƉ '2q^FW`vA26VgWҙ*#8 {!b Z[ e,Pn*ks Tr6\n=aqakh1>Bml% ˀbq[FuCʛu n-ZGnJգA1JVi[q V-~sP#"(agb<[S ۫0A0865Ki٠*Tb=غc䇽a ) 9'i'R]S˖;Q`lF 0.Y;vAd G}!DShb tلiܰtL"hAQD.U1ZjFZ t;Z|" 4O#GXޚigQ1n hƢwf*gS9}NpsTFp&. FK\16>Z|Ph\pv|q+-1VXJ/>}ₙ;z6T}-Fϴ'3C@ *)

UݥxP(PxJZx÷ $cF 5s͗#GvผHBJPj,6qke #rB]X#,%}h>T1kA+!p 2g ujgSS#ztV3f`A20;`Fk2yc1 Z  oc1l?`cA9Y4>à Sz>TO8gƻV,@ }'c7^"jwm7F KPFv DwV0f9y.Oo/ =Ky]I{'{bq47pdd GO JkD.v˚_uGĄd^dyyת/MGݫtu&q֊)0>S5at=2F;KcSdFPD}CcKOHbjuXU/*MLE_ ^5L-v˚[u㿣bbr/<Njhs$JIմu A (&[˥kbWYג7m EzĮSۣ*İ "X ]xس22ɢ>3~y[㫎a0T\x@׺eœaŚ3\)k@rhć/C[׌5Rd0*Oߺ0oKyd'5`̂شNcfl:9vX`~rw" .^+X:4 -eApA %5>&keCBT=JُƓQA 8%ZZhF,ꈐ!r6'%m9@/is]I+5mK`7isP /is)=]zo9e`w +@`d3LxڜZ9aR^n$yt˦&hXzVZ3b'#4sg+.Yڌn0uX)E f[Le\jUZ &ݖ8u͈uRR&C8m:!A$(_zH:؈5ү@S'80Ӎz;t f~5`Iu.|aBybI5 Z^"NCPKWEQBzMʹLQEejk42L>ZCux^x7e+||Н2^Kdx^ǟ7efv禌unx.PsuW.dIbĉ2^ׅk1ݒUZSSk BLeꦱ8w`?3eQ7B<Hm?$%%4}3-{O".֥Wv C@p\~!%(S>3y[ca2dLVU> 5nj8dw=24v  &e7xm{%'b#3:ɛ*61Wp+ܜ0&lX8eABvVPXQYpW9.f.d𚹜]rnΙКg.lK5nVְ'ŎJCväiHy›e. sWXA|0SExV |Vn$5\ 6Tpm#ՖCZq<{bz|'!yWbzMMLE r!5L-fs˚[u㿣rɘ1C\R8YЎqW=ǹ:X'b8Wʎ,`+!Gl8D7θ86JDbawAr'F`~UvlUz<~VP\geN1?l˚:_eĤ^y9ߥ*t9Vstš%5S +| |Mae oWpV#U-[Apyy0I 8 M 3ܑ,SۡuAWl>2r=l@c>&(R(Ce*wX}#(u>hJLe%NJ9džE4S> (1U`yg2 zku*|̲U︘41HuNH|Nwxn"9FsFsxϑxyZ+- qrpӍt e 1.Xr0ǰy053i#룉M2-f=cC-KD=̃NfXz(Z}5]L!a.#ć[3J1c<[Uo߫8HΉ`ql;9)JbFzX!l])2kH.8y7Re<`/GÍ,'4rE'rmJo`%ܛ4)eqU0 .KJ0u#(@*s$70Sfq&y7,-1@IbxĔxDt6R7m"bMIq' C%P<N̸g.kjl= adLPEwAZ, 0 `vpaV Ai/+sk`1Szc.Sϰ{R^r&}8WEhrj6Br2jR<\3㛷u . eXHwy,}u\y^WaDܥ⃺髌9%}F5}]*k*hS+)TZ֨"e:% oTWHUȊۏ! #VGY@1 v:9Y8BgNWł`6l'HV8! Hu[l%fϯv&$=;ͭ,M/v>-e'zh,/2zn;\^6r!;Ⰾcc7 r RҔ9*.֩J甲R6^YSg7L\F01'Sٓ13ٝ%j +\ݐ3(a%M~Feӻ'@af,7㮄LG.CSz1NyC`7<\lUK'Ub) H1cl2b65 fjj'8M#UbY\YzOxM; g ^RD5ext٘қ2۬m N!/ȘM:_pYR_yz)%mtSb=]Kst-nJZb=ݔXO%ӵzXOw%ӵziXOZb=]KRb=]K,!S4/Ag&qpf*~4 FV1EI;##ME>?wxqVǣ0v4jy2c:)< %D% @Hc!H^ $(S >3vYSci#r=D c_ 4RTi!ҋ[P㠷)åQ$Cl;CrfΔۮR[Uٿ07<ӊ)ж7я`S_)'9o Z߁#/k;ݫygt膭pXmP))0߫hg[,[#6\'#(a2h1Ϝ[تC#|󆥨y:udԷJ<+n4r(wI4jqn Ld뛹'TCQ7ܲuE)/JB: #8 dt ژg-kj\Kн4SQ}ҊtX(`k)}R0L'<8K~Ʉ9fk )Q4EvBpS@;xŏ8I J픵1όcX+c #}k|zUmt^~'^~kt[;]~תR;VNתwTNR;I~Kt[;]~ת7#6< +йƆ1ba|Nb)kl800HƆE;Ylx\Wij!YEy僒izlX8]lXl6LۢoE}MQx-E}㵨o)okQxS7עR7עQU7jQx-KQx- ku;Q , P%2bg=vɣ̬9.#R&f),&of{#]{05ehމ;;PJ9))@XBuC[)gcqU0*.:*CЍִ=G4z <t*h(!ЍpQdܬ- bS$飵k/T,<0XƢ!bX/e'xw˘QPiJe|#瓵4񎇉ǑqMU eZ>bVC tK5صJJlZ UVCʠ #U e"#ʐ^DMUPh#R E$k5pGk5Xr.z$*z͹."kEל\sKEr.v͹%BA Е L3"8T3Lx΅ʚ֛ aR/9w\b  lXY(g݆^6~ތ XzbҀAFXҀq5&5t}:SZ?2J=\0ҏ-,*L^kQK m1&q'C(8.kQH J1όcXc  }h'QϜ'$\o}.[cCu31Mea\a49i:VLzѾi:s:d߼Ir8j.u\:;wrR<7>2YK pd\blc\M`f)T*TtSiF@y^1r\d՚r~3ִGfo:4-1;'$ 돧\r)0ޟ96hCҚɠ >snY[cawTLLEk!]NֳwHg%Xϑ阬*n`a͞Osu6 3ZϚI3mDmզyT;h^z46)7@?$S*)zo*C-B `z녁ȰmsDz"+8O5.c]NyJU7& 8CS<ŠYtu6tī9~ yB $@ srz_˓C1[~IG?}ap䠟VB90pi,,o6Ɋ{<6q!Oh{Yҹ%Wn+__);y[-eyp6̐|$7סɅ<Q΅V 1{Ջ}(,Jat9.wZNw:Huk:hmLP[wA蛷Y,k&{V+tm6\ ɫ홰Ok;oi/KtSi4`9|"ݞO1baɱzj|YIɅ Pۂh=6cxe?|E|^'c팇һz22,b;0^ pdFumT1w1c&;?7[1tw97݂ͳn~l )oC3;Fdv1Aț/سogÐ!OXm@U*NU3ҩ6;g1)3VQAC,!k- 3^UfUCs &2d^ѽ5r84c͌ҹqXpD_6eYWZlzMVwjV5SDMԶkv]6QVڦj5AmO.id_Ur%5dkbZռiiz7Ș,4Ͼ$ayHe$<5gaWGE{G;wbQG`-Fwf'ST26dHcjdӮ͆ 뱗#Fq.,守U7E\/x'rM-K"n\!7D "~C\/xj騭E fyUXCK ;J!tMꝾxJɋ2TH׸}&+hM0+yz7O ɶFӋ$)T\+RdXrVS,5N4j'󆆉p q(}) "vA5#)Vw#־۸, 6͘&mCtY&r0a zMu 4|}{K 29H'7L 6H 1@ljr[X ؕ1qŭP* !|'ԕSbGukOUZL7Gbңj1Q59j1UQn6E;QsvBLFd:sJf UxtwTMd9fYا(Eze2^/(_DQE"x2^DQ׋("xse\D"ʸ.ze\Do.(EzeCTWg#REͦQu5V5 TMZ"r5 ],3VQ<yw:`'dGqQь# P J^UFbUuK[P{6S0GKjz|?ٗo~Oo%O_W?;xV/?*5?,2ZAo"'g +kYihOɹ/?VOE~i-6= Fm~x2?O25Q/o'__W,y ?V%B|2_ ,__] endstream endobj 13 0 obj << /Type /Page /Contents 20 0 R /Resources 19 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 29 0 R /Annots [ 18 0 R ] >> endobj 16 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 8 8] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 30 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 30 0 obj << /Shading << /Sh << /ShadingType 3 /ColorSpace /DeviceRGB /Domain [0 1] /Coords [4.00005 4.00005 0.0 4.00005 4.00005 4.00005] /Function << /FunctionType 2 /Domain [0 1] /C0 [0.5 0.5 0.5] /C1 [1 1 1] /N 1 >> /Extend [true false] >> >> /ProcSet [ /PDF ] >> endobj 17 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 16 16] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 31 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 31 0 obj << /Shading << /Sh << /ShadingType 3 /ColorSpace /DeviceRGB /Domain [0.0 8.00009] /Coords [8.00009 8.00009 0.0 8.00009 8.00009 8.00009] /Function << /FunctionType 3 /Domain [0.0 8.00009] /Functions [ << /FunctionType 2 /Domain [0.0 8.00009] /C0 [0.5 0.5 0.5] /C1 [0.5 0.5 0.5] /N 1 >> << /FunctionType 2 /Domain [0.0 8.00009] /C0 [0.5 0.5 0.5] /C1 [1 1 1] /N 1 >> ] /Bounds [ 4.00005] /Encode [0 1 0 1] >> /Extend [true false] >> >> /ProcSet [ /PDF ] >> endobj 15 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 5669.291 8] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 32 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 32 0 obj << /Shading << /Sh << /ShadingType 2 /ColorSpace /DeviceRGB /Domain [0.0 8.00009] /Coords [0 0.0 0 8.00009] /Function << /FunctionType 3 /Domain [0.0 8.00009] /Functions [ << /FunctionType 2 /Domain [0.0 8.00009] /C0 [1 1 1] /C1 [0.5 0.5 0.5] /N 1 >> << /FunctionType 2 /Domain [0.0 8.00009] /C0 [0.5 0.5 0.5] /C1 [0.5 0.5 0.5] /N 1 >> ] /Bounds [ 4.00005] /Encode [0 1 0 1] >> /Extend [false false] >> >> /ProcSet [ /PDF ] >> endobj 18 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation15) >> >> endobj 21 0 obj << /D [13 0 R /XYZ 10.839 272.126 null] >> endobj 27 0 obj << /D [13 0 R /XYZ 351.995 0 null] >> endobj 28 0 obj << /D [13 0 R /XYZ 351.995 0 null] >> endobj 19 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F23 22 0 R /F25 23 0 R /F17 24 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm2 16 0 R /Fm3 17 0 R /Fm1 15 0 R >> /ProcSet [ /PDF /Text ] >> endobj 37 0 obj << /Length 2170 /Filter /FlateDecode >> stream xZoܶ_oP4@ćMnl'$#^I{iOpf8H7{'W@*YP$e(4N'_5ݿ~h㛿Kk֐'NyŏٲD{~!s\sqT_cW[\_NNuMR^QY՗5 zӁ|(,'&6FlwRCZ;|]7?nѳ5G7۫m\nJG)m]❶~s}^\bз^D Q 0P;C'6Sڤf-Xg!-coC8u]? >͸d9)0Uv1VBe͢UA3N8s?xp97c&xAANo2"GPT 11,"ExC⦥9Ŷb5h1@؆ xO2jItjCH4rC#l|yl 3) c8 Wܒ`u~]'Dl4f8ATF/@_h2M8дF|80 Cx!lECFy@:n.4.`+cAy;HJsc29P c/uJ9ex-6yQPq2&cy-~ R Vj" t 35)13!dA3OZЛDHU"bz\7CD'Q%ÂNaM`*k[A1+3}\XBn{A8._UpDHG=ve|ΣsXԢ-͚G|D'(%΃ψ6yyj-_2&4EŰ3|13_| #E DH(*1.G4}G_C($3/Upq^߯ggc;3ar۟{%YĊ'k%AN4O}^OUqđ'eZg;EɆ ff6\@3?glZgݽN3Aڊv[IAsf T %<IiǍR,s:uʽpx/ iWC|ZW.?J?f#jLyjv8=4zoӾ [Dx; DXqp!փaT6f<AB/v~Ĭ't%oxf͙_יxX '-KlW #3|sols]n -cC]t޵)RmڕgeDUsUn.ٙӧC<}fd4Ln*.(k~[jk@svu>=}|SoK:zoOTzW=I4YiXC[DMk`PY_5Zr)V,=3h D<&$c .5N|?7T'FO}tu?sO'/O,[ت32@U~m۸~mm*]6m|Ub6mBU~m"Ī 2$IUe1iÑ6zj݃Жz/KmCنZ)XmUن^UD6IJmCQ V"iU`fG+Ha[}m&Rm5_VXH5HR'<U1'vvvm+<ٮ'<=Pڭ\cVf`؁A%D)-tli-i alAbZ3R#:BV Nb[ ifIb[}mz1C)涚579 .]G;HI8 C_ ?$)8d8ɏy7H;`q͎Hcf' X"2e^{EK58YqԼ@^{T_p#&~GK Qs*6q}zTnš-)|CDy%ʖrIʕ7e8fAt]ZHu#.tS7/y!xkXDدq8VĞ6{c`"jcv {4(]$6qxvq\nݶvpA]jw1k} 5e5:Q$BKTq C۔`Ļ/s, F%I*Y4Q䭠 8uȎ|\RX'ج2yJkF iœBq ܶWAL1KuAp#=+l*apڄSkyߎ4*~$d2>i߯5>tL!:׽$[?|lB+ 1ݴ+ZlG7-z{6-1/YͪuAP^lZ*w]Md&F./Қ1qliٷnfm~|$k"ov#z0Wgl7[?Wj2TMUFݛעݰnDqh7;G*MƁ-EDRT,`KQG8 T%[H`KU li=c{ ^,* @3--j^ӼF[_8=ATpol/z^ܫWY4fUadfQ EQY,̢j",Y̬"U702852V%߀dzSUl)6i}Rʂ_u(Z3]ބm5- yNcТOVzZstV,2|2-44-.c ȥ/NeY26ҲV#;k -M@nIQ|-4`ai^Ōns'Eۋ`fIlHJaAʁ-Z-B+PF=*M{ջPǠ<=ӆ@N}]{ z~UC!ɣwJvjI܉Zc6)ZIOm5 :=Z nFb$1Z'`VP`+4a30:tr6_@,#z0 "yD 5ٛ:^fv4I=>𘞁[ކ#gyh4\|(R8~܁s*$?):W-+|-U/qkv0%<\-ׄGT ~r)}Ψ:{͇O]^]]goo.o/>5[_ޟ֨_=!zd{mJ<R,Ƣ[(5|_[נ{P"&X%L2r.o. t=z#/kfFl|tC$ϙc-pP-zo}gU·O|sYBSHOvG]-i54c6\J endstream endobj 48 0 obj << /Type /Page /Contents 49 0 R /Resources 47 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 29 0 R /Annots [ 46 0 R ] >> endobj 46 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 57 0 obj << /D [48 0 R /XYZ 351.995 0 null] >> endobj 58 0 obj << /D [48 0 R /XYZ 351.995 0 null] >> endobj 47 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F17 24 0 R /F50 50 0 R /F11 40 0 R /F49 41 0 R /F51 51 0 R /F14 42 0 R /F53 52 0 R /F6 53 0 R /F55 54 0 R /F8 43 0 R /F56 55 0 R /F57 56 0 R /F19 25 0 R /F21 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 63 0 obj << /Length 1370 /Filter /FlateDecode >> stream xXr6}W4p#.}K+3i2cM8,+ltI)q)lR:E `{v0#ȫ#r $H-FP.4)IOn gH9!jKꇵQqGrŻlyأ{oŇ?RT(2mAmEMbxARiAWҌ)"2N3dxI>%jY,U/$ۢZ}~I?2 SERg`ŖrC8[{G:niʫ|4JLKqjH^(8;gRMO?8qic@]\Rjݪ?y DOR[&sS b7-qYY~?ɻ^ʽwaj@WKbI^u/EUU\lw)rũ4{M*/9+:pUkX+މxwEY zXe^D'HC8'O=+}j2_58RèH|oc +pl'Tܬ EZҨI"fM" E7"[ (wmZ+gTp[3NS0LKFv])xx494~H;dT= QAK(nQ͠zYZm ҂5ؼ6$x:sRf6Xi`ra;،D>1m>;'6`)*QgAˬ$~|p_6Οxaզk=/m&9%q5ʂi+S#id&$Ι<>].PƳٺս{mAv|_򶾴kb]#G[w7 m!}{< <KJޝj>_ϧF{7>pVd _ [#WXƊn|Ojxh|+N+ e=x]Ipw s䮕ʷ]x @A*S^l#i8du;xC~LD_=ܫŪ?(,?y1W~-f˥k&X?2\ìcGuصA57{~;c6\^>Om .|eWU1!jGk^/Ot.l0O~PAt@}=xO&#W쿕ErC,smY 5?GiHg endstream endobj 62 0 obj << /Type /Page /Contents 63 0 R /Resources 61 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 29 0 R /Annots [ 60 0 R ] >> endobj 59 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 5.139 5.139] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 69 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 69 0 obj << /Shading << /Sh << /ShadingType 3 /ColorSpace /DeviceRGB /Domain [0.0 2.56972] /Coords [1.67305 3.66563 0.0 2.56972 2.56972 2.56972] /Function << /FunctionType 3 /Domain [0.0 2.56972] /Functions [ << /FunctionType 2 /Domain [0.0 2.56972] /C0 [0.88 0.88 0.955] /C1 [0.4 0.4 0.775] /N 1 >> << /FunctionType 2 /Domain [0.0 2.56972] /C0 [0.4 0.4 0.775] /C1 [0.14 0.14 0.49] /N 1 >> << /FunctionType 2 /Domain [0.0 2.56972] /C0 [0.14 0.14 0.49] /C1 [0.09999 0.09999 0.34999] /N 1 >> << /FunctionType 2 /Domain [0.0 2.56972] /C0 [0.09999 0.09999 0.34999] /C1 [1 1 1] /N 1 >> ] /Bounds [ 0.797 1.59402 2.19182] /Encode [0 1 0 1 0 1 0 1] >> /Extend [true false] >> >> /ProcSet [ /PDF ] >> endobj 60 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 67 0 obj << /D [62 0 R /XYZ 351.995 0 null] >> endobj 68 0 obj << /D [62 0 R /XYZ 351.995 0 null] >> endobj 61 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F17 24 0 R /F51 51 0 R /F61 64 0 R /F14 42 0 R /F72 65 0 R /F26 39 0 R /F76 66 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 74 0 obj << /Length 2210 /Filter /FlateDecode >> stream xY[s~ǯطR~ɛZNR$3q(͋~gX,D83"g}Ypv8Ug+ämCuu0F斕oWT{ZϺ-?iN *dBZ7RQ`ӓzLFi+5F4;v:qj%dnzEOnoׯ/@ЍnCiѸG>Κ0 L*hH9o4.%#Y%%|ua_.&rBZ7Xm8B !DgRZ4r2gPiCôDf$Z~`Y+V]8ϣ.Z'cx%m oi])JN'x5+G .#}>_ꀯٳ8zSE%3ݫ&yw*셲 A9l^ǟz꒱' @㈯G!_1_ hׇa_ aed/A P2(oF<33%6D \5$;Ehn6,"d\. [E9s OSw1cE:JCй^ao B]pM~׊6i%&7v}| :]t+'7-^vI۸LhU>rg֓^-M9?PyZ:8DơJGsX<89J6x&nfΤlַr9$oҷMU$e'"?H*#u2tRRFI@~ 1<!z],Ŏ|U}=yOЗy&a6n×tKdV/~,6q()6foq;Ɇd\WNzrWI|.V \7z%eN[rQqЎfiz;V/LV#F:wO3s>n*O923C^ p X}T} NZҘTFk+HH ̠@S@i~W=$UT:HG)!%|J>{RSk@j@z&^ffE*r̦ʂ6`.],]SzU{U r{!{#ףF1GMvO [JyLT<-D焔Vp#%IJ۠[̊*Ub{<(nX%N228X[5^R],P@=#j3L KdY}=\+-sf'Z þgGB3aTޞeF;3Em1(p^ө JY WP5DQp~%0JfuLP%H8GyYUnKnX"5>SǓ܃("(#S%[ola Ź6 EhdqJ1,hyJ Fձ.V&傶9(7"aM?3@F ]컪9uL`\Ew軶Ui¼m}$5}YaQ>msIl*:J Wo;+8Q뒎}$#/do2CB= z~hu1]-n_Ϸ4ay ǟ~ ''Co;j8}q &ʽ uuxN<''^~35 kCl[?=Q}&\!>J%)Mw*C<, `y@o=> /Parent 29 0 R /Annots [ 71 0 R ] >> endobj 70 0 obj << /Type /XObject /Subtype /Form /BBox [0 0 4.141 4.141] /FormType 1 /Matrix [1 0 0 1 0 0] /Resources 81 0 R /Length 15 /Filter /FlateDecode >> stream xP( endstream endobj 81 0 obj << /Shading << /Sh << /ShadingType 3 /ColorSpace /DeviceRGB /Domain [0.0 2.07033] /Coords [1.353 2.95702 0.0 2.07033 2.07033 2.07033] /Function << /FunctionType 3 /Domain [0.0 2.07033] /Functions [ << /FunctionType 2 /Domain [0.0 2.07033] /C0 [0.88 0.88 0.955] /C1 [0.4 0.4 0.775] /N 1 >> << /FunctionType 2 /Domain [0.0 2.07033] /C0 [0.4 0.4 0.775] /C1 [0.14 0.14 0.49] /N 1 >> << /FunctionType 2 /Domain [0.0 2.07033] /C0 [0.14 0.14 0.49] /C1 [0.09999 0.09999 0.34999] /N 1 >> << /FunctionType 2 /Domain [0.0 2.07033] /C0 [0.09999 0.09999 0.34999] /C1 [1 1 1] /N 1 >> ] /Bounds [ 0.63757 1.27524 1.75346] /Encode [0 1 0 1 0 1 0 1] >> /Extend [true false] >> >> /ProcSet [ /PDF ] >> endobj 71 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 79 0 obj << /D [73 0 R /XYZ 351.995 0 null] >> endobj 80 0 obj << /D [73 0 R /XYZ 351.995 0 null] >> endobj 72 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F82 75 0 R /F17 24 0 R /F76 66 0 R /F61 64 0 R /F26 39 0 R /F78 76 0 R /F50 50 0 R /F80 77 0 R /F46 78 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm2 16 0 R /Fm3 17 0 R /Fm1 15 0 R /Fm4 59 0 R /Fm5 70 0 R >> /ProcSet [ /PDF /Text ] >> endobj 85 0 obj << /Length 2657 /Filter /FlateDecode >> stream xZKo7bth,C&HliOqhb,'_njƒ,dFX*N|Tx*<"GHmG$f5 oL䧠1Ǜߕ8B|rwHad 3./v MV4*+Ql J3U"J??/sެߟܮ.&tuWa{&2I?lGQ<_WJ,#t #ec2*C0 Wm'I_;fmNįz":HQ9QNjsf%.6{w(~)wPra4[0*=+Ƌ@i 7l3g ** 2Y!-4 YH j,Y.X0ll&rІ?mL,߆O5Əa;)kӼ$$ۄ!j0FxmlHK:tLd_HnJ44mu5I&**CLְ*zcO1Lb5b%IQI+:@:Zެo-I"iD0+80hAh@|  Ҩ$a6RMs'HÖ H7.R頬 Vh鱲@#.{D.HaHF! ?b `EZI~^|E6s e'I> #q *"2A jL rEM~7|0(HMm7aރNUߐd鰲*n.k?A0ٍ&"yŜV htIe. G(?\I4*G@1WW֋,V{P^~'/5*IBK+")"VP'i4B*Ĺ|y|@ɘŏGǏؙF-(-{Hؖ"AW\DΈP|!Nf/3ee7=Hºh+&ZV+iO$  *,V7=XvVWher!N!3rXhq  Ls3QOc}'0CzNpH~R{@`Vh篮W,ٮEQD;Wmr#~bߔz%ɟUZ@HCvw5+sN%ѿp8_WKb٪HJ*hQ4Dk*Taf~mrJTU׬7ݪi:qZ;Sq"HJyk"/T3i"ɦ02q{ÇLxrIkp€±& vCuJ\cZ ~#lG*jԜ_!8ii3QԂ_ N|#-];E҅Ed6%ߊSJFA'r/%BTѨ[= /*/h࣒8x4F3ec58mJ0my&z41Ye$Edl ,Ȧc_Y|:EښsW%'?SvJ1܉&ZdϟShfRM&"Esqc\~z_s:gD"?R }쨗ǝ5 3> /Parent 29 0 R /Annots [ 82 0 R ] >> endobj 82 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 88 0 obj << /D [84 0 R /XYZ 351.995 0 null] >> endobj 89 0 obj << /D [84 0 R /XYZ 351.995 0 null] >> endobj 83 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F82 75 0 R /F50 50 0 R /F76 66 0 R /F84 86 0 R /F83 87 0 R /F19 25 0 R /F21 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 93 0 obj << /Length 420 /Filter /FlateDecode >> stream xŔKO0 N:2" 808*݆Ŀ'YyRv\c#p[D'ߜPČ@aqɒ_Q>|72 kK2C|"~gi$30e"UP9)Y AWH&Z}Hn?R^wSS7Ԑ8B;/_B$Z+OӒV/U2슔U(/(\r7l9C I α^+T,d^- bVM'+"n #'(M}t V^=$#,ݸa:/^ZK)&=5 bZנ/~JC߫W6n2> /Parent 97 0 R /Annots [ 90 0 R ] >> endobj 90 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 95 0 obj << /D [92 0 R /XYZ 351.995 0 null] >> endobj 96 0 obj << /D [92 0 R /XYZ 351.995 0 null] >> endobj 91 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F85 94 0 R /F19 25 0 R /F21 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 101 0 obj << /Length 1289 /Filter /FlateDecode >> stream xWKs6Wf GoqZu:3XhR)ʱ},ےݙzX~]BHa 6\"L2A7'N1C_r`Sʠ/xGty٢ށB˄LETP҂Fa.w\,;A^Q>G5 sB`$h1uGv` L℁S9pӈ s,\1)N"Ch{[ uP0) f?alFE. .-63GydaV\CYP#*J3Pmtŕ׳àjiΥ3rl[c).@ڃ;hѩցY$5hab8:$(:(X x#:hᶌ/؊7.SR .bMyR׳b6e'1sJ2Z Z_ u- 3,lй/ĝճ`iס|Au^o][hMPhEc|+q.j_`>|R@Ʋ/KV|Blf='~p}[^B)h%$Ub@,nO|뮺~a@ɬod5EZ+] 1(|\4Ͳ O".vnRItx9j~$~> /Parent 97 0 R /Annots [ 98 0 R ] >> endobj 98 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 103 0 obj << /D [100 0 R /XYZ 351.995 0 null] >> endobj 104 0 obj << /D [100 0 R /XYZ 351.995 0 null] >> endobj 99 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F86 102 0 R /F17 24 0 R /F83 87 0 R /F84 86 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 108 0 obj << /Length 2731 /Filter /FlateDecode >> stream x[MsW(GnvNf7Zдeٴ $%J2\X.#^wcS_gjq8~:LL46[/_.z77vNՐOJ =3q7[l Y{ǗWt]R}Vxzbpum<v.Z0{{{m!c=q7*OTA)h?fv.5Ӫy6Q9d<)mwT١yѤzs7]tie{Lbv>omɔ!.R++mbG@KwYs JvQ.%`|[m5]ar6765df,/XBzma8Р `&0emXtfpͽwބuh b.؇hFSb!b1TWBdP5LGh0,xH8d3`=^ QA!0quDa(l$0'q2 (bBŘF[ɇT0tET (&Mm[D!2e0uwG gSX 8^ eSdR nfijmOACT UT2~QIJD9-(ԈR4:A,Z&эu5<%e14mdet 2jR<b*9󨤏hm¢Pz(X@-> cɇQӵysn3ا4Wn|--&/PLGS ܣkNxT@sԀHijA<!d**| 5N0AUP3j|\ʮXdlǣPD~5gn7tUz1.L.24OFlh}5A[UQk.?-/*cʬ"q"EybS8Q )l$KvEHN %~>#XZ AxF7Az^QC z>Sj+i]\T~xEtʍ=}3< óRkzecS(ÛpnCrvQٻ}iBPX:g<^WGb͆6!D@F8PrX`)R nÎ>O7T=T+CC7ԩ,X hVst0Pg 4L`+Rv[SP^"700*T5BaRN>>O7 NQRiMyePKe1;z<& M8#4N)IY*b ^ iwB U16{)2 Xܨ˯0;yp9?W1tp8)LuS}V؉Zekq=h`X_"$:#i* D"mjRVI;>6# ` iOؘ㻽pd}ЪշMUaՈ ZA Tb-&$KSdRd{,yTzQrbJwL]Z U}UT8HԶ m6NuFΊjm9}Fo&i"N`{a\#­Qv6q9cD;rǎ{~[ҫL{}h cWozmж}%z+Ϳxػ>1#zU__Zs~wju:u<뫳_Cg,קHpVyv]Ǜ:BoznLHڣƒ`}Zmi{A".ӹM8ۏ*뮾 ߗ bly؛I~tr@}O&x,w_bτ(|z`T>ID7(` endstream endobj 107 0 obj << /Type /Page /Contents 108 0 R /Resources 106 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 97 0 R /Annots [ 105 0 R ] >> endobj 105 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 109 0 obj << /D [107 0 R /XYZ 351.995 0 null] >> endobj 110 0 obj << /D [107 0 R /XYZ 351.995 0 null] >> endobj 106 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F84 86 0 R /F11 40 0 R /F76 66 0 R /F19 25 0 R /F21 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 114 0 obj << /Length 1728 /Filter /FlateDecode >> stream xYKo8W(+oR=hfnoMpm%l'ݢ3$RKĔ>qo(F.#Nˡ^ˆ4:raH]={ToI}AۓKk;}Ƒǹ[^t! Pdq*}z֢}= ARA&QӂY2/٧z:-˛q.6r̳z ɻ;w9:pCTr@Ј,Ӫ\`zڛrؔx'jSYY.lh6caWѼY[3CpjT&z>^}JeO'Aoa@e+1/xuɹ4^5j,[1)q5Lܓ sO:_A:("/5?C3mT_pqp[K&>[Գm5zA[=(h *^қqo8ܢ際<&G i)I)t;b?'x1"ۗo4 J)e1l.mf\NW0#4{c4nEZb֛XGAoϟo']Uwɩ,!oNp߉PCPZȾHe|9qmHAMa&t\=-TwUJB:J0AI:«"2fvX5TtXzU0uXkjv:v{oOI0x@ 6ҳCYMB.q^B0qؖ3t mp6#kSĒ─mG]f$)ڛ(X؂% ! 5*HEY7@7=ޞ"xлl?}J/=U~^^2}+i>XS m+I2NWoZXT+Dy!eZ8wH!ӊbf%hRRg'1d|ռu<08tƳP/m0t-w4Lò 4Aލ}q~sXF9'Dfr0Td_Ǡ=N%! qLv9 "UaMJ`ObTRv$~ ]eYy|i5y&@R2P(9/\ ߗ$dj͝dA11E4.Ѣ+-Bc@E5ެ8ǹ))xלZ$4hc" tvixxiDǀjX}0[@m1Ih ᓙ[oGb+xCoADpAp/mmx+"(xXGNjZI%6uyt8z_̶?^[c3>9p}< 4i~4䘗C'w=r8NO-֗"%.j<w2֫UsbB,C\G[`WW1~z wCIZ$%W-„+(> /Parent 97 0 R /Annots [ 111 0 R ] >> endobj 111 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 115 0 obj << /D [113 0 R /XYZ 351.995 0 null] >> endobj 116 0 obj << /D [113 0 R /XYZ 351.995 0 null] >> endobj 112 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F17 24 0 R /F76 66 0 R /F86 102 0 R /F83 87 0 R /F50 50 0 R /F84 86 0 R /F19 25 0 R /F21 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 120 0 obj << /Length 2008 /Filter /FlateDecode >> stream xZKs#W(r+Q6v*LQ !)QFd9j9oFF1%nGW•pZFZb3דv*(܈Kj7]>'"xK2*lN\kAV뵸Q:ev$ J|el/^9'&cRyhW噅Y<. Fe.9 :5~}SOݞNq鰫U[ڶ_y\v86)+HK]?K1d+:UA|s}9K axҍLw Y)қ庸Ɣ=`Av@āSTlI6S2.Z3ZaQR6hF#sJQe)3جR0([O 0=#.aMucw w0lQ[}W%ў$%΋l$06>\L!N.rU` @FSc@z tĠI{,O]E& ̳P jM׸ndCw;TvȽKncJ'%~3o͖OGcY'ylݬ7=/Z9%f0p.^LC7w>=QY_V`P:FQŴdEUj` Q!٥ (z@V 65TF5\}ąo ?暐K$;翮wd~dkΘȍIU* UZ{sT64,^i_%q&"K:TUc+2r]>2xq?)?]w`dA=oɱx!$ev| ,X]=夗۠DRl2J&`-9~;e_ejCbR7 AMXDh3B8W |>5r_ ~m6U)sϧAtj91^FGӄ蔷#]`Wu]j9L=g.>W\zj*co婮Ns5Ub1Wz}#tK}WCOy})B5Y2JS:!*YI  xk endstream endobj 119 0 obj << /Type /Page /Contents 120 0 R /Resources 118 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 97 0 R /Annots [ 117 0 R ] >> endobj 117 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 121 0 obj << /D [119 0 R /XYZ 351.995 0 null] >> endobj 122 0 obj << /D [119 0 R /XYZ 351.995 0 null] >> endobj 118 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F17 24 0 R /F83 87 0 R /F84 86 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 126 0 obj << /Length 1606 /Filter /FlateDecode >> stream xXr7+p0 R9+U]e,(rDM<$ԖT$@7uM`(1J1#vmKXS{JbY3e?];kBͼl9؅BH  1=[gQ7gJ1i6N Ô< φ},dӗx]/RPVͪmapQsa5,LʟJo9L X%XF(Je9йz^Gd jYL[UgcNДNB78KwLFlM_Y^-jӐo|K>ތe_Ob=wٮHWz"Qu!Z.2 Ԭ.kr;v.kբB[9yXwzY9VԼE}Mq/1cJdadC\afQIC.6S)!Kr~SR|賓\CMj4%V>!=K# Ýz1` EGѫxLLWU;7pbܬʄYbD_\HbJDiZ-297t%}T2R.܃F͡7#﬷T}\+M\!!HxbP쫔[+[#ʭ (+Xѡ%N&F$+Wue^r(ڴKK HKӜYYs}!Z=)4WM Jٓ}X[VϽ‡`` f/4H3:#I8u]͈PtX0mռpkB,#.36Ї%ml6IJT|a!!o` lQij=x"E̎I Gy ݯ>*MR#-#a6sWYC{u yRsLV}A'tg{@`UKif^ە' <; Njܬ^m5* BD,DshMw8Br0f iO!Ab%ޮdOS l%T$1kah&!'@VE@.FwNSA\$:FT4qi0hH.|,+n)"BL/_ZeQ3 )1X$@P.Ҭ+ȴ 6x`A(v#fg(Ꜹ>ݑt^yNr7jCcj'^:SaO `D/K켍ƒx|Ѿ4fpVf6jTFz:Xƛ$A wV#8BoYfJu(<C+!G Ġrh_]n*nqEfZ_o~mdg1pwqPq0{pmrIgmi%DD\HYRgn> /Parent 97 0 R /Annots [ 123 0 R ] >> endobj 123 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 127 0 obj << /D [125 0 R /XYZ 351.995 0 null] >> endobj 128 0 obj << /D [125 0 R /XYZ 351.995 0 null] >> endobj 124 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F76 66 0 R /F17 24 0 R /F86 102 0 R /F46 78 0 R /F50 50 0 R /F84 86 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 132 0 obj << /Length 3622 /Filter /FlateDecode >> stream x\KsW-axtQJc'eKU9X>%EQIٕƻg0Ҋ墪0 b]%]%]?PQ8(Fps1>{h먆7o^5j!ո!q. 4WzꛫnRhG+:ȭKX 2̱ FB?,.FkyFK "?]^]ކƈy? &NFa`Gz- }0x #'}/nS섚o.ϯR:uyn/直Ky|q./7oz{ACŕ^RS.K(7b^LP@9>a !vףCѢ`W|PŸ!  ԊJWGCmAmڦjmV3 u:z]r=S գԜ-|#j;FX#tmeT,w׉*<%/Trpˑ%)iaAʕb.P5)I/`z,wLȹZ$Áa(X)N!c1HB-̏ڤ ͣ*UTԚL /jA;Zc^F" @ЂΙy4ъGMfaMepr3|bDE̬: IZ,ъ! sH:SjVY =VAn O3 v. Y B h@AA\q1@@ t .f.4} hA #%('HP4?bȪffD,kSjU#hbƖD5BU/Z's9=XH Ka_$,;nFn'U4uǩn oHdP: +:5I OOg8;eÓlO^z%;x<ߖR])mJnOG۸jӦ{~ϱplH7l>u2&f0 p:b'}x |(ጠƦ)td3(" [Ȩh~!GבppĐS`Q/ڜ02jW;8$(hWd ԘL ^Px5BEN BHSκtt'(45XZGH("+@(g y E$]^dB gzp&XiGI4Q0Pj44 Dl'~GI t. Ϗ  GF ?h٪e<奋qFpTJ *dF%&bTaAxmo]#}8=Z:+O〪,=-i=!3KVE[z[Q=l%NlJ`)}I\g'^H(`H <O{>  TqSvO ӿ]5k J|J endstream endobj 131 0 obj << /Type /Page /Contents 132 0 R /Resources 130 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 137 0 R /Annots [ 129 0 R ] >> endobj 129 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 135 0 obj << /D [131 0 R /XYZ 351.995 0 null] >> endobj 136 0 obj << /D [131 0 R /XYZ 351.995 0 null] >> endobj 130 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F82 75 0 R /F89 133 0 R /F17 24 0 R /F51 51 0 R /F14 42 0 R /F53 52 0 R /F6 53 0 R /F55 54 0 R /F8 43 0 R /F56 55 0 R /F57 56 0 R /F11 40 0 R /F91 134 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 141 0 obj << /Length 1698 /Filter /FlateDecode >> stream xYMs6WVyZA{zJugķ8Wuّ} (YqI<xX<2U `0r%YFG_9c[V~}󽼦o{5׎;SzX_hOC?IkNM>n1-(]_ DLj%vq<7B325{7|v?MfwHI7ŋ65\Jnj~z0;M4:=*~(%j&Lw|QzHEtL d"n 4t6"?[/Aå2b5]_/Ŵ[?L/+ [|[5p - *0qiDžjvV=<[!E9bXy嵢۰{&Fl>P'`>xǣyW|VJz*41rSxJ@.>%c I`F PS:F.pEtO])#S5@4FF Pi&2:)%Xr4@J6Qb1dV"c%ȜZZZlq+-V+-x. &@ 2x:[kȝ(?fh~LAZr4*֒!}Oo,g(uudapX,m+)\UuXrx بzf)_-͜"$i)ԅ7 ] !EPUwiW}ArHhWa%fK11=R9pcN{(xWSZ*DM*+ n}vB ABX#=Fb@>ܰ0VSZaJFs$Fo4֟ {GZN`3I悰ԏXkT 7R_3,XBF,~d@z4eBnU[wPQuxA"p`>~𘈔S5xV$Vgv%.Jn4+l~=IzV8l;>إ4v/B&z[ɴ嚌ԂEH޶-<ƹ2XwRb0ZT97 IB(lh I1k6qʒ$YIP!6GI !"f Y"YVY`zƷ.;{ iO)ʭFT 2~:v'/oOxtv|!E+ v Jהnv j^QNNTxm'J-2Duj2Yu2}6.,FՙtZO"hn\zT| @`lׇ~TGפ#K>.!ą}}X6PzCTQC3.|U:^3GoNmi_U(ƯX I=8zTϔpduP8U&<:S4\^߭|v4=,?j/ZLg#gm5?O>4S0؁WЛC:ItHzJ`BIydjG^ …wER(}tҜ-R]8}w,}qV7*~r9BM*(:N\*#?/g1Y#LB(Pזlpn?Z endstream endobj 140 0 obj << /Type /Page /Contents 141 0 R /Resources 139 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 137 0 R /Annots [ 138 0 R ] >> endobj 138 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 142 0 obj << /D [140 0 R /XYZ 351.995 0 null] >> endobj 143 0 obj << /D [140 0 R /XYZ 351.995 0 null] >> endobj 139 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F82 75 0 R /F17 24 0 R /F11 40 0 R /F49 41 0 R /F14 42 0 R /F8 43 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 147 0 obj << /Length 2195 /Filter /FlateDecode >> stream xZrF}W-d ͭh8v%TI%qD`0E-"H=BW(=W#QhJPNRb9+.?o :ZbyUY[ŷgh'!O!Yާ1 12zé齳oGJҔXU_$a E j>狛h^|3ѩRJGnuMgAtҴt߃̰JBeʠ4ZX"`R䐃1t ;1Θ pI4< 4V䴒]@k)drU2Қb%)r uؠ<&~)s/{=1y`24OV-Ja_J|,ld6xP"cfY*,qi~q:X֔dtOhN%gNj,#冓b`}-c-@IS -yWJu~?&_v0xPC|41a ZtF]X~h+t|ӽ4yL))P+>?_Kòac?t=+r6Б;"_գ~.W"ᬪfGMC?[OKL# IB;!uplKhzm3E({U!9_!A ]6`S&Ta ɠ !s%J'~qštօs^¬4zhjΧ.>K4!=jBl^hSdձ1pqs1϶8$N)4(4u|^\c4[`Ww˫Egj~ypg6V Uޟs}h0֌5$!6 u"c+OF8KddsG糐HeeN)Tv)Eu6(,UaR4 KxEB$=RI郒Aū(q06Kl-e0C3kt"Fxiyܨ9alJ܇n C=l ڦ6PX fhCQVؓr9z>h2h cdh,@ Ld UL\ ȳ c?؀y𖸴'"5}j0p61YO%! ?aRN I&oRP-QI _r6eO]U&Mbs#E"R+ HcI9zB">uv|W}- SK $/_ȳݿg{^@ӍEwՆ?ݗx_pbtd?w??aPP>-;NFZ yUkћjz)fY{T?i"4}czFxQ7mZ(Pȍ{ʖ̗|d >77=7tWwS}Md6 |6^¡{ *x`d|u!>}FU0}}渵_6{Mr00+PR Ք6lv`u endstream endobj 146 0 obj << /Type /Page /Contents 147 0 R /Resources 145 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 137 0 R /Annots [ 144 0 R ] >> endobj 144 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 33 0 obj << /D [146 0 R /XYZ 351.995 0 null] >> endobj 149 0 obj << /D [146 0 R /XYZ 351.995 0 null] >> endobj 145 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F82 75 0 R /F17 24 0 R /F50 50 0 R /F77 148 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 153 0 obj << /Length 1508 /Filter /FlateDecode >> stream xXKoG W̭2 = I)dWm9rg/i%KΡ]sI.9ĭPںP0^hAK^faGԢbu+~֎jQl~b,{9[{thVj+[AmLj-/GsYiFDڑL*˙4~x^],*CaI8a;Jy4h :mwR+N]wܐ[FުCz;܃*Zbا7 Ϩh"ԶIXtɨ|d"csD:hJ\*ER.:Ab#bGzcv'%C '6[<C'چXl]~P\AvLhCWX-5&C 6Ȣ榦U-{+K: (ghi#% j,k3 n29Ae {v2&krrskmi%`Fh:EK#Bڠ[:mZT']jiQ+XTU4(BxI&nĔLCY:`#BωeNc480yFD lMN@,1rqybLOr4Ңui-Q^p11~#,~ʭr 6j1j_Vi,抂xi\U3[Cّ@1p5 +rt- #'{fu8:m_TdN޾g,^/6)S9әZ8<>apD8-%F fVH,_=ɡq 1Bp*WT^>R.) 'Jo{11/40Ʀe0\;> -|)^k> ?R/,4Vm ">Nl 'rpF2p~\͖nqeO~~XN͟ccj>HwB͏CWR}czgrL z:RsFz\xJ{.Om>|Z1KNg'|;sn?a2^ƾ=Org 7WѷՂh ' ՘6In \)T. endstream endobj 152 0 obj << /Type /Page /Contents 153 0 R /Resources 151 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 137 0 R /Annots [ 150 0 R ] >> endobj 150 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 156 0 obj << /D [152 0 R /XYZ 351.995 0 null] >> endobj 157 0 obj << /D [152 0 R /XYZ 351.995 0 null] >> endobj 151 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F82 75 0 R /F17 24 0 R /F84 86 0 R /F50 50 0 R /F92 154 0 R /F93 155 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 162 0 obj << /Length 2074 /Filter /FlateDecode >> stream xZKs7ϯRhf'VyC,Uq MI2%;1 (Q/Z[{@Ggl[W3E0^ ]Y/w&=*t;欭?fRu?Bo!#c<у~v!j"]\r*ğ| ,Q=nZ!6+V(}{}_-NnV(??T+aj}}3fa8;<ֺ׿ϊ+j-2Be^PzG$)*Q6F gC1=tu0[\Fp^݌wh?[9Z:l󛛫'MwБ-7gkу&Y>@ˬ 6bWQQiPQkX9,QoOP#j8Ȱـ(I.ё1(8!Bׂ7J - SFXnQ*DHb5A S*xZy A:mȎV(,f_AYtQxys \<ԍ&cM9T;AP!E!^N8`7!,)lW{l?a%.~]& - jQI6<6oAE'Gaij 56Be:;`~)'ϜP:!~;z7Y$Aꋆ  !@#$QB"yi))*M 8etm "gZ c)shF$둉fMoer1m \)̾].MW=gGlNPsHSfS{LE654Bv(`  y2qK ֢9^Uup,3a$V@M [BC?ʋR;QE%oQyAFBoJ2" eWXlbk1[k i>H1:1 _ ĂKSPTj'cЉR: DP[g`Qk+(Zh*X4Xk0U`֖}^h~]ʠ~(>ԣIg:)pNX0.NVz8ǽz¡> BG*fawUXhHjdc \JӕeZqȣ&wWh-:Nl [6{$E8:K=|z%x|}&/ CXg%bt*[>=`)bP>Y-x޼m,JZSicP% J{{I(_4 r\V 08ED a`mNo!DRG6 vb&U*It!ទh$t!#H|UDK`DB{=c+2PHbӒ ky%>Ui3a4[F9,{VaKGVAswajNJ>mVJrFFy}z8lW NW"þ>?T,LB{IxՄG$HFϻ?~5w )=90z2?\!}Y}r:^|#;7Z*wtೋ4kQ[odG$~״XPrbmCjo 3=[_^/÷u_PY%7}#{ګ9x6q&Fը"o`ӏƪ+Zʈ9S~Heo{^X]#X endstream endobj 161 0 obj << /Type /Page /Contents 162 0 R /Resources 160 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 137 0 R /Annots [ 158 0 R 159 0 R ] >> endobj 158 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[0 1 1] /Rect [106.949 206.286 233.459 218.664] /Subtype/Link/A<> >> endobj 159 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 163 0 obj << /D [161 0 R /XYZ 351.995 0 null] >> endobj 164 0 obj << /D [161 0 R /XYZ 351.995 0 null] >> endobj 160 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F82 75 0 R /F17 24 0 R /F83 87 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 168 0 obj << /Length 1101 /Filter /FlateDecode >> stream xWn6}Wmey'o ئh@ZvȲ#nË5E Hz!E  i)gÆK4Ô)T[4s3.>_Ϫ 7c[k"~-}Y΄L|C*lmDm{7 CT`.C)2X8%&䡘MjsuIr41d1ԋ^>>%Q/0Q HP 8|Ո:ΰƻ+(4ysIq{0Ԫ;% Kb3v?1 cuE c(F*R*Xx[~e<T3I͓V>M\d,̏ / GٵYGkz)#iR~(֠q.0*tz b^)k/~|‚wƢeu C&x^I.V%x3c"^A#D"x Vꧽ0M^'$ eZB2p\Vr䃳=-3tik#Nݰ (f/ʱ4R77Q<&BSDԮЅbG!^9A\LR͑g(<@P1 6V, +w⻓nةm]YnZPN1BRTR]\HxXHKMd΂A "n/0;|N 8y}S0t_YE K/G84v+Kx,9 b9[0{~hrZK> /Parent 137 0 R /Annots [ 165 0 R ] >> endobj 165 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 169 0 obj << /D [167 0 R /XYZ 351.995 0 null] >> endobj 170 0 obj << /D [167 0 R /XYZ 351.995 0 null] >> endobj 166 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F17 24 0 R /F76 66 0 R /F61 64 0 R /F83 87 0 R /F86 102 0 R /F26 39 0 R /F19 25 0 R /F21 26 0 R >> /XObject << /Fm4 59 0 R /Fm5 70 0 R >> /ProcSet [ /PDF /Text ] >> endobj 175 0 obj << /Length 557 /Filter /FlateDecode >> stream xUKo0 Wp7Yv[e@&Nf[Q:hs"ELJ9×QAT}" iYd )_]z3eM\C/m௭ bm0| sY)+*P⡗Tr%'f:Lj  LW` P x%fH 튪L6.pHV,~8BMϸTNNo/h"{4;w#k&:?CXl+["?}a()@]eyMG9$>0ӧQl\xֹ^T佷>Oi 3GYZ;u.Oz'@3$&Y1t3JeQ,ϳTHEou|noRct4Wx ͢Q[ɥZ{TmmϟVHdN.c\ӆV6$iC!qKMYOh(=-_3Eߐ4΁{8%Aގ> ; \ͤ2ȹH = .& endstream endobj 174 0 obj << /Type /Page /Contents 175 0 R /Resources 173 0 R /MediaBox [0 0 362.835 272.126] /Trans << /S /R >> /Parent 179 0 R /Annots [ 171 0 R 172 0 R ] >> endobj 171 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[0 1 1] /Rect [103.97 161.449 258.865 176.589] /Subtype/Link/A<> >> endobj 172 0 obj << /Type /Annot /Border[0 0 0]/H/N/C[.5 .5 .5] /Rect [131.963 0.6 230.866 8.07] /Subtype /Link /A << /S /GoTo /D (Navigation1) >> >> endobj 177 0 obj << /D [174 0 R /XYZ 351.995 0 null] >> endobj 178 0 obj << /D [174 0 R /XYZ 351.995 0 null] >> endobj 173 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F22 38 0 R /F94 176 0 R /F19 25 0 R /F21 26 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1 0 obj <<>> endobj 2 0 obj <<>> endobj 181 0 obj [507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5 507.5] endobj 182 0 obj [531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1] endobj 183 0 obj [285.4 513.8 513.8 513.8] endobj 184 0 obj [625.4 704.1 583.2 556 652.6 686.2 266.1 459.4 674 528.8 849.3 686.2 722 622.5 722 630.1 543.8 667.7 666.5 646.8 918.8 646.8 646.8 598.2 282.9 489.5 282.9 598.2 761.4 271.9 468.6 502.2 435.1 502.2 435.1 299.1 489.5 502.2 230.3 257.5 475 230.3 774.1 502.2 489.5 502.2 502.2 332.7 375.3 353.5 502.2 447.8 665.3 447.8 447.8] endobj 185 0 obj [525 525] endobj 186 0 obj [976.5 803.3 833.7 731.9 833.7 789.6 602.7 776 803.3 803.3 1092 803.3 803.3 660.5 314.1 545 314.1 660.5 833.7 314.1 620.2 586.5 597.9 631.6 564 541.5 648.5 620.2 304.8 428.8 642.7 518.9 755.3 620.2 643 564 643 609 462.7 597.9] endobj 187 0 obj [306 428.4 428.4 550.8 856.8 306 367.2 306 550.8 550.8 550.8 550.8 550.8 550.8 550.8 550.8 550.8 550.8 550.8 306 306 856.8 856.8 856.8 520.2 734.4 730.3 732.3 703.8 793.5 654.2 623.6 734.4 777.7 305.6 518.1 760.9 593 961.3 777.7 809.3 701.7 809.3 708.6 612 748.1 754 730.3 1036.3 730.3 730.3 673.2 334.2 550.8 334.2 673.2 856.8 306 527.3 565 489.6 565 502.5 336.6 550.8 565 259 289.6 534.4 259 871 565 550.8 565 565 374.3 422.3 397.8 565 503.8 748.6 503.8 503.8 477.8 550.8 306 550.8 673.2 183.6 730.3 730.3 703.8 703.8 793.5 654.2 654.2 734.4 593 593 684.8 777.7 777.7 824.1 809.3 708.6 708.6 612 612 612 748.1 748.1 754 754 730.3 673.2 673.2 673.2 795.2 305.6 565 515.4 527.3 527.3 489.6 489.6 717.4 502.5 502.5 550.8 259 411.4 353.1 565 565 565 550.8 374.3 374.3 422.3 422.3 422.3 397.8 397.8 565 565 503.8 477.8 477.8 477.8 595.6 353.5 520.2 703.8 730.3 730.3 730.3 730.3 730.3 730.3 946.5 703.8 654.2 654.2 654.2 654.2 305.6 305.6 305.6 305.6 793.5 777.7 809.3 809.3 809.3 809.3 809.3 1068.9 856.8 754 754 754 754 730.3 640.5 1224 527.3 527.3 527.3 527.3 527.3 527.3 795.6 489.6 502.5 502.5] endobj 188 0 obj [372.1 574.4 957.3 574.4 1006.3 869.8 319.1 446.7 446.7 574.4 893.5 319.1 382.9 319.1 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 574.4 319.1 319.1 893.5 893.5 893.5 542.5 765.8 767.2 766.5 733.9 830.3 681.6 649.7 765.8 820.1 320.4 543.1 799.1 617.8 1011.6 820.1 840.5 734.6 840.5 740 638.2 776.7 793.6 767.2 1086.3 767.2 767.2 702 348.3 574.4 348.3 702 893.5 319.1 550.7 590.8 510.6 590.8 523.9 351 574.4 590.8 271.7 303.7 558.9 271.7 909.9 590.8 574.4 590.8 590.8 391.2 440.4 414.8 590.8 527 782.3 527 527 498.7 574.4 319.1 574.4 702 191.5 767.2 767.2 733.9 733.9 830.3 681.6 681.6 765.8 617.8 617.8 713.5 820.1 820.1 862.2 840.5 740 740 638.2 638.2 638.2 776.7 776.7 793.6 793.6 767.2 702 702 702 831 320.4 590.8 537.2 550.7 550.7 510.6 510.6 748.2 523.9 523.9 574.4 271.7 429.1 369.9 590.8 590.8 590.8 574.4 391.2 391.2 440.4 440.4 440.4 414.8 414.8 590.8 590.8 527 498.7 498.7 498.7 622.8 372.1 542.5 733.9 767.2 767.2 767.2 767.2 767.2 767.2 989.9 733.9 681.6 681.6 681.6 681.6 320.4 320.4 320.4 320.4 830.3 820.1 840.5 840.5 840.5 840.5 840.5 1117.5 893.5 793.6 793.6 793.6 793.6 767.2 670.8 1276.4 550.7 550.7 550.7 550.7 550.7 550.7 829.7 510.6 523.9 523.9] endobj 189 0 obj [516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7 516.7] endobj 190 0 obj [524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9] endobj 191 0 obj [331.2 276 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 276 276 772.8 772.8 772.8 469.2 662.4 658.8 660.6 634.8 715.8 593.8 566.2 662.4 697.9 272.4 467.4 686.4 538.6 863.5 697.9 733.7 633 733.7 641 552 678.5 678.4 658.8 934.8 658.8 658.8 607.2 287.9 496.8 287.9 607.2 772.8 276 476.1 510.6 441.6 510.6 441.6 303.6 496.8 510.6 234.6 262.2 483 234.6 786.6 510.6 496.8 510.6 510.6 338.1 380.9 358.8 510.6] endobj 192 0 obj [843.1] endobj 193 0 obj [988.7 813.7 844.2 741.5 844.2 799.8 611 785.9 813.7 813.7 1105.3 813.7 813.7 669.3 319.4 552.6 319.4 669.3 844.2 319.4 613.2 579.9 591 624.3 557.6 535.4 641 613.2 302.1 424.3 635.4 513.2 746.5 613.2 635.4 557.6 635.4 602.1 457.7 591] endobj 194 0 obj [923.4 758.8 787.4 690.8 787.4 745.7 567.9 732.5 758.8 758.8 1033.1 758.8 758.8 622.8 293.6 513.1 293.6 622.8 787.4 293.6 619.6 585.7 597.1 631 563.1 540.5 648 619.6 303 427.5 642.2 517.9 755.2 619.6 642.4 563.1 642.4 608.3 461.5 597.1] endobj 195 0 obj [666.7 0 0 0 622.2 622.2 0 0 0 0 0 0 800 666.7 666.7 622.2 0 0 622.2 577.8] endobj 196 0 obj [737.3] endobj 197 0 obj [536 536 813.7 813.7 499.9 319.4 499.9 833.1 499.9 833.1 758.2 277.7 388.8 388.8 499.9 777.6 277.7 333.3 277.7 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 277.7 277.7 777.6 777.6 777.6 472.1 666.5 666.5 666.5 638.7 722 597.1 569.3 666.5 708.2 277.7 472.1 694.3 541.5 874.8 708.2 735.9 638.7 735.9 645.7 555.4 680.4 687.3 666.5 944.2 666.5 666.5 611 288.8 499.9 288.8 611 777.6 277.7 480.4 516.5 444.3 516.5 444.3 305.5 499.9 516.5 238.8 266.6 488.8 238.8 794.3 516.5 499.9 516.5 516.5 341.6 383.2 361 516.5 461 683.2 461 461 434.6 499.9 277.7 499.9 611 166.6 666.5 666.5 638.7 638.7 722 597.1 597.1 666.5 541.5 541.5 624.8 708.2 708.2 749.8 735.9 645.7 645.7 555.4 555.4 555.4 680.4 680.4 687.3 687.3 666.5 611 611 611 722 277.7 516.5 444.3 480.4 480.4 444.3 444.3 633.2 444.3 444.3 499.9 238.8 355.5 324.4 516.5 516.5 516.5 499.9 341.6 341.6 383.2 383.2 383.2 361 361 516.5 516.5 461 434.6 434.6 434.6 544.3 319.4 472.1 638.7 666.5 666.5 666.5 666.5 666.5 666.5 860.9 638.7 597.1 597.1 597.1 597.1 277.7 277.7 277.7 277.7 722 708.2 735.9 735.9 735.9 735.9 735.9 972 777.6 687.3 687.3 687.3 687.3 666.5 583.2 1110.8 480.4 480.4 480.4 480.4 480.4 480.4 722 444.3 444.3 444.3 444.3 444.3 238.8 238.8 238.8 294.4 499.9 516.5 499.9 499.9 499.9 499.9 499.9 777.6] endobj 198 0 obj [458.3 458.3 416.7 416.7] endobj 199 0 obj [761.6] endobj 200 0 obj [272 761.6 489.6 761.6 489.6 516.9 734 743.9 700.5 813 724.8 633.8 772.4 811.3 431.9 541.2 833 666.2 947.3 784.1 748.3 631.1 775.5 745.3 602.2 573.9 665 570.8 924.4 812.6 568.1 670.2 380.8 380.8 380.8 979.2 979.2 410.9 514] endobj 201 0 obj [680.6 680.6] endobj 202 0 obj [826.4] endobj 203 0 obj [777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 319.4 777.8 472.2 472.2 666.7 666.7 666.7 638.9 722.2 597.2 569.4 666.7 708.3 277.8 472.2 694.4 541.7 875 708.3 736.1 638.9 736.1 645.8 555.6 680.6 687.5 666.7 944.5 666.7 666.7 611.1 288.9 500 288.9 500 277.8 277.8 480.6 516.7 444.4 516.7 444.4 305.6 500 516.7 238.9 266.7 488.9 238.9 794.4 516.7 500 516.7 516.7 341.7 383.3 361.1 516.7] endobj 204 0 obj [555.4 555.4 833.1 833.1 499.9 277.7 499.9 833.1 499.9 833.1 777.6 277.7 388.8 388.8 499.9 777.6 277.7 333.3 277.7 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 277.7 277.7 777.6 777.6 777.6 472.1 777.6 749.8 708.2 722 763.7 680.4 652.6 784.5 749.8 361 513.8 777.6 624.8 916.4 749.8 777.6 680.4 777.6 735.9 555.4 722 749.8 749.8 1027.5 749.8 749.8 611 277.7 499.9 277.7 611 777.6 277.7 499.9 555.4 444.3 555.4 444.3 305.5 499.9 555.4 277.7 305.5 527.7 277.7 833.1 555.4 499.9 555.4 527.7 391.6 394.3 388.8 555.4 527.7 722 527.7 527.7 444.3 499.9 277.7 499.9 611 166.6 749.8 749.8 722 722 763.7 680.4 680.4 784.5 624.8 624.8 624.8 749.8 749.8 791.5 777.6 735.9 735.9 555.4 555.4 555.4 722 722 749.8 749.8 749.8 611 611 611 860.9 361 555.4 444.3 499.9 499.9 444.3 444.3 674.8 444.3 444.3 499.9 277.7 402.7 336 555.4 555.4 555.4 499.9 391.6 391.6 394.3 394.3 394.3 388.8 388.8 555.4 555.4 527.7 444.3 444.3 444.3 583.2 277.7 472.1 638.7 749.8 749.8 749.8 749.8 749.8 749.8 902.6 722 680.4 680.4 680.4 680.4 361 361 361 361 763.7 749.8 777.6 777.6 777.6 777.6 777.6 1013.6 777.6 749.8 749.8 749.8 749.8 749.8 624.8 1110.8 499.9 499.9 499.9 499.9 499.9 499.9 722 444.3 444.3 444.3] endobj 205 0 obj [388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8] endobj 206 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8 500 500 611.1 500 277.8 833.3] endobj 207 0 obj [569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4] endobj 208 0 obj [277.8 277.8 777.8 500 777.8 500 530.9 750 758.5 714.7 827.9 738.2 643.1 786.3 831.3 439.6 554.5 849.3 680.6 970.1 803.5 762.8 642 790.6 759.3 613.2 584.4 682.8 583.3 944.4 828.5 580.6 682.6 388.9 388.9 388.9 1000 1000 416.7 528.6 429.2 432.8 520.5 465.6 489.6 477 576.2 344.5 411.8 520.6 298.4 878 600.2 484.7 503.1 446.4 451.2 468.8 361.1 572.5 484.7 715.9 571.5 490.3] endobj 209 0 obj [708.2] endobj 210 0 obj [510.6 510.6 775.3 775.3 476.4 305.1 476.4 794 476.4 794 722.3 264.7 370.5 370.5 476.4 741.1 264.7 317.6 264.7 476.4 476.4 476.4 476.4 476.4 476.4 476.4 476.4 476.4 476.4 476.4 264.7 264.7 741.1 741.1 741.1 450 635.2 634.6 634.9 608.8 687.8 567.9 541.5 635.2 675 264 449.6 661 515 833.8 675 700.6 608.4 700.6 614.7 529.4 647.7 654.8 634.6 899.2 634.6 634.6 582.3 269.4 476.4 269.4 582.3 741.1 264.7 457.7 491.9 423.5 491.9 423.5 291.1 476.4 491.9 227.2 253.6 465.4 227.2 756.5 491.9 476.4 491.9 491.9 325.3 365.3 344.1 491.9 438.9 650.7 438.9 438.9 414.1 476.4 264.7 476.4 582.3 158.8 634.6 634.6 608.8 608.8 687.8 567.9 567.9 635.2 515 515 594.4 675 675 714.3 700.6 614.7 614.7 529.4 529.4 529.4 647.7 647.7 654.8 654.8 634.6 582.3 582.3 582.3 687.5 264 491.9 423.5 457.7 457.7 423.5 423.5 592.2 423.5 423.5 476.4 227.2 327.5 308.7 491.9 491.9 491.9 476.4 325.3 325.3 365.3 365.3 365.3 344.1 344.1 491.9 491.9 438.9 414.1 414.1 414.1 518.3 305.1 450 608.8 634.6 634.6 634.6 634.6 634.6 634.6 820.2 608.8 567.9 567.9 567.9 567.9 264 264 264 264 687.8 675 700.6 700.6 700.6 700.6 700.6 926 741.1 654.8 654.8 654.8 654.8 634.6 555.5 1058.7 457.7 457.7 457.7 457.7 457.7 457.7 688.2 423.5 423.5] endobj 211 0 obj [1339.5 1110.4 1079.4 980.3 1079.4 1063.6 810 1003 1092.3 1074.3 1456.1 1074.3 1074.3 886.4 429.1 733.6 429.1 886.4 1115.5 428.1 761.3 720.6 735.4 776.1 656.7 628.9 797.4 797.4 377.1 526.2 789.1 601.1 964 797.4 754.8 692.8 754.8 757.6 568.7 699.3] endobj 212 0 obj [1148.4 0 510.4 265.7 297.6 669.9 611.3 611.3 930.3 930.3 574.2 382.9 574.2 957 574.2 1047.2 866.5 319 446.6 446.6 574.2 893.2 319 382.8 319 574.2 574.2 574.2 574.2 574.2 574.2 574.2 574.2 574.2 574.2 574.2 319 319 893.2 893.2 893.2 542.3 765.6 766.6 766.1 733.7 829.9 670.3 638.4 765.6 830.5 333 542.8 798.5 606.5 1021.9 830.5 829.3 734.2 829.3 734.2 638 765.5 798.6 766.6 1085.6 766.6 766.6 701.8 354.5 574.2 354.5 701.8 893.2 319 547.5 584.7 510.4 584.7 530 350.9 574.2 584.7 265.7 297.6 552.8 265.7 903.7 584.7 574.2 584.7 584.7 388 440.2 418.3 584.7 520.9 776.1 520.9 520.9 497.1 574.2 319 574.2 701.8 191.4 766.6 766.6 733.7 733.7 829.9 670.3 670.3 765.6 606.5 606.5 702.2 830.5 830.5 861.8 829.3 734.2 734.2 638 638 638 765.5 765.5 798.6 798.6 766.6 701.8 701.8 701.8 843.4 333 584.7 549.6 547.5 547.5 510.4 510.4 757.4 530 530 574.2 265.7 438.4 397 584.7 584.7 584.7 574.2 388 388 440.2 440.2 440.2 418.3 418.3 584.7 584.7 520.9 497.1 497.1 497.1 616.6 382.9 542.3 733.7 766.6 766.6 766.6 766.6 766.6 766.6 989.4 733.7 670.3 670.3 670.3 670.3 333 333 333 333 829.9 830.5 829.3 829.3 829.3 829.3 829.3 1117 893.2 798.6 798.6 798.6 798.6 766.6 670.4 1276 547.5 547.5 547.5 547.5 547.5 547.5 829.4 510.4 530 530] endobj 213 0 obj [496.8 993.6 0 441.6 234.6 262.2 579.6 531.3 531.3 807.3 807.3 496.8 315.2 496.8 828 496.8 828 752.1 276 386.4 386.4 496.8 772.8 276 331.2 276 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 496.8 276 276 772.8 772.8 772.8 469.2 662.4 658.8 660.6 634.8 715.8 593.8 566.2 662.4 697.9 272.4 467.4 686.4 538.6 863.5 697.9 733.7 633 733.7 641 552 678.5 678.4 658.8 934.8 658.8 658.8 607.2 287.9 496.8 287.9 607.2 772.8 276 476.1 510.6 441.6 510.6 441.6 303.6 496.8 510.6 234.6 262.2 483 234.6 786.6 510.6 496.8 510.6 510.6 338.1 380.9 358.8 510.6 455.4 676.2 455.4 455.4 431.3 496.8 276 496.8 607.2 165.6 658.8 658.8 634.8 634.8 715.8 593.8 593.8 662.4 538.6 538.6 621.4 697.9 697.9 743.4 733.7 641 641 552 552 552 678.5 678.5 678.4 678.4 658.8 607.2 607.2 607.2 714 272.4 510.6 441.6 476.1 476.1 441.6 441.6 627.8 441.6 441.6 496.8 234.6 351.8 319.5 510.6 510.6 510.6 496.8 338.1 338.1 380.9 380.9 380.9 358.8 358.8 510.6 510.6 455.4 431.3 431.3 431.3 538.2 315.2 469.2 634.8 658.8 658.8 658.8 658.8 658.8 658.8 853.8 634.8 593.8 593.8 593.8 593.8 272.4 272.4 272.4 272.4 715.8 697.9 733.7 733.7 733.7 733.7 733.7 964.2 772.8 678.4 678.4 678.4 678.4 658.8 577.8 1104 476.1 476.1 476.1 476.1 476.1 476.1 717.6 441.6 441.6 441.6 441.6] endobj 214 0 obj [903.2 741.7 769.8 675 769.8 728.8 554.5 716 741.7 741.7 1010.9 741.7 741.7 608.3 285.3 500.6 285.3 608.3 769.8 285.3 625.7 591.5 603.2 637.3 568.6 545.7 654.6 625.7 305 431.2 648.6 522.8 763.1 625.7 649 568.6 649 614.4 465.7 603.2] endobj 215 0 obj [503 503 764.2 764.2 470.1 299.7 470.1 783.5 470.1 783.5 712 261.2 365.6 365.6 470.1 731.2 261.2 313.4 261.2 470.1 470.1 470.1 470.1 470.1 470.1 470.1 470.1 470.1 470.1 470.1 261.2 261.2 731.2 731.2 731.2 444 626.8 624.4 625.6 600.7 677.8 560.9 534.8 626.8 662.9 258.7 442.8 650.5 508.7 819.6 662.9 692.7 599.5 692.7 606.3 522.3 640.4 643.7 624.4 885.5 624.4 624.4 574.5 264.8 470.1 264.8 574.5 731.2 261.2 450.8 483.7 417.9 483.7 417.9 287.3 470.1 483.7 222.6 248.7 457.6 222.6 744.9 483.7 470.1 483.7 483.7 320.2 360.4 339.5 483.7 431.5] endobj 216 0 obj << /Length1 830 /Length2 1384 /Length3 0 /Length 1943 /Filter /FlateDecode >> stream xڭR{Ȣ4!Nnق=vζ;]T]b/׸|8ʼn1; Cor8TZ{ĕ)  _؈#@asK*-D e/dyac6V6lll`~!;f  oLZG,=qj$^A)L!>(20.HJO&]m.z9 CRC[?pD}`>&DvPN-7kLܨܝ1S=fP.67'^ۧއwL3o# ١IDQtIQ{\tP"Z\q>/ۚ jovh^BiCZxN-#AkPP ]8$,\/hIs5ѵw 0f[5w*+yiI$Xc7RW}G.ԯW:z񚵝 U$WΧCN^dIH-ŧ9$7UXΉATRܒ(\}OJf@rT=mP\" J ZG4<1*+pv8V}Ewe ud7;k Ut;qyNRq)I.TVɘAJݣ=uRuUczRmb`m)y]UIñԚ: k9 ;Ri;Z<;"VeSƥ@sG4=Ί^Ȅ(hc6[- jŘ; Jez ^&NL(Glo)v]b3>-zvw|pu(֗@.ׯ4ܿ:1Pz[wW8Thu)WbWkNPt5Yn=8A5e7TMskn>7qasc?aڧZsܡxcQ}{nYv]ASR#Ӥ;ޓ0~{*&?6\`jRpH/6-w˧wx=k{ʛqGs6;eDR1.Vv}m)SydbO6vAi0e aYTχ\QMAŌ(62Gn<)J]XT &_96}U_jW4|J<- URYӚ1iC&ތ:$iKEЅLceW֫Ep$]%>=LyVYg!~֝. R#{Z6:1s1xמWsrDNyOօMp1;TV3D8NcEr? ȭ+;@ sj^PJyz`wb;m{O]R|cʈϣv}7,[x|h+웋raDL3zn":Fjx%$ e=ȑ!yľ E=ybpm'ԭ>ܱ4ķz> endobj 218 0 obj << /Length1 918 /Length2 3160 /Length3 0 /Length 3767 /Filter /FlateDecode >> stream xڭi<ǭٞd-%1]}͞m,cYٗdIvqPiSɞ03={.!%2\0@ #MPPkiVax4T4x!1)FPycA!$("`f 4 88BS x{F(p 8"/&K"heƄ ɡLQ S$D 兞$1L-Y7 OQ!8[$ug bpa߽6$A@ Sˎ 5QA=(|(1+a)g#Ri ?9$2 x”a083)MBM@(/󈘤DRT U&(9hK"~߫&5nA?\Rh¼(dLgR0H$ COD0SA8j̿jj D 㢙;8A yGH-u1Ϯp*J&>LQxBԉC֧Π'$@\EF(k1t& =P^ĵ~f^>¥s/d>Owr6,5*9FGvVcb|12y.䁧Ng?`N$WA}6.3j]j^EZ3^&gMֱ)܃j'ߞ:VUG]8*ë736%lz:?f7q}\ n?ea1t=W@ϒ'C_ s87RZdmʵQWޞWB%ń9$G|Nf l|feRγg7[DiOsxԑr 1J|2:l/y&/7-QV(A+E{GmbtuhicW[lajNFȳm2l-lwso:@Bݕ0?k^c9EWnZd8;zZ8|}"exr 72X.}Ľ=]IIٚ#]x]^o5~=պwYk9> kOТ'V$ww=^ѣxz\$'lrҼ}Jy;_=Dɯiǜ srL&8mUo9s\ \|p!zL![^ ߐPϒ kLZxІrOyY}W"|5-Y-r+j3'pA `F/UCϩ`vQ gpdž6҄ԭΣE団eX܆haN&\Uc Q8ޠy`zn/"TΥYM;sbZ5ԽH෱~=;[3xT734ųG6<#gDw$ܼq߆s<QLA{]G6Q"܇},s#7r(#)osWωrj)}tASWlKg|KঔO%pnλHNke&tB;!טy퟾8dW$j'}\JY]%BjHb"*0tFYtKLei,>dWae?RO~{TyMH0>͡H|Ft0^UZfTR?Lx|!VH>ƶ5}z~wЙ+x4D|5w"KOۓv k݌ lttRD6D}TB͠U QH,nzikQֵp:2^?i9gyq(دy"' OSxQOvWߠ~Xwz Ev"pwb9z~[EI̫u%O?9%`w}Yb6#Gm㶁YnfĻRܒ*X5z' ̠=$W`S;:pډ7j$vC#B2 fp>bu>ZL-[Ґ+0qt:(/Aљ妒l %&R^PV\Zg vqN GғQE"Ę4+YTkͣ6,18qc:Joﺟl).\]m^oP~A-_/"P;f?A ަ: ]]ql+EQMasr/d>mh1_o, endstream endobj 219 0 obj << /Type /FontDescriptor /FontName /RJYVUT+CMMI10 /Flags 4 /FontBBox [-32 -250 1048 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 72 /XHeight 431 /CharSet (/D/T/a/comma/d/i/l/period/s/w/x/y) /FontFile 218 0 R >> endobj 220 0 obj << /Length1 766 /Length2 1623 /Length3 0 /Length 2160 /Filter /FlateDecode >> stream xڭ{<s1rj۩)0qkɠr3/2{ 42%{EF$T.D#B Q?*O-%1ZirE/Lzta->FADd\ESPS7\,l~H؆)J{_v_tdHi}R?.ƷԨ5$D{c( Ro_pme]auuNοhDik,N^tEZаyC6r?#Qhn䲙:?QKs_WfuG/i4?3u4x45_#,:/Cv /1}#")ݱ-i.  W(ox{ʥ3Sf%b^a+4loHJL$S9NnSnlrHt }Fx2B>Ow>KSUvsfyAvѽ3Gʃ|L T@՗P#n_cJdoU_9u_\dm7mޯ'R\%V?ݡ!E/\؞WOw}ݱ W48 x=3r%*j;],v$ӄvJVi(3':<u;/߬(Z-4< ʯ6Q/kzI& Mӊ'u^!~5,7q[\V7‹3 b endstream endobj 221 0 obj << /Type /FontDescriptor /FontName /BRKLDF+CMMI12 /Flags 4 /FontBBox [-30 -250 1026 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 65 /XHeight 431 /CharSet (/a/comma) /FontFile 220 0 R >> endobj 222 0 obj << /Length1 744 /Length2 1168 /Length3 0 /Length 1696 /Filter /FlateDecode >> stream xڭkTSWPZ!)!B`A";1䜬0D"hBP*Z{4Dk\*4 25s~8caJ($`Y4`X8'1J J $E<<C48'db$!Q\s"`qQJ @$CDF DH0S!PIv89$6?En (2IH> dqa4h``-4J¸92 L(J@1`c|(FJoؐNY1n/mIBA$D$>D I sGa(gmHHV2L*nYPGA\+Ñ VT*HC)R; $-nqsJЁιdb42p,)4 QɻGK!*I 9CtJ!b<߬$ecvuƺ3bCɉ-Ε: }Iɥ7ԺV42үEm}ʖx4 o,vIJӺDXHW'w ؊շ3;tY TBᡂ^=*0.ToFugǀU =O^t+>|! CN~?\uJZj^oª-ƭԺi {u"aHabG5 MN%?HMQi4cJ1[o͖UgԝFU>77^<ݺ#a^ <,|0)S.RxdjH*sՈʯhWr_XRYd\n5<-_/4Rp6/b[NUȘ變cts.-=k"86rk*4]bc~>TWS~4PdxMs̚E.{SgX-5;1̫Ƴl/ A%}*z~z5c(Xq蠣iݏ_[_ojc@,/~(m٣i#!Mi7aoC+]QOl :ݙ|n2ea'٧硪 OǴ[]f^6wyk}2-3^(e*ߝqGmwێ)[gr(Pަ%SZ^q@WKcہ#]'= ȗ+s:dZ +vZƣ{G;|6gSf}vYzmqWa擣K9Q6ق.Y1"[!H=3^1|5*i|]g,Z 7OuF+VZyg~Ӕj2zpyG 4j[kMY=}JyȪxfWaӰNCړ59m~`I+G&'G3#-xL,_~ihO#)2nq:-5{6yˣtG7|jqvu\RpL~w.<|Y0р;؉9K|'$_}wYFΆjLiz͏V޾W];4> endstream endobj 223 0 obj << /Type /FontDescriptor /FontName /VNHVYB+CMMI7 /Flags 4 /FontBBox [0 -250 1171 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 81 /XHeight 431 /CharSet (/w) /FontFile 222 0 R >> endobj 224 0 obj << /Length1 941 /Length2 3195 /Length3 0 /Length 3824 /Filter /FlateDecode >> stream xڭRy|{_u_-)jk`_M8L Ô!TR҈z0x' `ZZ*)xvjT> !F2?H?H'A&hiA@Ll=18Ѐ acZwY^H{>. 5u@ Ҷ0C!B3Óh%'/<c0@ $ӆ@"j& <po)-@ ߱2IqXЋi`%"H>IRH( ! *4ڇee-@K]a5MM C?(u:7nBuIӛCt릇YcAVsvoe_d\</DL鈰2];~䱘&tsзb[w6W 6,J_brUq4HoRsV'J `Mdi{ sy*/YJUY"'Gw3=Xd|﷈M/ 4q7lt.hU7Iu׹wU9w2˩r嵌R|Փ;,amVQW#82I%W\dE9=/xc,DDB\ B1󜻾26Y9=:)|fVT8AI$ôP.Npsϝ?)=˅g@͝W5yyrVHܰ~ *HT]cb6ac Zl#/Qӡw?U'Fvڐ4ԯ^ʴKȨ0(tZTjr5l~G=iV? 䮔BZ|8r5^^gⱰ{LfPټ#{KOm֗m}(\o̶H̼"y7^e"'jD^yt?1.b!TƾGyP R(t,5l;Q>_m#/2~~݆zčȳHjhvTGRayqPa:q^]ϭIvwʍ_Xgs-e<7q3!Vۚ -pW<+ȗ+7=]T+-ϯfyBGyͼ 8Z2@z)b TsUQϋ{(h|gO>,&[?D|طAi֎ ףt籜qkJ5PmnӈT#=@N닥6jԛֿY67$)B>{5: %ȤIS{rBxjjqzMibuN`Z7Ա7&{9M>\܏ bsBx]uX =7ZkV5ı;\3qciQfqk|,~#+=_hsԎ3D>r+H!/Gq(I!5pZRl&;;y5jAh4Nؾ`IIHDW?RU:${UjOY}V?ʎf7\}ק-zpcڗ*AFSi0CXYz]PNjF"f )= O? - oFd_YX;t*1!RÊu*m qtnF 9֛{br zA j6 /ӸǕ󦟘PEz+!c }]Y)󢋃Rqգ%X̕A7n]=-Ѻ{ǂh6!%N]!Rt6Oڵ%F?Kv||F E\Ȩ6;s,-Bv%ӷKzڳ~_gf}=U'A,C1'Qa3Bp!Qz'AEo*#Ԭ*/nT0ϝzLRק'ѽ_u.l4GP'Q'mL0Qv _\tOP=SvfyH W:WL /"jNT0Y~кB1f4.{|14a2ЏWf8yH׽:1Gpumr8p8qL 63E(fۇ䴃&.3 퍺_lsmUscs=rO>>_R,"Q[`u_j,Ko4=RӁ(Z9^~w[q[Ұ!C'^3Hu{$ 9%6]&-s2jYOy};žPZiZQdYIk=FNsqɲK|BU Ѻ+p:N>7)EЊJ).D rZj٘nyw>d}j fzdŞ/e7 mo[%U(ܱ_ xwጨ ~TRȖ}]Grnu'>s~cٜ.]fǍ<~ N{«NBKA(9U3wזpQE|`ˠv^}w몯(\U5*7u{klzLj[ \*م۞WpI![}:% vrzUf>gnr0E_WWX@^4G]md0tݡGEfjnX4iK\m~Б̦[Fټ=k뱂3Q$FT=;pNη*ǚ)=;!L\İҸW!?eA4eZTp~]?Hے1'Qy`j8PqưuXM,όM]C5/-.օ'ޔlKbr`)M3uۂꨲ6*JpBM%T}2N Oxjf?X˒vmu6Αz'zN(nctJJvI=B=[&'h*ޏ<&'X}M endstream endobj 225 0 obj << /Type /FontDescriptor /FontName /OZGAFA+CMR10 /Flags 4 /FontBBox [-251 -250 1009 969] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/equal/five/four/nine/one/parenleft/parenright/plus/six/three/two/zero) /FontFile 224 0 R >> endobj 226 0 obj << /Length1 739 /Length2 1045 /Length3 0 /Length 1562 /Filter /FlateDecode >> stream xڭ{8TyǗbn4c !M.Rq93sj173:5ZPZ %V&Fm[ZZєUs}_3/ٙAqLL(plD\,Fql,Fg PdDspڑ̀+. QW ,\-'DtG(ƀ,"|_"b98xg "D(EX=H@4K"X"B,HK@ p',MƉ]y&}R(O $bDp"ĦKw Sl^ W=0e:cS)T3 DdX!&mdO.x2 w S)T*D߮iwaLbBX($b3@d5@xظ41N{X#abD3\\p~2m vԨēBx1fs"CvޓG \¹}9:NhaI̅{f, _":^M@X}4'3bIp7P֑;o?]&KKkT<ős2;\/5C{:WWI tSy}6]؝{v> o]6>Ve.^B>,9,d$ ~sqGFUQ߸{prGEz*](jkUE뿺(|$K7hߕϷ2^خ7{(_l{6mi7ablwg4I8 ΍ؔ{:ֳ8gX+%RNiALϻ>Zu> endobj 228 0 obj << /Length1 756 /Length2 1214 /Length3 0 /Length 1749 /Filter /FlateDecode >> stream xڭRyXSW"*HR $`i B a %<= aP)-|~*&tYtuM u2Hy`;{;{޹%E@ Y' V$b` uf {@ѬkOړ %H0=b!t$9lxEq`H$t1@XkE @ćQq#À1W1x(` !H^~gj#[a-<& !ĸ* G󄸰XuCGHGp `'H 9Pxq,?ݤaT'vnp<!q!|Xr 0T[  RA"(P[j+;]\biתf}g˿TQ++S Owܤ7t\񌝳hl2xgl{BV|kqÔki gcϻ啇՚(wwmL=ѺPu}f:eScBX #7ݤ&F#l#-Vu +;{R3{̪ں/bfu>{][#lciԥ'هf[G~{[GMrF7g^{cg$mup3J ԅ1)tĤ|n_}$㷖wV_kXq-."Œ?vLe>OZf<^o(b!d+G;RQ+x)Z==PyoRg!)S?ؚl`g)u[>>yo.wҪZP (^Jx~8͒ma8aU5s8K%'0n︻*8M>k&ը,N7֨/G,eٹĺo3M`mۅv>Z=4X؈S3rpkUvVçJ:q.xS*D:Q͗F@U G+ѦϺ3.|q'~?VN=ݾ{:R)w#W'y6}~Z`0ásv0njėӆҤ(Mյ2]>)_H K E/5+~;;3iO[zE. }C%@0c\c0gR}U)#̻P&YGમdPS⥜9ϑM?^[{2) 5qI@WŒe' 5 |i/}Vxr{w ^e2nS@A}4^?ߢpʌ4׀bWuhm˧,cZ qM endstream endobj 229 0 obj << /Type /FontDescriptor /FontName /RHUHOI+CMR5 /Flags 4 /FontBBox [-341 -250 1304 965] /Ascent 694 /CapHeight 680 /Descent -194 /ItalicAngle 0 /StemV 89 /XHeight 431 /CharSet (/one/two) /FontFile 228 0 R >> endobj 230 0 obj << /Length1 803 /Length2 1807 /Length3 0 /Length 2364 /Filter /FlateDecode >> stream xڭRkYTcUpfIrЕUK2:wm~T1[*\0!5U-HCS7m|XjDpU5i=YIчWIJ2< Nk<㨻--D'`3*+QH$*#mHobLpL)<[ >󱶳>+ԋiI觶eߜ))>" ͇[e}ߝ9l{Πű+k|O/FJ0!'Cm#{jM J:cTqne+),|ˬ+FP$VlmZu:^+y9 _#IH\Qpǔw c(Zv,FEW,s4)&v6JQͬՀe&s_\6$q1ؔcFmGe2uOƂשM%C5-*ezs'ׅ۫r|jyw)[*6бTan=#[*+]Um5;T]1 yNRoƩODk!{6XD0un4^p0shX*'@6 (/-4 2y_dΟt#9:?{V[\䟒&>vKeua=zX܎2IX6"f(Cmڼon =ߦ1$r6 XpWvѻKή5]:7(SKИxϿI\òGVG^EQ-tsCM֢ry Ks/)ceypj|=s*Sauve+ Ky<!GLAYFӒz',_vv W4agU U'N)%Ll6Rۥ-~;|2 Dh6Dڴ(&U*L$s Su/?u{A+9L;d{[(2FB4 ]u1n8?Z8lZg|~/cI+FeW9Ӟ{{ؙ)Ɯ!/* pHj[ |wk ߝCu<)诤-H"V}LDZCr~o1}u}Wdv}L>;x\5&=6W $VfUTiҰB?]3XK\ʩl醔dѹY;‰϶ykn>8hkb^nk,ܫG(T!=p]']fȌz)L@pdbbdzSWm& I)ԿH endstream endobj 231 0 obj << /Type /FontDescriptor /FontName /WYSOUE+CMR7 /Flags 4 /FontBBox [-27 -250 1122 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 79 /XHeight 431 /CharSet (/five/nine/one/three/two) /FontFile 230 0 R >> endobj 232 0 obj << /Length1 1102 /Length2 3693 /Length3 0 /Length 4383 /Filter /FlateDecode >> stream xڭSy<}Fv"dWMfh;%wdc0ƌȾ";gN%険~}?:uιhhVv98, TLL8* qX5%ADgKHKH Tq~x TQx4!.(wR $0!(@Pxo= pD# 3KH v$zMy^$S $@b('z> EraD F)pGc{ (<@c-5GeN&" 0h2B{Ѿ(GC4pB`P(MDCK\CE"X?eaoL !.&.% IlL9 x=6HH (_ʗ"H)PN8<υH Z?C!YDD8zCo q- qB{$ !i`o9 E d$^T JD(o Ir/~'yR<|p$,"{QQ0THNN #%tH"~IG7vBNE!'qHp״`‘*rD ao1E}:"UJ3٘.z6 7C=ߜ,y/e?vl]9[ݟ j4.]"+\Z1h|&ݳ8Z2jLJ2pXkm6};,桵鱕6Y³dXcɝj$REJb<{nՃ|Pu" ;oZ O2_G""9$" GTf3eJ,W_>Xםav쮸DeySAc8aŐq3e1ךj٢_jK.g@+芳#<2ucSiM5M f>3i`sqΏ4n^wiTsg5Ǡ!caǒJ=FKgwC['y v` Pv 7i=2j[@ܑ^" :# ;Q;t/m\v޼dtV\,<^wxxu ƺ穔2no/}Hzͧ9-cN*pKK<}:!mF=hф(XGH6c#[1mZ|z)hMf٪w3TRP0ޚtVB@#,?:೺.vETGT:гvsd&Le_~j2V,ЯYKdZa ㊆ZaǿM>UqQ.Ĺ^#OR[EVaGmuڑoy ' ˣpz7LSg0"̻'Ef#/LQv:gUroLtEek,.$ ?T^@=~5}[:4u.>\39SW"}VIloNdJsOf>nEmg;ڮ_VCz{*WusLC@ܙޒɬ& Zlՙa)Ƴ>C8"!IMQTJ|4iBΑ*b{dRK++CCi6̵ ZMd7iD9&t.vǼzsbK0]qDnZu0daKup.jҠ묖&-&tD( RD} "9rD!]wb^Gu>s|dH2QȪyg;3G흟HY`_4]Bf̖Zޝ*;{\Z|nfZMT5͏CӘgR|HR}8/K0cQ'Ȏû l_ ޲RJd 3]5[m\,DY/qqG,oŁΟ/p91c2Ɯj%)wg3x(ϯ2@޼}JӀǔ\i%"/6iniOdؤErMU9 h?6KoQ7=30S I] E\p:d(.HEĤկ|6m{ emq9ioe\)DCӥ)dz6CւtDjgt>h𶸀G T֭P!+ӣoߕCi&aT)a/ <ŖpWҍ ϳ}\=>,e\y{Zx Rhna*&d ;X! y$ xݛLJ/o*җhph9eWo4459KW#AJNWȔ8`',DE\ɩWTo4C2~sr ʗ^ TVyŝOQAB *, l: [gv@\_<EUԂb}MUXv endstream endobj 233 0 obj << /Type /FontDescriptor /FontName /GILZWG+CMSS10 /Flags 4 /FontBBox [-61 -250 999 759] /Ascent 694 /CapHeight 694 /Descent -194 /ItalicAngle 0 /StemV 78 /XHeight 444 /CharSet (/I/N/a/b/e/eight/f/five/four/m/n/nine/o/one/plus/r/s/seven/six/t/three/two/u/zero) /FontFile 232 0 R >> endobj 234 0 obj << /Length1 833 /Length2 1182 /Length3 0 /Length 1761 /Filter /FlateDecode >> stream xڭkXg*H(Ii@@ERi20d$DKՂveAU+SvE]A."WE.iگ̗9vLpD hb%0,"5p*tA 9D("t (@<*¤"QTQަPBNB'. )0셒$)0XX~iJLՁKdJJPA h \(`J,\HwȋdI` L"BX.y# {]JFTZ;R ) 2L&DfR`R`y `5|Ad$fХ<B,Ei)OL`R7铡<&Pa] 0YZdwpx lց1 JKϏl6bVPT (^\#;FtWcRObxHQ>^:Tdrd |S1_wyمJiJy(chOYt36*FFwbxKQ lݟ Pܶ}^w͂{C",Aٴ.x/Lr1mglj6d:L_UfS' -5ٔp#JzgS!F~Zv懞 ͮa/Y(B5QC3/+EP?ܟ]QO.ɸ2ϗd{*k &xv?L譲S~-E66>ȹ. KÏid]} =)/Wh]Nn CrdLG&!Sݼ~ooO?鷘Ӛ2Ul+ޙ:%x,'q^>Br3ךB=VB朼Y C2})5qՖ33 fج4w2ےKQŲƜ|>w忴?լX9}8vo-?DќefyO]7Z|w&2c_,z͂5Mi5F]Z~ 2cIgB om˾WJm/ T-lUihTt?z7>xQ\Gf,$)]JOWb,]G7uA2d*^+*<2>1W,̴EymD] lt&k:aD s][rqWu[[Nz$4}`0.ůe}N:/cwr:8V0ְ!6#J̀jdˋ!m&)ݭY dW̺[uCmjb|h!|G| ˊy:ohtIUFP۶xQ;+PyF4~YcvP% yba7][ݳhEVZCd]z-5+] $hPNj endstream endobj 235 0 obj << /Type /FontDescriptor /FontName /MSAIWH+CMSY10 /Flags 4 /FontBBox [-29 -960 1116 775] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 85 /XHeight 431 /CharSet (/O/braceright/minus/perpendicular/radical) /FontFile 234 0 R >> endobj 236 0 obj << /Length1 759 /Length2 1144 /Length3 0 /Length 1675 /Filter /FlateDecode >> stream xڭ}8TilmRa5)Rcfg36TZEk1>b%)$VI|DR*_jZ9yy~_ 0Tf @NdCHd ddL[,=hNt[% &Q0D(.&,qC' >O|1>6Y$>+x$,!A |JN2pxWDH>"a\J@ *RLzbn0`M!yē㧒#"{&D`p0ӭ\ ]wOQw%Da7"OaT0HnN5y*SH:пG F F8m36* {qD\B1@P,ڠXLb@0&OT '#F86UX,L5X1i8+CDA#D0,V2.;ٙMyZ,a%շ.*$i]nyܦs{zE&=PcMgÿ?qMo޴KmzQ's:hT Mйh?sm#Y{lY5NH^رU8]Q}JJ/T&m^i-/V+4ZƻfY\wcE)jwbpä3*ls/צ{ VJD5^ߠ4)տot S V=EA W\זyT}3'I:o /H~OaLU3N/c8? 7MɚXoTũ_d--]gAkC qJ`#|ݹXr޶ZgKCErEi%]Ī6s^!lYݓ56Kr\3{i?XRsĵoK̪. SH=BH݃ԙ2 Keu_Cqn A5܇M>=foߚk8RNR)6*o|Sg4> endobj 238 0 obj << /Length1 819 /Length2 2031 /Length3 0 /Length 2619 /Filter /FlateDecode >> stream x}Ry` Ă`L$pF| $5X&=X,@,0试T)s ɯWiN ( vY-ᣡ ϟ5gla1~ vts X0I #|φM9ק/BŽEAds 0!iGE$\S@ 0j( |9C#t\A b~WSooZh _\#d@b0HH ֡᷍,(Pa :2 CCMdЎߐ.> h59Iz[0b@!X|!baX ؈l%ۿ1C@2UL6 Hκ)sgn]]npvʩu' v+-7NEVޤ۟!sv9a"}"%k\%n7hpm@xizwoqwgj=^L_gCh3CKa53(9n5ڭqT+Lg^oH*] )tXr%7T̖fGa~Xft1^:mϔWB~n+aϽA,=1.l]⑭4Qvث*șQV8JRir[xrok ü'>f-*Oc,ZÁT!oGr+#JGXY9uO&&N{n(Ǹ;N<zf+rn=W >~h׽rDaGX)&iء:CیeZes^>X{spm|HߋV Fg^3oI4iV%/m_;F/\AhG8Ud]!P =rњb]K#*{Vj)}OҺñe~HHXEkn@@dT}6fҲb>ߧʮN'|@.v s9׫%jv RPn:;/htr4Wk_n[|xT]2 UcSAo2I_´ʂohDK4O%9?fԍy[k k^#$RMAK^n},KO08آҧݐ2-*hE?Ѣ2ޫ6Ԟצ{q~bXW8]_I)ّܱܺw.N3Q9 &5tʹ:^Y~Dxoeߺ\0J,kOFC7>y`4U*+ Omvyb<{D:~["WͫO,i1e~h!<.Ih2]`4κ{!Uss2uFH 1yews*fy "&4s3$lEʚڑO3#n R Ry^-Ȼ2f],xLo?ژUUQqޕp[`_Q>_}C6 U!i5?qϡ+sTup<>OW SmAEVODԋLyvM&5Ƅ9F)Y5I.rO;eV{}Z${{e{cK1$b`ȩ?t Im+srEzↄ$'a֌\u<4@8(PQ /+~B:'7Xers|EEG~l}whh}AvQ$\|[m;]߆;uw7OP#}ULZWӈf?#N:5L|vd'_ijUGSjV#fqijF-ڲyU=xt?2 5tPkEB;n=ue J8Qs94JΈ)`L'QAv1>['*5%}9BE#M:`GD`$ۋFPٷֻiыHCh Ij!1dw͆~ \~[q~(B1F,/C e;3Z#I.mpTjEo>&qP8#f0',8Wg}xS{6?H endstream endobj 239 0 obj << /Type /FontDescriptor /FontName /BVMPBE+LOGO10 /Flags 4 /FontBBox [0 -11 722 611] /Ascent 0 /CapHeight 0 /Descent 0 /ItalicAngle 0 /StemV 66 /XHeight 0 /CharSet (/A/E/M/O/P/S/T) /FontFile 238 0 R >> endobj 240 0 obj << /Length1 722 /Length2 1780 /Length3 0 /Length 2352 /Filter /FlateDecode >> stream xmRy8(ZDYO h0532fH] ]K`"k\E us=dPH"[u?*Hą0)E"p8J# Ix&h 8$ / LaD58EÓTp AT"0>Ă1XG`!,L Pi p k{' < 4*@S =| @[O"D'Qp  pH{`!<mtf$?h_WG0 }}D%2H%~@u Y4i$G͢ XLA$A5vXx@5\;Deσ_%AtZ?+G-ԳrCj2ZيNHT:2 /`SOGvx&x?#8!!`rp% \^p|I o:!Yoʟ m-p\`ᖈ.Z~;ݺL/:׎ʴ^![;{g%[Sgc\6~>^=>RhCG>b|3#7Bxڿ6.t;d8"VKTWSľdb`a'忘xL5dS,n ,vt29iG"Wm9}]ʜ{,Sä== XHkr8vr/BC@RɆw''KrH~áU1n%dQ,+}W Ucj`*.|z3geuŤO=IOs}~S0R}u])ۧFߣ7gU%DBoIORVzre㶩.@ѱ،Nb~I ВCRÂ[ er${)y /b $J#Lwɨe;FA&4N/p];[u2xore ㎾]\!9 fe]Օ3 lْᳳnq`ML{`/@m3SD.镁Uwo6#26fr;hXRaO`>CFjC3F"Vm~"`1| ͻ>Dei~?mk*PAq>tBݿfyKcJO5cT)R&վG[L޶S aH'Uvz@hz+Bgϋ m=7NMݬSX3\rhǾ* Җ|!fSx'+Bbߪ9=A.s*iרzfq!@믁v}C5B'pan/53qQ1WS?߯T"sj :f/:"Е,䜹q\#[N4*(0j endstream endobj 241 0 obj << /Type /FontDescriptor /FontName /ERMCYJ+SFCC1000 /Flags 4 /FontBBox [1 -250 1495 937] /Ascent 507 /CapHeight 689 /Descent 0 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/M/l/o/p/s/t) /FontFile 240 0 R >> endobj 242 0 obj << /Length1 722 /Length2 8918 /Length3 0 /Length 9507 /Filter /FlateDecode >> stream xmweP\ݶ-Np{ww \qwwOx9߹ܺU֟5kԮɥ.@vfv6;?7Z4u;H:@ `ccGH=!֖V.:sm;S k{k@lv69@\?m.V@PQՓS(kd@@hmtp@``a/L,ppB\A%)M1ieM(Yo5_1Lkoo`am0ZZ; -9ﰅRa8E=[jgljI]]qH::N?=v߮s1˅_vZZdj:ߍSުF]ꟁzJҌ?i)s%@/bSUM+@=l,ۿ,{xs9\~.6:E$ h6 Ik *glWn_A ^K+m1pLrVH\؞@v1;}[5bz2/U2udfW%?pPLK^," R^*}zv+_8|FHIkS4N- ^D9 ~F ߗ0j|o陆k%`D!DJ~[ݔ0t)bl-Ьo&.I?ZzSZ#x,h9b\-ΑAJ,܋]ynx|;<4,JJgLJ/}zܣ_eW~±$눦V ^zͤ _Z@O\cd6B8\/A_nI 4EsE&lw ]w)`k;QDGa/҄يn9fKm#tJqHP6\4+{UuBvb} S15r6XXs¨HÃ?K]X,!Ljd|q2W-ެ`Kxvv Ě؎sG@ܰ0(5A) c>}Osɘ'*>ʀjʩG-zp͏ }3&$yUKrT7N~5"Tdϸ6)s3_ʎ݅_Vunuk *q?&UE tk0Zf2LBҍ~_?fw)貽p2`BύJJj {ݬ ۖBbI=">o]VmzC1"&+;x4iOW|_[T^c̄#93Y h!>\e;U@*0R4w+ 9Ql`>hlJiܗ ^_$3ۻ=2A81Vg56jC{%fg:$lX/Wm6Fx4oE5#baAƠ σlvb>+H FxCodBjY^.4\i\qKtz3.'[-le 7 J%3@\\*͏XJT}AݾX]$(6prKɢʠwЬm+s|ň}WO2KDe=%'XI2`0yMBMh, o]]Z"MLE#CKIDwE5!ry5d &rH8+Fɼvyep[<(=nX=IǑQDK .vP=н1\9A:љ8:۰G&9_ۏo,5jqT}j}ZfbPگ7}2dm{m [9քLIʡS(-L] 2^sg8,kAk fZkv"']wٕ=B{_m;giU )7MM@ŋ 5mbMC 3Z1zX ڒ eRFĒUbհ*2!ʚ{k4˥o;S^> 2#j7mH$2jV Q7{ԫ` WgR] '^ |qf1|4Jُ+y]SD㽐Ĵ6ZRo%% euؾst~T]5 %4웆B ,?G؃F_Zv .ffijtsZlg$hp,ͅ+{!0Cy”ɫ\N߫ohD|lo-DE˳v15?~Z6 ~ nr]aZ)IdDM~tc_W*.̷*$z~784xZ.H@o0nI8xKW|oX.1SMJ]"w[2^ =M?[Q25 {+>(7=ϸH$MlQ +XB(z/B ORJ{{׸)iqך4 ?rY\s'Zg IVj:5#‹n}+ż?Nor?E=gOՏQHkmy'$,}}AD;dZ}*R0QL]F[ 4H8L( ;R̤Z mZx|6+ Ph&Nbk)wѡ=s92z,09HڃJE8=ym^P^v!1W%cNk@μ7zf_]9* kP\è32uy_DNwiZy[ǿw8)ޚ L$TsAu@9wvG`rg/,E|t%Eq3 %‹[6G9] s-?UuŁȘ͚{f[<`\uM)?@~)b1Ϩh}\"ó]Xf_RY"ayj 8'hwC{drI͉`9w"X G'c4An"D&ڕ&%2#\qԤ8pIP ]ڰ̰5Uq*)41aLCSj/6jpk! d7J:OR1ZSEe@]#;&jDb|PҦ`q $o]FOx4F8)J(y õpQE&lDѥӏ'OI'x:Vgi.֣#fg.\b_qw3wp?H]9S!G}<_^ on{>/#@49+:US1Y?P*m y6kdzhûR~4RHhzܗ+ dk} 'vNORěg]*Yew[ڟy,QŖg!B݇1?? dm }2Rf&d3=.V@,b]󜀚8&rkg߉HO&؁l#6|SS}mxZ9.lV."xd3ڝȎ5_^+aWww4fv]_N'T{, s^To&PoʿkcX:10Wxg2?܆?C(wٍ 5GfcAh--u#S#MS13bi fYes!uПdNM!ũNb hٙ9TR#שvA\H8PEijz3LNۈLh~=ZvJ%TmK[^o0y|aq Ƭ `&o[P![ `m·+L1/UU6|roe~h<e >+&qO1_Ɍf0#E)UɪG0T5X 3p,_:i~h}E g oP<5&t6,Ҥc}f_3- p.| PH ;00R ;oK?okiGs5☊_HJO-n_nGo'a3d 3lpdDOuv0iF|^9)NpQe0GN` W3|1=ʯbH&C0s94IN 5@\*u~N,޿|Rtjg_VGU'Uh 'v7262P1T>$Rq?1>kٚAöDg5sN>pÚH* ,wT =pVOZۗ@ Y13HhQz.Ї{Q(Yݬ!-0y4d8 .E ^z9ŽqWIG8ܾHT B.O$r,Avo RJ{q7 C GЪHw`_#jt؊,܃svjS*πIZSD*qc5ef9g¹b>D;&7%>U0@0+j:̗?& hHW*u(4;a#P$*k%gyE( խz,dw hˎCiL-b[6d+V>3~\ޯn|QӨPZpKĄIXKw1i1>FF'^8szhpx/큳23gX=hѴ8]X.<[Ka-3umxnF}9Y-^5 hGrS i/%TRHTpvn9M|Y}MjQ}dˁ D hsuRW*QUՖAIQLmZO*~+*G7&ڢo7PhߞQSt|Lw1;k'B7YLIvm O;Xn-{>%ײ Tآ>D7 ѻGQ.9aV*PxdIKX"3R~9I)6$NZFB "%AFDŬϹ?חC7Kg:K/&S-hWU 3`~c͖NGѺqPN+*ZYD HpyOSRy<J9f;Ԇɷ&qRb4)MW,D8VU-d˙~j*6ez喀F4$Y9F,oŏ*61?EWYE,0 gOڂ3 ou#0l]&k^}Zpm7Y6:ڗT54!'_JDC~ó\U] V,ezoqjz>?[3N>7/Lj)-m;7ېƩfd\Iu`|{WbEgw cy{G?50ӥ964Q gv)AJ a&&77Lweillˮ;[uOV߄-(#)8#?}XO;??l%9$6p6;"v`9F"^R68a&D0N6岭8ԁEKA(6b7n8vdKMk0|CG'd@ Iwބ3zX +~y~ 4/V3JM~;1ҮΠ $/~( 7ڒ' [`b|"䋐ΐJ_imp KXUxL =h'q;="(ZfuSY&GE,SA]{R]?<~t!W517)+ endstream endobj 243 0 obj << /Type /FontDescriptor /FontName /YDTNMF+SFCC1095 /Flags 4 /FontBBox [2 -250 1514 940] /Ascent 508 /CapHeight 689 /Descent 0 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/M/l/o/p/s/t) /FontFile 242 0 R >> endobj 244 0 obj << /Length1 722 /Length2 6791 /Length3 0 /Length 7366 /Filter /FlateDecode >> stream xmVuTڻi@KZcbNFCRi.F$wo:|YAusrrBB|>Alff98[{`v r0W_8fw`l @3 br{` 6VT)iP0i ClPw0;8laP/L<za. ׊Zz9^=95PWpS k;.,X}x lbŖ xOo ?lcv=5]69Ѐp(@ot@kg{] ξoWxX5{| 0Hn;k?47s7`~n:?K=DOQO?"; P{bk8?֐/_%οT|Bb~a~1@j sgmfa#+8d[4:p擑K̠Jo2c+!0.{%CIOs\mKՃʉ";!{miq/FVDv0r%D^k+{[l>P)1UȦ]S|F}^DxY}&Zg^'ǀ J9m{  ^4GY%G O< F+DLj)Bj e*"&G˟BH귬1/jB#d1Ie+wP?f/599Emxд z'n&?7Ge(c"!`blIJt9KETUE+wVnءi!UsƢ:ZBgB .K򐜹`hi2aC';vʈ PIU^'yw%mΖ*Cc;YJF><(QݟG>bZfW׋XoEa!_gOu.ag9` jkS)kV~J!#/- ]<.h V?+!v/GwÐ_sUDB $n~ 9H* nX4O>~MΕl ݪgd_ o)xbWI=7y mXٕJ(a6.%9& 5ʍ)|#sç&Qq'y R$7Aw{2զMӝGVoN}8ZLmE\T^tvƶX- ^3ɉԲ<[m72^7A…Vn(cg)hVݝ.C$׵AfF,cw8~ђgS9Q/RP>5bqF$sRgqBf -TIS<Ŏ^9+ZigQsaz(yjRȻ]͞KZ!O"H%ӊL};!p=Wb k1<'̷Ts9BǕAwYwv<{uɮ߁/G̀IG\_360cJʼweƟm.n[rrqo(N+'!MCg.鋘H>?ԗ1HMV>ZISG1:&`[CTzǿuᓂb:4nKy?6*1ɾs?t؝ Yxzn>'4l_C7_-zFgي`%iGeCYrR'*SrtRt)b.~% Nwdl1P C& o"A)ER6F~ rvIT(>(,,qJh1@2/PR(Ȓ NI?Mz_ifr'eTIƙ'6 y%$>NwKLִ*Ro`^U{;at2N![NOXt?M0û|cb6m'Fs[B^OTS9\qg]Z$6U"*Ķ@٘oy < {켢b5o/&|?)Rx;iOfȼG11Y"h񬦰f1ROh0 [}mX6+ BiE3b)bc u/S#T$zw(b/w2VoHnf֟7ۏy ~ 9i %tu*|'3;B]*) J0@ٷR*Vyy'0Q**s?WZXjڵb yf?48V(~z9 VA~`pf;gصnU T܊Mjk ('scZi~fIP.~-5>U8[>Dl{Ef%Bp䘷ָ'=tqHr%7REhdI?C-'q{ evYŹ߅eu4-W'2n qc_{DzASFleiߙAkt[ښߝ9|9lo F D"e~gFVwo ܤP&M5,js_\5[A"C9_,~p,X8Kcpjc(݅wSaG؈l ,Љ&g&j</xH 'U7|}~Sh!ʶz3&'T뤡eiR}U-}42ET@1Z^'=ch)W8J b1Rq71aݤ}u-etU4)2  ʦY*0B=-UO<^GO`b\ӛRcF( ^6૝s;5[әB%p`ߙy٨-) #tpkX{W:G>^:@O?M;Y. rj&y^ٗU|RkC9H"4]LUJˬ4:h3S42ìH|dgM\N5CR%vj(^wIT3:g"3u>F 6;U'{e8:Ws F+zpLmެ萶j}"H*B7qIݝf42W-G(VLjܙq:b'd=(?!+!Gp)QѪg=S1ygluvau׼L? nBk얞?vkϐr(%FPcF; i#d%0T}@Lt\_*cn|$G.Χy9y[[ݏmgdiS@Aräe/RhtWAlY {ĉ[9d nf1mU Qy;>QzB ZNQ3[ܮ|ϯpCPCnI:zϤOBϖf+%)`;kݒ!%jJLy71"UItf?w,q́efV1WinCm~aqT<m\V4?~cO]:tSDLA 1^uz7@qWnG RnOBF.}[qY %J)x坡teK8q/oBGb ڍ2A%*퐎q끞}HFmۅ\Eiv;0Jw*VCp,"DC쎿ӵxׇipXpȂ򂎰q* psDOIKkH?izj,N|aHzE tmI;yU6Gۄ3mEz[udFMYM%2T9sL(!žOg,G)F֍OQ14{ C}hL|N9/jׇb!՟ŦKi8,W 6.&3eM2flGwK#z-5U{8I24(~ϊOn/4C!hW%)k9*'Qk T?´kz=:FiB:֧FWi dAc~&ӛJG,?swx}K5wOJd]=gfOzH-_u'#C(Qx2Epi6J+#|$ (OB=`)U!2^fT|)d8IA>1Agڌ5jg㔑O~-ܨ~HR (@+ErqWoAy 3_q:u1P|خfQVEoƵ/c*H$ưkQ$Y,+2s8"Io0 uo>}+DCzzJ Cn{@mbژVbLD 6H=帘2bzphޗpkna6:E BPVMqN+_[7RV\;yپR˵t6$73vZxK%mOkbzl+M2N#@׍4pnriO.~"t[Kbڃϫ+ |pt#sATZDY^UJw'/hPv b ,WnLԮ'*PSАIoRV$$6aDYe?d3ڔO m$oT?1~TR> endobj 246 0 obj << /Length1 722 /Length2 1738 /Length3 0 /Length 2313 /Filter /FlateDecode >> stream xmRy8}V%ETKc$ˌ%e %sb\v_[W{I嵟G͘OO=M;usQ3Fq/]6 C.u>9smۏKZ]1m inI>`oem4teO&b}feӪk%)RbU"[.61P  M2Ԃ^rUKb,V]CA/( H\==8cAն.Z`HYXܷ0~5%~,Xb'h^Sm-$hL^!|xZR< COY'(ކE:Bʔ%2uo7 3_ Qˊ8ӡ5 |9=KU?NC2[6A׮HBP Dy0W?%ߜ2-Gpa07$/п71P=>zwK~w` ʯ0C^Y_<_-le}) 4>2ݨ1cz㇛ ?Ev}UK=M?}z9 ɯt۾_UZ)HE?Է(0G^bqX𮸚ҹT 9UU0v~p/*uƙޔaޏg1.DZ9L[Hk(`٬=UruvɍĬ,f~%GYy7n*d1,NJX+r*:xA[@쳲@{_~Sp,xtzԷgTt4IUm:(qhCyLB-*$Gz3{O_B*ܑK-'FEbJ)uie'b>k\N3'َ۠xbO]?gTjKd^vRe$=#&5_|X9%#<"+#٥񽜺Tz xXcGkKh`.ne^KޒԌЭ녷x{[zijJad\3&oUPceOsvtZMѓ)uNp~jq?:YaOsOʩufņG(콳۾#7qp5lp?ڂ˕k+'EF}oQ;o*gjSM:r/8%lWU(n$֞"C"|sDVGƊ-|m&?R!1yۆիs^"0Nj:b5^fo8jʘgE4QWqm)<5ܰ-m^ $9t2v6[o~e{n;.C:P!Si.u0vE)Fs~zwvߊۺ-oz*ح:ءqFyj-a6_+T0~>]'"|+Z|W҃+k\ tV{?Iז O:q~UL3 FWaEn|jJ,țQMXס)nI<}i.NY endstream endobj 247 0 obj << /Type /FontDescriptor /FontName /OJCXIQ+SFCC1728 /Flags 4 /FontBBox [0 -249 1537 946] /Ascent 538 /CapHeight 689 /Descent 0 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/M/l/o/p/s/t) /FontFile 246 0 R >> endobj 248 0 obj << /Length1 721 /Length2 1030 /Length3 0 /Length 1596 /Filter /FlateDecode >> stream xmT{8Ti5Ժ} 3$q)[T1̙fΙΜfImzҴK$EeD+ r}Z6=}}}>#7 %bN4[ Шf ŀnh4:`b0㘏 HȆ L8d2KP&\D_f;0s 0 l!`JÅx!怋@8BȘ& u\*q1fs F!AĞd\46r@LEBT>MUqDDB8yJb` Iœ%RHsIT(a``悉RƁ78 6b"6:by_a#M@ !Hl!i8 O7 !RD?LA(B+1/ ]6e CSxF&gR6ܛMlQփ6v&XΘ>`sط֭ܣbdA=]xI񹈊uF[? G\`{6W|zMý& W^۠k7(m--1ѫ7kv1X`ҡyԄ-.ݦj^/u 6˰(#K;Sn+{/VuUU+ICcZF8^lN[/kV<_mt_':Nx.9;uԒF."(&w~ioo=y6ak:; k^Dg_X gO=0> endobj 250 0 obj << /Length1 721 /Length2 14928 /Length3 0 /Length 15455 /Filter /FlateDecode >> stream xmste.tlNvl۶w۶m[۶mtasq䨧kZvΪ@fzf&7\4r5r4 OwY[8LmZZ6&>WWWAW'?I*@ 0D%Tj ddPt14Z휀3{? _ r '*$ aTٙd%Isv'h+dzA&cW^LJe@q8iO~wdfWp%e&S0!%OIꊆ퐻'{ǁCnqiQ#=VA6‘=G˪mO LuuoJ<ۯ]ӻ@՝=c~_ 1MG ԩZ7-٭D s2Ir3xPЈv-sVMw_udVH%EY\sW裒BZ !;Ϝ6 ,#X\p/4{ h;%˙SGUv+auĵ({i##o9|"wFQtV8}yZ5{H!hH_ gymozpa[jErQ%LRiFfUĠ p S^?)]I3e/E4kZ[y}kp%ܼժ`4~:v4>f,wy଴kddDN3%GzGMEK1$Tal:;o;P? ׈=8[[)'mP ' Trυ5Og(=-rA|#uBugK=ȵbYIx_A8mq%^ z6C$ \̩ᦃR4(ߨjLn2YFl6aGT<:"p}W%(Ǭπ|;$FW0)ObrCVѩ2݇/I5!pi`5O8c7oZ4 zLY6I村{5 `ԁF1Va`yY!;Y8x9K$maq84$W 1{X)Lyg(C혊:tc%TsY6*U9gy4)<WF _POgJytDUȓ5)'V}LBl6=9q@:=z6sЅ2w$s{YznuMg)FU(wgvMMsόYJtD"CcTjE3s^*aO+*C΄AE,: RaOUy(|u?bLj{0|bE>APƀ'`(VŦ÷ cGw݈}0\4sX(Y+*TGXsV-g EU C42khyz=F[rgDѺc8gWl<ү>])3XL$ S5lAE윱1%55#$lf83Up}fq̂B]72 w%}U|1t细ͼI Əz {)B}ttO?dU&j]f]H: I~q 6MIDL![K=O7eK-nɞGsZÞܜ)ss:M$ WKp̘.3褾gBQ<|? A9*Xy/ď mXqǹ>}A1 z(HQ)LМFs玖{OMA}|s~~J^M9W(nW7 6$] K9zZk~-;;W?wSPVns\99*eN+ATT&{^&O0QsyE iO}g'S- AH=aQSAnfLUbjZKpґOq0:MH*)kRABX,uwY1{ع~x -h^q$xvy[3Fa'{ $C_}JabH} <-AD=rGk#C 3'eM'I y:S#_3C42cЎYxIBfn*$ݾ_z)My" eh\qg.sJ {exxRun"zC? ZHG UϏ.给k907ݫTCee6m\hznc9Tg} BIJc .]5|" `'XXu.hj+0hBȃMYpM 7$PpdfAe(<򱛴 ;oؕX< 񰿐Ǿ)*u%Q+/@FДKoidK'*#q1/:2 <݄w!_v7"$|~8E"_AHH}&G휌 `Yۖ,DEJxtNJvZfv' !LԁU׳J^ZUưW6).hb$e(o(=U r; ?JKQ5B UI#&sg Gf+]Nɴt&?4}Y̛Qn7LVٖw ثMLּ8R!2FdUv%=4h{ROcʵ16q?߈h~Rk9o5FuƤ  ?>TR}[ELI|AڐaxO+:Uh!g+-;5t5AwUm ٖ+A!D.̐%jXXoʋ!'\͜|Q>RaWY&kLk!Kֈ%|ə.dcuyOx;-ip { QВ.;#[ O6`>|S'v;/^c4`TY/d#N%~M 7^6>1=Q ~]ꈽ񖯢>@TždAhԼ7 -bQu4ږ (vIC7e9iN向9B)qN(ulD~賢]Rmsǽ>O]Z9yγЩE9f>% XdG8₶m8Cueԕ*h^qP6ï;*^LDTaxAN@cBp|&zsGfFDMO-8DpT[E(iv' -!6=)s3! 0mMZMˆ̃Cϙ3rjX5RTμGA3I=(cK[<i콋,!G"JG7CEqN@EK6ɜ ahho>tӧ=^mJhx E];Dp Nto@Jzޯ/k٪U^& m>,-ZdnwE~]u'2VIXh]F{i[U*Aݒgk/ϣ4k;KMz ډՔ$H<~IldB$a=q $:"+l^+4Jg,\sҞ~Zi(E:^"dz؁p~[ )N-LaQ(FYzs53Tb5Ǯ$r CiZ&1sdɂGň츛 K//xxqa- D϶rh)TŦ8^B]bpk䔒,gLG'a8I{_'5s6OR"Jpkm3 .a(nB|ƻ^=h/;Pq3hvzd'WKɀQW:'DmKD~p:jt1.f pb]ߝf΢0vC aNR%H?j9 lH/|/U̎2+|ZD8ɉ$Wěmhl9rgR!貶!h+_xS?mn<6`ƊnVP؍y4:ZK׻^$uGVg;|~HsVʮU'7΂/= ?Ta8&: {ǹ(Rœ?pLʢ^F۞df@#p0R7(AHCxutV q6HNn^6X&3R9!ġCcs{ Z?A-E쌞_n>ږ?ScPȆxc}-ռ[ETHRE[q" R|}DNbμ1ӕ6$ݧ{+ū&WI!_*\17ܦD&+3ɚUM2[nV_+kڳ,uK"|lYd~D0Œ8q+aаjOdb^5HnH S޶k+$#"we\؀uM$!nՀ|J _V^K3&O8͞~brp3!yx wwYSwr8%rwv(B2Pï\׾vr [=K`RduArJ嫨;>VLME.rwPq̔s(X>1I XL2AZ6Zq!ixg)ȿ`j(%y;m5v|ȒUYd=ĞokyN7:sQ9q'+T2P(nԏrtΈ 7:uZn#@3 RkF T0v7oBR,, 9,]yT6Lq)1H>ŐL -Um_b̂@J&IQyCo%.}YGP")<&GI2g⭜~ x%inQE>(19/cJΛVT\ [7?l_\K5L\h=ӕdI3&fCxBKdE}7j?tNKX7fz /_)aQ+c<3?h ֘oHSoqF|ȎNcTKk0J\_Nu6\OZpa /c"[?lgaG ^If_[_Y?%~XVf=:ng BJIRxcN(U& vJrDPxa.^keLdaI ܇ϳJaEDu -܀cx#<AǷZ{M\.m S_Q@T>ت֘A$yp7|=|6#2ciN<7޼FE^/~/tOxOSݤ瀁e_zhQ,:L%Ǘh'጖_N'g6U~q"v4~H#Ѷ" | }Ac: SY.ȯŜW/qZh|1`Zy1k,)sqNFx]ySA_+S{6KsfC+0!GJ]]+wv*8%-}37Gg. r:f\&g5.BpYkQZݙJAjG? 4Qyfsm{g_a+sOzma'A敩}[Bo2R䄫 Tuv^qi^KO<1>8Y}<+|̵S^B;mIAs/7$:ŝ`Q`ghk?y̌uR!ne . n_7').i: F?h}ThF?PI0e`5(#gpj/m(HaJspzsvnjWj6eT'}g3Ϯ jhO)|~"r;X"oEH|ꥆ(aըv1Z/4|ҦVj khWD&0Ck)ʴE-ZZ8#.Ftd:y9T 9EO}xz|޶BHƷ{TSnrnޏ6_8kH-Ĵ?;[$u+-b(_lb˝`,<~=,ť`X#>F?5 T7C8 ,1iTxRo'L":xl{Tf+;(U$^L=Z2v䓇̷%R ǪN u6%B8*'sH{I馱ځpko8vC3c_ "oh %5 btpv#4_@mJguR9FشUe{|QVpdX Tf]VGg;VGc_z"GW لc:2RG"ŌApd; @l|A#x>> ?܃.XLf<%ӆɲ0 8܇LcpsUK2Plҩ MO+330s_On"*n }p((ϱ FݷVpMpWV&:XSEq!c3-֟qq9 % `RG{B0; WJ0z]m׍EXԽc~Et\fbA+Vp _ּ/>;a1.\tiLWZRfP*R\9,zCԻ!+m_VEsԭvpx^'+D@}#dc֖C( T.Cc#cqO/"\}vZfo{m;,϶а vp:h"6+TSBJlVj0%!v½(9UB5Kmy;)-t5ܻ]TȂy CVo]h>=zڀU|n7UbP oou%?7QcRWᖋddZ)>:49C9p⥾=[:"ç8}8pm()eDa> .Dk0]ֈBkը8rٺ9w/%< LRae1G=m22Rr34(<${~ǟ4F-5 mkqfCL`i(kH&b^Ȣ0- YuV0e(]dKׅg;eLjTHA3Rn?)]w|{ 3 ?;ItsB TphUBt4D{ShwӵvU` [ y!Bᙞ T"B*mПMU(~,EXk>q;8;͹a:!fRe]IP5?<ϕblLߥuM R3zd%:DdѥkVDՇ1O_ "RG-(9Yn!u߾hQ'#L1hd _jN/rD^[j FimӮ!x }}VIj/+2'9A =KPoH`RXuՋ"|Cl*X{Oc|'X$8T 4v#" F~*^1'\ʃA ׏R#Ly|fNY@lV`ɡ0CwSR, 6Ȃg}!Q,· 퐝"w%8`x %Pî'.3Ƃ Yl׿[>txH ;N ~ne :Hk5 TZ-=7 I!%j 0Q ;֍S(QD_wMm<տcϾ>r:'~H۶4}OJQp@υ<)S"`]h}z}Қx%촦e#n)36b&aC~"nL ߩǟ0.{;xge]=|$}*xgIq﷖QJ-0>/<˺Yq6&Cr8b~ -uHy:fh%Xh~5,k + Øx4#UŒ ^zD eZxSK_H.imO~=/@C`7t4MCu). w8[1TSbN,Û&,V)H[;ՙS[mA ߸}R1c#c9/SY EʁH ncMg /!-<(ZF.XJsk2L%̟q7j'Wd[2*ikV=l)Dgx@Ќ/>S}E ے4Ñ#= 7'L},2Cp1+ɺ%#B&g]~sxHo-lM cZ̹KGȨ~A߉/]V)MZ`7zOqJc*֌WѸʀ:yڷ>{[9E)$ʹ)TѧSuZPx"JRd >w'#W,h,MRt ņ;bL3G+ڄY^zLl2ڐd锵 %nYϚLiY.>c#bu<aa&s5RRGa6{yC(^ rǻ(xK ߯^9xь[9yo MUJ (Mۋr;eF(yQUU ^AρdݱINl?rgCck `qy!g'G6N $8DCJJ{Rxr<vp.y{~뾻 ڷ/)sRh\~ј M{Ij3-T͋~H1Aɪ?PAу]cкg)kNu0GHXR5l\V&H3\P8k(צwPb~+:Sp:$>iz[[VgP&F/*Fj4_g,5MJgeP +UMPƹNWЏmXbk ͤ4y4xW Z *}3C;v| A$BwsLѶoJE,_a#UDXJi|PT7.Ǒ nI6X# @+Y6KjN&nAN0NhIθe]鏆ܙĴwd+K;r)ny[1 PWDfNvpҙԟegty/qY0gE H') ởBm | =u.}a>!Nr@S2i'sW?N},yTp{_'(H/nf+O\9ISCmSR^Rh,B^"}1bbeP6]L.ݼ yyH]=+9[5 ۄ3X:iOsZJ\. E2?I6=OodJ냹% > endobj 252 0 obj << /Length1 721 /Length2 18998 /Length3 0 /Length 19561 /Filter /FlateDecode >> stream xlc.]-\]UOٶm۶m۶we۶vٶu}o/?csV۹x:221pŔd t0N.v".\uS C wt4pPS+P14tػY[xܜ]\)R65X,mL r q9U @ ciljlJ 0wۙX'gs3ur-@VTEPL^N *L" 03HSnײ1e_Y'[t0Kc &igf`w?9@񏆔SЮ66r a{[WS'@?(C[K_EH?1;d,faj`f6HEώx%i_ +(Pw373(J+Z{zC?`@ƃX%$dM efb08}]cW''S; O/5H0+!V-a~EsTB r}ݰk6:v5^YQvD[&I\[b} ?߫z4oƥ2NR ǁgY9G)Ϭ1$bwۄNjV$/C?;ok1\"N|)W-`r5WFCi%""5gZ([W@YT#FN?`uI1tzs۸ Vyb@/%T]2[8Pdf5d>'"}#5GX_(;5X{ x̘"}l@~-9/2Rō,`en`LG54oSdL~21eT88QN%I,:Έ$RXş>:wT,b ;< 7AB8nIEFq٥K,( 7 Uvd ]?'_KXw,64qp9_U4Ҝ}*Bwo^Yw#.<&;1D\ac/[B̰Mh<]~2 JwXq42]UZ  o ~SE'@p;lEwk6/v7"m^8)tcW TmSU=U*Ƒs+ޅߙCf|9JR b45!uKRK7Vi\/&3zC2qXw 70K ="ɦȇukmͰL8_U(\`X!cj}OSB _^m)%=~[%S}oyhndYe)i|aw_#[qތ b4c_ݸ*Z_Aju' U9Ie9Ҍ,9^2Eqt,#Iu=!5Ummh-6{I([IѿA#ڠ}m_J/Pv"rYsCȱ14lo5b2ˍj SM qQjVКwq5`=~``WB]WD,ZS弨IsGWeM.ݴjTNޅ##I@>;! 2EOnK~A33qwr'BY~G"ZZYӷ(cakqg=RC9(e"@  LA&qҧE@s₇t#O JݯѬ,>Rjgp)*MFO!kEm {tUC98K^`e6UӀi^_ 5}*?+ "xu|۪0l3l%[5r[,ΤNp5n\t;87ݶeo"*eA~no;GZCXCaR8ރw?>FV~E`/ ֧Ǥ\"D([䶮a3a3": IoIyjBo-q\X4%r>~а=9c#{JI?/Cb2ϣ=ZLԸl`hu4E?8]~X5@ksʹ?gl!yK/9eq5ԁLۖzM-UZLB Gtbm-1 p)2葹d*u_i~mxjz55IS( HEqC,x${ _?ŁwJF'=oŵ5==)5ؚ Y ڽ0Rjf\6}Xc{N avi9Mm v,2:u~1 @j[}dA/: Y5ʔ4贍bI*hv U>\*w D3 ?G+X[",qGr_>h0S2g wȓYֱɨv khHsȘBDMTO#umѮ68F_baBOHLO+ex>lQG VDwuSm}-:J:4"wP o8jR>!LE1fAۏG^ӂʏfM_5IG1!?"LQLcND$FɠB$oB,U|TgWy_EYMpw7BlAAرhqs ۝ë́|3@=z3N] GD49eY4B3;}EdPz|H,t5%l苻VУF"6?FC2)9H(KSjMn)~:hK=I[qL8 )8 #M|d{]u].|"?oCQ;FmQuk֩TЦ+ wy=jJVzhfZvF6z@Eqo6WM3?l0Ts^$z' ϼ7G ladUVW|pK#^t)Ozn%9Q>;vB/b\$0JH*Mru7 Ve:f[hj]`QEօ;#Q)6G'{ۿ>[ڼF҃b${WRM(#a#Cy˙L\:4OO H"q\. {dT\[8p/ FVn1gEUq7]!q5: P9Bh1AO\oD )L ?R2XQ *a7g_aX)~1Fneezr To2i}Yy͕]kRxP2E5Qq+^USgA_[Z^8d0Kg^CZy- YܔCO;,7*]CA\>VE_f !,7hKrg 9ib1]5(d j4W۹M]L _QhY Z{-yqh*܆:ݘ̝2EN/20=w2K9Q lAaf3RG/SvÛU5Sy 874(cNJt1 2APRb$pU7_T lJM籜%pa^f2ϭ1tY_X"n}RN~+jA /8 { rRUoU`gx2X] &߿mqfdR_o,,kPq܃ӡI+-#$xUgŒL& EldT2j0`8_b/n3d]YL6t"b睤z2ti`weʞXYN8t_dKٳزf (ceRܶ`X6tQ,S.~uV 5lkA0~OP*mk/sZ5Cken#f?"}5b# c&a'Iټ1׆̨=/̌<9geН|=UcxTkΔp!yx/|>냡W[Qyˀѕ}WTF'- s%aIӢt>r;cftX r%[!r PH#2(>A :`y%bH<* b|4<˳]yO)kUb-Z8=oL1Y13.^4.Ť9gSsLj)͊;{?W1a} o2.V u>}Eox-Eڴ )~fڙ ^0k"K :{]PuA1BFh\@RRϴG`#* & A-ҝ]N}6KDէ`j,#hV>Qp<@5 n0ɘs{ޅv\ Rdpxj؉ӌv߽|)#keji Gh~&m5PtbM7Y(R ٌŴf@Sqd&5s-s(㔠TIit[ X"@=ՐNr?Ogtu454`0!Je#>_:OIhW)d6:BL%[ U@wp>c;-~.D)qA-i3v] -:i}UVYN @T/f;b)~747nev &$i{ңGߩItpdЌ|7H.|]-TR/h+-g6ey67d4\3y)Ub6Kn(/ Ԛ#)t*h\9%N5p FkU[$F!3%^DylI2}IyUgR 杮 K-<\JAa 6NXJ9x̑GYeӼ_0韡. /2R}fX?C?yP"0 f"?/jJFݧ*uz/NGdk7(\<( onwB61ZE xOSp3n ][éI4ủrOu)p3fGci2D 1>jB4xOHׇm|D [;;Ěo]yd3/YwEgϰ?#aIG]+{a?hRw5VvW t:`3r֞CG!%@NaM%,2(C!cfYN$,J |!tCI=ODP 3`;m|[ 3tg* mhu]"XK|cQcu hno8 ُQV 2 ̑;Ip !gx#بG@( ]}} GЙ*VhțH *EE7$7bf!t6 oș!̬VHv2`_.'qiࣘ.OxLmzQF#5* mB:ZeﴎAiO3m)`Nlga×b=nb}ūʌ pxNRZfl{s&bOLUo gV\i ԣ2Zxa/j-cz,Js J\/bZ3'SY*%v{f % R݌綱k.: f 3pp^ؠ3G9\?XwpPDf϶Q`6"8 ^ /O!;[̫~;PoW(|kC!d 9_Z#EC //UB4TߠT%ř}JǬYe"^ k/JJ~9sj/8'V=CAT j[38:ػE3 ){ b(6O|}UNIi!L&xpv|TO|Th9[I4|Zm=Oq? ,)pg&W{kBArHOUg+6=zFkjc!06F8+͉wj{ eש8hoQ#*0JcaAC~^QFfCbHl¶2LЍVfPs<'[Y?g L!{ѢS0&(wuDܮ]$OvH,~2Gi^dM'/t6QRi~e,$_bmvwATsD8l^9s͌W.?suxzSM{mw|hEgVB5XCA+S>z'F)2Eu٣SfbO̤a5IY4;݆͆3\'UwƲ3nam#Gi6>" lU8{?"Q >WKӁaiL[:IxRd~}J}r,hP۩PLL>JxzM$ǎ`VO%L3$+#x=Eƻba Ժ~e7DA4u'鄔x60>I ǐeRU'9r4_vhDu`r-% /lvaG*QF&ffuSu(f}.8e?J 7\8!L ̼:̋1ZuȥeZL-굆WmLZfT}$UMZ] Sz7NQG8vz{];d,AjtvWTt:+ks #Y!k͏SA!JCie [x6HGJ(T%h뗘.NbL ɌeK\iD ㄋS \=.8|\ Auy:70w0>vܹY8MSpD$x`D'T^!׬zȦ<⬐D8q|lHWI]D* 2H'*#I SLj2zKC`8JrL)S3>H9hW[y45>X.AtUA-Czu+lsK{ T>sjP[8 jUWyw u@QrO%0hp"YRQav`et˪HW(. ՚d91$/ ֙cKm@jI {"kSOXU* g=6OƏ"{I4pMT݅~n5{ȺSO&:.܂[偛:=7EXVǡ84Hq,zU ҋ'r-N,bWj" ~EZO@-tY "mo]Oq XC {pBwaӎBD&=0N5OpЫA״[t J²>!U?Z=G[f6"ˎY=zU_cu`x yoࣵM6ɹk: * `z h>X:l- Np$Jxt6L?eYϳh&<ieqoW./H"kţ4ʱvkw)8r1ުD{?ɩuh3 a.b]PqؒH2 :wȸPE`^[?循#s^=7֍<(}/3+Ͳi2j[GCyޢk:""f{:"̍dPtt7B n7K=ECAg\ұww\eo|O gy5 8igs(UcL=M"5 syzs}R4g%ss!k6Tza~ 8 P%/{6ص/и枼 >^^=W6 ™9n=C( ʆ%=%V{hpW?vERـ:q$T+TQj Mt l^ [50L޹4 ϘXFS]}·LjAyᆬeɀ@r҄W=4R"0L'A㪲 5rY~$25ӒUS>.a$*HI.gd樦%Yy 1 .N?fu+-AGsX!3[hǴK@sGP5?յhT)" v= ѱ(^9 qٹ1h|sMԈ֟)٨چd1K}1u(d$(4x4Q/W,tbO;I ?#GR?BQSQJf"~[}tսS e4ĻBA`x^B0ݓ PhžnIk+=E2ɛ6<}c߂XkxC"#P3*;X.]Ǘbs9Ч7~MّQs~ wC|\=fUQbefr ntA*owmWq9s 4Q*[O K?epWW?IztN#ih6`jeB 53Ӊc"KeiP 48D$kȤ=FNw04#ޅLRxHTMD0vnu!]AxlD)|qQSi+Wښ*V. l|ا`}[.MQ?%)LrENڽ\ʫYuK1P.y'~F(5Io5":VC@,6DS}C nPhmxI9I :\5KQWc3Udmg#rc@CѹAĪ8gyuE{x:w43L?{U6eT%hbU5Qc Y 1Ӟi 7q6.eǡ$jwաP#cO`)= @Vp9OόC-ycVON&O>ſE`na`V1}(b­ 4|\ cg}Sn2XiY#O%|ھqtDŽV_C&`[E(-iK0eR[{J7 dXàS^ -{|Ct# l J,Tb Ă ѵ z}Yqޝc 4¼ܝ\fqmm/GƜ"xN;*s^3,P*gU}9a?0ˇY!p4'Ʌ/5dwt3 躆rۀ%b(]MNmQ@x΍kcwY\JYʻ }fڋaO$pYX>,e_h`l{vHy17}fQ@.A_`<0H9ʼ(+J4xC1 &Lm:2B߸Dd:N|%Ī$}m !gɂ8>0_&Fu%(`1ÅKEvwgᙀ~.o-!Giy(e\)8Er= WA42 (8/hL;]~jfu;]Xhg@J6fl]ZP%60Ĕ A"Ow]9N:NUPG:]D?AEM":mT֥?C:ď֦KVihj%*Tkshn _4Ε|t~?~B*OpSLMM9 EJ&PvʵcV̇ކr8$qw}˨ ЏVN;R^ AE.w ] NlԬsܫc |RMy)[@%>o#tRߙz{KC"VYhHme=9x}G>] j˯]%R_|GkȫV(zp7,ufZm,Ъ_3B6 oTd!OAF:fm0cׇ8)p}`  ƫw@Mzxxג`}wLܡ 3O$?GlnȰ)S˅ 0at gh֬ JeyRGa*.8w;x ;IBPjx>=}KQfY?ctj6Рa;b$/*00 PXԋlM0M .% 'iMwLJZoWX]CMnҩsM:q_2P(%3)f!!'ڧr2%]hjfź\G@1}m GJG-u)@*zҽ^ 3}05]?tz+eg^ Aj{}ݫ0|W܎HEt>رy!c]b7åػEJ>^VO*0ɹflM6;O^ {edԉ|}6|l+'IS9g=݇/v~KkR&sjz*BƱ*t+V Jh]q7Qc#S0[ʜFyb A=#Fb5<&x۷eFʺ䱈VnRy^e,Ug(< J-q3ϰf[b !l{[pTX6W,:EFFVO Gw!q,t xla(ncB@1eg6cByQ*I^dC )(o5f`}6) ޥ-&?0d{"x թRt\~cYM1w;ʨof١䰥*o*oS֨W5U lK5M*A^,Ȃbk}&'ؾ;?vLn@;y:Q|e(59{K<-Pz}sPCK"]/:80ǝ i?m{SJ.D@63^N1kOH3F ʇ6aNf0KR:~Ou[ksrffN9<޹}^#J@kp"%h\ZSV}ʰ^$MnnkYD07f`$F/JUiUS`O5ŗ/sαYyY}cj;Cx*k~R?I^>o(A_@f90m%ǍF&e_U<(ޏ _E| 1dwFIth&mlr,L̍?AVNCjl=]fpdXYaS3LJh- :'qXYtSDHk$\"T=!b g ` L?y`wa`l~#dii%uLDg~)=;L󧡌ìmջ\F^AΫ ``:{ l{2|8X_ϥTslM肜Quq y[y/A~t}_&e`X6Q*˽^Ãx͸Ziwo~.Ź(YU%w3Toۻi$&a0deq U!x-eЃ!=tOF>k#䡅G?y_}02~?IS,3U/ _l&0z΄UJĢ endstream endobj 253 0 obj << /Type /FontDescriptor /FontName /PSDMLL+SFRM1000 /Flags 4 /FontBBox [-189 -321 1456 937] /Ascent 689 /CapHeight 689 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/A/C/E/H/I/J/L/M/O/P/S/T/V/W/X/Y/Z/a/ampersand/b/c/comma/d/e/eacute/f/fi/g/h/hyphen/i/l/m/n/o/one/p/parenleft/parenright/period/q/r/s/slash/t/three/u/v/x/y/zero) /FontFile 252 0 R >> endobj 254 0 obj << /Length1 736 /Length2 7769 /Length3 0 /Length 8377 /Filter /FlateDecode >> stream xmWeP\۲, :w :83w' ݂kKnsλ֫z]zQKA. 6&6fV~,+Z db KZ s`geeCC<-\ftv&NM &*\@ k;@\YEGVI@+AN&vWS;k3 X@v(3/L\ހY8ARJIquq  vq9[U#____?32` #ś,l 7|7 hW;;%{Vbr(BAN` 'k [yI!bF(FmvX1oabv-?mR[s荞Cv{[U_")&-<A̭57jM5V1g=o@iad(117' ?p\@`?sy̐ f!6i͟INCY~Wj@ ^J+iKWyeD)6WWGOKu[Jk,2ޛ(;ɽa m*n#XT,=$-I=XzX%+h6b\6ց"~+1%Ѻr4fʄa#TzЊAup^΋iy!]O&@Zt5CgjG psMtj\)ԻP֋R+){Ҽt>w޴P8܆IjnArO}ކ 6ohS*zhbu^oU$qd704G][ K{pʨ[[SEVE׹@S򺐺8%%]wdÃ*ϫQ dz%4u%7 _Mo5 r?S&Lg|^4ORb>ȿ M>*rggq@7ܲsr844TxΥ+K*8R_h1)"Os#YGN)X_&*\8O㯸кT848i\ui#e2 ?҄E 1AB2۾,>)0PT.(/ OUJbBݟ}&P]/JLM]kܞ;rp qRkJ ˶S70& 3#tZmݎ$욓r$|g>H8IhTlsD(}yX6X3 Ps~0cr/a[Q;^=$=W{jB?i"cv0.b,nufzP<,0TH7 m&P7}Kآ5Hhӫ&91]]A.r`MKH5s?y Ӯyl7\i[~>)~Z03?O_ہP=c\hOy4t(;㺩/ZatG ~( !ޥ G@ݮ;TOSYMz8z/u~A6G;ZSXóU)vv!TjA q˸(lj$oblfF܄}{^+Hw 5 'IK +L.˷j/c׽QY[7j[=C32jJAvy9')UҴ]A])3A4%;ƶWhЄi;~[o7 u|b~W(¨=]J č *&Q^b)^E"d XLnf-i.NVKŒ7pې|^-x#gW._ [5 %PC3'$`4l2DP&ҧ 1b3Y> }"'6>d+K`CR)z q LwAV --oBiXK_1c%<\M?؀[j6" 93cm摞7-p7q_OHqeF13:p[mz>1O mﮀNCDuwb{1`犃|Ҙl{bJoqm 9V,EwM5nߝdJt,OVp"]E9OThS%wDhS%/8td'fV]#@>b|NSqv;cHڷ}m|~r0Hlns8aqd;Dt,V#=K[` [/66B|ِJ伯7gœixdU!)#;˔IRVVhdٕ1d@h.l_e*ntuY6U.%äc%Zh]m:9CxD6\GN  Aa EÇ` G9 ?TOފU.9CoUbB0<?WbCK^V VLia[!("T la9IR ZREad[;?! _dk2/61RJ_:ݭ){"=YՃsғMd>mÝ%D5.' ~T?m`i|>??XC쁅}' }Ëq.S?nR!,)6|]7D5NtK(M8<cƋ3Վ1S/y"F،z쩯c";uK#:}xJc_Dtg)y凬i:ݲ{kn?VoR&\PvHh~,l`낶Hdc.B8_+oϐaQҎ+32dR) #j7$RzOةk;gJbzV0EtZ+)P-CWm8؟pv'tϹ~aѷ8C |GƠϜ&R:Ɩ|/fwX[>9[* }5_ȽOO#R*aj]Z uvru#g$Af\#6Fp8Wn橎oeqH8++K'5ò@4Ez,%8lmd~h^&zHv~v}1}Gqv>Ik Ke;d$ ^(IU}~/77ۺ>}mU;ȡ gb|2Tqo/I)m#_r$ CX [=8~-};贶#2; J*` ^˼}&!}4&)TV>d&'?Gˮ4.S(CT,iz9P#EMu,k!#nE'V$WĂ5D|5R#$ǣӉ!xOI1s/NQ]h/0i M R!]ѭlG|L mu8YcV*S .?%z= ; q&W浤s w(^X{'D8kDOntr`^yC}2 #J8W:vh۸|c7w~0Cgxq<|)h^פ{i$P,,n\ԡNކ"  ^,D7L~<>1 +hwjx hY~ϝ&7_$gz:tBFX!*e_5נ<ٕD2~q?2moDi 9?e[d\:VtK O^5 @6QZ]i(_6ʇbm*-7hg%-o*BmG()1Wt$.+zl{ u\VJ.GN!H *!C_|ɗ#=CSj~ + p=أ"+n,Mè9_g>>jŵ\ DcV✂:G.1$SƗ}BDϲhڅ("edF'y~ȁ )Xo7tc5zh):.d|<"CjUKP rv?V]9SmkQ=g.v9Ҡn)uK Bݘ#¨my1.Ë⻌0'=)XvlvOYTa3hMGO߽'*A9G?ԲQf}A.2Zކ*AT`t=R[A' -h1ՙ. -}ԖJIRM]o<„+. D_ t˵Vl?͘ZDOI*]¨Y4=(xS'@}e"I&`02 qif$8O5=ܞBZ합_mx( 0Hv%OkI,U GE`_QCqǂmevI*djYrD iH9qsӜ{3is﫪 Vy_U?=a(ZʞԖ2-7O rzVbvҀ0JD"|n;!yJ꭫xȾ;$m#MΜ*gidh.)NXDcZi6IU<)ad<7?97 Oj:MW%3O梬fZ;t]~^)<-#|jΨʻ$n0F EES ZٵJ_vEQuLe$) lH)=zBu]g{]f6F4ѽ7KlYP_E=cD%j g>%g``¸pIB̙{LPo<81`|n]ZBWLgJ5PqvMF;-Ζ ہMM$㼗#=="M(ٞv䗌tr4>} [9 $0TPhnM͡%(1o\g~r)_ظ(*Q5>uȜu@mDCdk[8gWvܽ>GZh Ond Tdl[s AK aXAexWK""Lx~?Z:Uh,ԥA$1SUq ద:k-HA{ X w:$6.b6>/R:`IBT7Bo=M,\+ &,}*~hv#/0rbJ6|pHuʥ0Mf ^1^&fe]$M(h!tLm* E> @tpԮ `:e8LLQhLEl^-su*0 endstream endobj 255 0 obj << /Type /FontDescriptor /FontName /EBBXCW+SFSI1095 /Flags 4 /FontBBox [-154 -321 1520 899] /Ascent 730 /CapHeight 694 /Descent -194 /ItalicAngle -12 /StemV 50 /XHeight 444 /CharSet (/a/c/f/g/h/hyphen/i/l/n/o/s/t/u) /FontFile 254 0 R >> endobj 256 0 obj << /Length1 726 /Length2 1097 /Length3 0 /Length 1669 /Filter /FlateDecode >> stream xmRiTS-Vq@%e0(H0PMr.& & F"*3*( E   Z0UdR`^յ?:X` Le.˥SJ^gF"1qR  )` T*͌L#Hp8M D )LA$بRJ2L&0 0!09G߀` 0I@/Av" 0TLj*WD8&l,N@aRBю* >HFh#@A(mGEpJL$'GC' E[)@R821LqƄ0. GpD4CD?aVTLG9 Q@DA-$OSx(<9lX(0a B hI25ᮝ**\a( gr LЌr65'o:f/byya:SsW.orJQŔ.35܁ 6:m>9w :y+RJkVk $yᨯ>Zw&-Lkgt6YײjľԸ~No;g쾶?q ݅'W=NvMqലj>uٹߝw1w7no~7#ߐ&7k:si&~}ƕ}ڻzC=:MG>J\{3sN"Dyuį+ѽwյ4nYnu>zsޝ ;{WlWc_ֳ%YǚZlԥI7Xk ζ$5-}˶$V-~\m.t6,Ͽ gX5%'~LQ:'QM'pOs߀-6(IS~E/6Ov> 6؎,ZStMeU-BԿYk(.=^+ ٓkenN9DM ld];Y۳uIeCĖwwȦpdoc6iDɽɜascEaT'sj\Mg܅44Zj_вd`7} uht5zh|uqy٭n5&/O'ղb;OU厭?^a;yeX(d`~ANVҹԘP*qSח쉸ü=SbK<&ΐY3>kXٵ3rfo2W|}g&َ܁ՕLNo885=[?Thy="no\\^ g>0|]'^;2'X\&%AFg EEk|ۢ}cp_}9ؘ};=-j^g8yw)!ʋD[*1r=>8m}_J4M+/wnrY 4)J(lHHb76xD?m9NKBJ#PE=7Յd,Jd6G؍L3cj]ˇ+2t~푷)f5w~ endstream endobj 257 0 obj << /Type /FontDescriptor /FontName /TPSLVS+SFSS0700 /Flags 4 /FontBBox [-225 -320 1645 923] /Ascent 700 /CapHeight 692 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/A) /FontFile 256 0 R >> endobj 258 0 obj << /Length1 726 /Length2 992 /Length3 0 /Length 1552 /Filter /FlateDecode >> stream xmR{8Ty& ]EįK3qK S3hМsf͜3ΜqƢ۪G)]T"٤I&v D7ՊG%) zy}~~ﳛ12 "4Ƣ*<iL&Q1 Dh.Cq1 J1Z))}bdH\P8@r@%THR%!ʌ%1Ja(I-dOx$29|FU~2Vd)_GR t -[,b ٘QL $e(Dcp9 BGNhTI淜 V3C7zQ7?ٕ\bOۆaש]FkBdDLk3n>]tl*'̥;e++ƂS vo洛hpnqcR4(RX2g@s>q ok8ּWꞂOx}p϶ m\~)|4q`|7˶Y}l%u%ydGz w3=R%x;[寲UAStҭ _,+kَxDnT؛F,֜c+$i'Lq99\ܧ WV)(˿|j/P͔mʷX.:LI҃V|Ӧ=v-gOl~I疐S3^3[·l-H#6^>IXlV:nКl:UOi6ͨNȽaY6L'^fۚ]XsEn oN5m6ҵ;FF[iܻq]I˪Tiz qn8r?WN,ucw6cK?Ldf?UHG[j73Sۯql8ncIcxZxzeqeER^cxy݅z+ 9E055/_S(kuqg~؅Iwȭҿ"z>VokSD#RH#Ofmi|`ikY_I/lPz5  u2Ӧm㾘n!i-}0>A6ֻ{#p±kds,D3䳢7.h=~]fh%\d|K̊kz. "ŕ~틛}@$IMs=e_tl|Q/ѱ%Е?@r'{l(/Z"yZ+m+pӃ{9 Ձ:>ghq> endobj 260 0 obj << /Length1 726 /Length2 11579 /Length3 0 /Length 12178 /Filter /FlateDecode >> stream xmuspݲulŶm۶mv2d‰mNlgbw{9W]{;ػz9113rTUT,0dd"fFVFf 3S#CqprtPPmL쬜V&^wwwAw7zg7~Tfs+[3RB^ afold Pt32ZٻQN&VB{w3g׿̝rbB 1U)@Vq{Wl3uG podkΞaV&c3 +{&eo`7l_A.(zH053v73P899L͜*F.q2K__3-oETF}0pL})j`oW DhML-* 5r6/OY+1Y)rFVF㿾Dzvcӱ03X9Y\L~\7gg3{\fm':5_x Xآ-Qo6d5 ضE^;+-ڞxqK4y{ka#DBB0$kEդL6Y2A8&+稒3-TaZ_px2zygHh {ǃb5B[e_ԙr<-5 LxGMhdEi%Paxo~/1hswK4WPZr,*}6A#B uaгM)uǁ,!y-ME` oQ/ʾ•Z#ެdP0GG_9_d $(; .wlX{x|03ffHr-5&h"M`v![Toqg 3k% ctY}N^M]JkՃMA<.Wgư:+Pإ:p_=Z2NLiڬѫ#$;ҩ'q[@%7;<{ x)&½-޷?R:Eh`< Yߢh_SaAu 3e[xp' D4$)>0@oDv'bN1]YҺ*8/[Eka^_T#/C4W3t-XAwVfd5]6NH2ېM}7sqֶ2$L˹B#D'ZDt0nŗɝ'ew;;ڸ[b"a|iN&W Hd,)hcŕn, FEnGm:m)B4?I̩/nTf2|C)-hqckiyfOTFZO22"=ܽÎZ]8Y!_#1YnߦoXKJBUO1ZAo򓟄"|$.$3~Ja͉jDܳS,W$9˓O^szqri`ts %BHNV,@,@9/ 1|5, gzk ]#R =0Ϛ+ڝaI?\`i]x˲݇4 8jME N˕2z2k 1`I|ܬߨ>#7ς(]v 9D*R<>2I>Z'PErc;t4)\ܜa1ZgotF&| ` Xe4LNtձr1H_SK4BL"b:;O~*KDmN s@*q^cףgse6NimW@sƏ3e ju3P~-+D.5s);xQW6{0VY~%+B3tT:j]0XI|O, W@)_[cx`;.8e;;-+&e5**{f2uΦ$쉪XFdH _v5+\*?`ܷfc":7K\?30^QRInD]/xTW[AU>kg~uS/y8Z,ǯ88'ўTËٟ P>!ߣ=zsY㣹QbS0E u;4CDsQ 5%ՕkM1{1ݷQxT*a9&i)q{{ӿgԃȸvHHv>+Ru\1Äf^"RYX:cS;=h-?;2-g,t$H8|$5SҌ~ϵ *<~3I=aFLr%1gPaۯg-xlb]2ehD_w}T뫥NtԯJ/ؒQY3ڪ^Gn'S$TJK@JEIǵܷ+MSǸ2֊,B{Y=j`05jP'mJf1Kɥ؈ç61dENOA MͽnU9_'iy—Z+iFY3ԗ.7=jPG;#ácTxQ=5&VB`eKtP fq۠_GF07#mbzV*3];5!QE8Ha=̯ⱶ#4._jn.v|5]Ұ1jo %е0҄H^Q~yf/@BEf͒mVP̒,(9Bj$I8kڔiāa2]*eY%vzzdkSqr^ i-cKSw0(Vv~D5fwnGsk*TM+DCj.έ+][_ƌC Y?S5.o|K [S+"+ZJוQ1˞ iC lyn?.HO v|6Za(spi9G{չ2MM]}u9y/inFꏕiKkt"'p9[!#KaX4s|;E,.!R^Kr`${v5nY4•"fP1aK+Y/7=4E37ߦ(]h?%JnU*o&,FBo|7aOﲿ{+&`^ H,&PȀGe5~P)CE'Dtyqs&e9åj\4j][-Nǧd uqJCSRNo^nmioJ4K`7ud{2xN] eZp<E04B`~OǓ"Zz|z)~LZ4fFhNmo4[9dok^{/0J2* .xU b$4N8WYgFZK$8c!"-dm.Әyܣ ᱷCQ+{<%?L͓65AGl]Mi.Ignhs;rDž& p&&00 .Q7:RN PEjXv܍@4hJH!f4 5Xw~ʑ *$p 0ZtNo5*YbU5_$`Z ,\ض W [Kp87Ev_<-&sIϡ/7X e!^3si^?JQ|jjW^0#$ w/s syHa %2 Kgj+$>sǕEgNX~8Hn(b0Vm^J1_jX26Y)<[.cea`gGЄsE&i 5^@aĶ!Ib%4(,j#`"9:ApTbeu@DAn[jhڤь=/TZ%Yr_"%q`*J %]8m~ZU眻e*ˍYBanɒe )Pt:ᩋɕ>L>OڋڻLA-ebIf(.s>GC^A#Gz a ďiU+Qf7-Foa8H%!5i=h!|ۤg|LKߙtU*+dc5mTݪ4omHfH{. >*ɋTKEpugMy& NL"~9U(xZx1:ۦZ%{ij^M 6Lٴ⅞KRL7@\ vJfjq זrknZ~-vas040$(B^7f3> v"Z&L4v~f}#>AM7M]M%h!.sHzXSP%8sEZlpo\Ht&)áW{{> NkdT{Ͼxn2NuXn*3}QJrrFyfNۿԜqa9̳ U Dg=[Eg*\":/U\^ hL-9!.f;*/P+;LxC7KӪkCևl)MY|#zCEV_f{`܍ OvߨS}v2Oc:[q*B_9Y?@I\h5Y !xX&W| 1up伜"jtu`+r~S1 Sݕ]!gY_-I4bdìtBw'D0!j1џH`kcZ5V|| 'V h\ ~_6|;aD;r(8fDw]\,3L,Ěi@N'p^Org8U4Ru3w=o0 COuDƃO~7#IG h C^G[ *%D5VTЈ+mm̵6YβX`j1 Bwhz,K B%jTA Zb) )}P=;3|aC'3LbHhiAU\kV E戇$Ԡk~QρFF9?^cR`vB L)j1(¼)s*; l."-O눙/Tu:|"­{(LRYvUO雏fNKEHy󆰝˾з,yg&C ϖ4a@L j5~&o?Pds5Ϯ6aL4ݯl/>RG}SFWAf ;˅z`BMtUǔa}5DWtb1$JiVyFr{-^ RT ؉,hfG IJDzGbDϴԻ$JɷGRH(ڶ<Ñmy!: M-] 0ͱsøsa\-+L6I>~cȍsi }L{DY$D̖no&^&=|ޗ&},OL?x"=0|=si8Ẋ׹8$^],]5t8}Ѓ3o[no`fh@UMMv\2u[l$k?GtwlP ⻔-0{V{o-.H#WQNR^p!} eXI)JZOP&"icQ씃@FӮSw(Da/HdBL[{e4eFͅֆ#梱4ᬚ 5OX)‚܊xQa / k.̥N `IPt=<5Y皌.pE GN ?(rc⟉lZE9NknZMwceVÊRQ q׏ xj>-Tɿ%Ը ,*SSX?sĺ~ưZE[%-O*pw_eᮏ;ZޖPHp.7ԏ 5/{Yo}@hvc$Iem%~63t*|ct-ng{\LHֆ%vI]r%ӸB 5$BZa,Z~LDl~G(\(OeK="W}^fNW1\dAy3MU&RRF@L/NG6.MDDMJը m.:cEFڇfvo:we t^+Uq7м;&>l7C7*w cv-"5 oAМaAi"YFg"~{9[)1>6ZݬdH+hc:/mwbԍYo,U `k|8; SzЋ Z>@R]Wz df`ܶB{2ؿ:kZF守'&aVq\ p8]8Ȣv%{"+Stn&@SOk^jl'V7AW~sW$ ?7K(ל:*cH@~ 2D =U!3P؇=EՖ_UH(jdKEC!(SP{t ӱ|Ʀgc'MQq}tQ\b±dqQ} q fx2sBiΓ׫f%dr"qp?SotI/e^KY. ,'8 pN {Ыx'[>A(XB\q]WZj@,B2ͧd6 2*f3`70<`~k1 סTNߏ3 UzbNyΣl[f;Aa0eDT>X%t MU϶lvT`n`uN{WpGT-d .K ;Z:x8}nT_M2"`7xsK]=~2|`Fj#a*5'Hs鮆.syDoq6v7Q{jA0 kW"RLR`y1Հ=ZHcU^iiP&0nY?"}4$>j%N1}`M;vޏhKo>1ad2p QxP7({û{E ̹ū\K,߉4Jj&Ɂl'pTf= m$y5xh PH ?ӏGo{; `kDxt$߶TuYk즉>h1Y;"\YwZnrJ=NDr,hLcM24JjUZQ5yY}LNL~g9|ڴD`q</](GJ- 3#>b#>ϛo}6VoٸGa)e Bw?m :ZF<~8G?YU endstream endobj 261 0 obj << /Type /FontDescriptor /FontName /BYMUCY+SFSS1000 /Flags 4 /FontBBox [-201 -321 1483 901] /Ascent 722 /CapHeight 694 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/C/E/L/O/Q/T/V/X/a/acircumflex/agrave/b/c/colon/comma/d/e/eacute/egrave/f/ffi/fi/g/h/i/icircumflex/l/m/n/o/oe/p/parenleft/parenright/period/q/quoteright/r/s/t/u/v/x/y) /FontFile 260 0 R >> endobj 262 0 obj << /Length1 726 /Length2 16919 /Length3 0 /Length 17529 /Filter /FlateDecode >> stream xlctfQ-NGOұmv:۶m[wl۶m=;1T͚kԬjdvΪ@&:&zFn #Lhlag+j hM*@{3 bghaf 4P64pY۹Zx]]]]\]R@5 %%/WHmE#k c1 H0sXw05/MN` tt' '*$ aPښd%uv;9t 7211L,F@3 [8M߰ r@C* Zwq:LC[8ZRΆ5gCN@E ~Z?/GhbbLw&vYӐADQ]\N?e1[c; [3?C MOYWJ_.ghaa"scӱ03X98\>.@[oM@;nmΘ'29WhTج%^w >h5Ժ闭DgfJ-.IҔ[xAi׊_RY?G8i0〳rghR)>ɻ mb]җbA~^ne*c)1WdXWF%V}A fg!@m -+LȞa#Lj瑩)1*?vjzxHMQv /%ԝJ[?`M68.pND=({ C\n Vyx3mvڇ͂*&B_!p>  ~a^(T;ϱMM܀(e9r?NR&NI!dUЗ\CoY.l 5Pt0uGotRS/ pPHJt^<[_3v1іb{. @k+x+zuC e9YA|=Zj2]5m$R[cMa>74tyT^ݷǔZ>[ LCT$S;1/8ptOglZꆪϽN.mnNh"x,vCj럞{< }ؿBV2jI$40Ύ0+&SV2>QZ >M|^N?>poWyv>:fl=)Z$r&tܓVEgiɀW1'riƚ.nn7__}SFfɋ=n'X9 y`096R#`F@}nVa׃v=xfRKƞ+Yd!VCthANr$wf3fYO~/=:l}q_pc6Շcji%ДKHRu#ۋ'vx?n]v_ieÿ:@n~fN)bI8 6},,|ǻl +@Wy/tNJGu+zcWt %ҏd X~)Ҍ\ьRϩN[ƱgA >QJ"_J{sqpߝe,âQøKϳstdMYWv3/ 5;l>̓<:s뤡|/"0)N-Dt 83:; }U9mJmuMF.vh8lV>EBA5[ $*y|TYNwf5_%WJQi6A6x ܊h|d̓=7 '0@Ҟ݈I']ʴ $ w! |uSdooD\i/gO 9ooheL5M)ֺ !p8+n m߇i{q/2OzJ[(!kPwz!j?4G;%$ڭ> ~5XN|7k_rv0x;ؙ-=7{^㺼ʙo;y-b-S:Qj hE7ä;6w̭'pނ{#j(ъA99o)+_`aE㌋{^{xT=}Fb+c}"fQiZl.c@ׅ0̎eOKظAɶ\o 끓L* ؼڍgK&kt/]_ x[ĶИq|su! b]d%s %^rsW #9r -'J;i:|2$r]y$悅Abʫ>KF6w9H\ֵ^l+m`@0.Kq@|9jWz^ 6=0BIKҲ{FCoaw 20ЊKZ9+Z4?Gs<̅]"ٳ_BI/3?)W< 9$GGDr9y$.9y?Pե:o3r=+CQ)'TԞtkJ n[Ϻf2N=Z$=6{VuJ7IŽ⏍A;veCDS&VuS=if#|CWxe{2<7Y.oN/;7\^ƛ.6K厷!ݠ df5cšl!}?Ds_ |XBq6gX9 vbگf{d|i']nE~=.<9#A-Xfv<|ƹ͖6a4i s\!k;`ztw$G J~ Es!ρ$%j o xl1fO)Z0jҝKrrA0gbV(p(f޵P]3"o 8(rgjI)D6 G9׸taHG; . x^zBw7ܴ%=ClCk֢_e4׏Kg ڄ/ =sour{aюR1/obD{Dd#AD%OAV'8TnNu&wgKS%/OElMԬS m++,e]vƾO$TyOMs <ͪtv~N4];.VM/iQ#*P7ƕgW9e vHl^A5] н;B?< 8y eU['ץh3Жr= (/W>ϑ4'dmQ}4 +d6Dzk(dS^:_U,sxKOb\Lǒ0!2ؠ&Ǧ/d !x!$W&=4DIgaI,=A%a<ܮr-n=X'maY,A}}KNsHgGL6[^޶_nJB]& |45 < A;5~zdLv=e6'vlCNFp2}"MHHF`0]%Cg,ִT/ֿ3aK`!K="Wv>M `/kyi=~쓯#F7;yt|֧183`1@$@&N( !)n8 eַ`ڴE;;=u$Fܗa85_ rƍ*ZʦVaEHԿ{|M{2/)U vk`3vZRvwz[L؃ HG6՘,/1a|8Hh7`;__ OZ/B^x׽wOǶښ ^Zx+V*y|dTu}!occ^. Ԏ9X#]"lZD<{(^:Uɸԙm*["7!%" VB?`j0FX$eo;DؾqzO'ݒ),a><›7@P1m D76F&jәZ4ȩYi2PQAAC{)DD' L =ൂ%Vt(m^kVow:'\:{;. RD L(eWɾΖ4R.3f 5z"+ɗ; Hė%Lе<{ٻtקoΏ '(`){Mhܭ1a2WE?3QxM~RY> Tˇ];lC46A9)3R4tח!Bxc[nz2dJdK&[ k Qс^=94[z| !%Xpч\hx3ڋgϞ^h΅+7ӻ) ixc j=VIVb3`XDQ9ICӰa Q6ì_sh*$<{Z=WՐ4sS-gY%dPw&<01LYs5]r.>SYն, RWSV`K $X+βn> y$L?eR*:8ezu6~8o7U|unO ;9 Yfq{^Ɉ)Lu:9V4bsUiuFQCo $WXLқ標wRtH"lIO,Ϊ۟BHlnt Hŏ'8j+ִ\Ehn z;U@qÛ5tSu"+C7IJ=nϦyC_p}>Yqx"ƫ,ꞙ k<7JozܫP*؃Ȏ,˪u 2RuG;)fB4.~l4Av%g^&ˀ"v 5P!G:0@D3^D-P4AAdv?ԟ*:j(]$%+\oMa~fr?}5BFؽlRw^SSh6?y6`()5 :;D;Ӫ&Y%$'O\ oUв9"sxFO` *QԦ'ba9288B+k@݉aE& Y^_#gV-Dud_蘜%y+(#N|.5ic g9WmaȵXM}Ptd5RAv+?B_qӜl .2 kU-2d.k }XmG׊=: jS uPU~:pn~RQ|n0C {ϷI\x@dRg.Jwza0 qXj̙cj<tMNuB@lz;\VK<&%b[t^[W˙6oF6C]SDkoVi2Wo|{J.aJ:*o,Pn):uC5sC~EG8_fW1_]:{, dH;Eu%`eHi '`Ѳ7Ig UHp)1actg/6΀,؉'̆,lr0fX[P;xd؄\13;ʲ܈+xx|?ޫ?~EIqYcCvU#I1gu~ :q_ ʹw%kAQXL"7( e2 eoDR8]݊0CZh!۟4~V𧾾{g)yU ֧{.p #pHzwK}XsS<6USQ$OszX6 Jvb,RjꪘQf5 CX !;z !zGf1!6qȽV*ĿHxL5KY5h NgPhþj.дRFb-7)+nJyKaqyܚ /wt+țO!>+#v%*r >j~"_FO_bY74=U F^fyMrFM_M-uj+ RPޡR-/l8|$^py|)FM^ՄTld1a'zjK +x{l>9x)˕\˩kbL3‰QI#ʨY2?F(8c3]#T6Y V޸k=?MaWy*R[r6Ͷ?dʓ׆H)2Z\?okbF;j[7NJno_\X}`UΑAcb?9 E;_)o :?:7'` RDkQ2 QE[hB[Jbwr@XF|2Ǵd d/Ԉo9vy̑s7{\@g8KJ\ O:I;h/ zOф;ϼywUK.wAz,dmD|72xYwHI^F ?kL|Rl:]zUU73?wц귇g4UKv h ־xS)d>yְ~IJ yfZSv%C_fdVf*u_,~׹'$wGu_'( 1NUl,L~&!-%ZsxKyG<)~Ps)M7+AḍmYpNqᇩWTP} s˵Wf¸3V L1G1z$H8~]sC| =,b&iwk)T?d ?M h udkg\_54l6$.b- 4J}UW7[)nMOWk1sg? n8!Ba%Wq F.g#(lbLK8BiQ SȅD`e}΄<*^mDÇcuzU1{?y=PIx $uv V9@~@.@˃ ^HheX3y/q)ʴ*Bs/}ӿvu8Ug3wna 9Ȅ xDA}: M _@1zfuq^.15PLo8w$>T3EPB6uF}-ڥke$x쓨W"gzLk!n?n+sE)~Mj`XNl長Q,!# x8Z M'z~<or,3TY>~*A5raB -8c*Pthe G Fwum7!oA)%rdn#rh 3H.4NcZwq\jK0^簚0蹹)W^@aK]?<+_>)a1UB`r< 1g\|/{ws΃dݗ3IF{ ;u\Z3왢 G d.Bސ/ iaa' LU틵ьPU*Ǒ8fXe}|cc >|N!1U8yԗ>h/zLgʉ"rg (#A76K4As )s ".YӁj `Ą>V,Y8@@Y4ggݰ q2Xjv}5.$%qʃN1QJ>+jT;G׊WKy[c S (%LRn#I a \pE)frjJsxڤƼiLc;h-,, PEw㨚c]>/3VlGK]C7q h5+5شĦJ;}"N=>}Rwx]WŪ|\ $8bS3fbe9_\nkB5[Lhy6NZFϵ|J׮b&bp37a";Nz j6=Rp80 "%.76rZ ޤT7l18UWKAܤ1q*j7x+)>cAg1_U&eyȒK!l'1BB3=3npM؏0>ghS/2. =lU1u2B*!䋬:e_IhlgkV'j0=meޡa-:/G=SqZŇJI=b޼G ZeVkLm:j^n)a.{_bAKG;!lՉHlThd[:<+"g{`ę|1s*YbqϵleaF̍Ͻݩ+`HaCrQҀmnǯ~Jfy߯Y:aH^J=O1T' ~X|%ľfn2Žr/MUGyRؑmlB$`;HEAQsc6u)`4;_a-Qp}J5fL.$Wm]q j ;{,&=O.Kh0/E<+^Jn"{_Zx16l1T{`CwHc4{ -[dpi#cȆ4y2@KlcIJ1_3\EdDU5H> _[hXswj%G޷&֤ ῿AXb'b;߀#KQmTnEʇR8TK(3@穣K]I .tdzØm""(`cf*"}K;_QOf3to qɓ0M~ "#9K'[XZcHE{׍^B,(nei4Z7uC7֜vxG+K9 p17mASp?Wi"w&xEoy|v˨Y՘"j>fDm8C?8z ?^ʙVPg ^?5@ a[3ջS[ _ ~'3v>_3rTi.ӮpB6wx!:ͥKM<7~Guy.Y l ck+/~!ǚ[/ўjLH "6{E*Apa{4yYqK,>}bΨ6x61UB/V^f43*)2E?TPam nNeoLۻ 딙`$>IIQ? c9uK8h/[F$ΰQ[a>3<0ˡBp f]0XڇBizb8MI?d ܏y{2M-/44ϑm =me4T56wICh"LJ_S<֌n ܯӨqWG B|=@le ,VK--eh{[ 7K( ]jM5wefӅoaj?>?Zs_T^ά&٭8$Ն"~m{Gw8Ϛ+r1T?\ֻݒ儹#j"#'`]hp5Eh-$2#P,v0.29?yAho^1_1rjLma):W7̃BCΙm5;f1!T^Z7r<rZ4B \MrɊyuk蠪}w yeMͱc1FTjWiب^[xn}ķk , {6~}_}}y3+yT:=64qR$h]-7h9;}-ݓ~^eص=* olLQ /=c{3NƐ4,8];TJ4 ,/.u G߱X' $vh߼u^DR0jzG^c,z1(~޹B'}9 ֚OC8m )x޳h(cY "`Ƨ #=tSofZh臺mixA&5cv?]D)[CNcℸjXvgLWSg@gG*v8PUtv. ϫ0qo J(|̧wkTRAvZ=j Tit % vkNky&4)]$жyvU?htix O&~d5 7ds) nhnޯ}.bڄjXOV9}ue]2ږ()BC]1<ՅfSCj_OdtP2О?$c,y Y `\S%L[Α٠óWs<֨=}Âo l=I B'}:f~䰆't`B^rP:2*7y8$#ъ(A-}wfAGNI`(wN}0d˴[!G3GȀAHyq3FGFyL0֘C-ЀjHεC K=gfYmh#OG®74ul{$DxK|4fɟA/aNCNP0E{Ɨ?3Ӑj>KtGg*Ex{Oܒ=)k@I(,;]neow3hFm2I5JNw̓:]qzeBLx!="PmB=>\=qEd2FxJg/< NHu괧 nέ0 [,‡!{#"K/ ]궙!yL[qEe2̖DzŭwRnsQQ.<ƄW"'άD"lPPR*a"%&?@QwS$ko@;]s4򭙇d`w,mg]n_ SZVoi`T. fC_B4 #cխXLr}Tc4Զ8g]kL}qȒl6ι$u[HOq  =B`\)tG [$lu< h/oRĊDh׊jQ WW7g"]ę∪u qa,M)E'5r$#*帜شHz៦h-fhBj,! :!<+!οFF Pe=f( |NZYr<+(n/Jb0H{{$3-P"EoDā3-eOUkЏ>W6]3'0>uQrqY\t`)@wkZD_v3 Ҡfq5W##Ӈ+.Z_<*~1 T,Gt'.)"Hi=ʁ>9+)g}O%d}>1ճ7 \[tH#t5 G-բ1 D噷*:{_MM|Bh=q_,FMZGw*JFL$ TכD#p8~ԛe\'U+Oe7_%J+ǂ=cp/ ht0, %!@IԹ}\R, <3]f Fꋭ^7K:;I{RIWq,f1)mŮgDӵ!ݕ}MSė\R *6,얜*HޏN{GGAu7L%q7Ƕ( Iiav,f;E =-5[<5[1>x N1UIZ8zÉNKK#%zbm 0wxSG9'\,]JH6𞡷꭛. OFz[o\l?ɨR.'& opcJ7K&bQj ^꘢1y͞U\M:V2iVPK2ElU[Z ЯкkP[PHFYfeEÃLgQnH*D3l?3/Fa0݅Zm2JLCvsĹ uǥ5'+tKlFEDS[.Ga @X25|#,, iΑU>7Wr\ gZgY6rfzmeE #&S>2QU7ΎWXݞC)w#Qsb# IeY􀣮0)dJu8lK8R}Ȟ@ڳMR_;eeO1(qCi)m3=%ta;l<չRj2 endstream endobj 263 0 obj << /Type /FontDescriptor /FontName /CPVFMJ+SFSS1095 /Flags 4 /FontBBox [-201 -321 1477 898] /Ascent 730 /CapHeight 694 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/A/B/C/D/E/Eacute/F/G/H/I/Icircumflex/J/K/L/M/N/O/P/R/S/T/U/V/W/X/Z/a/acircumflex/agrave/ampersand/b/c/colon/comma/d/e/eacute/ecircumflex/egrave/emdash/endash/f/ff/fi/g/h/hyphen/i/j/k/l/m/n/nine/o/p/parenleft/parenright/period/q/question/quoteright/r/s/seven/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 262 0 R >> endobj 264 0 obj << /Length1 726 /Length2 6264 /Length3 0 /Length 6865 /Filter /FlateDecode >> stream xmweTZ6Ȉ2t7 ")00103tHJt#%(1)]Hw˽]Z:v<{g?gsaeRq{Bxx%@z*zz ~^! +" vnP ҃A +H ;2tC`0$f $!rEA WP R1QRqjTp(qqق4`P8 sAq@.p/N(޿ =H{bvHg>HYO_C@n({4 ,'Y?/P@ٺl08/v. wSP@r P{ Ptqvuw"A.(Q avB0'/jn{1T`^P^o;ӽNǍ&swz/B\N}/oȧfVۺ@`p{۽`$i0̿#?_솄yyֿ\|yğx@"" 1q; }/ONOJ:ՅV.Q S>^Sh nTSgs*'3% dp^8.1G0njd'vmFqh^+K>aTx~e%g,gM};/|=>NŰI(!e$R;6ݩEJ!"o$;Ar۸zlw[ʜA.1?ph:|&w~qjK _ 4lӳbہ~J=oB'ђkR΋=!iaWY?MkmkfEm4rhJfYF0!!FK;ab1{j3þ.=/ [za$^J;l+EGJy>>n`0&±O(κsS_ )y%OؔUUI 5O_{V%u2Y`Ԭᵟ2xzĞ5A>? Jl㚖Y]P^G9r\VGXnW}e;H{9C{h8}3 8̊6%xHtwKBHL;𖁏YPkϪ 궬z|+,uGbXIq,G-̄lMH#wԛ*MF='Rx9U&yraݶ}:{{,%c@s7˧>1-x߲X0<]~¶bY3&RpfUl5c.X}xA+5-*h^F${XMMzk&z.=]%l햘;F]2* ş.\;+v7mJ2Wt5;kY'oߗ͠)0da9TToeXk=v[|`F4Q Zh`8mTˮpNxڒOX1wE77}A݌VDJOfXzɰ'>aOcroh%g"RB~>r>Xai9om~3s8XX%M*\Zj aIv͒ O^bܧ5tݴW3fe Fe, rE<;,arvmH ,R Qxj_jx zǁ2E,UL$ވY#-ScDɑΩuMԖ~Ȏ>$Uq޸Q ($YkM=)y~aK!p`W7UR6n,Th>j nXrkjXr"fobOrIW)|=X>]uvpfo_@OaAA+e<UlC P# 7!eQ6fIko_r֪*fl;f[ 3|*sߨ-SAҽCNG~n)tSVKњ(q5yj+/aF:>!ތjlLJMU)Mw"56O11As#wx$CGm3e샙zE!f,q!ˑg[5ӭ- zTuc+Я l {Gw4>6TsБsT>{"Y\쏍qD#MV-=Iy1?C_C֡!^Ϋ O5ʈnJ+aӻL,{eĊkǕ9eqK\ J9M5ЭZ/Uw|R_p/JvG)*{0ɜiD[sOa91q;i)9U/M{!1HA|9y\ `,Wk) O. ꦡ12 ň̫y`8TԂPmlW=`J# nf"ֽ*L}%4V'^IJ{.:e\5{Au,1AR5q37MģnƑ4.:׺}ˍz9횧 ›%Rgm}G~:tXr:i|YrSne,IɈ %84ɮ`P I/S+jpEچ}erUeN:nTQuşҗzm GU!Xyr~`T{a(hG .K9Gr ]t.|mfU5@bёmlgõMq6L+3QH21;1U +%nwՙ9>b>Ny=_cYgJ;sR~Ti+=+w5@'u` )Z ؕ냄1M!$=%2}rt;+TJ}'TI}=0ق$Of[+-oxCjCl A{E۫UTEկ[QIE @cA֢*MoRT93`Dmy s<@p]p$-3q[/Wy)O_M?6Sl^g>r—Z΢-'ȫO}*J"⑗Lr=[am4.[Y1>uخO<.5dAFS \Jq %u@W1۳Uֱ}'``~ YJqsYg-ؠ ֬/_kDfǖ q+¤/o* ?5 eHl 8B8ڐ^@7wq}GxgD.ޜ )a%ĈSlB-5vïm\xțfV+V&GY˦6x50@b^n/$٧xҿEr nu@3 Oқ= &!ȰwNE%7cyT8ĕT{hä9-l Ϗ%F ;6nvG }~u,GNr+dė`#y*Om[H,&hӊl[p"zI/KԧvqWYdOXN65LK‚$m-6XW:ͮ%&PDbElؼG%dhv)uCX#綉 G,!h׷--1վ*l09Q[N7:$Tx"z+h%^iR#}D#F]ņ٢Ɗ|Z:ѭBdlC%dZO"X]NlR֛V0?A dp2[NҌL[g,JטL@Ŷ~VQG@:G a@$6@m-\7zXWC%@`PH+ guNՓVӵnQyZfo2˞oF-gBd}y,_KWKky'0/5U)( ҧ``.΋G5~'(rSәc'2:о$ L{(4X} *h*Nx:Yla*!!R$#IX)3HbfĎ@в/Iļ[q-bGđׂ9Eѡ܃F(/]ύyruݶqZ Z 8r4 I=7LˆFd)W_ln}矏*P @up mp\8سeS- e uxtJQMst}j FBj:3v (>=f6]|btWmBE:`wx>T3JKuŰ|, 3PϬi &QM!R9R-8/P+NLPGD}iőUޞD*hdyn$;3bUilvuoط" 'j}["i_.ao_q}~6[]Q Uɪfѹr+[ɓN1; 'ԙJV|U#xI \?Y.AIOzk~TZ!؜j6Gja)>yXngjT8͗j R'TpuGc6;+10?$_+\~.U.gYN ";#py:!mw_*P 3g`'ſ3vSyn ѣ%~Eû+ߏ!Dc7=j{Hh Ua<͍PTxh!`1- x.RJѻ.c]ZzA<^;>3SR5c6:k8։oʣ0#E*W'ߓ9<0YjB*\3)KJ+H5o 78808a4RIpt*`GQ%]F2拎WJ47FN$r 1~*ݻ%c{&Y+^]y/d_K|h2{?CH̓$9} Lm Q:[/#KO:6_Y[!1 endstream endobj 265 0 obj << /Type /FontDescriptor /FontName /DIVGNO+SFSS1200 /Flags 4 /FontBBox [-197 -321 1455 895] /Ascent 729 /CapHeight 694 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/C/K/W/a/c/d/e/h/k/o/r/s/t/u/y) /FontFile 264 0 R >> endobj 266 0 obj << /Length1 726 /Length2 9204 /Length3 0 /Length 9805 /Filter /FlateDecode >> stream xmvePݲ55N]w]Asӽzukwճ騤^ NVN6!:'Ndj s:DH88z9[[Z͘Zv&-;wk3+(&ujXXہ*JFi%M4 r6Y@```6&AήY8;%5>K)+i$%5$&`sv_6_ӱ\ٙ72oߪ#6NN+di Fao` ߿as7 rC&9/N`pwts9A` #[yːu5kg_8 YHY{U]mabקpmп/Gdnf~_S^;?kj+2w )K̭u׿8bbrEWgkO>ۿv_"c;xr X8܂NG3gO6@ 3e3P ɢJ▭J} ݨ!?J ޙ`ME%1)>Kim㼓D?˳YBL ?Qiufa@oXZ)~3-*a~Ǖb B{@gQıԔ :8 ӡ~`b$в4 'pD ߛa69 ='$T렙i4En&8WC뾪>1E5꺀mywb߼ccpaXuJHfv0zeHeD#'_Ev7cecmj9^D( scrcuC._ץ7jSlϵRXgFLBim gRԏ0:MHbZvV=nJOG[!Zk1//VZJ׃"񔋵nX X`dVb'fO!Dv^æ 慆;IMHԓmwo7z QQ'Bd\*n10b:9񖬏[6idskaS̻IBL&!O9^Qdp;Z`J.;ίbXL轉WT.W8;'4 B"<>龵}]?myܩx͌b98>1QPDO6`atհab yW +iBVLE2 EKd$ui^}FfpFUҁ̢ryZQSuiP: UH;qJ\(y~,?L金^ͶHٜ YǏE.O(X$E zWKL`+)\,;BśE{ 3|=6Hꓭ~w(y5Rm6gqaCYshb7mPIDT\dYKoQR*k ʀ썌T5 #@Wiy:84;nnĒM9Ϋӂ)uu-La2`?O~5BSpP鮣< C"U%O#*!I1js|/M~y\+fH4бlg odUY= q? HS_&~K8*n83qC9o9m\E`lȱ ቨxBgA (4b36;(bc։'AG!'D0/4*T!<zt󗝢l}T!q2h/L$?2E}j<>#^&F!U1Y'*c'x#,5I}.Y_0-6Is5ʰ+%VέGlaoMбZe+9yKZ?])giybI2Z$&0'y 0 .730]nb@*n?'}sgy "Jмʍ|LԾ'},Cy({$OjSb[Dэ"Ɯ_d5Ir}Gf;%. ٧0{?ws'iy+%輁rGeg1w8I*T9FHz@O'Msl%%Z /`SU6̑NWDhbڅQ`@M**Fٻv{x=I~9z&Lsk{x!L&E9IV;9Rv[[}qZ[Zbm7Q\V/b /ueu &CAG(}>V$*^TREЦC]p2"*:L A]\F^a QoIɚ`)Piߚ-iZt)Tⳝ9.vezRItg;2DuΓT+hpOg0 v;~X8$zg+|x%>[ދYsI*jTU0G2Ǻ*Z:A Oť7LZ#t|;*ey,F/Y;yWhj64)?F fĤm8P̞cn'.H;ܰO _1ԫ#mèa_51q^aHIh|Nw,>٧"9*}w.BՑb/ҍ-\y ThiJ;:sjvHzb4x)Ȯl6Ti~XyglNN,$D?Xr2Tޯn{;VwgS+KPٞp:9IP)bþ?blnzBZCWf+7E(gxYe~3~_7p@DA"ֱ`" :赴+ldH#3Xq6 MvIRwnp (2.Q/ylҢ+ǃE*ؤ&љwodu6H8`t$w`Wa",EW zME :JYQ|-WMr͍@8 GgoE6Β-* ji60y-쒆~&w iq(}]PSfGn D-w9Z| #d"V#KPjBztR&p.N(v$w rN\`ЀlK#&|p$Ԟ';p7ࣁk~~wUjy&mM$ǴT3|Je*G [6#3ёnp.HK%EZY$Ӟl>nOTK.v('vݢVQ[=%|aџ{4#m)\1@w{^BaQ<ﵢlr!PNOq`rOޅ$mUEd~pI4N)zH?G@y:*<Pbv, ")'4%)C𾛗cPHeA>$m 39(L>k=<Ԗ'^;txcItRݮFǁ .1- QR; O9 ~ZqW0^vNhLRl7:_OJUqlQZldS؟e %_oX!|>hz&۩)f~"\rR-Ejw&)Þ׸m~ERglK#ɩ^ԣ#ɽȊXk7!4TG'zw.%s?PRiR\L'IHv;Kzؼs;))ק U&8g^ 7XAO-S UY"}} H'R_4G|L uG 4[] ^Z 25E ,HAy[(|~owЅ~]bO[͟njk`64fhwvW+4O#ݶ, #-z*^3ؠJ+^vvF2DřfnV^/AXi;SDbэ5 NwLx8σ% jw+ tM!|tϝ0&X(q _J|nQ:S':QC *n&n=>S*L0Sѿbf.N2% WN:nl> H'[1uj-ZcZ L|[#3x@ %t[͵Ѳ{T993p}lkʘ &#\8 $b4N+X4?B|x$3ޗq|C2[dӫ(!R{D]K鋃"@pt=OTayRM n>oC[|Z_^eDEj虇u99k ?W~EX^E?vTNP9xz4͌& jJs6Ӳ*@"/zǧt @Q&g?h- _i? |󌸗1R 8B 0dGS1`-Ӏ^ phۃ# '3< Y(̃!uQ{a]*pl&Wb );^h}OXεKB.CQ>tMy [B4hCM_D,I)rMQcV"iT%GЙ kS"NśQP -{yvpX=3j|CTЬSkI)3tyE;XH.=K_,KȊ;aБ-2xz@'e63IҐ|ED: f?`cK'N2)=Oh8ՉP;,dAZ|+ 6@c0P8';n}X7ڻf*@1Ec'r'1= #S"PζˮEb}pH_6:gw:mA>pfX`woFiߴh$EϰTy~m2$ڟR[oX{L"`Z)D܃wkA 7T}!:p#%).CL73)5RumCx{ lZ{5d VJ/p/d`3ڭ%qw*g![A9K o0Y$!~1i$t׊,eyU^X YlUGߍ1$>X7P]ϋifakK-3T}Foۘj_;tkWQ'l5vLӹynכxlO\P=[ml(G>˃[<}RNɹ/a;6;XtL\^A5 h>6a!;X 1+r׶:k[C!Na^uH8䇥ȤU:`zjwsSH V|ioVJ$es!Zu>-dIم֙kUV"&I_joSCʔNg|;W@ ϴ/%D6?uZ3r˾Tٰ6{  PsZ*Q 4wZJj&_ގVWih38?oBqD1QLVjY4ba9ɗ.իyZX㽉?HzVʓzR=%C.wrbԠMCOmjq D^ ; nEΥ8Օ &T5wq#[C<RF6":HHe9WJd?{}LU\s<IN{o^Y]/yq V:3IP97zgXp/JwW,$A/DY'7H"V/d{\ Ӱ;]Mgny]~D@Z$wRq0֮dTUIնn&3,O{q'Ć,A"%o#PRH}?ic"f@ZTE#WCTXkbԒnZ4Dņ(/eZ3NݳVtsd LηqSbvL)qYar.9ǻ%*)E-Ãק[m! M )X%9(wҞ0TZk2;3TY rK` П65rqـ-$, \OI"9= |[#>_ˣ F,wc~'`,uS }n/Q^Rn\tSwB2lVz]9;?M2Xj<^:0@p2I@&YdgXTĻk幝kiyA%s+)#rܫ 6daQ`GՏOrGǹ 9Y 80,jz?s]DJ2M(zXDj3F2 <Ȓv6|eQ0š|pu~;,nVYhlS`UBx ]sfHs85\DZhYIѣ;,+a(U6lJ2'Y8[/㟮 Tar$OG~d3=K<<[nA`/Wx!d{W7ʫJg驡ӞLxm)-ψǢčHrzCf-Qהx]=_FEN/67K5j&mMl,͜ cjo:Y_,jڄ2bL|;OT J⼂ΰ܄5wd0\dx(+1Q F~~DF?Ngi$ ~C/9ۂ G }qzME]y;,nX֒ 2TY>ƏM>b0J-zǐw9ٛ ZFwSЩ<RAk>N$/7ɉ1{# !|pAm+Ґ$"w&"4lE˃V6 1*q% t6S] BI_O+O[LjVastzl='c2qYgy&$-gYf$xRmU4)8:q5]Ny9E)(ָiI$ *PaC4U[X𔾷@_6ñױw$֩iwF;M5rtAP z>rIc/::FŰ2Fkr(Qie;Lp9f rzA<ʓd1ڕD3ߎj endstream endobj 267 0 obj << /Type /FontDescriptor /FontName /UWKOJI+SFSS1440 /Flags 4 /FontBBox [-187 -320 1390 881] /Ascent 713 /CapHeight 685 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 433 /CharSet (/A/Agrave/C/L/M/N/P/S/T/U/a/b/c/colon/d/e/egrave/exclam/f/fi/five/four/g/h/hyphen/i/l/m/n/o/one/p/q/quoteright/r/s/slash/t/three/two/u/v/x/z) /FontFile 266 0 R >> endobj 268 0 obj << /Length1 726 /Length2 4597 /Length3 0 /Length 5192 /Filter /FlateDecode >> stream xmRg4j (a2(GE'eØaND-KGDeD!JM{9>9̊HZ uuub@~^Abvv9 C"-Pqԅ:@~~01;P聂آ\V Pn9P@}$ JJ:\xotP  @9M*J@.%@%(\,0+ pH'Z!ߚy @BQa(P]AOFQSC ǧ'@@j7 jv#ſѿU B`Vh% 75(8S|u!Z߰]p (K肆HZ oAZ8/ ō2@0gE;Cmm7n9PO?Ɣo p@>Cg4q{ +$o @A~,`N1\y?XHw/G, <>?r\P((]_"BZ= K )z7RG֦.FmnL,ScP*LK|`Y"[PM/*(go\_M=:¨UqE2֊#4ە/2f-=e;n|%{=;r+4]GI'&DS(۱Jʷo' ) )Q,gJon}c iz_|If6Bee(i},EM+jd +tw88f쳷Ji7=zr]s˞I9`?'v|:\ӜwfQazɷCPqQɨδ>S=n:?4`#Sbg8[~&G2Еh-'u9<7[-L7(]sL%,i%%!)UEw܎09AŽ; Z o˓ܓy~ӝ Pj뚠on1 #P/^%/^IށT)ZǠvR.|/\$}s ƭ΢Em@޵M3*_ TX/u0#'z6 I6G^Ȓ%J51ÿfg#]гE&1KZ{"0MdbԷXgv[傦O8c܌ǂx3jk։#llz0!w?2]7r\=88sӛ+K)bgތ]0W8\ ="CJˢ(#-VX ~*6/lBj[kT|ӧLo905?tl0ΫqN@jI0 [f_ W׈L>M<>1(da](c;`d>jwV2iq. dE,)$=.Li`m0Yi# }?`ypε%LqId}1=X^hwB=wχ/[%_gUDރ}NAԎA[w[V?J95>"!'ۡ@12&Ql9+ Ɠ{(_"Pʈ%zu NSe`M|ȓ㫃+3z~!9RN*߇>bEe5!z'[܁I jh۾+j0/1oWH7uY-z#dN;1ƃzFBt~ 1yHcy()Yzc>xĪ4pUpoo?-u0 Axh(rf!Y3(?Ŗi7't!о4az^a#3$;m);m2F6@kc8l9.VVϒOz=ژ?'?Wɓ)ka8ȱp F$ 4ýjӅ- +&2w.,ҵU*䟤q);u59a[^Z5}*e|˵M3l7q<aȯqP.`R]]!T/6&Pa G'lؗ:3w0R!B\=zZ.g,eN1h8H L-:3iL*5X\1 ҡƿ{к_H>B[ q{]bJ@s>3L;/Lca~BۡgY*ɓ?Kr76fa#8w#n8mw=fh f2Zl@1;Ri]%n[D㓦5Ol a;mpبI ;RH"ziD%<UKAɹQC3 Jև$etTu#d~x`gx9.fڽ[YUObgvG1Qr5[;;J^<@ꂬ ahG37יn rSYBXuݼ ai޹(&4# \+L3尢5 8!"\6Bkг:}|[D]Anm)ѫNlq(fFn3 tX-rɆi}gAXg8VJ;|yZ O{O`T8&9]-ݯU[oX_8Mʰt")&=y{aġ)eF*>y-м\[rK @]d-K0[Oz!L6k" q\&$j` endstream endobj 269 0 obj << /Type /FontDescriptor /FontName /XRKKOK+SFSS1728 /Flags 4 /FontBBox [-184 -318 1369 879] /Ascent 715 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/F/a/b/c/e/fi/g/i/n/o/r/u/v) /FontFile 268 0 R >> endobj 270 0 obj << /Length1 738 /Length2 21193 /Length3 0 /Length 21725 /Filter /FlateDecode >> stream xlsp&7lddsŶmvضm۶m۶Ms >H~a&4%d?]ʱf'y]*{r(_&WR>q䃚HI&h!Wsm4Zb5 .bVsG݁ Ȅ5pn!JPgF7_?؂ne+fj~WBy(sg̴lc*ʿ;Lă0$`'3fs!,2m*=3,V闁1*|+A<o>, lYC jI|lp5x Z@7#pj}6RLJ7Pӷ,d$y0iBz >>i_"Z;qc=32Ư_Zzvv_Њ|). &`y1C&^!njh;AٯRs#qjl!,<7`0s(jU6"U $sh/ilKpv }4#>bIT7ioM3a|08E@֞qr&ouGd\>J&D"|+_* & 0ѻ;s$sb,fk}uadɩ7']_1'04[ӃnLy:jaI/k 霐uH 2洈ba5ɞ@a/T6dXt+D乫:Дk ci:k=˅YݖGM ݷ*DotypT1RV _Hm\TCeVԌzR5?Fc9f)R7Vt#ãϷͫ8l(@,֎'!0u`$6ӮWM^%}p46񓩋*{' ) ^4DQ!Ylj[7^>rVW(,y>{SIYst-3:=4mt]䴯 "?ܛ=? pM @ux.mEo/CÜepqgx? c5y 5m4 E3P"( GF^_B/֡?*SiU8kb13,% &S|?̲u)!;6 ҡDZ,cңn|J>GzZV^rYdLRX^\v55:FeLCmЩn4оaf%!<ԁq8/ȸ'Iwڢ,.BجBL^'p29]x+rM֓k15Amo%QjaAA5 Qק' 哱WZ-x[ R^KTrHfb *"ym唡K -T_}+ tBa5]ۦ.fuuK^d~9wtͭlV@YcF;#n j0znk0arԦ#8-b a;C&qfhF.=L<"cf.:8˾¸M/&*cr~ٌxdK,`-5߬5RWL e^)WC3}4geG`3:[aKp`C,d̑Iu"zgO{_aR ɏ1,epS9`S1 ]Kw 2QlkVGO)'Y n*_n)1L~N GQ&̲AZ[uxg|u*l(LVQq:M`aWzv.]r1֨ jbR"en'>K!Sv`MIE~`Y9Jt6!s[G>/Rmd\jym΁JwXȭU'=`"whZtovYGX$ jK+p"/1 `SMQOT_ 珬$? Ut׵ k"`yy!Iގx.jDZCDo+$}<z!^jYhgQ2E3djt:y9$w'{s)CԶcT$#ku|ڲ&'ـF`3vb=PK1+Ce yC]9הafW~`T$'蟔R3hP7٥ڂ^GmLq7(npN1_$"9?܇FK?""yƯU%p &?[S>mn:]u0}<魦~-yj"g/wBYd(|ՃA=d[|xCŎz~a yxMY5^I>Y\t#-@#KnݻȡoHM-B,K,_2n̳pA4'YnqkOhk,' 7D'O_s?ʁgB}Rȓ,+܏"6ƓԀ]5ْњHL?thh_ZN:Ǿ*o&.~)` Ey7c_sEap!]A' U YKڄ5:+TU,$% H:'h=8RAcja~Pن#S|,^ (DI^g0:3áʾtzu;ߏZϲ>埣xl8Cաy1!fEL$ŘLעɌy?vˋ>-hRd S an^~ިkZF蒜_UWdCVԳYIʴ2wI![O2-UPtWouS}dK AI韟z ?(aM~V$W4s[.aV`B{6ǹv"xf۞@ /r_>ǐ™ at#N}x]/BFfHkoҿBxΪ0|mfu%._-rz)]1?=L> 9%cbNȾ,wg0*gf[NH㏿L4sQ߸W xŜ7UBL(9aL3l}@cvmXR@ OsXXl⮒ul2cLӺQz )&x@ ( чtbn|XsV7]k(CP.w7Iqs%rGudM,pNF#33$'I){IM/lBϰU_hq'6d#͘nt>{A# _/bcadު0:3&4 $smWfDǽ(*o vDaO|ʉ M4s\J٤xqJb+ 53yH^D3Fw#MUH_tu| oo˱5jc百iS3{ǽD *)сr*ѳ{-0 й2`a sA ̸o J,} ^wc+S)~S;}/IJCWR]"ݮn‰7\dT*K]1ij:G7Y x䎏bƙv?DmG92FETX;(A4ߕe_񊄷37pRA*R4n.~9ߚ+y a((s(AD1&ѐ0qoPE\"Kڶ{⿕j`dKߌ!OD 1E*qsJ%J/TRgeK}vފ|rQBF{8LC)~6. 5A}a wwAo6:9O]"fWx.}K'R[E?Tw^p*;]bj_oLrx]XdbrA#)*9^Yȉ=$HNtX՜¸[QQO \$jmg#/Q'J{ۯi%qcA4mXA-CTi5%OJی9fI9 ȶ4 2HpL;?eA%p&a'NJ?rTjU*ކuyZ8irhlҡ$/L\ϳiCf!n@^tG>k\i}R8jOL#"{A{Z3eFvN5;$1j0n6F8#P:љTCۊZ*%1=]ƇFaw=ɡ%D,,99y)?$QK(鷼Q ;̴q?8 @7m'Z\n]r6\vjQR Jc 2)fHu (IJęV,ʞֿT`[0A^|AE?Fex_buR1W4`c!Bm||hއ(F0)E#v4:i_I?&![TH!OF-T6еyΉF̤D|Gq C> &:!ڙ+/҆L Q: E'6VÆ]6 0^[{0; bܶs79dD~{5$[4T1)+3ݵḰDba4'0*JeIPLlI?yƟ=N /OH08!p~&=FWJJncW(r"61\>FlpЭI[NOOMh<;Ծ%YTs,W2^8!*dݵ+ I1U_hbZog eY,՞)4WvZ^ᑞiwK^XXiY_&Rl$ď:QZUK\ly" *yW4BT*e܉N.Dk vzZ|,Cy)Q@,>O2)m*/T\'Rr*\~^캦߹p]pE)^ld*&>dJ /|KVH! )bclX˹*~"!50ƅ)Qto̭pU4#ig퓎$֧oKPPj'>_)'x kDS'9WJjUKU/;dTj<4@3׸`_ $6ehy ""P_ϢS}䵩ݹ {~-^Vfu#Z-pH&Q . L>qѶaJ'0ʚ''ţ8,ZK .>$W82 ==6VTQx3 0#[z޸.!LqQn0D\qI^&Ijti53M=oZrDJIRTBÙTdPitnѡI yi 76dǐ7hoXrڇ3zwԢ.3o.N*5{t7 H&id\7 K[Hχm'detp)Zz$foY7a$ "kNF*`G'r_*%9BwugrY LOd+NG/%wi. w T d,6O  ,A}Ks{jDa{tD?⒈3rlA|able~RI'?v`s3.‹T'~%V&9e{ȣ_~!ō>v±6//x`drmA b Zؔ?.'1#F cS'!U1&#spˀM*/d[l3U{ HpwacGG9=1ai5SwQntǡnb`G cbys{B;Ou|!Y <ǐ˨PHc-Z7b&r1fʁ$Xbg gHrQF1UGḛBOrh۠`W HrHݳ £=5^  r/? #O\q1V^=p%W+wD|Y_¾E!{.~CH{FG5qƓ/C_9{MT&w'\b,RGҬX$j4l $>>PmBɏ*蜻yAYz=f`g a塆n#Ҋձ9 |`bzK#wUȮ5wTC;c8֕ +[ O560c;DtI35쿗2rLJ71A^;Vӷި)i;fӇM}Uӯbźvh?BUKDGׯBMtDif+S_Ky^fƋQ| Z%0K?^h99"t{|a7_)MT,&aSሂqϿCRpCд>Ϝt6+=:ڶ8bQgJsZc!(|9x%bj=wR crnՋ~6V+ww>=[$@jSOwZ\TN- []+[FQaۍ%vw}$ 9;[MBu :+Ƶs;|ṽ{J!EmoT%34b~Pcv 7CJ.ss^##.qGF{ Q=͙n:> jޖf4#U%{#}f7fĿX@/~'wo9(Ov0uX~;XX^AYq6UQbJhW{O-~,27!;Lj9xXܜ2Ll|P.BbQ)Z^u]g Klx!E. ldGDتSLv#q![`@UEOP~1e6)8j }γ %솝D:3,j柜@6bi@؏<,1,]șU{9/aNH4T\Y|o-ܵ%}e\1cKqƼSR؊TusY/GVɪʥy^f k}ł0eNjNuS"#cˆgDBn{njZztKHag h _>բAH-2i7֭x) k<Ɗ+e:؊tn;NEXJ("p_sKu4fԲA6&%wJ!%漬k{aF9[hC 7cc57cF A71؀!G!eT}5qw%[ev,fcP0`&@D75aG2mJ+0,2v.ce>z/fi\`m6ڃg#v?l"DX\k'LpTc bLp| SCf681OLyC00;gf_kuyFp+u,r6ZanB-A}>m"N ))٤VY<c1xݒ_Ǽ- <`^ExGuO`.ي(Q %) Xct+ 6j4zNNjm*Cm(j˯=5tW:y.E8:kmM:*fz&?&Xgoi$Ⰼ<%6zw%TZWx&D]jC5=0b>tN'xm^T24>c|#P@J{"Vj+ձAx(g/pXWhjma+sŝ#/+Vh9<ϟ%?j{vu)+5f!"PkM+v,+3gp&$"KtGҐYu이|{PHuk CgoR~AP(?MKy?̑e!{Aڂk $_oҙ}BaOԖ1tkiX,iR/T"f-239 16Tg F%<+ؓ+ Iߝc>rھ❲51DL|ΙmDwvj`f#Y=֪&4%s:)Yyʚ3u>|LjT.^=:MB~}넲nQ&'dzUުnmܕ0/51~O)/"bKi}j!ꇔ\E +$^'eѣeldج='_jdk?&HP6qpM1ot||a=jjU׃M:Ş}w2:d EwknW&!&A/Tv:Ƽ0d OPp{ 8z?H4Mv^I{>JKVycNScnꂂ?~ӴGiBʹbI[T{R^tk|аt\jLdv*=xtZ~ow &|XkŊd5gUpAd\_H˿G6<YJ() ՈSĆΥRK,e (/)f e D$(Z,L~NOW < R\ H1{+ mv]egqH?,P:رS55xpirߝœy w"~  E9!lD&x<}pD?6W@n+&zd \$&)ܘՁK[pr[5Qʼ*3= 9.Z\ܒF{8bB:7b|.tzG9X1GsP^:T!5!vVQrkLúkYעqF3AxTnƿGyZ1 O?CAb.396$4^~ 7~?:hƲ'=m$Nx1'ZwƿΟ.|!d ń"^p(hH٤Mt^O?.y 35pK06cۿghT?}uwͿ[(&{fJSe K#=UY8]m~!YwF8Ж,E`N>+BseԂG}nn%a[ geJB3)Ϣ4{1kwqK 0N3ucg< Q4{nAciItKeO!E MM\;0t櫥Jݿvs@$:^ ~ 9P(a^>Ţ#4z{YHvoew`)#~ 5`a@f 6gS=Y=f*gS>X''RQA;?M _gد$/mT;OC}jZiy,C6m\g9@l._ۮW 46^7a8ph#Ȓt_,Y/6FZVTvw^`d΢zN凲V䔘3ԗ n(Ԩ:$\Rc% -K?$E>'eB6#% $}ss}٘(jn&\W);L=2f[e̶85'$8%T'Rwj2KKpO1 u߳7'8u|}#>.0WGVdHO¨阬qf|?U2';Ou v$ՆI >M~? }"d{ČurI("SD;"WVH|3Lb 5ȶ ~,)|!k3vaeF֒vd4n餁M-?I*UW 8_ie)_ĥRJ& 4+\ g6wOH4"S*e `Fbvyxjp㦢:x2i+nxͺ4+G1(K*:XEa=DVPWǺ@O}Fӈ:ILE}˦D1)*UJ,3LxJp <7ju5%"%gm+6i%yYm=zEZ,"rJǎwMd!?!zȬ~f]xZn?ZNd7UYzl cŻtXJ(GŤkk. -t AC<9ZuT@ӏ O`aBOjN2&|FyN,Ѷ@Y r7A537ͯނh`t5̃A\`JYحPjl;<>-¾4%.\8)Ï 1SP\%ǦF/NqGNN ꪐQݶJxlvqT^>?Iu~ݎb?oAJ޼e 0PT|zk6s 7[:\)낣 8U0BIQ|CSy`Iɶ]UQ[#Wsw}ƾx3a0hk8q@9F}/3P.YL8FGhl1N,A]U)o'W "GFZ/(okԲQqEXCo ` B7b7ʘ%v~)p :ۓ5r]0C|͢ L<꯳M2ak gXb;+]hzN;V[9g{&!9m\Q|l׎?PqcRGalc"#U3Up+'KUEo,oEsx6 VGmHwIpXuWoxC][/Ş8s}o_8xV=Pҿ>P d%WBȕ#ATƺ n]s@.A/=u=TQ WE5fKl"^clɬHYͭn\<~oUIUsÐ*:2hl7uW|-&$۟~"Pad{6Bz %'A #]g_+Ӂ^̞~NRO洭FEA<$c[7*y2`{Y1\MUt WL椲|mogAZ=дޟ*umcꃜp 0WU Kc.l|!*P)zwºϧ@@m4| iAqhcN[|"׉5󼋸˦ 'Lꋃ7i%?gw=|;TǠ'^~ rBǾ!FWEkޝ0/13a; | L *U+#f))xC?sQΧښ.t_MErik~p_Hc0=x J|.H!W8Z~7Ս|kvywizF"' 5lPRBbWhpO+5q;(n}"gdrgl5DFCT}$,,VJI8PY'5GDTjceOwjkB NѮ%+Bna%8_4 .r`aӃTڱx6 j,:tl|VZUJ+{!\ƕEpòU-˜h9p- nAkM1`9 %bV.4w;cyrqTJPro-d?~-A=ma Gc^lײ$&+L7VD W UsrNC3FQE6d%>C.ȝ%-lH[]vVTɩFtMG ]Aiޥh.,΄r%gc+A9֚ѝl Ʉ^q l.Z\qZy7mEM&[×RF Am ذKT뮔VT'4֣EH 'kG]޲߉x(LI˫zJ/}3e_*mܝ7֒!g3Yv-+t[BV'9Sbc՚ :XɎ +~ hjRFq& _?@@=h9m)Or"G+U~{:bsp?4 $T7*~1X61%Y;p3o\(9j:@X;!e{JLe{yKr?\Ʒ W_bZ wl!+7jOL: qїŜQ'Un ];@d<1VTcѤ3L^wYC u 88o;+S;h;hsu,!_VR;\爫$+RD۝hnO4A S4xYUu QQvZ4q{ZN0,'nKDtd{O{9[*zȩck5Ϥ $K(xL~RW 2=1JկF,XQ#5DZYs۾̇q0 V:`Ƕ-;C7<ɔ)_ e>( !")| Ͻ]b1N{ęBt^j$a4J t o?ذjge*#V P< W([i*_53ceNZ 牵vNvm.{ HoR܊wPKp3=;/>x]r+:kirS 0GVB1A/:r2r6¼#.6nJjH:N7!\yg]B ]kg]FSՔ˗unXAqu-S"yubJ߻X]!8BT [7)|аg+Ǎ}:%R5k(t hCf(Uia#f+)ksӄgRkיr=##>rz2l6Em LJ?ͫS|^NT6)ʂBD lޘ`J Be>O C5ǹ@ʅc:ZZVK,82Za$GCDC) FpõF 9t\袌n9TI zwp {Zo}X Aa{n>#O/}M!W0+Ch>" /J[xpfP͉ b4L1BCe˼G4F ևNJo{ceꆫ1$ɶW Z /䛙:6֤vDH+m| Q/L< 4@rt$ҝ Ywhq 6Hd`HlJO䎝zSR/ՕvyT6]$ nmsoSK򯘫eXWl}> 4r]_ٍP4ֶ@O^a@ #t.=NGB|qҊ?V J-PW6CK&T "(ko#4&nXi$"WmݽPujR g/R=L7gս(5 bPt_=͚EoضVQcl3KF۵N RH}u\Drt% 0+Eɏ$SIO{gWáI{D!z8B" [f/'  Cu=ǘAN= LdC@6oB[Cc X齯>^R~w0MP8#9a-].P|6?wj)(B`q)A1]ol#;_ouN"^2dP!Pd CjͰO]xDo/쓐=Xy )qRxluB~BeNCa0>Pi}} ?}4:12hQvdͣZ^鲌uyDP'\\~};[uR2Sg>ޝfeѶ-"Yd}Hiޫb 'VՋA־L'x槏y=7V #y)```-Yxv3gB wp<6v$@$=7YɏjM=<`}>e}{5 I.CZDzp˙m0u 0K0-0NhR\P ?Ȏ({(f^(_s.-c ,P@07.]"pʃ}J~(7)G`T1 9V8r5i;ӟda+|crgڒS)+j)r΃K %%{bo)VbD;~:ӑP7Cnrz 6 ų{q1& u$ S00[K<]CmK4]xW#t ИvxUQR:}b 5AĈLr)(#}7=M˵EE~!xx[eIS&K-O9mk[f:Į -5~B9~˯!uݽ'WVg 6~JM֔)$z*qLsϴP%NZd8aW lOOhnPum o<iruT*lՇK9UFg*p-0KWY\R[o2ZYH ,󩝫]xV6RS7-[Oo}dz;>@uͭ3P|-}ZN רȦ1lgQ`qlN\Ǚ#2fAq:P c;Cp{o1ˎfC%+Y$$ ؁,){k\9i[ش`x{ި=R8֜_UMǏ+8hs,I5@衢N^rl%*4 dރOL=ӄ({ۈ3z.o"FJXZiD|U`o(ᬲ0j4pk.Li8 72է/A/tky|?([@sݔ RPvU=Cj6)RĘeAZ j4P:hAC|jtZuU\<i=i`p%ra( _,kg!]/gQo>5s9P#KWCpח6N3ϠMš;$T*",) endstream endobj 271 0 obj << /Type /FontDescriptor /FontName /DPHIGK+SFSX0600 /Flags 4 /FontBBox [-245 -337 1947 943] /Ascent 723 /CapHeight 695 /Descent -193 /ItalicAngle 0 /StemV 50 /XHeight 460 /CharSet (/A/B/F/J/K/L/a/acircumflex/b/c/d/e/eacute/eight/emdash/f/fi/five/four/g/i/l/n/nine/o/one/parenleft/parenright/r/s/seven/six/slash/t/three/two/u/v/y/zero) /FontFile 270 0 R >> endobj 272 0 obj << /Length1 738 /Length2 15049 /Length3 0 /Length 15635 /Filter /FlateDecode >> stream xmycpfulgb=m۶'mƄNlv&7=[YzuW޵ɉ%]ռ L<U U-f&nv+93^Tf 39@@eJaklfeg pup2𹻻 18 0MR@- - TPHƶ%7[+S)H 0wp[:؛Y ?݁ή;;Մ%⢌jc{3t{W@SuGpdk_ΞfV=x7wpl_@.rH 0vU0D\y3=@/#V[3+ hDc;+[oDHF/L6YHXy͔\onl_m߾)w."݈fVU׿;[(Y/ƮV]& ӿH%"C gee0sr\S7gg?6 ­-;ZgWVAҀX%*4ZYM-kѳN'Eޒ7K^Ce!iTpb@bZ&, I{t';+=LqJOhx:zigP?kǃb5RGu_Yz,-579f+BoR>H1ڳ0$o lނ^a 稯)qjzXtHYm<Æ~&N | '?4]or[FK0k\658'b^TB|_=NF ʘp{IahDqXr;ǎ_7 4ؿWKNȱ$kh*8ߓ^~+L!򳳑'y8 8 &evM(AFWhF.sqaS!ew568{ 9*rv="oU)Guն{  ֫B=3yAaj˒+ܨc(\6BSuW*q++1OlQ7{NOvL [g\\5z'Py#"0ysD:.U6&;3]8"ܬ*r`K# 3 >##Eɠ)\k njL5@ßG>>\pʉ'1`UlSx_]_bgt% Mq߬@uT ZO\;!þ8Lk5k<%*I(h] twр<ohGű 8c>K9z}\\+oъ"+Қ.IʦG8ROh g3A0Ʈ~WO/ӱޘ>tegYqhi)f;|vxOBf 5'4$/UAT_AcS8lHxs4x MxP .))Nr 4tͪfqI5u _XhH}rxwA7-)ෘ6Nڅ]ezdb$5K9]K@u4zRsd<(w9agI/.7X0PBV&9疪^\\aVVGZٿ) UEj$]̣s 1Vo1z]K@'^ rY.70 Sht'c>EΪ N#/׫1-߱wa" nH!YޢN~#_ۻS u2c/]©z/H1: AKWvx =cԙ -} JJ/$ E݇zH-FJ"-=Hd~ˁ5߷-a֕n} lCmjzCȲ8=wUs°z9ە` ^1P`2 #pp~Y[h*P%W]AM̛6EB5`alةdhzn|B:}6}NbҒYxA԰ܡQc{J:4&A6O)m80r}F+MuɎy."L@vTpcW/5j9~|ۣ<L1GV%_7Tɂ) ṽ^vL] WŖ'LrZγ;?Ron5 5+ߝ9gRƽ,R/j`mɠ,.+I5BL ,+IFB:)ljHi\ `@ژ#W vrݕȜw[CKUVXNkqr:jMفk#X^#Bc+۝MQERNҍ,zxs;v%Ҫ1ƚ5e}2+)tIc{nkLhN-m@43spp?"xu-3A0~8h=m"pbny{ouªݰpӕm'Sߑ(fƬyu˞0&=));%)Cֱ7-CFA/AXw*F{ƺs|]gW$@v.1b=6b=IR6-;Cϥ.#)DM&Bhy^R N4[,nWX<2f&m<Lq q"[}Sȧ,g $O/ݴYw7_LG. z_\[p"p6_4H~Η "*~ UP$Jܯ=Vԡ*c x%_.<,~ QlH؛?RF8;:6wG]aLMg5L|7ډY m,fD>f=c$y얙߶JHqU<α`#'mS)eJ`Ǎ%V]:(q..BwEG?' Lhu3-ɏ9ԻDg-noh# }arpfT֊ݴ^/VRx{˿= ԦAV*&gV5Αn)>emU JEuC7YU7h<^YE47'͆XAp YR@);Q-`l`H)^Xt7[1r 칞h^'wbJn#BӸdAK{B~cwf̬:Syǩ-M[3ψsHEFu$HRd_WeWSG8m.TQ^,{9$HFIqqXayuq e QB~Pˊ- y=TGHq>0X$"ڹϽEmں=d``rz)g.OUdL!tդv[G,SJаnuq>ѻ&kp%{׸'ً/N/Wn?يکnWlD$̟zy>OGbӶ/+Ees?Oπ*m9_j]G9KNoЍ"" 4gbZo"6mT9[h͚aUiD3:~p\b69Y *jkڳ'=?hMf.NeiʱI}1洣Y6Y+hie[.Dk\1Rٍ@~R~VH$ .Bz+>zTTi.<ƊƼ `]:Wː 9( $fd'T3A]xI;NUvY7^ܧnT<U_fP߆! ?ws]x)O=2@4H*OK+D&vK%n]y_S"ϤS$Yj pdC 51*\a97A~c=bW![7Q1- ,=@JQнlү|NW[ѡ|F.۝8 V)2F2#^}u󱾱_ *ŴyGy 40%Ze&!v?DT"m?T0svG@VEL=ж*1KT?~T2ߜO( QGlzm8# U d[MxS`(3iZob4iB-^W8(*FFUPL\u ~`Rk[,@Sk>KWזj2|Z4L"mY)}D r)Mºd,>s]oJ}] `pZL썏mc:6SU0g}0,wE(Tu+0xfK'MmUǙvP~cby=/k*G~.4[]}8w7`jLL`?&$.0Z,X2jBVf1+Gal_hsmгXqV ~hH)OB31CxDq SJuvxdxDhEiH<^ ^ClhJUGu&7g7ѪoxxT@*]`l_n/L JNG7Ƚdlؕ~!0yjְmn|d^KFBeE}:pfa /ynh\Gx$,R.s*]ժ\&:+^ , 5dDoE~zTѯsn}?uv )FaqfKY/]̋ś.E/ d*{"ee+b/olnx,*c]:5uSC pdagHSZ{ѳ !rLd%_e::q7u3X8h&8(ʡ0 Kfa=llW-[CU xٷCznY}ǝdTV$ dJ!Q'R8(zo2\V1:jk}0 g`v/8f6r%ݙϷS诖ߡ{Ξ8-̓@+/~.( -^5zg]٧b*P!EvH.Yޙ_?zg~YBNk 7Z %ahUkS7{7/fn.Ǝ*v$NJ(|r]H?FZzz=^Fo !/0eA}g8q1놗5^diP6K7AFq1%?C;萑Cv 1r7Q&DdΣ ˔)m`E9qYmV JXZzf,d]zo 2ʐ_L6 CsbO20gtc덃Tn=I/ 2BܬgxNp ٮ5.)O[\4ntRbr7`K7IE:Џ}R޷cW.Kjѻt`s8YFF]xU u iڇajѨ%Ejى{ÊQgN7l%MEnMz ;Ho1r[Zn` <]]`2,Za$Seo{yvg'~ werȶi:I&a(zS7#;(>v8$\8 AJAO*\%YsQRk[ Жl8mXdbD; \W7/FEus\U^k:l9i01K8J6TOxD&ol(yۈze~&r$rQɮf&HpQ\f7y*;S_ ]:49)ol1fPxl}?YmxFDB4')Q2g$2(b~TfV}Y۲4fv< 9N׵JqVD+q!51F0Di;\ӑ 륤=Rmy>q*[b,Bua 9n9)LlX 1U $7**4%± N'-UuD&WWTMXF22i(Kg3hlnofG#8eۗC+W a,~ޘ b_|L5pu=kW?jz9TEs*8[ /|덿hM*=>>OAT7XdUyӓ/ ^xMPXPLXFX7eeTrFmxS3J(/;025&\72LF !{ m;$UxE/·k`3a\Mr'm-_Om@ )iNtm)5.‰;Ƙ0GTv&nގvj6mXb総dAo*a^e)6Q'|호DVIlA\H~=K">" %()|ĕQ W)#k^m8ѥ]"S~maLwNZ]-e39*$S +'*S Q oаrSľwO68TS\霻]j N[ׇ(qzí̪nUN"{OC6xxN-!yL@Ryc;Ӏa`埧hsw6&!(O(;iūLmRoENdt L(<-D$źDd^2סwkL=>nPzq 8WIb,\)҈$l>\"1(oQ-;<^B"SղF͌#u_Q~S\mbQ܃Lцyןak6{0 0>sZD*jIӘCzkouS03\ˤDOoS XȄ@9BբERhmN}N'Efk,T:r#tfzyleQ)Z_n1FS+y I,HE1t݋@ G9qx$Ʒ_ig&uO͖Թ_?ɆRَ.vQPN/;7]^'Z*a+lClv53N^ DVTISeI{P;ur-<⎆nR١FPeqYY1 Ps3>w^|͵,ܙw, SO\"}׸yEc#XӣWp&|?kYHlzQEkΦ"lѠ/d Q=S;6 /YŲY <\'r-aG{W´>2Zc$del(4lʹw/u<ISwg9K߃Gx{S^ y5lԛ5.j[V X|KhG v<_J\_o? %|JITa肮g4g;3Y{JB"}0GP|v #v Î_SSgWGW' ]Pٲ) s9R۹ ~u_9?^h9K3 (NF*,`Brcʸ1ŷ2:`>Re7?6MSNtݹ]>#H(l< ;TBZ7a$Py氅Ns9RLis%RJ~YQk[Ψ~ɰ~j@ڮj<{/,FTl\gEƆ %V*Eœ?3)sYNJ :sXH|W5ns vyl0}.m Lf*I M1v6;Ktv뫶J[-$1Fùz=LwGc(# S#@k%PA[wf|ʉ,t ZUpx#yna;@JRY<%kpPx/z 8ŚA{05HRzX{.ۖ(4G]n2O 38\{LCҶ3κ8VHcBtN= D\؇aǼg=!TE޶]LgCS؜F4~P_P" V1-)d dII޲Uj㧾qM6$h$z2fz}c{D$A?I+R7wcX*St.Q'%eCek,6ބ_s6|F0Z: u.ll0E,+a23{Vt|6Ф!,Q3aaaogŅ'|AiV-~$? 4Lpa(jXn䜱ڦt)!)$uG =lJk]!(L'z0bSYP~hÝ^}K$8ûh,e{rxIDU"\5 3)P9GQP?'y)>Y:aCm3Q@/q&ã *:[֙?x}֥n+˒t[& cfN  * m_SUST1f_b$8t2-=RK{qH.DRF4<۳pg*QQ_qMo9%eGbE)،7 脥1<-5H䓯X>KMtmI)>6$9pb)>0 3x5wt+9,487ʶ¯Q\Jul#cpq ,IO Ֆ3e0J `d)x 6#;DN$a\:~"H:isSUb!5Zʥ%xXRsIF\)XZakRAT?z9r?G6ڳaR҄R9D~Q$; 8O1x&Ѡ#?xRCoBq AWZG"0xEy/"K`b rzh]>.,T-g,X{%'/8zcENDOJ ,5P|ō™LՃ$W uy0+~NK+ґjyHIڊ` Pw`ywpZþ pla)8WI M>;Zm!kfJ?3ʗU-!ɷCCѰk?&Ñ"y]%wyܩqH]׊ "Zl ۷È9"v \.mM\zDH,(6*7- BjDd`¸kñ[N~:C4?$ ke 3 ^cT3Y*:' ,QUEGt Z1V/v˕VGݼ..gCt'1!W!ɿ+[>>qLٰ]2 ޏ)leQx?Dhyn}m U|ie8)e ǁ̛ೣVRִ,~f.əA#}]I>H]Q2e3 g)bE+هz. 'iYݔ^A @xB*`=[oPu#7Eǟ&f%B vus/GqF.vJP=AMFtihe14(p1؂3YMXh\+*#Sn3ayvCc׽}}[DsۺO|DF!R@9VL~V-]wpF okvVKb.;U hb$߂¸TU8Ú+uٕE| y ޵^Т}⤾VlU"~@ YUOYxJ36>)mMw_p`p4oh; GڻB2B݋hYlq-6w9BO=8s֠>VP$E'x0IFUqNQd kR[iBN|Ϲv\8g>S4[x7pvp?i8C5IՇ I۲Ʒ(7 "[ R,lJl1 ?)\1߮Bִl<5,2_.%cz6|uj!Mi7b c;T;'L"1$)\9cMnptt>8pbu׶J.3jUo@nC;r 1C;ݛ,2{Q^(ǪϼH.E @R0QeR$ wnF)Å$qKiAj=2vLB.)eŁ~ZCx4 Q~eO8#,߁4?=u?2<Qt6׃d?8Bq;񏃓h^yYbd 8qAQ ͤU#a~i>Rd[&]!_ܷ* 6v+b Z(:䟢((DDuA &dD͡+@C* nDDN)+Өs}PAz/7ts7aR~y9^˝bxCX/>RDZqcֳ<4 wcAYP*>V%2`( U: Iu_Jvv݈)+zݦlO0 [Ry\Y澜%p_=^rymvЊT} :?ﳔf-'['p3R.#*B0N0$OW9>#TZ^Qѯe̹^wyIȝTD_Ydݪ 0Xpy .%DtLP+/B4+(iHhDV'$p *GAMQDBv+2r_e)+yYD ><)ة7nK;5z*5PKٞ2L0`5j| >ns?-wkhEh9s7U+^|ߥƒ|"C<sU P۔kU33AP喠.Ԏ׏LDo\uBx #iɔʇ?P8{n)y2:q^^XLW:Avm-?LQ*hIrj|prdᰒǵ>M LrE&1vG㲫4 aoW}i~=~? 531"ٮȃPcx^OUli ;'j=pɿ-0XC*uHxOZ`$ؚ )#\ߤqK|aӏgLTK,kZns ňQir. A %Vs]A>h/bE5]ċίjJάϏ*nz{fR$oXau׌p4pꦶ\-SF(E$W( $*+$uދ":[kiS-_=݅*eR+ΐ0lc*~p|O( fIȩRɭOgbGdp=PW/'DW)hE&~[NU*MG:a>~.S6KײIT{Dy#(&:ו.2~M 7,]],"yvLM(Jz;`QRRb3]߭y1`*6%)ߙ!)gY9Ce-&t3 endstream endobj 273 0 obj << /Type /FontDescriptor /FontName /PYIBOF+SFSX1095 /Flags 4 /FontBBox [-229 -332 1765 914] /Ascent 729 /CapHeight 694 /Descent -193 /ItalicAngle 0 /StemV 50 /XHeight 459 /CharSet (/A/I/P/a/c/d/e/eacute/g/h/i/l/m/n/o/p/quoteright/r/s/t/u/v/y) /FontFile 272 0 R >> endobj 274 0 obj << /Length1 738 /Length2 10310 /Length3 0 /Length 10870 /Filter /FlateDecode >> stream xmeP]- wn8{pHpw yܚzn^kӛLdedebKrpX))ŝ + l6VDJ3@cNegj9Awwww7&g7!A@ *Ji%M4 t6ف s H tp0w[Ʌ`w_`EI Q)e% 88lPvu 4wWu Jv+o `2w@`D& tp[m_@.hrH ZvS2h\E 3n vˈ3 `gt- 4y_YWӿԈoE Pe/k赁nտ;o*[8o¿uYYGN^TYl`[]kl_?fSп?P3^wV4uuyY5/,#?/11OF6v#;?pݜ`:, h`bVUx R̪=AyG/Rj"]YX;+5 Lhķ5:,5`%mgňżLY&^8&+稒'g Ԡ6\]~n!Wjm>} g!ԔKJ6hKRApVg@=i-K@,~1OΑ3ВI1XLFD C,ܨ86&yRO7t=o h[$&KTTk|>AN' .Jh8XMA3`g֊{&@Bup>HS֩x$ROT]{9ԋϞK@h!)I}YNYi)V"ivOYezeH,d.Œ>FܙY y|-ŏUKP M]"IL{ږr421eXsa=OyBN{ݮ;Ӂ 19aip\)8AcR*sn\ .rnL(Ե^lk1t ;;3 F_t_$|cwkׄW}[fajͱg2iW])UO07~I2+ CXn 5D|׶|ۘ96/4?]+k'C,Nr2Vd go0"{9_SCO%߂77u Vv[ }v2QGiͱbi}idƄ]TݥwߧY d^ݑNfQh\S'ˇls-tֻJ2.phr5zdI~5;&4谑Yy'־!a ?7)M7ڑG8Bz<]զ 33p]hS[D]M/=եC.1?a/֍]s!꤇%1dhcsAiW6&P.OI(k yݿ7Wpn_Lj%C~i@&I$lDO,)0,B8\c{)raG4JOzmuT\{V=3px~E2>[,.-*5)c5,Ts%"y0WCjpVAP$p4z=FgZjsW1T3-c2ڿ]%TBϲe|=x KпKF=O_mTƧZ$DV})9Y$Ə٢`BrH&ȶAE8o>H U -wqAhG 6=ɽ!"z3<! J|HKOņ^V^?UTJ'_C6K7mg4u*(~01QĸH>i7e$FjB`Gs w+"zxŘWtkOaݟi5^ʧ<<3l rג;MH_UtgAđ#b=%ǎ_N5M[ pix鍅2arЭq7(=qyazri 4d#h`O]:4ID( v"vz݃Ʒ&2?,za vHvSHlDq ޜ?_F5;|ڕ~ 0\vwJ s0tآ^;괨K/ZS/1Pޞ"wvN$MzH'&u ,ml(k4"N Sq'TsZɎ^ZKPD;,WeBhV3KG(G-i{گVM̮Xt,2JZuؖd#:N[*:%i5> &预2V/OpǏQp;!y4퐁BĵF`bZq'({'`Anbz3#7FQNeJ- }C\n&g fIC& "}l rΜkR6 zJʫ?L7rLaȮX\5d$ke3zeRDē\SYǻ{yFܧ{Ozc}gy-{R)a=Je-,ALޛK>;K-1cH.[hAuOm4̜rAjY11ctuPIJVovNs)X\7#~V=IU=mb4%q(|Я$ En5\7\yi x%%S0""uP>zS%CnKG+'GQJ!WC8k>#*Yp(N(&5&h/tu4s}%kM:\" :w? 9#GOqtMVEVY;pJ~yD LZʼn6=ɤ7&J(Q1,*!YKУj!}a-%[f%)Z.->-nb[*t)W>KNSF^=D2`2}?,o~lB4pK*Dw)ÞtCIfaمtD}t_I9oTԍf ]g$[.RE gٟZ<{Ө-:\T2 EYcCr`.,yLs2~ 5)|N.DU`z;=5sXMy'Fgn >: 6z=i-͟@*#}"3u بkLF.}BN$bYzaW9EEѹ6|EAةMv ήTbPT@a9(>xf&P4?(M_(/sM4 GBXl VIȀggGeBOaw-'ZL E#5 W6]Y+LLWg#׳N"h˸qU)z'a$r^ɔ|b )GUej;T S!%ӪH}mċNĨ(cWϳj$]ɡZ5 ivȄcґ2Y x׃_$lo9'Z 0PG'y@떌6Vx v'-IQFUdYUxH҂a)A!pƴ5ֿa:0GZ'LWEUЫ sʍanR9sz/t7]Q`(Xحlt7qDE1\\OY^z/ě*9ĵ@w>i8ᅒj%asy7 iQ lMC=X' ௑ϥG]XbLX$MPԚ>e`*)|t(i24iwpc?q閵yc8Qh<+-;֢(xyVd:X8,ML.uiG#sbщ瘌GJ޾"o%ͱW^g+rAݛS/ՁaM_韝̴Ɏ֌9K~YDnZUtb))Q{. ޲uf}Fg iߖ鼲 #x}cq RML,{y=x-~3-&5w%f2gq˔Q~In)*,& $ D)* Cy` ᨔ{aŐiRvNm\ sJ2RUWkf&<܋q ,w,ngW6v.ӛIW1ҠDz} %b0b-: ꘟ/N=Jt\!¥UQlpѻ p(~ߑmK%pB >ϵV<>r#`/ *=Iz*(CmF׹rgMښ/E2,WȦ[Ea&7*sƿ |DAJiUnKvqT=M,"DCS5YגDگV ,}hOy H%V|v7ⱒg2`NEOmڐ)2qjO>djT?4F$wKn" ǼQ6?rD@&iwE! Α3)j}TËÈS=RCǞtRL[K. Ö}-?$="MhFic bqdj҂zcooE{`[HV]T '|IKﬨNDhğ:*i!Pe6ŐIqܖE"P>?F qY>AB{k1fR@טgz+#]`!&|/L&ziFbz1cYO/-A5Ό:.~OV x"N+,}0Z!MZ'.:o8e:# {`Ycϝ)kRKʽHȀC?rk`V+nEkF J;[kCwz& ӢRu]5ò<暉a0H>#5B_D|cib3| ;_5K3lebK5#~/.-ïdp\U%]f!ȝR+Iޤn1v;4QWdFAqtSfFK/.Z=ѹ%^e רto;o-ժs?º :ܜ"H6g^"sa!\V`n1,=Dʎ|V_ !r#4 \=䛾H_XPذR޿`%= @)pZ}R&>gպtjS;r!օ=} MEY'M=mx1cAv\y]2iNDL;^ ,i)mv<,oK?di\ 0_D3 6~ `|сJCDiъDޞaO1|Jt@SMw U$9 @I) d\]âqZ>Vr|PVǟceQr'[-'|=|Ӂ3܁*v-ˤڑ>GY >oJ+fZmex}MZIBuwj yEMriI+LG مڛ9hw0::T6% mHwF&1Rڐ4rqu馧yw[g|j Y-JJ[O 1'LozW=} BxF4ZIgۖb^A=Ҥ4 :zEJ1 Tz^lNg9[Hcv?1ϢC?4w6vbuνۙ:ڮQ?hʥǮ~Zݩ]#/y:mMz8cEAr#:?b7E'NLCH];X!>iD]ĊlRZ0ga̩&q;PX (s__L%i\$HQ!}F <۹ͯ]2M]drl0ui_%B$[`~*X* %ce8A|psEŝ+s}mF/RChʇ/9: e{~G յ淽N)gO~9_w6`|ҊK5-Ҡeܘa_u_@D 4EMը:{V֟]o-ҹrx8gK^7yod6*XR'-/\=Řrstլ3'RB,xd`Mg?@t^nڎX0@&#",uiAOT8Y_ UcsJ,c.FۡjK9`8NJbk1? endstream endobj 275 0 obj << /Type /FontDescriptor /FontName /OXJKAW+SFSX1440 /Flags 4 /FontBBox [-238 -326 1844 909] /Ascent 709 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 451 /CharSet (/d/eacute/exclam/m/o) /FontFile 274 0 R >> endobj 276 0 obj << /Length1 725 /Length2 25850 /Length3 0 /Length 26288 /Filter /FlateDecode >> stream xlsp6vpb۶?RLfD(T.@')/ݝ,Oov1 a;cYhd.N5f*-bZԪ$53! xS?]c6nv>EIn$Y 蜇JһR0ejuV!H|fIYB8S>@C|'cXaMY[y-J8IGWJۺA֤|Ax0poAUCŔ|s/_rAOi\fΕJ:0Q{A@s~DNLu$\|t d=UTGe\dA!x}^Ois$+FX󼺄Hj}^7*̀iT¡hѥs[e~!f_Z]T=BBu1}DqH {rqZj!Ĝ)ڐQ s#zi cwiT dcJvv0GI!"RGAW(xl9R9BKgPJ+!-> GURn zS'P\XF3>g+FoZ! b==2qB ^k숕;|z%GA C&VI!Rz" LI,o[i(ԣk,4KRK1p^iǍ["7$~|:zork 3_HeaNFG#aYIi]NfOaAg8םi3XjDRtJt0GvdTO%ЩBQYah2מn"6d 6 cO9\f cHzF";d$^o5`ZU,6N~wċ8J|t| &,33-Y3&'xpMkJ{@|>ӆN'⧳ Esw8Hnj55->) s@#P<@I5py(TAN WaψL)\iRv3ϕ{eKZ<~ #\⼊זѢ$3@nYf9-MESv[ZUyոN6jIU%o k|s(LNù,V* .ޕjzjXMĩ!s17e;(IJ֠aܪJIM؏(Jo]HC W^4PR2Uڄ xF(zӑ=Nx4qݴ3~ʯCU|'O?~mliap{扂7%v/DEAZ A%1ܚZZ _. s'+hU=?S+[2̪)KOIB5pUUL$r|`2 ڞZԽFZ^MLO$Ɣ }w>]1Ix ɧtpcS;2y>Tj_v7eQ[Y4_{8ܟUVa @WÞOU)RnvUEQ=vegH; |AM1SK5RvCs] B Rn"6o!^TaE#My*`-`_ 3M 1j?sًdCͥ Dk۟\ d!)[57V, Y Hw(8* F=v^N7^yK"ft>;o+l>g'gp l˗9yIAEjW~]gQMN$" M+AL&X'@G-xP5p% { W+r&yئ4gs>8J<5G$hH&}E4;R":dgU3zvszUxy|!?f/,dD64rtT|ī+^xI,۰( 4jiM5VhQp.;mD^WfPvC&dr9;1#s~CNdygXa=` .c=ꀴ >Y”y<ݣ1~b>'[ ,TL{RK ъm?p#,H yw{z+Ȇ-յ7U¾\:#i/fpBpm94ZqhUy]OK2pzAHJ1tH:[y";?o2⿛1,~cΤd#/yHL,~ɁgX:4(,W8Gj:^]֞vtVqƺ-3 `[zO+:^~ wkX_`,b #E3Siϡ-8pdm%:+( Gh#+%et-G+8i߉ .u| /IK䑅Ab}a)"DŽ^Ym/Y,CNNv 0 ARzx)"hsy2{R0 ~K\->ZR,>[K:˫PK3!5s= |T~ &H[ë[Fۚ/ԟhrK64}_ЭCRBu\m.Yd:zX-5W/Y6 f%@AϟwcH[SH&a%\(bWOp=2Y煺FE]$T '̾>lcm:c Z+ush5^B;Ŷ]d}}`}F~yw01qܸSjފ7GUU1S_IF/9EUaN^MBv3bir5C/G؆2b:wA~]L5BM}H!wN`eZ/E2Ư4@#S'~iKk :Wة43S)5~_ЖEg.1t?!-BwĊ{6 kj 5|@1|C737>ފ!zYu"pN9/rۍO+x?o+tqƭO r5 *D%8tVy~<^/()UosLԃt$G|_jkd襪km)d[̸͑y-Z{yԕ*蕻UvJۆդV&be"A\V?TܒصH;t|<}3Ud8eAP [#'a, b.[@$ 1X0IoQ zmhT*x\k;{ moK-V4KگD|CAP48Wc$ 8q]10ɮj|oW#e-pKF%Z%V:8a/dwGo7i:sHfR!=krR38DKTAJj~Y9S:y~_YWqLj׉@yȹFwZS@ BUы8grW0\Ig_ޖn̙̄~#9NmS AMîgx<&4U\"=z24j&R+!؄h+5Dt&QJ<ۘDJN3u+ig:>2 ^.;sn[&yA7t!4)/ly(zu3j<|Q9_CxPT!c%oh:Xj.ޅfo3/!x<2ӻ\(gˊ "6ॣr1}d>m.Șj| ;G\kBgs"ԙ lJc_  F8*(HudYm f榈5I7^r ~WK |M>q!^W;|-Nnzk?]#cO,-'^U*R_#'uz1xz2ѭP$QOI=)3Ic Yd3J| QtG8Dt$l;)Bkɕ#\MҀZOɸƼA5fyv sIf >ۺ]##rKݹͦf4 8B%B0'bQ9w Sd|#h[T.%Rtc%rd?@?Srь+S(=NFLa9*%sgk .Gg/*H, x25|d2>xdAɰUGl, c2)ߥ:^Y@$n|-Ը_zS1Cñ,u^A܋;cS*w}֊_4ƀ$3-7-iHm+|kp P=} @aJjrY׾ էeII՘]yQԖ 6ةpM;+ԊyW] >>ߌztC`&г-xӚ#q妲r$Kw愰IÎ)``CSpN>^&;LMt?0]KPaq 5SEr칶uKz0AQ;0 ߋ0E3vݎYvSR{; بo:~KѺ&:Z #RO\! %-JLLTGO=G`>*++v^>#[(l9kHx9 M3zdW(}։k) ө_> !(:eʿZ6- 3$)>+/nC [mù> 8[J|(J0BSNm F$"{fk \!*x*s4lث8d?ϖo)XӅ/<}jpq|U;6htL̴4wFÍdP9nǎs$O<KYcnwR*Ur#Q0uZ<.gN9VkX( LgUT3MUUx} /S?T(q?W=̨b 3/e(j vp۟QİIY 01:VIO4.&\Sbnىu4ND %gԬ4!w"v0v߬{m+lAu pu³W5e_:""u4^aF޺~{ˣydǀ&c6,[@>U[Ѧd}:X74qre'3U6l ;xr-OBْ%iŷl Lч 1$iȟ,K'WJۜ*ȉ(!tû7szo$jU:AeqB5M>ӌŠ K8oHĜ"OȳMjB89A[[ v֯j>+f}Xxg_Xt0xJa :ܳʪHif,PY~*`rp:*%  F ]qr{1 oߣ. d}!xޥEJj^`JxUW{A[E3Y-x Va\+SFXP Yv Maā}I^fuSw(O4Ta!t9JhK 4gJ󦆃aDMU߽ Dp_X9XoPɲj>͟ GzODfwڶb4X(N']_"*ӾKDt C9\E,[if(R *IJtkRRYv o)~[ 6a;T(zAwT[i氓F಻E gor⿙ w$!ɵp!m*Ģ YR~Oū^iMÐR9rlz԰i<#Y͚o<P@FQrM1-/-AEHV*J$#?G,>}D|/>{V]E>ܳnpm*DoVE澓f<$l9B$ EhN%輵 ]>>w|!?):T)wИ9oǀ*rT7懬f*3U|#ʨARZv$BACjFqSC4(,x ׀8h͋8"56)ĘPL E;ċ3ݤv|@d|}pa{ᨣFn^^pӈ>1'5n...Q+J@egjaz\^N+,*5] 'Iٝ.epň:K±OV"eIo]H*9O^a:KІV!W29h¦F\=8Fpx]Ȩ!b; HŽ(_9 E0(|')FZxzt1&Rk͞;"$ DuYe|Cf Yi af]*(ӊ}hc|4E;^*0h+?"&Kd?,WC);fMqKqr+jK"4VtP p3(Z VloYL(6RuSYk?߆B0/:CMۖ-a5 bf-tvwhD:S1A;\}w`,q( +qr'+ o bi0SW9i$,m ϽI \쬾?W؃D|c@΋WGY5+kru7hE'Ńy0)P]qj?Y( #Slte~O~i1!4n  MȈ\і{滾(%/:ˉ(x1ؐ> @ӜLNi|(Zϖd$}_0 ۓ fp -H~rD^2,M ]%ˬ@*R;P9֋4bC:+#T6.9w2/Ӵ(&QT䧡Uuh>r,$FAgJd҇itL 5p-AqXg H77ڼDk2%/Y >]a!k$qn>BK 7?[ ^ 6i曟!#eG-~ClȦQ! ei?{`dk5eCc#V< EGv.ik`[y+ `U<̏yJ>&=׾МC*,b0rm96fq+<ۚ&/hP(ajJPg4_~ >$-Jd3wcas[ty+IEA2sLwmZ[n.\aSrDNT^j>k7!U\WYIx >$?(D1Wj.:{!{Y>ļCc/br9Ӓݼi&hLK-]ovho #Gk{<ts^*mXޜLP;l e Ӟ種5>St(.P-)76!䀀뇟Hࢨ*_L7G!C~MjӇeMfͶš p+!6$^On`%Ǐ^aPvi,w[}F);4Uc()q>.]8L`{DS\Aot")~Ss#9r\9 {ֺ0c0pci4Qz l"&ߊy92 8pRҦ3yćhK|@֠Y_5f xMreH*u ǕEw2!;;'k:V1)H]O'*Jڗ);-X!'i2L2L>YT8OI)!_ tk(mUle >ݦ[9m<_Rƽa,sQ zMhAkJM-5ŊqZi̙e|rض$ߵɧ#gn-6J0nqק叓1m utau;<ܑБ'Vz:>+fȠJ?sߏ~d}d1r&B ?+ L`J Eln[edN(h8Soq)'/\¶l5%Β6\6{S% }%*gg4%۽y74r~B,j{sS.2%R嫞"Ym8ҥwjM)碆qA1D@$Mλ):Z"Srk]磀>.6%]C\x\7qç tmwZPigЉ;@fω^}2&_5gyH\|W\4]F#%d aS=\ce+NJ &j3q39ܚT+Z[mUz|;4_e=Rƙ"ѱ-|{ 0#|\mQ1-oZU\ݟ]b~AHq,7pp'JeN";D;p 1+Qc|);i!7|u}\~lg_v,Ηȭ5@B?^ +;{ ~saYo Hі)xjA%?cFdg/Gb*J)u< ; ]&ul+iSwUIsñe߈ fCG0It9nh %kL"q>X3nOnuFm`VTu)L5v]lbNW;GC~hLDNLrDVٞmQrlZg1J*%?" ^= gz͚DlڽOfvN KG2H֕(cT;@q 0҇]벖fn 'm5z uܺ[&6գIBt.lyԉcTZCv+ /ڃF}`N\x6}_`tK<6uO߲ѪOnukw3}&UÄSUch4@\ZpUIr CSaibd;͖+Rk\oRRjSNT&Sь0"K7= P ɣLVۊD {z!Ж8c;NlN0<\@EO2R L'Y$n~k9Sf)Xz کk|ޘ.6$yzp.L:1JR^ԫ|Hʞ3Mfi㝅݊ Su 5&(*&iҞkx7o|'Ym+wSW"Zet0-KW]4ßpv]jt!ҬmP󉖇`R^ ֔G1 | gV0R)[l+DdӋȱqJgk'#F7)8բMaAF>Z0m 'RӢk:>wb?q\n۶s2#V#[3if: QwԒ0u` .z%2q C,V2b!1: m -FύǑ*G+맻,_kŃ& ZSQ=dJҨQw=lllf -0=x))X޺#->K}8+hwf, TC'-GC#&؇G Svb/Ml1̽TQ] ^}QSIA <~k$}'՜kR.{n #:X9Ân-ea`5\*qj n3A q(ؑ k|Io(]&ҰL~C76~ȪJ)q\HUQk ۮ6P m(όaq QmK8:dӧ@ %%]v2Ab:y $gPBǺoSHB)Lo5Cp_fm=*T[up ['VF 9=Ȳg0rhمLm9neÝb -^Pmj圻 ¡!fRXBj:68bwDK#rڽqp +4hv}A "আJcRxǎғe<}1*xOnj,$Y5OpUľ\wb5]raJj@!^XȽ һ0&@~ /g[ \stBCȶ9>QGɔ~9pK2hr@J։FVt!Ont>{ vlcBwb=)IqP, f.4ks&>B^KjW ׊(\6Ir:?)z9&Y5ks\/G#T3>G$J~TlQ_DPPY `đx'33`Z7rxoѠ*zzo!&ɇ^ UdGV'ܮbjd&~iу' دNOu4|3*j=W? h߀9Ӄ;LspאùN/ ֺ)j4A;1MebV)ӔRHvˍ4mEcU40Ի ٰw@mQx3ˮZվlL5ky8\U ' R|bV,}eM36忂lp  L7VۛI'w }&byy^S2bIQY/7҄'Y%1)/MKF#Y|="p.ԋ^i6f oP(/9nf 33emȖn._'ZWT\ %;8s4*,ǨA~wuL IW)uf5$yR Ol[<"*}!Erc-8 +Z>fa.(2N.q?uonaFTQF"8nh4HO͋B xc8s@>²ދk"@w8 dYQZgRl ->uS5|9跭ˑ )+URܰrpB}vcA oRH6@.88ߝ RC!Y ^U}«1x=`inS4=xG0J':<}ɡ Sl7&0VTs,O,}g'ǍoZV4cU4-X3]6*K>Y{z!&% :v%Oo? ♂XwIGaH ώ-Kz)ڗӁADC$*aÉ%lA򖒖Cd(qLQZ%,ox 03 {:(\rUN]\(WxmP9O;/6`&FQF+qSJAz:#5hnB- [-RB1Lyp,O|7R2ZeQγQ6cZ;AOpQ8!+´Z]{:LuY_ J>7$1D/qT!:~Ԁƕk 4WU;Q[=is8x}KOeqΦz{#Fnh~w42bڥć1Q @`*kp@)K_6< `X`!?LtJA@<8GB'8TN4spX3 Es [=OӾ)WD1dm-nϤJ ]4gS0Szj#jDilDtm$}BG aS88lJD:_Izc1s䓖RuWΓg .rÈ=[F뻫3ʴjVD+C 6h!zۂgb#xMC`! }|o KpzqdFw>U%q$S "IEFmtT2eVq` pwIH 74#=I7^8),R3v1i t-O֌9}cSr\ژIr]CA ֽu6v W2 /CLM=W^îd)Tk9Jq*#HKHC037'X[ ȣȌLf- =$7%!5>t߾SY"({#Q)TGƲM-SM=A2U}ǟmg7&%%PY"$h%{!\FmhUoZD7ޤ%K޾, _(ݪ ݓWOmgv"ȷat :\:QҜκGs8}/x^;m=r]}u)M2.fLddm84n_XԫI8Qv\J؄ػQsQy\EƞEl;ŭ5-; <՜o`8Z4[A!ΧچJ#W:XnHc53s"F:E x["Vj_j6ȷ e /7f_A-e  𘚐nl!-DUIk Xή d9(Ζ;%}*on(%x8?x5)5d}*Oŝa/UZYcn::KCNUNv[5ICo1\\e5d!j 5}&78KQ\kU:fx8Nc~G4O,oMGViMJݫnYjB 80,My:x5TU (eʹp4M>f([DyE|$G'!y&/?i[7_8a:!vZ0!RdKRPf95IhnU(7uQi,,ML+iO]- {fsm/x[`t+ձAYEk&s'6>DoJ>lVx[X}DH/ao%d{I0;~I9T&4ʗʞWxoMWP ڲ (9Μ>=(ҞhQP/!R?ع]3pklm\3nlάWh5f8z dO(Xxd\6n$Z! ;!cպx XZ [E\P!bcF/*f | "wsbوտ2|et.w5 v.آ0`HCSarvlW?e m\ظ!*\bOla:ї=nw5ӜĮc[cC +pvRL;n8B}f~g(AĉZ  i\ 写 7V0TX$㝟Au&ݗsxF .c6瓢4^7L7Jfٹ&<e8َen[ ߪl}VӹLt֢6 m㩓_kDuI~}"SpjxKes>#1a}+р G'D6$:~Dq8QCqMvj'WDnj'L1U~]gh\J%xѝhUcB> hV_v)<49,ag.uG;XUőHg^O2i]/gyIo(j(oԤ3UBs>-鳣洛:3etW]?zy ['Q1.󁏵t/*7>ƃÃ,9pNk"&uQ lm^|.M?}+\sM`V%}FP ZƏ =UCb5ΊPZ2T<+ͥ ڲř8W_(#Z3Z.Eإ3ernċ^ yrs0~ V~/U>[*AgzNT*-=5/G$M,gFǃ 'R*dRL`ıF7rLKj6#db~? i\B-s.>wSPJA,jjPă zdiQc\:VԨ1c,@h|[ū8,o'SZ^QU 8# (>x8iA=} 6/t` /*\K.$Zgwٖu%B|mIwx c%CjJcnn`,c{J^%nkB)&i~={]aq`DZ]?h#k{} )_CoD#7D:guV{˭ n^Ǎ{Y$lPb-Sȃ"A.uAsFuf5R+|쇰GGm~֌s%-l c9,I67зSm7h5\0H#P8gO"M{yWa{iߘƉ'7^%#q%9bcs\w EyxU@eŤ/&^&?}*8 %Of&#oŶb0y)..oOfОw̷#70Ev `R"#+[ir֚3=9:}:!Cz}Myk wr% 3/qUZg&q*!5Z9e&r HV6qo3F_=>콵[ls H<l}F7\T j-iwƦxLTdjCtb;[_o+&LQAԓm* i;p ud RMY3 V/*Y +`u!㗞xWk]B4:w*g@ ey cDpmHu>>erx%@F40HL9u"aҪ {ݨam{d#@6B,DfiY TS*ll<\9{^.^F*d] ]o~U&L\D| ݹޤL3"DvTT?72o*p4hn BF ~ATUBN^tjwJ &+V7Reڸ-PNjdW"Bxޱ?Ul QR風)g^.!Izy3Jʸ90JNIA׆8goy1)Щo1OpC7V}a~F;!XA'Ia/sG͜q@Q^?GLÌ"/#A!\}gR X8HBiFǐB~qmcZK҄- sR$!T3*k>`L+.:NArCgTæ *K>Ӄpjmd'8=p'83mÜh(j)ߔl͵G *e <p)!؈fNq`5S^GGΞ ~EO' 'Dvٷ22e';Sqz`!Z !jz\|΍kvGx9q_Iǥj:}NL DbH^PBj@JdO#`#\fC.;">FtI^TD#yʻU58BXM$쾀Q[j5TK-!}7oQX(&K'[atBD[C&9c"Q-psu}F:iDDMTm,bRc4O"rQB X ЌnQړ%q ITgڗzVIf9h?=t(d#޸c!Y뙲nx [0P~5 g-/>A?e_kU:Sm0aF6FOKϴrd@ꁗTa8#3 mSʎX̓ѰJoh'b]ǰmO^X{o¨OZ@w)_uNp͵Tvn@qw;`")P5U\w#e>OyDZ?綻YHw0bMLaEz̴x˦iZdHOe;F!"}}6" ^t`uO<aH7 3PƏ* eH/j7\mmdl8</o C2@/;!^ EQN>"b餁~\x ek4kX4ei<;Sqsn;P`3k2X7 UrZddzz엉_A'W5[T\:c;?\QW7Yē^V-E+EXD/+&4wsefuI4eE)R) ->{ +0^PՂ7/xDSag\jA! ;,FR\^cTo},cc˷&\9ae= EBn#cS?BK iʄUZV4Ki6Mǹ*JHv0512Z9eƀ`z*V1#H0VOPC A_xQSpV=ؚ$h7vcWMY%B g,aAG6UA2VM=.lJ}ivFtjaJ!"ofǰ8S8ʮ oQe  jH9& aZ\BSIk]قV@5@叩'T47Gci]vQ9\GDHOUvԙ- }(< 5@2!{催UuEgwa9 {ͬ{bZ'daj鷤M=3A4pNoGX˔({"@~l6WQ2_Ceҟ#V`af}cڎب!Z٤ 3QgM # i󋈽=!GȱQ\+*ۥ /{6?CޡW # {"O%O?)M޸ )؅;D>_֝6s0 ĎGʛb]pr-NO䄐-Ql? Qh'w!_ 4qs{Tޡ,7a 4A\1:9nQS]4Uc&]g6 `qc_B"*rbG×M&@1\}d>œ F&;5` (4U9ɓ?xYRbƷx ̙B,QZm'XJ) x, կDo#n+ io] PK:$GRE5!6]Þ;3"x 2cx5LT8V 0j*ͅh/1 G߯"|͈}FhW)/螅BYrrΣyd/p͜'4[$#剛,vЈdϫA1f7j/ZZ!as3_;i:<=r z.?A FgE%1f7=xږ8;H3 rw.cLa54Ħ՗}q{[?|3G,0zo(ZM;O* nC!'v}#ܤ5OK* j}}cc+E'ܓe+*_Y<޲ɣ*MaR%ƚ\6ͮJ'ԃ~1Prߛv]/8x:V{%A7 LilpŸ'|/}NkEz= kH6ps0ݜ %MCOȬ.sU _Ne+Jh_7AiCө];%n^6=lAJ!d38NqteS&pcL Sթ2Eس 0.Yʚ{;]$lG4\6cc[] ʁ]NŻ3B|]EO(Lՙe=x^Rs|EX/+-lg^+G>W}uz2V~ۅ/= *{d=`F?ah76ӇJj*_,e=9¬0gz''"*u\sU/KZX\:sαScE~w&FC@xHmG|Vr\VCYrXk}YeN:1xu>ˑDC Yq7'3]Oyu$KBqڹ5-xU]|6$Ƽii -PDSRKM[Θ{X94̪sTJ@-z8f@!|WDrjZBj)0arsϪe-FSagZE4q>ץ0@> endobj 278 0 obj << /Length1 725 /Length2 30287 /Length3 0 /Length 30783 /Filter /FlateDecode >> stream xlstg.v~mgb۶mMLl۶msb۸s{ϹY[O?Ukww&#sQt0ecg(0122Y`ȄL ],D ]L&eS3 ldin4fchbikPw4𺹹 9;lj p0Yژ4%rqS;S'C1@ٔ `f03&gs3ur  +CL^N *̠" 03Hn_W1d_V'$z&& _IڙQ:_|ʿRLLzښ(m\]L&NvqdWWC[K_!bvcGe,faj`o'WF9U{;;ߩ{<QM  5&͢v&ve|:Wo?,(k8Yz"z#?/!!{o:fFN ;#:9ڹsOdjaj lolZ+Z8[N ,d'лlIN+#9ŽxqK$a{k a=H\\ $׊o?'X)ӎ2Τ'(R)>sm"l]畎"~;Q"NcIїd`rUF)}"A a"U!Z([@==FNM]S`T\5 Qaz۸MV9b@7ԝe,AUmpZ^WbxRTf$N9> b}W9ͱaL"}fQ琺nRH9zΈ}wljyc+D /{z\!2|;]5 4-9>]@݅d@hMmĮ0nIk?(oq3RRʄX֥-nٙ'#;m<)MF!k#OJQ)ze\g(i`גP{fznLiclGF8A"_o$hUr{%,) 3>|q6:]mʴʙ۾V>L)*hX~z:;[y8܈{ME*Wx.厎+ >|z͑ 6q'v,K(pϵ> pg=m!R5YV}4PF +z9i:_:M ggST;P^IbtuS5?)Kh% 2}kM"#:9Lr<ˎ\ 'SEWF`h SeDf+^4 $G9=`IO(AE{BҲvPc# >W)ǹK-j.At3ƫm8V$-"Ylu•,Й?/8_= S ~֐D=T8OZOMȧQP;oK\a{h0 Joii'4UXM&Nj2C2LDp+JH=%N3R|L-|>6hxBq`?TڄSԄXq{QqHIqHk~((>{,}]<y(Yjꃻ6_nϋxn=ct0^%Pk$I^ \fNXMj@I)]xsqM)*0LΝwW;sֳ(g3l/2_<ց_s~cOĊ'.) B._mPW.aeWoT5~l5: ulkm|{O"dϟ2S,W\ 2Y'R po01BׯUktPwp6&#);7pR| %tiiltS叚*R!PP#g+xNr+/徠,563: I` :+S3 遐&\7-gH # ե#D6_/=c U t%`K)Di3\wZ=9gN<{uؠ-%}n)4M/4BQnT^ȟ.aϭu[p cyKC_ ۭ U:Zb0fD(#c xZ鰗 ;/CI.Aڠ|POpͫĻ{Xm5ų{݅AE3.id%pwv$U/{qB]/Mq.pRI'),))Wo{v0J1+jY(ʯb$=9Te_1:0q =ێ~MOvEbR h=(*OMmV*2g4m[5Aqvl(ġNd&"+4jRfPQIXlԐNwvۈo1"ND?0tQa Zc qp6jiK2"%@<?hPq4;vABb =W>3ŗх=av51edYr,y^H3 jav78';6BO#㛺ETꔏOSz toHžibd5]ibnz+BZ5] f4_zhe3*~6'bP KslΛQhfYpA [CPFQ~H9SuF:Ęq@&bV &2Vt[i<]݊cmJkw2Dz%MG|\%B'ia7#!V&a\IPɍ- p ]%gC1 ˏ'ohD)RqFeJȻ8 spue4%JM(ѫrEH_@ NuΡ }k*o<ފyð e_֖ q1t R\?XJ/?10EWTGV.E_1`Vr2w%]hV̨!(]1-KΆA|ܼiuO4zz)Ur;opF&#D°^z^.ה['+=FzGBIjZ߶9HL| ,Go4ZԮb>2{h>V;mD)Gç,wo%2Ayì7y[>+TUXpu9G;w"3 彊%&Y;/VJeNmߘjt0&9a|BU$Kw<W O%Rŝzqk oPR,,u:O? :4W㯻Ϡ}{RI'J׉{X+SXŽUaQiZP~(a_;W鮃! lj2[ EO̒aeM\VESf#XeB"vH儎$:!VG InQ*mHNc׫-sA#}VF`B}m|kUɴHO} `NaݨMI/OLPVxrU>Y\UyK@d,ܭU>S/#o['PZs ;vo 9 h}td&X<׈suhR?#ָllJI$D`gMlz"jo~HjG22}(doC+ڶSK(b7Tϲ؆S׻E7QW`Zr4Na>fP$4UXN\|th0q#_vӜ doSW~RkP#FIT@Xpch-DT7)E>)n/Ep|k2b~~YjHƽvi65+tiV4?9*Vw Uq؟^pZ~u~M{rQndϔx$? K|AzDg r$v bE$Ga zU0 lbTu.QL2kxnxd+FRv1Nk܄SiwХ񑾎I\g౛l*?) G=B'}CHrS+ᦻ85G<VRrKIhF(֧o7iI5l,:EKkqq9,}?𣟖#y-Q5{rɤ[y(Jakezkc`NW9!u*Ԇ;N|y9XT>?Դ,Hl ~i=M"GߤX;]Īp0R]S7'# zn=q5B_Y7ؚDr1RP15hI\; 8>or/G8 p+^;uA;ĝ[ۓ_slpr^I74uti@AXc!{,]qPce?~5Ag;M*v"~Wy>&8{FxCڗS7XfxnΎ`Z[ {{Fp$f}V,`~EʽμYwdP!x+=3>Vyxȋ0 ǭ -9 D44^O,_oGE{RfeNv6UNt?VR+;3k":8'm-wkxƃڱ2Zj!AvQߦܒ  I[O nP*[, Xm 1M()GzS N@@FneLuU]6 Q;`:2ڰrԿEXpqCC9M U@H;%)nk4zw&ģƌOWm᜷*ȡ%cd3%\z4 Ih}Z0<K6t vflFi 1$L9զS.!!op~`y_W7E ݆4bY5҂woЬmZ4>;V|茣J]<D"eP6V 1BE* >~_0[YgBe!=vcc_n'Y؟p;Swgc=J3xq 3q'{d! `Ӈx܆<4Γ/lM>P1:LqӽҞzk<+\&vT A.\(VIH$Y lFƌct2;†qQ>L2KNxyFI$M^inod.~i$"<_xcL|)}2;z|auE2^ϩahPN$u4=eO WV'rtpoDkL*}Uef\vo*=%z_0N y'>#{@&Cw)Jo9IëN]q6 gqnt[N1C G"0vؾDak!g$PUۘIFyH# )Y$p(h.&bO˦ʅס*%4fr O#٧|tnk/R\/; o 9T91ㇺ8⬣@ymN83R茵`B N.AM؆7t&!?Ѫq'l#KcI?cQ-4 $N9dx,݁ɚVT"?fbߧ&j;{MzȊ9 |Ff"QȄ\6r%F ،kr'V%dys'fC3˺#:,()`/ė5+N@;i.U.!7GEWL:'I0qy2U]ٵqw'GdM oIQN_UZ NL,X"b 䥞G4E0(syrgxN9>TtbeQ A]~|r)Ͷ$5dBzR,2 HC{g_Zfh BHFy䊜-P1n BЖ @-e@0IJy3UKZx){VbE7co%&qEjB"r\D$fL/ubƮH{3brm8?2Be}%m֏ KsM Σk ƪmچ.VM|I89tPү\zԚOuy+2mktTS,mZ f~{lGo#ҽǙ5Q1W>5M$K飖D1h4$`gfPN'y]_,Ymt7!Rymfff{lLg(=j1ڷe`j7iJSDK Shл:0s Oys_p? v1&;fבP鿬2 R J6,[W1Bh29hܒqWcT&x5U#ȗv8B4JlN?Z~R\L04N{mTF}Ds ۜ@ALUaQ8`6|wOl BVh.-֡MM aMU^;~F1H[й{V9?m$揽yk[ wC썦~2_/ Zf[SoѶxHCLj) ȑ7(%eP[:0=#[a6Gz=:[iwމװ0RQʷIWȐe ppc@DD4rZ%pg38g=|Ao/(|Din`<}/x<-/>鐋RQ?k 4a$nsʾH=:?"8! ŽZ=H)JT\:{j(F>] TZDF>3Zi%[QMKBͳ5x¿&)7BܤB̂U%SkUػ#1TbL?g;ͶiJB"BNvM(V0<&Ē\c`GTƌaj̳"l>vLQ0.ER$KR;)dll(wT٣\aoI%3$2t&۰G=Ou\jׁpI)V'FxM/kf/V/8k90E=4<-9t)JkU}K?oi*!q4HKk4ct`[QIQTGz hD#4^foNƁ02W(Gxqk'rjESJLF ĪLZFnŎ}xƮƹ$7>T5H&1W^0tgB\ηƨX!;["UI$*1+fGpe *Urne`nh'$ismO7JNae7>Fa*&:wKj1-_׀J.aTވ1R:=dhGn"baϒGS@W Q|asVǹ>uSQ5cA:{:N g"\oq$WQOsf"ɇkZcKBcvSsUCOif*=mlrZA`7MB]sSX~i!u¹oq, {8gi!NwrĞoXi"=E4C W &#"1EY:V 394Et M2هnn\L,XƱ3b&ڞgqEnR>i!F+l%l|0mfٱ8rT yPf[\7XhtZIioĻ<|vdL_o32?wgx+Y$7<61?"zu.KԹɑ(vUO. ;׏8,ga}&obYDBXC,N@e CȌRJAҸ("eܷ 9 ;,>zEaD@ H̊M3uBmu;"_vi0w M1$0v F%-l/y";'ͳb)D3"z&&SkqZC nNp[d#pnQ0sT&cr=1$ON$Qr2?[ǢMǚK'fpٚ8`dtS{ޅ! QdA\!+)ՙw5la)Xb}nD ӿ׶)CfeB4{kbd K&~3z>= u#^5Hؐ˿؅4-/\J23aޞ4( 't4D #/lgn1áhu }l(c%r;\?@wv銬l[N`".ڞ*TXFȥ3i\c0V b69e*ੋ%6@"g@Wߘܕ^F'#b?mL-zByHóf psccBNMrVRgk,Ug$AÀmL>XlfYEl*ƕЧuVͧ.%h;:: À(ĕu9O{9Fݻ h/z2|/!#ylOb@ړf.!ьzv6S/>H16i'sޗ0$M: ѐyru3Db_4):Z#c-=b ڹBLjT'yhUIu*>0<u!.,Hgyb1u䇍euZv;G5ʔkIK~c}$DZ>B+l# 놢@gPZl(SkmoJ?&="UCn=3_s1_lk> N1 \ $G1G]4hi))Կ6)rQ`!彰MiF#T>Ɍɪ)C_vdJtx)Fe@f:G.J<Ǯ! C3ScIܟ(WD8h?&5쎑.,ڀOҰfvc;x$)@%M ᯻-'H(B딲l~0E572s|XOHDs?!^Rz~UaU ٲG˽{ξ( 4;`VcR8wIʝdOy[:kt8YeԮX*Yk&B9x iikqbq}BcPc?z,J|z%Fw.sG{6{Kw vT" T?5~*jg:I/BhTlRDs-I2;=(N<].˃7@RsX^ѫE}gOq$oA0_{1LB P/Z觼DlJ{ 3}MP'qj!DLX+CJlPU/!FRLrO2ywD)cB8.@E'nWFdC_Two̬Si ~"<. t[|wDUxJakf靳t)ǡ vX'|7 .zWG3]p+~M['Vp0 Q䞤K Q#l6t O4ꇲh h׷6e Vߴ~Pm Un=8BWCX3k}q $jS;Mct;T\3 ~p.qu>"g9}8U Utc};wY0aH.0s.9!&vXu_ _by-_Jz"Al~2ڗ$X).]esFlF< ZGɓ Rz3=!Is ) 78hfaev5XVϯЧ HCLCf2ofsB"iȕX˝#獁^FTanrɎ 2T+TrQk~S*! ǢtQTM$%WVLHE1DmBޘ޶v,p J[L{Jp8Nc[g>hpy|d֍!8H  T:Ľ?~v,f|'\taR{Nh3$  V2k2E߷N顜"HidFfp6.j$8~, NP_P㣲Vh:24Ht2Jڡp:~!Z#s,B Dxs,F^.d~( '@X ܟ1-nmu5]>.Dϑ)s:qLtX G $]S 醙5=+zm vιV8U!_)hO.lgLm'2[?\PĜE=-:Ѷ4OTiGGEuFzyxӛEPp(P"d) TnLDMD<#~ƎͽŗFnT03޹,rZ"f@#[8.,w2ڎԖjNXraWN7IPldK DN!1} ܦ.|m _lbOUK`V$!$Xџk.e*'F?OXY c`RU酚sXg&>˦i}n&Zckb1F\N wv_Sa3,7)tU6m283Q?D y`ejEEgI (T(R@!MWR"eLN辑Fx3_cd?)_ n]Uc"$nğK"i!mPmbFkoVō{ n^-eA^gi~:w11´hj\3{QlxK91 bE/&1,k_$.kMrMM CyB0HYD=BѢ\q_osK['Z S /cf-R7$0Jft;Ld}DLCDd6=ĬH{WA>Ptx-ZJHǎ"[Q0xtY鿺6B7)7{2hsemHO޺$AIW1bw;EI3A}a)Eh9ׯ Z! 7o;]%mV('v#5Fi M?i~_ԧ)^za1N o)UWo>E^5!4 GSx[}ު.I6l #-2mLJj,t7Ka@-B<_7|*8fH C=ft̥4ùS e<O/j"CPMn 4 WRaƇ6mz<l/=X7SikY fӜ'0S9AC95 {0*cUls =pgs0u ,.ML ]]b"+>.X)=ACKg;rG刐* ]I;iN}-""Kk ߜ;BEc."76Fly[~32{B|kjF޾ZhT<nƗjh#!*Y?k*f`|+)(!d*m:篫}ouI1ݧDwn"Jr؜F{Fͱ;Iǒ5*-\R9-Y4<Ͷڃ zb3>'he:ºAQ`6C>Y[nhk? x+~fy+z> )3h3l30P6A+1ԮnsPz?]\ބm8{8S/Ζ8}vJ;]2KejyX!4<{C?C$6 vYI)rDfu[Nj.K:!9nT s_n!5 g΍+~VMRM8q'PdcGUN䛚z1B1$ErɃۡo^D3ȱ3 @Œy[x"/K" " tpZ#ǖ%٭8O⻂ }Yݨݙ`9Uv{O|"JȜ}y]Rq7Bby^{K9߫^{M/Z2 hE\6`{T6u{؎s1pd ̗b5\0vͬl3჈w5sƖET.1д*iA)A^2<mN,c^P9y![Svc[x8̠w#☗ȢkTE(Nj֦~™bQM|p  Hx‡"uR"Y@H@OiOdFy'l̘=f š$Ϝ8=+'?^LCE>R1qkxh+CgZ{;Ź-s#e~M{˕Ѫ}b > Ddv8A9;Sy8\Tn+Av^9 <㣵*\c?g9hm WXlXaV!.=G9LJ>I] SIM/2.ZA1ƫy9GhvYSjAN'ͱ!v}[ Qh 0yS3V{G- &̀ 3NlKȴAy_:.<͸6lX~B@{#- Z~1Hitm- q g}-ح"SCNhʊa|OoL\BБg;}6vP庠&Pg.J?Qr)cd;Jn9[ M}~[W0#%7?|wOYO1;Le&5HlajRaD2V"6LEMZ"W_)[J&7Xȇ7[yt`~)BH%Yukki` Jܞ0B`/7叉 T?٤viN\:McZLKd#$C8Y4My\Y퓿tfL!rPG5fC~th_h]o7o2.X]YX|} jn ˛`a(GLFVha8i}†O=}ꟕ(vitAr9W6{ /OۂVZ+c=xVLI?Pdg ۷ڿ7Io9us7ԘDD  %j[{ O3 Gqt}oby`eTlY,Gӆ{`%ڊ6 Y?F ?Ĝ?_eviu}0-ټi3L\]7Bv'#A}5+UPj+9Jbs A0ӭu}{zc[  TwLC;HǞZ24+ZC zP%oNwZ :GFgo[T=T-R)pĈCMnkDِ4UkwTx_*Q?\R~{:8ra_M}qap&VQi| /9>MGeB‹s@^1)7iH!U$Uu԰Pr;$9K_BZHj ꡓ*8"]8U4(|\T``2绤,{*~T8PVӏ b|vX-n6SsļGRזvG4?;e:p}~CaGnksQiNkԨ7Ȁ\Q,M7P l rU`!(Gr/֧{l=Mlzl{e;O (4]I`;uF҂nBӀm:fÓW`W 12-dD4* Hv?K 9vW(tt. ډ<_ap|Bhˣ.Kt>eL04^@gG=jk 0;"*Z)î$Y@ 6+79PLmAtΏ[x֑e$K$uXh2?~ocG 9*"K.ʡF[|a`k͌P<<;C''_;ɇ_MVY,Rj5"p?%jLJh$P}Kªا4D4 cź*|S @~7oݹ¼&€$:pHJ3ȮHMc!b{$ LDUUgzb6:{O<fWAWqh 3SYߙ-zl^? Pyy-x;x}wD+}wS0,Z~C_4m/l3\h]JJn뿰h:릖OM5xBy@"F4-Hj+uޡt]3f}TȔ .^=njSEp lD=)FtGJa|{=AIkttgH մUE'Ǎ\#ʊZK{Cƾ pgCN"]l2B%Ӻ*rso^KE']d΋O֤2 RHW|/P R2Xtk_],m"#n_Sfk)BΧ%H<;׶fFV{AkGv'{p$qD2/Qtia +l-^N/l4JTN+7)X!FȠ}{͒}I9^ɠ \=>^W=.J5q y¤EwQbCw=jS/KMҽK)4zԿRVj>GjyDW\p5Xl7a84C7?P=Cы[>C^'fXU8xKe Z@Yu' ӯēUZtNfnmJ8+^ Č9~im+:/eY q_A~x`X{ }xDM~:6:(gC,놆%?(j((1q+T?!W뽮Cߊ589Ǣh2@GzƼĹ`ZoPq4/bֿb™攒 az >Hg\x> c qs&>o~)A&qv/Ƣ-1\:*q|TPM VKօK8KF *2Tm=,_}E5 b r,V,:Ԯ;VػQEqN t5o};0$Ϝ@{zkvzv砣YH%)s-1ǂob/,g޳OLωtEI>Fz71t|:>#%RJq%RuOYM`?M>Dĭ]b E4TLWM"G ȹ3dǹDCu{ԑ9p;B{焄O/PӪՈ%߹Hy#EMj&5J CSN}١ai5#4(J-V$f[;9`#R!,_jT';k(-=8b2}=زfi~0Дgq&Z/H;K bNNɢV$eFiEv1i\y/= Yȷ=1=ή;M8Y`B,ovW Gx?l1loiN-%=\62dUC@/y=~(U_( $ר!yǐ'-S@'LǪ|@jp[7MܨtjkTS`Gc02ZWz4vҤy80 \΢°{[rPIhqO_^L,jY צQ4[R $a3\Y;1h+Tqq|pG V~&~Q( !/D߆-[Zmظ63:[ږg*apR=P,&NWQq90룓)᧭]EtiYYku_U[X`;cd!?2\%QȪ$<;lCG>qj4^ؒDZYM%nTcQت5j}Gf9ﺲ@anxx$7wܫδݾMX4an1O@~<\k޻QrlVPəq@YTD1կo;GR{&F^&2x ִ90cA0VH/4/|dfB!AHiFx g)&a(Cz/WϸH%Wѵܢ>;i*igKH*{y׍} S㩵8TUG=)1A`³~r>2Fn8tNJI1^[[ _"64 nN^I^ ]]tdgKNs;&++tw{W"QڂQajy{;|S7!9By=a/{=b|>M|l^X 8eRZYXhT!: pKayJ̣OQ_gڒLI_&\fcstJ'\AGYRy}Au8qU}SULg^Lq a4'F2#DBא0{fRח0=]j 4km')Sٙ䃽-mXd!ݷ9K4v\J{5u0h bCDha2;tG;Bq؃c@ʩxTښ8ZMF"@zL%zEgʣ2lY/#3^+}Ӳ?^/"w]?D 'V)dJZ'Y'xr Y^ &K ]go'Pi 2yntc(OO,LÃ9ܰ͌m);@*-_ a/Sa ,A 01f^(9gn-omʞGu:{$}-;y|Oh,Ōʑ6 Ua;1VyRcu;͋r +$aZ8Q[r '}iI)ێ-qcԧdOS>8 *bX;ꁛ;%c| ȡΎv# Ig4½&P2,щ ms4 $, R ]nelFoKbɧ!^ R#Ӵ2\q.6}1|MY7EXa745v"Ǿ(H-WL@ q~;`@xyd͍=S*jďr-ēw N 6\#?AljY?oY4~eTP(kAG/S&kQ tIIl(3_k Xl!z $gↃFshEyD ᳁jS0]S< xIi<C"eFc3~huӹqJX{M("F=ƊYҸ J>gn&}VZKn k7SB{-xk=۟LQР^[4u9FWk#i_ ""d??e]Rގ͑Yc*7AIK٢Õ^刕I\[ǣ?^D0άBb !aB_)&*+b_\u@v Jj|U'UjblweOwz->TZĪ/i@ܾB*#B , fEQoӧMk_n%)5$n@D(UU~E)n% Q ,$;'SF0YtǬ׊ǃC:Uf% 9 =ט|;9{xx@OR$)F_o32VsԮG -RU/m80\e*Sɛ](͏NC 2aH`ɠ>=i?DYTJL~qKw'QT)\e NJK1}@/vF۰!&T nУ/"M]C%QVJt4]C}ӏ}\>7u"A>`D -痿Km/`"hZ^B"rQ9y57I U[g:AY_b&;dUKIA>bAY)KxVFUYB"?/©Nj/}y>) @Oqv=JC {{?d [ׯI$g;wQ=D eTyXjY B4اCS@}P%g&Df#4b#40+7Ϲ6C?g.CLe5WaMdQ>U lAz)(G CB؞N4 z`O kj"ڱ;*fBLC,5YE6/1e7o"nPĺ#ib\q{_J>z R~Ĭ}oh0?TP7B#`tR:ަ&4M~Ij&+bX\wZWew k[^I2+}0Lޜ 4 t=sAnۇ~0!).x+2fuKZqA(kS? 0׹ЌfհcpOO%wߏ+-̇KC/g&x;cdExsnZdsHe韂|NNmk_MT^~[D-&akmIor x f~,^Ѐ5sGRS!z zNEy^5Nccy%B5F:5z,iK̳X8tg7-:_!EIۊ'q?jf_]E`K9a:׃ F2#_ê "xu#s"iA {[D A#-DEQ[h,i-?,HAeh KBӖ8MH_89^)зElT Er>.9FӌS|di`RcЊ kgZr\%sUOݰ438q/. 8[X eaeY΁Ѕob7"^]K|-*ye(Wg.oa[ T1K-~o|Ң_xVcUYCd-:ˮayF,HGBB7ͼb)#?s7$ P'h׹{% 'R=})loO\c'U#MѽeNpJ{ 1iZ'4(#@mmV$cAloI=SZmC q4wNtUqX*8:>=w@6?#Jv4N> BsŝHND k7xN8ACFg_0?Be~~s9]Pgs3vhP1@9uJa`ldu[w'_vs87d8Q&!h y g YQB%R)wK{Eծ|?G<XaUH āϯknĆ..K'xKkR,3 7/M+ AV/s)> Mfң@$͙r!Ŋevp:aa='=gXil۪F{;r (Ɠ&afCYq1XB񁣵iFd8`6yq/\XJ,6[ 呐4vGHLwٕw.<%I] )+WBXͤT{>qqiOh~R! [g׆e9L@}x=.P}Rpv@Y2Օ$9 C,ad\<$[<ȰC.iħ!J8;ƫf2]|ũV AEQq2F%qQ|kt޹JN շkEjI2XU ainDF$(kXWP.[Leʮ Bf- 2=cA&zm"{i8Ez:6$ek(JV?VyO;;MpCo/M]} \Ӌ90i(r{80aJg+ &ɐ&VXu3![ 5XLa*'bIQn.D؊4V`]t% ?1{*#=a:M}j 7@I"m'|V-;tVL:k[Q~cJj=%^rkK|LG;?7nr&bfۮ 奻cW೿y1hDHPԘ@Gټܿ0VdR">l+oD`XϫH6!bؘ6bNŪ#pqy>сQnFf 6~2ycsQ b8)V ^Vґ :VK\q8DeҬSD=Z7Z (> endobj 280 0 obj << /Length1 725 /Length2 29334 /Length3 0 /Length 29885 /Filter /FlateDecode >> stream xlcp.߶=ٱضm{Ƕm[;ޱm۶mv9ĘkvUw&%uV7aec(02paHIM -lE M&e{# lghaf 0Wfm`lacPs02𸺺 :9Slbp67ZX4$rq[Gk@Ʉ`j05NNt"`j1SG; @T^E``k ىtGpem?`FC3 [Mﰱ!??RMLAX[ؘ(l]Mv&A l,=t6G A[cwIX]LV7Ț[MUc;[k]V:_iQ[#;c [3?z8'𯴂ſ'D/khba,seb`21Y >E_&w#e;#`˔2_тrp*`!8ޅ.ؠx`&m[*H[]-Y%1) ^3qu8]7b?GX)v〳̣2gh)> mB,]nvBA~/7hru.}G>ȱ䤘+Rf0+EV}"A "fUg!&([W@=9=TÆ?M]S`5v Ѩtẳ8z MhQbv@/ET2[KPdUdkV9X9'"!A.y+UG< 6;fA)`8O޲m_(h;UNs{q0&n&HYnIiZZu.7xUqo$7ɕ|8Ék%z˨9~tJw)v b,Ut+_X̘{¬ TXxV@ 0-w i=s;t4(mblOVB$sDӆU__L&wFT@)j̸Q2K ϑN_YV! vZ${ `.Y΀lg! ؏"d1Wc =zXv*CThN*}($AQg@cgr Rz4@ 9c%!Q(Nُ'*T )f"%mr ̧kHl̃ku=eQk:8ZRXڣ<ҍ`\ىOW>+(y/@hBYGoevhˤkv%“ AGeLo!&u Fbn=SļEAmL_*vl짬n`.d.(|8 ^?dX)2e)t*%c-O`Xqp|Z 5+"Mhb|6cR^[\ Lyr$%INkAHҾ-Oͮp1$CP" 5,~w2}),]P(Ec|^uHK9bqήCg¯Xd&r5I2J_'U۽L+ <;oFǿA'fnMQZ^k`d?Dk_DSiHzlߖPIv&'tCV,2P\|l _Ț?D6h3y+1nieӏTHS: ҌЅ 4(=bJћR >k)jIdΖ޵ jl-('i&5 Z-!. 6:Hcb+[$,=բDxnB3d 5a~-a0ii&1J {Kh^ؚVF'H䤬rvrĹbm ؂0^J# +5 'YϚCAt]8 ՜FPhS`ULCyiBX9E캡iSg?d>]rB~^'iڸ6m _l{;,.­r~.C)Oү6Aߋ5abݒqaUi%x {u{ u4'rjvgc!U!]+\:mvP~!OvPuv.-A6v 6«#nz$2~d+lPP XՃ_b<%@:yp}R ֤yHV[h[eRklLF"؄3CkXk9nR4AM-P,vq9\=4W@c^ȓqeʹ82ݐ[K.꬙1Ao#^mA[mJ݇eOl-C/r[1"S7el`mUфiCqo)%h{=_a}Xߧ!] -V,eJ{*tX U_2[?§SS8(JSVݳ5$l4(wi%Ebر4èLDvoFFYC읉 t-<&&fzޡ)T|@|̽[꯼L/gw:S/ Dq:0bC%^gܣVmk1fsYCe4A')9 !"`sur+y  ђR V֖nVB!SNG״'553%KRgA[-=_'zZGqO飏4D땋\xrK߰W2ITMX?r. E{C'AK7 +qD]P Nx+z6Ʊcm)vLhi;̃OđQ%b͑xN8]c~CP)bjh-. *Iȓ s3Qb;h ::sEw)a^O/5II|ZdfGHDw(Q+tcGSCX4bɚoXvK.HfKk!,zm7\[+[LAnxa6 ϱ $!$D@|ъcȟm3Bta+r1D<<bBzDD| F>`cw4/Lnr յLL` 3CwͲJIz5%z49]q=o3:<_[L&T0_McJ؜' O* 0rA﫚%]fGyʼ ?#6?@,ikEEj#~A'/! 'eFZ}Kg(Emx eW>a-]O;>F}~E/:dl!刑羇RJΐ貭Z giA$zZ.ХUMuNujƒJmo=Ʈ8eI{Y(nZ+!)BC^vХn xpgtPA-vuNh'qX}ҖfLֶ`׳sSR2coq.IMӕ{R_bd=c}'g%a)g2E-LѭWrD-&(o_E|)eT/[/?v S7|#"l59t`QN*b%P^*_ͣfqKM7"6܀5 -(IWd!\)Z2Lm!b2wဿQ qk?XnS>w)qƯfv2kA]03(7 芰<↢Ü\bbÑ,AT 9Y 82-J,V 1$ <o/b6ܛ% b18'cq XA [K<L&=.u߂j^lK>\aiis6!}x +D]WSUvGzS</Cϳ+G fH"NXg"6>erTĢ:`յ}䦐c xi%s|C\]Lq--ęׁ>^MV`2@sq?HQf{{$bBy<Ʈ xř@`PJb`x >-Bj3R{uT!&oUint{]w c՚C dv #]f_6_w`gi#"/^Ph|2!|^3t}D#0 _'uPgNwvԿHfS"wCUt}n=wfȦ:S>Dȣ2~SO;PS:r Ԫ\`QBb-Pn! qዖנ[Cliݜ^(n~`B6:ߨ,8iq[Q"_`6]6`x1@Vw㱢0Ot,_a<"q5_uL{#^^$-aMTog=uWk(A eUO/kq$ rl9wQ$I"J?,YOW&;2@$1`3CX }^;q: l!H S3 PE-O$X'y#nB8VyeDΫ 1_K^è{6Y:R~o.uG7OTL/<\KQ Ja oi+_dcwV O?d]PiO$D2Idbeؓw GUDPg"jcu%?_H؅7\؋ΰ8}[XDd'fӢ@h 9`F; #JV F^i%\qy7D@X$1ig fЖO wv"i]%)(yA^%~VAy _g7UGvjG]_LZYTL6]F)-de]m:w{|xDU\PEl9:zC.a!h[c+qyO: f[C(FE4~[!,Nߜ-%QԽ Eq`o o_7\!VU@]P[MC?=Mx,VOE7Ό$"AXyfl H= u1nj@F2ys35*US9mUzNPauCUa48M ,_ ^/,ddzJRVLpe)]7aU%eFJ=&y 0(cx($"!mNpR&aд%}li$XTM+@0dk90DzSci͛u0$f¥ljX>xJ-iyEsmJ /gE1 ־XzIs;i!,*%R+ɳpb6"ϲ,/[; PJa% YWX#+݌$Tw.U>r~a8* 6&ΩBtS9yQB!#Cm]6Qiz6+}7&Tve"P:w>L+.VAkrk tsaw@{:vҪw#C} \'ӓDn3un(hybRp乲 |'y@+-t-h,4@S!k D)%. K*ވUb"\y+b|i$Nf2]2 i f-T seҺ6["-.<XrST\h'miۃQ,4#bx L7<9s! PƆ tLں>ȿmmy:+I5\ IE'u(~ʭ>Cc69hf1|q՚=z²76}%I:J~PH8#;;>_ l9Bv 3[젷iaZxAj>(ze܄wky4pcR۽gg0,S}{UvTof}ѵW',햅"|W gD4r+|L6z{M𖄣}e=kû`q^ހOTnUcdId輩xӶ3XN9{?P`N:LPxCl;p&b73[q~~lCQ}G#YgŷTkV#+ޞf7Rd 3Ʒ*S4N[p2"·&i3{eE#~{`SAP}l!?ׯF*phח{XMƛM7<630fcւEš'|V[Ĥ\>OP7b(pf_ Fx~F a+@?ḏ?-Ԋ#\U;XĨb~KIs-ƹQ}TX 3P[KckY.:WiJDY"0&p MͷAFl^YT3xJ dI0P[1gRJ{4ΰΆ5Md).*N?~2AFhXz㰱Ђv|aP~BG^?tRXIh E)61 +n#qpz U7/Wj)KV~4V-SrPzm3\'WTw+d"7^]9 qOT;+>VVM&@&эb4&0Y'ɯL\>/+QӰ-CQNK/!+'ķFBh+s+>'5 h}3 "Xj!u]zsٻQ+ A}YikvuRGp<ot s7,4H.F D<"h@C%jt&Ub|wTNs`&‰~D,Y1PmuGu:xҢyX(vFWNleñFۦå &P_"Dt6m\2!`Lsí̷bSRϋHRئƀ5g- ֗"z mѤ >rGxQ/LVEqRE@Ajji(S;_$1{AH4;zMWYQtRL>g`gNTlj@-%{ъ8c𢗨ZG]lR,Gi򼖥.T$N"6^ӗ;B?53Y*->S8r>D;|$KŘzrwHѷX794bg o}Z$ESc3-VR 9c[FADe: LD9Kr 35X@f=Z!ov1[̜Xn֚Q:`T1+F&ߓ <8}%t~-ZrdV9}~~m T{|pp?6 g ֥䊭t}x/Z&@ NUT hr" \kV]?:5ŢAKأa~x[` @Hb:9G4+DQK;A"|+t@/'9O޻A3ӞWlvhAY}x$0e0˛`"Ƅ:Pt R p$ۚgg#[PفX&SV]IѠIhGXmRD0trxK9QMi;'dez, |$i84S։szӭ8@AD)9F͌qnҒջ݀4ټ`[!&P!$ =V=YxS'G(5btsaIJsNY ZA"7R}w41 nS # I# f#KCkv4WLJ|7eƹ)K$!InÞ?YAPڷ8z™V|YJQ&BSMDNsR>"98 *3(EÝO1#?-FRTȫG}XJn4%Y]BpTYa/` YaMaժsg ,fk'ԕG&) n > z\ENR(^ѷ]r@w ^<7+K-]7"(+Qd׸_zA1LrLk[EEmeηDV}B©g&}{0:q>k>tVphG$ \xHDz]&#ŬUQ/WPj.VzJ!!U4b`PӮEpn4,(0M1 I eZC%b3mt:1%?S"%]H+ladi$1q y=fg/,.E亱?Y֞݋Kk"ƽz8S I::z ~NWzr|))y^!"L7e"b[}]/v3o]T>D)jaob ;ɵKBM&v,#A.1T@41U{~:cݐJ1ɟ,G'N?II))F|ւ՚%Zno:O]]%?@Kv>7E ڻ%=X2S%BR(9c8-WR7br.ٶQ"QOgk%O{ !7] bK)yŹdYI6ig~Qar`thI2?dNA.5|MƐΔ6֫ۀNŹFȎ*2=8 0Knk;tI8|xN MЗJH\pjuEp U&dW?ojO-nN:] !/nS3(g!>_oBQ j]dP2E|Xʚ[[Ae2"%LRrR$NA":m9{wKn^w6vYOoklعfd3b@1aIl:\46XqDge UEQ%'EJR$ 䅷)ٴU7>[:r3ϫ=O{K(v9B7W~ hN; ި*4HD<M&ۆ hā#ZXJVXbc ^KL_q>CD;{(E,PiXK[q.I,zbCwx52psh5sCU ;F'ZI^keg![F~\" _l`1i &l!7$&E|Hj!YJ>c֧IE(J:DWxX*wxC8JGtYH!^}йWГ6>}2T#TJoIp["z)c<!Vt [l<R}4x_b6_Xy0ZX8GH+Wm{sI`gEI= hd~ҮnF 99+{}'u2 cكt &zc`o 0&uXɨoQ>^ ]N Y+^ʠX hpKQ^R G`O댊L1r0IGx-Jgy/-ĐEGV}^cFGs!KDW=Bn,( _0t>wBoaͱ}ձpe8 ֏%y|#^d[D4}3ՂjmP5{~ 3*7H!Ӌ_6=7=G1'Bn}>;2˶}!uC9C8yٶۛbckTN n "KFvվ ?ʑBi7Si %;\<41ݣ:/(}c`F{qGh剎cW@J e,}3KXT0Vdc@@9h2*GN-`?UC {!1nO{cusNbIxu>E )_evʝWMGR9+Hx`37sB$q}4H+T5Pٯk/#n~㫮C`EhoWTX՛hR6.U+V1uri%%M(!&"Ze8 P x_F/)ĚwK0|*;;s f|AGVUn/_мrR}M9;Vܰw[ (}S!@u!0Gu=Nʋ0fx6 Lz[9̗V3jeoۛ(!!&/ґD 'mS SE9A{Ckh_#`:ˑ(!;%8 4H^?@0=_i `Ԡx0g)u)pZl@l+Z_`A5\w!kVDH Eƺ[;rDH3:i-l-T~Z{MV7r]b87(h1KW f>yu/Lp4Ֆ>+% >S$T~vMDM]yAzL PޏFN^ʹl<T֔>bEfj. Z;FB؟I'X]"*:+r$싅hp-IDRݢҪo\ Ł[l̘RSV&^ %]@]+0AwԎ=#q'(w~Y:UtV/$D)WR Ap"%Ύa`YCk'b`Ȓp: lQ~1gTjF`2voiLr 4?u7e/lѱDEJP\~ҍ|}}g[%'i#q { 0P'[&+u“>^;pˆ&c4 ʡ@jg~)D!n%&KfU㡞2߼˨ؗղDݹw{ydhN@tohML'tV:)l/,_ҟ>D8d7Qi QW97[E֧I篱BQqS)L#h|0f/#7 58zgXkXE;eDIMhF+4oW(5qE-B,uX~}fYVp zDVpr%Jf3~[![Em,& :6.x_B/I;n~r\oƦhN[|8g$G?&6 H+S,Gk칌bO&)-a!) t*' S \8XdyhB?O $E"z"ݻהV--.hqGS&S8 6XUA񪫮rCH'V,\3Ԯֵ:;כjE6.pkϟx):w5t5Y<1ccnj"CRĻq<ƧTa6˩tO2tVI4a8dC:>m: wiH2'@r !R+PVsdS Q:b^/[ѯ]Z|>,2RQaW Λsnȶ)8F:X$v2P {z% ]R:aī75Ҙ2 36><%:xCUҞy;8}VxUi) D2skV sޑ@]6?i1 u[w!j_}cF+P^cB*RpRzS ̠B'>K k'Kr_׿Vc;uYvW䜓XݙTg";-W%"*F %PwK<9qZy/|I* [P Ȭsy,2X Zy`;؅/hD̤XnSyWҁߦ/U,$ݳըTe֧?wJ:AXH"rJ;s"U-Cs=;F.cJx]Ao>N'W[#0t! ~bgk*3N']"ͨ1jkwlRlG5d@:ۮA3sSEG\-{'U옍.`-d*$Vryǀa>\p^sp 2bL4ȰRN8 $f+k6oO&^w{'KItUVMH%٠eyK6S06 kޥ9f.aQ'=,㋇HhnKMDQ+~ ?qF Sz6]V^x8pv0*N)tYVwGƝ &~;Pҝ.>#PeA.J]9o,#⹥xj*h!SW|6@;D"bq@=$=ĞhNln IۼͯC[Io||2U9?{ 88Rp:M*]ZGv^I| ۄ(฾(UN$9_ kJ_ hU]'@-}v[G-uSVծz0Tt%Zw|EbV 2?JO@WMci)|HfDEWEJ2{A U{j[&zh|RumWߺI fHL=WMq @ybSP]M"Y P:~^<хNC ٱ ']zH38q%x_gy*L`ou#"58<3,E;[km]!5lngDXy&)Rpz􏝕Eœ!K %}ttֺx*~k2$Tbz'4PR^jCaaNl%R2mF0= h xÍ82<7fT-( 5ى]}@.蘲o>{Dx;El{Ŧ}oLe81|bf&{Bxu5PM |/,5]x%]Sѥ~ XJ8WkU*Ӄ]ǖ*f0K?XIz!v֜:?ނ*]w+yZԋw,x^p3Ov@(̫( 6>6-g` 6(w,.ܰV%Q;L.QS@ci_ۿU4nRx8*͘`+TIK\*7d#H C+0v/"XO0p3ff+b)+)nTICD/ٙ sA+C ;I09&ƻTwڎTdx"iމ[ mE%h6z#բ)@CWxgʬ_.ԶE=NLi+:xu({ݜ]baUz a2+u~d9&#LƼN8ul7&[PgKAN/X)}[ d) | ;8φ4zM={ca@&+kna/=0"Lu.!#y+0w 6)ƻv_og/Wr iY.츰Q-f=j"Wäe+F]Lp#Wϥ\:ge|@4 *oFłU&V[^ /,:0{M\}3R @Ǎ_iq)8# и+cS!ڍcЋd`-9AE>Jpf΃ PHz 6,l ٖŋ8"O > ]^A-F`r0.W&pn9k acQormX= mxO񚷌3!GLĹ&'m8d0_\ree 1iPj蔂9Ey9mpGLVq,>"wɜ>LPZ1x ] Zk :rbwHIT4!9_o/oMeC 4gu,):뎂 hPW+"m&gFe1T&1-, h±#ٳݣ4uѣuNtMaE ۬q5bD1dU mnE;tm߁,ܢ~ `FNo(v529ǚqlUN 84|5293o $Z>9oCӫUȜtLWh1ڸ/\UV:ĔL,Q4X)M+5ɮas}Rױ(fn\|x ~8PFz:#9hM!X_eSWdv[YtR %. _ OIЖ|-GW{Q)RT7SrgĚX!l U("\4U Z`,:@LwмCt!l˶ 6sY oL{:#4ܠv h5{iإ眹#C(SU~B:ޚv:h0>i` ȥ O8+7V9_A Elۿ|v0{>tpÚ8s/"-HoE`SMo|rgrq*iL}MݱwcPD~#PvppoF2:&| h=L\ILP[Ƚ#īH}igm1`&7LnostĚ<]z)oy4q?¹?u/Jx@ќj<40(6p!z]xbL6j+kџ=խIEKl* 5F "`xYm1fۧHӆ_{PO/T3(6&ŦN6i靫Kk`NHJu˟$%@،L!*Ɍ 3H8nvh//7kQEס,Sxy Gxe7qP'#2Q/⥲ij"t.7s-N:V]Ipg9~/!`g =de3//G~X{i1\΅͗4NM@iIĚ28[b +Ch:MQ̦nDkc E^Mi/0mTIYAicM@& tu&|u:6Z:921| @ * \vȩ"x~,NMdl㦅䟴dPQ&3PwbWF=fpY`6t:׉- PCisA+NP{.0uنj* kYy3A_8?? 6?> U̩¹f~oy; Pf',wȪw}lAL)SzD$=oDKσ.HZA(S_)>=6*!Q1U{qoY<\@>nL[O$#qZVMMsH6o/JZ? qgJgfe;gWoQK% &V$P,#<;{_Rbr\W<䶲Dz0<$A p{+9gȖRE%괺b4j]^NҿXքln͘H+2#c,&=?0 ++RW_Zcdwy<(g-;`Y_q=HT pkU@ykh3^,@ /HX8,#X lb|k@mEpJnY霡Ac%2A*Nm}C݆@~Xµm:C.cH)uuOUim wg$*S{$*+4GhM:%mAH^8-bey| Po8zt J/>f9_N7!ٹќq:.ֹNÚ_8sy?]r}} a̬({79eih9[b=ld(0 ]R}mc;dApr (P:~KDk]{MX4{K8zAMcM(ʱWChFxu>2 o% >Yv2Qr9ΝHQNtMԖ$K6ǣ՘>sZTD +=jEGs|hoTU*NK>cwTPB%ʤ0" OyVOsFkԛy ZP#}3Aeļzd.m1C}Ys氵o#47RqaEҖϔrH)L ܾ`OLS"DTأngˣ AY^m}z#kׂ:neq^gµc\cٙoE_dGi\(CgTNvb8}˟R۠娦>Bbܖ: DgI^}!ȀxEkCmΚr=|P2=t hSG`\eTԈ։yLmɅuZU|%o'ЃL_r,cHPݱgDQb>Lɔ_ǵF3,~jEZ s76K{jb\Ar&|#ZO㓾 +wZmB+{GAI, $\>nE|]$9<՘:;3Rk<(gknx('=Iuv[k]u Ft/klU㞋3zC,YTOI{әT$FRf?_!ʆ_MJ+`,Y 'Q}V-!]_r)$NO y`xߩqEn=sP"S{}prܯL;4 S{-{ZG/evUlwv[zGӈ"nQ(߮1q 6`Uά ' /zcFIda0<ᵃY1n/LlKu VN!MaM0|#cn3 ʋW_6ITխ ܬÒs,N ,%S+Myoai: _k[` 9ê{>|Qȸº:g2oԁS+icn tBueݻ fyA9t+:Kds3-"n5 ȈHQύ إCoIT ք"znqLŊN,ۡ .4>h)3<Ԥ2"(w2{"~(!ݎu+T:f<'RiwV1k(3{LfBfyՊmELJH>8߄XZZyuK;U"o K/Pa/9<˾*ۺzȳh]p[r%R)B+pI)@7|:( ](\8'A{/V%v(ሒ^3JNΚ~@.}U}X[tq endstream endobj 281 0 obj << /Type /FontDescriptor /FontName /RGKNBW+SFTT1095 /Flags 4 /FontBBox [-204 -361 1351 830] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/B/C/M/P/T/a/b/c/colon/d/e/f/g/greater/h/hyphen/i/k/l/m/n/o/one/p/parenleft/parenright/period/r/s/semicolon/slash/t/u/underscore/w/x/y) /FontFile 280 0 R >> endobj 282 0 obj << /Length1 725 /Length2 18785 /Length3 0 /Length 19306 /Filter /FlateDecode >> stream xlsp.gŶ~m۶m۶m۶W{gS_t\}M]3=CJ(fo`HHPSQadaa01C ;XۉrMMʦF&#4)@@aLo%@ focfilqsspsvsr)`fic WДP˩ML m F6KcS;gSJ? 09?̜m*br*Qaza @Fv.\x+:H6#?V'HtЌKc4x3Gm_?CJ?ޮ66r a{[WS'_ܻ;Yt1 A;cYD]\MV7ȚX?3&v6gBx RZ6ۛXڙ]6+Z'`mYC'K6ݿR_%%$dMefc02318|\cW''S;O,m;LM=LW썹C*D{amZukReM'݃ |Whތd$@ةOϻor+9RYcH$. vO!sI^VKv>9*bչD 'RSbHjJD!#DkCMđ! F@"Z{D)9UbP"vp[Ѭ ^,nKz>>e ՒorX_`䟊xRrd%v…WO9-& Wi#Ի)~srRjr.Z$ќ]^xqbauORU\&u،L~jף(|UmFg~ܓr(b"=Q'$m1e ykTUi@g{ox [Kb!ѠX}-!mP"r◳zZ@pآnDyb<^fǂzi5CWQ9!@9q zS%~pϏ0M7'Cp(?ڂ1J3g%1v p|9&1!gja6_UySE{,LK"ӌF KKn9CeԙL]*J|RW:м¶zǵ9!bń֛Z]Ǿ8W@qdw)/vP<b-y+|}ro!+0ĠPKe#Ng)qRکg߬Q ,P8U:% $%/Kl3y0&D)YÍ~jOIGhJt@K˔DE lhʉݐʽ3g3^4ǶanOBk-KG#>&p}uP|&-8#~uU}:fXd¸fstYy!:?F6/ZY*2|ڬ"OǍVjĬ o[k?&wd@8_S,bY҃o9% IYey g,e#+ZbAtJҚ=`8$p\:suCy_G HyĦ¬Ȉ^kGOb1of~:pDʈMSI~3r h " t{5rl/'H N`cQAu4*884Q7$elAaS}#XB8FLIyA)'ؙ /g wz'.C!J8q~6 K n9%9L :4cEGRj~$?eJJ#oϡ8~b՝ѐc@BX a^uhQXUg zD04%A2Aԟ,׽5a~Z^eЃ؜3,leזb%r^M9ghcaGYW :LlK/i Lx'N,bàh Mm#l+@ϝ&鲤;x &`RDxmѥ5Y5q;!nPGY L1}Bv2L["nsVY9e;yzXA F4Sd[4Gl4:a,o +]`Ye_J+EO6j:NW2Z E_!jmiWJ?0%2488!Ph׽:i~$GWLw >Q:'Cf^'P@q ;^,B-WZ\#/CM&G*j`}]}'uv@tuyQGw KN2{wފ,CdU.t`3\鰺9͈41Fr`K,;F9>c мp.$IK<9jJt212[񯆫aw:*(~n`&#bn6Ks4MωVCQWJ_&L[VC Qrɑ9;Ϥ8tVy&|y3}=*-H>O! =ަ8Lҙ"~mXVN/ot bkԯӇ-l6ۉ T./":E!!p!f|7pS%6u1_t vdTCцn@HfYkشjEם'Q4ӳ0 luwL^GPhUr8YA &G4;xa7E1Ł84| `jYY=OtBn1-i͐$l Z.c_y)+R,F8M]7##B,u1YوM,Dm՚h7'9)oe VVdHdt& ;vIgi$6H4sS!F:1\# TSc4y!)]U톂p`U!: Cљb}v}l"/ r>Shpd9 FUE$9Cڤ3$N8sۯBJ,16l'贏 <=V-\/(heD^~'WPdJW_C[u.bY&J#s`Vlƴ}⦚Ja )!>Y9ü@=֤5CnF7 /86>2muGU8>T@O6%#Zir[_!Ac"",! E !)U J GKeͣaʌ!)6u̼];ѷPƔYsl ̨i()Yv2K* k*^}rucҘMVFqT &<ț$qe_nNHm]|[tnrYOn5ߢT`)50)OT"Qs\ 6POTcZCYdUa.[ 7H{X}}+݃+LRXK3C𕹶XJJtv5vΔi[~ѡ/S ]6>?T]Dfȯ~u䦯6%_z 2& GF xެH\ s~z5P`7!fm7fD7;ҐXV@3a2"4!s: IK,>V>8MZaǟ &[P(44ah@dW,e Y:V9s ?,S-e='IgXLtuTS73i'%;VhtD˜m7W`)-mQMjwH,79tGTޟZEZ^S6#R} Ҝ[5&R<*ALzvPV '}]A?,5 +ldʼz/>_-\Li$è|wΛ5Ht9';*l:)+ANjgQ=gxbSt¨KO $7=ظhT)? L~p(0OMu&Ûu~ kxl9p98U(bB*4)L[a&j P%_\EYU\f(N&Snw08!!…4\BH Xzce7(vS.w-]}I2P"4Td ;å6TjcX%"")a G31J+ l BPJjSmД„mMA'Qp|n;[37S"9̌P` !Zv l<ӻ:Sa;)xўqU>jm Kuȶ! *"د+$s)yНqdfPY< [L_&ȧ@Pz#ao !;.  S3 ĶS/\2o=vw/ /}^|Iխna~Msh#(;g ܖ%QGIE8SβQs!y}3wԺخQ24rFe)1eęa5\J1C*D(^k'Y ^&?K}@Cu'`d!>PM[lFGO;4o,)$2l I%l;.ߔLS#8*Qw]!>zn}L E\v3< '_/(.ӕ1h.jTq .rn u"ܱWڄLU1E\g߁qΣDۊ S2fDFhT>r@ $͹"SUrW`Mvgxʘ$Ȳh ?h[y$q_;1d31:Zè✏? XsZ$OE)64umG_4CXɋ7""!Yg4= / * E7=%M,ɪiV̚nD4-w=;oͫΊmnR}Z+KH+-bkez-)ƫ7T#Y&oj 9T;rD;E) _/j,%fN"gGOΏpDֺ˧߫7ꘕU,R#br̘<*k">Wn.ō Kn_7Ap:y@S+Ra8w*gqJJ6-ܑmw>jlOqL\xVM)aM;$^mrܲM{nq*"0]h]6ШnkqgG;ζ&1hq$z=|LL)aWV)d u/K3*TˇYu#g -ռ*ͳ5u`X,e|}ϦyCVks9gyO1=*1AjN{KEQ?$1X˩=z׿QZ-" n}0s1>yf@.%/;KG<(yce05TWR,B2ɖ{Wμsƛqrg"P.>pxkj Ro5hrMPtoP;OяNsct?]|+A4zÝF(GEpB]aly_$3h+#'<)gCgj:D_s7HDh$]ˆihƢI/ <ӣ;%fM"Ȭŧ2??aB*6߳q&"J=CHdQ08CGeJ$ty0Kpw"TDt&ș@:q€A*Be?<ޏh;5+`ZC*s`%Ekm P@'l`PP+(OZaA|-D )o,Ӑ:3__iv&pFda}:h_Auҡ߈<.geON!KS'Pܻ ?/~'@BKsٴ<OMM>htA]0@زziF*1|; &ъΪ~I "II qg$kN,iZ:Rmy8B%j]ptՍͥn;/%¸-SHpa~KJ]nG}DI/YW9 '28a;қ3 }k*,3}Jo0jւiJD Y |~f X/^yD"?2km1 y "j:&'p* m?'Z.)2UX)x4{a6{Y@88ǝ:`u1PP KX%X$(+ }v;^mnZV >d;麄+>I+1NFMSf9'b9Kv%%AH@ԴPXz5ծoE.~Fذȼy6y\l_l1\|8-f|E*h 1r Wn&R_|}9! m pO E8|'=9}]/38s&sg*VxFFiE{Yz~36Z/Wh xE0!6( 8% ={S&|Is d]=Z6RroEIƉXaJ,<؉DMoC3?xu=ʣF(2~!6-% 1\q(U M `U@u?;# bZ [0 ~GN1Ly 9mԙױӷ88ct1*h"/Utn Q"WvsxvAhlb!,W6;{i@峤B*JIGQs%ǟ+R׃5,ӳq3E*SyVRi#$5\!d*o-+In{l1n ,A{h~*1gYIB?C\\p!⸉jGƝT%:s?Y#M^RkXH1ȌWWfUUiS9`"gYm4')R2|@C+* {ReAt]ZJc"Պ7"r|8dN(IdI%޸AJA[j)sGj+Rb`T EuK*c2-/'c*f `ao+T2O#<-.j8їr9WFNw:8|E&ԘG]fjs.Æl-lqeRvf]N$x+Ć-յ7Us0qJJ>Aٞa CT$09,VVbJwi,2$ta-\fкF󆳱%)?ޭ],0\OCȓt($8mQK4Xc -=Il9_?/n R4zicݫ,UWB(OnEhaET)WAW9ZhV^HN2{Cp»N\q*:(wRME 3NMN5ڲIY]Tr=ň0:T\KhFehx!a{~YG~vY+9X NDEJ |CӰXn[ϳh֩k >Qd~Kq2~Rf@r lU@ IJ]R>1{qXǞy =o5j^؄Ϻ.%FTV_y Pjc 11yȵcgMe9b'H5t0q}q1%Ǚݍ%(T1#~ևlʆ{3Lqk)CɻUG3DC铵X4r瀈sdU!d[Oď27 ,;2@GZ7$.u!-][igJoxstHR>IJG]N>jA~=CvB|_¿o+_˛z^,zNrQrhB`'nXF3[m mvXϣ s;F84 ii1L^̢glrVUٮk+89iv}"=CWC\󃴗onSCx/}k6Lx"͢+_}!`yc ]rDo/|jᅲ'< Mm5pG 0^FޟSA* Y5~P;,bO\j#p*%`#>OL;j(Cl1Xw^p7G XgVqyem6x%fwvvG{j.(N\ZӰ ׄX6V3se١(e:+0\q2So #m4 Xiinyl| S*B⾪Jڕ]Zs.ќ$アG6E~9r,A&d.v;畧QAxnjVe=}/ uܳ7>DT^BHM0Z{x*X ͅrlʸr> k*)PEfK89xS;y! ;"S0]%gm}|G~7r0]&Dއ|/$ NXu.VڿdQ 5Bΐڸ#^"x.h4sZ4I}֬(n3{ ;g/4X`QXwEBAD{c}v&DU6BBWtZ@@KF4&dm&%-rU^7E:ATKG)Iǒ~o^bLp;B//eZ23|,5g/=z~Y^QӞ*O>4`w/1_V=Ssb ,YamN%m1ymwJm:$&)d-,#*5]1&V)Yg"DΕ4{BaM`]/vgr\\y]74jj {(YI"|0i=!К1C$9| )ɵ ֹ/ڝg=6J! }ψ}?F"XUo(Q鵭sCF,ۥpi#o}"<{zxs+ɯ慩8HHvE`,fs.Y*g,غ䑨2tM3*Br}>f HI=ȵ!X*3wN V(L]OUFOP|-lY h.i>qAsβn^k.,Q v'螊IvPbs<݇0JG|1 U@Sυ,M5q}ʚS96 s^wD~uԫ 6?îضjtc`ǮM9[~78?[dgVF rȔc fR\My?X#Ѕ%@RbHN'PtR D=O48IzP<6#pU[#Jh_r P{J$>i}cr>cY}wJFRAc}A- aT5Hr͸to7;|('Z%ʂGDWq63vCYܭ-_ pۭ%xTEõnG僓u=KN6ʑ"vG9D}%`djFW,F,ƻ?bnډ'VR>JC ^~֗ueE/l`%8 |!BW#)'`HfT֫ U%U11]<uHZi? 5IsALLo.n6!u(|) lwR< řI%j7AI,Y9oC ۢ6ݡ"0컧_xrA(L (Y@Zz)?tBȦHu*cW  hie^[հAqw*:kܷW0+^ulM_Ү&sbZK{1}lU'8$ b_= ;sc*pJVރ,K J󶿨퉰' k~ev:ʷzCW,=э6+Q ~zu_B'lK1Nk/L/rWٕ 1 j8R->zPKk>[8 fsMA{숦pzb ASV'{Hz#s p.EDɬqChw;C[&-y|2?Wm'ԭ PLw32`Q{W d4՘\ڣ$azA/]݌y jJ/̀Y7|8: 2 u3:r[c`ԫ1`IH 7]#۽MTa ҝM:S~z'&T[3>\%fQMybnoqs65q|lXiv@sm 92fA0Ofָ~$MU>?ȡ;KKZ( [7􏍮+#5x :"zn;8yQІQ_J~ f 8Bg;+ d\k;Z2M1ULZWK ؅L av*u@ֺ}.Ft_*3ۍbS}2 ԏ C١T}aUOC*dž]XX=Jfa.t=༱Uu#aѺ!U& ԇ9`d2N6Lm_g[0j|/l)|mQ+WPd9 GS67 9bWU !AY:F8G?,?@rHYf1!2⊲In?1=#7LỷU# 84Jzħc%izeT{ +i(px9uQQsXҟ!cW,Brz*/ !>0}E64VXك]̾W: e|2撱*3w^_/t=Hۻ%p2TN[Ws5>ӣ{NC|FH¶,=^KoV? ]%| U.T>_1ĮDhl n:*12t.2Vl+ Xլt&\; @Z*~iu7;]$z;Wn,&HCqV &Tb>w$wO };==Db5bT+(̛)L/wX@5C.JŁ^߭[D"(, != ZA'it\<>+_&:HշxJbQ@ , 'Q;jxTLHBwDG%۷ZۀٱuLݻ'KEbƜYB.]e&FT1\8YW~KuUxۈ>衟J>^zgPr^ZB)1RFW! ޖ'k!N?D08-WTDfLm\`8hۛ%BHLR2 b%}U-# ankH4q=9E3s D4ugܽͭL7,@d_ 4|ES7Y3C| bɔCsm6VV7}'x'gߛr٤qBxRc?$U#i.A4tߺyDBP9@JxJk061+Nؚ@Lf%"*yKLbT{Mbc6>ؾ{K#>I1?^Mm]j1޻UoVVj;I.@̄x ٣Ю\0 ȟ"cjpi/@#QSppl`}܊%n&ID߬z%bRD*{8ޏ-{07;CF V5G=åŭۣdT1?(_Ϡ6H_Mw5RoהN[..Mv@(Kݴm-~1噁/AȡuVVRXM\_7>ϟ5m<('}wL; ٿ7?mӦU3d]1O;vP{Hsُ9p1'f7;6*P1OA$EM `ګ_ Ey\qj|Edn‘G-P=-N7iAbiH?2ap)ez D!ܺZ8Su4wV$QT'G3 2:X}-7} {'y@@/c;'2 T~?]f~A~tewnw& [^Oݔi8/I|$c8U=}%e+3{b Egk7Nwȉ xo+6(LwpYe` 404{N[Z[b^'#jz͈s9 Hښbb4ӊg͸N*edqبђi@gهYgL6]Qz\.1MhIk{qZuȊY[k1<F}&M>zc~P^bcu[ A L t)-۳vU%A"hUnO6:-^mqQu/P{ɱ5k.74|oxOLJHEN4-UY S P '%Q)w%d*MÑ endstream endobj 283 0 obj << /Type /FontDescriptor /FontName /PUEHJZ+SFTT1440 /Flags 4 /FontBBox [-198 -360 1322 830] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/colon/f/h/i/l/m/o/p/period/r/s/slash/t) /FontFile 282 0 R >> endobj 284 0 obj << /Length1 735 /Length2 15942 /Length3 0 /Length 16553 /Filter /FlateDecode >> stream xlct&\-ܱm?AǶmNضmul۶mvtpߙ3w}k})ڵI,nodcgk032Y`qXۉ@S  `fdd wt4pPPP12tػYXxݜ]\IR.@  %%/WHNF6EWcK H0wGۙZ 3ع\fdo SWW0L۹8s 40WwIuD04q-`Ŗ=?fSW*?QLfD".@') loc pڙ]XUlll#[K;o?ٙ%L@SEK735Կ'&ljog 1ɩjo!373,M0?]Hua=t,\&6;߃^+ hbobOhDؼ5Ao.xMiDWfJҶi28{xaYת>Id4(Iymfog2i~ɻKbE=b!ݷk1*NP)ɱW?1[嫯RKE"DͫCېW?2!zzG"Ũkc#`v 91 sXܖPw8TE>$4]&7&_Pw*I7Rz[Zs̛h1b\6 $#PrW~ {?/vhD(!0-C{a"1THU{y__3Wn]P^nm[1%d9$2ZWo& C Ƴo! _z+bkR8-lqf♹=.֓t).ӃՊOEWM †R%[h0ʌZ>zO2-ԣKgG@sx{*DUY=9GFst.xF1'{LEL ;\HuHGjȖ-W k1[|ޏ GrV#ī;~e9Ta%l޺}o1D¹栔NFLLڋ88pΙetm noz:MC@:U|incq,RL _Ņ=j#@J~G\FӹBi<3Ү%.?ގШX\[^pV>h}t=y=q&NM:²j&C&yuj;@EU_t2U X=xCwGQ/ƅ(@O(07Iݖ[!Hv!Λ@"ni%^ג @3Y,wٍ ץ⚛bT̃O;Dc .yttvf:pc@'5]9r3N֪* [G]Sq37wߖUڀW:R;Ջ?gl];q([L~|'Q&y/{5+M`U & FHjZܛ:;7A_x7}IOg1 ul#|TJ$ɭ%b2W&8/™v3/csjX=|i{ٖGL2fDp v;Pr% {}ҡ_y*989b58 ;1|{cǡ#M&'94AhgeWdf #nN3t}޺".#tdH*\T^9PTP;F\bSKKw֟%X4J Lڂո)yV=i5,$(A[tPZSoV+"#/Tj`rkR\OPx)maqяד)UӫHi9[| ;(8,?>oNߤ' BA0_PU%Ҧ ?xttZl |85>ndhi]OIS\$4d8on$L{8Ƚm?7>UTh6ώu2kOsnMGU^uf}ʑcUș_ӄ:7$jG-(9⁛ 3H# P},9Չdͨsas,XC2ry"x\I=[#!?/ŲQ9Bd>|W6iԤD5cm\ܝciǏMt֋&H97yyhqZy4ɑܸ {+so?“"[=:WK><ÕPzJ8ďt`Tv{t/5wM^~,D( X>[ig0(u2?,$W9 -Yܯ^V6+ /˂p (M܊ M",}͝!Tp 3)\1LJX{v9$P-l/9tW_TcedwG'h zC^wC?qu/\Z-I؀i4 #oI]<8X2ٖ{G:KU{c/ x˓ՙgkȓ` $G 7:qh}ר"잚X*ٶS܂o D%'衈Ogo)-<҄vhMF_cDmy/@/5hj\h m4QDʷll Gۂm xQ!t[|%' ÖƄ&EÐã삔5p\j:]c6j(~Oލ5Uߓ 4;Ob| wݕ@}Z9H> tnʩK A h C$6]e&dKÉ:` '{P bとet<^a̫pyu:mdO'ݲڋ9-ԑp ]Xo& j&RB?:?\׵"nan1{:}ic2E#`˕.m÷3`$归hͺ|1Qrr1H$E)v;Ele#$.jh9K&!Nר$ qHKOq']|xsU/py)4iLW,OO'SMo5ơf6!Cڦ$tclϴQ* B0I*eK5c .KJ]Y%/8c$"01S@ ֑{AtlY1}WXq 3Q@>F'gtyudKxn3}2ӡcj3-%6 5e7sGW;yѹB@G`N*A&zKsc!gG)v.lDΐcJL$ed@ҙM m-"'C 75,G. Fmi`So-u iD:/%Hّ "|qFZ 'S0)L/fۼضYD]a#`Z᷺j A t S 2C#щ.w8=HF%'BY[" /<H;,cO3.n^+Q86+<n 25 ¥M,sna|= glQK͞f8GZ@q̷NkS"l@L/tRnggt!̝6D?亾U5l`4=Dg +a-Q_iʐF~wK\Gt0pw1jKBg߫ѶEPS+L!cʌ& 56a8! vV&*#ְEwH;Z݌B~0qv1JZԳġj>9ja"oZ!)ٯv,[)n.&{7}:hRty#F'3o&s)oΉeh(Ɉq:eÒZR䂥7u* @2č8Ρlt-^,} S}~Y2ͭTDl?y[\MB >S$+[%v{)w߭a`W@,=_LU(P(J][4r"&W/b+f)q,*ׄIdX}4O*d^:> WW ӰӅ8> ꙆazB;-er0YqjFCdL"EACʵe?=Xl}-pB $ t"ΖW[H+y]*U V e9ĆT/H]\vX=ѫ?W^e #o5Fq+Giz*(7D>+cm$(H*dHUb $]gm8G|lYHT"r8fu?VI¬r9L+J1;$gxWr%fiwmȣoLa/5 <͆ 7C2-g**\M8໛*_4x`ju rROɑ.lҖ?d3K a (Ũ/ژis,y 8" iF>dyW9e^G3J~&i4j|O70ϙ4L!A"Y6onUG.'QaDyMB!QԊ2 |4=杂NX%>wuPW"c^/vW90"gXe T4[/_PrÁ?B ?ɪ=48-z&8+h+Z!B%&(Uf?.qt_- ]Tv+/ 5_}) ?~'{^\潺]5x.#qQ@ïOT%d03k$4 ~jP>r*͊*,fݹfu$p7sR{Ý Au{Vgs[o,LNBO낱=U16,\:=Δkxo[|qGLE8} 鏾cy*JlH_qÚ` zG rdh7~{Ni_3 fd3@ cO_g>̈́ a}d3^lu ~xӨp.hAK9fVEW /uW)vYASD#>!zLvE}Sb3xm _Nb@\Z]p8\46&ޙ4bt.%|$p1678OM]P |h^3.OQc&TZ*n8S_Iniy9( Ii_]T u F,CKw츯S!) <>MA}M8GX@]|$|EK-%}yk]':/k$ |lg8@;],3|IȬ_yS7g8$RHmMyLÌ?.> Yj^cVw~YrMA⿞-M\R~Fm'8xű,(܌/׉GH#+NGb&3h,Cj*q5S}5s+zd;9?rxF1D!7be7:".5d&E'l#jaQL~?ؾߋ|ntA;Hq3lx3)*{CLM{6I?rR{T&`{h$GodcUt` ȿ&_I Hb(T鋛FE 5Q^ CuW®߁ |p+Lž@j>bGҡ˜-BASuQ#=*=(6g& g\DGVıD`w2CdX׵ɇE2!~t ~lon &9"l ;\M)g|})bt*smdu" ^%f6%,ZR06A z9 GTؚC.V c ԕ%48d˓h[J4_3fj6e=PM1AHht Ju{+`xDU *۫='ږyK4*J4Ϻ-1GB>vcUĵU J>U-1pʳXMQ__[BDkqaA![YZ:M]|Q[Vti(YK A#ʋۥ/ WX͜l_@$oC1ZdSjtKdxI ,x2nA{6So ddi<G 3b(Ŏ.sl;5D#y?M5[Q~'Xf+Оv8,߳Gz2Vŗ #mN>Θ:Jtkvx2v2kXĤMdk^}~A9MHQ<>yRrI*ϙ>y@ a0lW|w7@i>yÐ^ZC9;dy'96t J6i2;j}o?h`@:R.5sjhju:9&*U&Q=۳W,eb7wjS+㫖b%68?fxpN|t@T[+iq LG1WAR6Y4QT\r*//JL&fF6afNJ/nRK逳hℵzŇ"0g왱]6UAS)8K;˟R?~rUC6p!wU%d=n]W1 MG-{INk˲ݦx 뤤 Eu 7l 8C+g* xA?oq婌yu0CDؤZ wru#$4p]w*헱ȘsSHCR/5&k}I1NUzpwGAp֥'`Ž?VbgEe!!PuvĆ: =SA$OPhIk 0%ދ{YaI*4^ Vg!t $h7TnJoI ;Xrg_' :rjaLmSVr !`iEcmfBYyZį4*-ȋA͑=-R &u{fv딄\Ur )q>c.v,;EͭN4,{y^x;G jg+ϙJ*xXRǂhV@k-8+x 9(9!g%j/Yx9{Ŋ1n=^f |.Z'T\ yӡ#de1]ά0hjukRQH8 G&';ٷK903\鶯 ZQ !ؐlV33ȒlYHEP zp b$b }Vg`Z-SJ`P!kmy ^͹䌽pK$_#*2g֋ldrT:g!1ӫ5 9CKVgU^I5J8|[$[F=Dс1N*fQRLz菴/`'$mfjAR< ŵM>PW4b<shT+kt:lr8A+$Id ##8(Pe~ZkKǥ[ "JAbxմᢙy|duq%[mB3 cȒ6չ-_ 'ԬHz!Qf@QH52 rD| [/_d +*kY]J?B 8#6wyGGFcBVn~_ zw-xK PT]Z`<Inֹb"ྼorˆDoh?h=_7%Tr9_Yo0VQYhQD\JkB*3l7]j,@$Rs͸vq?8{=&%5nA_b |+RZvi!7 k8{ۼ9̷|,#ňa8kcxunxe *oA ԇՃgv2M0'Bpݴf|-~ĀC㰢kg`w^OEo"@'^p| %YSҴxD=|Eaa7'6Md{H|ZGI1&\#l0\ 0'YCξD,%T;RV Ґ 33[ӊVb2%g1T৶]Jy_+Rs!*2șC( \/meQ+̗#85B^|=SK l;Ը#Glx9ՊNR?NXFoqu9J<{`2מ-/"13}'576W')7oHfCA-[GjXBMx#./#%:Tv4'[[CI(7LN_9#2Ôh/.|(y y;jlbڳvN?5CףF%̓/ ǻu-B˹%g%ט$kW`AC*OSn tRNs/ _7|˜G?\^ z~]qđɓH ,KN'^7pN4}5Yt OKQumi|]+O:EOs΂jO`L0@f:]Rw31!I,5N_0UT)Q~$U4 g*tSp%)ШKuOh;/X+жT:|RS{s^PbPstG*~2pUbi[c5ҽ"*nuX B1 m~8+|ެ2ی;]c~ݠjTq~-zuL&ShI^Y8؏بWR |I!BF8>3rOAOa8탔~ouQ6ir"H *ƜGțASkRopjde2j[yſSg_|2t1t?IXM1q(1N IHcEɆµEsRPh npoHF[P_X?OT=Bךٖ-F!A;ܓw al0 `?7Ih6J>B9)A:ޖmqhw4ߝژuD6i SQRyQʹשvUqu:Jyy~j7*MsDrǦEGnJ15䈇!m[[d=~jٲbMjNf,*IًIeB`U @՝ęv|$&+ 10f,:_bŖ~oM}OtݷZW陕bb"T̛*&yxEnuEPQC7fٞ_5KBd/,rYU|OD#\mC̚A]2}1gTÍf}E;\Y -I^vfSiÃWE}̍#N0鑘;<(s!y`?^V`,YhLgD1ު2T=j/KϏZqDG6w$:nz'c{ ׫O\(;_ e *M!.p[qsk4Bz8!}>Y zd#TI P:3uHEɇ^Qzԫ$6+ CxIPU>Ku/G'=58'pk bg43hlxs,Ӻkا8?U+l~ҧDCV%TiE{B}0`4  srez@S[sf\S?J?)ljR'3᫡9AD׻UbA=Doo"8:cӫt 8F17}~5=.j)rnGq+9/I]0NJ1 ^z~$#G±-y;_j%R sEQO{hTYa:\RD_ByUCP2d +Cl1ÓuG#=}5_FWĴ7wi& &cK[Z\xw91wAs0؋NLkZE=@='}@e$(-t R%%dʴǍ?o-, 54 aKv vSc1`xS`@ h*:H 7:qGhyc`G}vmuzBamRX\K]A~6M yfV}` 4iр)ڿS<+aQ"F@kD-; )v3Uu$K̹sAO2 wQgFx/yw*)zz{M旎LZEuoec %8C8)2H kya%&RSu8 wulov16֭mzt㪴g]+%x\7h endstream endobj 285 0 obj << /Type /FontDescriptor /FontName /UMTYDN+SFXC0600 /Flags 4 /FontBBox [-6 -396 1757 969] /Ascent 495 /CapHeight 683 /Descent 0 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/M/l/o/p/s/t) /FontFile 284 0 R >> endobj 180 0 obj << /Type /Encoding /Differences [21/endash/emdash 27/ff/fi 30/ffi 33/exclam 38/ampersand/quoteright/parenleft/parenright 44/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon 61/equal/greater/question 65/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z 95/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z 192/Agrave 201/Eacute 206/Icircumflex 224/agrave 226/acircumflex 232/egrave/eacute/ecircumflex 238/icircumflex 247/oe] >> endobj 56 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UOEJDY+CMEX10 /FontDescriptor 217 0 R /FirstChar 0 /LastChar 3 /Widths 198 0 R >> endobj 40 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RJYVUT+CMMI10 /FontDescriptor 219 0 R /FirstChar 58 /LastChar 121 /Widths 208 0 R >> endobj 54 0 obj << /Type /Font /Subtype /Type1 /BaseFont /BRKLDF+CMMI12 /FontDescriptor 221 0 R /FirstChar 59 /LastChar 97 /Widths 200 0 R >> endobj 52 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VNHVYB+CMMI7 /FontDescriptor 223 0 R /FirstChar 119 /LastChar 119 /Widths 202 0 R >> endobj 43 0 obj << /Type /Font /Subtype /Type1 /BaseFont /OZGAFA+CMR10 /FontDescriptor 225 0 R /FirstChar 40 /LastChar 61 /Widths 205 0 R >> endobj 55 0 obj << /Type /Font /Subtype /Type1 /BaseFont /QUYCTL+CMR12 /FontDescriptor 227 0 R /FirstChar 61 /LastChar 61 /Widths 199 0 R >> endobj 53 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RHUHOI+CMR5 /FontDescriptor 229 0 R /FirstChar 49 /LastChar 50 /Widths 201 0 R >> endobj 41 0 obj << /Type /Font /Subtype /Type1 /BaseFont /WYSOUE+CMR7 /FontDescriptor 231 0 R /FirstChar 49 /LastChar 57 /Widths 207 0 R >> endobj 51 0 obj << /Type /Font /Subtype /Type1 /BaseFont /GILZWG+CMSS10 /FontDescriptor 233 0 R /FirstChar 43 /LastChar 117 /Widths 203 0 R >> endobj 42 0 obj << /Type /Font /Subtype /Type1 /BaseFont /MSAIWH+CMSY10 /FontDescriptor 235 0 R /FirstChar 0 /LastChar 112 /Widths 206 0 R >> endobj 134 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PPXBQD+CMTT10 /FontDescriptor 237 0 R /FirstChar 48 /LastChar 49 /Widths 185 0 R >> endobj 76 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ERMCYJ+SFCC1000 /FontDescriptor 241 0 R /FirstChar 77 /LastChar 116 /Widths 193 0 R /Encoding 180 0 R >> endobj 133 0 obj << /Type /Font /Subtype /Type1 /BaseFont /YDTNMF+SFCC1095 /FontDescriptor 243 0 R /FirstChar 77 /LastChar 116 /Widths 186 0 R /Encoding 180 0 R >> endobj 75 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XZTFTQ+SFCC1440 /FontDescriptor 245 0 R /FirstChar 77 /LastChar 116 /Widths 194 0 R /Encoding 180 0 R >> endobj 23 0 obj << /Type /Font /Subtype /Type1 /BaseFont /OJCXIQ+SFCC1728 /FontDescriptor 247 0 R /FirstChar 77 /LastChar 116 /Widths 214 0 R /Encoding 180 0 R >> endobj 77 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XUCPQZ+SFRM0700 /FontDescriptor 249 0 R /FirstChar 65 /LastChar 65 /Widths 192 0 R /Encoding 180 0 R >> endobj 154 0 obj << /Type /Font /Subtype /Type1 /BaseFont /GAFILR+SFRM0900 /FontDescriptor 251 0 R /FirstChar 46 /LastChar 49 /Widths 183 0 R /Encoding 180 0 R >> endobj 50 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PSDMLL+SFRM1000 /FontDescriptor 253 0 R /FirstChar 28 /LastChar 233 /Widths 204 0 R /Encoding 180 0 R >> endobj 78 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EBBXCW+SFSI1095 /FontDescriptor 255 0 R /FirstChar 45 /LastChar 117 /Widths 191 0 R /Encoding 180 0 R >> endobj 65 0 obj << /Type /Font /Subtype /Type1 /BaseFont /TPSLVS+SFSS0700 /FontDescriptor 257 0 R /FirstChar 65 /LastChar 65 /Widths 196 0 R /Encoding 180 0 R >> endobj 39 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PLKJKU+SFSS0800 /FontDescriptor 259 0 R /FirstChar 65 /LastChar 65 /Widths 209 0 R /Encoding 180 0 R >> endobj 64 0 obj << /Type /Font /Subtype /Type1 /BaseFont /BYMUCY+SFSS1000 /FontDescriptor 261 0 R /FirstChar 28 /LastChar 247 /Widths 197 0 R /Encoding 180 0 R >> endobj 24 0 obj << /Type /Font /Subtype /Type1 /BaseFont /CPVFMJ+SFSS1095 /FontDescriptor 263 0 R /FirstChar 21 /LastChar 234 /Widths 213 0 R /Encoding 180 0 R >> endobj 148 0 obj << /Type /Font /Subtype /Type1 /BaseFont /DIVGNO+SFSS1200 /FontDescriptor 265 0 R /FirstChar 67 /LastChar 121 /Widths 184 0 R /Encoding 180 0 R >> endobj 38 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UWKOJI+SFSS1440 /FontDescriptor 267 0 R /FirstChar 28 /LastChar 232 /Widths 210 0 R /Encoding 180 0 R >> endobj 22 0 obj << /Type /Font /Subtype /Type1 /BaseFont /XRKKOK+SFSS1728 /FontDescriptor 269 0 R /FirstChar 28 /LastChar 118 /Widths 215 0 R /Encoding 180 0 R >> endobj 25 0 obj << /Type /Font /Subtype /Type1 /BaseFont /DPHIGK+SFSX0600 /FontDescriptor 271 0 R /FirstChar 22 /LastChar 233 /Widths 212 0 R /Encoding 180 0 R >> endobj 102 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PYIBOF+SFSX1095 /FontDescriptor 273 0 R /FirstChar 39 /LastChar 233 /Widths 187 0 R /Encoding 180 0 R >> endobj 94 0 obj << /Type /Font /Subtype /Type1 /BaseFont /OXJKAW+SFSX1440 /FontDescriptor 275 0 R /FirstChar 33 /LastChar 233 /Widths 188 0 R /Encoding 180 0 R >> endobj 155 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VXSNUX+SFTT0800 /FontDescriptor 277 0 R /FirstChar 101 /LastChar 119 /Widths 182 0 R /Encoding 180 0 R >> endobj 86 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EYXLHV+SFTT1000 /FontDescriptor 279 0 R /FirstChar 40 /LastChar 121 /Widths 190 0 R /Encoding 180 0 R >> endobj 87 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RGKNBW+SFTT1095 /FontDescriptor 281 0 R /FirstChar 40 /LastChar 121 /Widths 189 0 R /Encoding 180 0 R >> endobj 176 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PUEHJZ+SFTT1440 /FontDescriptor 283 0 R /FirstChar 46 /LastChar 116 /Widths 181 0 R /Encoding 180 0 R >> endobj 26 0 obj << /Type /Font /Subtype /Type1 /BaseFont /UMTYDN+SFXC0600 /FontDescriptor 285 0 R /FirstChar 77 /LastChar 116 /Widths 211 0 R /Encoding 180 0 R >> endobj 66 0 obj << /Type /Font /Subtype /Type1 /BaseFont /BVMPBE+LOGO10 /FontDescriptor 239 0 R /FirstChar 65 /LastChar 84 /Widths 195 0 R >> endobj 29 0 obj << /Type /Pages /Count 6 /Parent 286 0 R /Kids [13 0 R 36 0 R 48 0 R 62 0 R 73 0 R 84 0 R] >> endobj 97 0 obj << /Type /Pages /Count 6 /Parent 286 0 R /Kids [92 0 R 100 0 R 107 0 R 113 0 R 119 0 R 125 0 R] >> endobj 137 0 obj << /Type /Pages /Count 6 /Parent 286 0 R /Kids [131 0 R 140 0 R 146 0 R 152 0 R 161 0 R 167 0 R] >> endobj 179 0 obj << /Type /Pages /Count 1 /Parent 286 0 R /Kids [174 0 R] >> endobj 286 0 obj << /Type /Pages /Count 19 /Kids [29 0 R 97 0 R 137 0 R 179 0 R] >> endobj 287 0 obj << /Names [(Doc-Start) 21 0 R (Navigation1) 27 0 R (Navigation10) 115 0 R (Navigation11) 121 0 R (Navigation12) 127 0 R (Navigation13) 135 0 R] /Limits [(Doc-Start) (Navigation13)] >> endobj 288 0 obj << /Names [(Navigation14) 142 0 R (Navigation15) 33 0 R (Navigation16) 156 0 R (Navigation17) 163 0 R (Navigation18) 169 0 R (Navigation19) 177 0 R] /Limits [(Navigation14) (Navigation19)] >> endobj 289 0 obj << /Names [(Navigation2) 44 0 R (Navigation3) 57 0 R (Navigation4) 67 0 R (Navigation5) 79 0 R (Navigation6) 88 0 R (Navigation7) 95 0 R] /Limits [(Navigation2) (Navigation7)] >> endobj 290 0 obj << /Names [(Navigation8) 103 0 R (Navigation9) 109 0 R (page.1) 28 0 R (page.10) 116 0 R (page.11) 122 0 R (page.12) 128 0 R] /Limits [(Navigation8) (page.12)] >> endobj 291 0 obj << /Names [(page.13) 136 0 R (page.14) 143 0 R (page.15) 149 0 R (page.16) 157 0 R (page.17) 164 0 R (page.18) 170 0 R] /Limits [(page.13) (page.18)] >> endobj 292 0 obj << /Names [(page.19) 178 0 R (page.2) 45 0 R (page.3) 58 0 R (page.4) 68 0 R (page.5) 80 0 R (page.6) 89 0 R] /Limits [(page.19) (page.6)] >> endobj 293 0 obj << /Names [(page.7) 96 0 R (page.8) 104 0 R (page.9) 110 0 R] /Limits [(page.7) (page.9)] >> endobj 294 0 obj << /Kids [287 0 R 288 0 R 289 0 R 290 0 R 291 0 R 292 0 R] /Limits [(Doc-Start) (page.6)] >> endobj 295 0 obj << /Kids [293 0 R] /Limits [(page.7) (page.9)] >> endobj 296 0 obj << /Kids [294 0 R 295 0 R] /Limits [(Doc-Start) (page.9)] >> endobj 297 0 obj << /Dests 296 0 R >> endobj 298 0 obj << /Type /Catalog /Pages 286 0 R /Names 297 0 R /PageMode/UseOutlines /OpenAction 12 0 R >> endobj 299 0 obj << /Author(R. Bardou \046 J.-C. Filli\342tre \046 J. Kanig \046 S. Lescuyer [1em] \311quipe ProVal [0.5em] INRIA Saclay -- \316le-de-France \040CNRS / LRI Universit\351 Paris-Sud )/Title(Faire bonne figure avec Mlpost)/Subject()/Creator(LaTeX with beamer class version 3.07)/Producer(pdfTeX-1.40.3)/Keywords() /CreationDate (D:20090204144522+01'00') /ModDate (D:20090204144522+01'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX using libpoppler, Version 3.141592-1.40.3-2.2 (Web2C 7.5.6) kpathsea version 3.5.6) >> endobj xref 0 300 0000000004 65535 f 0000066349 00000 n 0000066369 00000 n 0000000015 00000 n 0000000005 00000 f 0000000006 00000 f 0000000007 00000 f 0000000008 00000 f 0000000009 00000 f 0000000010 00000 f 0000000011 00000 f 0000000014 00000 f 0000000067 00000 n 0000014079 00000 n 0000000000 00000 f 0000015370 00000 n 0000014234 00000 n 0000014702 00000 n 0000016016 00000 n 0000016333 00000 n 0000000117 00000 n 0000016166 00000 n 0000421291 00000 n 0000419500 00000 n 0000420801 00000 n 0000421454 00000 n 0000422599 00000 n 0000016225 00000 n 0000016279 00000 n 0000422904 00000 n 0000014427 00000 n 0000014897 00000 n 0000015570 00000 n 0000057532 00000 n 0000018959 00000 n 0000019216 00000 n 0000018804 00000 n 0000016554 00000 n 0000421128 00000 n 0000420476 00000 n 0000417592 00000 n 0000418442 00000 n 0000418725 00000 n 0000418020 00000 n 0000019108 00000 n 0000019162 00000 n 0000023174 00000 n 0000023431 00000 n 0000023019 00000 n 0000019433 00000 n 0000419988 00000 n 0000418582 00000 n 0000417877 00000 n 0000418302 00000 n 0000417735 00000 n 0000418161 00000 n 0000417452 00000 n 0000023323 00000 n 0000023377 00000 n 0000025324 00000 n 0000026230 00000 n 0000026487 00000 n 0000025169 00000 n 0000023719 00000 n 0000420638 00000 n 0000420314 00000 n 0000422762 00000 n 0000026379 00000 n 0000026433 00000 n 0000025525 00000 n 0000029189 00000 n 0000030095 00000 n 0000030352 00000 n 0000029034 00000 n 0000026744 00000 n 0000419337 00000 n 0000419010 00000 n 0000419663 00000 n 0000420151 00000 n 0000030244 00000 n 0000030298 00000 n 0000029390 00000 n 0000033573 00000 n 0000033830 00000 n 0000033418 00000 n 0000030681 00000 n 0000422109 00000 n 0000422272 00000 n 0000033722 00000 n 0000033776 00000 n 0000034691 00000 n 0000034948 00000 n 0000034536 00000 n 0000034036 00000 n 0000421781 00000 n 0000034840 00000 n 0000034894 00000 n 0000423014 00000 n 0000036621 00000 n 0000036882 00000 n 0000036464 00000 n 0000035094 00000 n 0000421617 00000 n 0000036770 00000 n 0000036826 00000 n 0000040075 00000 n 0000040337 00000 n 0000039916 00000 n 0000037104 00000 n 0000040225 00000 n 0000040281 00000 n 0000042488 00000 n 0000042750 00000 n 0000042329 00000 n 0000040520 00000 n 0000042638 00000 n 0000042694 00000 n 0000045218 00000 n 0000045480 00000 n 0000045059 00000 n 0000042970 00000 n 0000045368 00000 n 0000045424 00000 n 0000047536 00000 n 0000047798 00000 n 0000047377 00000 n 0000045690 00000 n 0000047686 00000 n 0000047742 00000 n 0000051908 00000 n 0000052170 00000 n 0000051748 00000 n 0000048045 00000 n 0000419173 00000 n 0000418867 00000 n 0000052058 00000 n 0000052114 00000 n 0000423129 00000 n 0000054439 00000 n 0000054701 00000 n 0000054279 00000 n 0000052500 00000 n 0000054589 00000 n 0000054645 00000 n 0000057382 00000 n 0000057643 00000 n 0000057222 00000 n 0000054946 00000 n 0000420964 00000 n 0000057587 00000 n 0000059615 00000 n 0000059877 00000 n 0000059455 00000 n 0000057866 00000 n 0000419825 00000 n 0000421944 00000 n 0000059765 00000 n 0000059821 00000 n 0000062448 00000 n 0000062618 00000 n 0000062880 00000 n 0000062280 00000 n 0000060125 00000 n 0000062768 00000 n 0000062824 00000 n 0000064432 00000 n 0000064694 00000 n 0000064272 00000 n 0000063090 00000 n 0000064582 00000 n 0000064638 00000 n 0000065759 00000 n 0000065927 00000 n 0000066189 00000 n 0000065591 00000 n 0000064953 00000 n 0000422435 00000 n 0000066077 00000 n 0000066133 00000 n 0000423246 00000 n 0000416940 00000 n 0000066389 00000 n 0000066834 00000 n 0000066967 00000 n 0000067010 00000 n 0000067349 00000 n 0000067376 00000 n 0000067620 00000 n 0000068734 00000 n 0000069934 00000 n 0000070445 00000 n 0000070956 00000 n 0000071397 00000 n 0000071422 00000 n 0000071674 00000 n 0000071928 00000 n 0000072021 00000 n 0000072046 00000 n 0000073344 00000 n 0000073387 00000 n 0000073412 00000 n 0000073653 00000 n 0000073684 00000 n 0000073709 00000 n 0000074146 00000 n 0000075360 00000 n 0000075487 00000 n 0000076135 00000 n 0000076208 00000 n 0000076597 00000 n 0000076622 00000 n 0000077832 00000 n 0000078097 00000 n 0000079332 00000 n 0000080592 00000 n 0000080842 00000 n 0000081399 00000 n 0000083461 00000 n 0000083735 00000 n 0000087621 00000 n 0000087874 00000 n 0000090153 00000 n 0000090381 00000 n 0000092196 00000 n 0000092415 00000 n 0000096358 00000 n 0000096646 00000 n 0000098327 00000 n 0000098549 00000 n 0000100417 00000 n 0000100642 00000 n 0000103125 00000 n 0000103365 00000 n 0000107868 00000 n 0000108166 00000 n 0000110046 00000 n 0000110307 00000 n 0000112101 00000 n 0000112326 00000 n 0000115064 00000 n 0000115283 00000 n 0000117754 00000 n 0000117981 00000 n 0000127607 00000 n 0000127834 00000 n 0000135319 00000 n 0000135546 00000 n 0000137978 00000 n 0000138205 00000 n 0000139920 00000 n 0000140143 00000 n 0000155718 00000 n 0000155955 00000 n 0000175636 00000 n 0000176017 00000 n 0000184513 00000 n 0000184767 00000 n 0000186555 00000 n 0000186778 00000 n 0000188448 00000 n 0000188671 00000 n 0000200969 00000 n 0000201356 00000 n 0000219005 00000 n 0000219519 00000 n 0000226503 00000 n 0000226754 00000 n 0000236678 00000 n 0000237039 00000 n 0000242350 00000 n 0000242598 00000 n 0000264443 00000 n 0000264816 00000 n 0000280571 00000 n 0000280852 00000 n 0000291842 00000 n 0000292083 00000 n 0000318491 00000 n 0000318730 00000 n 0000349633 00000 n 0000349993 00000 n 0000379998 00000 n 0000380353 00000 n 0000399779 00000 n 0000400039 00000 n 0000416712 00000 n 0000423323 00000 n 0000423407 00000 n 0000423608 00000 n 0000423817 00000 n 0000424013 00000 n 0000424193 00000 n 0000424363 00000 n 0000424522 00000 n 0000424632 00000 n 0000424742 00000 n 0000424809 00000 n 0000424887 00000 n 0000424925 00000 n 0000425034 00000 n trailer << /Size 300 /Root 298 0 R /Info 299 0 R /ID [<7170209D78BEB819ADEA7E48BDE4BC5B> <7170209D78BEB819ADEA7E48BDE4BC5B>] >> startxref 425572 %%EOF

Z]OMYBT7R 4x-'ùJi8ҳ3u&(sr!_N֙0OaM_tHF4C !v*σ.`$05鎮HĞA(;cEs(r9S0m&Hg3`>qMgbH]pl! lFޓgH׉,q,eva"'sݮ 8ЂO0:K*Dp< /b3x`^X_LAN eW`8JnC>WKΣR>3aea-X&zUsM$kt:43[9Ν||p>OG*7R[B:+ :T̼nƞXHq{<讅9(v5zKV}>ޓ;Z-A6tAOi7broYnFƆp§"! 6IQHA^NuCZDA>FnސrԁtLT8`f㯐cp}FOiA)ʃoA9_̮]1VZs sAJih;Z:'Z ,&hcZ@b') d5)G*0;ط;S#ӕj{";ݡ}~88t U}w!YԐ,ol >)=/dJ{Ȅ.|^XȑWT79"&]U?C7W @-W;Vaw=Mjhݳ"&&78TޛհB虅;r+t7LNN0@/pD?Id²/.lPLa6> 'eZ^IzHނkuѝhv͏vLE~.lu:+l[g T+?t/c{H1ǁ /|%e^vAsMRDKX@2PDHIkq!)jBf*Ǒ?oqOā)Ww:z餣zHY41$Ǐ ' ?y.m@qŽqHI 52:/|of3I8: T77 endstream endobj 65 0 obj << /Type /Page /Contents 66 0 R /Resources 64 0 R /MediaBox [0 0 612 792] /Parent 54 0 R >> endobj 64 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F43 27 0 R /F28 12 0 R /F29 13 0 R /F11 22 0 R /F46 33 0 R /F48 37 0 R /F58 67 0 R /F49 38 0 R /F40 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 70 0 obj << /Length 3920 /Filter /FlateDecode >> stream xڭɎ^_Q9u50Es_x `x}AR(P-J7Q*u{Ƿ/iKaWLmqVC([@OUm{nw)>B>if=h+s{vpu/6lL-ZJ[m aFm槟s_o)n+[),F¸aC#oQ`)Z&yfK7 Ux1Ʈ pF yݜ"˳Ehk@<‹up _m&7BKl74c7qcW{돸( wp]; 0H:'fS#K=ÀlU`5ƻ؞L`{.^h(G(dVR[_Zo%4T~ԋ4(JPah(HֆA4AYaGDdv!~˻`Sx]w ꨆ(_ƻ*Z'n~G7QHt3iۀ8̟e3@@Ӧ_™e/ $cu:40m{1^>`QW+'ꅥ+9b;+%!qW4))/B0OlOFs9/]H܄gJ\s:m5M`Fݝ&1ϗA9@ix<0NCtIGG[rC]w˹)QkB}BL™v0{ᷮ^[oGy|jNiA|- <7 )vZ ]tܜB2vܵas j dۚg:/{3~ȦOnrj.:!S:>9:gJ"( 8OC`zbf8zյ=Ή`I`n} t@lr/|拒t Fm_]M2fm}w;oP 0710_a? Nm(̑ *[n q0߅bãj4\%FDx Rn&C kO5<`N_7eᷡCgM5<)Ԟv 2W<wx0>F>4ǘc @>S.'eN40#c\|9?|Æo}ǙBɉ1ux[^YOe"q ZA0$ +-Y"H5 .%XEh305FLUě0 XQ7ԥMwٕJU4zWnv_d3~^2AM;f 8D/):ts,P87SuxOk8HKbvGT߅l˱A4:0X$ Ot+ .Nq@XdD }wc4F#ߒ >]sy{|1T^,.FIcP:GsH~w s7FB Q7zWv^6W>{m' vJQ&Wdh}j0ĸІ[υk(Jح՞3$y*q| Y%]kE1PZ@;E.G{rG+]گ); Z nBf@\֖M]Knp` j݇xt +( /*0ͯ !;Wڐdҩ⻆4Xe{i6ݸY-OQrԢ|Cihb"P2!xk޿(~w#(*^8O^dIʩZ&AMϞkȃshBL6B]85Shq䩺Vo;LM@$Uɓ62s7(o̽ !mHO7V-d"֑tbqs)xWaT(}|e!@%%OF,ARLV/n-_*3C>kxňLđf D]x5s|oӼpag*2jxŀwu|7Bv,Pxrb()f%.ʽ:݃! F;9%ֵ@B?17m!RPRK)`? /*\@+Sŷ#Uvh η=Cm_y>gJIδ9DmF`7n!k,*b8n bu)ïCF:|!4=( bI=P i,BmFtt mʧm{>q:vLRތ"1t#znGAwϘJ]$B9z)-*^ P CϮ d R PiZǗ e|_#2) TD' s_(gD bLw7fcnegȡux7HLT$Jog񍪴 6LNIVp%Nؓ& N F˵,ȵ X Z*fNd8(# ZjP/?zGV M[\/A0:gBʕJg "i .eS&B%48& gALZVsa^p]1&OB07p+? r&99?s,J9mf%fx {RAhZXӘ Nj% *'r [bL 'U{$MeZX7J:z_ Z6i3&4yo;Xم|*h̉ ~g\o@˪D P#T sKC2 50h3cK4~&ق7jc> %Q왕XyXE>#*\q==G,%!ZY‚1³ M9kO+-Sj.Wy<1 t%XPPTgׂE)*iNhG_@rZ2OӜF,hB L m]]^|xS`a? ]7D:Z /-Rk4$G]I& {`H] endstream endobj 69 0 obj << /Type /Page /Contents 70 0 R /Resources 68 0 R /MediaBox [0 0 612 792] /Parent 54 0 R >> endobj 68 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F46 33 0 R /F49 38 0 R /F29 13 0 R /F40 21 0 R /F28 12 0 R /F43 27 0 R /F14 24 0 R >> /ProcSet [ /PDF /Text ] >> endobj 73 0 obj << /Length 4260 /Filter /FlateDecode >> stream xڕZK㶱*-B" ,ƉıO^%v7[/a;D(Bew_dhUoOǃ ;Ww`E4uȔɒr/zwovZv@az.NT~`؄s+DnU_=x| ~G~^Zy7u*ǏWI#⑿G&NVW5 -l1U.5,nx1T-J{;9PX,Bjh#HDFc,8E#g {Vr\W5tE&Y[JRehƋsF,=lV.Hp% /8 ϥ*nxpR(zR ^Ib>'qGwb뤧`MӉs?c[(8w;0_KaxA%%,Xh MMZؿv5rwGذe45gTl/*t@W߿\ל|?68w@:ҳ-Yt.$=ЀjCs=qɼ{Y'aM6u2 F|-T\s{ kC$`T&GѿU I4y$1rqO,{p *pԾ`t7I<`ՂM"8oQvYkzj `$^6^HںbWAG]BJtkH;FL%y s.ZxUIoǥjK՗ܣTt2x "v[@󹃭O`d(ΊlwV$yoό9˔=b_5\I*Gμ+HactHU4& *vOvԎ.e2o~vi6{ [%8z5t#c '*Qi.[0;d $Whi&J$4 qZIX[y cOY{(/50aARamW dS<JxA^) }13Håc%l\yn6w7~|«3T\Y1YmkQ9hh}_ƞX*p`dɥI˵~b[ύ>4w3@U\ytNp`CX"}$u9WB0JƦA&r %k };\kR0ݓ{%v%>mcr `a觡415[d:.,NMob,fzLh]J96bmռu9vR:̅\ >.SS7Pp\8vѲlROEb?CՂh6WMDbwc̬ ,p>E` -d];9T4+Aoʗ;㉷QTs99́jDQ6`eJ`2dol)>KVs~#!n{n;=+yw!d&2=#zW3`^X pBg}'5J~!=(@),NR|.Eɢn}LgV{5l]dAޯسO9/قZ1Iy<ϚXز|ɀ l(Ӗ_6[?:ЕtW܀]aS„W8|6P=](2Ag_m0v"sUUZۛ PL,~ğŜ T#?AM^k|n+,Ne]<05EZP5RfSg%ӂp ldR(]62~jЖ 3m-Ο߆EKHk" i$I<07k "joe~aMP>9c㜲?7hB{k l?c:'FAʄE+^.2Zi"Ɣly'h'H_5HϯKje\*SΨ ^2('4U6ͤAq{q>#+/޸2,֍WP-uctshijeU'S.ˤx Dn.YuyM#W O;toѻД' 3hHv#x"<C5Q1KR]- c5dFJB -ZzXXp wBrâaJi"k\E:migT%Ј$qh@[YO>И6CE&5A.@&$Q]{JxւOҡ Ph-jjH77b6tX)^N2%fv<u~J46W5]ā|ۿѽ02!—#0{l!Y<!˕듳(yzN(@ Zg?peQ,Ak*P _q{U՛W Cʑަ-5˱b;%$˅;ru2f$gc1>DOcu</ +QûZXu)g* 7bpjV$?޸Iq2|L1O(Y~"k Nԕ49T7R ֪Su^JvN*h|wni)=?s6KN RK쬮ˬn5oL"J$`J󈙔_B7tH3hud^vw\1g3efSoc4&A${anMꁕ8QPձc]Q H'`#@# fviWepכjE_o=Y]['0W`bu5xs2.%Ղug (upEqt3 ӫXg~:,vZnyS3@z Nd28?Sb?;Wj^ wZL#}lJ6+\+%Ŝfw4cVЙJnsx/(ZթTvCQ5eR݌y!#U)u+'61 5'$Yt]>:"c?)8 4i>UZ`ΩC%x?VCdTjҝYu)F13R/8Oxph3b^/nrn%dssdXLO9SKAޗa&ӗ0_% ƌ!S2J`LX$'"{|⩗֌\@Ɲ9 y8Ԙk>ƔQQH& &1r#NO:Ÿ9D[_*%R3A%q28;9~LhA&{GMz`~b@bjUϒEg7SBcbgwVp&o(ݹcSW4e#Xߞ-q:W= 9*_ZOtT7C⧎lHۣW endstream endobj 72 0 obj << /Type /Page /Contents 73 0 R /Resources 71 0 R /MediaBox [0 0 612 792] /Parent 54 0 R >> endobj 71 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F29 13 0 R /F49 38 0 R /F58 67 0 R /F43 27 0 R /F28 12 0 R /F11 22 0 R /F40 21 0 R /F37 18 0 R /F44 7 0 R /F51 46 0 R /F60 74 0 R >> /ProcSet [ /PDF /Text ] >> endobj 77 0 obj << /Length 3268 /Filter /FlateDecode >> stream xڝَ}yY`MF,E bرpg9FO]c:aWWwW] yveLe$ (پN6/zg]tmZoCc?_dt ziQhNM#&04TQq(qyK` T&Ky II,|WOp~7Q24 w˜ 8VL\S]Hqq_tL/:LQOK7#^:sۺ:jb@S *}{mᔈ[cCƅH=LiCj}KN]v݋%pIp`JC9R1] vFe`Bxn;`KA K~/ Xe lƩrQhv:pAMXDSΠA/fBw%pv~@>+Ȼ o%Zr@rT ^q" Յr 6إ8,9~h='g0EmW3P0ni 5-Q{~Mf~Rg3dCv`}=ʺ37#QV|?vmY?09eS=>qm>U )(y>֋WE4PJ$nXoePe;,xY^&?xZ@f_OsϧO,k{Z.m.hgNSf{aiԚBOZ1?V3`}?ʊc*C:4 څ{~̙gkĞ|RKE##\tç6]G!Ec@ B.' /Aq\^ gp ` U14Ҟ4BvIA< ˊg뼧:gT ;`X-OW)) t6ǝ5Csں,Z$™WP5 iCq3"{S8ʘ1,m7 ㉡ Oe906 =H;…U fwYhbLG f(8ԲȇJ&U@HdDܞVVyU Q)L堉C+ꔷ* `dž8v _Q3QM|A!0}> @khڝSm~*>洉³f\`x? }oN m ]M$BJ:t&\ΔV{GɮPbe^@$c/ l3B <_0Ls+}::6,{1:)9#J}ρ!rx.\b)I%H1a]ÿN,.y[$*SA.떼zA]3WCEM fE(yB&6w^JLLjf$|#}>{]`nϣ+쯨"]rBPr}vr92HPET0T~X{!tŖe5ypOYTwUNW;cST}1b HxiO4Y׳7=˄єu?ow|71LEYI ړ)3Kjq~\ZrG2j˝9)ŰU3RQzngfur4JMїtF-ߋZ,٩KΛt/T;J(+zdl{ۇaB0G`3O/+evB+;‚/xʮg:VI-b<`3aǔRYluY{8|A]JĉJm3 IS;Uו1faYtvhtrַoǽ0s_ uњ~xq{ ~WPE폯oר*bJ3AƇH7vP1s rqL214Z^^S'}]Ftexvy{WB8$K]>V&|8b>Q\>nlnٲCcBĒ3p,H9Qd$}RbNjQ"vx.E1^jCB2 9nAM?zq;vD?HY`56&`*,PwnH!6oÚw( ~\6:SMqՃS0!}yq $& Xn5 45WЮl(,wqa2^7`j"e&0NkHL%I 846%) !hkC J2'I!UNbȷwAȝ&3fId 8q$ 3lAAqq1| ITųqBSl8lrw7Pa X.AU!u,H )ZѴ}NiK"OyPY..0099Ʀ1 mk/VCۗRh-E[z8ZZ|][J-\{=$-!k-DxclI}T ~,&ӛ/%ccr ǯ=M.`=?ez$erGѐ蚳Iϓ s i B858J`h99 qi&6`yI~[VL?SmR]ܔue?N3#N|B+%~E9 zr%BR~xrq(s8/әx80 !m%K&cצ i;"F}OS@eT h|OyltW@!DUM܁R v!2p/D3`v5( #Qw"pT0yP:!cXL/fjv{a2 kL2pb"Rݨe endstream endobj 76 0 obj << /Type /Page /Contents 77 0 R /Resources 75 0 R /MediaBox [0 0 612 792] /Parent 78 0 R >> endobj 75 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F46 33 0 R /F48 37 0 R /F40 21 0 R /F29 13 0 R /F14 24 0 R /F28 12 0 R /F43 27 0 R >> /ProcSet [ /PDF /Text ] >> endobj 81 0 obj << /Length 3845 /Filter /FlateDecode >> stream xڥZYܶ~_,j r**f9䈇,/:X5F@v/cQ&ip{*4H %P؎{u|}6]a Ʒl:ê݇] γ(lp8AGh*P.g<F ݷ;t,*4btޔĨmk_&Ţ8@&u8v̴H3A(T ,Xo߻& 8!SھVp9<9o;ۦAT>^[ JGi'\|׬D\}S8`41Y]h^Yط~,aY4\II4v}9šyܹ`$^q+npߧ%u/vc`G ?+pbYH,W-gz^W<`mnvǞ(碃iP T:) YWT޳"tش'}WGE--bHӠ`1IhʌW+O.ڑ?bym' R774.(/Pv w5 ՝I4lzt\iv*$QN, IhMGȁQ.noErx"T V=,CJVJWΰe7\Hi %{\$cVA<;k?檉$ROyYTdwW]i zg!F%9?Hn&=vzmL-X㿞i/_,ţU`sqآ&w&65G.ϩמe׵?GCU /`nX{X~IiUڡaėhH >WtiPQ_+ u2 G\q[8_D܂C ģa%xDƝQ@*Ust?v9FД"ԡxd&tRD6KϪ'pMc-:֩{v} :5Q&-0AA~7\%gzw,IYǠY3 iZ<'nk{?gMR* , o%<ǻe\^ueq`'.U].(0;]#.诒wU-~9C =@ϱ/U,mCY$,Fi1d-Oړ {QvZD?Vi/װ14FP) xwEcWW كKb:k56B:v%,Rp _ N6Y̷!{_vx@+0VUyE0ݾ}BP6}Fg0B;a3Y66k#[0T "UGM6ԳN* CrFkw-x".S>dnʋ-uW\αM4C /Z` X1M} 箽J`c3'm X|i:z ЍEȥ~(ZE)‡q*R]gB*c=V y=a{^vp6NSQ3p&;X18U 8[Om*2 0+uPx*c>J:wÍZk%[9uQX-(YXp\~V tYv ZǸP+bnTOlӕDEq.,xz<|́#~bbe%xJ E2}^ CUә2V(Y,|~V LiAH5j \;om#dLPb,*13.xUFw:jGW]p,T_qE!eLP6R#0q Yq@'E2Ke 柟,0KI]b ,N)*:2Eٛ6KE\ bGGO:+^ZȤҤI&KA:^NgT􌌲b߰ޮp@_ :tϴ=}oǀa_6'70O;-bC1Vғt-܄#1I{(B7Y(32pp^(0ȍ#~p(ڏ6/'ԭ( o0K(YǺZ=on˷ȉKlɇj:~Yv eYC\0ݜxɲI@P1m8i{0X͕ 2DPn~e$m=}O)zY]$9tr7\mAېMriX(Av̿@E,(ԔQ1_C&<^/+%*GFEWk"E$eK!y4|{ 0-鍧Glt/%eC̿e"V1HG c|wDR3obFр) Y^!؋`415?W_Up9#\G{%?E׶D7BO纥9,8YV"6֞ C: ~ե!{/5`l7RnէJ#D wgMT[4gi@.J~ *I3Stc(aO#oMk%̤{kz'k϶<`lV> endobj 79 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F29 13 0 R /F43 27 0 R /F39 19 0 R /F46 33 0 R /F40 21 0 R /F42 26 0 R /F28 12 0 R >> /ProcSet [ /PDF /Text ] >> endobj 84 0 obj << /Length 27747 /Filter /FlateDecode >> stream xڔ]%9&|_"&ˌ:5 CERt琕de0G ?:RbFI wO}W>c ͷ~q!lGC@n~o^߾1Pnοbsz6{+wܿoWiK,_OϿ}7^.SoVo~GwA]Qn^xb=Ǜo׶mB[O'BVn~{/(߾?;}o>=޿|"9?L5O'OmLJ?1sHslCoCoߥto]*ȥ4U{9aO'KC7O] tˑs|~y{zo|}޾>s}'aCk`n%fۇ}A$M?is>n~Jsmk4s7_~8o??}xx}x>!#[>ׇLJOZyk21ݾ[#􀇩^᱿~/$?>|_< K1_= YޑG"'W(\lc3s KzvXKpNy+IJB=\ҥĄori-8uM 6~uΛ7oɀ|oKn) ~qƋo7.1n.]=pE_Y%\d@t\lr;^}&|v. S¦;E2(;kGcq2n2舞1Iv܁e {(H\jC Ë;$wBfұX^C%` I|F|dh?>Py2v0_RwrO).B\Gc`\+!\DK(Av\^9_eHF :upzxl>eD Ul8w ܗJQ2d:t1V0+&*"Ew)b&|d_–T-WzշK ^l U&6]03{ǎѻ<8yB0,8_.K:Y zో=,gnM8&xi1XVVi|SmMxb*t=ZU|Cdb&RbV* TbBDwlx6.*b|x)l"FЇDqʽc|G1*_6Rԏp 6wDMW[C~ 0E lO"6@xe\ٍn8"gyE&`j'KfVnfct dQ72Eʻ"o Av"QwbVQ#8)*L 'QPX QC03n ͧ-L'a T#1Q)Xc,aP\TN$.]%!jZr% PIaK 0?~Q |an oy>Nh =`c/|<MG_~aU2^F'BAؓdOI,Z?6C+)Nl{2K:N9Nt2cfEٕ=>j'va'Dcȍ/b^Ceaؘ t!C\;3s­-mG͹A&숾+f*ĄۏYy7-NyzN3ʋ^qid][UMeN헨pLk鼨הY:Vk( a;*(˼8YMZMw-IT_Zdv:Sn$If@&C`ٍdѲ ]xb+<>'*]TTqt(pGs&AZ glWLq %_1M=S%."$E$hd||%v{$nu dq $O`r~#s T[r!|4ǵ|w(@D ̏Fvl;B!iu\S~P+oIw}J$FZ[tC!5 nt1qK2x;?&)kʠ(fs)G>ƥ( W%L%3j86A0Ka׫Ǵơ\SvPe+/7TTL$SΈ$j}52Xa\d P'JYFìn]-Pywkѝ& (_Ylt ʠ- G# TO{601VXفk/|5T O^۲ ~86ʞv]I'" !!/\[Y "vN|=N-+y+|SBpn-015/a͈p a'{/(&cZ (qJhN6(e0{纡1l'v;8X\UC# aGh(ߴ֒=®F#>J>&T!pE^ء'+yq0`K8%h׿B,R44h=E!II:*l17"b%r (-x d Ki6')lN`S؜as)^ d "lNT)lN`as xzvOvNcas+as}$]-$ytSf؀f4FJdR싗Ј]$0H9ESw GIS,/ȖRkصՖ60wQted*X(Vw=4IX@n+Ʋ mÝQ6Hai!~[ܙH-|]M$O pLk ̨ה[:VK( ! ZC<) I?8#NU^Obc:@-Ù@Aor;jjxF'A.i8!_㠓ŋX|B0 >M\HqLm2הc6VYk != 6܇nM9 krl!,@EL0xo?^8b ߗѝ*mƽ}h]sCp׺!#ퟡNOkB5 *dcT*j%";˱ :rY!=Xבq_E.}\,ZE.}\,x/"+crܯ" 4M(aȆk4Ul!ebp|-Sre8G#TAvl; l8*7$5L c*b#$2ŠCZ4˄KHpă1UT5Se&0ʑTԙK-l%J{-.cc/@Iyfy& XA]ck^)&YuƚZꋠwX]wHIbBV׍C0KF%Ҍgr+l9bϕ%JĬ/j|%L;Ks\28 hq6*^ 8|6,VA*A׏ei];%)/gga5SJ~d.JXtqj^1{&HT( )sODi$߉pZVf䝑>\HV0 ۥM;J;(wZ1yk,\5J0y9,<<1̞VfO| '^` O|מgO|+O|'=zd.kv6ߴ OW2{Oґa'+&d1R<))dP3!okyIQlZ%rf#sL܊|\!c 0v?ڌ0DGda-RM;) ckj`eV1Ԧ12SĮ̆:lrP+*&:wg4b9:P g\>;G~1\tG1 ˅)]0n-OAo#$ф9x$X:˛rF'3-Dg SNl]:v0xpDiY6TK( .%BZ]BV[$U{kMc&N񆱦4,1ltAkX]^`btHO^t²7B7 E$ʲI1PiB)<Ǵ6Lk.lP2*(Bz)jhEA/M`nF.ف#%s@8jsS@4sJulP$D='.h(eF3)pC(f1]&j%Gk.>1U\SX0-b0lLfBdKW)|UU$1E|)&P"vd3CTP`a(j yRN?B~WKW`( 6u9CvyF~ĸӸ6R 7,ADCaj #IuS61`)uAfұV^Bo I]Y-^=9=@`hQ24u&*2bXgʄg#)h ΄O({Ct7Hbf1%06 {Nl @d8 Zk-\IIѝy (2} (z2bMH}ڨbaNraHs?&?;߉9Dp)Z4rr99"ޝ #F'%sЎ'li:0HqLm2הc6VYKk != K:v>\Wsﰬww~e0WUT;\Wsﰬ߁~^;P0U˪a~eoۧoNVAg ۰ ˃5%pH}!.|âu|B0A}gPu*%k(4[|Va!7iˢ~QE}_sQ_?sQ_(E}\/eQ_?SQ_*碾^sQ_?~*碾GV2nj@(C{~PΌ3pbd͔Ppj͈Fk;4sCQԧb L`h7lӢe Bd8Yk-\5y zG"s;4b`|fAP @CA#ʻun4$_p)ozn@8&E8>/b*2` >O6ĄLv;Ƅj6cw&Fc*]#.t2W7j۴LG^+galicGry¹|Qo97*o5_NCk$A9AHfԣw^ ~o8}:SpI#I1 ٞRO/r T VGӝҌE$@YͤBnzf3S@?a98Bɛ]ddb fZU1T}I! 6d85uvk]:TK( !<١|Ojv ҦxsumH(l" e?tCg6~;}qC4segt`lT !0Y+Z5J#BQZX ) QBF4'H`h?6GyQ zVs{c;gBpv1m?Q[{_ w@l߸&Lqr- !#3 ޅIQ j)0< tY9k*,VP.*$By)e)_(R~Y/JK_R~.|K_s)_ϥ|}/빔KU)_?s)_|C[b8F-QA0)Hh)ZEJǐ%"֤ΈSyy^kҰL?3ˀ|躤 ~]k22S:3p͸cPQ1“8 e h&sFl=#.!zDTu k8Xx\'0zeioW3}+||l@3DmB3Xmil G6Y+CN+t02&+Czj<8Hvwġi(jXO>;ѧ;&t&fE"@e d@m' ztAxiEuc'$;wtfWVwLF,y޺K֒j遞VǢ*3TiV44;46밖VZ\"/2 Mqk v9Yš5f;lMK3z.֟/W=}26V8ɅNy`³D S>N-_<*ky㜌4zR>9Z΁OPBn- l24U~9lH3 :M+6؊vZcCuUJ\P0!M6< k5Yn=\mhmVVjq2ǩ9L-9F-jyPˋZ٬0Yf,^;F #"vW"YUUIJS(O&K$b#bjA"z1XvC\Xh[`1i\QдQJ.t*g~JUU*(&J5ЂpqfRuz_茠Hh@Be@4$-ïx謇 dtNqQ8hxYGYuܫuT ݍ mkjP 誯=[m E> $ڸ|q_JzۢHyY&^$E9j6S+`딲` [ҭ@ukNƓ )fSA>6M&hDe;0:Q|W :@b+-@PLHTJ=DSϞU'S|XHUS|T5XTkSռ[ mT'PU(Ҭ3CYqUC#J݈ύ(QF~lDF~Ոύ(u#J?6׍(Ԉ/QF7܈O(QF~nDZP+mf lYkJjC=T Z7@a*&6@݌rhIe|x7Ik|FpW8lnh64X [iRJS1XBTAi$i+t,qV!aB$6|)^ :7-cyZ6qpV0;nŌ-Ԙ^0:N.sShnj1N|sj6 Ppd\D-r inmf { ԀG&;H՚ucXԴ*:#xv!R`ν'; [.;X7?_%8Yo ůͷn~/Ooc}ꋯ|q|6޾GG}}zB}m fr.|rǻ?i%===ۿ[~ƴhܿӛw [擦=}i]=F}}??OXO_ W;Ūk~99N y]#m]?h ?>|x}9Y^^?޷;O s8odGR>. }>xof0^[ جǻ%ܼ|pDo~GwAg7_ɛhA}vx5\`xN@aH2RZ;=g8:,yuLҝlG3Ca$8`͢rt`C~"PQ6UPԕ )v|n"P.r"jUP~ۡ[E%WAX-UPfG4ԳP|hi;"!+CpM9fc1YҳP&VH&0qs py݌HXQkS5V֣gN2NE[_&nc0H57}GM5*x6& ETqiNۥ)—0Dcz5]K\EH IN^ɸgW>fPnу(%6xY;vT]#f=ZJ~#J-"DΈsU\mH!F A|!&%'ڄk+SSǴFdg)tW7DTH$SgP׋oLL""1?.(*F52x;Ӿ΀zil.p$$$/o,3̀|¤/]2B:;pM٥CPQ1“8O9#F7nP˻W#v Gl;gqSt\(A=6qƽ w:؞]ٌU,6QN=#ú2h 8m3$n[R C7BrɕW^C@$&f\74T6$®~kfOSdұ ٓ"-'-2{ҾI22:GhoS| 5 Bc(4k2{62{A=*^me6G^;'as)RRRZͥx66*l.9l.)lAvOPP9Z)lNpLk챰9╎L9bļVћ+~`3v &C0TqLkה_6Vkt+&&:wgߢ{\գdBKaCLȥCD[9L!r!rc|}4FjlaAl.)D. w )DD9D2 "W!P.mOiɨn!qM:ejWW$nmy޺Vm@HzU|ŴI#'AQJ3C7+]Dc|ӱaZ$aȘ lP ]5HsY*ki,kAAZ5HsYt] e uY45Hi*kAe 5HSY(k麬Aܽpejb8T+hU9Νe{c q\ZJ&V`Sk#P mÝQ6!ڊk4 ) ŝ1_65-L% ^HpLk ̨ה[:VK( !$|nvrʣCL> N2CX0$4jp&Q_^c󝮦gtdtQL^NNP"%vOA-mc?W RSD 5嘍U*BFeeHBI5@BQ{fT e/"ʷZ!]vۓDFQ1ȈVݿj6޾cnAO Wb0&tY8nB6V@ҡQZX0)#u8Kzq.*&F.j&ƹhb\VMsx]71Nu8Nډq*zb#OSŸb\QnP rEcP`0Q%@,D:Tvva;GIdC{ XqHA>DN_B$ƃ1UT5Se&0J#R[g e.tP*]J,yU=/5,τk: qkyu3bc+D8z>(6R_氖֪؊hC"tM5wnY2*A5mf<[ieˁ%{,Q&fu~P+-a蘨 YmLV}LL֝LVLL,ڙ,:[,zMM]MmM&dlhmm277Yt7& ݣ;ǙJzAHTDZ@8}:Qr{Dinn'%qwFc#*%)q*fbbdtӳtgUi%NkT8&S^1K*Wy eR2'ib O<{0{cXyc=1̞x-<_{⣟=ѯ<ϞJg5'Ӗ6~' WO<{Oґa'+&d1R߶2bɷc3rb9 D&NnE>. ɱw]~0BKsDFւ+ϝ`l T !,*4FcJZ疍U~EDgF#8G gQ[ O#(@"apP EDqF@F1rJB MKgy@H-Dg SNl]:v0xpDiY6TK( .%BZ]㪽>qԘؚq2|gl`Y^49"w)0ϰXc!^g&&MW;{Džkbkq2b0 #҄7HKS!!y"%im rה]:T:, dTP$S݃U_݌*\sGJ&Dip/ݕ'i6}W'!*У݋3z JLJ=<6\ &j%Gk.>1U\SX0-b0lLfBdKW)|UU5y 56a}j -M`n t%+JEWbR+abqG l%~dړCdTy;Vuڈ/!+0l/ ^€1)w(6]YELrBpng3}`BF#CI3(-lV+aح[q(lrP+&6ve2!rRG))J<`$X`p<|@rfX͟‌PC, l^_'tYЁ1.@v;Af<LmLMMQZlVB۶D#J̲U^BOt)<,%\b=,KE0Xc0XaYb=%âzXXs0Xa.z%Xs*a.~zhSDM)Ah~iBhMҹC9U~"ԠQ #4Eg~vZXO2qNpmP)XXe Eav$@@=; B< J5eUK !=KXjS F~M@HRx\_W*nRUN+y:XAAF߹'9.!WeFqCaue̔kө>k˒KupLk9yQ/)th)7LTD$Sƭ%41 `h`zZhˑ>~LJݓZ?DTЀ:bǰov( TVߡuqlͺ 3:AN3x[ؼ`IbVfb5 ]Sϑ>2TOϔ/> hb)\dNvֽn\\.~N: <ދ.` BL}K O96T~QB)`tGP=sE³@=in"W`W`Z` d{+4!fv=)2 sF'Se@A'$VX2":4|'R ÁZVFiNQ<ChyJآ"(6cdla2x C5Ǵơ\첡UZ1!) qF c7:d>c+RG9ES inهo510D4Lt]C84t0Nߙٷڀi ӧ\#113׌[:VK( !<9Vԫ'G0l [d>ʇ hjMTeŰ;Δ j- eGS.p3& %P(qnʅ& c0K"`m@Zr 3ÁpLi2ה[:T ( ;4BQd hG `9Pe#׳QP#!~M~vs<R(h rrD@;2'GNJ h6Ota8y&ke)l02&+Czju|aY;UUUU0W˪a~waY;LUUwaU\;\W˪зOpٝak J7"C\EX7,aq꒥UyKP>)i6(|WC$oX%r6]~.E}EQ_,碾~Q/UQ_?\_SQ_??ZԷu8qCPP*Fq^* u(wfIK4t(=5SB53B߫6#~IKP EQ10) #X O5à &ge)lrP+*&:w)%\Ј՛=B$9 *Qѐ|w¥ ~w$L'3MBq |t+<_FCTƅe(z}l 1vM׍ [lMTF\2>He(oxx IEPگ^×PDP|PPШWP*WPwP/-2B# aJS5߫mNPK4{Tms3Pos̅V1~c.6\yyysss M haz-l`0*{,xCEq_1٦0Pj Pql86 OY A4Q,4_ A T"7m, qOg,{. H0FM-mV حE"1M\SXe-2 dTV$T:3sdH^qZ%~p|ԶiWkpyf:sZ!~l>l<^8BwʡτT!c&~l5V>7qG-/߭MÙZ[BGfe ;('ynSwZN HpLku>2JG*Cy"B.$e\s?g52ɷ&W&zyX'Ҥ2zToyTY^<[G/ -|_M*V3PgX솎`KK;b0 B"F+|D SaxFIl/rהU:TY:'\TH$SR~Qϥ|_s)_?s)_(뗥|\/Je)_?S)_*RK^s)_?R~*RGKz0kUIq8w#*3)[ڃ`RXSH=+!KETI3"~a3 P<V fUTuI"dd85ufqK*[y 忡b2'q7 `=M<؍zF\BǕd:,qre=;O`, !p߮gpc`=W#ـfڄfdj)mVVXc-a20dLV,&myǪzm@UJ~ Ca=‡|39@`ɞ@=al! AD? C*Il*kKkuwDj G)i뎁H<lYMKg-CƖ%UyKn͖[V'k9](Jkܯqkb{=6k  m~hKځa% }Gʑ~\8G mntѱ\I?R!-Pe;tH;='3GBN)ame WF1QN~,82EWq HAeg?BJsN\1qC]Yq0ytIv8!ͮ(YlguU=%=߭&E?Tm9fҤs-viivYuwkil(Da-׭֏듵b.D^eΡ`s(5jfvٚ$g\:Ey?y_({0em>0q( Dg[O*yC}Zܩ yF9 rUN9iLO}rʵtѯn Z`dh'6,=voU;r *gt(HWl&=:3,zaC\Ym8tyBkzjbն9TmHeSsZ^E9H-sZ!j#iy Ok~mMi"2m6K8,%VqLI-r;$y9"TͥwPԏUs 9Z~-g6QM߇⎭@2UԂad0u,d5Oe,EmUvt郔}HMщ(0T1gv`t8kunVZ$P{L=竆O\LUaj9T5j6yHUmjgO!FP.!YgII T5 T5!)UM%#FQU#J?7c#Jo(؈ύ(QF~lDQ_4S#Jύ(}oDQE#J?5׍(܈2ȡV*ڪʳfCzͩ| nj *TVMmLM)f}-* hhont$kqZm"iX ҤVVbV5\3G/HVX0B0HlR½tnZHimV ,av݊[1o`-'u\iMU:uNG!]C_QU{ u+Y7Nw4,p{a7\Edlo~/a<ʨퟡ@!|COo޸d_΄Cl_Ĝm7'wP>=}w]#ݧ A_|1G m3⋿e =/}IuWԡw cNľm{r$4>I)qϠdIKzהd^S=P/ߟ~w/wk?^z”/Ϗ ]wwm_edO!*#ѩO!^?~j˓L63@t;n%ԌUk.;/M#?O߿w/hl$ߩixWY=nŸ¨Ǘ!&E0˷[ Gbj YGh?+WO߿÷l_bK+"?ȶIޞ=PIy8A4_^*Ϟ~𩁿\v鷏wwk/跐nӧח; ܋wbs釧?<:?߽޽Ō=w}<6[V~߃L/Co~忝|mE>=|@(/]y'H}ysv}n)}Q<1Y̗Խfehu$On;ODom+_>=Pj gor[y ^˵&P6>$ݹEͿN%V&*[(xm߿6#4$^{Gٯ]E^DiǏՋrKK⾾ r/xDRG|4_:~:= 6_?(:y+u[P{9Us ѯGvhϟ귰)BUϿl|-$zo]H.BΛ\^ K .|a^׻~Twsp` 9s`z!UQbF1qōd=.MN? S>]:?/WfCd~_)įx>>4R*og M A7mZqޯަ|v1keqV/+= u~-M}zfSZ4' ?]r0ݯ^>ZuuQr^zѣ CwOA _8 R9x$E8.Çtg<߼a xKzUZGAU٤jko! twMfi"3t)JtGƪa2JL,$1N$'efE'^٧ʌ9Nv U z\kӵy&4zĹr\tSx8U Ș/&~j4J-.n%I|3o[$i]kk@nQ%f\ mv"4='-x!; ɑMwUUۇ$JPaIxmfy K O9EGSp Klq2}W4\4Xe endstream endobj 83 0 obj << /Type /Page /Contents 84 0 R /Resources 82 0 R /MediaBox [0 0 612 792] /Parent 78 0 R >> endobj 82 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F15 20 0 R /F46 33 0 R /F43 27 0 R /F42 26 0 R /F40 21 0 R /F49 38 0 R /F39 19 0 R /F29 13 0 R /F28 12 0 R /F61 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 88 0 obj << /Length 229 /Filter /FlateDecode >> stream xm;o@[ .{]I$ɢrPX6Gp6&+EvCh=T9Jp($7Ah`߫)Ͽ-iI|N?ǸVSȜc~8a`3Ull!y;[a8uu(tzJ dzAε^[lChҬ;'`:7I2P_$҂ݐ(YF D$+*?N6 endstream endobj 87 0 obj << /Type /Page /Contents 88 0 R /Resources 86 0 R /MediaBox [0 0 612 792] /Parent 78 0 R >> endobj 86 0 obj << /ColorSpace 3 0 R /Pattern 2 0 R /ExtGState 1 0 R /Font << /F44 7 0 R /F15 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1 0 obj <<>> endobj 2 0 obj <<>> endobj 89 0 obj [666.7 0 0 0 622.2 622.2 0 0 0 0 0 0 800 666.7 666.7 622.2 0 0 622.2 577.8] endobj 90 0 obj [733.3 0 0 0 687.8 687.8 0 0 0 0 0 0 870 733.3 733.3 687.8 0 0 687.8 642.2] endobj 91 0 obj [700 0 0 0 653.3 653.3 0 0 0 0 0 0 840 700 700 653.3 0 0 653.3 606.7] endobj 93 0 obj [524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9] endobj 94 0 obj [680.6 680.6] endobj 95 0 obj [826.4] endobj 96 0 obj [1000] endobj 97 0 obj [531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1] endobj 98 0 obj [513.9] endobj 99 0 obj [638.7 638.7 958.1 958.1 574.9 349.9 574.9 958.1 574.9 958.1 894.2 319.4 447.1 447.1 574.9 894.2 319.4 383.2 319.4 574.9 574.9 574.9 574.9 574.9 574.9 574.9 574.9 574.9 574.9 574.9 319.4 319.4 894.2 894.2 894.2 542.9 894.2 869.2 817.9 830.4 881.7 755.4 723.4 903.9 899.8 436 594.3 901.2 691.5 1091.4 899.8 863.7 785.9 863.7 862.3 638.7 799.8 884.5 869.2 1188.6 869.2 869.2 702.6 319.4 574.9 319.4 702.6 894.2 319.4 558.9 638.7 511 638.7 527 351.3 574.9 638.7 319.4 351.3 606.8 319.4 958.1 638.7 574.9 638.7 606.8 473.5 453.5 447.1 638.7 606.8 830.4 606.8 606.8 511 574.9 319.4 574.9 702.6 191.6 869.2 869.2 830.4 830.4 881.7 755.4 755.4 903.9 691.5 691.5 691.5 899.8 899.8 913.7 863.7 862.3 862.3 638.7 638.7 638.7 799.8 799.8 884.5 884.5 869.2 702.6 702.6 702.6 1010.9 436 638.7 529 558.9 558.9 511 511 810.2 527 527 574.9 319.4 502 386.4 638.7 638.7 638.7 574.9 473.5 473.5 453.5 453.5 453.5 447.1 447.1 638.7 638.7 606.8 511 511 511 670.7 349.9 542.9 734.5 869.2 869.2 869.2 869.2 869.2 869.2 1041.4 830.4 755.4 755.4 755.4 755.4 436 436 436 436 881.7 899.8 863.7 863.7 863.7 863.7 863.7 1169.2 894.2 884.5 884.5 884.5 884.5 869.2 722 1277.5 558.9 558.9 558.9 558.9 558.9 558.9 830.4 511 527 527 527 527 319.4 319.4 319.4] endobj 100 0 obj [312.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 562.4 312.4 312.4 874.8 874.8 874.8 531.1 874.8 849.3 799.6 812.3 862.1 738.2 707 884 879.4 418.9 580.9 880.6 675.8 1066.9 879.4 844.7 768.3 844.7 838.9 624.8 782.2 864.4 849.3 1161.8 849.3 849.3 687.3 312.4 562.4 312.4 687.3 874.8 312.4 546.7 624.8 499.9 624.8 513.2 343.7 562.4 624.8 312.4 343.7 593.6 312.4 937.3 624.8 562.4 624.8 593.6 459.4 443.6 437.4 624.8 593.6 812.3 593.6 593.6 499.9 562.4 312.4 562.4 687.3 187.5 849.3 849.3 812.3 812.3 862.1 738.2 738.2 884 675.8 675.8 675.8 879.4 879.4 893.3 844.7 838.9 838.9 624.8 624.8 624.8 782.2 782.2 864.4 864.4 849.3 687.3 687.3 687.3 981.2 418.9 624.8 514.9 546.7 546.7 499.9 499.9 783.9 513.2 513.2 562.4 312.4 480.8 378 624.8 624.8 624.8 562.4 459.4 459.4 443.6 443.6 443.6 437.4 437.4 624.8 624.8 593.6 499.9 499.9 499.9 656.1 342.5 531.1 718.6 849.3 849.3 849.3 849.3 849.3 849.3 1018.3 812.3 738.2 738.2 738.2 738.2 418.9 418.9 418.9 418.9 862.1 879.4 844.7 844.7 844.7 844.7 844.7 1143.2 874.8 864.4 864.4 864.4 864.4 849.3 705.8 1249.7 546.7 546.7 546.7 546.7 546.7 546.7 812.3 499.9 513.2 513.2 513.2 513.2 312.4 312.4 312.4] endobj 101 0 obj [319.4 552.6 552.6 552.6 552.6 552.6 552.6 552.6 552.6 552.6 552.6 552.6 319.4 319.4 844.2 844.2 844.2 523.5 844.2 813.7 770.6 785.9 829 741.5 712.3 851.2 813.7 405.5 566.5 842.9 683.2 988.7 813.7 844.2 741.5 844.2 799.8 611 785.9 813.7 813.7 1105.3 813.7 813.7 669.3 319.4 552.6 319.4 669.3 844.2 319.4 613.2 579.9 591 624.3 557.6 535.4 641 613.2 302.1 424.3 635.4 513.2 746.5 613.2 635.4 557.6 635.4 602.1 457.7 591] endobj 102 0 obj [524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9] endobj 103 0 obj [666.7 0 0 0 622.2 622.2 0 0 0 0 0 0 800 666.7 666.7 622.2 0 0 622.2 577.8] endobj 104 0 obj [536 536 813.7 813.7 499.9 319.4 499.9 833.1 499.9 833.1 758.2 277.7 388.8 388.8 499.9 777.6 277.7 333.3 277.7 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 277.7 277.7 777.6 777.6 777.6 472.1 666.5 666.5 666.5 638.7 722 597.1 569.3 666.5 708.2 277.7 472.1 694.3 541.5 874.8 708.2 735.9 638.7 735.9 645.7 555.4 680.4 687.3 666.5 944.2 666.5 666.5 611 288.8 499.9 288.8 611 777.6 277.7 480.4 516.5 444.3 516.5 444.3 305.5 499.9 516.5 238.8 266.6 488.8 238.8 794.3 516.5 499.9 516.5 516.5 341.6 383.2 361 516.5 461 683.2 461] endobj 105 0 obj [388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6] endobj 106 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8 500 500 611.1 500 277.8 833.3] endobj 107 0 obj [569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4] endobj 108 0 obj [639.7 565.6 517.7 444.4 405.9 437.5 496.5 469.4 353.9 576.2 583.3 602.6 494 437.5 570 517 571.4 437.2 540.3 595.8 625.7 651.4 622.5 466.3 591.4 828.1 517 362.8 654.2 1000 1000 1000 1000 277.8 277.8 500 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 777.8 500 777.8 500 530.9 750 758.5 714.7 827.9 738.2 643.1 786.3 831.3 439.6 554.5 849.3 680.6 970.1 803.5 762.8 642 790.6 759.3 613.2 584.4 682.8 583.3 944.4 828.5 580.6 682.6 388.9 388.9 388.9 1000 1000 416.7 528.6 429.2 432.8 520.5 465.6 489.6 477 576.2 344.5 411.8 520.6 298.4 878 600.2 484.7 503.1 446.4 451.2 468.8 361.1 572.5 484.7 715.9 571.5 490.3] endobj 109 0 obj [569.3 569.3 569.3 569.3 569.3 569.3 569.3 569.3 569.3 323.3 323.3 876.8 876.8 876.8 538.6 876.8 843.1] endobj 110 0 obj [749.8 499.9 499.9 499.9 277.7 444.3 277.7 277.7 444.3 444.3 333.3 333.3 333.3 555.4 555.4 499.9 999.8 0 388.8 277.7 305.5 583.2 555.4 555.4 833.1 833.1 499.9 277.7 499.9 833.1 499.9 833.1 777.6 277.7 388.8 388.8 499.9 777.6 277.7 333.3 277.7 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 499.9 277.7 277.7 777.6 777.6 777.6 472.1 777.6 749.8 708.2 722 763.7 680.4 652.6 784.5 749.8 361 513.8 777.6 624.8 916.4 749.8 777.6 680.4 777.6 735.9 555.4 722 749.8 749.8 1027.5 749.8 749.8 611 277.7 499.9 277.7 611 777.6 277.7 499.9 555.4 444.3 555.4 444.3 305.5 499.9 555.4 277.7 305.5 527.7 277.7 833.1 555.4 499.9 555.4 527.7 391.6 394.3 388.8 555.4 527.7 722 527.7 527.7 444.3 499.9 277.7 499.9 611 166.6 749.8 749.8 722 722 763.7 680.4 680.4 784.5 624.8 624.8 624.8 749.8 749.8 791.5 777.6 735.9 735.9 555.4 555.4 555.4 722 722 749.8 749.8 749.8 611 611 611 860.9 361 555.4 444.3 499.9 499.9 444.3 444.3 674.8 444.3 444.3 499.9 277.7 402.7 336 555.4 555.4 555.4 499.9 391.6 391.6 394.3 394.3 394.3 388.8 388.8 555.4 555.4 527.7 444.3 444.3 444.3 583.2 277.7 472.1 638.7 749.8 749.8 749.8 749.8 749.8 749.8 902.6 722 680.4 680.4 680.4 680.4 361 361 361 361 763.7 749.8 777.6 777.6 777.6 777.6 777.6 1013.6 777.6 749.8 749.8 749.8 749.8 749.8 624.8 1110.8 499.9 499.9 499.9 499.9 499.9 499.9 722 444.3 444.3 444.3 444.3 444.3 277.7 277.7 277.7 333.3 499.9 555.4 499.9 499.9 499.9 499.9 499.9 777.6 499.9 555.4 555.4 555.4] endobj 111 0 obj [305.5 549.9 549.9 549.9 549.9 549.9 549.9 549.9 549.9 549.9 549.9 549.9 305.5 305.5 855.4 855.4 855.4 519.3 855.4 830.2 781.7 794.3 842.8 721.6 691 864.3 859.8 404.9 567.8 860.8 660.5 1043 859.8 825.8 751.1 825.8 817.3 611 764.7 845 830.2 1135.7 830.2 830.2 672.1 305.5 549.9 305.5 672.1 855.4 305.5 549.9 611 488.8 611 500 336 549.9 611 305.5 336 580.4 305.5 916.4 611 549.9 611 580.4 446.3 433.8 427.7 611 580.4 794.3 580.4 580.4 488.8 549.9 305.5 549.9 672.1 183.3 830.2 830.2 794.3 794.3 842.8 721.6 721.6 864.3 660.5 660.5 660.5 859.8 859.8 873.3 825.8 817.3 817.3 611 611 611 764.7 764.7 845 845 830.2 672.1 672.1 672.1 954.8 404.9 611 501.7 549.9 549.9 488.8 488.8 761.2 500 500 549.9 305.5 463.6 369.6 611 611 611 549.9 446.3 446.3 433.8 433.8 433.8 427.7 427.7 611 611 580.4 488.8 488.8 488.8 641.5 335 519.3 702.6 830.2 830.2 830.2 830.2 830.2 830.2 995.5 794.3 721.6 721.6 721.6 721.6 404.9 404.9 404.9 404.9 842.8 859.8 825.8 825.8 825.8 825.8 825.8 1117.7 855.4 845 845 845 845 830.2 690 1221.9 549.9 549.9 549.9 549.9 549.9 549.9 794.3 488.8 500 500] endobj 112 0 obj [611 611 611 611 611 611 611 611 611 351.8 351.8 935 935 935 578.6 935 896.1] endobj 113 0 obj [691.9 0 0 0 646.9 646.9 0 0 0 0 0 0 826.7 691.9 691.9 646.9 0 0 646.9 602] endobj 114 0 obj [1022 841.5 873.2 767.1 873.2 827.3 632.6 813.1 841.5 841.5 1142.3 841.5 841.5 692.7 331.7 572.4 331.7 692.7 873.2 331.7 618.7 585.2 596.5 629.9 562.8 540.5 646.8 618.7 305.5 428.6 641 518.1 752.9 618.7 641.2 562.8 641.2 607.6 462.2 596.5] endobj 115 0 obj [599.4 570.8 570.8 856.3 856.3 513.8 285.4 513.8 856.3 513.8 856.3 799.2 285.4 399.6 399.6 513.8 799.2 285.4 342.5 285.4 513.8 513.8 513.8 513.8 513.8 513.8 513.8 513.8 513.8 513.8 513.8 285.4 285.4 799.2 799.2 799.2 485.2 799.2 770.5 727.8 742.1 784.8 699.2 670.7 806.3 770.5 370.9 528 799 642.1 941.7 770.5 799.2 699.2 799.2 756.3 570.8 742.1 770.5 770.5 1055.9 770.5 770.5 627.9 285.4 513.8 285.4 627.9 799.2 285.4 513.8 570.8 456.7 570.8 457.1 314 513.8 570.8 285.4 314 542.3 285.4 856.3 570.8 513.8 570.8 542.3 401.9 405.3 399.6 570.8 542.3 742.1 542.3 542.3 456.7 513.8 285.4 513.8 627.9 171.3 770.5 770.5 742.1 742.1 784.8 699.2 699.2 806.3 642.1 642.1 642.1 770.5 770.5 813.4 799.2 756.3 756.3 570.8 570.8 570.8 742.1 742.1 770.5 770.5 770.5 627.9 627.9 627.9 884.7 370.9 570.8 456.7 513.8 513.8 456.7 456.7 693.1 457.1 457.1 513.8 285.4 413.9 345.4 570.8 570.8 570.8 513.8 401.9 401.9 405.3 405.3 405.3 399.6 399.6 570.8 570.8 542.3 456.7 456.7 456.7 599.4 285.4 485.2 656.5 770.5 770.5 770.5 770.5 770.5 770.5 927.5 742.1 699.2 699.2 699.2 699.2 370.9 370.9 370.9 370.9 784.8 770.5 799.2 799.2 799.2 799.2 799.2 1041.7 799.2 770.5 770.5 770.5 770.5 770.5 642.1 1141.7 513.8 513.8 513.8 513.8 513.8 513.8 742.1 456.7 457.1 457.1 457.1] endobj 116 0 obj [886.5 657.2 822.9 908.4 892.7 1221.3 892.7 892.7 723 328.6 591.5 328.6 723 920.1 328.6 575.1 657.2 525.8 657.2 542.8 361.5 591.5 657.2 328.6 361.5 624.4 328.6 985.9 657.2 591.5 657.2 624.4 488 466.6 460.1 657.2 624.4 854.4 624.4 624.4 525.8 591.5 328.6 591.5 723 197.2 892.7 892.7 854.4 854.4 906.4 776.4 776.4 929.7 710.6 710.6 710.6 924.2 924.2 939.3 888.7 886.5 886.5 657.2 657.2 657.2 822.9 822.9 908.4 908.4 892.7 723 723 723 1037.7 446.2 657.2 544.5 575.1 575.1 525.8 525.8 831 542.8 542.8 591.5 328.6 514.1 397.6 657.2 657.2 657.2 591.5 488 488 466.6 466.6 466.6 460.1 460.1 657.2 657.2 624.4 525.8 525.8 525.8 690.1 360.1 558.7 755.8 892.7 892.7 892.7 892.7 892.7 892.7 1070.7 854.4 776.4 776.4 776.4 776.4 446.2 446.2 446.2 446.2 906.4 924.2 888.7 888.7 888.7 888.7 888.7 1202.2 920.1 908.4 908.4 908.4 908.4 892.7 742.1 1314.5 575.1 575.1 575.1 575.1 575.1 575.1 854.4 525.8 542.8 542.8] endobj 117 0 obj [524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 0 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9 524.9] endobj 118 0 obj [511 1022 0 408.8 306.6 332.1 613.2 562.1 587.6 881.5 894.2 511 306.6 511 817.6 511 817.6 766.5 306.6 408.8 408.8 511 766.5 306.6 357.7 306.6 511 511 511 511 511 511 511 511 511 511 511 306.6 306.6 766.5 766.5 766.5 511 766.5 743.2 703.7 715.4 754.8 678.2 652.6 773.4 743.2 385.5 524.9 768.7 627.1 896.5 743.2 766.5 678.2 766.5 729.3 562.1 715.4 743.2 743.2 998.6 743.2 743.2 613.2 306.6 511 306.6 613.2 766.5 306.6 511 459.9 459.9 511 459.9 306.6 459.9 511 306.6 306.6 459.9 255.5 817.6 562.1 511 511 459.9 421.6 408.8 332.1 536.5 459.9 664.3 463.8 485.4 408.8 511 306.6 511 613.2 204.4 743.2 743.2 715.4 715.4 754.8 678.2 678.2 773.4 627.1 627.1 627.1 743.2 743.2 780.4 766.5 729.3 729.3 562.1 562.1 562.1 715.4 715.4 743.2 743.2 743.2 613.2 613.2 613.2 845.4 385.5 511 459.9 511 511 459.9 459.9 511 459.9 459.9 459.9 255.5 255.5 319.4 562.1 562.1 562.1 511 421.6 421.6 408.8 408.8 408.8 332.1 332.1 536.5 536.5 485.4 408.8 408.8 408.8 562.1 306.6 511 768.9 743.2 743.2 743.2 743.2 743.2 743.2 882.6 715.4 678.2 678.2 678.2 678.2 385.5 385.5 385.5 385.5 754.8 743.2 766.5 766.5 766.5 766.5 766.5 984.8 766.5 743.2 743.2 743.2 743.2 743.2 627.1 1073.1 511 511 511 511 511 511 715.4 459.9 459.9 459.9 459.9 459.9 306.6 306.6 306.6] endobj 119 0 obj [531.3] endobj 120 0 obj [773.2 276.4 386.8 386.8 497.2 773.2 276.4 331.6 276.4 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 497.2 276.4 276.4 773.2 773.2 773.2 469.6 773.2 745.3 704 718 759.2 676.4 648.8 780 745.3 358.9 510.8 772.9 621.2 910.9 745.3 773.2 676.4 773.2 731.6 552.4 718 745.3 745.3 1021.3 745.3 745.3 607.6 276.4 497.2 276.4 607.6 773.2 276.4 497.2 552.4 442 552.4 442 304 497.2 552.4 276.4 304 524.8 276.4 828.4 552.4 497.2 552.4 524.8 386.8 392.3 386.8 552.4 524.8 718 524.8 524.8 442 497.2 276.4 497.2 607.6 166 745.3 745.3 718 718 759.2 676.4 676.4 780 621.2 621.2 621.2 745.3 745.3 786.8 773.2 731.6 731.6 552.4 552.4 552.4 718 718 745.3 745.3 745.3 607.6 607.6 607.6 855.7 358.9 552.4 442 497.2 497.2 442 442 666.3 442 442 497.2 276.4 395.4 334.3 552.4 552.4 552.4 497.2 386.8 386.8 392.3 392.3 392.3 386.8 386.8 552.4 552.4 524.8 442 442 442 580 276.4 469.6 635.2 745.3 745.3 745.3 745.3 745.3 745.3 897.2 718 676.4 676.4 676.4 676.4 358.9 358.9 358.9 358.9 759.2 745.3 773.2 773.2 773.2 773.2 773.2 1007.6 773.2 745.3 745.3 745.3 745.3 745.3 621.2 1104.4 497.2 497.2 497.2] endobj 121 0 obj [883.2 724.8 752.3 659.4 752.3 712.2 541.2 699.6 724.8 724.8 988.7 724.8 724.8 594 277.3 488.4 277.3 594 752.3 277.3 628.2 593.8 605.6 639.9 570.8 547.7 657.3 628.2 305.5 432.5 651.2 524.7 766.4 628.2 651.7 570.8 651.7 616.9 467.3 605.6] endobj 122 0 obj [513.6 513.6 770.4 770.4 462.6 256.8 462.6 771.2 462.6 771.2 719.8 256.8 359.7 359.7 462.6 719.8 256.8 308.2 256.8 462.6 462.6 462.6 462.6 462.6 462.6 462.6 462.6 462.6 462.6 462.6 256.8 256.8 719.8 719.8 719.8 436.9 719.8 693.6 655.3 668.3 706.7 629.5 603.8 726.1 693.6 333.5 475.2 719.3 578.1 847.9 693.6 719.8 629.5 719.8 681 514 668.3 693.6 693.6 950.8 693.6 693.6 565.5 256.8 462.6 256.8 565.5 719.8 256.8 462.6 514 411.1 514 411.1 282.5 462.6 514 256.8 282.5 488.3 256.8 771.2 514 462.6 514 488.3 359.7 364.8 359.7 514 488.3] endobj 123 0 obj [531.1 1062.2 0 413.1 295.1 324.6 619.6 590.1 590.1 885.2 885.2 531.1 295.1 531.1 885.2 531.1 885.2 826.2 295.1 413.1 413.1 531.1 826.2 295.1 354.1 295.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 531.1 295.1 295.1 826.2 826.2 826.2 501.6 826.2 795.6 751.9 767.2 810.9 722.4 692.9 833.3 795.6 382.5 545.4 825.1 663.4 972.7 795.6 826.2 722.4 826.2 781.4 590.1 767.2 795.6 795.6 1090.7 795.6 795.6 649.1 295.1 531.1 295.1 649.1 826.2 295.1 531.1 590.1 472.1 590.1 472.1 324.6 531.1 590.1 295.1 324.6 560.6 295.1 885.2 590.1 531.1 590.1 560.6 414 419 413.1 590.1 560.6 767.2 560.6 560.6 472.1 531.1 295.1 531.1 649.1 177 795.6 795.6 767.2 767.2 810.9 722.4 722.4 833.3 663.4 663.4 663.4 795.6 795.6 840.4 826.2 781.4 781.4 590.1 590.1 590.1 767.2 767.2 795.6 795.6 795.6 649.1 649.1 649.1 913.7 382.5 590.1 472.1 531.1 531.1 472.1 472.1 716 472.1 472.1 531.1 295.1 427.8 357 590.1 590.1 590.1 531.1 414 414 419 419 419 413.1 413.1 590.1 590.1 560.6 472.1 472.1 472.1 619.6 295.1 501.6 678.7 795.6 795.6 795.6 795.6 795.6 795.6 958.4 767.2 722.4 722.4 722.4 722.4 382.5 382.5 382.5 382.5 810.9 795.6 826.2 826.2 826.2 826.2 826.2 1076.5 826.2 795.6 795.6 795.6 795.6 795.6 663.4 1180.3 531.1 531.1 531.1 531.1 531.1 531.1 767.2 472.1 472.1 472.1 472.1 472.1 295.1 295.1 295.1] endobj 124 0 obj << /Length1 752 /Length2 1024 /Length3 0 /Length 1550 /Filter /FlateDecode >> stream xڭR}XLYU SDw>j1 5e̽S{NJԦaRR)VQ`IDŐ'XbZ*N}6s9'a+ \#\!7p" yxP@q_L y'+hL,fH-GD1I Xp In-PÉx#v@Q  1(Fq7XaRx~h*'(QƓl@zqL`DJqeip5VbA~4p%}dr@ %6|0J>b*ac12x|h\4(!R,#<ܨwHrN蜏3b#%)5GkߚG&(2_$.zeL(y@T(!+HH"@InNG& ŕD!ܕb0 _4R>/JgWG8ij?fȖgm9Ac8Z*Y&k)kt፪ozU}˅3'Ny垵e|4mu`uv>[}E~]9rostKuES]斞Jt.8TQm^_ hs´5'g |Bv[,Tƛb(;ʍ"?Gd~*uXld]bӅW 灁_x9-qg+}Djlsz~P@o{G'RoX'.s8PjqnCW- Uޤ^顦^?HέfSU^6!Bj^Q+UNp":gsav#?o}!p/ MjU'>~.[=.+|V祠:Spu =ZZ^4c\t>+;=ͼyG2g䋈)gnRfXl&Շk/ٱ6u@9Pу]':WwBu&~A%^pTÚKT6tb}:YYL}}C +qK=f/SrS{q Y G:wr#Bn}Wsu}QqUxڟNP#71:4g@9H$+vK4%fW3PHxrHZumٳFu>Vy'5c&"o  endstream endobj 125 0 obj << /Type /FontDescriptor /FontName /CZNUER+CMEX10 /Flags 4 /FontBBox [-24 -2960 1454 772] /Ascent 40 /CapHeight 0 /Descent -600 /ItalicAngle 0 /StemV 47 /XHeight 431 /CharSet (/radicalBig) /FontFile 124 0 R >> endobj 126 0 obj << /Length1 1044 /Length2 4718 /Length3 0 /Length 5392 /Filter /FlateDecode >> stream xڭg8` FtŒ: Q'J001f&5jH{-Z=%"DI^x{O_e^{߳ I#pHm !%)jI5 pChVF@BR  @ Avr&E4DL]nh8 4phI:4;tD"$RR@N:"XO'=, Fxts'JE~iD Qx:?0W4_8W4!nB%gD=\Gapu Gkc4 D0_q$Ob~yL46ah,R3Inho X "&2-,@cr@@""}h, DzAXxH?sr@H7)A!Y ?D|R?D  w-" 9"  80B"ߐX7AN>NTGD!QD'}R!Q7oHׯ}%drރe9%=ܐX¯81f8dH7B&ׅhuN) o IQ\Vbq0G^e c.aH/!Pr8}@acYDSͨkvd=]opM\׋o}J`E ùEQy{Ko I; _ޝrq=충?9L L^LQ|iH)E,ꍚyJsx J-?b$—rZc&ܐ_ ݰ^-=Lb.N>')u5 `&AiRDAS3]h;?~L?lۂpWHS_sR~|gsNX"NӪ=r:xd)e!4`z욜uZ;V˛DѪ<(MN[fڡxOim{&siŝm\juvkJ @q-~Lr'<%PS$Byʅ.us1_MVRA^6dIKI~qώ"M Ŋm),=NT[~྘h}_!GjsvSky[;ey"Pڙ9ENЃ1ZF~qҋohŹ*-:!Ikl5P{S{d}Ec7Otqybm*D={QAJP,"_Z [j𞪝BL|̫E9|O34/&[T(BnHJ_m׋N}.Nžbm֗d-=λ!V% x#:G~`k׷wePM1Ə3ZWƗã:.-yhg$G= wT+~2uHwP쏰:!!ӨSDgpE&- I%6l!dlwm_PR g+sf//FZNzs er* ˻O/B`bL7h fyNX]xgHbP/*YkMŀhK*dO!/d.xHimY=<%9|? 7)+i;AXxu1l.$Z#:MH߭w)*u,H_T-! MRpqu@4uʪω0-CCdR߷p> X~2<.ݔ ¢ 93^{njbw;TD\+ S~-=-Q, uu|IIbqdQ7xgCF_-o볖 jYNuC/W'<[h7,^hIERL4iܵhz#!' '+-\*^%1ѩ<_דɲFRxi-3 "pP0ӷâ$1eN4_`&t|Qݻda™><}/]El6ƴê??!TZHPAorޫ&]B"QpaMJyT+e>UNZdRvđL\UL+Tn}"q!Gcfb[6S6.2PVOK`4^LUes 2rĻ^ݹHQG+^tǼS#[bZZ,+~ݲ[ 坽ұ1!85Tkhmg}5a=NOG_Yuh-)-N8Z(so351ЏB~`Xk߇#dy__xTRq=ݗV~Ԕ2HM aLYGrXc (űq1=`dw.G0&MCI\L]Q=M llL]cEn Ff0հ}v̷syB&l W;r,Ğ$kǢ8u vbl<[@!qd -LJ ;lS/gS+- o\/⤦u6>P(lfDZ 9p-Zt+Me('%K6h =ޔɼV/~,jwiPIN;9W9ΈtSCX@h,W~XlUW F1 iTap:yJ#eJ%]|&1 D`~k*zyhuZ,`xt v.>:н~B ^&ύVwS 5+}~]::*,] 9' Z$DsY;R9s!p{[QuE,ڐFugh=y`LR{: YWhcKVEpaQ c+ IrչcQo6ͣ?|. ipH77>Y\3Yd`xrkD*t"4A섾A4a-D 7`t̝V +,ļp5I][ co GSo蕏5ŦpA"-Kеe ir١q>_IS6C<ݭM')9,/c;  =D y(\V9rƈi-/AQeׁ:SfKV7GW{SbXz[9؟v>:YqIZxZ*}Y=M@% ot=B""p\OY5n?𾦝. гҪkPHMr{WYv@!I6ky@R-ԛzX!Ly?.lec)ENMTn"@)My4\Z0(|88wr"[۔KSWix#rG۫2N<5 ,2&aLByح>CL#> endobj 128 0 obj << /Length1 744 /Length2 1168 /Length3 0 /Length 1696 /Filter /FlateDecode >> stream xڭkTSWPZ!)!B`A";1䜬0D"hBP*Z{4Dk\*4 25s~8caJ($`Y4`X8'1J J $E<<C48'db$!Q\s"`qQJ @$CDF DH0S!PIv89$6?En (2IH> dqa4h``-4J¸92 L(J@1`c|(FJoؐNY1n/mIBA$D$>D I sGa(gmHHV2L*nYPGA\+Ñ VT*HC)R; $-nqsJЁιdb42p,)4 QɻGK!*I 9CtJ!b<߬$ecvuƺ3bCɉ-Ε: }Iɥ7ԺV42үEm}ʖx4 o,vIJӺDXHW'w ؊շ3;tY TBᡂ^=*0.ToFugǀU =O^t+>|! CN~?\uJZj^oª-ƭԺi {u"aHabG5 MN%?HMQi4cJ1[o͖UgԝFU>77^<ݺ#a^ <,|0)S.RxdjH*sՈʯhWr_XRYd\n5<-_/4Rp6/b[NUȘ變cts.-=k"86rk*4]bc~>TWS~4PdxMs̚E.{SgX-5;1̫Ƴl/ A%}*z~z5c(Xq蠣iݏ_[_ojc@,/~(m٣i#!Mi7aoC+]QOl :ݙ|n2ea'٧硪 OǴ[]f^6wyk}2-3^(e*ߝqGmwێ)[gr(Pަ%SZ^q@WKcہ#]'= ȗ+s:dZ +vZƣ{G;|6gSf}vYzmqWa擣K9Q6ق.Y1"[!H=3^1|5*i|]g,Z 7OuF+VZyg~Ӕj2zpyG 4j[kMY=}JyȪxfWaӰNCړ59m~`I+G&'G3#-xL,_~ihO#)2nq:-5{6yˣtG7|jqvu\RpL~w.<|Y0р;؉9K|'$_}wYFΆjLiz͏V޾W];4> endstream endobj 129 0 obj << /Type /FontDescriptor /FontName /VNHVYB+CMMI7 /Flags 4 /FontBBox [0 -250 1171 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 81 /XHeight 431 /CharSet (/w) /FontFile 128 0 R >> endobj 130 0 obj << /Length1 1217 /Length2 6222 /Length3 0 /Length 6969 /Filter /FlateDecode >> stream xڭVuXT{ni:eȡFc;EPCJJDAFPZx~{<]Z:m] .yyEjڼ<^nlffY("g ֈ%*( *ȇ uuB{d9 P @acq=}NN_mBl<gl/IJ.vͶ0P^`B/H[W'_-8 !`NNVοj!NCj`˿] kSB`f< 6.ϜMVicre[sIKʪq=ӿ8M+?Y9ycDw G?wf:K 'XAV؈A A?/b }.';W( JL#aP7Bpֿ/AlN`;v?/B>Dw!wh;G_+ G"zt(G@A ݬ`*P]Bx߬/D~DiQ=B`!q̇HC, u" Az#?x&` XCfsTy| 4dgo_7|>T2αRox] 'Bۢp"k疗ܯ\wӍ"|y@YHyQQ_I~&6=RWcwvHPYOM^#M<¹x#.|,Ȧ_ hB7Rـg:PRxITm |1Wk!3ld¾Hy$е*  RC%5i-8 3?QߔՁܸԏcvJdO9py$jѽ9LUu~b?4EFouM;zfbT9M`2d#5/F<cx.jleL@1z.YDRUx!Rj | FX; :(Dn'" =E'UZ5639*_SuoYOENe,1Z6 '~'">,G@:9W)4,wS9u!ISelT@ܤyG)ѓuaᴔf qawG֧4s=SA"Nfܠ kx~êH0gCr釒pݡ'rj|7P)PêV/⻞ߝpk|gLoJB!=d,WfMKp7!/(gǃDE3un>?: ase7J'*bd=8E 4cquQgje/ϙ+J;T91Htz'khB]qg)$[0m!N|}hϬ Ӈ{bձuԺn-ׇW7[-uPf^"QgwԨPh<3Wr.F< т*EM]ȇ}[zL??<^[|"ƹIYq¾zicҵx?I3BcӢ+JnݍZ?)?ޒ~bzhs|3s=sCFH$< !Nrap/&右4c%cUU07o{*.IF}GYj͡<Fh:0w dd+-++_QwK?J~dNg|fשfx3WÚlx y3PD-D45#(NqR ‚WЊYc0''UtvKW^}Fny;"UD #I5èTԼd"KkmżLX|DO^TP:荳]y藗;NvY<K:{<ŕ]H*q~Z1Yv!j"Nj>72rHMIei 6Cx{YwĞ rB>xC-~c~kS3{j<&tlrѯhf9zX&t~ CJ$T)z\sj0c~E-閟(c>-фqnRY.pĺ_c->e#%sNSti'Ɖ !}e*CCз|g WY#^|@9dIH"]x%dԂ!nv28t.-7 Me=YGhy)'|\.#hRA73d}=gm!`nǙۯƹ=fk rH+!1)o0{v,7Q /qLT]Hx|ih(wrRbˇ'CH-rQyKt $wM [s%Q?Q#g HT+*ɂ6Zs>nI?<2X4@owd{u%JaB;aݦ:w@(yX\k)S3ѵJ,`/͗/ML|_Xm"s#<7m NΗ=KWX iiIhaDt1􄷄wm_'%2ra_?2ѫi2wn\G[Dh~u(i9j$q{;:L_SGze*fP#*/n$H_?^+|#E3+jB,JpDpx!QNPvegT5r!> .༱Ɓ&'v~L]Mȏ)Oz%fcRziJư2 s'g2Nv7 ;GpUnOIeﲄ5jx9'[a̧]Γgd5Uɮ*3Աs _3yo>\GU߬,4 >M>]!fQITɠ|&]E%i|bwT I} gu"L϶Ӧ/&G'5Qĉ\k-$yoW￉ui ,!21yBtD&{>TQDQ)t}]z* 8FO?Kjify݃F[PkQպ jm@;1*lw#z˯cwlaM:Ia6Uo,= `#VQ)Qvѕ\ ,*8Hjs:u밸w.g5Ӌ/*kƾ4 4ͷ" ;Æ)MWm;l7(R|oP =lyj}jL@JY']ҁ9/>; fȡs "ed]i8]L?RډciSC5>?r6[JTg£i_ka/ h03=g1Aq9-Z'^x)o$OmUL'U`aO2UOZs 3VG?(Ir칸\su| 7R AkepڑF6v*RpၐM~՞]=QyP#E` rNŹ3iExmO ƙ2e vm *_&5voML@@hy|`>FaEA-oDU3 ?)kBܠD #bb0ދr}ձ"KmʠE *\\qWѐ+[z6>&WWfQ /D{Ǡ0N~$xCZ0;񫩖`r3fƌ1+h1inH}E\?CXxR WS)cujVWXPnli:m/^hJGaOhpW,?L/rD'RKjq[I-y1azr:1j{9v9VuRb5vrC~9cV~RZN,Bʼn|eZ/ 3+rypbψZ\ |nGhV4.sx8؛U%AjO+8qu/CxmQzwɴΏ,:ᡜNc'3u`TB٭0~-Rcy_˯^6)ǏJ1YmefҚA"xv"/P.$i.-6n|ŋSExc{/~aͺ˖l?w-XlŶnbKRUHڥEK]dq+\RײʼթeUi&)-Ka"foŘ$=`yJ7A%T|w fɫeJ?0Dh [)a /x?P0ئ"Ώ!0Œd2US}dˆ_T/;oK&Xf$^Ib]n}Ux1zĵ^+jMidUOvuNo6Fee#Lyu:yMd[k&?xZլY7sHoz|]eC \=y2g5R|,ӵz*(9A4u9WBota6)8<[}HBg% 0#[gв`fE*@3\ރ/e_xR'KM dZ7$+Y-]3w_ 4fsw1-x!i-A y AQ'Q__EװQR >ň6N7d]CGLZg`} fR' 'e}HQ`tܨ-2XDZ!f\t_1M8e740A jc}G7~22T:v|(>I;9Q}^6?%ᗪ;iB'p5Ȭ$'>fP L'k⹜kʢqpwچQ% *p}npqA=CA hѵ@Bh'o5Af񾫠vae2sc" <=ٟz7h endstream endobj 131 0 obj << /Type /FontDescriptor /FontName /ZAECCM+CMR10 /Flags 4 /FontBBox [-251 -250 1009 969] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/I/N/a/b/bracketleft/bracketright/e/eight/equal/f/five/four/m/n/nine/o/one/parenleft/parenright/plus/r/s/seven/six/t/three/two/u/zero) /FontFile 130 0 R >> endobj 132 0 obj << /Length1 756 /Length2 1214 /Length3 0 /Length 1749 /Filter /FlateDecode >> stream xڭRyXSW"*HR $`i B a %<= aP)-|~*&tYtuM u2Hy`;{;{޹%E@ Y' V$b` uf {@ѬkOړ %H0=b!t$9lxEq`H$t1@XkE @ćQq#À1W1x(` !H^~gj#[a-<& !ĸ* G󄸰XuCGHGp `'H 9Pxq,?ݤaT'vnp<!q!|Xr 0T[  RA"(P[j+;]\biתf}g˿TQ++S Owܤ7t\񌝳hl2xgl{BV|kqÔki gcϻ啇՚(wwmL=ѺPu}f:eScBX #7ݤ&F#l#-Vu +;{R3{̪ں/bfu>{][#lciԥ'هf[G~{[GMrF7g^{cg$mup3J ԅ1)tĤ|n_}$㷖wV_kXq-."Œ?vLe>OZf<^o(b!d+G;RQ+x)Z==PyoRg!)S?ؚl`g)u[>>yo.wҪZP (^Jx~8͒ma8aU5s8K%'0n︻*8M>k&ը,N7֨/G,eٹĺo3M`mۅv>Z=4X؈S3rpkUvVçJ:q.xS*D:Q͗F@U G+ѦϺ3.|q'~?VN=ݾ{:R)w#W'y6}~Z`0ásv0njėӆҤ(Mյ2]>)_H K E/5+~;;3iO[zE. }C%@0c\c0gR}U)#̻P&YGમdPS⥜9ϑM?^[{2) 5qI@WŒe' 5 |i/}Vxr{w ^e2nS@A}4^?ߢpʌ4׀bWuhm˧,cZ qM endstream endobj 133 0 obj << /Type /FontDescriptor /FontName /RHUHOI+CMR5 /Flags 4 /FontBBox [-341 -250 1304 965] /Ascent 694 /CapHeight 680 /Descent -194 /ItalicAngle 0 /StemV 89 /XHeight 431 /CharSet (/one/two) /FontFile 132 0 R >> endobj 134 0 obj << /Length1 803 /Length2 1807 /Length3 0 /Length 2364 /Filter /FlateDecode >> stream xڭRkYTcUpfIrЕUK2:wm~T1[*\0!5U-HCS7m|XjDpU5i=YIчWIJ2< Nk<㨻--D'`3*+QH$*#mHobLpL)<[ >󱶳>+ԋiI觶eߜ))>" ͇[e}ߝ9l{Πű+k|O/FJ0!'Cm#{jM J:cTqne+),|ˬ+FP$VlmZu:^+y9 _#IH\Qpǔw c(Zv,FEW,s4)&v6JQͬՀe&s_\6$q1ؔcFmGe2uOƂשM%C5-*ezs'ׅ۫r|jyw)[*6бTan=#[*+]Um5;T]1 yNRoƩODk!{6XD0un4^p0shX*'@6 (/-4 2y_dΟt#9:?{V[\䟒&>vKeua=zX܎2IX6"f(Cmڼon =ߦ1$r6 XpWvѻKή5]:7(SKИxϿI\òGVG^EQ-tsCM֢ry Ks/)ceypj|=s*Sauve+ Ky<!GLAYFӒz',_vv W4agU U'N)%Ll6Rۥ-~;|2 Dh6Dڴ(&U*L$s Su/?u{A+9L;d{[(2FB4 ]u1n8?Z8lZg|~/cI+FeW9Ӟ{{ؙ)Ɯ!/* pHj[ |wk ߝCu<)诤-H"V}LDZCr~o1}u}Wdv}L>;x\5&=6W $VfUTiҰB?]3XK\ʩl醔dѹY;‰϶ykn>8hkb^nk,ܫG(T!=p]']fȌz)L@pdbbdzSWm& I)ԿH endstream endobj 135 0 obj << /Type /FontDescriptor /FontName /WYSOUE+CMR7 /Flags 4 /FontBBox [-27 -250 1122 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 79 /XHeight 431 /CharSet (/five/nine/one/three/two) /FontFile 134 0 R >> endobj 136 0 obj << /Length1 735 /Length2 1050 /Length3 0 /Length 1564 /Filter /FlateDecode >> stream xڭR{XY6*Jm'e2݄=jK1͜/37teȓ(nLYOQܓAFቤ+k~{ =}Lil,:cȔB D2E:2EPlm)&d@YY$$4LV3L7( p  |0E$@r !B(@6H6Di?(_l1$!n ME6r#rf~ĝf;\w&oZ;C/ApPΦ f"&aP.-DH!™>DٳMX0uߴa<3'AED35FHA D&Sp"f]儲06`ELI@4 (J~H(&!ɎܨGs"_WԮ6Rh9kAU}_W(|h9%qozs-#3Teqsˍ;G qܓ޿nX 5ki kqØ]-凎^61^tl}Eaj6p,Iu*_v8R|Wޚu@r_9+-\wN(ůe[sqgj5ެcKiC@7-cn۶fF-)]ܩvo)9_T8O A6;"8֙TԂ6ǂM~;2kzf$kt[4yH[Z뛸 U?H҇0#g\}êYF{zlNo𓚦PsJFG 9b+5L y! .oBCCxwޚ&92}ڞԨ[~鱗>qi4AzZ ~7<|W+3\df0݄N W7QBCt/m#+ˠI0޾^ҧ>Jָ+*0!MnP~i&?Z೮E_jTu+ e,>Nrw5a|,)?b㥸[:s''Ȍg\F EQ~zJRqI+Z? \ "LOFbKe :}(`S9o8º'+1;t蛡e{B<˜7yZ;7ċK߾`5W{W~zgeK5JwmTŧLB]}9^{#?Wwl/ZUcLNuݶvǂε[;:Sy{rr?2-^:jXC~ͼm,eNSe] uXQr5)fyjag}Y1uʼne:)u\ E. endstream endobj 137 0 obj << /Type /FontDescriptor /FontName /TNKJCO+CMR8 /Flags 4 /FontBBox [-36 -250 1070 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 76 /XHeight 431 /CharSet (/one) /FontFile 136 0 R >> endobj 138 0 obj << /Length1 908 /Length2 1580 /Length3 0 /Length 2193 /Filter /FlateDecode >> stream xڭy<с!2Di7rDfw1fֺ%kL@F9"f$*t]Rm=|߯;L.b Ģk}s(07,`5=F8S4)hsȡUSEAƷ m^W L1!սȔXp4Ec8Ĉ|_9̞NfP`z`7@ 䡐Dx t  @1MgpM@eP+k510H#ܪCp1 9M١_e1"@2DscM>\:KLf2!#L@ ? caDFfȵq83@HXCTY0ECd`?skoNP#^lPO]0%/ NyT٬&Tq"7EGf(G t:h=hwg9GToɭ{b9tC6)b9ѪK~C)-7+oWRȫ% c4saMPNY=G"a 2 Ų1[4|&k i+Mj6)8-_ V`%1<;y,LD5,˜H({ƨƖpu6U~S[tN"˅e)uӇʶo)[czD&F/AB"EL7ށޤu}k<.ނ2hxrhUr '#hJ~T\>ņ`ccWq@\vha'ܽE=]ba|>V@XMk6>מW9RES56zVGY7{@JD4Jy4gc7aE+flt _phBT | 5Ug'g2YCYђN-KqJBg_O$I'&ׅVi'eQy4XcfalaQOQigS窺LBJ (pB~?տg{f'r/,  ЧkZ X7:r*tW;>gjdz/u.e U]x@6coN ꃒ!?& Kܣ3]%ާ-ln)Q=_4Mjmyy9v=2o7> G1,KTes* 1Bbb_pm"KkƃN:d$\ ]㻱$$*,S9Ҷ%C9 dT\W1kY "mm߶ Wx~t?|'Q]1”2 Ï w .yS]W5غ fZ_p ?".>.2d2'Z.J2 K>1T~uñmc:諅y'|>L4&(+Y!ƞ./+,gm |+K?q~ 'bJ(/ endstream endobj 139 0 obj << /Type /FontDescriptor /FontName /VUDZWF+CMSY10 /Flags 4 /FontBBox [-29 -960 1116 775] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 85 /XHeight 431 /CharSet (/arrowright/backslash/braceleft/braceright/minus/multiply/perpendicular/radical) /FontFile 138 0 R >> endobj 140 0 obj << /Length1 751 /Length2 607 /Length3 0 /Length 1125 /Filter /FlateDecode >> stream xSU uLOJu+53Rp T03RUu.JM,sI,IR04Tp,MW04U002222RUp/,L(Qp)2WpM-LNSM,HZRQZZTeh\ǥrg^Z9D8&UZT tБ @'T*qJB7ܭ4'/1d<(0s3s* s JKR|SRЕB曚Y.Y옗khg`l ,vˬHM ,IPHK)N楠;z`GjCb,WRY`P "0*ʬP6300*B+.׼̼t#S3ĢJ.QF Ն y) @(CV!-  I9 9.L89WT(ZZ)ע(L.-*J+`iPLMHMy-?ٺ%ku/byb˛"vL 6^G[g_J*\Eׯ'"5[,`_Fxes4<͘HjY:7(ן)jq iMR2.x?~6[>n]츓$~{Vvmε6gIݳpPY3> endobj 142 0 obj << /Length1 847 /Length2 2260 /Length3 0 /Length 2861 /Filter /FlateDecode >> stream x}yfgr̗}NOG7cePtQh+z_֢-+fr?&ౕpW҉U}}M[՛O?Ixk&Q2O-oPr.H+ I;|$19rgx3=$~_#9oٓ:5Pi{zxĪ{aޙ7&0pV._5V(I\K*y}P͋9#-ek̨2^r_rEcgs92)0ڡӒ0%$`}"b = Q::^D ehoD .l#Jߧ 3 tjt?˙PRϝU1>Gtݥ\ Jp{ʨU?R+Q%op MOMI?ǘ6jz[yQ}Rejg$S㊋dE􌲙"oe/sjyu^}X=ȄIcZG٥̋& fZ[O6?nMFs b 1!m<Ŗ֌|P|S73D-*[9uu̇zϰYMXiu[v0NO+7v gm.l=_V9;A]$qOx/^i.]B4{q2Abqe'=,HpOHjWT\|t\1\gM[%Pxݷ1&U_@@%u}=Vp`0Mf4@:^8 LZKUӖ?zd تcW^ކ7xb?Psn7 scD_MlXeSpx FrKHmN:r=i=.X줱}.uA p_5No/꠽ m\}mnJ1ʦ8mFKڋӷ.)rP뵦+N:YeZ>jt|K=)RS 3\u݈9q,YYRR` DpqϬ t2nu{\[LIt߈ټb$qo-&~K%|ULH$^:̻@T9\ 2[g]*`m]}Zɞ?8mvpz JcojpȩLwKD2S_'4Po c?Ԏ[W&beBAJ~[#/thj&c4ð+@I}_58(a-?nh}KeSzUZk09սWvW̞RGdh81`m9O_ljPgGU&bIv/]%/RlȮWhTp&\eu~VUIŭ7>e5A㌗]|}ٸFG쵺Ri@&DVT#iGNf._94u8:GO*ՀКVU f},Es^^Pnasܗs=-p; endstream endobj 143 0 obj << /Type /FontDescriptor /FontName /WNCMKK+LOGO10 /Flags 4 /FontBBox [0 -11 722 611] /Ascent 0 /CapHeight 0 /Descent 0 /ItalicAngle 0 /StemV 66 /XHeight 0 /CharSet (/A/E/F/M/N/O/P/S/T) /FontFile 142 0 R >> endobj 144 0 obj << /Length1 815 /Length2 2032 /Length3 0 /Length 2615 /Filter /FlateDecode >> stream x}Ry!Yc-@v5v Lb~gB 8w/'0"fDk<qSE`D L$ ~N@ X C%b~mn`g{嬈hO`zLF1@.E$QWj#A;+f;=dF;bsN#vwv?pFT7F̵߮߱JӁ3K?ܜD ;z:O:Lm_gocѠ$qYI Z7֖uJ7㺯wqOBuO@|j a4tݿ?pvEƠr򵆮%'1YUvξ@ҧ;޳<ݎz6X!]7 tQ #ډ.oB֓?R!T.7FSjhP$YcsJQw 笏'܉M; yW5"V[@2٢$]x7y^d1ՋF("L"(oxFX!O .S׾T!YjI uje2%_Teeg^*fm?Z7iF (6>"[\z$$G'ῙOTJ3z2珞wI{Nm ]⹪hDmU=u bɱ,\5SU~=5h ngH;HW'竕"o\`iV%OhMt>ڶɍezVsG7y}h=<]^$n;.5J<4 qM,A󡭶eo^$4Lʮ#$~) {@./sΔ_,֘ r(|Vf\@ }o~ut138 !TA~gF9%8Xer?si:^h==BG.?̮ٛzMk\]bg{xay~8X}̯C=ҊR\bҶvJKBR%-0Y41liU¥ɯݜk{gM|'_%DZU&&ӄb>'Xwm!0@k7qEБ\ѧ m{%tU\\@@~n"zK_`>Ϛ W 6-rz Z7X0%t ]3hvRiL`hnfN>QmbNL8ilo~P~J[ڗHm*'#d˩v?4po:L\%-)iHu5Mj\p$O V> j,#4b+`rׇsk4.}N'Z$^k'7~eQA gz 7eS> endobj 146 0 obj << /Length1 815 /Length2 2034 /Length3 0 /Length 2619 /Filter /FlateDecode >> stream x}RyJc.E@( җ9^wH#+,(ޡ5$P^i>0Uӧ_r`(XvKnW;DZ=R^?fΚϻ++dOx]se033w&gEVy}|=(,gf)[ީӗss7^oO'/j9;'O]j@9'xnyy\o|y~,6T.qryvgΘk ,/ʪ~ٱЩ.ﬣnaDו$Q)ŇϟT_XQre?ZyҶOe%8rץw;Ү7tP%T;v饡pI_P¾mq#YUQcRN#8+7PM$e'dyiߗC ֗T,bȜ+>奔'>{षhu{l^4qQzRmѧ&sbM>fKUQ3c)_+ ƢNjT|D)W yEHGڦȩ-2LbL4EzFI (uƅ̧aXW̞,i-=mJuda"5pUΣT\>sE]X4ess%֩ѲB"sGnW8J>R˖ϋt3. 9Mf9ʚ;}mF%[e&J/<7y\Jhb[t2YܳT"͖풴H<gt(+>/$H0HNϚzi~dfGPesa'>j3QA5̣U7z9'Z^: o9`%w|'ܴif!bKީX0qǕE۟]7߱41dΘ}Po6G6'Y4 eyN~-)je&չ ZH۬tpo33lآ@|zo![&n7>Sd_y8hNd@no oXv {v^W},:,4uefLnx_?-AQƱ̲\NLDEB!0Ul,Ov\va^le6g%{3<?s6QE6+-O,oO*Myryo/A|/{C4}-1Ѻ[R*]<1Mb#)KKï_:7(pfyNqFsⶥ;g+͕{Fկ+Y1͐w rq`XxMZRV9*EȽKZYk)rF~̯|F,ɃSIZk1¶*GL)sWnܩ)h[?lߝRD n6;c5gHFrZط&τxFMFoj՜mG?~tV nG}){ K&I\t$?ɴ~” lsS fݞV&f)79Ki/|Q GF:"}6ٮ6ZIÒq f"+UjiVV pے=ޫ!ڝmX H>x$n$5nl\,ks(UV"&7rh_d:j 􉬃ONn+ypGui7RꑛG1||K7_ #;ˋGnŷtiiQV6u66g/=Wɛ>4;ϻK7+uTpY; endstream endobj 147 0 obj << /Type /FontDescriptor /FontName /ZVJSAR+LOGO9 /Flags 4 /FontBBox [0 -11 738 611] /Ascent 0 /CapHeight 0 /Descent 0 /ItalicAngle 0 /StemV 66 /XHeight 0 /CharSet (/A/E/M/O/P/S/T) /FontFile 146 0 R >> endobj 148 0 obj << /Length1 794 /Length2 1990 /Length3 0 /Length 2559 /Filter /FlateDecode >> stream x}Ry >Y)X C8LAkR ~7@ ~c}`` ;#$; j;U ,,*~N֘%DoP0d2&Y!`re"):E" nCv B* @AP@RT!5@~{k Hd; [b(d|0ݾ"zr(zG/ Pad2H@_a /HXȋٙܶ.Ko*ti*^̈m;ǻ.H1<& A'مeR, Y󌊦Y#ʜbgav*?҇,ouysǜ7bmo >?-ڵ`vy.P}|B,Y]ߘT:&K(+UK-k] s",hfSQҐa'.r4zTm7Վ{aY,e~y* YA,YHWܟ>|>?*=)DhEFմ8D=Z݅ IʆoJq_)bTI#bЏd Z<#Erx3 :嚧M'|4TH o4@PwF'b'"s,&mo T'h|TKGB^r%vvMB=Wz@ڏf\l6axɟEBxt5c˪/+WO/;"Q5-恝d5|4p&~&إ`иJ2Myh?/CA8:E9楀‡s ^e %o{8gUn>iQ~0yZ #k2S6Hhb_6 4:[)[V.WgGN:GF1~Iy/2ctWLd[#wȯ&j|'vR%$V>mXXQk;B,c\ޭÔkpM87W*<&B'*tI}/=cRaIO|ؾ-p!0T;Un硏CS5ZH~,A?7Ι /m;tˏ?F2s 9 o"eCEli#ߜ@Uo> #I<?{d=xaQѯ&h"|m9Y/۶i/@*MFx~]^M1.[٣EZsX.ITlT0stiS`yhS,ڶnXRLrSpb49b'EuԜSn*vJGn>w3' p\Wk9`TfΚ^=o|F5"n}^>2K ڕ ǡC{Ώ7_K$TgR?*/7~T壓1TZN.OKuԊRDk6fZV( muo7- hVL-r`m {q8- c5(B<t ޢjInm%&S +wu$p V.&CM=Mff \?q12hPXE>e%TcVɴH.F]᠛G\%9t6ڌl]1w4dV0^\dz 1o|jG1)Wfao/Y*3}61†E69~]FBV,#b %c)Un;Yx_/5#_N: endstream endobj 149 0 obj << /Type /FontDescriptor /FontName /ALSLCH+LOGOD10 /Flags 4 /FontBBox [0 -11 771 611] /Ascent 0 /CapHeight 0 /Descent 0 /ItalicAngle 0 /StemV 0 /XHeight 0 /CharSet (/A/E/M/O/P/S/T) /FontFile 148 0 R >> endobj 150 0 obj << /Length1 830 /Length2 2089 /Length3 0 /Length 2680 /Filter /FlateDecode >> stream x}Ry4~7`p@f:J߻c^o*Ġ*@YC,HaJeL3<S}tɻ  Ud_ލ?/ٗFg~N>tP`iLZ0H(Go2 ~bPANcV^ ϫ( h'~ |dP)g7(;{c?-m̠@Tjid&uh<`@,^  !u[Z5(H L~!e /ī8e }[2gh0"`Z0= ~g ` Y:6w%A{x;`xQNMMº/~cGSSYCﺄueW<߅<QxmO=˛fw'q&tL&ԎXK}Ŷ7&e+7:V0fkYO3m.~҂$&ɉ[Z^?Mn^Xx- hFr2iG⤞͖dE`J?,^0Y)es8U>09^jvҪ[zL9aTޮcb6^_R2%?1Ro[} ࿗BrH!;moi=qZznG@4T ,I/[V2ZMKRri>;בS)aE}#j] wn@ g^Ӫ?#K8S;ٖܓ CQJU1!G:%셉&13/rkU"h 9a/_󬛘L7y`Va/˹gto~6q#fߧp i$|"z,jed=?:+w8J'DF`kxb"Osp}H瞿"[ԟ0(3Sɍ.m=>3*twVкcdz&RU,Kg3;+Mw)girea0|Ʌe5qA8kq,1|rf3'H͙_ KQ5M]:m^Qpk¶R V N-s<\Bp{\MA` !촍ZFΕt< p[)ʿ=Nʹ*e ܗg稵v*cvVQqf߰]!Aq̃y(4k|gu g:,!͏ "_& TVlרY|l ȩ7Dm0G>%sӊԆ+&6'Ddk׾Mأ ZEik*35vn{Zo ޏﶫ:x˟%ܦNtD^kD䈏(.{`s9_6;5ݽn'{g,;ܗ,S!c@[<_5ŒQ.&Zr.)* UbOp)sܜ 55ha{ɹ X˗B;%KKWtCĂvI(vNN檛0wd-Y{<Eqe#Z}CmLen1}iVq+5Q_򔕕QhMl :lszޓژ@ p7SRM6qQw|?U].f wHR[bK 6b6̛["8-(Hdq@ʅ&ww}ϾʱH:^ ę /*L NA!erڜ^22Gf^4~fUu>>-}}~r؉BBɾ%Yh BMZ2U܆}zXį|F1ThowοULAѦțCIH=օn csFX' :I/,+>49u A c}TO;ܻA=0 HzS\#o_oe[Qj<79U1Ǹw=޲!Zf6@=.!eB]tܐْ\'>>oDt7$ endstream endobj 151 0 obj << /Type /FontDescriptor /FontName /STESQB+LOGOSL10 /Flags 4 /FontBBox [80 -11 867 611] /Ascent 0 /CapHeight 0 /Descent 0 /ItalicAngle -12 /StemV 66 /XHeight 0 /CharSet (/A/E/F/M/N/O/T) /FontFile 150 0 R >> endobj 152 0 obj << /Length1 727 /Length2 11549 /Length3 0 /Length 12128 /Filter /FlateDecode >> stream xmvcpmlcضmvlضtlvul'wt=9_[֟1k9|j=RnN@VFV&>6 / Rhf ahj@'+ bmi1'д31vh:9zXY<<(67LÂ8&50'\K1lH'tXãkQi7 ]&X'[!wy{4Ԩk֩T7ż,91Ҹ܈p˯K},@Dލpsֽ۳'ls"73GZPE7mu~:(fVbӇϵ58~gî$dQ>j ''u8O"9I<ާc=U>234x%x>+q,$#X R\oSJzo+Y's[ktٞMNL]'IF +R8b6.s`C]$7:|ePo9V3|Z5뻪̍E!F(qj&~9W 6~ rBЍCbOy,)ԕcHAFneT S]jN7L'iµW(Z] >D! d Ssz ^͖ʨ g^SWJ]<4. g>N5gmkD$ɯ&L B!8djTBU-*IlKdʗ$ EA!@!#a/B5 PR NKsB2<֤nSd, } I)2+dH\ydz#N#ޯ\6/^L#U ՕjGfR"VK_#_? 4d?fLʉ{&1reTpƧ/>SN$W*#(R9?b@(J{m?#!t6 sGexʀ0&t*RK ,4j+^^~ ,E9Mfw p"<# lV j`&]"_zwҏG4? lxD?iI}]td/^Q=‰ C >'ޖ^jFQj3̈́ġ.H|&+Uaqwc6}j+hgp̮dG1;ދRi%YҪ\,z߂seʼnXSͤ:HM"ysE9݃m2D_@޷M'=58^q\n Y? >gCof3 ۗRGkj3D7}Ms3nQAN1҇D@W̠vĥ$*ٹݘH,Ԩ>Xa*Uu6/wvJ&j_%Ǎ; ~jPg'.I@ڜԯHyn>ԓ>%`b2Z~*PdDNv'27+NޅG`ʹEJV'uwN ֋, !Qƺj.1[#Sښ`lN9ZT/#> j$ &mN0pdI_s-s `\EHD4cP 8: ##2/Qx,%\*m-"Wكf1'A8/t*ѧy[Zm֗~Ql4T6vE!i_oQOhg!GUcrO)K=ODwQzuײ&ZA)|]'7QwIIXactjż:M44rdu %] >5L?| 2*U+l fe3Uv^7C/b#D<һC G [jUu)3A 7-9ZI>[p{.R-qOs ٌLo#E- ( Om gl΢b>U4ҿo-l`GlJT-[T,^~jEɢoh=dr{Ac\"Pr0PQ`efA4UY%@NAi&RH2"?Dž]]G^.v?]|x;%zޕ/:'fvy{eψlc*$%Ư">,q TToƺ;vȆSXS #={[OEΡwΙ\ɢQ8ѕ(@"IV2X $#2xGglv+teu>f uT1?#PVPL DtCR;\!_k \$`P/O=&A q} 5TXi w;T}$&/i=O8պtƮ@ƆhV]2+;_I+(79 _3 d'S;t6&Er:lؚ/:>[^~yts3.l[|퇀ia.h72zlG}UI{F0p;B = ʧKq\H:Ep=PHv~gbO|qG$g:vC&&^EO ׃6X{cvQlmE9['DO@`l{8w)ʝ~Zn9WN((g/kق0Z^t߂p0.[0z{8ZéR(?XM,2:E&iE^g{Wt&B^D(w ʆUeŶ:.GgO.C3dB3)0VodeLNU;&# @EѨ ?unVO>M1@{OdlD7Q3\iO>ԬEIpLȚWx󓳒7|n.WO#' cDM }SQI/y :=0 ]c?rQQ?~2OQ.HJWwrvz+EG Eku넫6gZl^쏷%QF'~mNk~ t{nW8)|:FߖC=9v:g X&@G~eW)?!f]dVbK۴;%PQ@9nECN0DMka3ׇmkF*KgByrHq5F}kD\i'>b&,"4oמ|(/${tS_1X{2Dɇ~.bApobbӉ׶Ch  f.YE1^SdYHx{^q7XP;k*Y>مTE&_w~ҜC]1xmd/v-9yr­7۠-l˛N‰׈ItucG'ʼnA<z}8}zeX )ý&~;mTʑJ= ͐z&_hxF֫E=Sp#Hl_O6C ;e'"f1mL@<랂]V~Q)“jk"ؑ /exu XLz)͗_Gv٥v)w{v m-(}>(9T*$WQ (/\pQv[(<P~,3xOّO zE%%ZvjC=+M%L?G!x L f4x侺8(6#gGk?1i8s 7wLYh?>dz'f6GW:L꺓5'z0ţc4%˻`#qjX@ϚϗwkSe[4v+Ffj1>'9x]K9ڸWc "( CVn>o,yHq>LJt4 FѲ} 730P"k+5r~hIր2JSr`Ll )|glA}6˲ygf@2bK0s= q9$?? "qje˽.!]H9#SƄTQe R-QrP*Ü\‰(~KW$|w>mi$&>e̦b(8Rʚ8NV( ikɒ[_ҹPW9d,=<ti*j{mYڒF(6C}Zo 8~񄽥Ŗ,5Ul3eI>%lL 2SN;miH9;ܤw?iH^nzy+_\t>o[*QhC7d»RջI TG?8pwAl# \4JKGdWZD%, HU1aMxIr!O~WVD +üUm?db j؋4U8ahG߈܅G"}x>38sgJh:t/۞g7.Q\GCe pF}LJ] w% Q%R.k~)ޏæhExIK>h[< }sdƦ+!0Jln7t9ِJ ]RDl"a "m4E_`4`Įw^աIӠ3H$s7[}"Ճ'<D-ݺcor &(M[k}Y%(z pX QX$HNMP[PtC(7[juJdks_7/l+g`(Txp.+^=㗡#Ԁbܹ'sT6(M&ZCI>] QF}E-f½l3IϤtZy;dS(D Ibi3+wB֘]/M'p?L2B!5`7bgc_7%SsL'T~8 (AuxّR7¶k y.`<qh um%>铇)_^f̨tC'2QYs;Owy<^qif!w˺׺TV |eaXN6Jv-u%Ԟ=se }pKfnOާD=jS~XGAQ`c|~iAzCYAӞ'3b0>+{#~ \1UBT1tP4GΌtk_hBD@)+RkTsؾ'XHaӰZlܟwyDAJkFzZ+P{gr4ȩ՚'!,(g]νU_^14x?ʀ(5w'Dd>[xqwVp۔;ÏYSu݊jý uLk'WbI5+|eAx%_Om%\6;g![|j=v AQ$d&0r@*?WgfR6[R'lAqr.xЉ`HkǸ 'q4AٿVn;"KXBd(%/F7Zb 3Ƣ/kǥq6p0/+x)Yw*N6:ѕQm3*yPhI&{m9Pe*E2;Ϩ׷b6TBmIciUJPQ{Idh/ Gz H[SS_ ?~`[9qj`&hQ~n 6x&Wn1Mo3cîlAŅgœ`%ADQ^Ou2ZQ/⍾Ps% 't|ϴx4_[QDoz|,ONXR20J#\X S~z[35@0)nl;A9,r: KYhV^dۺ})b٨u1m}߹]L]tݒ,w( %Ytdl6Ybaz˺v<Ѡr/wנhdY}勠'Nf,SFS?u[fvqPA6ꛥ+`g7%QwE R%iPy'l )>6kbmbQC@g!ׁL禮q>g;4 >eB ۥA_vY@ns?Y{/n>[?^v{TKYReޞC[_K„`rl?,'UӧaD`+jUQ 9ڠ&pMJױJpl-AUO0Yy)VC-Rd{H۸F (kӝ[ @Ee[ap9O5Nm;% LtramϏjB`MƨxCI;6J6}RIPú345R8>ˢ^Y7}ء5,cm-A5_aav#3 v=X;XMy78nMhn`E~„{_4ʦ`'=VaOf10BHV{$&)<=i"+^,qصLBȧF=w^l'@o1MN'a骔m_\Dd2E#|JdߺXW+Y{12=B_+@1 sѲ&`W8.es7(EfFTo?^~9݂K|-AȆC;Fhy@"OFIu$b0VlF<vh%s_i{>32[٭{-ygl)VD?0]B쫑%U[/H ^u<"vF^sA)r^}^uϗ5V@O/Ae4ǡ1 v"O4$>Pէ[o>ʬ!q{a8s4BՅpʏw A#A W xKC_nZ6 U`C: T E< S-ˏKc[7!>(s@ RߐʎTm&%L#"ʼ()[1dbږUh]sx@R"o{B㰃mf]y7>ۖoOyb:'z-QLE^6.~0E{]j,rb "?~Pcco7l(5d.#s@Egi7$.-^'HgkuAM9Jꈈ3c]󱚫ĵ4~0h _%xTqOnRW jPY;DžЖ- jAh8iV/@ (Lgz 5 Tj]_ eߌ:PE`먗q`K /fCFtklqtP\zrQVy%A8`g1E N6>Ml.7CB;{ALHūfSXݢօ+ڑP"ASa`ņ[3Xl)ar(p74mAEGmئt/Hm]*m6jfm 4@VOi`nb YudMCj @^ tw{8XuK#'D~qwiΗ7 'Lk8Ѹ{6FU p%MJ2RUH;l^q(*pha3w3|6Nɣ^z!~꽋<>4}S"m:wp\}ؽ;9q2z%.ʍjSzqz^s$#WFHSYϟJ"a[*qy.0%Ƀ8iNc%19ySʴe9@w-Wʦ) 1mҍbnkDyvbvEpo0(KfQve8'o&T?2xtt7!fyP!ZGDOc\F2$i*řDf1݇[z˝R.O+bИpc%ٲ0#Żl5gd5W #6,IФ5h*2GP"5uum+tt0ոHCj} iZнؒ\u89s;$Dx^wxը`e<;X%?R?+ = -yѻQW!eeُ#,s&gۂVrFnL~y梧{Q]3@ tG⷇L)A'nb aAO|Bg9#wu`.Sy9 ވPd/Plnqs,Il%t؟RXN\|ƹ]\X ٓ,3Uqb-;`&p72DX׳c&4_'/]eUr;GT35bFդ ;ڽ'Oy/MM }m)6Wc9x*#r6Sca59*lLX4'jchlr_}u eMoWWLK( K~Ql&끍_Λ&x?Rd+l=\JCˍU4/8P)?,g7O!]'?6u~ե0_0gXqY(L.FS-u8$ TaxX5%s? endstream endobj 153 0 obj << /Type /FontDescriptor /FontName /HJQQTQ+SFBX0900 /Flags 4 /FontBBox [-237 -328 1789 944] /Ascent 690 /CapHeight 690 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/R/eacute/m/s/u) /FontFile 152 0 R >> endobj 154 0 obj << /Length1 727 /Length2 20968 /Length3 0 /Length 21516 /Filter /FlateDecode >> stream xlc.]-\Oٶmmlsm۶m۶ݷ?"be̘+FH:+{؛021pĄ t0Ž&v"&\5c= C p03wPQ[ P60pY۹Zx\]]\\]dbp67ZX4$r*q[Gk@Ʉ`j`dgkl/LNt`j0SG;2@T^Y``k g?&Fʎ?H#? ##`hbfa C/$mMlQ (`lb B kglh 6;zH:Ç? 2Ge$fnb`Po_3P'W,H?eo@F GojP[S75pvph1HuW^BBv^LLZfF6#;3;khboڲweJsHhl98YK\CBlj mB,]nvBA~ߟ/7(r5.}G>ȱ+Rf0+EV}" a"fUg&([W@=9=TÆ?M]S`5v* Qta8z M薑bv@/ET2[KPdUdkV9~sND<(z]nVxlvڇS&B^qeHQ/v䫜XpysaMLl?Kr1z'\ Z)1r2F'Len_o64⇖E~hknC/Wd=z}G)7ooz¥2jW^ ]>1Di6baN ľ/~@|D̻9,^ʤ}Shd\HX'4R"q_-\&>m̍Mt; \)T'71YxZKUg;ق Đe4G-nݹF+7Sy{:\`\'PFNm{27bݻgUl?ľpU/2}fn]zadHCE(̏H"m6=ڹ04O] ͉AI!}[R!xZm1KA尾 `jZyûb'򚢠vMa!{ub?a`Y'ut#v]#SMM r3M Nv9%[䘞'->G؅c ov3".gsqVBokʗHqkѭѺ+ >6q{bqLqܻ\}! ULgN6=" {"nFA:.ìg;χEAeᾗ [) x5!Z#9e 4/>܌.$ +,.LyM9h^kvWA_agX %=1i@~%KLC5r9jBY1!/}gKS7;l.#Ɛ ,bE$n~*nӝ^=cΕ|*(\tMh-0e uΰOw"8ESWE٩i=^ow7wMu`ff<$+cN"#CG{L2ț 87ˡl\on{Ny4iǎ9J,o¥r\9Nrt[t"}c|&O){9[tu00Jxu& ] D*?Rp?+= |~ ;3#zhNLA1M ž5YzNOr~K"F#[K%/U]#kNonOUtB.gAup{=w42F](aOc|t; 쎴jhWi <:|yo*!{g,wiq10(Q&%>3 k "F2ڞ=۷ _7eS#o$ڽ biLyq|~7'2yM=V~Mibxwa)h9tdE3v$JJR=\-KXfH\&߅:n5iF``w]AS >V4{tIWF(.h>n-q/ryy4Pi1/3'ժVR2US4&:FL#[)ڀ7XT1ڮC*t"rVΤ«CъhS~4 FU>@OY K\ᔄ7"f]ƑM}M z-ᲂަvѮ :s7IaTdУ@NcW*H~y-:`qC|nN׾3.b^1z.y:J.0bߤ٨8n%ӛu&z ŷ#U6;BRvNRe :MrS&'m*gL7͊)KKlw V;N?\vnh-MYd3,UӌGF{$SJ&TFs!nb.$tf<.Y|gcv|փF(Ia^H8f޳G JZj"ar?n;E7'b&y!sWr/~5zFH~;I:rp"#.}[1 @Z#yc1KE>r5E4 x&^6YW׽V.p1V3:9]ߐ{ i_/F4ys͘{&:xDĚ9M:QD1t2-f~#`81/Un Y.v&e3"H]+5 |!f8;0x y4S_d aa E#S=;jF&Pa_e TZYS$3 ?yE,F*Kk#y{(.\\&%{Eɦ3tliN Єj7?FȤMWJbS7Z^1[E!wY<|F׋lwHȖ!FlW!qh5bZ{bbޭ5'}02.ǔ='2$/RbP b(DiNUm|x.V!G/Ȇ6O-EAC#8=_:P'J2 )<|" ^Q{wIq sk$.2l4Xًviڀ;tVd~ҁ+/[T9 D샿HLJqf<yiq E(砼nbո3 &zetNUXXO3tXmwmCLvd/ϯyOa.5M:g%A042m- 캭07RQuZ椺,&1v(٨ZؿS.nwh$ ʮ95m6c*ㅙU$2"o^17Pg~Е~N|]cfe  u=A?JLYiEl mUݑJ)vTu9yf+Ԙ.sS;1?˟,Գ#8y߿8 gXDL* 晡זo/?%2Eϐ(m\]cz\A^"=zn9#֤Q@#S|=`0={ҶܒRLXv\6f@gb}M0\|O ww5N'qgq@ Drſ /^,7s/͋]Hh|.D~1' TXwp 5^Ыܡl_~12.G&tNItLOCeF]=Rr~~)~i:M\;YxrdղխE;|+"cY[<j$6y42ɉًbDS!Z2 7'xRzLǧ69 vuHK9bqήCѲ]핑d(mgw]>>$*/LTo>&-NAlTP09"W5n ڗSq5 x F"1#}ĥ/N{nd+h.WF:}]$ =`Q{B7hv򺵄%p(V b Yw vRߎP4=ߠ)<&N*x͐3J^=B,0RC=FT#{:2͋d*ڿw6Ё%XϏմ kELHҶ$VJ 5//0HgvZzfv";~ٰ~d~LBΒ(ܨ^;/- JKV{E>QZVk砵d~Hkt4Su$0׍Z12[Fu}>^9 qT8hΗY=>v&sw|fx@j,@aVK#s=FoZ4I# 1{S蕷NGJI G#HnaScޫ~GR4_=:o^0w"1.ċ_~IlEye~KAݴ2EhXRc9?ݡf H]z= }kWEo33}?~ #AyLJYjtYqOۋ!Bj `s^|,e>(8Ț*?U;ɭ@"j%_3|dp ~=(GvR:eϊA7H D $H kx]0 pqNϜhg0NP܍ZB#*ȳ߂KA}j*i٧_mOjH1>+ϵdp[#h2Gلm;oO P[\[( *s@m[6v:?nծKj Šuq?`i4MYD!9[|{yL[vKb@X.X<`v|I#*|iIҬϣ5cuN !NS`'TY(w*aN{"=ÜBPFnvbv/Spi:nOͮ|U0nH5|= *r9j M}WY]=:􏊴l[+ = lRF@B KZ5Ղ73\rvȚS:ԸPgPҒwge.}SL}Z6/6)1-2bxǴ`ŷ_` vβA-Ph ׮.B 4AwRl cgTǐtG`X~d!L sP_11'H ufEƻ!eh ^>8jnb}paFT$XHhkHAŧ:*JLW଄Y]Pdwm\F"?. ݨ'֋dmJs; JYb8vC8 ?6+"n pxŻUxB|Q\DM8h}v2p%GHmr AHb|DXqhd2)G!j8yu[)%IaqUe̓Zv@+;lJ%];yPh]/0^Kr?4 CVנ+Z4*,6e>*<$$6K˵CCf_uP.XU灵WtڮK͆ x3sh{d»R?RgHDgoDuODxMz)x?.W% DuȺ HωH:BYS ^oBeKbg˓;! *Uz;7$~چ2Uj0BtX-&xA9k| 9+)\R׺h1~@`w& &8鋜x}4 T9*n2x:JLO7e.=# 3Eq"޾R\dgƫm G_[/Sbys"OvEFd$sjRߡH.qȕX˝#ឆdBu,-9@&vG@X%K-j4c Y3܂4۶!},0|CN](M,H;.'7M;9O 2`>!1+!+idH!Xf#D_u0Wc"ZJK3Qj)LԕLU8  ͱ~tI^}X] '⶜oi8@InGTS#ϗ,7]4`|wKߕODEKFeyj+ c0k(ZY_xx-M#3?CZ(cfHQn权XNk%iVEv M)-7`nxғUln[]|>5du@KOhCGi忕+ ʱz\9̞C{n6@">.;\pgQ+r":l.}eY:ifptuDݰ9~`Nw{t٤Ij)xoYғ& %-& R-tD'PFVLsstm/.vrZxIŅJngt_=_L/hRB4daz5•eFǸuTXWOe\ _NP l#wowD^ :AXˢe|e*!/>( =K m{-&\^fb6SXWɼg\ܽGZޞLAE+ #N⧹< ѱOHn_`ضGDN| ń%}DN 00U⸲Qa)Q-}V^aȝT%!O2ƌ܃F7̈zF=l/21SZokӁ<?6oi\WG[؊@|HpK QCo}hwL4cxf4K[zѼxhܤ(D_.c<^* /5 i0Q'N_wEjq JJ*Ϫ3WGVi]mZ5  ul({~Ѷ37Jv)N`wA˨ƥ(;ljűVgc46e|`F .@E'$1xdρF7}kӑ1П4KteoJi'x\#+ i\[q!cьse6U6!'HR!J|Ǒ i9A'o!~%Jڷ߭Ty{urQ A 4„qwu~āY?7[D34lCX"'* [YOBor ͟kQ1e B;%_( Dඛ%Ux!}/!ڈg2v%HwG\ͫzӿ,YxVM7Ies$03>P&bEubPLJKٳOVXt FM~-DVmG/J|f̲${ bwb$k?WY+wk,b +F/'Ka{'Ri`:G6RJB$<˻aKw:KŊdM rO DR\\ƃ{IvB@vG>OJұ#ʕDXWկ0Y e\;o8Az7]XC^NiSpiN))#) ^YG9;"iP݄|2SrS;@DZIQ4cIVŠP^Zo4s} \.FpZ:.d!lJW՛Bc Vv]Y7zEg]>KP׃zI ug\/ Z F=x'|9>bR";C-ԐO$3rzWW_?Zvsn?BTKkAZ'Þz7UL3M8PtM+_!XנQ=dalv U۱s}Hfj8Ӎl w_/*Ā:@4BQc h%Qj1}ɸIdAM%5Fbzl%4l7|uW fR:LŬJh^O>tv津Њ6mIWpR쑄կg~l{#+}?ľ.`9ߊA6+#d".8BwJl?x7 kF2z_)F7,ٔ5LlD7 XBiٿԷ浩a|ujQKq\k%bxr Rt_{`z٠vrT9(-$؀?b̵{kleDŅ7IejUڼ ؅-[HorN"O(O)>S LC/ (<Ġrl|ymqֱL/4h㌌| nDO/VW|,C[Xtփ4C>cmf=A: B-n2/hȱGᔊSM- J+!f"mg|h-}/.@V''-ǙHˊ 6d1:* ہU&-xs̍oCJW=Rr KR~Ջ 0gٞ5ꪡvsD[FUթ/J1\`æׁ[EB1׳(ē"к50Yjl|0EDmkU%IƭHGpR\M߄0qEqWLx'e`#ӈ'0Z E΋=A#uϏuu(N[T t&-\s"5Q*.H2NH鳽ս#Ize:[kլr!rm?F*»:N02ezvKL1VL0Գ<ՇۖWZ ԋ9]K ׸*~005 NR0<<L&a %މڸ6Il]iMJ:@Iq+jLNqZi%YK(=>lڽ}Xd bVF(.p@L5Dr ֻ\P&:m55pKaIQlT϶bS.|W+@eoٴ_OMFʇ]hUImX9?Zg =lǂ%J瘹>$`+YOvA>]_GQՀˀh($Qxf52I+3AčYPRGv (A{{y2,BcVskM 8  kNJK3 V6SA麒&`+Pr^bl^N坫7-'Lv s,k.F)2yP>BY7V ;ċ|.𞌈4/MmsC=r疞{CYQ>&rެve{}8\/_V]: Vm]T`@0yŽt5{c:)TZӗUﶊ=28k z #+R[W ^i,&w_T468@nJ3^B  NSR(> ГOp%` !@c)`e5̍_Usn׵ƕbYB#%.KRCo[iڿhM wqt[n{}I>ǰD;7MmuH=EElFyjWp׌BQSs"ͣ+TQIE /iӽ'Lmo7 w1.mq$k޻. MʯbYuT(-m8zl4z+b[6N-5'fN4KW&(%TT\"yber2T1 -AܘdldK5H'S/"5[P;DeSe'tcF0U`!̘b:mUm:0bɨ 1\CQ3rG-Nl6[Li ^yp3{t$*cOat'q.)Y~ @N}Õlq_;Axy _`N} Oѓ}i|JUD.Lw|QXB+o!_ڷ)!/nG_V!sKxgp5?'- oU W"K{??)V00k M(UJE1P GqyzVu|uʞT$LY䐈O-^ _3?A4CݛvKrԎ$i֜mVIomdzdEFY"e Dm*RH?%NO)?tsO6{7M&O#J=MC+gX.J2UхƉ.k%E\zF$M}1NNv?L-8u.M.*څ\ϖsaͺNN,*1AjqQ9oh^';&Wnuiqz S r-~ Q8XMߧ+$}Pz 7bĴPiCRSO8 ^ FGaM$YwfJ׬<ڙԉKxS?t}&+ZֶOm5>yog&)AGrO|,ab˾ 3I}8i eM2w >UN~(kA?0?(u{5o:م&Dp >&iw(۱Y*Њ5Pqh6RЦ-Xׄt| 7@E6Ӌ2f _etIzlꀋkog<.i ?!B = E\M}|-3خ~: *c_tp*4wТYVTG?Q̫+2tt#8m9tЗk _HLdw DYnP8bI wÔt< O$<8Hˬ;vlɼ7~XfPx=]c[/FO ؖ6׷"a=;ވ cU҉FZdiIuʬʺ$Rz`:[q%]/025xco_~+"K^xz$`~6|:'˒~>̛{`[IuK3u )## x6@.'n-S2mRnZ1MRʋ=%aݙygQJ|Q9]#PS:\ >;iߚnl+[\.OR!27}ʚەx O[#N#,00M5eV`~ѽl =SN;XlIR/]3-*EtZ3-5(VޟO_:l+ p?'4i؊}(`HɁJJe)!UM\9a+ PEek5:_E7o\np;uR™wh}Ƚft_:Yv%Io= Zq4ӎ* ie״0*}P֛i$-;l:*A`CئSGq4>mcajKU|>e--ZQN#߶9PTN=xRZhr625ej wǿ4հӉ$"kH`3s̾ܪȕp"ד>(݉A%m pq^`˨8;Ëf+>p+ :=[{`q lx=Q́0X_)t2p~,=-C zj>q*@3ye+ePrc_l^ Ns T}/ gQV ӳ 4%)NYHl%nhk@E&5o/j6MgfqhtZnk0t#jJG ^vuYXT]離z$AQމT?M 4B'tÿOmL\"HXJ;W 2^ݯhٞ:&sygSڗ9Q`(CAv+ @F[W\Kꭵ&RDYܽ`QxW!4Q{ӗ Qj٦! _8bz=-SŷI!<@n)33@5TKd3O򎋷-Δ0`τWǦW(Iqhk*3$*fI"3Y-JC9)~zR!(?I>LDKSX@Qt,c+x!Hjny{AN'9"#SYq)i}< a"m9J> V0EY[]g劗"&&2#vݥ)-cgk 5gke2us\0]*%&,h¿3V˲>+ ǚ%g.H?98L,M6}cL 2DL>  @k8}@PW&7` $PVhk%YSxl+Uj.{@,>c{ }mf#Nt,ilV7<=&Y An2~Ƕ""Ug?8L4$Mx.2(1*$(lA //ztz zjƪ@HIb\e4A>-# -\[+uha\K@^]ky^biSi/8gH%Y1?ܰMfBWsjODNzkEc ʮXNVg&q?t35x[ =!>tI1T ܜ]vWwLRؑ Qy&Ws H0; }lN{ cJ`ܰ]]3{kA&_Q$}WUH"Fom>癈!Cv|M%`S v,@:Z@EvI"o^U?.!ԌU` OW@zqȗ_˝~p ģKJ56w+8u eMT0bpg_G0.,ǣ!"9{, :'yFJ=}R}si nbS2g\"Y9o0gǿLb) BX>"gKUXkn4+i%:N&އR&A g||球&jA߷xd5t`VPo"с~s7~MoćCfY4J+F:+N#T֫܃zVdAi1 endstream endobj 155 0 obj << /Type /FontDescriptor /FontName /SRSTGQ+SFBX1000 /Flags 4 /FontBBox [-229 -316 1737 939] /Ascent 690 /CapHeight 690 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/A/B/C/D/G/H/L/P/R/a/b/c/d/e/eacute/egrave/f/fi/fl/g/h/hyphen/i/icircumflex/k/l/m/n/o/p/parenleft/parenright/period/q/quoteright/r/s/t/u/v/y) /FontFile 154 0 R >> endobj 156 0 obj << /Length1 727 /Length2 16564 /Length3 0 /Length 17163 /Filter /FlateDecode >> stream xlsp_-Xol۶mձm۶:۶fܺU_=l]{uv9#*!`b`#'uX9؋y@3* GupttPR;а56rh8:YZ܄ܜ]\)R.@- - TPHNƶ%W[+S)H 0wp:؛Y3ÿ ػ\!f`WPTP2rRۻ8xk::,[Y&u 02u-?a3W!??R̀]mm*Q;GW@ dq5{̀fEYzB=-Q?!+g +?#տϿV4gcUTUU;-no`feoPuGQc'V2w }yc'+.ÿ_-qgaaг2s9,]SW''˿eg^' h 7:5OhTĢ-A>x%ԶE^++5ʞdyS,igs i=XBR($kـմTI*^(&+簂+=LqJ1/^NbAwowJM=1'ԔKrVKb b5@IMK@,Ⱦ>a@)qj:tY-<&N h\ g˛}e9}B#% u.jc1O`כC$aGGAyO#E#R4m9v||i;A^F07k' 1mx؄.k\9?{5"՟Z/3[bS` '%?GWv~y_cCI;2<1l<0 һE+ |Y-z }X'/ԷUpyYX2,QrVH`NÈܕAqK [GLQ(]j7V!C24Ǐ'T1\хX$74#Y."әr!R`ZbھN{q壀uZ;\eUP %6Jd"3Xz1.p.'?&/[i~w:J{^i0,$r(ve$iLugzSc?4E3=PԐ CgWkA𢡖lL1&ajn0lT(?]':;)k\5{k1dXk7ҽTZطZEL-YݨOD<UA^{Ի>;D&n@5?2$U;nD#)7DsAuwۓں ["e 2W3Vkٖ/< qI2v@hޏ4]Afp ki$THj9}hmg{Yȼv ]?#̷-p)oS6/EL)dCIdFc;A#xx釓=0lnˋ-ʍ̥~D6uă\jkvH"a߁D0/aײH0ˤX;E>pxn5 R۟ f}Kf25E_>E+5{ǻKp8?YQRLreF[aDG1ͪqu/+St!Ak'ŧl a-?a;դڹyBr@l)cpyug|_u[ WvޞC H`0hg◱>{ c<պ)'C 4|) P&zV6$|T-0&@@HWUBo`ƊJڔdFULؑp4мsC'yHObS"v+EVnsrܟŜÐK`p;On4o9v[ËPѦXC& ~ }!cAmGej{TdTJ^tU\Y|'ܨg0Bx/wFyL4=;ҸNJc^b.gbˉ_ !,#u}Th\w) mG'N$Uy̎ #IB'mXvb2c_hDCY\;Q\P@%#J낁"?q)R4)!ڵޥ62HeŝYr^MXZ4y"kwmoﳑ8q:VlF g^ cM^VJmYvҗegs- VQ#(:A[pq1S܆lm]<pQ@Cp" 7(m^ d!"1:]rUWXOJ9PE+e 7Լ搨4@=&}WPC:d~o_i|x~̦c{N}*3Iqcxjf ؍:ʬYu20[+d},By`F۩;kSauesVr~Ul/Dj(|䖬ohZ%tVi=IZ`g>'4plIiobdIjQiFH^#"Bj:X(yϢiepC_b')ꪶcyQHK25|}M1L }҃mi\ǂZ %5rL"zP. 6c)(ع\BOîUWo8(c }}XDfxh('h:V#9sfn}Mdlht X$7~ė65 7킥ŭHZ9)@Gm*.N>.Ds R/Y32 lۥb9-Xbuttn_"A, hG1Ni]cz!јփ>[$QH2K xxN/24% cհwQ)v\@"!x6 6 F~O‚6v sf +(s%G?IvOtFʜKT0z<g_GءxXb7\z8(od]dB osm@֨Jإ{عA,E6NܗHT3rzmwBd]I&(D')0?6?E^"ɹyS*KNQRI~ ̅$Ȗ7+`r`rdׅ$ͭ9skU|re`; + Kba(kȆcz^А2HT,pP4z.03yF3|ɽ8hTLb/g@vju6wM^^ Ydr`]*݀jXƪQr`WUVydXP0gy΍гdX%MURYM(yQd榒Մ*ZmgQZp8$ZF{=vtXJ(=/z},E#Fŕ h紺x,ewnU&LZ܎anVZ<2C^,%c|BdXa~3շg2V1$O|%D;U`FoleγuL*xwpn*Ƒfخ ?e} -T *4T3[S! x _B yf>/vk{9wҩqHMmg4 1DՕ=!/P,{MPHhJl*GޓhTX`5ms-XO~AnD}~c=3Mdlykpӄ4w XbW= ;|GZu] 'i8kBBu'#1g(+r߄yvn7i 7Ehx3dY/K2H7\kb571վkRV OɟPc:nq.%h -l;WoUk5)BGFi^u f"kY{QR,LzEo|9s ]>9 ed 13Z XS৑p+RȲ5JIv*^Fmwn&'ɰ5 p]`q7AzfȜ1|P- 8ll%8H]*Z=1Lm必atؚX]qRt#B*!׺ъAhP rNұ#b  7H3}z gM`,?}Z2Z^_*'H)sj]ג8լb&C^בrݝQ>f6mP):䦗:$mE+m iUl&<Ѡ\Iݑb$J#!k\ar+i95Ē^[X&n 04"Ezn©>L%&¢һMv l26 o˓~\t?u/|~bS;qϪC.gGebw6stIkj bGPqh{^(M#c|M=j;ÒQ]j&z\K&;N|sZ>! ޳劼pWH8٣5hN39٢Gh;eI>S]uΗ73JiPUQIB _M_$ S\nU M$ٔw)a2| 8ʏi5oC\)@υ9$Ȋ $Bx(NFއpTFy$<{ҋatvwTEYsʴC^ (z]}/䎭1'D upc_V,;Ƅ,bw\b%WĤR;D5EG+I,Ө K E] uU>6}¥hj/!QxWkkjV/ "$tqǏ x_P>kЏkr|^A)?'DĚAdo<~npfü ;xaf!$f:3n06 ;DE||{nwpE$dXe0LO]%mE Bx]n27bt'KӼkl"5T9ڷRa~9#Xc9K[4vDX>y^ w-Gq/T,(`^[4˴LcDudfY!Ib!$ܐR{+d…5i<1r!ʠuT ~my ':&w쨳}oRm$Yhi41 Ǩp%yki4k亚9%(O -]bef׆^O])Mԫ7/ dKz0(U`ܥHjˬ' YE:6|0BȺ!ўS? = - [S(mh/29N@'Jk\kؽӳQNeF`^Uk9K8ƛbIjI>{=6AtPg1-. \(a+ }$^?$ *vlkq-MF.4c]>07T)nUEo#:zMQ:p )`'&d$oO=L1JU|gq ÁYaְ{151A]l"5ctiO=߿fۧ6ӈB`4Տl2hSVX0+keRiK6MipW*4 n͋dE>2ct6Dr8(r2O |OεysE5ZCA.K5TX<לUs#9tn"' X"kߟB&$pkdR;hc˫u,w-5/~x2|wLJ[qU+0u^ ؖl^&='Yϡ>J˫/ǻD2ƓU2#%T/(⺏d0 2:%6VcNTI]d%c?1L܎VL 7VNu DGG87˘ kph5BЙ~oz_Yƴ-6Wn nvV7_ɨNnݎ"1s8ئZ?\?ۧ\_P=(4enA77 tR6-1m#Zƒ!Mö/= 4B !{:Dd*0HNB-stʻ/:WR֫?, x8i[ZMt6dhd 89_pu0wMt]Ҳ%I E2LW޿B0-NMAtɩlD؎?_8Ihmo [boas8WczwBSG|n'):Km!?^C!A.o@O11|0Ab~tL"'P;sR>Qͱ~VsxGCGcOwC C]z8.se'%"JۛQZ>~o%yET8P;R 裤M6*Ku :~_ ;kT$6ׅw\Upc)lXR]i-'.X-^(B̙N"ۓdiJ0E4e?XUG7rfpw?*eb7tPD4g +?Yh[b Ÿq;#! Tj ?FV3u[!T5{77T7D4+e1si}mtO*IXk6CVs_hMN$z6Oku<P&.v\;nd$9;߰]uZt =ZUoEg]玩Ӳ.R&| Ub(@Jи #؈ѱ#1#3 kab;ƔL#|sk:%'4wܕ-GqͰ =e^1V795e1=┡dE`)I>ipY$5]+Cj,08{pae `KOH~ի%U^N"@07G ǝNajQ<5,A_ C/C$ =)3REl'#f30kPT&˕bә ņi}$$W)!,O=aGo+ 0wyGuK%o&lben5~_N .e<هFd}3 T?dzz/~`M= +žywu ]1dV5+>5.V@||Iˊu UiŜ̒*Va,G[5 ޾xٖW 8pQ7 Vv*lC =ѮIeKǯE `NqU_dzC{(,,z:(@ v0L{4 KE(#,y[Wq5kPj Cwxr #y?$s3`sa{tObP!L l[;(c &GyA-dO$R[*/J_1>q1cx e7~hհ K5hi Jڷp؆^o3 tǾci5R˔bĄ "ܦpǀ'A+5gݺihR&(j}.2B4<ˁMř؅1Q0m؊Rʛ9rV. :н޷Є#&?X66R l(jvki]=C2|XCiU_=l$s<*WvjE(NUy6 ut-ȅ e.9Gw5>3[ Ye-vc~">9n2s/v kS+FB#ۂ1D{w^G-<@޺Nk/T6Zu=##CedIF݆q $v:})ZV!@ٿƨmwk81\{S'M6Z\r'R\]wJxKPeWVan7MoمD ʪV7u{Vzė`8G$4Ԗ)CQ:#-*"8<1G@Vb㗈] hin >B%w2PcVCZv ^6rw~@ВJ:?d^B^|ȅm|NE7p ,gC~֏þn"Y}cclbӮc'ŘWWd_HtKĔ!2:5kbֳ7^1"mjd_+\y(֗>ðWWS8_QB\V\`YGW] o3n!eQ;]p%hD 1TFx7V-v G0NQ o&:JM?OTEJр/mSp(iuc&AGfyx! SnWbmBHkn/X\cnRR[s@.%QLĬr׆o7%`wrSL6狛dS}EU u`f4,VX.B6F*(˪Sޞϐ^CM, nxEɻn3^$Hıޱ]Qn_oIuZM%6"z  t<= ]lkS/3P۞l؏rp/+Do@sW,e~~"9# NY(U*~؆ϕ]˿Nov2I+^@[>0S76c' NL4*+pZdg?ݐsTO<0B=5,`ݦeu9|a[/ff@!(ׂ ;>`Hv"ӻs27?4 4J!ҋ^7e~^D 1cTP 4A!¸"8d HN3Q|I7\A&6mth=@m+j[HhIj#/*Jвv˔ KaIhB:糴hWOE$Ljwx.~Pӡ^\?[۟@VqܿUu 4kʚCPKa WgλƩlc>^D:=p237$PX>cA4+?i2&ڒV!--rSS?~M5U|?sG/&}یU5zݮQPu` _BI^p IDks^aD8V53}yc} :T(V@l˕X6$4K?8jhwy#SdxFGyØ ؤyi3XOk`(o:@j|YnB@ IK^}.$R(ET4O'.I:kj.5XH-;' SIUV~Ȣ$ 81SLK+tm(Tc\כfBUvxPx'5(ZOwS3ypr,Fc lݹ)$-+rs elW[?YFg!6m}$֓Ax 1YL|S>XK ׃)E1Y|fjET S[_XQOfHP]5jis7Jt6ku3l qAi?u'bdY=IFTztR<( s&!$35rc]B1Hi0[|'yOeܥ&q#IkwNMo\~0F0Wi:ŀFNھMQ:DD2wKHtsZW騉T8<$"V+7Q6x,Ԥm梞U-[ws_]ޟP ɪ}:r]S竿qlד\Gy5vg _4VܒB1;^Qh`4oHe( zO>sïF!%oо:HE=4)ŗ,:„WղÃ~J^uD,̈́~w n.N~JV#- ln߃b7.Z'<ݥ$Y9vCQwP?p$WrL}(bC;gD\~Nj&M默ҏq2@j4 L2݋+ tgj%ݔI|c$pbo}FawV-_Rmπ!pLWgAq ?ʫI%5ݬ@I(A`ìbX ɁO&̼9<uVQz?@`0yUȁ쐣~ NUM73*K7zWÃ%!Ft4BlRDn7'S!oNpNaPJ|3aQ98n _'RXsaӢLIY봵5>޾V0Hn QTWuG:?rɅgsךk_*m4CQ/^s$ZbgF9WKOpD?%å.(F0yRIG.2zSy(d7`xR4ԢC>Ya(8eoAHLC \ \pQՆ>(;AHd|G<-<+0 JbZ_:0UO }'|̛cuؑkEyIJA]21Zrz6 ] 4rQgyshƚEi/ANY^Ϩ8?q8<=jҘURx[5l K }x6 QMl=l.SK*+a}jA^qV'-VGE[0$G@5l0wOje4W >q$ ٦ZVf,lq`2 JPXÅ^f/0_ ؉lXݡ#Έxyjn\3dtlJN/Hgq[k6ٵ^ VV0C.M96_ mQ|4@)$,1."-[ES/L xL3ȸNåz4O%O/]_'e q=XsKG;oLR#z`w*m8ih DRCoɼ۳8C8ö,RùQ0:!v:gy4hDEcqGa#7u7Z&2I=1/[>&TK> V,13!GucO:=IH̃,OBi4Dƒ׽$zٞl iаz1"1~,! KF]fB-GxݨQe{Z+a ЇTSC+h='ҕEqzb՜ 7w#5J 8kPb usmp!1.%%2G}*H%-*ݾ`~~L ΍u̾\cG f%mI[oUT;jB~#pț@mIDW{*9z%إ! Ԏ R*g~|5E9U5D'%Nޭh'c7ua 55hRrB3jP/\Yr/IsK~s_欐'W.01k–WiR-GDI2XS3R ^lv94unQ] y#?@##ڎm j'>ݳWNKWG-簋6]:Q*r@(w!ye!Uxf^t)EMqhaf@0g=fi4 /X,8ޠSߝ($a NѮv0 q>HJK%ţ-U7GCP\./ޯd@"Ȱ2lhROV1l# 8ˋ&FpYD'BzN͎6P=-ųPƑGYsoB)4bd!sjp975_y4Ӈ_Pˈ7{y]،Pt(p=]鄶 Rڥ۟[d Bpʼn9>5>qPfBيgKE ȒH X I`ffBTI&?*,'zꀐ]DmpTL _VG Ew7oM& (Bɺ*؃~] nݟfuv0֘C=D+}XJ˧ =lV[w%S9H}:pqH!_Ɖbi*QJ^\_N=4P~k n zM%vMWoB7\F*\ye7|R.|vp7!]k endstream endobj 157 0 obj << /Type /FontDescriptor /FontName /COSKSQ+SFBX1200 /Flags 4 /FontBBox [-223 -316 1694 925] /Ascent 690 /CapHeight 690 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/B/C/E/F/O/P/T/a/c/d/e/egrave/f/h/i/icircumflex/l/m/n/o/one/p/period/r/s/t/three/two/u/x/y) /FontFile 156 0 R >> endobj 158 0 obj << /Length1 727 /Length2 13345 /Length3 0 /Length 13925 /Filter /FlateDecode >> stream xmspom5v~m۶m6Ol۶vN|b3|V4Sz=k&#wwUr4ccg k22Y`D͌\E\͸f3G3 lea 4wnkdjeg Pwup2𺻻 ;sH ji05((jIK(%ffFE7c[+```oj/N.&`n1sg;*@LAU`do 總 ?h3cuG pek?ΞaV&c3 +{&eo`O@TS3nFvfJ;G7W3g=@ jfojf_/ \Cr43UrGrs#w\?B9O)?j`o ̿1+i(o 7q0N+YgK3`'@_C翖E ;x13qXLl.&6]7gg3{O/=Nfff&0& $+Ie`H~PruW3kfadY)ٌQR6ou!4Ȭn5?6[kwsoU}"zȧOC R(,dC9I3\idU@ͯJU]m>".Oik%(0kk\u~=M~ek%|l?M$ XŢؘ[EȅgTf˜ƅO3:* r~6!\+ GH1@|4qvmlIs$J`*]nhmȋfL* mUDGS,O`Nft T{_JԦ*AkI$$g} i{ Hb*v%dve_+M!8e7mQ7"5lmLS^%>xI1WU p̓`,~3h\:3\;l+b]+=M8NOGy "5;(mHDa^ UXNӋo#5wro֨8~; #[8phOm7ӂ]ڻfaaS} 7omZk/Q:ùD}|UWM<ʨ_h"c>OH>O?{hk${ss=k~Ĩ,Vܙz8 =%glw1rώ>w_; }xq焤c7w(+'LhƟ{COB=whޝnNO3hhB3ե}Apaː!0dbZg(}"(+=Dȏ9y\eA#PHX%['\w (fqm#M˒-H*l3HsҦ#'e΍})!(]H є=n*md'%cPw"Ha|lW_su=$tD대0]#x~P OPw'`phQc^bF&B$Q 9!dʰv"" ~Dj Fʳ(Ŋ7M\JT:)wHܦ-V_#t ~j40`C:& C9,s1/;}Ȯmi=3ę.AR;B:Zt,4NQZi Pt %Q=JX'/Yb=C ZX5_%upΖBְ=/P[֦uN}]Rd˙ Y ~A#4۴J(PsD/=̼Ab6 [}wS^z,HgBù t;"vaT:^0^=,7s;` P)+/wCԽ#]оVnaQVYg+sk~n,OA],7St{n:Ηޅv?2QPR Š=l /n8+\A}]ۍr(XLyuo(tCw2-RS&Ow+bf0ו;Z+{2#䦨&bmq L- ] g=yQftI]P"1zwc\T\MV|LxxڒptK +ʡnyffZ-4X\5mL>DDCkE)T4#eLg |h}PV \j rgP D;婴d Ё\#@|?uv+?Gql)؏]q , E8#E)+bx q$ [8'>fc8[G3nĈ`f`OxwݠGğ]E?|:4Fۺ!)57M}@ >%LdHB^htB wdZbWr: 8)@b]$! _=3ԪULs,R ,L#Oc͞;PhBh%nNN 4pgGf.cwryJU1VUV%1O]cW`IA{/ (X4zz|SrPJ|Kgشjd6L95" 1QaZ*2irl' @ɮAQv1CѤQC H&/C5lkIgzm2*ȗ0zvۚZ8pu#~pucT˸SH'C-L)J8]EF8[7 M#oцjnPvrWcf\a{{V/nj{iW@l-17 TLwUvͤ/`}] 6 $hBtCc\:QYh+ʐƼHT\ .x]jʟ{m슸5P<|#YS`)-(Y&v9'R5U|T;x`S2/E7#hqNBN-Q ^fZZܑ&,R>c1s\>V6}WŞBUI.OE#_EHfI;A;ٞF(g=L]v_;g>_^ݕhleLz|2$z` Az -}ŮDx?KaNį\6 n;'dBwAy3zPQvN}Kh$>՛s%o(G-!;m6?Wd Wh *YlAbԽ)ZdE.HD3ՀG EJMkPw1Y'J`ZEƇ8sߵs]ODApHu1 A"PDWLl*jn"CTke`BReچyc!3uK͘YLVWɅ%4YYق\q{0'Ug`^ӥ&;wr]3V ~ݙ! WD.=5) (KTvzA$'Sy@^\J_ҽxSQ>yM .RROZpb&w^I쭸t-L^]9L;C"kX/(@WWrf]B.7ɇXo"(</08&Nc>% [y. G%;' dSڵN TNX92?"'G<]LGCCde`'Mo7.Ւ)b`aD\:!@2as/ 8Y:}S(=g(O|AJ$GZlu0V̽k O 6pS-_:OLty~1:H7~PS$%"Rg]iS:ZBR@dy;ILwme i8%oxw(E B,N*.k\7 Ed#m j N5ĵJRq/q gBf"?Fbi?"ZѺÖiOCgaffeBk&Ylt~6F"c3p-H<+xX4>#21}@#CrkJC*ellQGb`$w%܊$$~U(xcw>s Ѕ7,rXًbBes æ%z:f:Ă`{K`rQ&JȞ`-5swy%x}_+U%{Yc# Lb oLfS tz0vlZEE2ui I u\RHʔc ̧hzNΓ!4eMхcv[cQr,sqf@n紆9`s.K/^W*gf_I"% 9/%u~w["'[h Rk3TgV":Im6 ω:qÇ/K.,4Sc$2 KSݑdH\fi,mc[Pe`KaB5tk,CoI?lʌo/1{xO5$O01 -1Nٱ r|=!3b#:}b@Pfdy \t [ "]7)^-)yn9kh3n"\e~<(B+߭\1s#&E70fz]mj:AkR1BmҢy]zϥnز߽? `uǁ_/u''ˁzk>QEQCN ͯ"+ef:Qk+}f; ƧA x -Ŕ66 l Z%0Gr#pPWħؽ y)" ex{B( CMbʁR@Sr=N_&ʙp}/H3ӑM{/L,̢J*1*l&2+Q>/F!j!0RvJ(w~8og mQI]zYӱswW q) Oƥ3B ~rPk_ $ԍBٲi]8u$U5,u-iWnpvGx 9ҡ29onsL-eloMsIBxUTZio=SF2tkb+k8:6ĺj)qdb5d߸[{l_a<|O6->@zK'P%i%U][h(kI&,Uf9uac}-z"@v<Dk|[a02_囩sihyKߑCr?;(; 8/{Aɘ66:*kf<6eW{iγ)>alYZzY2]Fb :3G8z<Z"]Ve('%0"L#k#c^"COAì=|s:s4V)Snc͡UZ{@&pĈ@xğ iv:OfĖOF0ATƒ/9ᐐb+JаޣAKOx-穸abRu2 dFO\}&C/^-QqO ^?!c#]it)KH=kVB#Y .w2АtM@9ìkyԛEe-j>D|p;<so6T?_ :CkӽF@LW֭_=E|CoLĨ0Zھ-QAdkŃ'^"y uZl$EX ]~q']fstkP~Ԟ W*K:5,Ĵ^"G3}Is\~[ܥSQ#>L[^週@ \RPJ #SSdߡ($M?IF{N(|\I F7"e[̵/]SOߨl QaD0(ORR$.19~r~es?YbIuX@XGy(ӝ POfɞs\{Ac~KO51[gjQ )P`e0 |T ;uW} ?}5 $vD/+H*1Է)UuJOLcm^_ Op~Gۖ|I&Q Srl\5}EjoG>0juUTYhid83C-?75QXYTZkܱM*WWI+b빑>$֜=2>p ^J!dLO9iWOLҚ?>UY ZR7`p$.duxnҕ I< vC)x>L6S2;p3ϫJ5r541W>vjVB@16ֲ_/0 Ac] Omp|E~{AS 󣻍*:,9'u6U6L"@h/VxemBظ)&Rrn!6ۛW:w`fWިV JQK`Y!Zy𞽤ͧEOXɚ"[~ Y0cZ+GwE"r" qa&9бNSbzPaB :}RWԳjcvoBw>__e&P1ғ T<rlQ<0j.^~{ҏ&n| \u-TfG9<87e gU݌c,UɉO[7.bׯb.J; 8S_d!zʼm%+C 7/\ qߖjuc4S⅀jN8H3t3̟%Zxç&_a43yJ]C=dF>z'C3[̅ɏY#X3O$\La9 n[)BVHݶH]FDzG+ I[+Y $?@Jr S[FpEi#ܙLlJ\33;Һw"Qt1SS9!#ΆAMyٸ짾5O<y8GMrg-OUa *_Fn4!Ո[Og>uEq30Si\(c|A7 #^/-CȮ@uh:+Ύ^ {iQv J~&[ҋk g! h)S/^E2TlU-FJ-nȅr5*2TC!ExUҀPBukU t]]Lց-&"^,9ſ]4Zb///\,ˈIFc`m =Թ$fnoda+Y*<!*h(gHP;Xn9uQ!Mo4TBٽ!2֫M6 o(S'PZJ 7#dWrs,jv|@ӭy쑍 |Ui]+^3lUtHc7_Ӂ}ՠU๪")MvGt8 Ζۮs 7j7!*ªZfv5W7*ۜHn‰ȺO&G7#0' ųqMUl#ޣ-R9ule[oFtQZ*N&U0Lg% GԖˡ/lvƾ#!3NrOѿpxtxu= qaCHcXثLQh2TPvHH:hGe'H2Nk,-8`HZ~ wuཌྷ̲mQUt@C;H{mf ΪNq4ۧP@4$k~mȡxKк!-zӑA_#"ӃD?W:ĵ]^cJްfxf-އm@ЎHm.r*r)=̘LoC?;|G_5$_M}nT^O ڶ,4@"]CJV̐e~~M=pT\dи}(|5C 0p2bWÉU8~R)xi?%HaŤc~ׯd2L5L4c.zN8BIX>2"hѬ؅@\Zk> u.YYdPHcs 0s)KL?VAeSx 7Mh6ޖFj+[)kp&#m4> .Uʵ̭,9Pu ?g&W0W塸eDLOGMY&1f9 \ެM&gЏ2躸B5 Chk 8Ƴ%IОҬk}TCQYOj%~N\pKhv <1+95V^M +PԱ)oxZyËaAf:m&SL UVR#>zwU(֞09",H;=/=`o}8i91_F~)S`_ U 5Ri3yÌ|;&kz6\6͌LjK+^ ąpA`ؾqh2R=S<838Zgp(¤7ʸCNg&eQ#jL!ٜ7!6KZJ!9 ͪIK_x`/KK'_ɽ QESz8E.\h^%5A ec[%)mPe39cMϽNh~ISifY'$ 0gxC,t xJxlkͤ2զʾ*AQ%QrʲOUr2W5hϡ Jnv6 vn2 oM #7zo`X^={(E (ˤ# Й$-9kL)ۖ6m_]j S}>n72yEoM1h뢩.5˶gP|Yc׀Nm6(=)fSp벼UY,//ҹkِZF rQVnD4(XYKԉvB9&n% ˙S.*C^W!jn+XRI rCB#՞< b_4\~ Tň&^.g4j%<4iv]?Fpo endstream endobj 159 0 obj << /Type /FontDescriptor /FontName /DNOUWO+SFBX1440 /Flags 4 /FontBBox [-218 -316 1652 915] /Ascent 690 /CapHeight 690 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 444 /CharSet (/A/C/I/P/R/c/d/e/eacute/f/four/g/h/i/l/m/n/o/one/p/period/r/s/t/three/two/u/x) /FontFile 158 0 R >> endobj 160 0 obj << /Length1 723 /Length2 8760 /Length3 0 /Length 9343 /Filter /FlateDecode >> stream xmwUP\-N hCpiݝi!$[pwww-h]oާNխ2ms|eQI;B4@lLl̬@ i V>VV +32 4su@@ ʆLptv[۸i-),`(!.l@@+=(',Qʀ 3{=A\At@+G#/Nx\rqt*IiI(k$X4%fK_8͕4_17o32l4Y!,RKbw?4\Uh ;nolJ8:8\J Pvf9s3z.]^ KU_O]QYU-!Q,dSWWc iKA,-k_f.-V5A!G7W2ss{ Xe}wJ\˗ dbq.. ???V@ȫK-埥 g+ŭ[?$@ۗ4Bd}2#!JhSA}2:oƌ%.q0< v^dd*M㊦T<6I{1v[~wHl }דl%F_cWEq<9) N|(خ_2h1\Һ0/D8JߛK?b%⽹{ NkVb4s,OBVOQ9ҎP6]/{j{$WyrOT) r_%1lT:Dx+⧄NjbJtRz5DžO$< a@^ʲ˭s.ק( ooտ .uU?PݨwSmlbF9jrRo_# iP?҈إx~~LJw*&.uH|=yNΆϷ{-cBvB峂ͧkXkb!DAX,> u 4W{V51iҝ. qLS(]oa3;Rލ"G)UV(`|¥ (m>:` " bboY\&!cRKV%bMؔx6$:a̝?ƊQ*3׵ds˘*gğZ=^rqE#'LT*݀I":w$  `U>~ ×fs\>;(\FZOm.SA:ö# nP<252懪b-,Cⲹu 9ө SvCvb:>O~6 @ i)]` GٞTgG̅7J̜LӋ*aY Xnݯ"<{IېH{cĒ&U$?*NqʐQ!20?=j{]\hcևJ^ ܍YB L^Y|+[dAi7@t\w%@H)G}! =弶|!ap>WNeJFϊWlۺu/W>}q[yIGD > $W`fRB.mC! }UIsQ!;@eϑ\W;qZ:_X'!:Xۑ/+2#ckq'}Fq4K,*O-OdN.:z/ k‰`˔T GMlT{ϙX׋@͈.QjeM5gec}7~n = ǹ(ȗQ=Cd˔|->Vl^PFK}2V"x[6jV{ Zu8bS;7 ދ|#sot.FW(rDKw:YX7鹣!s^1riPf#"Sl0'ܸN>/&JBZ<ʗWl5!7&2HEÏ2P ]Uoa4'T e>G|Ԅ?- Hlρ[K{ۊFo[fHE,rqAku9#2Ol6!.`yW3N{ 4hÙ'hѻ k*j/6Y;T49 ;5Aw"8Oqb* l?tal'/y4VʬJ]Ňd=+sh 4by+3sVHvzg4 X0s#Ye/6FMoBug[9AcHhpT mZB`FBh%چJ}Fdn=-~'&8tuJc7b>r<9z1kk]m!C-q-V3?ąs\aۇ+)'M7R|y⃲3B{+JlHDytBKå[38"|o!<8n.99Om[M+CSk{ O٬gU˻̅ުs{;%-:5OR }>=iTmmz)X/Ø^eK<` <Se3G Ug1b!Uf{˪w/6Uv_X?ܧ?=Eީ/ὡ1.XM+ Zȸfp%~`Lӥ |I9lOjX`^Nk9ڛ}25e{%KB>k D=c7/ ۵Kd_+_/4df ~Bp7fKK)@$aG{NPiŕ`y8? KF͙"9b7׃Od#9mɃP~ 7"2Bm,v BGzҀ 8 ~n8jN Җ<b^Djه`wyQ"+ v!EJ*%m?+x>@[2zn@+I\1rkGR 15?}Yd' Pd_h<!S+E1IɃφ0Z3ft1^02jZg P#* j+1-UsķO?xiwbx]wzdQ5md-nw,v ?WΙP(*h5Z@2 Ra,= (pu!BFO;LW qK;bͺ]yl*棤/=EA!vlku(O=5O3R\YBANK5OWW(ArXq{d{W#,tCq)ҁ6ڨ7GOmE̪s7qE8=h0X_]C m/"}fyODsfHVbJ`ތJ;*L~ـMYC4hgvPKv>i^q}>,.wZfˡtϊ wVw:m$xve,2eT$%ֲ?P|];RL!8@MSZ.Tx^ga[nOٹv_I)VIqtv !mJmal9~[1o=0h޽Ape+#=dE,STe3Q#íp ޞmyc\>YddwBCڅvV0ӈ .b0A\C w Zl;k0Hy~" KZ}IYBߍ,x9oD)f>LҒ BjX> ?j3E m-l:26"=w Ml(UHi7DtihQ˸WzkT/1nD~=(lZGu/63ۯzѺU '3CWX_z0GMƢuڎ5eHF)w^K`4th9K5~U^+t~;x sK-c@Vٙz_ cXjkKD&^~:Z|4sfyygRz\Vp`eeuseT7؄Tvv5L7۴?x-^A#՗?*Q<%1yVMbei+Nm8ڨUeW I*Xw͏+C(8}XaTqҖHƌ|l 4J$V[VApunqd';Qc#N]ibÙ!5h)BEl^l}RFZy>BmPFW6hXElE@?hWשfP"Ӕ1z P_ \*ݚyx>TD̊R3nw`x Kg>S6GSꭳym%̼$zH"eb@fl{['BsE<% `)<54r.*]A2 7Z ;-gqM1,gFn ~]%8q(Cn:鞎UI$vs NF}O\2[| `̀e Oh8m)?`k 1M.(yYy33*LO~,&!G2 M7 T,H }1]4QjJAjM5#,+OwC 8zn*5Du9f*Q$Y6 Ԃ[\ r:tt$,Q;tN}"qbۇz:PpwV0P__"*#j܇#hE l<-f Blh7rl6GxZ7,x\9zɅw3]Հp-Ti0M]FɢX!1h\R7&iIyUR\$F~#._=5TڐݞN/FGjn2``윪Rd[6qyΘk۩UlG4 4~{,nEOgYK|DCk9e_8ܡ|S4GXQ'o34 eoLGf^rj' p-ׅ:؝Oߤ*Bj(GӰcEǽH8)A(V7kEۆuwW!峳M"!ºZN#IQ:I^˔o+UFd/ӑJˤE83nfjWkeJ5>,ҵ>+8Pb$nS!Ge'ad OFN%aijO<UZt< ;:5+B iQD0|qlu8_p%mIL1;@W_~܌)6 Vme?X:vcW%k-}G(ZSW}ޗJb.j 9,^Fx1i=5 # !H̀v?^x;C׏Ko[:fUs?q*Vb !9 #} ʸeʓ@*hsFzy lW/U72h!kfAE)_V?b~z >Q z=(o)c}o(N-tb8(epUӱ~=Ǩ dhk0%1î5A9}Ѩ26QRQ +CDkUJGSSjz*=iNE Z1L<+n|Ԋ2-mW]+|+q+ O1UMLBhIpz{CՐ}xHFT5P07" Cu*Xakz銰U!XmVn?dNyMg0BƓBy 4_laக20]taXn5+ppietb?묊A> pry`G"īFQz S42'8UTF'=3N2BԞ~R(*mXbo¸le,l&G}mɂ[&r1qWﰞ7h(Mࡄ W2g`?.9j]ZST}H4"hblN$;ne.9u#qrmv_M+&80;S"-#J00qǾiI=ݔeopt!j_?k?#E6&(e@SOa7%dه攼c*K1/c, $2Z&d㳜]zŭm#N^|LpjU)b=uy=f2~%ٶrIAðrSwId1J=3c7H6 _=Q(QtI.GDCKvM]> endobj 162 0 obj << /Length1 722 /Length2 7124 /Length3 0 /Length 7716 /Filter /FlateDecode >> stream xmRuTzS:E!F@RA@:A[o~9Nu} ~ (r@Qtrn`;y<@ 7#@sX -A'sy@bRpw ?C:`0 8o4*k(X5`(ntrX `+`I0('Wο @=p?l0' ],, )[[[uV^D8 `@qRKjܝ-rO" srvw0Z:NK'w?nQqUxA?rX:oߨAwU ?+B.MY]i-i<@m:n[A.kZBqпdusuK78 ` "޿vyn>a~0jnk{qg`֢ɍ!~cel2MAsqȎE &PiPe:(~Z1?ih`8kqc]WQAd i=N(J|fDKdbNps3~YTlkwt;oOHfU9`bB#y#FUoRC\$fmG"1)6 [7~+xSC3l {yM7P>"Ktew\vwFX{iA5dS4 䐽O;AǹbiN[mʒ\9Qlf|xc@LM8?J,x( &ޗd$ur^WN>ҬKF )n@Y$v}uz3~eR' bU(HL1u`뎈Ȝ8ImVߍaX[׿"-ղcHc-{w:x }(k4>v~]S͞)j^krgr Ն be>zFy(Nt ,BiI Zm{_M2kf/tzrdQ;#}oLʇ-miIm"c\9i.bDh'@q!XQ)zc67;:-?B]#'OɤR5g>܍8¶>#|3L'/3yt >>=r]Eh90wLb[\6&?6+fnramY9'{,/MTJdi[4AAgf'g/$ +i̎rY"Ъ$꽞^ƊB{-H"lԀ,ʙ?ޓq퉲5h2=IϗL&HcdvGp%|B?g!9x39?+H>[Ʀ tlz^U$E|zo<#{r!*fA$͞Xb,usȈkL+m2GG %b4ޕ0RQze5hS: F˖0jE0交J5^o靻d]6ڸ_j0wdJ90l8R$ڻ$xZ;1>V6aF ;etrĉqʩ>b Nf7KcPaMșCoVr$kyaS _%KASj?L~q>cYFQ܉=$k/Ӛ1pXlMaxhxINaXv^Ie4_Z&F j MzqXYbk%Y}TJii~n\g%jix_F ~hb]rDj/`BO> a !ڽIT̋M+Fl#;\}&2ƼXYRFШc꼙mx~T5GX*l^\"Q"fU%&nA;p0ąf`J~|򬭐Jh0kZ7f2=(qcWUx<2w? -QKf okVfT'ģ+rG-{ 21^5 h\os/EHEH'-y;Sr *? <󎢮FyG`DSl*:mm|OEhlGL5ݛ؃P\^-v7ĭsEƘ~g:]WG 'Qu&-7҂duBd>.[|to.*ylнC^; ƒO|}}bB3l:/NPL`Z @F *Oc(1ʏ!Vt6hu~5,NW1\[/mBx+!4z&\Fx9Ƌֹ 5QRV|mkF8U&6Q~&/`c<~˂/d~w6PJ3]"#aheF;/hӜ^wwXY(˸6n|/@fHs|L?Y ?&ӑVm=X$ן%"Bhc v#L-,ûlH9 d(xqSRxځH\ !{ZY)ˇҎvЮ-D9ۮ zyDXICp^u+N7UAJ\].c*VFUϻCqj(۫3 iiU}<7vs1l2)s*7~qIItX^lE^񎱹2]pFᔓF=׋Ɨ]M!shQ9+Sxedk`Qr'pʽjG)bfTL6?$u6_Q0͊\zt{mN*I<=Z2riRQȸ߳*|IWlӒZLS']KT/404־6Ǝн8O{Kka5_6=7%P2s vfXt$-*?](`YAx aYhiqF=F oōL 9G;p{.E-C}ER_j䨻ڪӞ r l³Ҏk_Nav^[YHUǘsSځp a ^߳=qr/>@EGuJXˠ>fIع<1 QGU HS|X08k~G'q@Mw3J\S8xk-gag.ro#I~H) Z`78[Z V2}b )] qnUxg%. Q]-lHMt`߷ap 'A!6 XXEUZT4=w&R7 36.so3<KG|.q{d,yf]3igN*g۩ϹppAjZRН#ndāPe-{8? 糸߫@$2|"yN$1Z'WoP><w=4Aq_*i!DH60YT+n3ğƄb{_ 8 ЧHT<:I'D1앐llD@C8X=D6Q' M!M ƲvߛAL7ĩ5`:o-/d$Bb`JH?YvѾTAnGv/k[3(j`O(@_Y/<s5O5ͦwvcjI8lj (-I_u(r)xد׭a!*OXW5,/=fٛѣڨ1|Jۘ2X1?^c_xq~>W'_\0'D!a:IZɔ@ήG1CKۊRrN&zFrCMFs܋;RuӇuAJ=5 H[ ! c/̽ y1zw\0!O$՘eh_{S++,֜. l3 iH&v ,1gR$I6>\tMo) \iM=}k,'Zj]nJEl Dގc)=ї 4z^8u@dZ ImQ{zTTYb4]Հ4EJE-d* 6ARŧq;PLO,:S]e5 nC;t*˔39H}x'-$)Tv{=K< *tL Q e;Vvl@0l=ӊ@jFPD턊U=hvLsBjՅX:LtI%0c,*\݄4S<8ڵֲhe g THxp+o4M'U995fp]{1.']x)Ȍk!7I:|.ђS 7o W(^_;t|ekS3-(Qf,ng_= s5+CY+?~`p8ȥeE\_VAM7b~+dl_: rg"[&8\2|6c琓LX^ B =ɣ7kU..^w-{T3<{DV;9**}qXg\}T̘.ELVskHX|_'>$J0oH,=FUW!`A؛Z}ie6M7!}@g5j񻮓^,N nöfVf;Fxg\눿{"]Av^G(@ 9LkO'~O%N}{ZF/_+* VFT(4^Eӫ=+*H}*b϶QGJ:*BtTg`ݍ8G73wQ^,c؂ 1Z\st([+uU 'ٓc]$hAb c?0M&SLFc %*Tu8k 4GX2v7BG”l^Z#|GQAnue9 p;Iʹ6Š5AF]ZF*{5͚^b9q"E Ĝ AF'wy-EdUTHڌ|%kiW^_iws2Sbo<0++7(0k5 R zWҰ?/nc3`-99l`p?sbZ"@&ԧ//fbZ]Ԟ9: YKVtaMdeJR!x&YI>ƼC@zȼH2{qq=zYis٢5$lWTQv}!&OXCKo%PtP||zY` ʗm\+Ԗ 9]p9}<)8&ڷv tO66H+KLxI ]nE9ޭMSјiFKDqQ$]-KtA3":U Lٱia,zQcvb[.%2%2#oLƝE&O;>ϛ둤.4RScX[slKbr@6v2c)_Ou. ~em nPQ\~e|gyi>Î`dzu`G}zBz;#L떇b[㷩SC J"kνާ_ ANTv|GV=6;e^UGڳ1ҭ7<޹xlu{f)B@BY mBxwS&/Pql'ёgIaq9Eٮh/ڕ7yN?23 x/,,0 mhKrLErz6??aAmWӿ2mzѧYz.@)$2juudC5!ɄX9X1+Oi2fJ z^z UWw,? cn9ѧޑi endstream endobj 163 0 obj << /Type /FontDescriptor /FontName /PCTAQA+SFCC1000 /Flags 4 /FontBBox [1 -250 1495 937] /Ascent 507 /CapHeight 689 /Descent 0 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/F/M/g/i/l/o/p/period/s/t) /FontFile 162 0 R >> endobj 164 0 obj << /Length1 723 /Length2 6834 /Length3 0 /Length 7434 /Filter /FlateDecode >> stream xmrePX5 Np  .! >` ww ;}U}ut>}a9hx:Bع8@@uIIn/ @aR.a6qrqA .L$v2 L-P8P fs[E޺9r]pR@.%TQՕW2*ke!PjTC!,@KhO49X@771K8$!.Ԑ:X;8 醘u*㟈 h5wA%` [:[C+ X?ݮvvʦ $*, pMN1yCVAe U-M7 o PW!U s 9u54u߱g0 PcSeUS?̿r_dzAY72. 7;WȚsɿV@< 0spMj}Xt׈V 5Sm/ d˽ғhqW,gWpF݃e:dM}n͋r;-g &]ЫtɝLeڬϵxw?{ 0i oJߠ %'3GV.?6M) B*#Rtdw7C G>׵"KV4c9"1Vɍ+A8u6&Y20g[+lQ͠3Z3., fޕd v=˝+IO_k =ّiã JFϮB|R"wՙC{VEN%GNVDžʙ]2Y(.b|Ȅ P_|q5mޑNmXd,iHi9?U)ϵw5St7}wU4yq5j vieՄxTB3PEfHxdX5(0OlIA,n/Uw%]XS?Ҏb W e3D]3'Gmrk4~.mb&7s<ѯ'^VvRa|Hݘ9fWg}풌85f{Csh˹ќ)H/xv24QƼ"p7 XmϚ&'F\ =g]z'ϝƮR =\OMS-|JiqJ2HN9Xuw>=z oPs !NU>MԌw DMoƓI5-lmF!MЩKYfZgks*4{*Mythzؽp7?Z!cP?=U N'pp.o9<@?\iWEQ˞vM~UyȊW6|bK?^C/PgOϮ%WN~34ǬN d*sD4וR$X5t؊CEۿ;VkZkDӕ/]p6`arIOH^NquX_>\U"&yF11M 9<)FWSS{,Ϫ?#ƥO2Ks{jo%>T*UwTϓ~1U/_rG-z|,n@ dS0.FD'(`lLG8NADjPZt. |ij\3C ܆9u͞vs;-u% i=u4EЎ/ӋbLte5,WYAeg]/N9KJ5CU!q>1Ï%;ɘG` R#e7!e?Ni+0]I d~*`ma5J7UuQ 7ˉ ѭJsƹDbWW%l$\xbPE[ R0@4Z. [WKްU;g37+G)4p3WK^2D@}LbbɃShVI{ԾN ͐iHۭ)J.hY|ߒQ]h$}dռZI7iؔz<#$aw=JiI*O#yb\& IĠμkeWts":`Od"j#nU?Af.3km.TbgW|n*- 4wf!;W^Os+d!>mEI:XH_X2}-t0e8$ݽEU9QZEFeÚ9J@pm“19V\W%OR6AD Y}jg~7lH~|yE ."]S~`A-h4t>6[V; @MnVZ1ÏP 0&~my-Jd̺'fA tYVUʉawȵtA~"ݲkRC%BQfg0b*Tq8Zrv2KXY_SlKB%pC/.AG5XG>,}Jr]Gܪ@j v/{Bkig{"?F^8/ yGR*!RH=IVD;qޕ*v,6VjƟӡŨLBf_YU𻃣UCLX%K:K 8}m /F g@[9dBfusYձԫXdbɮ)So~M.t0SPbؚjf>2"Z12(U6 jb{q[~CiI}<`; Kwϵy-3vSzt'3E3'gaXEKiw0?NA*R$Hd`;BXwFLWQݻ/G{ @blyPBeL˳?dpJ;KW:QI'ܞOꝻQ٩4DI S&3_3PA *Ư`i%@6\&+Cw8 (N?P` >dhC6hZTQ;^z[d*;;&]29BBcpgm&ݣFϷ-Fcޏw;whfc';N*p4{M!}Gu{/*491Uatvy\ ].ǎp#ہ>gڿOf{%f$?Nt!h, .qn_#= ڭ G߿?p"tᲽm&SNIXCG9Kk(a`= LiW>Joii\vvLQh=pj6cpq?څ (j*z({@N QU%\sD6A7V/B'e*w5}{Cv<ڢzݫ;wغN@{,&Cf qv판S&GH5έNh++֓qJW)~KEj)r^$cmS{j" GIS+!Ӗ9W?j}\. *;gl;m/3 pΫ#2c26|-Fv>VVxIXGV^V4dp~#Mw~ZDܚ#.WWJí1AԹ")]Ũ %3xᡔ  Our~̑3H0MyDʔMSXasarQw*`)Q%5W;H)* _U-WG-+߃{$* rf]]U9;Y ھuXfdↆG3n`d{_Hy?DK;\zc voENG2USQr~i/ϻ5SFܗSG 4yu1WykK ɤ+i<J_bL(>SRsRVQ}0-G ;ǣQ(d$ărǸ6.5+c6ߓ1k^bVUulO2mb*:J9R6K%#'(Jꎁw@uWorJ=G{("!ЌM 璵J_Ѩt7 gKL@QK#`}*(4@|8$eϲ b)h&QkqdAb^XHO2dʮ7({rN@xY\^cfEScM.q-xKdQn݉ z7f|mĦ;nZڻ ӱXMQ?$p9(g>5qPzBjbG.dZ @ d,߅5tJ(nʾkmF>᫄!n2VYy:s)0^7lpdk/wϜ(%_UυLx~K䆔dRȍXPЎ|BqzDOۊbG*Gw@ pϾ8xsxu1jȝyl+KB9 HD"Pz khmYtۘxsuxNhdM$뷒/򜭳Wh1#ly%?""3}®'Z`)/\dN25 7t_ ].ӒDi}Ċ}ջw@/ Hwu܉0;h2zg@?:ˡ:M6R@ǜ>7me.<ЇZ޺vᛠM k4,>%W_'aM=y9.xy}t{>!D2LK蜻sJπN11 PZIG7=Va *iR}z8*/t7, $Ujd_ox;k-G{sD+AAMǙV>{ӯنz8AΞaAؑ$fyn(3 O< Nz ^16Rg| %mYL9vˏ-O/ߚ\$dPEԏ uG@ݥD_hx~貛5b|=(%Y\B<A[m ЏLl{,rcCWqA ĿfR7{0A9W(J ,ʝE~ k]K}v"Q{vp9$zLxz vtĹTlЗ,7.kޫbmNXiбc `WյȐs&IἈh S#-B9Sxs/SN CJ endstream endobj 165 0 obj << /Type /FontDescriptor /FontName /YTTLYK+SFCC2074 /Flags 4 /FontBBox [-1 -249 1546 951] /Ascent 544 /CapHeight 689 /Descent 0 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/M/l/o/p/s/t) /FontFile 164 0 R >> endobj 166 0 obj << /Length1 736 /Length2 15480 /Length3 0 /Length 16089 /Filter /FlateDecode >> stream xmsctݲmlyctl6:m۶c۶ձqgqǸ3kVZ檇DUь*!`b`u63rr3r5hT,&&f8 +ڄ$@`neb swwrwqcpv`I ji05**iK+H%ffF%7c[+ ```oj/M. `n0sg;@\QM`do Յj3+MGp/5/2/o?`je 06coЦnG?xH053V @-`j w05s{g1ҮF ?FvV^ߞ[ra{\gfc`bo"aifdnf5NfVnv9yaS{[{?cRF9UJ?Nۛ8Z[T]ĿJFV&cy#Wg+Oÿօ_ qdгr0YY\\~Z7gg3{({ǒ+H H]p,AYr]* }}*_Q=sHKjP2Ne3 )fQsfSm $8v<9껥gB;A=9!Rvߠ~:0_/Ce9C"C05\6ոb^a!nE5|v!S/O8dh5. 8pff(yNi9SB|K[=0K.?M SF v!>kR%5?+7GʕWQ.X jߥp\ uqJ[N+i=* B5¹)-qq2H TZ ;y =''}]2/)#T?ӟrC}s oWFg[9 .l] }kC?GG4aU-\NEdϰǣ&h,Z'5TJE@kt-k2| mqKkV~YʩϬCt R~5p~|_%c<* ~OPpզ+cɍc=TnxvA3ό ;>_HAHllEѰꎺE5׺^eaV >˚UN20[[V r\yckDʹvaC-9%)sȦ(׏̸ i-M x ʸrzψ׿ FÍϒ7:~ ^] Aji'䭒GيpJ啙vLw,o`&q1& Ld~XevJԔAs-1=^[]#S"ryZ 8ˈYn1lOuչk@xRnJEQ?v3巕 1 hJO1erK8E`Z(ikLŸ7 WB S zلc߱;GW ,^0Hl2v<@"7N]Mnd0u&Oӧ.c]K 2 w8&i[m4@+r kf&>3ػ_lHS4M*no31P~I(s*Jn7JpzƠpWo*64 "]w~enMǵ`8Qo;b,+vXtyl}rd.pr)8D-WR(_2Ơ1#)%V-~*,"Xl٤C2KPm/#XE8F?6dF1Pa%\M~o`2WcR}("hF 迊ی% q$L[r MQE[d|& &'_W{HOvQE w 3ZY,m$yk~'|rn pAjj/!C/W\bL ~OԠij2']p٪ VRXq?fs]wy/mZRR )s\P%&̚?0 z3r 5NĢM4~p c`mū#|Am>yZqjYoR@ @,yW#O!wjZ K͈bRGO}8txK֖r)"b^bd`y38+zh?#$bip|e8Osͺ W0 a2I^ɔ:rGOs~WaQ Ճ+E_$%ܹB tL*{]yɴ C>gϩtZg}vT%s|aO+d B!YF~*CtT?Yc[C E}4w JF7k d!),;M(z,|jQb a#k԰m#e( $s9N0iʸ{`q[| ("R'-1nZ%Z)z51w-i7ù D(vKg(]¯䱗/[|\ăAaL%\Fc`X,95Vwmo6ҷFF>u+DGBd=: 1T?!єב !^"ڗ-XE*#(jl2"A.0)v/l b(OR2}@E~oUl M* & S񄿕#‰q%zm5=f/'h#F%6PcU#Sn7j%R]j>yxc`0r \8 x~&pAxQA<Ú9dJT㾏Ix`ƉY]6i1h2Vor; MoR͚R )l`O9KOAhhT,>ӝ;Ƥ׆c?~Zއ* Z6D:Q-ȼQg/t92%\ZȻi|0x9xkWureDüBN^8`hWe=JHTJfWCr$'|wy־KIY'|uoh_u-#6 1t0-RNl#g#qz~_u *V/@*ɲTQ;:&墾rvOўSGmr1-$%(/2tG9䢽K?4wl\9:ܳ\fH|J ]B"'e"aTfk] b韐'IVl /6v%dM%rp9HT;bZiRЗ*B7Y ay2;nͧ)\gQ ㎴}mNjLE\7 Px[AFm.8$(2~/)a]d- ` w.v%rI'LYGSb:"@0hӓC0ߚJst/vyԽo `hbC9Z_+ o>O*3#+b;~Bއ%}E#bپ mJ\#N]y/%6/D X._TOilf+M%%(>S-Ƀ*sQ}R S5z"u=pSƮm+RZBMfX!׸ [>^SZ'8"dW;^TouGk?p~:hXqE9cm͚˥{NSabpɒ Ceb-@5~w'pZ3|) PICen % ~T˛ jyGP _qʹrղ"q.,)Jr 4%Yfjko_Pw4y1M݅ΆgJg8{@˱ME06h[; !#T-ӆ@yD>a+[pk?J0bz~B= @6rp u-pkQա@u){ -N^:& őɬefۀb)~7wNaRj_ym] OtO7fFRn> OaGE\)jfhu_Aj SiIF<z[V-eAbZql.+!aaY̝HUS!OǞim5VmOD) g, +>(2OIHա(ƯYA*|i߯_ &s!s3$?YPSr  XVAco:7R 7'K+Lm)j^ $Esk"M:B}UN[tWN_`trCЌ?~Oc 63&gO]f7t&=ZlNn$'][C%CU97$t&{= K%X&ȥ d5x&C[l-F'Qt vTc^4 * iNݜg,]*怩ܖp]nQzyT/m$ T(:)CI,wv8-N)+J-*'; ˡ=#oL\ǽR7)KxS%]jhֈH-]u)zӄ B*FyK ۑ 6eNrT9QHuA7޳~v%@XXyS)ˠJ 咨4-Xpe"=t >=AΥ`BuJ.&Fl9t~醐`B\H\Z!Z#LңK6P U\6CStN;]tKR39Hڃ:q,Sl2&&Kpd2mr@vVQƗ8&]f!C 6t5Dc7yZ0j>a OD4Ň1JN۰{Eߋj͈}P Vn`;piqbkqfbwj;_*&ybNGI1d#Щ }-C3nj{uaai2D3Us"#ϒ\+16-s;ey]24/J %~|s[~ોts=EA=V !+mb $7hOW𷙵:&v,^{zW?ڛ;EX陽rMxc=G|ˮwW:Wb)ɏ+GuNƖj.MZ2={)oP=&mdN4JMbYld$X$xx[w&B5r<4酞ITJd;.ʿx?0JFۛ0Ԋc ]Eĉa1S#* _&-4F 4* )N /g~2 MNAijrepsSD6k=Ů8 勯j΄:Zbu|ĮBD_!z;A'nHs+J<ŶDN8^45.Ľ} &ml1U:-(gK.RQt3B$z2 L㥕]~8!<<ʭYxϷS^!rE+lX40/ͲxҾ(j"dƵCݻ+ H33-pKAhs0qx*19iggi~ b۪@jN^UnZg3Y\r+Ǚ*{U0RlW/1_U:dHq"0ï{b7[OxNU^Uɶ2pJ$z#+,j}0Qp,3z0^{ڠ!,x&z HH˚daUHd#ߕGfͷ V䍵j.Qe }$ wSwNVY.kXR}}x/q\G*ioXF JŜFlk# 0WGbi#`Wq6@w#ᗺZQh'H&>t}OlMkfe2~Kܓ%oi)qp.v\'tAн7I7\K:YHUČ̚Avp=sM0k Nt%2 9ZMWy%YHHBsB~_W;mMgo Um,D/ͮ]=n)= o 2KAbIDڟrwT.yMTZD*u/(hsLjp4з؟zm)VA/xiMbsV E"[w9,y@]^Pس*ndZ%x%9_qzG8]\<8 c-Ӱ<c:rGJhJ ٍY'V-} #.Ê;$@p&Oh ewO|(yѳ2}b:Y.,VP~[ԥ b/9۵Z?$s2SC]xLzqw5h>Ԉ"I,8eg@8'Z9>k8\Iz uzH?!E{mq7 ibcWDp#3)gx$s{|5=^Q!QERS<^1JZ!S8Λ98&DJ_2pY/DW{"3(MNʥIL+k\wڵ-֓jY ܷ󪙕i5fh^(& 9mן=ov7} sH$ꄵXHqC::du@5bt"$V6g/ZF` -hr'bN w*I#1H_ !3WKtt/W||uY﫧Sp#G*:x`Б3S$XE 2fo5o1km=^r\윽։$B7ʚ|G1K{raiEU} `:V`@W.IU4~iW,mu_1% zJ rf.aeI߇LkO":`C7B5S>RzXwLߟFj8J@4bx ͪ@F >b O(7q80k|rM0 Ys:"ͭ Ӯc|/PW<|[q3=Cc[U-8aZȖ.itiP ^MItH|ac'K{X._ܩߓle+lNtteumdw Liw_Y?xdx/P O%d3K͏Wh|w>h|}[RJɸ [^hbKM=pM;fS4TskQV d<6BbK7W'7q̤j&{?Ĭ)o 65c$ Ļtߚj;fWE,Oz Y !ۇ6# *(pܜ,2!@۹)QTCDzA sr:qj*ի ٽikR$gp>piKYٲy;04DESq$wQx7yÛiF&6@6ğ|3`a,Hi Iך"p3ۦnd :eu2^;G ZKNv@'(?#RX3M d;Zߥь^o?UҨ$j\R2o28 3/6GK0(8.supf-SjRyؾWm$`!%ؗ'}&fH%ZE>Wف J]*yY Ań?e: /3hA #$#85Țf35nsyvtszc>6_S5OFN~_=@v64VI8p"TiĤbJ$>ire`[fz9+=ۥT>q녡QePd&odJO L},7y]|G煂UpJekQݐVj[']k-[PL\&.516j}!j?Vi]4kM+qn9"?dQzLxYk(&1g}j^>f Ns]:J2De!!aV&ڈ& ZqGa٘Yq?371e"=624vu(X3ţ`KH,<_=>+k6ڟ `8cV)s FMDӸ9Z^79kWޠoCev7UimP̞͌l1T'Tg~?*"z$y v3,9A#0_s];U_a'ctpbj(O|=RFk٣Z:TB#neґ5Z6qe45u5OlTR&G>rnj>% 0ikA*gT06•e?GW eY8BdYxw=y]nKjY&85@9(pr@eM-ɍFUbF1_Q R\,=E6syp[}6Eu4l@9l bN# fl_jzP=;D!;LhֵtnCT>%4L*RMUb @v£#3B%)މ$=+^(cI1J2Zl;[lrbI{ b/;xG20 {Kѥ!a>v.jPPҋ_"M4󰛚FQiy " -&gHwB}m=XGS G|K >)jA{A8KRjm* A T?0o&"+<<_`?ܭ*\D[BU 6y4ioKbIPH]EcKYmrWb^ix:3ؕ]ǿ5"f! ѽwPf7aiV]<=LyCYƑ"ū #> eeU[GR">fNXor#t@YqO6 U8aNy8>NK"W Ѯ$!_ s\9CiW ڂTsqXл}:@ɪv[gQe2+uRKQZh1kR$tP5mMw9Wf*+.(Q^Pus`03,= $ͤZZ`8 D%AYh. X]ޱvd@沨W5QZu"aWE on]?aܓڬ*ْԚ6GԻNP2$X*3PSQ NPP]E)1fQZGLj .2˪,S6-'71$PnyAmܧH!y,,+uŖo\+5jZi!SZ-^cnn33FWڮf ]v2 T:TvUr CԲT\K!]\YTָ@a"9K]jo"TASGUn|NTu!hV7ΆĎb Vq_#̠i_mfcQOcx9d}Ѥ0еX)*m0\$Q`WmCI;DbLhc0ŢJlZ&m(6F{HC!J*1hoCw|Va"0h8`bQ1CL)V<E22&|YfO,fgAx& Szy]gC9w=a lE; UٙJT"$g"F@́/ OA;dW=ƘתvTnHPdX*3O%$%;[У`BǀkoȂѹ{r4D'=Sk51yNД" CТ1!nhLRD^3j}`I…?A!P#nv9VjISj`}$Gb?]޼(MIzjC:<@`LX%ɰkys-zpFXQߩF(Y4"\BtV5ÕUi c/ZsW>ڻo#1D83?ɦIZmvF2^p;%WbN#AK*%u)P<#աiSGV!=t>dgɲtZLW%ʟh6݄Y[kōS$3#A8 ~Z{zt{l# q+!^uД(^Ғ3 9Vw patV[ lRC4\mi+8UwZFż8ml-+l(Fms[fAݥ|q׿A9?|kkrOm[ N2N:nD~1^ζ3 gJǿČ#U:S#%,qg!\bح){irqt$ 4%$c2.?C󺀄L}<ήV! Cv\*r@H? _X突}Xψg2.pTgK)F;jYr}4GĜ_Q52}fғ!oJq0KXxHFBа3aL[0ġ8MŊ-ʨRh`!pꯧ*lzq${fBhА0q? 4U_p栐yz8 <籟KɀdGiѻGYsiݝՊINˋ/:]_9p# :]цX|*U@_C晟dy<<$'dCKԂn99q@`eZ==dQ )W`ԏ*iO{ύƥgDOQpoOl\D[3y 6c1B+N2{Q,CN"9 }܊/vKF94_OڢFw;ÃXXs:J('5ӼT{q$RG;> endobj 168 0 obj << /Length1 721 /Length2 16714 /Length3 0 /Length 17253 /Filter /FlateDecode >> stream xlsp&5vضmLlNLl۶d2NWϥ]{uݽDM PTU`df03QPMܬM܀-9@ `a23Q]-f4 4Ḽ]vfV~aWwFwA7+ SR֑QPK)j@;@ X8̭+8x]fhPPTRTH1L wpshb?egZu06s-7 GNI|8-vS4݀.Gs@?U&vuBD,a!kWIk/?T[CѿZEhnnvw T$WJK89[;XJ+X[=5X`bcfy0U:z20X,\,<vvktp?zW~ؤHU@҂Z&(6-vÇ%ڕ6;HUdF9!o+'-n#M{JYJi&ҿH˂qѝ>.Ny!W엾=7!:Yα"^,}}.[U;wOMjP4J+]+ u L ٛK;b = !A\먑a8oT7̅Ԍim+luSBq"}Hd CiQMmwTGܛogMj51fnЊɰ'G!?vOc%c24]j׻y|',`?+6daq?\#InSeV 6AŨónA孴uRK芐3MKU'|\Y}튖UXaMOE<ݻ㷫/5 1M5iܖ_}o0AHd2aX;mh[U0a+I-Q)e(D&Ӷ]C{yOga#!xd4$6&̣6!cp 7Z4E&jEh,b4U᧙9kg-H!%:k3#9o9*~zd n,V9HP\0E0iv3T`T-=HӬOHUX VWzV )[dɤBIWPoUPX~q&C}/ybFuw +ݹ9w,۪ 9*tS=6Mg: REua6TA%MN]#y;Ie߅#7ሢt<ӞFX .ԁ(\t9imCH An%ihKQdѭ#Sʷq/03@&ycb4xc",no$@zċH̟);0uy̐.up"lJ=UW\i'nLjϹŸZ#otx> ?TpX[{`Thc T &# >xB~?s'.m+ QNtَC} ȟj?)M`{2E(Kj h\=:#t- g`$d v$'EW(xy I2X&]rKdM';q\x fE7uJ6|zFΫ'|`1ã9_yU"b8rvd& G,~"ܣoMY\,l X-t0[T'xZ18NcPviԒUECdj\uB֓~]y'r8F[݌f-:)4Oro] Tpx3/qʬL^hwMcqFy2vW 9hǎ?evm Q2[ؒwc'hK,I]fD%@qKF?7{>uUEta7GAy"?gT\`$AkㆶubJ]6\5YN<{=!l,3q`޶Fjh:{z a~aH%^q5z5l|ɎK$U/Gh[?9̋\<?Fe=?oeDŠ.0%tlZ?Stnp,1qvbO1wg2&;s\AЫIm:5 ds#Ny:+ݞX,x;5KI/l!3m%:%DTׄʂG0HJ=nC~?>p\1rn_ZWQa?;# bS)0X &wu3ιK8yF=Y 9M^)lIό?;ö OjD5$ G| .obӶ@ &#X%ѲERφ]m)rZ=j+MN⛮S E"v,XHITUNc {@Xb'KABhB ;/>U`Yf~"vح[ /{Kp9'+YaZlE`3h=SqJSrS^-hڃ&<,2Ռ~ŗ)#Vj~ҥ04P z3yp*jd,nVp XJ~&evF @( v2?EMJ4U.%n$˧ ~Wy#P;3eSj1<#3W:e^_ǘǏW3͜I{ IxUUkп43mU ݹ!t5mfӡU4ĕ b/JBuFHt<(h 7p0z1CY{Cc~ T8@1Gjpc:ԯf_{RKR53h\ws H_Qa=Է{t],@qܲor_*Ke/_،UX߂@'ҡF4{Gz`Y ?%2y~ (tʬdevΜISWj".6EJJVs##]uшd5&;piKsP\jDA G+G, 9tWڡt s %Js u&MTw_^]jF@5(EYMC_O[Z'Wsk+}}7Tl[Y8^s-UlWK/eҐz ( 35.p m~풚kF"|`Ȼ/DSh/tͻލ%7t׭ްdtE+wJ\#jJ_o+sgPlNo/ >?F+~6*bMSSFiH(󅋲OY@BWua@e}@V09 f#69#'mS"V3ׄ"@0yX#.M FS♏pjtY1Xwk^Y5J 'TGtſX$/H4gъ|!NΪEQ;/8BuT2,Be[10]Iܠs}.SL'1)\ŧwF4T3|ZF#'B`t'X(nar> 34x v Oˆ3Sf*5ͨfFؓо!8? :?](c%jNYc?ld f@^\[v}KL:l#g8.cIVS̉%,sfUGlGLtcyK2zvdu2 5r E%wP\_OG>iYc6>@1,nYj_9P"Q883-$WTh?ݱ"?kfL-\,"5l_-;2 aa a5Ha,a7[e_F1fE }rhĕ`&کav8XVI{6\|'60{e {pjgTt;hL4#Waujm ]G{Vs1TF˗ѪSz7:L@Qtٲ-t߄׶0.v91$nXPSd҉dꞕ+?L/3Ƃ{{+P0BP΄+eKw--/OK=lH(oWAC"D$s2KnwnjШBpyrMT]d}N*MeH _,!#l`dlO&5!2e}K䩓9 /m-Ȕ?"518n]:"eۤ UY2!?ܷmzR=ZB_DC-Zvƺv~ftp"Fŗ8quEtA j~]FUmh&oEdN{y kD+^O3 "_y\c0qaڷ:ʘj[a@*,Q,ݿ%;| !] lCL|,>9fFS7W꺩%+ !m70g4U=R_f5 -K"P_k,rA?sIKNUlQ5ˆzO ^r: w[򶒞oG0J;dxz4o8 j #G[s=63hVYE8pb!a'/E2)pb %dJq(03J`7^=E+a]i37Gbt/5,:'N!u{Ë'֠ &a%WB4"_#'ϻ½Ej|)bo5(fA.*oHj@z\3%)xdF7+o4=!A!id>d(y&;P`PAʓY'\% +0._R,#ʄH&dwk& r.MT,¸a}#ݲ62=Eh]: We5vH;Hgzr/y@_fB!*Q2)YCͤb(rJ{j*DF̲%l?n=0F@RΩLN#mLCMgk2ѶwKb>ܺ4fJ>?^, ؞Q5) / e)Yh㌙?$)ܲW}ok)LTVVEƟñMd&OfN5!'ν**VoZ~\Rb8zYw&ϳZA']{cL`K]{ ijcsU>&HA䋪t˂:LOEB"aK,3@5mUK`GQ$ F]s)їn33B-6_wnu>xn;(PSo.Wi`nϟ݌W ;+HPwv`qvWEDzu܍*o"vu{9w~o'g8%FP!ܧB\7I=J|$WS4ѧ:dzl= S ATCID֫]5gzޫ/gP@#A1ơ3jvLUs t$Sp?$(=ALxKҺ_|R2Rh~50NV(:nф em%HΏ4l{+'Lgel(Ir?]w8[PS"ƕ{[[RRaf'lddϡ`p,p+ IUvB\I(@o#ibu[fE3n CtR;L7*u9֔mǚTN<9ekzt1zkհ YCy䒈i_Iz:W*s3&U~SvLeILqCK>ʠc2i"O3po t^+oJnDgO$ hAJUc+Ew<9]6%,/ $p4K*6f Pb^j{{b%}}djʯJT)&l!MJl~"D:qܧ04A LiGEZug~Pw)cTUᕊNHٟUyIh-P1fa4.rS\t栅+%9678:q\@71G>5OAv{f@ r ?}ʒ[`3 ?;cg+ٰxG+t礎ڡ▌g56y1lB9e=qDfֲ$*vscHC} q*=?ބ ,(uҽ9)Y> 0dD َd} wU՝ֺgw#qWd0&&Y1d?1۲jVz\tun-әO0ۄY3I4ߣ!!zk gH)ڲ&RD/[%?R'*vtgrߢe6[t7u  lmm@[PtKr>/f!5$O{x2%aA$_Ӱ'1 9%8fĒ%ȣie+.lˇn}k.NrF ;l%8|y=:d@Bc8;}Ҵp3-3+gL~wZf]"|'Vj = 1 6Y&}2c#^Nj̯;WaɨcZK pG(Rl;e}8YlV/WycOpnqr_u0GVS]L#( D89&_Rk I)y:81/\ }#Yq @\,:{׾`rxw]ZA=޹uO*"V_ Pl{1  QtT_>aft%nV\Mq?mcJc=-f$t 70ɾa-kZ݂ukH9I:?"2"[H,KIøc5/][rxɠkDc4- V|3Fs[m/fzdS &AHwGgxH(9KzC󧜞Sۦ-lwbD:C:@ދjD04%Dõ$Vxf1@m;Wǫ^. 2}@Vu{/2vqSaYqO!&vui`z蘒}`9bLKh?Ȕǯ+M+V1`@~%>KUL9[\no#_!2KS 4FED= Dh{|4 K)'"j٧ؼ7T 3z 7MB'} @v^)xhP>XsPeWTοj_e CpiTVpZ4g뤟; xOryudf`j@&@U|:XifL^g^٤gc8^Xk+؊#6M \O.u"z3t|謻2uu =.'MK~ͧ5|t+cl]Hgo\#Ac[䧙Z祓`#TN"c CE%>p,k7;H#fRg.{ w j%AA).g6/}uڵ Ԧ#;\3 ]WIF+"<qEBƄsz4qȳnaw챆 B9=!+|%ږdQ; kD P \Afl/P'Ea~ׇ՘:*7A@|OYi٢a 5 &K#T&GڬM &m 1I#Ys#W a ͺVM wO%%;&$2'/a¨\)-4KQZF*5ăktʋ|)A"E~j o]zaa/n1Uн-^C^hoid uL[ /+h=˭%lZ1چ]V܎xp!o}GL<+Yȧp-viRo3k}Dli?r{k8KDd6Rl)PX^9ET:-&gƬ@jB0%Y';o z80(G}L(0X e- ek#?Չ'G{{^28tդ# k&G!%\92#Go~jq(>4 Vؾtx:(5J:WLL4{ z8^W:vg=ЍeB B  z N98Q@GxWs1Ha ^#Tg;"=\@3B!Ļm!+‹ ճ0z.<B0*4}oP9@/<ݢU3LDdFSSSϒұ9o[eUv_͚o&oޟCm-bTqA=;Zyz4Pp)!ϔV_A{lᆬpsfo֊ٝ BJ=m`l& B'҇#¯>* hk]~uē(S "}JK$ͫKa6J2ގMKڤSZ/˸~/R+'<{s`^LESzڸqwmI^r>>δEEA8e8AfDJ} sq"6lnԺŵ>E9>A{ϒ4;t5  fdf&EڮSS/z!ixNQ؏H-(n"]rʴGF`3N`O֏kBm]!y(犗arv UTbK vD9o !#d?fBU)m۫§ecb o\HSݨ! [azBSzOq:n`B}6:'ƥZ%T᝜39%3tE͐Ywg(J(GyuśҚnZ90wׂɇZwşe<$V#svCdL/[J;ױ][g!AR(3X7ŚCi U'-BNe6EP ʱ).b'X_Dc{n,JqևWOVgh jKcGr~>`2 y, "Qr^{/K%&aE-IBHZh#)" ^r8??~&p_IJPNbtRNչ$?t]H˩Mlٟ Ԅά'JU:)U0 [k/퐜GX/b]1'Nc2ҥe7 T|4#-`ĀFl/fE4NS$U}̭ |& 0.!oo\@lؚU-8F^F A 7cd9݇6Uk se_rZF@Hkpn .W|2e!>JؒzCje-_G-w$(Z\&#tyV|9YGeU:ƗЎb:OlVod@o5kS+'Ʀ7L]GWvk%ν/l)Lcnj!25XF V3W5RbslWo"%8#x(%)=8 dAgn!Fv:T;'(lYʌMa)L{&ͬ?oX#ȤF P;G@')f顮aq=TqZź]ٛp.໖ϧhqM9Qݍ#nJiHߥڜϬUE9?mpqݥֻL \IO&UY'2+\CCFKDaGF݃ cDܵWV6 &W)t]sv)MVL3!҄nkq'_-S w\.pL)q)<ŧc$ԒcV,e0fM."ՀҔܮ!1|lRo=P]$]xDx]ݱ T>`؏%}9n|)P %B̯ r˖Sq?USq& mn}bD[it-8-!TOSO5\!Y6$1t:F+ ?]g`\lcp=sVd<kSMS+GKo+I~ N5Dx#83o{*hl>. ѐk6owU}Ws_ttNS H#h]ƭYw@ W$Oj?Y#z )fcF%&w2mf7!覟+Ay߱G\[ ^ ՞<" ػ<+.:)w0ZB{xO4M9ɭG#굒'/7_ςѼQD]Nč 4H6$V? };?6p!sγCo|d D4UYNڊBTx$VaZ\\LI Yi >Q[hMUCН887U޴Rc^X5R2}@S +1U&kCt}M_t`&--MwVOV3(Q?r tNVPF6B"W#~?cވ |# NC4Rj:XҨi瑷sަLbɟoMFejUxvGn՚aSl9\-}Av6vkVO$p-` R%n^6g1~Zƪ_(ibb)`H"^8h$ ^TA,D.k̹RFMW]$;0b 1RTvhR4? MV Gr{}crDs̞OV)(o7ƶQ$GjE~sLvjw"Y*-śWh+1xQ 1 NYY8FK_3+1\:B? u?ՋPdc!Ytc Fx>_Kv-кE x; >@'P%6lang>DTb gxmu?,IQo^?ޫ^3|̨Uh|2o{· Dr֢%eڨB  u>7PVәZЗfx5`Κ|"Da'ɘG&e,4~=94rv>Gvo"nIts D,4/K_c\wΐg!Ċú8J*kmn܋ҹDDK ^RǦ$uL9NyhS4N!@u4LP5ÊZ8 @ߑ1EUqehse*8P~|@~ޅ[f] xU%S|~U:Gr SI&k'8^}T 8 endstream endobj 169 0 obj << /Type /FontDescriptor /FontName /NKWQEC+SFRM0600 /Flags 4 /FontBBox [-210 -320 1719 944] /Ascent 694 /CapHeight 679 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/A/five/four/one/three/two) /FontFile 168 0 R >> endobj 170 0 obj << /Length1 721 /Length2 14008 /Length3 0 /Length 14599 /Filter /FlateDecode >> stream xmvcpݲmlyc۶m۶+mXmvw{U?ݣG=f׬HUь",`g!#q63rr5r5hTLfFF&2+҄_ @`neb uwwtwqwvI ji05((jIK(%ffFE7c[+```oj?\%av91U!qyU +O ?l3g近V=01LL\fV0 㛔߰JrGflm"vnf9S3g{XFvV^_eHバ?1r43Urjs#,a{33rw?~s^ׁ r"J4]ML-*xil__eE#ogL:[ytg=O,aaO:fF 3#5qsv6w_dfif`:OXXl%85Ek|SB7lo`]{̔({]-9%1)> ü}7Rgxi㠳 gR)~ɻ m"]җb! n}Qg~ȱ+2?`5WC%6! 5gf([W@Ay#ƠAΑ?-S`bT\Auj1۸-ц@/%]J[8KP5k6yؾy'^}#!n+5M.M#HYu/cءecQ&*iз)ZTuCa:]rȭG ^amr(,w)Z'cus}t1> <1KZc16Z2TYBv wt;^"`K@*/\|x2y:ȩ{ Ί!@(| -XV(>]bm?T͂ 8 6)E1VoHʺF_ih] JRs:hx+7/J.ڃ]@&DhjŦr蠚vn.QA<'iHEX~zRM2{=53imEl@ xH$boޏQq#1W,X~ۊ-! ɫRbaLzNHD7 ,Љ ~#O&@S9t&?r+Φi6G`~Y |6zrICBw)2Q&nCJxُmH{fv-QRg WC7r~|wl 0oeh$ NӃ~!%{+G8-O5Ct%ucõ  Ou*X5krh excP 9rAH"ۃ2Iό%-H3Ac9H-LuK%i&l߀1O1]cldU.3װ%.R;ݸFCZZ*b mJcugjH*7Rf,^È$B 2.=k(4|{.tNK8Œ ~༔rBOҬ`2[4̲pI^f^4ȵ~a%T<7Y{2T0GίOEg vüZ(IN}v+G4~񠎹r']xe^u b,"A͔=y?[`gph7 &I.-Ot%=h=5ANBͼ֥·E @$ᔟO:asy;_j"x%R/!JbC{y\yK$-2X(7xS8 /ek1h:+1] k\%l];՝}CH5eC@;0q WYјAp8 Uju"Hˢ/BB}q'opM丛G7hĵvpV(ⳤ)J g4lBˇZў=w1\`ąe׫S;d ?6 ÷U4G a;kL(D:St]ke }o߭jS H5td[3W$ǃsySy7dתEByi'|\jb.!TsB[\C)r'X hY5M֒с#gDt_}PM0JXQ)J@P\ٜkS xIS_PGYLQe`Fb F"]nWB>4 XP5hAsvFJ~ITg{ih; m +A;KjuhT6:7Lt ]np8><Ⱥ<3yx+w\:Mn{G3xטeWF/SIr0[!#o,JՂZ4>64XLUa~ܚ|VF5KK;5=LN=FdDT^NA \\IQW=6ڣUJs'<sK؂ynVP^5sbU*Zi@D[7=GNzBOf [oErXF:@33 m5M,lVݯ3mwvî+C+WOy"*'@NO5?ʲSTկ Xs}~Q7a v730vz~kO%]WGע ._L'>`P\F "m@oזSoeC*S35X{Sj3T?"nӭ6Z\~bŠʣ`$V^M*n? :Vd.> vG7 (q"h|Ir;%ggw(,nA-~DVWFa-P7'<}6mBRv/| `9񡘋v9''5/rb8!pBC:&7 W?L]Tp0f{0&+XNe{N{$k0fТ7z5 #B:!9TSlC>̓g (`ֺh84Rh@~2CVw$|7eWa̖._4߬x3K|%;~*l)#@!X6 :z)~[ucLx!Fw >"!)Tlf)v$ˬWn'ZjwJg25e2T^z-9x b l$>S׀.phvc zմc7`zWSt( \mQFYr_icv_˘/x33c$6^zP2oR;wWťƛJe~ks +$xpY1otuWhW>“ $AeF\^xr>%svM(F/LAsH(7ͼ4*9D򠾕Sd!آWBI.ZvIj9ulzⰲ 2Š<)\u*ءCyhE.rgn-س@%5s4&,d(97?aP̃eI0y#6 nԎLx`?@ة;M咂7ѠbPՈ]K}#!q $g |PX]=,0*}lp&Mi3qD&V?I'Vsϋh库f"nlvmxo(;Rߪ[+irL?Sqs H2-H+ =IoHdJRsD}X61g :4M)pzffzYf3:T Á?/D#*~ǖZ/֨P Ky Q'X  QMno> 0HTS`4Z:$F3~[Ə]?F^W{DeX4Ut.7 x4_7{-qҎxm'8 ,f0 JVbP2AXȝݺEFT3g cQ ; 76EY5,z8f|XUf:‹k }^Z, `g% m?ory<7>QaVeȱKWIQyl*nQF݀?#u|`3oh#Puy:IU!pAwEQ(*&D K:qI?O7zô?t[ XA$82e%\l;>>k)* 7;FlxVyJk3p}Z]C鸅N|⢮UhR|\ޜzbq}3pgRԮ*pyѲpd6VqCZ)PmKoxQ-G}sjX\ICe61tF6جr}q6Mikqx, /_:,/)KDLYgC|!h0) ,_5>hV-]!vRej|F/llq+@Qtzkl4輁;N%0IwUt^kލ>(F C{b*նk6:ďDMv ^|.~@%ƹcMeh!490]<Q1Qn<8[ɱ>3eThmc%LH%dR"{8SOɳAۄ^P 2N W &/vxBRs_AP'*0D#} 3 ^<1"b2P$(GӝEuHX0٠kw*yh? q%{~Q}BcSI 8[+`}-F=_Hxͫ2ׁ04SC_4S )I$!q-r&ט!$A\A rJhy^R)Mʺ/;5#^U .{ bت vmO1čpYN)@,i%" V^:Ax)$[yY|$uVE`:v^3N><$_{KR%y8A|R<ݥ!\!+ r⬟vt.,756ZqX%9 =X~C*)ۣzvo?{H[I:?D:Ç.}B ϭ*U2~-1&^2c!S 5vf,eeR).qFz ubF6:( ;cG&_~͵(>]޹E8GJҧ=E$44\Z컵9siW!b%hr%KO2d;Km'%N J0p̀cKEEl8gKd3rAT/|@E/'VU/&y hNfdfR:WCAgзGepS4OE@SWp">Z@!C3/Ijy*~AhAHʻJkMɞ#s(c- $?^YЈ:'K$Bhj<ԻY(g~ wJgOJ{+2b%e-4ئKg9^#*[3`(lL>ZL^,kYu ]b\-dOG"Jh P'/ u]uG>|\qXi'UdqlH@*t9ѦTR1S X(}3FB-Mb`հHEk516Xb>r )9%͉򱈸3~-Zv,蹁?+ҁ2cH;UWNUߛWƱCnR$ |ߖ Ifc/aI ƋY SK) __qϢ*ki7])ԒzȊnjH =3_3=y79=g~ޣvKDn\yw!1s)]7Mįp!).Ht~M!tm-mLn 11l.b9 h8u:s{NeΗ򯛖 l{~ng) {0QB$`ʱ =Ėkv0@rzD$ ,)lk8AIG1;U϶Cq5ԞABɔ_LbфkogW t4| Jop?j\^Zg@q}iw8J `BѐXJaj(eA})kͅK?bɅ9Z^ V!kTc;yHüvETcMݻ AJ\,I0D5(jL|zxnͧ{Oua]ճ%RU)lF6#>),~ËlQfT:b^.J^o?ʾ2M?3:)R!q$/7b7naSȘ*z|3EMݗ̶[{i<g?K8FRm^-Nq:1V/$]qj9+c/&|N] 2˪0(Q!vc{eZ5v2k$t7xAx~~4afvx-NҰiixj,dI檊@iTT/:XArs nĵqF\pPWY-65cFR% ,.~x kw!mK#|UlTkeQ:mE6GQM#6הjp d[ Vޢs Y(_Olt㣒/`?ӒlE7mFNtAI0o05od3uat/"S)a*IPWZrYUBt&,σTgTiiRη#~?H#)-5ʝ`)Ş}czۉMHf_Uv >}%/r/: >H1uSWIks}1(Y/sWP>ݾCBR-"}s/{Aw촖%ot0&{XCR #aF TY9Vs`PnPߋ2>2܄iipxQn=,IGe}̮RA7Gp@uqf%ueM{}?kȓ2ZF[̭aXH ZzRV|Q+9$h6W!-YIhE~dK ")Y%~zHQa(6(IDэzhza/wWPǛRd koYb e̗3% -6QVPTχ03ڍtFM{cje=I4jntBcPRA^1Eby>1 XDy "SP[`cVbUB/ӁyޟVӻw!]Q^&g9kW'y׹@uEt:[}2w"D &^"Ht!f0[F# bۢ`cRp 6 PEY'w x2h޺ܣ莫1_2U<Nw#WZ0"Lq-ΠifH89D0??yVJu|0g$/x5|KNVI(j|pR}!pq#?Tz,/TJ1ߟbwJd' zUoc3't|JtGFprc^lku |*ۣw|Θ /'v "3yқR}$[t$4\Σ=5Lx=bof5VZF$ ߏϾsJ+iBLd0XaBU!6P3hJHWɁ#zf!@&K0c'Q1e3}8,>NEBv *q 4 8eGҕ?c,QiqsΘEb 4OmU$sRqހ-Ů(v(*n2H>d@ {W⺮M bJ vkζEVRE@4:u817x!$խ^ޠ{ z5@m'TywFRZpΉxnqmM`Z{/cWH˵Y+croX=jp1!T-L0w r ^RwlA䢙,yh>n[=&e'-B)񁣥J$Ql";;/' %7 G,3:!XZ4 eۙ<#"R뵫ax:kO?[ɐ߶گ*5;u7Z> HD/IW1b媜><>y[OrU!i!W|,w" ;(ǸQxQmhIܩP8 g-[AW&ӋAc[y!0tU"vܮUvOx S}X#M*onz[>R^A#/tÙR6i  JX=rJ->:)!GE!y YDչ͔sc\.lk( Q.%慪o8jI6I#͒XR38 نL QUT[&gMlV]?вL*|+eqIinl3z;YP1*@.;"m'(hh x /2SCe2( gS}b^@kd£I8/" 'ŏD*QF v(aW B"Tl.tuAnW -Sa5o$2_KoV-EV/jw<~a?Fh 2K(̽Bnzew 9mwR`7w{=aPAWq 4 4 짦SeYuA?GV,6cRPhⵗx8j0|L[pR- iV֥wC2~ǂ\f٥4a L*d~I7C/,sUK")))Ǵ^6N~̈́PP"tY`y̧BIA<$OQG9oo9*AP3T@3 *`jd6?7 =fLzzھ`D endstream endobj 171 0 obj << /Type /FontDescriptor /FontName /PZMVCQ+SFRM0700 /Flags 4 /FontBBox [-203 -320 1628 942] /Ascent 689 /CapHeight 689 /Descent -194 /ItalicAngle 0 /StemV 50 /XHeight 430 /CharSet (/A/five/four/one/three/two) /FontFile 170 0 R >> endobj 172 0 obj << /Length1 721 /Length2 31830 /Length3 0 /Length 32349 /Filter /FlateDecode >> stream xlc.]-\]m۶]m۶]m=ݷύ3k1gʕ+I El=Mi8J2 0B&v&5c= C p03wPQP60pY۹Z]]]]\]xIR218L-MBrb 1Y5@ madbdB 0sX[[&'u5qt @FDY@TNV "D,05HnOTGp_%o`la 041$lM6 (`lbO B cglh P1Oop6[cIXM _v5E&OGl=ՅeĨw535(9å7 tgG wHQߙeYǨ#, StK†[xZ)湏Mۆ`9ӯ!Iɶ{Jp10g 2r+xhVcocj~3K>R4IfE(^K.~ I>VV57 z=o^7M:Q,[)5Df7V!.4(eI2R5u簧GqKǏ-A] Wosa|-UYŶt#BdX(6Ǵl*dh;N> 12S|Ӻ^X1(ϝy}ӫ8GtZ;˚_%Яz(,(Zzl._؆ %I"5y~]M\?³*[.]d4`sN i_(W(1f 1bzF@hy=?^1Vj4TISVIՖ5Dx[lGO !˵|#73DF-K|]VB;Ox:mFlAV_lP&7ӀQ?@8P"Qʈ*U>Pbk 2Xy8EegOF|g +{ۋSP?mŢ%Shݑ[v\GHNvp/S݄Jff#;q^e`4uyHy{hRB mlҬ63!"õ|%IFga%=*zӶvYeW.>k3,\9ļAVxYC!!yz8WLދ7y󀐄Iyh"\yy'u@s;h#6ݜm@ad MeedbAZWa33-]8$ y1QrnςfTyS3/vK9#$߰庰g3\8l,J=HZ~էCX[?EoesfL\]yYog^Q2~ R>c\e_̇%2uW=U$C4>ՁPJՖçUtmDs-7 k.C`w V;MIK@PdFJ{#ozϐ PvWNzwt,Y+/O\ $+#6gC>{f2w>J,*#3~:wLm`Ceh˝7msR^UM/(!G-h.l(=7J\aA+썊aN^9DŠ;/dRC)5R@+xXlXNkN͕ v !"wɲ3Q<}vJ8$,64 , Ě8>=rًu%8|ӻWnPW%7( %|8JC,͖dO!Oh=ˉIu Y ""r*[ntVG-W0}Y*roGLI}<<_AaL5[euYw֮9Z}{cjmRJM`%M zMNuV|ۏ/k@EU>LC Z*H3=\ꟾ~ .#p+Pfb>_Zt}":p;ZE1nΎWb`qkɒ RA9VƑFA mjmm=`kyڥn"#]$x|Q dVI& -1ڔK:Tr07CL&(7{<̖UL+f8J`]A=> LnktԏӾ":N-+y(F_矎 -Tg\R`dj(Ɂ@9Mj*{LQڤuK/PF#f-8J'vHh E#sŝR#~3=.OC+ U@i~ei a_ %)sunQ|#i%ƾR +/GLJg^ F^~ROv)4mUU\kĦO\/F`[#c N x1nrt|H" y+ XAs&u-#T 95Нzf2zSJEGƼ7SK8yk8?j4dߥ a%je)n6S?#Vcy` p$'BYWBg@}xvFbDM]ܴunK&DA4dsN_Dֵ:Db(Ex!ETi= x:RF R k5F2I&{" l0H~_iX(S = 8ˮMgeaƻ1#.;8GzHZqhF SnVm tR/ =>5*hQ`@dkx j%!֤Nɬ?TO6!Cq.VڅI@1GH> 9ɯwG8v (u>E2tt!܏b@%X:GδpΏJ?I$h!.KgFLj_0SacZ]olgӫ@f)o}d"+|-,ؓSnZ|/Zf3u#ź-ڃ 6ԑ&%#0ӷ.y^+yg*Wi]9W/TZx3Luc:\' %xu&V"ÿb!CI9Za5bIU?<^M)]L( Mt3$`lB":@ 13yy`~o_ڪffÀO֣6;d2hP^/z`QQ XpVIo]g޲J fJ#&iCoJ݀q<{ Ņ4.Һd{zvćuqּfb ako=r[0M \fѯݫ4xN $(  ؟cWT6?ypD1̭T)6/>zuŸV2YgwbRs=3_Ꙣ$y( h?xmD55mk/}9N!)"۾˳k5lʷAniy)58'ؿJ4-nw٨*) @>Cf!^(fovtHtl t 1n%];{i;q@@mZw8` 5!y|<:f!IJY^s0Saܮ7_`jS,)Ay`{wQ;MD̂+ꢿrڣ(LcVf)GVhuJS!# ug VN` (!5sس w?toBjO?-"|Ж4>O{^p+f{1T>⑯CP2C!ߍǶVl-2]_T+:`7"`l~klN6:hD<ql6O[:}%\0[UYT&MY(O#m2EBre)ja^c _9# iś8fUs2.{@6VY(Ss2ue@t' bױZ[ٞyuoyVdз,HJc ˦JzC">@6K-N=]5X>@zWbH;F1|8T6HtL< 9d3$|lp˪(qUُ̦Bz(+\+ ( 벟bvBh[4~nƇN3Z?q0IK'1zPzϘ=]/AU'?k)-D=$yEǟk`pi[]=A;4N9^Ղ2So**9 dPrBA'a[x#ou5kME$/L$DUI0\ً^i#z0" 3xwp-q]PC].Uy$4s&o`u+%3LOqJj * qݯd[b/!U ^W~G E>|/;U2!1t$h$u ,swO; uJڞnع/ ˱T#"6JF-;w aUZcݥ[)\ H| a9+YAʒ(>boEژQ3R[^j[a!#{lg-DYϕy3߭63拄:㓃#tr'nQnkdGLBV= VTY EBI^.疳wNmHJllH߽qN"wH";tx")߿v9ƬQoIk$:1wH$ʶH07(&F-x&/eG| >JL1W'/W1Wr]vj n6)W)=4D!zaĐZ4G@YSN+b۸OnN\dR&0d={<~w 4Fa)z9jH/gU Q^"1#GަUYRu+M>߁YRg^pl텻&&d+.@m PZ"uHp y\+kJNʶjfpa (l\ȝMjtmMyG'!+sF+bH"F/. *> 4tSTeK3_=owޅ`ZsGkAn{#/$'w%Q^r\)ogS/6ʿH0k zA\`[Z ?C.{UYb?q^T h! j:i {}+B$$ڙ-a6PB7"gr_F%F޲G(}l3УJ.x7D!ʸ#X!q9; пDx5xQuNrW5DA4Z{K9oe#+%6ߦ$;y? KUimaxQ#(.Üb?++mLL*ӧ?`ѕ*/< e[aY@QV8pYGAW&m93<3T{IҊ`q :3иu0lPӷԓ_g*ve)_η3Iq2GR ţ:3KG"ìv֋ nUIR wbQmK*4 ?yE׭oޠwe\{~0,;(+_A7=nd ijLE ^3@י_/9V"4,%~cJK R øJd1bAϡu`!M4 0;Qn1/ v/*Y"k|whEU=NOHqթH{; CR,RQp4/AҴ]U,i"u!`|J?i}"|䐶eEm#ႏ4j -Jn-y;ln=3CkXV(p(x1[哑)Ct "ql[:O=ݓiH^ ~.wt ab^!x?rOu3+g ؞˒s{9d?WE;ά0&|{Yo?@GɊ=<9\LIJ:Ns(cNB߱DE˦4ݞ\R,'O T92z/HߊID[HSkA A !sXL|"F2%[d|c^2b0a1/Ҹ@Zl_1BGQ((po!\w | dIRwQ+VG92-ǝu~[e _?8 J$k6PLVWXKg 4&AE/g#Ȫd8 U '{)=2 4b ¥D ER]vh9E|L`MXZ(=}O, Uͼh9+6DJ:Em3$60fى1zc5IF)!܄.tGR3. {=8)pSƌ\wTy3?0"U Kũr,`QXin8 z%KBDO'jd43]=VevͶڇ"M\|I~pe>yDDf} /QRct DnjHA"z%IJ0,TVayܟ.ٟ[xJpI *Q u'yoA .س~aGևt~U@h'`# ?k5UJ~qgơL 8 FR>h."0CDy>/NU~!&/c0 O&|djsؖ~{}+NT .u遃$ lVՏEo?S1TӦ*=z cwv0 DS *9'l =;DI~?*KQZZ2i*fJod.s+nAX)w [v sFϤ1GjQ%z)Xv`Bda]SskS!YlKN|J56_f/KԳ]AP4nHc~-y+L'">eZ`ܲڗgSa[|=21qHu~QEoy9/~ħq#+fM~&s56Ò?#><E43Kkz8  P&'"@ahN>;wD_8VCkmXE[H~; MjjYp:;˸̔ > -K>ZLHѯ癰_`ۤ%PgҰ \mU Kγ-GWyPI 7Y (i:* 8?VI6XKc޲ 3RKT꾒!)=i\8$Lz P-DDγ]_k=qvM뤛LZ|X b1%Q%"#-*g4Pɐʤ7Ad kel )PScE$)KH.yYr-ɔ0]+p1=2=0"D_ >yg# [VsrdU"ҙ h M>YA&hPɲ%@ߤy((OxvAWM˳[ʤ}룤oHk2@Pm(d4{y6%ٔix&|Ũd*k7 _@b0%D͘".|=$#ZD0, xKH,UQ̋L:C⇟2,'C}C< /RoKU*1_Wn#iRBiEp $1cI*\WQWXf;5Qa<ݔ^"V^ަK n2D{fn);cax0Xm26 u,Yc >(u6(дcmjW 2.$A&0 P۲tos,?l |3@Muz0IӋz/MMkdi9,dzdil\\ ?|*MlVrs5;BX#[͟aQz{C1q&]#-),TaD}],h~Dbej›LWyxT(㲼/ JTA,"*;A8̭g0Z*9DYX,hux]9 "}eq ң^J򲨅gk49>58B ?"*6^$>kYJb<# 9F*b6.^T_rj\i5VP~o`^ue";{m ̓sEG @O5Ri@j7ѵVk,X渔ehB TCQ!VqcUR0~I^ST䐟7ݠtհL0/cJ %nN(fՔ-i SpE,*t{@(8iȜWiJD{&٧Bi8V/9+jff[.t`$rV3tLK0T lc~ d\tɺ\Zn{k(G9J,Ym;i[WL:DrUr%S>њ9.G7z.]3O +!J8  O~ÎEQYA: ڥ䰄TFyMgPݸFS=:g~pZA(0 Ŷ?zHhu-xߊ fY>ˉw lEkL#TmY=w5Dja`* ~\+bfLzBF?}2D=Rֆ{ +U-)◩⢄M{ ÆG2ᵲry F1"CjET ǥ"43-re*N7hbACw فΜa:{}!m,$ FǾA;PrE&<Val澹Mpڣwٯ>{]7HRVBT)_}!+T$ӗ *I޹/@XZ篬^]#$m3 J 쩔5:)[/lL}3&k-3ZJ2kˋ’pP_kzݤHXpz+Ue0ʃ^ZwОS 26jDġP:KvS sXJe-|7aI16ԟyŁPACbiJI5Em, jti'jֈ@VHs#h,Ptj}fTI4py^@#,噀zH)B6l;lFŚ,˻/> k` |jV߰p,b6B Rs+Q22Hx ci4'fCd{ږ2"b^@Jxkb?&݀_ӿ97}Fz\[UAvuB0"TDa 7YJB{+].".fE緬z>X"Ըt{M*M΢eW~$Y[gjA(!8#tO@f MP%>z٬ Č?,ր#%I pW2ǶŽb)x)2(_B)1:T֖ VJ6cFD܄3T({f! O-q͢@olOǧ \gh'B7⠘$DMFLӀ gHGX[po3Z;%dpoAjFGd3g^s*22VCfhw8:;K߯N%ycvdT'cZy6q"6#T}Q~%5iB-~*cS0KBYg6 \= aȪ+ɧSi111'boUlLOW+)js"9lF|I`XsX֘N1Xh6x gF˸L+4d唒k7 v.<+]&a+K"xޱx"P {;vXGBaqW’[L5X]A 'C  ^! 4jJ G-Bw6];i(ʗQNθzpJ%tζ ?CR٢F4]SĜ rKo>n.kv*YRd-xlaTصE+c@0Kru13@N6ɯ?-{ȋz)9}j𗗭۵G3 cԡ%n&8?y6S˧^ŏBQi12en<>܁Sq?Yz '(WӵON+A;Mr&z`̓jgTLW;ea?| 9YOHm)w'$1~Nc$/޵/7cas^Șڪu-ݥ!O%d7ӷUP Rfc,sShfLW'׳'K>61t|)la@@H~g:h5AzplRJ6jA~yTBm[%PFpaj%aY&"*懶¼PnD g~sX9ZLК|Kg%=nX8ű,r>r5J䐘a_f:v˯E{`TFβU~0%"8|\FW++:8%Dz3ܴ |@vhE妘>[Yt1FuJ3dҨi,[}'-pV)HīES{$[x7/bMEzpu(b}b')yGWEh[۝~| ) vS/:G7ʆR=iTzL^4 ?-6m׊Pz|ZWF/Z}6֞կ^MIN5\4CUR*H/W8BFdʜIBrX4U^9,;9v=LeqO[$`;T u#Q|dN\G@Ul}Zl] %Nڮ1+H8Ac^=# IDCSk8 Mf yb ƳS׵-PW ˖U?Bծ5zKP9o< inDaxYT$^P2`!VǏh ϓEHjvg?%Ȗ=ʍYN;z`NjSٕ:3|f@Ҡʛ 85*,[IF*gp}x`잺JFLL`2!SrCE=ūVjHQgC#/f?ܣ _~*^h5CDr>{6_2H\~mϽ`f8/]-g}|ڲ7NqH~_Fǵ#q-ҟXżE9+Ɵ¢&oQUM~ I2pDZC`6a)1?zT7N-[@ svq!<ڡ?W6RPnHg A|_a@ڥ.ކHTpVh/46z gI`L@иϚn?2WlՇ +x3˽_6t5SFQ cs+s)@а栛2ђrJd!]Mrq;SIڢv'UxX剬TPXڤCPyOJ{MQi%G0 t|CruOJ'<t03cMּne~7mqjza8FDϜ9yѯ{X"dBLעvmE e8xAoE#wvxZu$xNf)߸[hAf&^uY]ci`?I#k7&N ,tȽ AeJkWO/  GV`O_F8e'_q+ypDYȘ.wf{3UpGli Uvv B yXN-1߭To36īyU8]7>YoiK|S׻en 0 .. VnU;sa|MfC7d=YvOwi'I. tCjWTgEWD3m7@k=B WH4>!1Ʉ kQ##a΅$. K =W=[+t&\%yg Rz{&{b%sWǫ8νhTZ͓*s,/%Crj;:kS4vzI=HL*h udZ5F޵1l"- PP.p~IhIFDjP y+}9yL3DW/|APl=Bp@ 9c<8NZˣo{di[E™ݳ_Qqգ oR؂\{}Th (kD6/P::M69&I 3x)UjFyt"-3^1C%U%_y W+ʒ'Gp4p[y6Gn oB}s?$婽ӹ%֏Gq*Zv /۩LQAȝ>&&~گwY:S4ڱ.ldĦAߏ w`|J^~\sNl.Cko@ T ~*rrayav#-z }1 6{̑OopOQ帵-%'ģ78 xukΆPʹoB93/8IC>_|!X ˉpF4ή G,_$:<"( `IwZ-Δ6k,Yw@T/u"o[ZĕXTt`l 3p\:fU2.p&,4Φ|jN,\⫑0BBCw_[ ¿ X3/yʿN*l,mdϨnBe-Xn"Zt(VMqK{b 7?@itw>ibh H)մ&sI\W}]Կ=Pw87}uRTg{$d|0,o&3o2${O3C,.ጟCSJeP6cWM'ފ0ulSr܃0޹rHǵVł"9Өfn-ב`ZQ(ܱjWQl%{Fō;' X->U aYYiH, uTvϛ77 *À?1뿃I$TEli ,X?Nh1s}C\qDL6wti2;qd Q`4.䏌;%2~ )' V(뜓±6@{$Ev¦q02]]O]#KU_qk~ ҳӫbRqo.~ ++\mՑ9B,4TjIo4-M-^;g֣ @< Z#zF]IGv:#%w<#IДhQuOS@?̡БzX;/r D?{/4ש̻ͻ0C֌n K(Qy3 /5g9UV UOõtd='VsY %N/ݫA3%.[ÎgPq 6ڷlvM6L gR ]Ǹ:.6Z1ǙD^)p1k_& bCXI#Ϯ\c)u=6ta6' &̙ER2EQMBoh[qH.Mܑy8!29dY^^H+n2Zq/S\`Ku~)l$>w W!mp>5DƜ/ \4P3L, ^;d* RIiRW LaAj-#*an uljH$ۿӈ,)?D]ځN|jP"/NO6ɎǃP8Ѧ::>P O=]'[p صĉW.( b ӱFƝ6vs9F崽XQ.sA>5LYY i?q.w&0O@>}Qns05=R3$X(-ޅu#_\-Ӣ0p^7Bjp|'.)LS dhXD ]l[ ..i ^`c5-BDDAbNW3dY3((Bl8_aI)]#V֕ ;*w=D/"⸎=?b>գG&ˠ~q "uҐTbS,Kz[Rg6TpE3%^R:wHrNSnYwAcD)̘w-Pc#a[զ#!heԁ+5WPl$:T<.: uh϶HZ ˤbՋ#Yى.sJZwJj#2vd2c$#P[9PBS-N#f8'ⴎ8sNn_ۥ;[EhNYN"Ac4F$(TB!K`Z~jƋgm4wD1=pn8ζ663kAB6{*!Չ؁ xc\'`/a]1)nIV{Go$SPJk屦@v}\GR~[."*0?FZ +:pS~9zryI#GQj>~4MInzq;ğ9(kZZ'ь¸Q?,K7/" nl\q_Ѹ`97.9S ^^f)1\ ġ?'T+ |u{.sn!cD[L`%[tp qZ_U'k=8V& ӵtJ%ee0n⨅ux¨a}kƃ,o!;xFj,M԰ 1D.zr7K_f,ˋ䙙??Z` 0T Y$J.d>ʪO 0OkV \QǷL=dL\z0ݡ\)y:r` po h0 2 b3]>_o` tȃ2agJIa(7"ؙ wU_o9ˠy.]-ma2-釦M:Mq[O#gEL40_G1g8a6jY172CE={\ˆ_l}B"f l IOK `\ G`sa2~Z՛c|=tnKXx7)jH+)Mnַbl:^9we]7` VMYX677M4 aHQոJψP;21ApIa҄ ّCajw y,Ɇш!"9nx~nbȣa|"AHHzgS=Qt5M66tmz 7wa_ސ*Se cjP] D +΃::4IHP(ج&U@1lQhqP_ *ѐ0KW1 o47%CҀY (Afh-Kt<_)al{ vEhKS*kǵ'b3,BsA>L00;KcAl Ty`3+Hn266;k-͖b7ǑHBiQkc&y .'>ŤiaMY/T*ZD cB?<Wmpu |--l B&Yԫ_Y[Wn 8P>q *z hΉT/rayIȋ/?>9םJ{pa WN|M8DlPLd&6Fm$OUrs@A%p}3;iBi`v;S;l^s7ɉ Y5F^yYJQf8>3эa@~Kˑ;/өolZ=RQ iz`Tӫ=:v'yI܆y~zqsjIw,4,C`UI+cVhxbݺDӿG=kн-aCR-z}ز{#B6"P"ZAZDž` $;.hd%}B\T,4nB lߧFJJ_n'2nl]LtdnV[CX6L4PԌL\~& 0-Ua(e~>ew|&5|\ Nv+`1k_M!q pS'Б*Y`.[ 栰Ȓ ;;N2>إSNUl&r܈4-z[L<-r2ׁGRK췭=g 5*.ͦ(+v2ng e=}9 ?&v`Y|r7)fݠ.4ž Pj^@^ eT sOO5/"%%'҅j;~(cA)үG $cREp/ .=FtFbqC, kBQav|΅GZVh[ ңe? ~r[|屎y+ߒ.E%j鞈m=ʀ|,/fW`e^T`F2{-s^Mf|NԀK٧FӼ FY\+@puMDwHtJR|fU/S2FˆOIa,` +RS&?.67:b3X(u=_\"=qOmEl}5ϞZXz>s{7Ϝy@dIb,h%.~x(:Ri&!n/}E A\fĚnU ./)#$O/@pU3M#:x PddLU -(!T/gb rlҊRX3ם Q'|&V=X<܅À*切]RbdÃ!^ ޢ)ŏ]a= FcC퇗rϸ-H?}]m_ZѡM9-1Ρ[V,KrƑ6o\/ewzbOLeJs>iEHE*O8&uaklԭNC[_$;o]k0ݼoPb3RI1k?n<ɷ,*IDDMZ> ʮa,`r ݷQ0R[G2/;%I|0ݳ~ yQ~nW |};@zu?lvt/9-MnAždf{K/:}"^f:ͯ7rP-~5MݚCz!`wn.*xLAyQi,_ snƾ'x\ >' u< DU}H$ {ihn5dk% Iv'ED['Dѣ^2\Iѡk޶ӲOD9asxsrs*bE\2o7`ɯ8b0 ;ZMKMؚ@e@ wJ>]+bT.b54 -i*ȷAF-uδh% 3DA_/19xPkC%1UR0.-?~mdy(U{+I(q* [_se"$o V ku1tr}姧9ϕ&$0U{.㮁2vJ1pq-?"e@_k3ߌ$+Ki VG^l ;@V{"ah]/CQ0^M` t!hNI87 gEʏ¿<ˉM+QSnh6 Gh' >Rsa-U x1m&gv@8Tlu1w%qi%B(h R^aʗ]LB@B\Lc<[R\ 2$sa_oߘe3kP&FdPg'd.7w,ƂY LhE`!&B7sLnj\<@AIL<H!=|9bM=Bfp3&k/H QK.yK 'xr%Ƹצ':GȂp|Zzhnm7=c *PgGpt CҮ ]NtEUʝ`$p,QkYs:* (F6GVB4(]')zSBpAA)-&-`(j}R~GGI(Hs&B`~r1,YQ Ff]=Jb1zJ޻y4T5$穡囀Uuۏ&RZM<pM7T`x{<4!hh637uR #c<T-?N)ŘI=m%D[㗗@>@n-y4HQND_ ܹUا!N-n?AQqZfAP+WJڂQLy!~ lGNHJ>%>f^DHFX1F. jv5 Jv!A]906l`MD-*|"~XhT>M\"]Uy)z\T;/Xu+gaisDR+pg,ήTNÝCtoh&Dwsq>VG`t g" Nܴb^PkihKYAR ?|yȓ10?umvYٶgu[6+eoM1&